AtCoder Problems を支える技術 (2019年版)
AtCoder Problems とは?
AtCoder Problems とは AtCoder の提出をクロールして管理しているウェブアプリです。
AtCoder Problems の主な機能
- AtCoder の各問題について自分が AC したかどうかを管理
- 問題の検索
- AC/非ACで絞り込み
- AtCoder公式の点数で絞り込み
- 独自に算出したDifficultyで絞り込み
- 問題タイトル・コンテスト名・FAユーザー・最短ユーザー・最速ユーザー・etcで検索
- ユーザーダッシュボード
- AC数や連続新規AC日数などの確認
- 各種公式コンテストの埋め具合を確認
- 毎日のAC数の確認
- 自分の提出一覧
- 各言語でのAC数
- Difficultyを基にした問題推薦
- ランキング
クローラー
クローラーは Rust で書かれています。GitHub にプッシュすると Docker Hub でコンテナがビルドされ、 AWS の Elastic Container Service (ECS) 上で動きます。
今のところは提出クローラーは以下の4種類があります。結構重複していますし効率も悪いので、整理したいですね……
- 全部の提出をクロールし直す
- 各コンテストを回って新し目の提出をクロールする
- 最近のコンテストの提出をクロールする
- 最近提出があったコンテストにもう一度行ってクロールする
HTTP リクエストには reqwest というライブラリを、Html のパースには scraper というライブラリをそれぞれ使っています。
API サーバー
API サーバーはサーバーアプリケーションではなく Lambda として実装しています。Lambda は AWS の余剰計算資源を使って短時間の計算を低価格でできるサービスです。これによってサーバーアプリケーションを常時起動させているのではなく、アクセスがあったときのみアプリケーションを起動しているので運用コストを削減できます。Lambda 上に Rust 製アプリケーションがインストールされていて、ユーザー名を受け取ると別のサーバー上で動いているデータベースから提出一覧を取得してユーザーに返します。
Rust は公式に Lambda にサポートされているわけではありませんが、 lambda_runtime という AWS 謹製のライブラリがあるので、これを使うことでマクロに関数を渡すだけで簡単に実行してもらえるようになります。とは言えローカルでテストできないのは不便ですし、EC2とネットワーク周りのトラブルが時々あるので、乗り換えを検討しています。
フロントエンド
フロントエンドは TypeScript で書かれていて React を使っています。最近 redux を導入して、ほとんどの関数が副作用を持たないようになりました。contests や problems や submissions など複数のファイルから left join の要領で情報を結合することが多いので、内部で使っている List や Map は immutable-js を使うようにして、意図しない破壊が起こらないようにしています。
集計
一定時間ごとに、最短コードなどの各種集計情報を更新しています。集計バッチもクローラーと同じように ECS 上の Docker コンテナで動いています。直近の結果を見て更新できる部分だけを更新する差分更新バッチが数分おきに走っていて、全ての結果から集計情報を再構築する重いバッチが数時間おきに走っています。
難易度推定
amylase さんによってコンテスト結果から問題の難易度が推定できるようになりました。詳しくは本人が別の記事で書いてくれると思います。楽しみですね。
図
図です。
おわりに
AtCoder Problems をいつも使っていただきありがとうございます。どのようなものでもフィードバックをいただけるのは大変嬉しいです。ぜひ、使ってみた感想、あったら嬉しい機能、使ったことでレートが上がった、プログラミングスキルが向上した、就職できた、出世した、莫大な金銭を得た、余ったので1億ほど寄付したい、といったフィードバックをお送りください!