http://www.google.com/doodles/rubiks-cube のやつ。
とっくに旬を過ぎていて今さら感あるけど、、
- Google Doodle's Rubik's Cube Solver - Chrome Web Store
- source: https://github.com/sugyan/google-doodle-rubik-cube-solver
この拡張を入れた状態で https://www.google.com/logos/2014/rubiks/rubiks.html を開いてキューブをクリックしてスタートすると左上に"solve"ボタンが現れ、それを押すと勝手に完成させてくれる。
デフォルトの初期状態に対しては31手で解く。(ちなみに https://gstatic.com/logos/2014/rubiks/iframe/index.html を開いてdeveloper toolsでcube.twistQueue.history
みてみると分かるけど、デフォルトの初期状態は40手まわして作られている。solveCube()
と叩くとそれを遡って復元してくれる。)
キューブの解を求める方法は色々ありそうで よく知らないけど、とりあえず https://github.com/cubing/jsss のものを適当に使わせていただいた。だいたいどんな状態に対しても30手くらいで解を示してくれるっぽい。
JavaScriptだけで完結するしブックマークレットとかでも出来るかな?と思ったけど https://www.google.com/logos/2014/rubiks/rubiks.html からスタートすると https://gstatic.com/logos/2014/rubiks/iframe/index.html をiframeで開く、という仕組み上 ムリそうだったのでextensionで実現することにした。
しかしcubeの状態を知ろうとしてもChrome Extensionのcontent_scriptsは"isolated world"で実行されるため、開いているページでブラウザが実行しているJavaScriptの変数や関数を直接弄ることはできない。
なので対象page上で任意のコードを実行させるために、文字列化した関数を含むscript要素を拡張側から挿入させるなどの方法があるようだ。
これを使ってcubeの状態が変更されるごとにそれを適当なDOM要素に埋め込み、解を計算する処理を行いたいときにはそのDOM要素から値を読み込む、という方法でデータを受け渡しするようにしてみた。その他のイベント処理なんかはwindow.postMessageとか使って適当にやりとりしつつ。