tatsumack blog

エンジニアによる雑記です

AtCoderの拡張機能を3つ作った話

これは AtCoder関連サービス Advent Calendar 2018 - Adventar の9日目の記事です。
今年の3月くらいから競技プログラミングにハマり初め、精進していく過程で、AtCoder拡張機能が3つ生まれたので紹介します。


AtCoder-ACer


これは、AtCoderの問題一覧ページにコンテスト中にACした人数を表示する拡張機能です。
AtCoder-ACer【Chrome拡張】

なぜ作ったの?

たまに配点の高い問題の方が多く解かれていることがあり、Codeforcesのように問題一覧ページに現在ACしている人数が表示されていると、コンテスト中の立ち回りを判断する上で役立つだろうなーと思って作りました。

作った後に、順位表の最下部に同じような情報が出ていたことに気付いたのですが、どうせ作ったのだからということで、公開しました。
ありがたいことに、40人くらいの方に使っていただけているので、公開して良かったですね。

どうやって作ったの?

AtCoderのjsのコードを眺めていると、https://beta.atcoder.jp/contests/[コンテスト名]/standings/json というAPIでコンテスト情報のjsonが取得できることが分かったので、問題一覧ページでこのAPIにリクエストを投げて、返ってきたjsonをパースして表示しています。
(ちなみに、ちょっと実装をサボっていて、部分点もAC扱いにしちゃっています。)


AtCoder-Video


これは、AtCoderのコンテストページに解説放送へのリンクを追加する拡張機能です。
AtCoder-Video【Chrome拡張】
AtCoder-Video【UserScript】

なぜ作ったの?

YouTubeで解説放送を探すのが面倒だったので作りました。

どうやって作ったの?

YouTube APIを使って、AtCoderチャンネルの動画の一覧を取得しています。YouTube APIを使うために必要なAPI keyはクライアントに置くことはできないので、サーバーを用意する必要がありました。
が、真面目にサーバー管理するのが面倒だったので、今回はGoogle Apps Scriptを使用しました。サーバーレスな感じで開発することができ、今回のような用途では非常に便利でした。

Cronのように定時実行することもできるので、10分毎にYouTube APIを叩き、取得した動画情報をスプレッドシートに保存しています。

あとは、このシートからデータを取得しjsonとしてレスポンスを返すAPIを用意して、拡張スクリプト側からはそのAPIを叩いています。
Google Apps Scriptは無制限に呼び出せるわけではないので、クライアント側では一度取得した結果をlocalStorageに一定期間保存するような実装にして、APIを呼ぶ回数を抑えるようにしています。

ちなみに、YouTubeの放送タイトル名にtypoがあったりすると、うまく動きません。

あと、現状、企業コンには未対応です。
今後、企業コンが増えてきそうな流れなので、ぼちぼち企業コンにも対応しないとなーという気持ちはあります。

[2019/05/17追記]
AtCoder本家のサイトに解説放送へのリンクが追加されるようになったので、AtCoder-Videoは削除しました。


AtCoder-TestCase-Extention

f:id:tatsumack:20181208232400p:plain
これは、AtCoderのテストケースへのリンクを追加する拡張機能です。
個人的には一番気に入っている拡張機能で、今回作った3つの拡張機能の中でも一番利用者が多いです。(160人くらい)
AtCoder-TestCase-Extention【Chrome拡張】
AtCoder-TestCase-Extention【UserScript】

なぜ作ったの?

AtCoderはテストケースを一部Dropboxに公開しているのですが、Dropbox上で探すのが面倒だったので作りました。
また、ABCとARCが同時開催された回は、ABCのテストケースがARCのディレクトリ配下にまとめて格納されているので、ABCがどのARCに対応するのか調べる必要がある、という点も面倒でした。

どうやって作ったの?

開発当初はサクッと作れると思っていたのですが、なかなか骨が折れました。。

各テストケースへのURLを取得する必要があり、DropboxAPIからサクッと取得できると楽だったのですが、ドキュメントを調べた限りそれは難しいようでした。
そのため、Dropboxのページをスクレイピングする必要がありましたが、DropboxのページはJavaScriptで動的に生成されているページだったので、単純にレスポンスをパースするだけではうまくいきません。

そこで、PhantomJs Cloudを利用しました。スクレイピングしたいURLをパラメータとしてPhantomJs CloudのAPIを叩くと、JavaScriptで動的に生成した後の結果を返してくれます。
公開されている全てのコンテストの情報をスクレイピングしようと思うと、無料枠だと3ヶ月ほどかかる計算だったのには頭を抱えましたが、諦めて課金しました。

また、AtCoderのテストケース名から公開されているファイル名を判定する必要があるのですが、コンテスト毎に規則が異なっていたことにも困りました。
当初、テストケース名にファイル拡張子がついていない場合は、.in / .out 拡張子で保存されていると決め打って実装していたのですが、いくつか例外があったことが後ほど発覚しました。

あと、この拡張機能もサーバーサイドはGoogle Apps Scriptを使用しています。
サーバーを用意せずにやりたいことに集中できるのは楽ですね。

こちらも現時点では企業コンは未対応です。