2011年6月20日月曜日

ブラウザ三国志 経路算出:ChromeExtensionを改良

さて前回ダイクストラで最短経路を算出してみました。
このままではもちろんダメで何がダメかというと、
マップ見るたびに経路計算をしてしまうというダメダメな仕様。

このままでは通常時マップを見る時に計算してしまう。
ただ線引くだけのくせに、、、ジャマ!アンインストール。である。

なのでGUIを作って(無駄に画面だけあったけど><)
そこでON/OFFできるようにする。せっかくなので座標を貯めこむ。

で座標を指定して経路を算出!みたいな感じである。

前回利用したcontent_scriptsとページ間のリソースの共有は基本的にできません。
コンテキストスクリプトは拡張機能というよりWebページに埋め込む。という仕組みである為、
拡張機能とは隔離されているもの。という風にできています。

そこでbackgroundという仕組みを利用します。manifest.jsonに以下を追加します。


"background_page": "html/background.html",


全体はココ

で、イベントによる受け渡しをやるわけですが、以下が概要です。



こういう風にしたいと思います。

座標を保存する

まず、content_script により、51x51マップの時に、座標を吸い上げて以下を行います。


var map = document.getElementById( "map51-content" );
if ( map == null ) {
return false;
}

var pointArray = [];
var mapUlList = map.getElementsByTagName("ul");
for ( var ulIdx = 0; ulIdx < mapUlList.length; ++ulIdx ) {
var mapLiList = mapUlList[ulIdx].getElementsByTagName("li");
for ( var liIdx = 0; liIdx < mapUlList.length; ++liIdx ) {
var linkTag = mapLiList[liIdx].getElementsByTagName("a")[0];
var point = createPoint(linkTag);
pointArray.push(point);
}
}

//バックグラウンドで保存する
chrome.extension.sendRequest( {
action : "save" ,
args : [pointArray]
} , function( response ) {
//戻り値処理
console.log(response);
}
);


以前処理した時と同じように座標オブジェクトをcreatePoint()によって作成しています。
ここで重要なのは、chrome.extension.sendRequest()により、イベントを発生しています。

これはbackgroundで以下のように処理して、イベントを待機しています。


var CMD = {
isSaveMode : isSaveMode ,
save : save ,
analysisDijkstra : analysisDijkstra
};

function init() {
chrome.extension.onRequest.addListener( function ( message , sender , sendResponse) {
var retVal = CMD[message.action].apply(this,message.args);
sendResponse( { values : retVal } );
} ) ;
};


backgroundの処理はブラウザが立ち上がった瞬間に始まりますので
そこでinit()を呼び出してあげます。
CMDはmessageによりメソッド名を送ってそれを実行する為の配列ですね。
自分で判定文を作って、関数を作っても良いのですが、こうしておくと、やりとりが増えても大丈夫です。

listenerですのでsendRequest()を呼んであげたらここが呼び出されるので
「save」というactionを呼び出してる感じ。argsにはオブジェクトのリストを渡してます。

ここでオブジェクトに変換せずにそのままHTMLのDOMを送りたい所ですが、
この通信手段にはJSONが使われているみたいで、その引数の変換時にデータ内に改行が存在してしまい、変換に失敗するようです。

で受け取ったbackgroundはリストにより、座標を保存します。


function save( mapArray ){
for ( var idx = 0; idx < mapArray.length; ++idx ) {
var point = mapArray[idx];
localStorage[point.x + ":" + point.y] = JSON.stringify(point);
}
};


こんな感じですね。

localStorageは「WebStorage」と呼ばれるHTML5的な新しい技術で拡張機能として専用のサンドボックス内にデータを保存するような仕組みです。
配列と同じようにして保存する事が可能です。
"他のブラウザで、、、"って一瞬思いましたが、冷静に考えればChromeExtensionでした><。

localStorageには文字列が保存できるので JSON.stringify(point);で文字列にして保存しています。
※使っている場所ではJSON.parse()を実行しています。

これで座標を保存ができるようになったわけです。
実際にはGUIを利用して、「保存モード」かを判定して処理を行っています。
※それも通信とlocalStorageを利用してから実現しています。


経路の計算を行う

これで十分座標は保存できたと考えて、
次は画面操作との兼ね合いです。とは言っても簡単なHTMLですので、そんなに難しい事はしていません。



こういう画面です。
ソースはココ

※経路表示はまだ実装してないです><

この画面から経路算出の為に座標をbackgroundに渡して
※座標は保存するようにしたので、引数では渡してませんけど><
そこから経路算出を行っています。そこから戻り値で、経路情報を返しています。

ソース自体はgithubにすべておきました。
ダイクストラの大部分は変更していませんが、

・51x51の配列を使わないようにした。
・座標データはlocalStorageにある

って事で、直接座標データを取って処理しています。
※色々改良する余地はあると思います。

さて、これでWebページの情報を残して処理をするという基本アーキテクトの変更は可能になったわけです。
次回はbackgroundを利用して、経路表示も行いたいと思います。

1 件のコメント:

匿名 さんのコメント...

一ブラウザ三国志プレイヤーです。(mixiじゃなくて公式の方ですが……)
ブログがためになりました。
丼ちゃんゴンを公式鯖(m21ではなくs21)でも使えるようにしたいのですが、書き換えとか出来ますでしょうか?

できればお教えくださいますと幸いです。