個人編が完成した後、「チーム編を作りたい」という要望が出た。複数人がチームとして1社を経営する——CEO・CFO・COO・CDO・CMOそれぞれが役割を持ち、提案し、議論し、最終的にCEOが決定する。要件を聞いたとき、正直「これは時間がかかる」と思った。実際は1週間で動くものができた。
なぜ速かったか
核心は「ゲームエンジンを再利用できた」ことだ。チーム編でも、ターン計算の本質は同じだ。入力された意思決定をもとに、市場競争を計算し、財務結果を出す——この計算ロジックは個人編と共通だ。
個人編はプレイヤーが直接decisionsを入力して計算実行する。チーム編は各メンバーが提案してCEOが承認してdecisions確定した後に計算実行する。「提案→議論→決定」というフローを前段に追加する形で設計した。後段の計算エンジンはそのまま使える。
チーム編ならではの学び
チーム編は個人編とは異なる体験を生む。役割を持って議論することの難しさ、情報共有のコストと利得、チームの意思決定スピードと質のトレードオフ——これらは個人では体験できない。
「CFOが財務リスクを指摘しているのに、CEOが強引に投資を決めた結果、資金ショートした」という体験は、組織の意思決定の問題を実感させる。個人編と組み合わせることで2日間の連続プログラムが組めるようになった。
追加で必要だったAPIエンドポイントの実態
「1週間で動くものができた」と書いたが、その1週間で何を作ったかの詳細を記録しておく。
追加が必要だったAPIエンドポイント数:14本
個人編で使用しているAPIは23本。チーム編では、そのうち18本は共通で使用できた。新規に追加が必要だったAPIは14本だった。
代表的なものを挙げると:
POST /api/team/proposals/submit― メンバーが担当分野の提案を送信GET /api/team/proposals/{game_id}― 現在の全メンバーの提案一覧を取得PUT /api/team/proposals/{proposal_id}/vote― 提案に賛成/反対の意見を登録POST /api/team/decisions/finalize― CEOが最終意思決定を確定GET /api/team/discussion/{game_id}― チーム内のディスカッションログを取得POST /api/admin/team/assign_roles― 参加者に役職(CEO・CFO等)を割り当てる
設計で悩んだ箇所:「同時提案の競合」
複数メンバーが同時に提案を送信したとき、DBへの書き込みが競合する可能性があった。個人編では1人1ターン1回の送信なので問題なかった。チーム編では5人が同時に送信し得る。
解決策はシンプルで、提案テーブルに(game_id, team_id, member_role, turn_no)のユニーク制約を設けた。2回目の送信は「更新」として扱う。PostgreSQLのON CONFLICT DO UPDATEを使うことで、競合を自動的にアップサートに変換した。
最も時間がかかった部分:ロール管理画面
ゲーム開始前に「誰がCEO・CFO・COO・CDO・CMOを担当するか」を割り当てる管理者画面の実装だ。参加者のセッション情報とロール情報の連携、ロール変更時のリアルタイム更新——この部分だけで2日かかった。UIの複雑さが想定より大きかった。
*次回は「ファシリテータードキュメントをAIと修正した話」*
同時処理の二重実行問題とその解決
チーム編で発生した最も手強いバグが「二重実行問題」だった。
複数メンバーが同時に「提案送信」ボタンを押したとき、サーバー側で同一の処理が2回走ってしまうことがあった。症状は「提案が2件重複して登録される」だった。最初はフロントエンドのボタンを1回押したつもりが2回リクエストが飛ぶと思い、debounce処理を入れた。しかし解消しなかった。
原因はバックエンドにあった。FastAPIの非同期処理で、並行するリクエストが同時にDBへ書き込もうとした。先に書き込んだリクエストが完了する前に、2本目のリクエストが「このターン・このロールのデータは存在しない」と判断して新規挿入を実行した。
解決策はPostgreSQLのINSERT ... ON CONFLICT DO UPDATE(UPSERT)だ。(game_id, team_id, member_role, turn_no) のユニーク制約を設け、同一の組み合わせで送信が来た場合は「上書き」とした。2本目のリクエストは重複エラーにならず、最新の提案内容に更新される。これによって「最後に送信した提案が有効」という直感的な動作になった。
この修正を入れた後、同時送信テストを20回実施して全て正常動作を確認した。14本の新規APIのうち、チーム編ならではの設計が必要だったのはこの同時処理ロジックだった。個人編の経験が「問題を早期に想定する」力になっていた。
*シンプルシステム株式会社 代表 伊藤勝彦*