Skip to content

Instantly share code, notes, and snippets.

@nandenjin
Last active June 15, 2018 16:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nandenjin/4f0e5dac6000f696cfee2d067f95b52f to your computer and use it in GitHub Desktop.
Save nandenjin/4f0e5dac6000f696cfee2d067f95b52f to your computer and use it in GitHub Desktop.

The Google Puzzle Rescue

Update: 2018/06/16

thegooglepuzzle.comが閉鎖され、コンテンツが削除されたため、このブックマークレットも使用できなくなりました。またいつか、こんな楽しいコンテンツが世に出るのを願ってやみません。

6年の時を超えてGoogle Puzzleをもう一度プレイする

The Google Puzzle thegooglepuzzle.com は、2011年に公開された、「リアル脱出ゲーム」を主催するSCRAPとGoogleが共同で作った、ブラウザでプレイするパズルサイトです。公開当時の記事にもあるように、SCRAPが作成した問題をGoogleがWebアプリとして構築したものになっており、当時から高いクオリティを誇ったコンテンツでした。

公開から6年、内部のスクリプトエラーでプレイを開始できなくなっていたものを、ブックマークレットによるコード挿入で、エラーを修復してもう一度プレイできるようにしました。

使い方

  1. Google ChromeでThe Google Puzzleを開きます。 
  • モバイル版ブラウザでは正常にプレイできません(The Google Puzzleの元からの仕様です)。
  • Mac版のChromeでは、全画面表示にするとうまく作動しませんでした。
  1. アドレスバー左端の「i」のアイコンをクリックし、「ポップアップ」の項目を「このサイトでは常に許可」に切り替えてから、ページを再読み込みします。
  2. The Google Puzzleのタブのアドレスバーにjavascript:と入力し、その後に続けて、このページの下に表示されているsnippet.jsの中身を貼り付けます。
  3. Enterを押すと画面が切り替わり、コンテンツが読み込まれます。    - エンディング終了後に真っ白な画面が表示されてしまうページがあるので、この画面でも3と4の作業を繰り返してコンテンツを表示させてください。

既知の問題

  • プレイの本筋に関係ない部分でいくつか誤作動するところがあります。
(()=>{
/* Web Audio APIの差分吸収 */
window.webkitAudioContext = AudioContext;
AudioContext.prototype.createGainNode = AudioContext.prototype.createGain;
AudioBufferSourceNode.prototype.noteOn = AudioBufferSourceNode.prototype.start;
AudioBufferSourceNode.prototype.noteOff = function(){
try{ this.stop(); }
catch(e){
try{
this.start();
this.stop();
}catch(e){}
}
};
/* スクリプトのリロード */
const es = document.getElementsByTagName("script");
let ldng = 0, nes = [];
for( let i = 0; i < es.length; i++ ){
const e = es[i];
if( !e.src || e.src.indexOf("os.js") > -1 ) continue;
ldng++;
const q = new XMLHttpRequest();
q.open( "GET", e.src );
q.onload = ( ( h, src ) => {
return () => {
ldng--;
let r = q.response;
const s = document.createElement("script");
s.innerHTML = r;
nes[h] = s;
c();
};
})( i, e.src );
q.onerror = () => {
ldng--;
c();
};
q.send();
}
const c=()=>{
if( ldng <= 0 ){
nes.forEach( ( ne ) => {
if( !ne ) return;
document.body.appendChild(ne);
});
if( window.onload ) window.onload();
/* Puzzle3のYouTubeプレーヤを現行APIで置き換え */
const puzzle3Patch = ()=> {
if(
WindowObjects && WindowObjects.main
&& WindowObjects.main.location.href.indexOf( "puzzle3.html" ) >= 0
&& WindowObjects.main.document.body
){
const W = WindowObjects.main;
delete W.onYouTubePlayerReady;
W.document.body.style = "overflow:hidden;";
W.document.body.innerHTML = `
<div id="player"></div>
<script id="ytph"></script>
<img src="http://i.imgur.com/5tksQkM.jpg"
style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; margin: auto; height: 100vh; width: 178vh; cursor: pointer;" onclick="this.style.display='none';ytp.playVideo();">
`;
W.ytp = {};
W.onYouTubeIframeAPIReady = () => {
W.ytp = new W.YT.Player('player', {
height: '440',
width: '729',
videoId: 'UfsQqI9C4dc'
});
};
const sc = document.createElement( "script" );
sc.src = "https://www.youtube.com/iframe_api";
W.document.body.appendChild( sc );
}else{
setTimeout( puzzle3Patch, 1000 );
}
};
puzzle3Patch();
}
};
})();

技術情報(いったい何をしているのか)

あーでもないこーでもないと試しながら書いてたらひたすらに読みにくいコードになってしまいました。お許しください。

Web Audio APIの差分吸収

音の管理を行うAudioControl.js内のコードにおいて、Web Audio APIのコンストラクタが現行標準のAudioContextではなく、プリフィクス付きのwebkitAudioContextになっていました。webkitAudioContextがサポート終了となった時点でエラーが発生しそこでスクリプトが止まるようになったようです。トップページが正常に表示されない直接の原因もこれのようでした。

この部分がエラーとなるがためにそれ以降のスクリプトも実行されていない状況だったため、まず「プリフィクスあり」のコンストラクタを「プリフィクスなし」のエイリアスとして新規に作成し、その上でページ内の全ての <script>をリロードすることで対処しました。

webkitAudioContext.prototype.noteOn()など、プリフィクスが外れた際に仕様からなくなったメソッドについても、適宜エイリアスを貼って正常に動くようにしましたが、 webkitAudioContext.prototype.noteOff()については、AudioContext.prototype.stop()に単純にエイリアスを作ると、start()が先に呼ばれていない環境で実行されてエラーとなる事象があったため、内部的にエラーハンドリングを追加しました。

Puzzle3のYouTubeプレーヤの置き換え

 Puzzle3において表示されるYouTubeプレーヤがFlashを使用した古いもので、APIが正常に動作していない状況でした。このため、Puzzle3が表示されたタイミングを検知し、最新のYouTube Iframe Player APIのコードに置き換えるようにしました。

また、APIの内部的な挙動が変更されており、ヒントになるべき表示がなくなっていたため、対策を打ちました。何をやったのかを言うとヒントの存在がわかってしまうので、プレイした後で探してみてください。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment