search
LoginSignup
1
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

AtCoder Color Markという円を表示する拡張機能を作った話

はじめに

これは、AtCoder関連サービス Advent Calendar 2018の18日目の記事です。今年作ったAtCoder向けのChrome拡張について書きます。

この拡張へのリンクはこちら。何かあったらフィードバックをもらえるとありがたいです。
※ 追記: この記事を公開した日にAtCoderのURLに変更が行われ、一時的にこの拡張が動かなくなってました。

機能

概要

  • コンテストの順位表のそれぞれの名前の右にレーティングの円を表示
    • こんなかんじ
  • プロフィールの過去の参加コンテストのページにレーティングの円を表示(beta版のみ)
    • こんなかんじ

どうして作ったのか

  • 自分の前後のレーティングを見たい
  • 過去のパフォーマンスがどの色のどのレベルなのか分かりやすくしたい

どうやって実現しているか

Chrome拡張部分

Chrome拡張とは

Chrome拡張は個人で書いて公開1することができ、それをインストールすることでChromeに機能を追加することができます。この拡張機能の様なDOMの操作だけでは無く、クライアントJSではできないようなChromeの用意しているAPIを利用した機能も実装できます。逆に、拡張機能のメニューが必要な場合は自作が必要になります。そして、Chromeで動けば良いため、ES6なども問題なく使用することができます。
公開方法としては、Tampermonkeyという拡張機能のスクリプトとして公開することもできます。こちらはユーザ登録派不要です。

manifest.json

"https://*.contest.atcoder.jp/*", 
"http://*.contest.atcoder.jp/*",       
"https://beta.atcoder.jp/contests/*",     
"https://beta.atcoder.jp/users/*/history"

上記の4つのドメインを対象にしてます。betaの方がドメインが統一されていてloclstorageとか共有できて嬉しいです。
上記のページに対してCSS,JSを一個ずつ挿入してます。

表示部分

レーティングの円の表示はcanvas要素の挿入によって実現してます(canvasなのでinnerTextには無影響なはずなので、他の拡張に影響はおそらく無いはず)。表示内容はおそらくTopCoderと同じようになるようにレーティングの色2とその色の最大値と最小値を100%、0%にしたときにどの位置になるかを円で表しています。
要素
完成図
canvasの円は上の3つの要素を組み合わせて描写しています。上の例は40%の場合の例で、まず左の円と真ん中の長方形の共通部分のみ描写します(source-in)。そうすると円の中身の部分だけ作れるので、それに右の円の輪郭を足し合わせるとTopCoderみたいな円が完成します。

取得部分

順位表にはユーザのレーティングは載っていないため、円を表示するにはそれを取得する必要があります。そのため、localstorageを確認して最新のデータが無かった場合に自前のサーバにレーティングのJSONを取得しに行っています。取得したJSONはlocalstorage3に取得時刻とともに記録し、無駄にデータを取ってこないようにしています(Chromeはサーバ側のキャッシュ用ヘッダを無視して取得しているように見える)。具体的には15分キャッシュします。
beta版を使用していない場合、コンテストごとにドメインが異なるのでlocalstorageにJSONがそれぞれ溜まってしまうという弊害はあります。
ユーザのコンテスト成績のページについてはレーティング値がページ内にあるのでそれを取得して表示しているだけでデータの取得・保存はしていません。

バックエンド部分

クライアント側でAtCoderのユーザページのJSONをたたくのも可能ですが、AtCoderとクライアント両方の負荷の負荷軽減のため自前のサーバでJSONを配布してます。
JSONは30分に一回AtCoderのランキングページをスクレイピングしてJSONを生成しています。ライブラリはjsdomを利用してます。
手順は以下のとおり、
1. ランキングページにアクセス
2. ページャの右端からページ数を取得
3. 各ページのテーブルの特定列からユーザとレーティングの関係を取得
4. JSONにして保存

TODO

  • beta版以外での無効化(JSONがかなり溜まるため)
  • JSON取得・保存をサーバレス化する

  1. Chrome拡張はChromeウェブストアから公開できますが、5ドルが最初に必要になります 

  2. レーティングの色の分布はここを参考にしました。 

  3. cookieは容量が小さすぎて入らないため 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1
Help us understand the problem. What are the problem?