138 lines
4.2 KiB
Ruby
138 lines
4.2 KiB
Ruby
class Turn < ApplicationRecord
|
||
belongs_to :game
|
||
|
||
SEASON_MAP = { "S" => "春", "F" => "秋", "W" => "冬" }.freeze
|
||
PHASE_TYPE_MAP = { "M" => "移動", "R" => "撤退", "A" => "調整" }.freeze
|
||
|
||
# フェーズコードを日本語表示に変換(例: "S1901M" → "1901年 春 (移動)")
|
||
def display_phase
|
||
return nil unless phase.present? && phase.length >= 6
|
||
|
||
year = phase[1..4]
|
||
season = SEASON_MAP[phase[0]] || ""
|
||
type = PHASE_TYPE_MAP[phase[-1]] || ""
|
||
"#{year}年 #{season} (#{type})"
|
||
end
|
||
|
||
# 特定の国の実行可能な命令を取得
|
||
# 例: turn.possible_orders_for("FRANCE")
|
||
def possible_orders_for(power_name)
|
||
possible_orders&.dig("possible_orders", power_name.to_s.upcase)
|
||
end
|
||
|
||
# 特定の国の決定済み命令を取得
|
||
# 例: turn.orders_for("FRANCE")
|
||
def orders_for(power_name)
|
||
# orders は直接ハッシュを保存する場合を想定(必要に応じてネストを調整)
|
||
orders&.dig(power_name.to_s.upcase)
|
||
end
|
||
|
||
# 命令が存在するすべての国名リストを取得
|
||
def powers
|
||
possible_orders&.dig("possible_orders")&.keys || []
|
||
end
|
||
|
||
# 特定の国の命令が提出済みかチェック
|
||
def orders_submitted_for?(power_name)
|
||
orders&.key?(power_name.to_s.upcase)
|
||
end
|
||
|
||
# 未提出の国のリストを取得
|
||
def pending_powers
|
||
game.participants.where.not(power: nil).map(&:power).reject do |power|
|
||
orders_submitted_for?(power)
|
||
end
|
||
end
|
||
|
||
# 自動命令を生成(参加者がいない国用)
|
||
def generate_auto_orders_for_unassigned_powers
|
||
unassigned = game.unassigned_powers
|
||
return if unassigned.empty?
|
||
|
||
client = GameApiClient.new
|
||
current_orders = orders || {}
|
||
|
||
unassigned.each do |power|
|
||
if game.auto_order_mode == "hold"
|
||
# HOLD命令を生成
|
||
current_orders[power] = generate_hold_orders(power)
|
||
else
|
||
# ランダム命令を生成
|
||
auto_orders_response = client.api_calculate_auto_orders(game_state, power)
|
||
if auto_orders_response
|
||
# APIレスポンスから命令を抽出
|
||
# レスポンスが {"orders": [...]} の形式の場合
|
||
if auto_orders_response.is_a?(Hash) && auto_orders_response["orders"]
|
||
current_orders[power] = auto_orders_response["orders"]
|
||
elsif auto_orders_response.is_a?(Array)
|
||
current_orders[power] = auto_orders_response
|
||
else
|
||
# フォールバック: HOLD命令を使用
|
||
current_orders[power] = generate_hold_orders(power)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
update(orders: current_orders)
|
||
update(orders: current_orders)
|
||
end
|
||
|
||
# 引き分け投票
|
||
def vote_draw(power_name)
|
||
current_votes = draw_votes || []
|
||
power = power_name.to_s.upcase
|
||
unless current_votes.include?(power)
|
||
current_votes << power
|
||
update(draw_votes: current_votes)
|
||
end
|
||
end
|
||
|
||
# 引き分け投票取り消し
|
||
def revoke_draw_vote(power_name)
|
||
current_votes = draw_votes || []
|
||
power = power_name.to_s.upcase
|
||
if current_votes.include?(power)
|
||
current_votes.delete(power)
|
||
update(draw_votes: current_votes)
|
||
end
|
||
end
|
||
|
||
# 投票済みかチェック
|
||
def draw_voted?(power_name)
|
||
(draw_votes || []).include?(power_name.to_s.upcase)
|
||
end
|
||
|
||
# 全会一致で引き分けかチェック
|
||
def unanimous_draw?
|
||
# 生存している国
|
||
active_powers = powers
|
||
return false if active_powers.empty?
|
||
|
||
# プレイヤーが割り当てられている国のみを対象とする
|
||
# (未割り当ての国は投票できないため、除外する)
|
||
assigned_powers = game.participants.where.not(power: nil).pluck(:power).map(&:upcase)
|
||
|
||
# 投票権を持つ国 = 生存している かつ プレイヤーがいる
|
||
eligible_powers = active_powers.map(&:upcase) & assigned_powers
|
||
|
||
return false if eligible_powers.empty?
|
||
|
||
current_votes = draw_votes || []
|
||
eligible_powers.all? { |power| current_votes.include?(power) }
|
||
end
|
||
|
||
private
|
||
|
||
def generate_hold_orders(power)
|
||
possible = possible_orders_for(power)
|
||
return {} unless possible
|
||
|
||
hold_orders = {}
|
||
possible.each do |unit, moves|
|
||
hold_orders[unit] = [ "H" ] if moves.is_a?(Array)
|
||
end
|
||
hold_orders
|
||
end
|
||
end
|