← トップページに戻る

不具合の修正
— 異世界衰弱・ログ・管理画面

「異世界衰弱」のマルチプレイとログまわりで、ロビー人数の表示ずれ再戦カウントダウンの開始・停止の仕様、本番環境でのログ保存・管理画面からの確認ができるようにする修正を行いました。テーマは「不具合の修正」として、実施した内容をまとめます。

1. 修正・対応した内容の一覧

  • 部屋まわりのログ強化list_rooms の返却内容(部屋一覧の要約)をログに記録。部屋状態更新時(参加・退出・再戦辞退)に room_updated をログ出力。
  • 再戦で「いいえ」/未選択の人の扱い — ロビー人数表示が正しく更新されることを確認。カウントダウン終了時に「いいえ/未選択」の人を Socket の部屋から leave_room するよう修正(表示と実態の一致)。
  • 再戦カウントダウンの仕様変更 — カウント開始を「終了ポップアップ表示時」に統一。「はい」を押してもカウントを止めず・リセットしない(30→0 のまま進行)。サーバーが rematch_pendingcountdown_ends_at を含めるよう変更。
  • ゲームログの網羅 — サーバー側に rematch_decliners_leftrematch_show_room_sentrematch_timeout_all_leftcards_revealedturn_timer_reset などを追加。クライアント側に再戦ポップアップ表示・タイムアウト/辞退受信時のログを追加。
  • WEB公開時もログを記録・毎日17時にクリア — 本番でも同じログファイルに記録。毎日17時(サーバーローカル時刻)にログをクリアするバックグラウンドスレッドを追加。deploy_remote.sh でログ用ディレクトリ作成、DEPLOY.md に説明を追記。
  • 管理画面に「異世界衰弱ログ」タブを追加 — 管理用ログイン(Basic認証)のみアクセス可能な /share/admin に「異世界衰弱ログ」タブを追加。タブクリックで main に fantasy_debug.log の内容(直近約200万文字)を表示。

2. ロビー人数表示まわり

「再戦しますか?」で「いいえ」を選んだ人や、何も押さなかった人(未選択=いいえ扱い)がロビーにいるあいだ、部屋一覧の「○/4人」が正しく減るかが課題でした。ログの参照元はサーバーの room["players"] のみであり、退出時に _fantasy_emit_room_list_updated() を呼んでいるため、表示は正しく更新されることを確認しました。あわせて、カウントダウン終了時に「いいえ/未選択」の人を Socket の部屋から leave_room する処理を追加し、部屋所属と表示の整合をとりました。

3. 再戦カウントダウン

もともとは「はい」または「いいえ」を押してからカウントが動き、押した人によってはカウントが止まっているように見える状態でした。修正後は次のとおりです。

  • 開始 — ゲーム終了ポップアップ「再戦しますか?」が表示された時点でカウント開始。サーバーが rematch_pendingcountdown_ends_at を付与し、クライアントはそれを使って表示。
  • 「はい」を押したとき — カウントは止めず・リセットしない。メッセージを「参加しました。」に変えるだけ。30→0 まで常にカウントダウン表示。
  • 「いいえ」「参加を取り消す」 — 従来どおりロビーに戻し、その人用のカウント表示は終了。

4. ログの保存と管理画面での確認

ログは test/game-card-fantasybattle/fantasy_debug.log に追記されます。ローカル・本番どちらでも同じパス(app.py 実体基準)で記録されます。毎日17時ちょうど(サーバーのローカル時刻)にファイルをクリアするバックグラウンドスレッドを起動しており、日本時間で運用する場合はサーバーのタイムゾーンを JST にしておきます。

管理者は、管理用ログイン(Basic認証)後に /share/admin を開き、右端の「異世界衰弱ログ」タブをクリックすると、main エリアに上記ログの内容(直近約200万文字)が表示されます。誰でも見られるURLにはしておらず、管理用ログインだけがアクセスできる形にしています。

5. 関連ドキュメント・画面

  • フローチャート(1回目→3回目ゲーム・4人→2人→1人再戦希望)… fantasy_flowchart_1st_to_3rd.html機能別フローチャート一覧からも参照可)
  • デプロイ後のログ・17時クリアの説明 … DEPLOY.md の「5-4. ゲーム(異世界衰弱)のログ」
  • サーバー時刻の確認 … date / timedatectl。ログの末尾確認 … tail -n 50 ~/make-001/test/game-card-fantasybattle/fantasy_debug.log

6. 追記(追加履歴)

【追記】2026-03-20(ゲーム終了後フローの実地デバッグと修正)

  • 対象とした確認フローtest/game-card-fantasybattle/docs/game-end-to-lobby-flowchart.html と関連仕様(GAME-END-SPEC.md)を基準に、2人戦+観戦者、4人戦+観戦者の終了後遷移を実機で再検証。特に「再戦不成立なら部屋を閉じ、ロビーへ戻す」意図(部屋上限10の圧迫防止)に沿うかを確認した。
  • 実際に起きていた不具合 — 4人戦で A が「いいえ」、B/C が「はい」のケースで、30秒後に B/C の再戦が始まらず「対戦相手がいませんでした」に遷移することがあった。表面上は再戦判定不具合に見えるが、ログで背景タスク内の離脱処理例外が原因と判明。
  • 根本原因 — 背景タスクから leave_room(request context 前提)を呼び、Working outside of request context が発生。カウントダウン処理が途中で落ちるため、game_started が出ず、最終的に不成立/期限切れ側の遷移になっていた。
  • 修正内容 — 背景タスク内の離脱処理を socketio.server.leave_room(sid, room_id, namespace="/") に置換。あわせて「再戦可能人数が2人未満になった時点」で rematch_timeout を即時通知する判定を整理し、2人戦では不要な30秒待機が発生しないようにした。
  • 確認できた最終挙動(期待仕様) — 4人戦では B/C 再戦が成立して観戦継続、未参加 D は再戦開始時点でロビーへ移動。続く2人戦で片方が「いいえ」の場合は、残りプレイヤー+観戦者が即「対戦相手がいませんでした」表示になり、60秒放置で自動ロビー遷移することをログと画面で確認した。

【追記】2026-03-18(観戦・再戦・不成立・表示崩れ・スキル挙動の調整)

  • デプロイアプリが動かない(PowerShell のパースエラー) — さくらサーバーにアップロードする「デプロイ」アプリからバンドル作成を実行したところ、build_deploy_bundle.ps1 が PowerShell の構文エラーで停止し、デプロイが実行できない状態になった。原因は「パイプ構文の書き方」と「Windows 側での文字コード解釈」の組み合わせで、具体的には次のような経緯だった。
    • 事象(どのファイルが、どうなったか)build_deploy_bundle.ps1Get-ChildItem ... | Where-Object ... | ForEach-Object ... のようなパイプ処理をしていた部分が、改行位置やコメントの影響で崩れ、EmptyPipeElement / UnexpectedToken 系のエラーとして解釈されて失敗した。
    • 原因(なぜそうなったか) — PowerShell は「パイプ記号 | の直前・直後の改行」や、保存時の文字コードの差で、スクリプト全体のトークン化が変わることがある。とくに日本語コメント等が混ざると、環境によって UTF-8 を想定どおり読めず、パースエラーの引き金になりやすい(同じ見た目でも別マシン/別設定で再発しうる)。
    • 対処(どう直したか) — 不安定になりやすいパイプ処理をやめ、foreach で明示的に回す形に変更し、コメントも ASCII のみで書く方針に統一した。これにより PowerShell の解釈差で壊れにくくなり、デプロイが再び実行できる状態になった。
    • 追加対応(デプロイ対象の拡張) — 「HTML ファイルは毎回指定せずデプロイ対象にしたい」要件に合わせ、test/game-card-fantasybattle/docs/ 配下の .html/.htm を再帰的にバンドルへ含める処理を build_deploy_bundle.ps1 に追加した(相対パスを維持してコピー)。
    • 記録 — 経緯と対処の詳細は docs/deploy-app-fixes.md にも整理した(どのファイルを直したか/なぜ再発したか/再発時のチェック項目)。
  • 観戦者数表示の不整合 — 入室直後に「観戦者0人」のままになるケースに対応。join_room の応答に spectator_count を含め、クライアントで即時反映するようにした(早着 room_updated が先に届いても表示が落ちないよう currentRoomId の設定タイミングも調整)。
  • 観戦者がゲーム開始時に部屋に取り残されるcheck_room がプレイヤーのみ判定して観戦者を「期限切れ」扱いしていた問題を修正し、観戦者も部屋在籍として扱うようにした。
  • 切断起因のゲーム終了(不成立)表示 — 「再戦しますか?」やカウントダウンを出さず、切断の説明+「ロビーに戻る」のみに統一。後から rematch_* が届いても画面が切り替わらないよう、切断時は再戦UIを抑制するフラグ(suppressRematchUI)で固定するようにした。
  • 切断終了時はランキングに加算しない — 切断起因の終了は不成立扱いとし、ランキング(累積ポイント)へ反映しないようにした。
  • 観戦者のゲーム終了UI — 観戦者はポイント/順位表示を出さない。正常終了時は「このまま待てばプレイヤーの再戦が決まり次第、次の試合も続けて観戦できます」の案内文を表示するようにした。
  • 再戦フローの即時確定(待ち続け防止) — 誰かが「いいえ」または退出してプレイヤーが2人未満になった時点で、残りのプレイヤー・観戦者へ rematch_timeout を即時通知し、「対戦相手がいませんでした」へ遷移するようにした。観戦者も再戦の結果(成立/不成立)に追従して表示が切り替わる(操作は不可のまま)ように調整。
  • 精霊の加護(追加で2回連続でめくれる) — ノーペア時に次の人へ回ってしまう問題を修正し、追加分は同一プレイヤーが続けてめくれるようにした。
  • レイアウト崩れの修正 — PCで誤って「最大化」判定が走り、カード表示やチャット領域が崩れる問題に対応。最大化は「タッチ端末+モバイル幅」のみに限定し、また「観戦者○人」の折り返しでヘッダー高さが変動しないよう1行固定にした。
  • 盤面の縦余白の削減 — グリッドの計算結果に合わせてゲームエリアの縦幅を詰め、無駄な余白を減らしてスマートに見えるよう調整。
  • 闇の力(悪魔)の演出中の操作ロック — 闇の力の消滅演出中に「続けてめくれない」体感になりやすい点を改善。消滅対象カードのみクリック不可にして、発動者が続けてめくれる体感を損ねないようにした(観戦者入室タイミングと重なった際の誤認も減らす)。
  • ゲストのニックネーム保持(編集可+開始時重複チェック) — ゲストのニックネームは localStorage に保存して1時間保持しつつ、入力欄は自由に編集可能にした。部屋作成/参加/観戦/テスト開始などのゲーム開始操作の直前に入力値を自動保存し、同時にサーバ側で「既に使われているニックネーム」かどうかをチェックして重複を防ぐ(同一人物がA→B→Aに戻すのは、Aが他で使われていなければOK)。
  • ニックネーム重複アラートが連続で出る問題(テスト後・ページ移動後) — テストモードやページ移動の直後に「このニックネームは既に使われています…」が出続けて操作できなくなるケースがあった。原因は (1) test_ 部屋が残って名前が「使用中」扱いで固定される、(2) ページ移動やブラウザの bfcache 等で WebSocket の切断が遅れ「ゴースト在室」が残る、の複合だった。対処として app.pytest_ 部屋を切断時に即削除し、また「接続中 sid のみ」を使用中判定に採用。クライアント(templates/game_fantasybattle.html)でも pagehide/beforeunloadsocket.disconnect() を呼び、ページ離脱時に確実に切断するようにした。さらに、弾かれた場合に *_rejected で原因(登録済み衝突か/どの部屋で使用中か)が追えるよう、拒否理由の詳細ログも追加した。

【追記】2026-03-17(ロビーのニックネーム保持)

  • ゲストのニックネームを1時間保持 — ロビーで入力したニックネームを、未ログイン(ゲスト)の場合はブラウザの localStorage に保存し、60 * 60 * 1000(1時間)の TTL 内であれば次回アクセス時に自動復元するようにした。キーは fantasy_guest_nickname_v1。期限切れの場合は自動で削除。

【追記】2026-03-15(ドキュメント配信・機能別フローチャート記事・メニュー表記・観戦v1・私の意見スタイル)

  • ドキュメント配信ルートの追加 — app.py に /test/game-card-fantasybattle/docs/<path:filename> を追加。send_from_directorytest/game-card-fantasybattle/docs を配信。HTML 等の拡張子のみ許可し、.. 禁止・拡張子チェックでパス対策。フローチャートをブラウザで直接参照可能にした。
  • 記事「異世界衰弱(機能別フローチャート)」の新設/fantasy-flowcharts で表示。再戦フロー・観戦モード(初版・v1)のフローチャートへのリンクをまとめた記事を追加。観戦モードは Cursor 生成→不安要素のリスト化→ChatGPT 5.4 thinking で v1 改善の経緯も記載(私の意見は .author-opinion でスタイル)。
  • メニュー・ヘッダー表記の統一 — 「不具合の修正(異世界衰弱)」を「異世界衰弱(不具合の修正)」に変更。サイドバー・サイト記事ナビ・当ページ(/bugfix-fantasy)のヘッダーを統一。
  • 関連ドキュメントのリンク化 — 5. 関連ドキュメントのフローチャートを、docs ルートの URL と「機能別フローチャート一覧」記事へのリンクに更新(従来はパス文字列のみ)。
  • 観戦モード v1 フローチャートの整備spectator-mode-flowchart.html(初版)を Cursor が生成。不安要素を SPECTATOR-FLOWCHART-CONCERNS.md にリスト。ChatGPT 5.4 thinking に確認させて spectator-mode-flowchart_v1.html として改善版を作成。v1 を元に実装を進める方針。
  • 共通 CSS「私の意見」スタイルmain-layout.css.author-opinion を追加。オレンジ文字・薄いグレー背景・枠・角丸・余白。記事内の制作者の個人的見解に適用。

【追記】2026-03-15(接続表示・先読み・スキル表示・ヘッダー・協力コメント・全画面ロビー)

  • バンドルスクリプト(実行場所に依存しない)build_deploy_bundle.ps1 のルートをスクリプトの場所($PSScriptRoot)優先+カレントの親・プロジェクトルートのフォールバックで決定。test や make-001 直下のどちらから実行しても sounds/videos がコピーされるように修正。DEPLOY-CHECKLIST.md を「どこから実行してもよい」に更新。
  • 接続中表示(赤・1〜10ドット) — 「接続中」〜「接続中..........」を赤文字で表示。ドットは 1→10 のループ(400ms)。初期表示も style="color: #dc2626" で赤にし、一瞬黒にならないようにした。
  • 接続中の先読み(画像・効果音) — 接続中に CARD_IMAGES_BASE64 の画像と効果音6本を先読み(動画は対象外)。ソケット接続と先読みの両方が終わってから「接続済み」を緑で表示。30秒タイムアウトあり。
  • スキル・時間切れ表示の中央オーバーレイ化 — プレイヤー名の下ではなく画面中央のオーバーレイ(.game-effect-overlay)に表示。最前面(z-index: 10000)、半透明背景で文字を視認しやすく。表示時間を3秒に統一。「時間切れ」のときだけ文字サイズ2倍。
  • ゲームヘッダー1行化・全画面ボタン右端 — ヘッダーを1行に(ポイント・ターンタイマー・プレイヤー名・全画面ボタン)。全画面ボタンをその行の一番右に配置。
  • 協力スキル表示に「(ポイント2倍)」を追加 — サーバー(app.py)で effect_comment を「協力スキル発動!(ポイント2倍)」に変更。クライアントで「協力スキル発動」のみ受信した場合も「(ポイント2倍)」を付けて表示するフォールバックを追加。
  • 全画面のままロビーに戻りクリックが効かなくなる — 事象:全画面でプレイ中に放置すると「全画面表示のロビー」になり、どこをクリックしても反応しない。原因:showLobby() で表示だけロビーに切り替わるが全画面の対象が #game-view のままのため、ロビー(兄弟要素)にクリックが届かない。対応:showLobby() の先頭で全画面中なら document.exitFullscreen 等を実行。詳細は test/game-card-fantasybattle/docs/FULLSCREEN-LOBBY-BUG.md

【追記】2026-03-14(盤面グリッド・c1動画・ペア演出)

  • グリッド不具合(turn_ended で 2 行になる) — 闇の力で 3 枚消滅したあと、その後の turn_endedscheduleUpdateGridLayout が呼ばれグリッドが 3 行→2 行になっていた。from === 'turn_ended' かつ gameState.vanished.length > 0 のときは scheduleUpdateGridLayout() を呼ばず、代わりに CLIENT_turn_ended_layout_kept をログ出力するよう修正。web ログで turn_ended_layout_kept が出ていればグリッド維持。
  • c1 動画オーバーレイのずれ — 上記グリッド不具合の二次現象。turn_ended で 2 行になった状態で c1 ペアをするとオーバーレイ位置がずれる。1 の修正でグリッドを 3 行に保てば c1 も正しい位置で表示される。
  • c1 動画の縦横比・表示比率 — 動画を「幅 1 : 縦 0.9」で表示(aspect-ratio: 1/0.9)。コンテナは c1 画像と同じ imgW×imgH。スキル・協力で大中小(2.2/1.8/1.8)になる。
  • ペア演出で優位でない場合を少し小さく — 協力時など優位なしのときの scale を 2,2 から 1.8, 1.8 に変更。優位ありのときは従来どおり有利 2.2・不利 1.8。
  • ペア演出で大きいカードの上下が切れる — 優位で scale 2.2 表示したとき、親の overflow: hidden で上下が切れていた。オーバーレイ表示中だけ親の overflowvisible にし、アニメ終了時に元に戻す。.pair-anim-overlayoverflow: visible を明示。
  • ドキュメント・ログの整理LOG-AND-MULTITAB.mdturn_ended_layout_kept と c1 ずれの一因を追記。C1-VIDEO-DISPLAY-FIX.md に動画コンテナ・幅1:縦0.9 を簡潔に記載。
  • c1 動画は全画面表示のときのみ — 全画面表示のときのみ動画を表示。最大化・通常表示では動画を出さない(画像のみ)。分岐(全画面:inset_full、それ以外:width100_padding90)は維持。ログは c1_video_skipreason: 'not_fullscreen'

【追記】2026-03-14

  • ゲーム終了オーバーレイ — 敗者に「ゲーム終了」→「YOU LOSE」に変更しクラス you-lost(赤字)を付与。再戦表示で「参加者を待っています…」・タイマーの表示を明示リセットし、勝者・敗者で差が出ないようにした。
  • 強制終了メッセージ — ブラウザ alert() を廃止。対局中の強制終了時はゲーム画面上のオーバーレイで「対戦相手が退室したのでゲームは強制終了となります。」+「部屋(待機画面)へ戻る」ボタンを表示。ゲーム終了後の再戦中に相手が退出した場合はアラートを出さず、残った人を部屋ではなくロビーへ遷移(rematch_pending の部屋は一覧に出ず誰も参加できないため)。
  • 再戦で「はい」を選んだ側 — 相手が抜けたときの表示を1段階に統一。最初のオーバーレイ(対戦相手が退室したので~)は出さず、カウント終了で「再戦希望者がいませんでした」+「ロビーに戻る」のみ表示。
  • ログ・送信の整合性rematch_decline 発火時の room_updated で、ログに state='rematch_pending' を出しているのに payload に state が含まれていなかった不整合を修正。emit に "state": "rematch_pending" を追加。
  • 協力ペアでゲーム終了のとき — 最後の1ペアで場にペアが残らなくなる場合は種族効果をスキップするが、協力の場合は「協力スキル発動!」のコメントだけは表示するよう修正(effect_commentskip_tribe_effect の有無にかかわらず設定)。
  • 起動・プロファイルまわりrun_here.bat を作成済み。1つ目・2つ目で別ブラウザプロファイル(Yahoo/Docomo)を使い、/test/game-card-fantasybattle/profile-check(プロファイル確認ページ)を先に開いてからゲーム画面へ誘導する流れ。プロファイル作成・起動時の待ち(10秒等)で時間がかかる運用。
  • スマホで音が鳴らない問題の修正 — iOS / モバイルブラウザで、ユーザー操作前は音が鳴らせない制限に引っかかっていた。touchstart / click などのユーザーイベントハンドラ内で一度だけ無音再生を行い、Web Audio の AudioContext をアンロックする方式に変更。参考にした記事: iOSでのオーディオ再生制限の解除方法いろいろ

← 立ち上げストーリー
← プログラム構築の記録
← デプロイの記録
← ボタン1つデプロイの記録
← デプロイでまたハマった話
← ログイン設定の記録
← 改善記録
← ファイル紹介の使い方
← OGP・SEOの記録
← 統合ログインの設計・経緯
← Search Console・サイトマップ
← 環境変数・.env の管理
← Git 入門・インストール
← インストール後に Git で行う設定
← カード神経衰弱の記録
← 異世界シューティングの記録
← 異世界シューティングの難易度
← 異世界戦記(全画面・迷路レイアウト)の記録
← 複数人でのゲーム進行
← 異世界衰弱(機能別フローチャート)
← 異世界ポイントの活用について
← 異世界ポイント市場の実装記録