Files
kondiplo_front/app/controllers/boards_controller.rb

174 lines
7.0 KiB
Ruby
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
class BoardsController < ApplicationController
include BoardAccessible
before_action :require_login
before_action :set_game
before_action :set_board, only: [ :show, :toggle_public ]
def index
# 参加中の掲示板(共通掲示板含む)を取得
# ゲーム終了後は履歴モードとして、過去に参加していた掲示板もすべて表示
@current_participant = @game.participants.find_by(user: current_user)
# マップ表示用:各国がどの掲示板(交渉)を持っているかのデータを作成
# { "FRANCE" => ["GERMANY", "ENGLAND"], ... } のような形式でビューに渡す
@diplomacy_matrix = build_diplomacy_matrix
if @game.status == "finished"
# 履歴モード:かつて参加していた掲示板をすべて表示
@boards = @game.boards.includes(:participants, :board_posts, :board_memberships)
.select { |b| b.member?(@current_participant) || b.global? }
.sort_by { |b| [ b.global? ? 0 : 1, b.created_at ] }
else
return redirect_to game_path(@game), alert: "参加者ではないためアクセスできません" unless @current_participant
if @game.status == "power_selection"
# 国選択フェーズ:共通掲示板のみ表示
@boards = @game.boards.global.includes(:participants, :board_posts, :board_memberships).to_a
else
# 進行中参加中の掲示板のみeager load で N+1 防止)
@boards = @current_participant.boards.includes(:participants, :board_posts, :board_memberships).order(created_at: :desc)
# 共通掲示板のフォールバック
global_board = @game.boards.global.first
if global_board && !@boards.include?(global_board)
@boards = [ global_board ] + @boards
end
@boards = @boards.sort_by { |b| b.global? ? 0 : 1 }
end
end
end
def show
@current_participant = @game.participants.find_by(user: current_user)
# アクセス制御
access_allowed = false
if @board.global?
# 共通掲示板はゲーム参加者なら誰でもアクセス可能
# 未読管理のためにメンバーシップがない場合は作成する
access_allowed = true
unless @board.board_memberships.exists?(participant: @current_participant)
@board.board_memberships.create(participant: @current_participant, joined_at: Time.current)
end
elsif @board.member?(@current_participant)
access_allowed = true
elsif @game.status == "finished"
# ゲーム終了後は、元メンバーならアクセス可能(共通掲示板は上記でカバー済み)
is_past_member = @board.board_memberships.exists?(participant: @current_participant)
access_allowed = is_past_member
elsif @board.is_public?
# 公開掲示板は誰でも閲覧可能
access_allowed = true
end
unless access_allowed
return redirect_to game_boards_path(@game), alert: "権限がありません"
end
# 既読更新
if @current_participant && @board.active_memberships.exists?(participant: @current_participant)
last_post = @board.board_posts.last
if last_post
membership = @board.board_memberships.find_by(participant: @current_participant)
membership.mark_read!(last_post.id)
end
end
@posts = @board.board_posts.includes(participant: :user).order(created_at: :desc)
@proposals = @board.board_proposals.includes(:proposer).order(created_at: :desc)
@new_post = BoardPost.new
@new_proposal = BoardProposal.new
@active_members = @board.active_memberships.includes(participant: :user).map(&:participant)
# メンバー追加用:招待可能なプレイヤー一覧
if @board.negotiation? && !@board.history_mode?
existing_member_ids = @board.board_memberships.where(left_at: nil).pluck(:participant_id)
@candidates = @game.participants.where.not(id: existing_member_ids).where.not(power: nil)
end
end
def new
@board = Board.new(board_type: "negotiation")
@current_participant = @game.participants.find_by(user: current_user)
# 自分以外の参加者一覧
@participants = @game.participants.where.not(id: @current_participant.id).where.not(power: nil)
end
def create
@current_participant = @game.participants.find_by(user: current_user)
# トランザクションで掲示板作成とメンバー追加を一括実行
ActiveRecord::Base.transaction do
@board = @game.boards.new(board_params)
@board.board_type = "negotiation"
@board.created_by_participant_id = @current_participant.id
if @board.save
# 作成者をメンバーに追加
@board.board_memberships.create!(participant: @current_participant, joined_at: Time.current)
# 招待されたメンバーを追加
if params[:invited_participant_ids].present?
params[:invited_participant_ids].each do |pid|
@board.board_memberships.create!(participant_id: pid, joined_at: Time.current)
end
end
redirect_to game_board_path(@game, @board), notice: "交渉用掲示板を作成しました"
else
@participants = @game.participants.where.not(id: @current_participant.id).where.not(power: nil)
render :new, status: :unprocessable_entity
end
end
rescue ActiveRecord::RecordInvalid
@participants = @game.participants.where.not(id: @current_participant.id).where.not(power: nil)
render :new, status: :unprocessable_entity
end
def toggle_public
# 公開宣言機能(追加提案)
@current_participant = @game.participants.find_by(user: current_user)
unless @board.member?(@current_participant)
return redirect_to game_board_path(@game, @board), alert: "権限がありません"
end
@board.update(is_public: !@board.is_public)
status = @board.is_public ? "公開" : "非公開"
redirect_to game_board_path(@game, @board), notice: "掲示板を#{status}に設定しました"
end
private
def board_params
params.fetch(:board, {}).permit(:is_public)
end
def build_diplomacy_matrix
powers = @game.participants.where.not(power: nil).pluck(:power)
matrix = {}
powers.each { |p| matrix[p] = [] }
# 自分が参加している掲示板・公開された掲示板の関係を表示
visible_boards = @game.boards.negotiation.includes(:participants, :board_memberships)
visible_boards.each do |board|
# アクセス権チェック(簡易)
is_member = board.board_memberships.exists?(participant: @current_participant, left_at: nil)
next unless is_member || board.is_public || @game.status == "finished"
# メンバー間のリンクを作成
members = board.participants.pluck(:power)
members.each do |p1|
members.each do |p2|
next if p1 == p2
matrix[p1] ||= []
matrix[p1] << p2 unless matrix[p1].include?(p2)
end
end
end
matrix
end
end