| ① |
観戦者 S:ロビーで部屋IDを入力し「観戦する」を押す。プレイヤー A,B,C,D:部屋で待機または「ゲーム開始」を押す。 |
(S が送信するまでサーバー側の変化なし) |
S:ロビー(部屋一覧・部屋ID入力欄・「観戦する」ボタン)。A,B,C,D:部屋画面(参加者 4人・ゲーム開始ボタン)。 |
| ② |
S:「観戦する」送信済み。A:ゲーム開始押下で全員ゲーム画面へ。 |
spectate_room 受信→部屋が存在し参加可能なら spectators に S を追加、socket を room に join。spectate_room_ok で room_status, revision, players, spectators_count, snapshot? を返却。競合時も最新の room_status を返す。room_updated を必ず送る(観戦者数含む)。 |
S:room_status で分岐。waiting→部屋画面(参加者・観戦者数)。playing→snapshot で盤面初期描画。rematch_vote→終了・待機表示。spectate_room_ok 受信前に画面確定しない。A,B,C,D:ゲーム画面 or 部屋。 |
| ③ |
S:カードをクリックしない(不可)。「観戦をやめる」のみ可能。A,B,C,D:通常プレイ(2枚選択・ペア取得・ターン終了)。 |
状態更新系イベントは revision 付与。room_updated, game_started, pair_taken, turn_ended, tribe_effect, cards_revealed, turn_timeout, player_eliminated を room 宛に emit → S も受信。spectator の flip_cards / start_game 等はサーバーで reject(action_rejected)。 |
S:プレイヤーと同じ盤面・ポイント・「○のターン」・ターンタイマー・脱落状態。カードはクリック不可・「観戦中」ラベル・「観戦をやめる」ボタン。A,B,C,D:通常のゲーム画面。 |
| ④ |
全員:ゲーム終了の結果を見る。S:勝者・ポイントを確認し、続けて観戦するかロビーに戻るか選ぶ準備。 |
game_ended を room 宛に emit(revision, points, pairs, winner_indices, next_phase: "rematch_vote")。観戦者専用イベントは作らず、同一 game_ended を S も受信。クライアントが role で UI 分岐。 |
S:終了オーバーレイ(勝者名・各プレイヤーのポイント・ペア数)。「観戦を続ける」「ロビーに戻る」ボタン。A,B,C,D:終了オーバーレイ「再戦しますか?」(はい・いいえ)。 |
| ⑤ |
S:「観戦を続ける」→ rematch_status_updated で再戦準備中・カウント表示。「ロビーに戻る」→ leave_room 送信。A,B,C,D:はい/いいえ選択。 |
rematch_status_updated(ready_count, countdown_sec 等) を spectator も受信。S が leave_room 送信→spectators から削除、leave_room_ok 返却。room 内に room_updated を必ず送る(観戦者数含む)。 |
S:「再戦準備中」・ready 人数・countdown。投票 UI は出さない。ロビーに戻る選択後はロビー画面。A,B,C,D:再戦カウントダウン or 「参加者を待っています…」。 |
| ⑥〜⑦ |
S:ロビーで他部屋を観戦したり、自分で部屋を作成・参加できる。A,B,C,D:再戦 or 人数不足でロビーへ。 |
disconnect 時は spectators から削除し room_updated を送る。観戦状態は自動復元しない。player が 0 人になったら room を closed とし、観戦者全員に room_closed(reason: "no_players") を送りロビーへ。再戦開始時は game_started を room 全体に送る(観戦者も受信)。 |
S:ロビー。room_closed 受信時は「部屋が終了しました」表示後にロビーへ。A,B,C,D:再戦でゲーム再開 or ロビー。 |