MOE3: OrderStatus モデル検討

OrderStatus(命令状態)モデル

またまた忘れてた。

行軍解決に伴う、成功したのか失敗したのか、支援や輸送が成立したのか、撃退されたか等々の状態を表す属性が抜けていた。

OrderStatus への参照として Order に追加しなければ。

f:id:asagix:20130828103345p:plain:w200

Order モデルの属性

  • player_id: 「誰が指示した命令か」を特定するための参照。
  • unit_id: 「どの卓の何ターン目のどの軍への命令か」を特定するための参照。
  • destination_id: 「どこへ移動するか」を示す Province への参照。
  • viaconvoy: 海路利用を宣言する場合は true
  • target_id: 「どの命令を」支援あるいは輸送するかを示す Order への参照。
  • sample: 支援または輸送命令の target に設定される複製命令なら true
  • status_id: 命令の処理状態を示す StatusOrder への参照。←New!
  • type: 単一テーブル継承用の属性。

「撃退された」は命令の状態ではないが、命令された軍が撃退されれば命令は失敗するので、「撃退されたので失敗した」という状態として扱うのが都合が良い。行軍解決処理の実装段階で再検討することにはなるが、ひとまずは前例を踏襲する。

ステータスの洗い出し

MOE2 で使用しているステータスを流用する。

  • UNEXECUTED: 未処理
  • SUCCESS: 成功
  • FAILURE: 失敗
  • STANDOFF: スタンドオフ
  • CUT: 支援のカット
  • DISLODGED: 敗退
  • INVALID: 支援または輸送の命令不成立

今回必要になるかは不明だが、内部処理で使用している中間状態もある。

  • RESERVED: 一時保留

撤退フェイズの撤退命令を Order の派生クラスにするならこれらも必要になりそう。

  • DISBANDED: 解隊
  • CONFLICT: 撤退先の競合(解隊)

どうでもいいところでは、DISBANDED の日本語の呼称を解隊にするか解体にするかで未だに悩んでいる。

成否の評価基準

「維持支援は成功した(成立し、カットされなかった)けど、支援対象の軍が撃退された」とか「移動支援は成功したけど、結果として支援対象の軍が移動に失敗した」とか「輸送命令は成立したけど、別の海軍が撃退されて輸送経路が途中で寸断された」みたいな場合に、支援命令と輸送命令のステータスは成功とするべきか失敗とするべきかも悩む。

内部的にステータスを区別しておいて先送りしてしまうのもありかもしれない。その場合は「ビューでどのように表示するか」の問題になるので、モデルとしては悩みから解放される。ある程度先読みしてステータスを定義しておく必要はあるけど。

  • SATISFIED: 支援または輸送の命令成立

SUCCESS の前段階、INVALID とは対になる状態。これを追加すれば足りるだろうか。

ややこしいステータス

支援命令と輸送命令にステータスとして SATISFIED(成立)が導入される場合、支援対象あるいは輸送対象が維持または移動に成功して初めて SUCCESS(成功)となる。

この時「支援命令への支援」は「支援命令への維持支援」なので支援対象がカットされるかどうかは関係ないということでよろしいか。

「輸送命令を受けてて撃退された海軍だけど、輸送対象は別ルートで移動に成功した」?

知るか。お前は DISLODGED(敗退)だ。

「他国の陸軍を輸送するつもりだったが、輸送対象は陸路で移動した」?

輸送される側が海路移動宣言必須の MOE2 では無縁だった問題だな。とりあえず海路が複数ある場合にどこを通ったかは問題ではないのと同じで SUCCESS でいいんじゃね?

ていうか、支援と輸送は SATISFIED までで十分な気がしてきた。

OrderStatus(命令状態)モデル

モデルの構造自体は単純で良いだろう。

OrderStatus の属性

  • code: ユニークなステータスコード。
  • status: ステータスを示す文字列。

素直に考えれば Order#status 属性の初期値として UNEXECUTED(未処理)への参照が設定されるべきだが、これは DB のデフォルト値では指定できない。

全ての ActiveRecord のインスタンスには固有の id があるのでやってできないことはないが、id に任意の固定値を期待するのは正しくないように思えるのでやらない。

Orderbefore_save コールバックで設定するにしても*1、同じ理由から id は使えないので代替のユニークな固定値が必要になる。それが code というわけだ。

db/seeds.rb ですべてのステータスを登録しておき、OrderStatus クラスで UNEXECUTED = OrderStatus.where(code:0).first のように定数定義しておけば、OrderStatus::定数 で任意の命令ステータスオブジェクトが取得できる。万歳。

*1:after_initialize などオブジェクト生成時に初期化しようとすると、クエリ実行時にヒットした全レコードのインスタンスを生成してしまう find 系メソッドとの相性がよろしくないらしい。