<file_sep>import '@babel/polyfill';

const React = require('react');
const ReactDOM = require('react-dom');
const Simple = require('./app.jsx');

ReactDOM.render(React.createElement(Simple), document.getElementById('app'));
<file_sep>const {stripIndent} = require('common-tags');
const mongoose = require('mongoose');
const docker = require('../engines/docker');
const Contest = require('../models/Contest');
const Language = require('../models/Language');
const Submission = require('../models/Submission');
const User = require('../models/User');

mongoose.Promise = global.Promise;

(async () => {
	await mongoose.connect('mongodb://localhost:27017/esolang-battle');

	await User.updateMany({admin: true}, {$set: {admin: false}});

	for (const id of ['hideo54', 'sitositositoo', 'syobon_hinata', 'naan112358', 'kombubbu']) {
		const user = await User.findOne({email: <EMAIL>`});
		if (user) {
			user.admin = true;
			await user.save();
		}
	}

	await Contest.updateOne(
		{id: 'komabasai2021'},
		{
			name: '駒場祭2021 Live CodeGolf Contest',
			id: 'komabasai2021',
			start: new Date('2021-11-23T14:05:00+0900'),
			end: new Date('2021-11-23T15:45:00+0900'),
			description: {
				ja: stripIndent`
				## 問題
				TSG LIVE! 6での東西対決から半年。我が国はTSG派とKMC派の二つに分かれ、混沌を極めていた！
				あまりに壮絶なその争いに終止符を打つべく、政府は各都道府県に代表者を3名ずつ擁立し、多数決によって都道府県ごとに公認サークルを定めることを決定した。
				政府御用達の凄腕プログラマであるあなたの任務は、各都道府県の代表者の投票結果を受け取って、それぞれの公認サークルを発表するプログラムを作ることである。
				やること自体はとても単純だ。ただし、開発したコードが長すぎると、TSGやKMCのハッカーにより発見、改ざんされる危険性がある。ハッカー達に見つからないために、できる限り短いプログラムを書いてほしい。
				### 入力
				* 47行からなる。
				* 各行は\`T\`と\`K\`のみからなる3文字の文字列である（\`T\`のみ、\`K\`のみの可能性もある）。
				* 各行（最終行を含む）の末尾には、改行（\`\\n\`）が付与される。
				### 出力
				* 各行について、\`T\`の数が\`K\`の数より多ければ\`T\`と、\`K\`の数が\`T\`の数より多ければ\`K\`と出力せよ。
				* 出力された文字列に含まれる空白文字（改行含む）は無視される。すなわち、各行ごとに結果を出力してもよいし、1行に結果をまとめて出力してもよい。
				* 厳密には、JavaScriptの正規表現で \`/\\s/\` にマッチするすべての文字の違いは無視される。詳細は MDN Web Docs の [文字クラス](https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes) のページを参照のこと。
				### 制約
				* 特になし
				### 入力例
				\`\`\`
				TKK
				KKT
				TKK
				KKT
				KTT
				KKK
				KTK
				TKT
				KTK
				TTK
				KTK
				TTT
				TTK
				KKT
				TTK
				KTK
				KKK
				TKK
				KKT
				KKT
				KKT
				KTT
				KKK
				TKK
				KTT
				TTK
				TTT
				TTT
				TTK
				TTK
				TKT
				TKT
				KTT
				KKT
				TKK
				KKT
				TTK
				KTT
				TTK
				TKK
				KKT
				KKK
				TKT
				TKT
				KTT
				KKT
				TKK
				\`\`\`
				### 出力例1
				\`\`\`
				K
				K
				K
				K
				T
				K
				K
				T
				K
				T
				K
				T
				T
				K
				T
				K
				K
				K
				K
				K
				K
				T
				K
				K
				T
				T
				T
				T
				T
				T
				T
				T
				T
				K
				K
				K
				T
				T
				T
				K
				K
				K
				T
				T
				T
				K
				K

				\`\`\`
				### 出力例2
				\`\`\`
				KKKKTKKTKTKTTKTKKKKKKTKKTTTTTTTTTKKKTTTKKKTTTKK
				\`\`\`
				## 盤面
				盤面は**2次元トーラス**（上の辺と下の辺、左の辺と右の辺がつながっている正方形）上の4x4マスである。
				例えば、下の図の\`A\`のマスは、\`B\`、\`E\`と隣接しているのみならず、\`D\`、\`M\`とも隣接している。
				\`\`\`
				+-+-+-+-+
				|A|B|C|D|
				+-+-+-+-+
				|E|F|G|H|
				+-+-+-+-+
				|I|J|K|L|
				+-+-+-+-+
				|M|N|O|P|
				+-+-+-+-+
				\`\`\`
				各チームのプレイヤーは、自分のチームの色が塗られているマスか、それに隣接しているマスにコードを提出することができる
				（ただし、ゲーム開始時に色が塗られているマスは単なるスタート地点であり、コードは提出できない）。
				提出したコードがそのマスに書かれた名前のプログラミング言語で解釈したとき問題（上記）を正しく解いており、
				かつ、以下のいずれかが成り立つとき、提出は受理され、そのマスが提出者のチームの色に塗り替わる。
				* そのマスにおける受理が、ゲームを通じてまだ一度も起きていない。
				* そのマスで最後に受理されたコードよりもバイト数が短いコードの提出である。
				競技終了時点で、より多くのマスに自分の色が塗られている方のチームが勝者となる。
				## Tips
				* コードはフォームに直接入力して提出することもできるが、テキストファイルをアップロードして提出することもできる。この場合、Shift-JISなどの文字コードも使うことができる（これでバイト数が短くなる言語があるだろうか？）。
				`,
				en: '',
			},
		},
		{upsert: true},
	);

	for (const slug of [
		'whitespace',
		'pure-folders',
		'concise-folders',
		'produire',
	]) {
		const languages = await Language.find({slug});
		for (const language of languages) {
			const submissions = await Submission.find({language});
			for (const submission of submissions) {
				console.log('procceing:', submission);

				const disasmInfo = await docker({
					id: slug,
					code: submission.code,
					stdin: '',
					trace: false,
					disasm: true,
				});
				console.log({
					stdout: disasmInfo.stdout.toString(),
					stderr: disasmInfo.stderr.toString(),
				});

				const result = await Submission.update(
					{_id: submission._id},
					{$set: {disasm: disasmInfo.stdout}},
				);
				console.log({result});
			}
		}
	}

	mongoose.connection.close();
})();
<file_sep># esolang-battle

@hakatashi が作成した [hakatashi/esolang-battle](https://github.com/hakatashi/esolang-battle) を @hideo54 が改良したもの。

本家に加えて、次のような違いがある:
* Dark theme に対応している。黒色ベースのデザインをしている場合に親和性が高い。
* 本家の最新版の commit は dependency update により壊れている状況。本リポジトリのコードは最新版が正常に動作する。
* README がまとも

TSG LIVE! 5 (2020年五月祭 (コロナにより9月開催)), TSG LIVE! 7 (2021年駒場祭) では、このリポジトリのコードを使用した。

## サーバー構築のしかた

Node.js **v12** や、Python 2, 3, MongoDB, Docker が必要。詳細は TSG Scrapbox で hideo54 が書いた「LIVE-CONTEST サーバー作業メモ」を参照。全部載っている神記事です (自画自賛)。

言語のインストールは、`data/langs.json` に書いてある slugs の中から、使う言語を探して、`docker pull esolang/${slug}` すると良い。とりあえず全部インストールしようとするのはやめておけ (ものすごい容量が必要になる)。

問題登録や admin 登録などは `bin/migrate.js` を編集し実行すると便利。都度些細なユーザー管理などを行いたい場合、個人的には、[MongoDB Compass](https://www.mongodb.com/products/compass) を使うのが大変便利でおすすめである。

## 問題の足し方

* `contests/hoge.js` に盤面の隣接情報や正誤判定を登録。
* `data/languages/komabasai2021.js` に各マスごとの使用言語を登録。
* `public/css/main.scss` にトップページのサムネを登録。
* `views/contest.pug` や `public/js/contests/*/app.jsx` に見た目について記述…するのだが、見ていただくとわかる通り、だいたいの場合 mayfes2018 が使い回されているよ。
    * pug を知らない人向け: pug は HTML を楽に書ける言語だよ (HTML にコンパイルされる)
    * jsx を知らない向け: ここでは、フロントエンドを React を使って記述しているファイルだよ

まあ雑に `komabasai2021` とか、パクりたい大会の id でプロジェクト全体検索して、適宜コピペすればいいんじゃないかな。

## tips

* コンテストページの末尾に `/admin` をつけると、admin なら admin 向けページにアクセスでき、GUI で簡単にチーム配属を行える。 (例: `/contests/komabasai2021/admin`)
    * ユーザーのチーム配属を削除することは現在できない。やりたければ MongoDB の users コレクションをいじるといい。
* コンテストが閉じているときでも checker で実行確認したい場合、d002a82 みたいな変更をすればよい。
* 開放されていない言語についても checker で実行確認したい場合、60bbc8b みたいな変更をすればよい。
* 何かわからないことがあれば @hideo54 に聞けばよい。
