125 lines
3.7 KiB
Ruby
125 lines
3.7 KiB
Ruby
class Turn < ApplicationRecord
|
|
belongs_to :game
|
|
|
|
# 特定の国の実行可能な命令を取得
|
|
# 例: 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
|