Google Doodleのルービックキューブを解くChrome拡張を作った

http://www.google.com/doodles/rubiks-cube のやつ。

とっくに旬を過ぎていて今さら感あるけど、、

って自分で言ったし。

この拡張を入れた状態で 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とか使って適当にやりとりしつつ。



いやーしかしこんなの考えたエルノー・ルービック先生すごいし 様々な解法やアルゴリズム考え出したヒトたちすごい。