AtCoderでのコンテスト主催者向けのツール紹介 (Competitive Programming (その2) Advent Calendar 2015 Day 17)

この記事は、Competitive Programming Advent Calendar(その2)の17日目の記事です。カレンダーについては、以下参照。

こんにちは、2Dです。最近は、あまりガチで競技プログラミングをしていないので、知らない人も多いかもしれません。2008-2012年くらいにICPCに参加してた者です(内2回アジア)。今は、ACM-ICPC OB/OGの会で問題作成やコンテストの運営に関わってます。

今回は、主にコンテスト主催側の人達が使えそうなツールを紹介するので、選手として参加する人たちにはあまり関係ない記事になると思います。すみません。ここでは、以下の2つのツールについて紹介します。

AtCoderクラー Slack通知ツール atcoder-clar2slack

そもそもクラーとは?

AtCoderでコンテストに参加したことのある方はわかると思いますが、AtCoderにはコンテストについてわからないことを質問するためのフォームが存在します。こんなの↓

f:id:Respect2D:20151215233005p:plain:w400

このフォームから送られてきた質問のことを "clarification"、略してクラーと呼んでいます。質問された内容は、コンテスト運営者専用の画面で、以下のように確認することができ、それぞれのクラーに対して返答を行うことができます。

f:id:Respect2D:20151215235026p:plain:w500


コンテスト運営にとってのクラー

クラーの中には、問題の不備について教えてくれるような重要な質問が存在する場合があります。

例えば、「サンプル1の出力は1ではなく2ではありませんか?」のような質問がよくあります(よくあっていいとは言っていない)。このクラーを送った人の勘違いならいいですが、このクラーの不備が事実であるならば、大変な事態です。選手は、最低限サンプルが一致しなければコードの提出ができないので、問題文のサンプルが間違っているだけで、選手の貴重な時間を削ってしまうことになります。

上のはちょっとした一例ですが、選手に無駄な時間をとらせないためにも、コンテスト運営者は、クラーが来たことになるべく早く気付き、なるべく早く回答を行う必要があります(そもそも、不備がないように問題作れよという話ですが、いくら慎重に作っても不備は出るものなのでそのツッコミはなしで)。

ちなみに、ツールができる前は、クラー画面を常に監視する係を決めて、クラーが来たことに気付いたらチャットルームに知らせるという原始的なやり方で、クラーに気付くのが遅れたりして、残念な感じでした。


通知ツール作った

ということで、自動でクラーをSlackに通知してくれるツールを作りました。

github.com

何故かScala (sbt)で書きました。理由は、ただ単にScalaを書く練習をしたかったからという、そんな単純なものです。とりあえず初回起動が非常に遅いです。ごめんなさい。使い方は、チョロっとREADMEに書いてありますが、こっちではもう少し詳しく説明したいと思います。


設定・起動方法

sbt インストール

まずは、sbt(http://www.scala-sbt.org/download.html)をインストールしてもらう必要があります。リンク先に、インストール方法が書いてあるので、そちらを参考に、コマンドラインから sbt コマンドを使えるようにしてください。

設定ファイル

atcoder-clar2slackをcloneしてもらうと、 src/main/resources/ ディレクトリの中に application.conf というファイルがあるので、以下を参考に設定を行ってください。

  • atcoder.url
  • atcoder.userId:コンテスト運営用のクラー画面を閲覧する権限を持つユーザのIDを入力してください。
  • atcoder.password:↑のユーザのパスワードを入力してください。
  • slack.webhookUrl:後で説明します。
  • clar.sleepTime:最新のクラーを何ミリ秒ごとに取得するかを指定できます。この間隔でAtCoderにアクセスするので、細かくしすぎるとBanされるかもしれません。
slackのwebhookUrlについて

Slackに通知するために、webhookUrlというものが必要になります。webhookUrlは、 https://my.slack.com/services/new/incoming-webhook/ から取得できます。アクセスすると、こんな感じの画面が出てきます。

f:id:Respect2D:20151216005003p:plain:w400

ここでは、クラーを通知させたいチャンネルを1つ指定してください。Addすると、次のような画面が出てきます。

f:id:Respect2D:20151216005857p:plain:w500

  • Post to Channel: クラーを通知するチャンネルを設定できます。
  • Webhook Url: このURLをコピーして、application.conf のslack.webhookUrlに書き込んでください。
  • Descriptive Label: 無視して大丈夫です。
  • Customize Name: 通知Botの名前を設定できます。JAGでは、「かしこいかわいいクラーちか」と設定しています。
  • Customize Icon: 通知Botのアイコンを設定できます。JAGでは(ry

Save Settingsをクリックして終了です。

起動

コマンドラインで以下のコマンドを打って、ツールを起動します。

$ sbt run
https://jag2015summer-day4.contest.atcoder.jp の監視を開始します。
管理者アカウントでログインしました。
最新クラーチェック...
最新クラーチェック...

application.confの設定した値が正しければ、上記のような感じでメッセージが表示されます。


動作確認

実際にどのような動きになるのか、紹介します。

クラーを送信したとき

クラーを送信してみます。
f:id:Respect2D:20151215233005p:plain:w400

f:id:Respect2D:20151216020445p:plain:w300

Slackの先ほど設定したチャンネルに、以下の内容が通知されます。

  • クラーのID
  • どの問題に対してのクラーか(問題文へのリンク付き)
  • クラーを送ってきたユーザ名(ユーザへのリンク付き)
  • 質問の内容
  • 質問回答ページへのリンク
回答を返したとき

クラーに回答してみます。
f:id:Respect2D:20151216021220p:plain:w400

f:id:Respect2D:20151216021312p:plain:w300

以下の内容がSlackに通知されます。

  • どの問題のクラーか(問題文へのリンク付き)
  • クラーを送ってきたユーザ名(ユーザへのリンク付き)
  • 質問の内容
  • 回答の内容
  • 全体公開にしているか(Noならば、クラーを送ってきたユーザのみが回答を閲覧できる。Yesなら、選手全員が回答を閲覧できる)
  • 質問回答ページへのリンク

今後

以上、AtCoderクラーのSlack通知ツールについてでした。

今後やりたいこと。

  • コンテスト参加者が使えるクラー通知(Chrome拡張でデスクトップ通知するのを新しく作った方がよさげ)
  • AOJコンテストの通知に対応させる(会津合宿・立命合宿での需要)
  • オンサイトのユーザがACしたときに通知(風船配布管理ツールに入れた方がいいかも)
  • できれば、風船配布管理ツール(この後説明)へ統合?
  • 複数のwebhookUrlへのメッセージ送信

風船配布管理ツール BalloonFusenSystem

次は、hasiさんが作った風船配布管理ツールを紹介します。

風船ってなんだよ

まず、知らない人からは風船とは何かというツッコミを受けると思います。大学生向けのプログラミングコンテストとして有名なACM-ICPCでは、いくつかの問題が出題され、1問解けるごとに、1つ風船が届けられます。風船が浮かんでいるこんな風景↓を見たことある人は結構いるのではないでしょうか。風船がたくさん浮かんでいれば、そのチームは多くの問題を解いていることを表します。

f:id:Respect2D:20151217010533p:plain

写真の奥の方に写っていますが、各問題ごとに風船の色が決まっていて、解けた問題に対応する色の風船が配布されます。


風船配りは大変

風船配りのプロ集団と言われるACM-ICPC OB/OGの会ですが、ICPCに向けた模擬コンテストで風船配りを行う度、実は非常に苦戦しています。何が大変なのか?いろいろ大変なんです。例えば以下のようなことが。

  • 模擬コンテストでは、風船を配るべきオンサイト参加のチームと、配らなくていい外部(オンライン)参加のチームがごちゃまぜでランキングが表示されます。そのため、正解したチームがオンサイトなのかオンラインなのか、正解が出るごとにいちいち見極める必要があります。結果、配るべきチームを見逃すということも。
  • どのチームにどの風船を配ったか、という情報を正しく記録しないと、風船の配り忘れや配り過ぎ(配りに行こうとしたら、すでに配ってた)などのトラブルが発生します。

ちなみに、ツールを作るまでは、Googleスプレッドシートなどを使って、どのチームのどの問題の風船を配ったかというのを、人力で管理していました。人力なので、見逃しとか結構あって、辛かったです。

他にもいろいろありますが、まとめると「どのチームにどの風船を配ったかを一目で把握したい」「オンラインチームのノイズを取り除いて、オンサイトのチームのことだけを考えたい」の2点が叶えば、風船配りが非常にラクになり、間違いも少なくなると考えました。


風船配布管理ツール作った

ということで、そんな願いを叶えてくれるシステムをhasiさんが今年のJAG夏合宿のときに作ってくれました。

github.com

僕はあまり把握できてないですが、AtCoderからの情報取得を行っている部分がpythonで書かれていて、風船配布システムに関する部分はphpで書かれているっぽく見えます。


設定・起動方法

起動方法については、READMEを参照してください。AWSのEC2で動かすと、READMEに書かれているコマンドをそのまま打てばいいだけなので、ラクです。AWSを使ったことがないという方は、スペックが低いサーバであれば、1年無料で使うことができるので、是非さわってみてください。

風船システムは、AtCoderとAOJに対応しています。それぞれの設定方法について説明します。

AtCoderの場合の設定

stands/contest.txt を開きます。1行目に、AtCoderのコンテストのURLを書きます。2行目に、コンテストの名称を書きます。2行目はわかりやすければ何でも構いません。例えば、こんな感じです。

https://jag2015summer-day4.contest.atcoder.jp/
JAGSummerDay4

あと、stands/passwd.txt というファイルを作って、ここにユーザIDとパスワードをコロンで区切って書きます。

id:pass
AOJの場合

stands/contest.txt を開きます。1行目に、AOJのAPIのURLを書きます。2行目に、コンテストの名称を書きます。2行目はわかりやすければ何でも構いません。例えば、こんな感じ

http://judge.u-aizu.ac.jp/onlinejudge/webservice/contest_standing?id=ACPC2015Day1
ACPC2015Day1

1行目の ACPC2015Day1 は、コンテストのURLにidがついているので、それをコピーすればいいです。こういうのの末尾についているID→ http://judge.u-aizu.ac.jp/onlinejudge/contest_standing.jsp?id=ACPC2015Day1

AOJの場合は、ユーザID/パスワードは必要ありません。


動作確認

風船システムでは、どんなことができるか紹介します。

オンラインチームを取り除く

オンサイトチームの情報だけを見られるようにするために、オンサイトチームかそうでないかを選択できるページがあります。ただ、このページにアクセスする導線がなさげです(今気付いた)。「システムのURL/ranking.php?contest_name=コンテストID」でアクセスできます。http://XX.XX.XX.XXでシステムが動いていて、JAGSummerDay4のチームの管理をしたいなら、

http://XX.XX.XX.XX/ranking.php?contest_name=JAGSummerDay4

みたいな感じです。

このページを開くと、コンテストに参加しているチームの一覧が表示されます。

f:id:Respect2D:20151217025029p:plain:w350

チーム名をクリックすると、オンサイト参加者と外部参加者のフラグが入れ替わるようになっています。ちょっとわかりづらいですが、オンサイト参加者は、表の上側に表示されるようになっています(後でもう少し見やすく直した方がよさそう)。上図では、kog_115さんから上はオンサイト扱い、SoMin_Munさんから下は外部チーム扱いになります。

ログインしてみる

f:id:Respect2D:20151217024743p:plain

ログインします。名前を入れれば誰でもログインできます。

コンテストを選ぶ

f:id:Respect2D:20151217024802p:plain

ログインすると、コンテスト一覧が表示されます。ここで登録されているのは、JAGSummerDay4の1つだけなので、このコンテストを選んでみます。

風船配布管理画面

f:id:Respect2D:20151217025647p:plain:w350

このシステムの一番メインの画面です。各行が、正解1つ=風船配布1回に相当します。この画面には、先程オンサイトに設定したチームしか表示されないようになっているので、前まで鬱陶しかったノイズが一切ありません(オンサイトチームの設定が正しければの話ですが)。

このシステムにおいて、風船の配布状態として、以下の3種類が存在します。

  • 風船を配っていない&まだ風船を配布する担当が決まっていない=誰か配る宣言をする必要があります

   f:id:Respect2D:20151217030634p:plain:w350

  • 風船を配っていない&風船を配布する担当は決まっている=あとは担当者にまかせておけば安心

   f:id:Respect2D:20151217030819p:plain:w350

  • 風船を配り終えた=無視してよし

   f:id:Respect2D:20151217030828p:plain:w310

風船を配る宣言をする

f:id:Respect2D:20151217030634p:plain:w350

このチームの風船の担当がまだ決まっていないようなので、自分が風船を配る担当に名乗り出てみます。「風船を配る」ボタンを押すと、自分が担当としてアサインされ、以下のような画面が表示されます。

f:id:Respect2D:20151217031818p:plain:w200

この画面で、「done」ボタンを押せば、風船を配り終えたことになります。今は、まだdoneボタンを押してなくて、担当者が決定しただけなので、風船配布管理画面を閲覧すると、次のように表示されます。

f:id:Respect2D:20151217030819p:plain:w350

風船を配り終える

風船をチームのもとへ無事に配り終えた後は、先程の画面で「done」ボタンを押します。そうすると、風船配布管理画面では、以下のように表示され、風船をすでに配り終えたことがわかります。

f:id:Respect2D:20151217030828p:plain:w310

今後

ということで、風船配布管理ツールについての紹介でした。このツールができてから、風船の配布であたふたすることがなくなって、非常に助かっています。自動化万歳。

今後できるといいこと

  • オンライン参加登録ページ
    • 今は、コンテスト運営側でオンサイトチームかそうでないかを見極めてランキングページで設定していますがそれも面倒。コンテスト参加者が、自分のチームはオンサイト参加であることを登録できるようなページがあると運営の手間がはぶけてよさそう。
  • 風船配布ページを開いていると、正解が出たときにデスクトップ通知してくれる
  • ビジュアルもう少しわかりやすく

まとめ

ということで、コンテスト運営向けのツールを2つご紹介しました。どちらも即席で作ったツールでまだまだ作りかけなので、こういう機能あるといいんじゃない?ここ直した方がいいのでは?みたいなのがあれば、issue/PR、大歓迎です。

あと、宣伝です。ACM-ICPC OB/OGの会(http://acm-icpc.aitea.net/)のスタッフを絶賛募集中です。作問したい人はもちろん、今回紹介したようなツールの開発に関わりたいという方も大歓迎です。一緒に、ICPC現役のみんなを応援しましょう。

以上で終わります。明日は、その1が skyaozora さん、その2が cielavenir さんです。お楽しみに〜。