ステマ記事です.
みなさん Cookie Clicker を覚えていますか
これです. 昔一瞬流行ったなあ, という感想が出てくることを予想してますが (ついこの前言われた), まだまだ続けている人はいて, 私もその一人です.
過去の記事:
Mackerel とは
はてなが開発しているサーバー管理・監視サービスです. 詳細は下記を見てね.
上記の通り Mackerel は基本的にはサーバーを監視するためのサービスで, サーバー (ホスト) の各種状態 (メトリック: CPU, メモリ, ディスクの使用率など) の監視したり, 推移をグラフにして眺めたりすることができます. 一方それとは別にサービスメトリックというものがあり, サーバー各個体に結びついた情報ではなく, サービス (例えば複数のサーバーを使って何らかのサービスを提供する場合を考えてもらえれば良いです) についての各種状態についての状態を監視することができます. これは Web API を使って状態を比較的簡単に投稿することができて, 今回はこれを使って Cookie Clicker の状態を監視してみました. *1
Mackerel で Cookie Clicker を監視する
先にどういったものができたのかをお見せしましょう.
これは cookies (現在の所持クッキー枚数), cookiesPerSecond (一秒あたりのクッキー生産量), cookiesEarned (現世でこれまでに生産したクッキー枚数), cookiesAllTime (前世も含めてこれまでに生産したクッキー枚数) の直近一日分の記録です (グラフにマウスカーソルを乗せるとどの線がどれなのかわかります). リアルタイムに更新されているので見ているタイミングによって値は変化します.
これはどう実現されているかと言うと, まあ皆さんご想像の通りだと思いますが, 一定間隔でゲームの状態を投稿するスクリプトを Cookie Clicker のページ内で動かしています.
Cookie Clicker はとても素朴な作りになっていて, ゲームの状態はすべてグローバルにある Game
オブジェクトから取得できます.
例えば現在所持しているクッキー枚数は Game.cookies
, といった具合ですね.
これらのプロパティを読むだけならチート判定が出ることもありません.
サービスメトリックの投稿は https://api.mackerelio.com/api/v0/services/<サービス名>/tsdb
に対して POST で JSON データを送るだけです.
投稿スクリプトは大体次のような感じで, これをゲーム起動後にコンソールを開いて貼り付けて実行します.
setInterval(() => { const time = Math.floor(Date.now() / 1000); const body = JSON.stringify([ { "name" : "CC.cookies", "time" : time, "value": Game.cookies }, { "name" : "CC.cookiesPerSecond", "time" : time, "value": Game.cookiesPs }, { "name" : "CC.cookiesEarned", "time" : time, "value": Game.cookiesEarned }, { "name" : "CC.cookiesAllTime", "time" : time, "value": Game.cookiesEarned + Game.cookiesReset } ]); const req = new Request( "http://localhost:7777/proxy", { mode : "cors", method: "POST", body } ) fetch(req); }, 60 * 1000);
お気付きの方もいると思いますが, Cookie Clicker のページ内で動かしている都合上, 別ドメインの Mackerel に直接リクエストを送ることはできない*2ので, ローカルに Node.js でプロキシサーバーを立ててそこに投稿して, さらにそこから Mackerel に投稿しています. それ以外には特に難しいこともしていません.
というわけでこれで上に見せたようなグラフができて, どこにいても現在のクッキー生産の様子がわかるわけです. CPU 使用率といったものほど変化があるわけではありませんが, 見ていて楽しい.
よかったこと
下のグラフは放置時の 5 分間のクッキー生産量の理論値 (standby) と, 実際に 5 分間で生産されたクッキー枚数 (actual) の直近 12 時間の様子です.
これもリアルタイムに変化するのでどのように見えているかわかりませんが, 最初に私がこれを見た時は次のようになっていました.
左の方は理論値 (青) に比べて実際の値 (黄) がかなり小さな値になっています.
これには, 通常 Cookie Clicker は setTimeout
を使って 30 fps で動いているのが, タブがバックグラウンドになっている間は 1 fps になってしまうことが影響しています.
Cookie Clicker 側も対策はしているので, 例えば生産量がいきなり 1 / 30 になるということはないのですが, それでも思っていたよりもずっと少なくなってしまう (1 / 5 程度) ということがわかりました.
実際にどの程度影響が出るのかはちゃんと計測してみないとわからないものですね.
ちなみに上の図の一番右端はタブをフォアグラウンドにして放置している状態で, ちゃんと理論値と同じ値になっています. でもファンがずっと回り続けてうるさいのでどうしようか考え中...