[Rumble-jp-dev] ロボット作成データのやり取り方法

Back to archive index

Naoki Kurosawa naoki_kuros****@ybb*****
2003年 4月 3日 (木) 21:14:16 JST


黒澤です。

ロボットが作成したデータのやり取り方法の案です。
ご意見よろしくお願いします。

まず、1つのロボットの対戦を複数のサーバが同時に実行してしまうと、
同時に上がってくるデータのどれを残すのか判断できなくなってしまう、
というお話はしたと思います。

以前この話をしたときは1リーグ内での話でしたが、
1on1とmeleeなど、1つのロボットが複数リーグに同時に参加するので、
リーグ間でもデータ更新の競合が起きないよう考慮する必要があります。

これを解決するのために、ロボットが作成したデータはリーグごとに
独立して保存・やり取りするのがいいと思います。

つまり、あるロボットが1on1とmeleeの2つのリーグに属しているとき、
1on1のリーグで対戦したときに作成したデータと
meleeのリーグで対戦したときに作成したデータは
別に管理されるということです。

#同じリーグなら、シーズン間では引き続きデータを利用できます。


それでは実装案。

■データ格納領域
JBOSS_HOME直下などにデータ格納用のルートディレクトリ
(ここでは例としてrobot_data)を作ります。

そして、ルートの下にはleague_idを名前としたサブディレクトリを作ります。
ロボットのデータはこのサブディレクトリの下に、
robot_version_idまたはJARファイル名を名前とした
(つまり、ロボット名とバージョンが区別される名前)
サブディレクトリを作って、その中に格納します。

例えば、リーグ1に
・robotA ver1.0
・robotA ver1.1
・robotB ver1.0
が所属していたとすると、
JBOSS_HOME/robot_data/1/
  robotA_1.0.jar/
  robotA_1.1.jar/
  robotB_1.0.jar/
というディレクトリ構成になります。

各ロボットのディレクトリを作成するタイミングは、
ロボット登録終了後、JARファイル内に最初からデータが含まれているときか、
Robotがデータを作った後です。


また、分散サーバ側にも同じ構成でディレクトリを作ります。

ここで作成したディレクトリと、Robocodeの.robotcacheの下にできる
ロボットデータ格納用ディレクトリを区別するため、
「分散サーバのロボットデータディレクトリ」と、
「.robotcacheのロボットデータディレクトリ」というように呼び分けます。


■通信用クラス

○FileDataSpecを新設
FileDataSpec {
    String  name;
    int     size;
    long    time;
}
中央サーバから取得するファイルを指定するときや、
中央サーバ上から削除するファイルを指定するときに使います。

○RobotSpecを変更
対戦情報取得時に使用されるRobotSpecクラスに、
データファイル一覧を渡すためのメンバとして
FileDataSpecの配列を追加します。

○DownloadFilesを新設
中央サーバからダウンロードしたいファイルを指定するときに使います。
DownloadFiles {
    int robot_version_id;
    FileDataSpec[] files;  //取得したいファイルの一覧
}
1つのロボットにつきDownloadFilesのインスタンスを1つ使います。

○RobotDataを新設
ロボットデータダウンロード/アップロード時に使います。
RobotData {
    int robot_version_id;
    byte[] data;       // 転送したいファイルをすべてZIP圧縮したもの
    FileDataSpec[] deleteFiles; // 削除したいファイルの一覧
}
deleteFilesは対戦結果転送時のみ使い、対戦を行った結果削除された
ファイルがあったら、中央サーバ上でも削除するように指示します。

○BattleResultSetの変更
対戦した結果削除されたファイルの一覧と、新規作成/更新されたファイルを
中央サーバに送信するため、
BattleResultSetにRobotDataの配列を追加します。

■対戦情報取得時

対戦情報取得時、中央サーバはロボットのデータディレクトリをサーチして
ファイル一覧を作成し、FileDataSpecの配列としてRobotSpecにセットして
分散サーバに渡します。
ロボットのディレクトリがないときはnullにしておきます。

分散サーバは対戦情報取得後、バトルを開始する前に
FileDataSpecの配列をチェックします。
・nullなら何もしない
  もしくは、分散サーバのロボットデータディレクトリが存在したら消す。
・nullでないなら分散サーバのロボットデータディレクトリと比較して、
  データ同期処理(下り)に入ります。


■データ同期処理(下り)
分散サーバのロボットデータディレクトリが存在しないときは
作成します。
中央サーバから取得したファイル一覧と、
ロボットデータディレクトリを比較して、
・ローカルにあるが、ファイル一覧に載っていないものは削除
・ファイル一覧に載っているがローカルにないもの、
  もしくは、ファイル一覧に載っている方が新しいものについては、
  ファイルを取得

□ファイルの取得方法
Webサービスでやります。
#Webサービスでやると、バイナリをやり取りするときBASE64エンコーディング
#しなければならないので通信量が増えますが、やり取りの内容が複雑なので
#仕方ない、とします。

GetRobotDataサービスをつくり、サーバ側受け口とします。
getメソッドを作ります。
パラメータは、
・分散サーバのhostname
・分散サーバのpassword
・league_id
・DownloadFilesクラスの配列

分散サーバは、1division分のバトル情報を取得しているので、
そのdivisionに属するロボット1台につきDownloadFilesを1つ作り、
その配列を送信することで、一気に1division分のデータを取得しようとします。

で、
GetRobotDataはhostnameとpasswordで認証した後、
RobotDataの配列を返します。
このとき、RobotData#deleteFilesメンバはnullです。

RobotDataの配列を取得した分散サーバは、
分散サーバのロボットデータディレクトリに上書きで展開します。


■バトルの実行方法
バトルの実行時は、.robotcacheのロボットデータディレクトリの中身を
いったん消し、分散サーバのロボットデータディレクトリの内容を
コピーしてからRobocodeを起動します。


■対戦結果の送信時
分散サーバのロボットデータディレクトリと
.robotcacheのロボットデータディレクトリの中身を比較し、
RobotDataの配列を作成します。
1つのロボットに1つRobotDataを作成し、以下の情報をセットします。
・削除されたファイルの一覧をRobotDataのdeleteFilesメンバに設定
・更新されたファイルをZIP圧縮し、dataメンバに設定
BattleResultSetにRobotDataの配列を格納して送信します。


また、分散サーバのロボットデータディレクトリの中身をいったん消し、
.robotcacheのロボットデータディレクトリをコピーしておきます。

RobotDataの配列を受け取った中央サーバは、
削除指示と更新データを反映させます。


以上です。


※※データ量管理をしていないロボットを救うには※※

ロボットデータ領域は200KBまでという制限がRobocodeにはありますが、
#クォータと呼ぶことにします。
ジャパンカップに応募されたロボットの中には、
ランクわけなしのリーグ戦を行う前提でできていないものがあります。
つまり、データ量が200KBまで行かないことがあらかじめわかっているために、
作ったデータで不要なものを削除する仕組みを持っていない
ロボットがあるということです。

これを救うには、たとえばクォータの90%までデータが増えたら、
古いファイルを削除する機能を付けることが考えられますが、

一方、更新しない初期データを持ち、対戦を行うごとにデータが増えていく
タイプのRobotがあると、お掃除機能が初期データを削除してしまって
動作しなくなることが考えられます。

どちらも救おうとすると、
お掃除機能のON/OFFとデータ削除の閾値をユーザに設定してもらうことが
考えられますが、ちと面倒でもあります。

皆さんのご意見はいかがでしょうか。


ちなみに、お掃除機能は分散サーバ側で動作し、
1戦やるごとに起動する必要があると思われます。

-- 
Naoki Kurosawa <naoki_kuros****@ybb*****>




Rumble-jp-dev メーリングリストの案内
Back to archive index