長文書くところ

技術系のアウトプットとかメモ書きとか

マラソン系プログラミングコンテストページを立ち上げた

ラソンマッチってご存知ですか?
競技プログラミングの一種で,よく知られている短い時間でのコンテスト(アルゴ系とも言われますね)とは違い,数日間から数週間にわたって開催されるコンテストのことです.もとはTopCoderMarathon Matchだと思うんですが,長い時間で開催されるコンテスト全般をマラソン系と呼ぶことが多い気がします.

そんなマラソン系コンテストの一種で,かつてCODE RUNNERというコンテストが行われていました.たしかリクルート主催?だったと思いますが,2015年の開催の後,今や公式サイトすら開けなくなってしまっている状況です. 私はこのCODER RUNNER 2015の予選Aの開催時にリアルタイムで参加していて,当時の実力では全く歯が立ちませんでした.いつか復習したいなと思い続けるうちに時は流れ,今やちゃんとしたルールの確認すらできなくなってしまいました.

そこで,うろ覚えながら当時の提出形式や問題設定を再現し,いつでもどこでも(私が大学とかで外にいることも多いので……)復習できるようにしてみました.

URLはこちらです.
https://nocross-zenito9970.herokuapp.com/

コンテストの形式

TopCoder MMやAtCoderなどでのコンテストとは違い,解答の提出はソースコードを提出しません.特定の形式のURLに対して,HTTP(S)でGETリクエストを送ることによって,サーバがそのURLを読んで解答を処理します.つまり,ユーザーが手元で計算して解答を作成し,その解答の良し悪しを競う,という形です.

ユーザー登録をすると,提出のためのアクセストークンが発行されます.ユーザー名とアクセストークンをURLに含めることで,ユーザー認証としています.この仕様はたしか当時の形式でもこんな感じだったと思います.ただし,当時は普通にアカウントの概念が別にあって,そこからアクセストークンの発行ができたはずです.今回はページとか諸々が面倒だったので,registerを叩くとそのままアクセストークンが発行されるようにしました.

実装

サーバはRustで書いています.これは私が最近Rustを練習しているからです.趣味です.
webアプリケーションフレームワーク(というかルーティングとかやってくれるやつ)はwarpです.テンプレートエンジンにhandlebarsを使っています.ただし,warpでStringをブラウザに送りつけるとChromeくんが頭おかしい動作をしたので(pre タグの中にテキストとして埋め込んでしまい,ソースコードがドバーッ),定期的にHTMLファイルを生成してそのファイルを返すようにしています.

ランキングとかアクセス時間の保持とかは全部Redisに投げています.この辺自分で書くと面倒な上にバグの元ですし,永続化やらなんやらがひたすら手軽でとても良いです.

WebページのレイアウトとかはBootstrapに任せました.かなりAtCoderに似た見た目になっていますが,見やすいのでまあこうなるよなあと思いました(適当に作ってたら無意識に似てしまいました).

ホスティングにはherokuを使いましたが,これはheroku containerでDockerイメージをホストしています.もともとArukasを使うつもりだったんですが,正式版リリースでクレジットカードがないと使えなくなったみたいだったのでherokuに変えました.

herokuの無料枠は30分アクセスがないとスリープしてしまうので,Google Apps Scriptで15分ごとにリクエストを送りつけています.無料枠ってどのくらいの時間大丈夫なんでしょうね.インターネッツの情報は錯綜しすぎていて,なにを信じればいいのかわかりません.いい感じだったらそのうち課金するかも.いまのところherokuのスペックは所詮無料枠なので,何十人もがリクエスト投げるのは無理じゃないかなーと思っています.

Dockerイメージはalpineベースですが,これはローカルのストレージを圧迫されたくないからです.Ubuntuとかのイメージの圧倒的デカさの前には,macの256GBストレージでは太刀打ちできません. ekidd/rust-musl-builder でstatic linkなバイナリを生成して,それをalpineにCOPYしてます.

herokuもDockerもちゃんと触ったのは初めてなんですが,めちゃくちゃ手軽にできて良いですね.

その他のこと

これはコンテストとしてめちゃくちゃ致命的だと思うんですが,ランキングは24時間くらいに1回リセットされます. heroku無料枠の仕様で,マシンが定期的に再起動されちゃうんですよね.別のサーバにデータを投げたりすればいいと思うんですが,無料で使えていい感じのとこを見つけてないのでやってないです.Dockerイメージ的にはRedisのバックアップデータを永続化する仕組みを作ってはいるので,やろうと思えばいつでもできると思います.

あと,「No Cross」っていう問題名とか,問題設定自体とかがCODE RUNNER 2015 予選Aの問題そのもの(だと思う)なので,権利的にマズかったりしたら言ってください.すぐ消します.