[[目次へもどる>PuyoPuyo]]
* フェーズハンドラの改良 [#t705b02b]
#contents

さて,経緯はいろいろあるのだが
現状のフェーズ遷移のハンドラの改良を行う.
現状では
- 開始,終了ハンドラは開始するフェーズおよび終了するフェーズのみが呼び出すメソッドの条件として使える
- 逆に,遷移条件ハンドラは遷移元,遷移先のフェーズの二つを常に条件に指定する必要がある.

これらは次のような場合に不便である.
- ある特定のフェーズからの遷移である場合のみに開始ハンドラを設定したい
- ある特定のフェーズへの遷移である場合のみに終了ハンドラを設定したい((これはあまりないと思うが))
- 遷移条件はほとんど遷移元の状態のみで決まり,遷移先によって条件は不変なのに,遷移先ごとにハンドラを設定しないとならない

これらを解決するために,3つのハンドラの追加様式を統合し,次のようにする.
- ハンドラの追加メソッドの引数の形式は次の2パターン
++ phase1, phase2, method~
phase1,phase2は開始ハンドラの場合は順に開始するフェーズ,遷移元のフェーズ,終了ハンドラは終了するフェーズ,遷移先のフェーズ,遷移条件ハンドラは遷移元のフェーズ,遷移先のフェーズを表す.
++ phase1, method~
上の3引数と異なり,phase1のみを条件とし,phase2は考慮しない.
- 3引数のハンドラを設定すると,2引数で設定したハンドラのより詳細な条件を指定したバージョンとなる.
- 3引数のハンドラの条件マッチが優先される.

つまり,例えば
#sh(ruby){{
add_start_handler(:phase1, method)
}}
を指定すると,元のフェーズにかかわらず:phase1に遷移した時,methodが実行される.
ここに,
#sh(ruby){{
add_start_handler(:phase1, :phase2, method2)
}}
を追加すると,元のフェーズが:phase2で,:phase1に遷移した時,method2が実行され,
それ以外のフェーズから:phase1に遷移したときはmethodが実行される.

#sh(ruby){{
class Phase
  def add_handler(handler, args)
    case args.size
    when 2
      phase, method = args
      handler[phase] = method
    when 3 # don't care of old/new phase
      phase1, phase2, method = args
      handler[[phase1,phase2]] = method
    else
      raise(ArgumentError, "wrong number of arguments (#{args.size} for 2 or 3)")
    end
  end

  def add_start_handler(*args)
    # phase, method # don't care of oldphase
    # phase, oldphase, method
    add_handler(@start_handler, args)
  end
  def add_end_handler(*args)
    # phase, method # don't care of nextphase
    # phase, nextphase, method
    add_handler(@end_handler, args)
  end
  def add_condition_handler(*args)
    # oldphase, method # don't care of nextphase
    # oldphase, nextphase, method
    add_handler(@trans_condition_handler, args)
  end

  def get_handler(handler, phase1, phase2)
    method = handler[[phase1, phase2]]
    method = handler[phase1] unless method
    return method
  end

  def trans_condition_check
    cond = get_handler(@trans_condition_handler, @phase, @next_phase)
    return if cond && !cond.call
    old = @phase
    @phase = @next_phase
    @next_phase = nil
    # start handler
    method = get_handler(@start_handler, @phase, old)
    method.call if method
  end

  def change(phase)
    # end handler
    method = get_handler(@end_handler, @phase, phase)
    method.call if method
    # set next_phase
    @next_phase = phase
    # trans condition check
    trans_condition_check unless wait?
  end
end
}}


トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS