Skip to content

feat: ゲームマップのプレビューをshared/へ移行 - #206

Merged
taka2162 merged 30 commits into
developfrom
feature/map-preview-on-room
Aug 1, 2026
Merged

taka2162 merged 30 commits into
developfrom
feature/map-preview-on-room

Conversation

@taka2162

@taka2162 taka2162 commented Aug 1, 2026 •

Copy link
Copy Markdown
Collaborator

概要

待機ルーム(WaitingRoom)のマップアイコンプレビューが、バックエンドの実際のマップ生成ロジックと定数まで完全に重複したモックコードを表示していた問題を解消しました。マップ生成関数 createInitialMap() を shared/game-map.ts に一本化し、プレビューはその関数をサーバーと同じロジックで直接呼び出します。

対応Issue

Closes #204

変更内容

shared

  • game-map.ts を新設し、createInitialMap() / START_POSITIONS を backend の map.logic.ts から移設
  • package.json の exports に ./game-map を追加

backend

  • game.service.ts / player.logic.ts の import 先を @ft_transcendence/shared/game-map に変更
  • 空になった logic/setup/ ディレクトリを削除

frontend

  • map-mock.ts(バックエンドと重複していたマップ生成コード、および参照ゼロの未使用定数)を削除
  • GameMapPreview.tsx は shared の createInitialMap() を直接呼び出すよう変更
  • BombermanRenderer.ts のプレイヤー描画を、番号もラベルも出さない中立なスポーン候補地点リングに変更
    • スポーン位置の抽選は player.logic.ts の Math.random() によりルーム参加時に行われるため、特定プレイヤーがどこに出るかは開始前には表示しません(意図的に退出・再入室してスポーン位置を選ぶ悪用を避けるため)

スコープについて(今回あえて実装していないこと)

以下は今回は実装せず、最小限の変更にとどめています。

  • マップのランダム生成:現状の生成は完全に決定論的(乱数・seedなし)で、サーバーとクライアントの入力が一致すれば出力も必ず一致するため、shared への一本化のみで「プレビューが実データと一致する」という目的は達成されます。ランダム化は必要になった時点で別PRとします。
  • スタート位置の一括決定:現状は game:join(参加のたびに1人ずつ)抽選です。開始時に全員分をまとめて決定する方式への変更は、待機中の game:state からの情報漏えい対策も絡むため、スコープを分けて別PRで対応します。

確認

  • docker exec backend npx jest(22 suites / 173 tests pass)
  • docker exec backend npx eslint / npx nest build
  • docker exec frontend npx tsc -b / npx vite build / npx eslint . / npx prettier --check

Summary by CodeRabbit

  • 新機能

    • ルーム参加時の権限確認とエラー通知を改善しました。
    • 参加処理に失敗した場合、以前のルーム状態へ安全に戻るようになりました。
    • 切断時、待機中ルームから適切に退出できるようになりました。
    • ゲームマッププレビューにスポーン地点を表示するようになりました。
  • 改善

    • チャットで内部エラー情報を表示しないようにしました。
    • ロビーのルーム一覧更新と表示処理を効率化しました。
    • マップと開始位置の表示を統一しました。

@taka2162 taka2162 self-assigned this Aug 1, 2026
@taka2162
taka2162 changed the base branch from develop to refactor/game-constants-to-shared August 1, 2026 07:53
@coderabbitai

coderabbitai Bot commented Aug 1, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d7a6d882-5516-4cb5-a0fc-4e2ecfcf5c77

📥 Commits

Reviewing files that changed from the base of the PR and between c47fd4a and 0e6f55e.

📒 Files selected for processing (1)
  • shared/package.json
💤 Files with no reviewable changes (1)
  • shared/package.json

📝 Walkthrough

Walkthrough

共有ゲームマップをビルド可能なパッケージとして公開し、バックエンドとフロントエンドから参照します。RoomsGateway の参加、認証、退出、ロールバック、チャット処理を更新します。ロビー取得とマッププレビューも変更します。

Changes

共有ゲームマップ

Layer / File(s) Summary
共有マップの公開と参照統合
shared/game-map.ts, shared/package.json, shared/tsconfig.json, backend/package.json, backend/src/game/...
共有パッケージにビルド設定と ./game-map エクスポートを追加します。バックエンドは共有の createInitialMap と START_POSITIONS を参照します。

ルーム処理とフロントエンド表示

Layer / File(s) Summary
ルーム参加判定とロビー取得
backend/src/rooms/rooms.service.ts, backend/src/rooms/rooms.service.spec.ts, backend/src/rooms/rooms-lobby.service.ts
参加拒否理由を型付きコードに変更します。待機ルーム取得時の追加フィルタを削除します。参加者状態のテストを更新します。
ルーム購読とゲートウェイ処理
backend/src/rooms/rooms.gateway.ts, backend/src/rooms/rooms.gateway.spec.ts
認証取得、非同期退出、ルーム切替、ロールバック、チャットエラー処理を更新します。関連テストを非同期処理と型付きロガー参照に対応させます。
マッププレビューとロビー表示
frontend/src/components/game/preview/*, frontend/src/pages/LobbyPage.tsx
共有マップと開始位置をプレビューで使用します。プレイヤー描画をスポーンリングへ変更します。待機ルームの計算をメモ化します。

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant RoomsGateway
  participant RoomsService
  participant SocketPresence
  Client->>RoomsGateway: ルーム参加要求
  RoomsGateway->>RoomsService: canSubscribeで参加可否を確認
  RoomsGateway->>SocketPresence: Socket.IO参加とpresence登録
  RoomsGateway->>RoomsService: ルーム状態を更新
  RoomsGateway-->>Client: 最新スナップショットを通知
  Client->>RoomsGateway: ルーム退出要求
  RoomsGateway->>SocketPresence: Socket.IO退出とpresence解除
  RoomsGateway->>RoomsService: 参加者状態を更新
Loading

Possibly related PRs

Suggested reviewers: cimura, rt6500

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning ルーム参加、チャット、ロビー通知、退出処理など、Issue #204と直接関係しない変更が含まれています。 マップ共有とプレビュー表示に不要なルーム参加、チャット、ロビー通知、退出処理の変更を分離してください。
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed タイトルは、ゲームマップのプレビューをsharedへ移行する主要変更を簡潔に示しています。
Linked Issues check ✅ Passed Issue #204の要件に対し、共有マップ生成と待機ルームのプレビュー表示を実装しています。
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/map-preview-on-room

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (8)
backend/src/rooms/rooms-lobby.service.ts (1)

10-14: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

getLobbyRooms の filter は現在冗長です。

findAll('waiting') は status === 'waiting' のルームだけを返します。その結果に isLobbyVisible を適用しても、除外されるルームはありません。isLobbyVisible は ROOM_CREATED_EVENT の配信判定で別途必要です。表示条件が今後増える前提で filter を残すなら、その意図をコメントに追記してください。単純化するなら filter を削除できます。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/rooms/rooms-lobby.service.ts` around lines 10 - 14, Update
getLobbyRooms to remove the redundant isLobbyVisible filter and return the
waiting rooms from roomsService.findAll('waiting') directly; keep isLobbyVisible
available for the ROOM_CREATED_EVENT delivery decision.
backend/src/rooms/rooms.service.ts (1)

259-274: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

checkJoinable の戻り値を型安全な判別値にする案です。

現在の戻り値は string | null です。呼び出し側は === null で真偽判定します。理由コードの列挙型(例: 'not_waiting' | 'full' | null)にすると、メッセージ文字列とドメイン判定を分離できます。例外メッセージはコード→文言のマップで生成できます。型安全を優先する方針に沿います。

As per coding guidelines「型安全を優先する」

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/rooms/rooms.service.ts` around lines 259 - 274, Update
checkJoinable to return a typed reason code such as 'not_waiting' | 'full' |
null instead of message strings, and keep assertJoinable responsible for
converting each code to the existing user-facing message before throwing
ConflictException. Preserve the current joinability checks and outcomes while
separating domain classification from exception wording.

Source: Coding guidelines

backend/src/rooms/rooms.gateway.ts (2)

354-356: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

requireUserId の名前は挙動と一致していません。

require という語は、条件を満たさない場合に例外を投げる処理を示します。この関数は undefined を返します。呼び出し側が毎回 undefined を判定します。getUserId に改名すると、戻り値の契約が名前から分かります。

As per coding guidelines「意味が明確で一貫した命名を重視する」

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/rooms/rooms.gateway.ts` around lines 354 - 356, Rename the
RoomsGateway helper requireUserId to getUserId to match its behavior of
returning an optional user ID rather than throwing, and update every call site
and reference accordingly while preserving the existing return contract.

Source: Coding guidelines


338-350: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

rollbacks.reverse() は引数の配列を破壊的に変更します。

Array#reverse は元の配列を反転します。現在の呼び出し元は runRollbacks の後に rollbacks を再利用しないため、動作は正しいです。将来ロールバック後に配列を参照する変更が入ると、順序が反転した状態を読むことになります。コピーしてから反転すると安全です。

♻️ 提案する変更
-    for (const undo of rollbacks.reverse()) {
+    for (const undo of [...rollbacks].reverse()) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/rooms/rooms.gateway.ts` around lines 338 - 350, Update
runRollbacks to iterate over a copied array before reversing it, rather than
calling reverse() directly on the rollbacks parameter. Preserve the existing
reverse-order execution and error handling while preventing mutation of the
caller’s array.
frontend/src/pages/LobbyPage.tsx (1)

45-45: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

visibleRooms を useMemo で安定化する案です。

rooms.filter(...) はレンダーごとに新しい配列を生成します。RoomList が React.memo で最適化されている場合、rooms が変化していなくても再レンダリングが発生します。件数は少ないため影響は小さいですが、useMemo(() => rooms.filter(...), [rooms]) にすると参照が安定します。

As per path instructions「useMemo/useCallbackの不要・不足」「再レンダリング」

♻️ 提案する変更
-  const visibleRooms = rooms.filter((room) => room.status === 'waiting')
+  const visibleRooms = useMemo(
+    () => rooms.filter((room) => room.status === 'waiting'),
+    [rooms]
+  )

useMemo の import を追加してください。

-import { useEffect, useState } from 'react'
+import { useEffect, useMemo, useState } from 'react'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/LobbyPage.tsx` at line 45, Update the visibleRooms
derivation in LobbyPage to use useMemo with rooms as its dependency, and add the
corresponding React import. Preserve the existing waiting-status filter while
stabilizing the array reference between renders when rooms is unchanged.

Source: Path instructions

backend/src/rooms/rooms.service.spec.ts (1)

361-415: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

参加者リテラルをビルダー関数に抽出する案です。

canSubscribe の満員テストと evictIfWaiting のテストで、同じ参加者オブジェクトの形を繰り返し記述しています。buildParticipant(overrides) のようなヘルパーを追加すると、RoomParticipant の項目追加時の修正箇所が 1 か所になります。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/rooms/rooms.service.spec.ts` around lines 361 - 415,
重複している参加者オブジェクト定義を、テストファイル内の共通ビルダー関数(例:
buildParticipant(overrides))へ抽出してください。canSubscribe と evictIfWaiting
のテストではビルダーを使い、ユーザーID・ホスト状態・準備状態・参加時刻などテスト固有の値だけを overrides で指定し、RoomParticipant
の共通フィールドは一か所で管理してください。
backend/src/rooms/rooms.gateway.spec.ts (1)

287-289: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

(gateway as any).logger を型安全なアクセスに置き換える案です。

as any は型検査を無効にします。同じ書き方が L464、L529、L546、L596 にもあります。private メンバーへのアクセスは gateway['logger'] で型を保ったまま可能です。または Logger.prototype を spy 対象にする共通ヘルパーを追加すると、記述が 1 か所に集まります。

As per coding guidelines「型安全を優先する」

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/rooms/rooms.gateway.spec.ts` around lines 287 - 289,
rooms.gateway.spec.ts の logger スパイで使用している型無視の any キャストを削除し、gateway の private
logger
には型を保持できるブラケット記法でアクセスしてください。対象は同じ書き方がある全箇所(L287、L464、L529、L546、L596)とし、必要に応じて
Logger.prototype を利用する共通ヘルパーへ集約してください。

Source: Coding guidelines

shared/game-map.ts (1)

1-11: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

START_POSITIONS を深く読み取り専用にしてください。

現在の実装ではこの定数はすべて読み取りで使われていますが、可変の WorldPosition[] 型だと追加の呼び出し側で配列や座標を誤って変更できます。決定的な createInitialMap() と startPositionSlots の関係を守るため、ReadonlyArray<Readonly<WorldPosition>> にしてください。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@shared/game-map.ts` around lines 1 - 11, Update the START_POSITIONS
declaration to use ReadonlyArray<Readonly<WorldPosition>>, making both the array
and each WorldPosition entry deeply read-only while preserving its existing
values and usage.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/rooms/rooms.gateway.ts`:
- Line 379: Update the room-leave flow around client.leave(roomId) to explicitly
handle both synchronous and Promise-based returns, attaching rejection logging
for asynchronous failures instead of discarding the result with void. Preserve
the existing leave behavior while using the gateway’s established logger and
context.

In `@shared/package.json`:
- Around line 23-30: shared/package.json の「./game-constants」と「./game-map」の
default を TypeScript ソースではなく、ビルドで生成される dist/shared 配下などの JavaScript
出力へ変更してください。両モジュールのコンパイル結果が本番ビルドに配置され、node dist/main.js
から実行時に解決できる構成も併せて確認し、types の参照は既存どおり維持してください。

---

Nitpick comments:
In `@backend/src/rooms/rooms-lobby.service.ts`:
- Around line 10-14: Update getLobbyRooms to remove the redundant isLobbyVisible
filter and return the waiting rooms from roomsService.findAll('waiting')
directly; keep isLobbyVisible available for the ROOM_CREATED_EVENT delivery
decision.

In `@backend/src/rooms/rooms.gateway.spec.ts`:
- Around line 287-289: rooms.gateway.spec.ts の logger スパイで使用している型無視の any
キャストを削除し、gateway の private logger
には型を保持できるブラケット記法でアクセスしてください。対象は同じ書き方がある全箇所(L287、L464、L529、L546、L596)とし、必要に応じて
Logger.prototype を利用する共通ヘルパーへ集約してください。

In `@backend/src/rooms/rooms.gateway.ts`:
- Around line 354-356: Rename the RoomsGateway helper requireUserId to getUserId
to match its behavior of returning an optional user ID rather than throwing, and
update every call site and reference accordingly while preserving the existing
return contract.
- Around line 338-350: Update runRollbacks to iterate over a copied array before
reversing it, rather than calling reverse() directly on the rollbacks parameter.
Preserve the existing reverse-order execution and error handling while
preventing mutation of the caller’s array.

In `@backend/src/rooms/rooms.service.spec.ts`:
- Around line 361-415: 重複している参加者オブジェクト定義を、テストファイル内の共通ビルダー関数(例:
buildParticipant(overrides))へ抽出してください。canSubscribe と evictIfWaiting
のテストではビルダーを使い、ユーザーID・ホスト状態・準備状態・参加時刻などテスト固有の値だけを overrides で指定し、RoomParticipant
の共通フィールドは一か所で管理してください。

In `@backend/src/rooms/rooms.service.ts`:
- Around line 259-274: Update checkJoinable to return a typed reason code such
as 'not_waiting' | 'full' | null instead of message strings, and keep
assertJoinable responsible for converting each code to the existing user-facing
message before throwing ConflictException. Preserve the current joinability
checks and outcomes while separating domain classification from exception
wording.

In `@frontend/src/pages/LobbyPage.tsx`:
- Line 45: Update the visibleRooms derivation in LobbyPage to use useMemo with
rooms as its dependency, and add the corresponding React import. Preserve the
existing waiting-status filter while stabilizing the array reference between
renders when rooms is unchanged.

In `@shared/game-map.ts`:
- Around line 1-11: Update the START_POSITIONS declaration to use
ReadonlyArray<Readonly<WorldPosition>>, making both the array and each
WorldPosition entry deeply read-only while preserving its existing values and
usage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f2dfc505-eb0c-4192-a605-f29e5866a9d3

📥 Commits

Reviewing files that changed from the base of the PR and between 60ea20a and a7cc480.

📒 Files selected for processing (32)
  • backend/src/common/types/room.type.ts
  • backend/src/game/game.service.spec.ts
  • backend/src/game/game.service.ts
  • backend/src/game/logic/core/loop.logic.ts
  • backend/src/game/logic/mechanics/bomb.logic.ts
  • backend/src/game/logic/mechanics/movement.logic.ts
  • backend/src/game/logic/session/lifecycle.logic.ts
  • backend/src/game/logic/session/player.logic.ts
  • backend/src/game/logic/session/timeout.logic.ts
  • backend/src/rooms/dto/create-room.dto.ts
  • backend/src/rooms/rooms-chat.service.spec.ts
  • backend/src/rooms/rooms-invitation.service.spec.ts
  • backend/src/rooms/rooms-lobby.service.spec.ts
  • backend/src/rooms/rooms-lobby.service.ts
  • backend/src/rooms/rooms.gateway.spec.ts
  • backend/src/rooms/rooms.gateway.ts
  • backend/src/rooms/rooms.service.spec.ts
  • backend/src/rooms/rooms.service.ts
  • frontend/src/components/game/BombermanScene.tsx
  • frontend/src/components/game/preview/BombermanRenderer.ts
  • frontend/src/components/game/preview/GameMapPreview.tsx
  • frontend/src/components/game/preview/map-mock.ts
  • frontend/src/components/game/utils/map-colors.ts
  • frontend/src/constants/game-constants.ts
  • frontend/src/game/bomb-explosion.ts
  • frontend/src/pages/LobbyPage.tsx
  • frontend/src/pages/WaitingRoom.tsx
  • frontend/src/types/room.ts
  • shared/game-constants.ts
  • shared/game-map.ts
  • shared/package.json
  • shared/rooms-events.types.ts
💤 Files with no reviewable changes (8)
  • backend/src/rooms/rooms-chat.service.spec.ts
  • shared/rooms-events.types.ts
  • backend/src/common/types/room.type.ts
  • frontend/src/types/room.ts
  • frontend/src/components/game/preview/map-mock.ts
  • backend/src/rooms/dto/create-room.dto.ts
  • backend/src/rooms/rooms-invitation.service.spec.ts
  • frontend/src/constants/game-constants.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

🧹 Nitpick comments (8)
backend/src/rooms/rooms-lobby.service.ts (1)

10-14: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

getLobbyRooms の filter は現在冗長です。

findAll('waiting') は status === 'waiting' のルームだけを返します。その結果に isLobbyVisible を適用しても、除外されるルームはありません。isLobbyVisible は ROOM_CREATED_EVENT の配信判定で別途必要です。表示条件が今後増える前提で filter を残すなら、その意図をコメントに追記してください。単純化するなら filter を削除できます。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/rooms/rooms-lobby.service.ts` around lines 10 - 14, Update
getLobbyRooms to remove the redundant isLobbyVisible filter and return the
waiting rooms from roomsService.findAll('waiting') directly; keep isLobbyVisible
available for the ROOM_CREATED_EVENT delivery decision.
backend/src/rooms/rooms.service.ts (1)

259-274: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

checkJoinable の戻り値を型安全な判別値にする案です。

現在の戻り値は string | null です。呼び出し側は === null で真偽判定します。理由コードの列挙型(例: 'not_waiting' | 'full' | null)にすると、メッセージ文字列とドメイン判定を分離できます。例外メッセージはコード→文言のマップで生成できます。型安全を優先する方針に沿います。

As per coding guidelines「型安全を優先する」

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/rooms/rooms.service.ts` around lines 259 - 274, Update
checkJoinable to return a typed reason code such as 'not_waiting' | 'full' |
null instead of message strings, and keep assertJoinable responsible for
converting each code to the existing user-facing message before throwing
ConflictException. Preserve the current joinability checks and outcomes while
separating domain classification from exception wording.

Source: Coding guidelines

backend/src/rooms/rooms.gateway.ts (2)

354-356: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

requireUserId の名前は挙動と一致していません。

require という語は、条件を満たさない場合に例外を投げる処理を示します。この関数は undefined を返します。呼び出し側が毎回 undefined を判定します。getUserId に改名すると、戻り値の契約が名前から分かります。

As per coding guidelines「意味が明確で一貫した命名を重視する」

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/rooms/rooms.gateway.ts` around lines 354 - 356, Rename the
RoomsGateway helper requireUserId to getUserId to match its behavior of
returning an optional user ID rather than throwing, and update every call site
and reference accordingly while preserving the existing return contract.

Source: Coding guidelines


338-350: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

rollbacks.reverse() は引数の配列を破壊的に変更します。

Array#reverse は元の配列を反転します。現在の呼び出し元は runRollbacks の後に rollbacks を再利用しないため、動作は正しいです。将来ロールバック後に配列を参照する変更が入ると、順序が反転した状態を読むことになります。コピーしてから反転すると安全です。

♻️ 提案する変更
-    for (const undo of rollbacks.reverse()) {
+    for (const undo of [...rollbacks].reverse()) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/rooms/rooms.gateway.ts` around lines 338 - 350, Update
runRollbacks to iterate over a copied array before reversing it, rather than
calling reverse() directly on the rollbacks parameter. Preserve the existing
reverse-order execution and error handling while preventing mutation of the
caller’s array.
frontend/src/pages/LobbyPage.tsx (1)

45-45: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

visibleRooms を useMemo で安定化する案です。

rooms.filter(...) はレンダーごとに新しい配列を生成します。RoomList が React.memo で最適化されている場合、rooms が変化していなくても再レンダリングが発生します。件数は少ないため影響は小さいですが、useMemo(() => rooms.filter(...), [rooms]) にすると参照が安定します。

As per path instructions「useMemo/useCallbackの不要・不足」「再レンダリング」

♻️ 提案する変更
-  const visibleRooms = rooms.filter((room) => room.status === 'waiting')
+  const visibleRooms = useMemo(
+    () => rooms.filter((room) => room.status === 'waiting'),
+    [rooms]
+  )

useMemo の import を追加してください。

-import { useEffect, useState } from 'react'
+import { useEffect, useMemo, useState } from 'react'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/LobbyPage.tsx` at line 45, Update the visibleRooms
derivation in LobbyPage to use useMemo with rooms as its dependency, and add the
corresponding React import. Preserve the existing waiting-status filter while
stabilizing the array reference between renders when rooms is unchanged.

Source: Path instructions

backend/src/rooms/rooms.service.spec.ts (1)

361-415: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

参加者リテラルをビルダー関数に抽出する案です。

canSubscribe の満員テストと evictIfWaiting のテストで、同じ参加者オブジェクトの形を繰り返し記述しています。buildParticipant(overrides) のようなヘルパーを追加すると、RoomParticipant の項目追加時の修正箇所が 1 か所になります。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/rooms/rooms.service.spec.ts` around lines 361 - 415,
重複している参加者オブジェクト定義を、テストファイル内の共通ビルダー関数(例:
buildParticipant(overrides))へ抽出してください。canSubscribe と evictIfWaiting
のテストではビルダーを使い、ユーザーID・ホスト状態・準備状態・参加時刻などテスト固有の値だけを overrides で指定し、RoomParticipant
の共通フィールドは一か所で管理してください。
backend/src/rooms/rooms.gateway.spec.ts (1)

287-289: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

(gateway as any).logger を型安全なアクセスに置き換える案です。

as any は型検査を無効にします。同じ書き方が L464、L529、L546、L596 にもあります。private メンバーへのアクセスは gateway['logger'] で型を保ったまま可能です。または Logger.prototype を spy 対象にする共通ヘルパーを追加すると、記述が 1 か所に集まります。

As per coding guidelines「型安全を優先する」

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/rooms/rooms.gateway.spec.ts` around lines 287 - 289,
rooms.gateway.spec.ts の logger スパイで使用している型無視の any キャストを削除し、gateway の private
logger
には型を保持できるブラケット記法でアクセスしてください。対象は同じ書き方がある全箇所(L287、L464、L529、L546、L596)とし、必要に応じて
Logger.prototype を利用する共通ヘルパーへ集約してください。

Source: Coding guidelines

shared/game-map.ts (1)

1-11: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

START_POSITIONS を深く読み取り専用にしてください。

現在の実装ではこの定数はすべて読み取りで使われていますが、可変の WorldPosition[] 型だと追加の呼び出し側で配列や座標を誤って変更できます。決定的な createInitialMap() と startPositionSlots の関係を守るため、ReadonlyArray<Readonly<WorldPosition>> にしてください。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@shared/game-map.ts` around lines 1 - 11, Update the START_POSITIONS
declaration to use ReadonlyArray<Readonly<WorldPosition>>, making both the array
and each WorldPosition entry deeply read-only while preserving its existing
values and usage.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/rooms/rooms.gateway.ts`:
- Line 379: Update the room-leave flow around client.leave(roomId) to explicitly
handle both synchronous and Promise-based returns, attaching rejection logging
for asynchronous failures instead of discarding the result with void. Preserve
the existing leave behavior while using the gateway’s established logger and
context.

In `@shared/package.json`:
- Around line 23-30: shared/package.json の「./game-constants」と「./game-map」の
default を TypeScript ソースではなく、ビルドで生成される dist/shared 配下などの JavaScript
出力へ変更してください。両モジュールのコンパイル結果が本番ビルドに配置され、node dist/main.js
から実行時に解決できる構成も併せて確認し、types の参照は既存どおり維持してください。

---

Nitpick comments:
In `@backend/src/rooms/rooms-lobby.service.ts`:
- Around line 10-14: Update getLobbyRooms to remove the redundant isLobbyVisible
filter and return the waiting rooms from roomsService.findAll('waiting')
directly; keep isLobbyVisible available for the ROOM_CREATED_EVENT delivery
decision.

In `@backend/src/rooms/rooms.gateway.spec.ts`:
- Around line 287-289: rooms.gateway.spec.ts の logger スパイで使用している型無視の any
キャストを削除し、gateway の private logger
には型を保持できるブラケット記法でアクセスしてください。対象は同じ書き方がある全箇所(L287、L464、L529、L546、L596)とし、必要に応じて
Logger.prototype を利用する共通ヘルパーへ集約してください。

In `@backend/src/rooms/rooms.gateway.ts`:
- Around line 354-356: Rename the RoomsGateway helper requireUserId to getUserId
to match its behavior of returning an optional user ID rather than throwing, and
update every call site and reference accordingly while preserving the existing
return contract.
- Around line 338-350: Update runRollbacks to iterate over a copied array before
reversing it, rather than calling reverse() directly on the rollbacks parameter.
Preserve the existing reverse-order execution and error handling while
preventing mutation of the caller’s array.

In `@backend/src/rooms/rooms.service.spec.ts`:
- Around line 361-415: 重複している参加者オブジェクト定義を、テストファイル内の共通ビルダー関数(例:
buildParticipant(overrides))へ抽出してください。canSubscribe と evictIfWaiting
のテストではビルダーを使い、ユーザーID・ホスト状態・準備状態・参加時刻などテスト固有の値だけを overrides で指定し、RoomParticipant
の共通フィールドは一か所で管理してください。

In `@backend/src/rooms/rooms.service.ts`:
- Around line 259-274: Update checkJoinable to return a typed reason code such
as 'not_waiting' | 'full' | null instead of message strings, and keep
assertJoinable responsible for converting each code to the existing user-facing
message before throwing ConflictException. Preserve the current joinability
checks and outcomes while separating domain classification from exception
wording.

In `@frontend/src/pages/LobbyPage.tsx`:
- Line 45: Update the visibleRooms derivation in LobbyPage to use useMemo with
rooms as its dependency, and add the corresponding React import. Preserve the
existing waiting-status filter while stabilizing the array reference between
renders when rooms is unchanged.

In `@shared/game-map.ts`:
- Around line 1-11: Update the START_POSITIONS declaration to use
ReadonlyArray<Readonly<WorldPosition>>, making both the array and each
WorldPosition entry deeply read-only while preserving its existing values and
usage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f2dfc505-eb0c-4192-a605-f29e5866a9d3

📥 Commits

Reviewing files that changed from the base of the PR and between 60ea20a and a7cc480.

📒 Files selected for processing (32)
  • backend/src/common/types/room.type.ts
  • backend/src/game/game.service.spec.ts
  • backend/src/game/game.service.ts
  • backend/src/game/logic/core/loop.logic.ts
  • backend/src/game/logic/mechanics/bomb.logic.ts
  • backend/src/game/logic/mechanics/movement.logic.ts
  • backend/src/game/logic/session/lifecycle.logic.ts
  • backend/src/game/logic/session/player.logic.ts
  • backend/src/game/logic/session/timeout.logic.ts
  • backend/src/rooms/dto/create-room.dto.ts
  • backend/src/rooms/rooms-chat.service.spec.ts
  • backend/src/rooms/rooms-invitation.service.spec.ts
  • backend/src/rooms/rooms-lobby.service.spec.ts
  • backend/src/rooms/rooms-lobby.service.ts
  • backend/src/rooms/rooms.gateway.spec.ts
  • backend/src/rooms/rooms.gateway.ts
  • backend/src/rooms/rooms.service.spec.ts
  • backend/src/rooms/rooms.service.ts
  • frontend/src/components/game/BombermanScene.tsx
  • frontend/src/components/game/preview/BombermanRenderer.ts
  • frontend/src/components/game/preview/GameMapPreview.tsx
  • frontend/src/components/game/preview/map-mock.ts
  • frontend/src/components/game/utils/map-colors.ts
  • frontend/src/constants/game-constants.ts
  • frontend/src/game/bomb-explosion.ts
  • frontend/src/pages/LobbyPage.tsx
  • frontend/src/pages/WaitingRoom.tsx
  • frontend/src/types/room.ts
  • shared/game-constants.ts
  • shared/game-map.ts
  • shared/package.json
  • shared/rooms-events.types.ts
💤 Files with no reviewable changes (8)
  • backend/src/rooms/rooms-chat.service.spec.ts
  • shared/rooms-events.types.ts
  • backend/src/common/types/room.type.ts
  • frontend/src/types/room.ts
  • frontend/src/components/game/preview/map-mock.ts
  • backend/src/rooms/dto/create-room.dto.ts
  • backend/src/rooms/rooms-invitation.service.spec.ts
  • frontend/src/constants/game-constants.ts
🛑 Comments failed to post (2)
backend/src/rooms/rooms.gateway.ts (1)

379-379: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

socket.io 4.8 Socket leave method return type Promise adapter

💡 Result:

In Socket.IO 4.8, the socket.leave(room) method has a return type of Promise<void> | void [1][2][3]. The return value depends on the underlying adapter being used [2][3]. While the default in-memory adapter performs these operations synchronously (returning void), custom adapters (such as those for Redis or other distributed backends) may perform these operations asynchronously and therefore return a Promise<void> [4]. Because the return type is unioned, if you are using a custom adapter or want your code to be resilient to changes in the adapter implementation, you should treat the result as a Promise and use await if you need to ensure the room has been left before proceeding: await socket.leave("room-name"); For context, although socket.join() and socket.leave() were made synchronous in the major version 3.0 release for the default in-memory adapter, the API signature was designed to support the asynchronous nature of distributed adapters [4]. You should not rely on the method always being synchronous [2][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate file =="
fd -a 'rooms.gateway.ts$' . || true

echo "== Package manifests =="
git ls-files | rg '(^|/)package\.json$|(^|/)package-lock\.json$|(^|/)yarn\.lock$|(^|/)pnpm-lock\.yaml$' | head -50

echo "== Socket.IO references =="
rg -n '"socket\.io"|socket\.io|Socket\.IO|leave\(roomId\)|leave\(' -S --glob '!node_modules/**' --glob '!dist/**' .

echo "== Inspect relevant file section =="
if [ -f backend/src/rooms/rooms.gateway.ts ]; then
  nl -ba backend/src/rooms/rooms.gateway.ts | sed -n '340,400p'
fi

echo "== Nginx Socket.IO adapter/package references =="
rg -n '`@socket`\.io/redis-adapter|`@socket`\.io/redis-emitter|socket.io-redis|redis-adapter|RedisAdapter' -S .

Repository: cimura/ft_transcendence

Length of output: 6006


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Relevant section of backend/src/rooms/rooms.gateway.ts =="
awk '
  NR>=330 && NR<=410 { printf "%6d\t%s\n", NR, $0 }
' backend/src/rooms/rooms.gateway.ts

echo "== Relevant rollback section =="
awk '
  NR>=260 && NR<=330 { printf "%6d\t%s\n", NR, $0 }
' backend/src/rooms/rooms.gateway.ts

echo "== backend/src/game/game.gateway.ts patterns =="
awk '
  NR>=70 && NR<=205 { printf "%6d\t%s\n", NR, $0 }
' backend/src/game/game.gateway.ts

echo "== Socket adapter usages/reflection =="
python3 - <<'PY'
from pathlib import Path
import json
import re

for p in [Path("backend/src/rooms/rooms.gateway.ts"), Path("backend/src/game/game.gateway.ts"), Path("backend/src/websocket/realtime.gateway.ts"), Path("backend/src/websocket/socket-auth.service.ts")]:
    text = p.read_text() if p.exists() else ""
    print(f"--- {p} ---")
    for name in ["new IO(", "Server(", "Server<", "`@UseFilters`", "handleException", "adapter"]:
        hits = re.findall(re.escape(name), text)
        if hits:
            print(f"{name}: {len(hits)}")
PY

echo "== node_modules socket.io leave declaration if present =="
python3 - <<'PY'
from pathlib import Path
p=Path("backend/node_modules/socket.io/dist/socket.d.ts")
if p.exists():
    txt=p.read_text()
    idx=txt.find("leave(")
    print(txt[max(0,idx-500):idx+800])
else:
    print("missing")
PY

Repository: cimura/ft_transcendence

Length of output: 10686


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Lockfile entries for `@nestjs/platform-socket.io` and socket.io =="
python3 - <<'PY'
import json
from pathlib import Path
p=Path("package-lock.json")
data=json.loads(p.read_text())
for name in ["node_modules/@nestjs/platform-socket.io", "node_modules/socket.io", "node_modules/@types/socket.io"]:
    if name in data.get("packages", {}):
        pkg=data["packages"][name]
        print("\n---", name, "---")
        for k,v in pkg.items():
            if k in ("version","license","dependencies","devDependencies","peerDependencies"):
                print(k, v)
PY

echo "== Lockfile installed Socket.IO source if node_modules is unavailable, fallback to tarball fetch =="
curl -fsSL "https://unpkg.com/socket.io@4.8.3/dist/socket.d.ts" | awk '/leave\(room: (string|any)\)/,/^  \}/' || true

echo "== Lockfile installed Socket.IO socket.js if node_modules unavailable, fallback =="
curl -fsSL "https://unpkg.com/socket.io@4.8.3/dist/socket.js" | sed -n '1,260p' | grep -n "leave(" -A 40 -B 5 || true

Repository: cimura/ft_transcendence

Length of output: 11374


🌐 Web query:

socket.io 4.8.3 lib/socket.ts async leave implementation adapter.leave return

💡 Result:

In Socket.IO 4.8.3, the implementation of the leave method in lib/socket.ts delegates the task directly to the configured adapter [1][2]. The leave method is defined as follows: public leave(room: string): Promise | void { debug("leave room %s", room); return this.adapter.del(this.id, room); } The return value of socket.leave(room) is either a Promise or void [1][2]. This behavior depends entirely on the implementation of the del method in the specific adapter being used (e.g., the default In-Memory adapter, Redis adapter, etc.) [1][3]. - If the adapter's del method is asynchronous and returns a Promise, socket.leave() will return that Promise. - If the adapter's del method is synchronous, socket.leave() will return void [1][2]. As of version 4.8.3, while there have been updates to how rooms are handled (such as the introduction of support for leaving multiple rooms in a single call via an array or Set in newer developments [4]), the base signature and reliance on the adapter's del method implementation remain consistent with this delegation pattern [1][2]. Note that historically, older versions of Socket.IO documentation suggested returning the Socket instance for chaining [5], but the actual source code implementation in recent versions (including 4.8.3) explicitly returns the result of the adapter's del operation [1][2]. If you rely on chaining, you should verify the behavior of your specific adapter implementation.

Citations:


🌐 Web query:

@nestjs/platform-socket.io 11.1.27 constructor Server adapter default adapter Socket.IO

💡 Result:

In @nestjs/platform-socket.io version 11.1.27, the IoAdapter class serves as the default WebSocket adapter [1]. The constructor for IoAdapter accepts an optional INestApplicationContext or an HTTP server instance [2][3]. The core implementation for creating a Socket.IO server is handled by the createIOServer(port: number, options?: any) method within the IoAdapter class [2][4]. This method contains the logic for initializing the Socket.IO Server instance: 1. If an HTTP server is associated with the adapter and the port is 0, it creates a new Server instance using the existing HTTP server [2]. 2. Otherwise, it initializes a new Server instance using the provided port and options [2]. The default adapter behavior can be extended or overridden by creating a custom class that extends IoAdapter [5]. Developers often do this to customize server instantiation, such as integrating Redis adapters for scaling, by overriding the createIOServer method and calling the super.createIOServer(port, options) method to obtain the base server instance before applying additional configurations [5][6]. The framework automatically registers the IoAdapter as the default WebSocket adapter when the @nestjs/platform-socket.io package is present in the application [1].

Citations:


client.leave(roomId) の返値を明示的に処理してください。

Socket.IO 4.8.3 の Socket#leave は Promise<void> | void を返し、カスタム adapters が Promise を返す場合があります。.catch で拒否をログに記録しないまま void で破棄すると、未处理的 rejection になる可能性があります。

♻️ 提案する変更
-    void client.leave(roomId);
+    void Promise.resolve(client.leave(roomId)).catch((error) => {
+      this.logger.warn(
+        `Failed to leave socket room { roomId: '${roomId}' }: ${
+          error instanceof Error ? error.message : String(error)
+        }`,
+      );
+    });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    void Promise.resolve(client.leave(roomId)).catch((error) => {
      this.logger.warn(
        `Failed to leave socket room { roomId: '${roomId}' }: ${
          error instanceof Error ? error.message : String(error)
        }`,
      );
    });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/rooms/rooms.gateway.ts` at line 379, Update the room-leave flow
around client.leave(roomId) to explicitly handle both synchronous and
Promise-based returns, attaching rejection logging for asynchronous failures
instead of discarding the result with void. Preserve the existing leave behavior
while using the gateway’s established logger and context.

Source: Path instructions

shared/package.json (1)

23-30: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n \
  --glob 'package.json' \
  --glob 'tsconfig*.json' \
  --glob 'nest-cli.json' \
  --glob 'vite.config.*' \
  --glob 'Dockerfile*' \
  '(build|start:prod|node |tsx|ts-node|outDir|paths|external|`@ft_transcendence/shared`)' . || true

rg -n \
  '`@ft_transcendence/shared/`(game-map|game-constants)' \
  --glob '*.{ts,tsx,js,mjs,cjs}' . || true

Repository: cimura/ft_transcendence

Length of output: 2724


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "== files =="
git ls-files | rg '(^|/)(package\.json|tsconfig.*\.json|nest-cli\.json|vite\.config\..*)$' || true

echo
echo "== shared package =="
cat -n shared/package.json

echo
echo "== backend package relevant scripts =="
python3 - <<'PY'
import json
from pathlib import Path
p = Path("backend/package.json")
if p.exists():
    data=json.loads(p.read_text())
    for k in ["scripts","dependencies","devDependencies"]:
        if k in data:
            print(f"[{k}]")
            for kk,v in data[k].items():
                if k=="scripts" or kk in ["`@ft_transcendence/shared`","typescript","`@nestjs/cli`","ts-loader","source-map-support","reflect-metadata","ts-node","tsconfig-paths","class-transformer","class-validator","bcryptjs","`@nestjs/platform-express`"]:
                    print(f"  {kk}: {v}")
PY

echo
echo "== backend tsconfig =="
for f in backend/tsconfig.json backend/nest-cli.json; do
  if [ -f "$f" ]; then
    echo "--- $f"
    cat -n "$f"
  fi
done

echo
echo "== frontend relevant package/config =="
cat -n frontend/package.json
for f in frontend/vite.config.ts frontend/vite.config.js frontend/tsconfig.app.json frontend/tsconfig.node.json; do
  if [ -f "$f" ]; then
    echo "--- $f"
    cat -n "$f"
  fi
done

echo
echo "== shared source files =="
find shared -maxdepth 2 -type f -print | sort | while read -r f; do
  case "$f" in
    *.ts|*.tsx|*.js|*.jsx|*.mjs|*.cjs|package.json|tsconfig*.json)
      echo "--- $f"
      sed -n '1,120p' "$f" | cat -n
      ;;
  esac
done

echo
echo "== deterministic export/transform verifier =="
python3 - <<'PY'
import json, pathlib, re
shared = json.loads(pathlib.Path("shared/package.json").read_text())
exports = shared.get("exports")
backend = json.loads(pathlib.Path("backend/package.json").read_text())
frontend = json.loads(pathlib.Path("frontend/package.json").read_text())

targets = {}
for key, value in exports.items():
    if key == ".":
        continue
    target = None
    if isinstance(value, dict):
        for n in ["default", "import", "module"]:
            if n in value and str(value[n]).endswith(".ts"):
                target = value[n]
                break
    elif isinstance(value, str) and value.endswith(".ts"):
        target = value
    if target:
        targets[key] = target
print("export_targets", targets)
print("backend_start_prod", backend.get("scripts", {}).get("start:prod"))
print("frontend_build_script", frontend.get("scripts", {}).get("build"))

found = False
for path in pathlib.Path("backend/tsconfig.json").parent.glob("*.json"):
    if str(path).endswith("tsconfig.json"):
        data=json.loads(path.read_text())
        opts=data.get("compilerOptions", {})
        if opts.get("outDir"):
            found=True
            print("backend_tsconfig_outDir", opts["outDir"])
        if opts.get("module") in ["ESNext", "ES2020", "ES2015", "ES2022"]:
            print("backend_tsconfig_module", opts["module"])

print("has_backend_outDir", found)
PY

Repository: cimura/ft_transcendence

Length of output: 18245


shared/package.json の default 出力を JavaScript 生成物へ設定してください。

./game-constants と ./game-map は実行時の値を返すため、backend 本番起動が node dist/main.js で .ts をロードできません。game-constants/game-map のコンパイル結果を dist/shared などに配置し、default をその JS 出力へ向ける構成にしてください。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@shared/package.json` around lines 23 - 30, shared/package.json
の「./game-constants」と「./game-map」の default を TypeScript ソースではなく、ビルドで生成される
dist/shared 配下などの JavaScript 出力へ変更してください。両モジュールのコンパイル結果が本番ビルドに配置され、node
dist/main.js から実行時に解決できる構成も併せて確認し、types の参照は既存どおり維持してください。

@rt6500
rt6500 force-pushed the feature/map-preview-on-room branch from 677e67f to 594bc72 Compare August 1, 2026 08:24
@rt6500
rt6500 force-pushed the refactor/game-constants-to-shared branch from 9349492 to b1fa1cb Compare August 1, 2026 08:24
@taka2162

taka2162 commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai
NItpick指摘を修正しました

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@taka2162 ご対応ありがとうございます。Nitpick 指摘の修正を確認しました。


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

You are interacting with an AI system.

@taka2162

taka2162 commented Aug 1, 2026 •

Copy link
Copy Markdown
Collaborator Author

@coderabbitai
Requested Changes はどれですか?もしすべて対処されていたらapprove してください。

@rt6500
rt6500 force-pushed the refactor/game-constants-to-shared branch from b1fa1cb to f685827 Compare August 1, 2026 08:33
@rt6500
rt6500 force-pushed the feature/map-preview-on-room branch from 594bc72 to ae68dde Compare August 1, 2026 08:33
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- repository status ---'
git status --short
git rev-parse --short HEAD

echo '--- relevant file outlines ---'
ast-grep outline backend/src/rooms/rooms.gateway.ts --items all --type method,function
ast-grep outline backend/src/rooms/rooms-lobby.service.ts --items all --type method,function
ast-grep outline backend/src/rooms/rooms.service.ts --items all --type method,function
ast-grep outline frontend/src/pages/LobbyPage.tsx --items all --type function
ast-grep outline shared/game-map.ts --items all --type function

echo '--- rooms.gateway relevant ranges ---'
nl -ba backend/src/rooms/rooms.gateway.ts | sed -n '320,405p'

echo '--- shared package and build configuration ---'
cat -n shared/package.json
printf '\nPackage manifests and TypeScript configs:\n'
fd -a -t f '^(package\.json|tsconfig.*\.json|nest-cli\.json)$' . | sort | while IFS= read -r f; do
  echo "### $f"
  sed -n '1,240p' "$f"
done

echo '--- nitpick current implementations ---'
cat -n backend/src/rooms/rooms-lobby.service.ts | sed -n '1,90p'
cat -n backend/src/rooms/rooms.service.ts | sed -n '240,295p'
cat -n frontend/src/pages/LobbyPage.tsx | sed -n '1,85p'
cat -n shared/game-map.ts | sed -n '1,100p'

echo '--- targeted searches ---'
rg -n -C2 '\brequireUserId\b|\brunRollbacks\b|\.leave\s*\(' backend/src/rooms/rooms.gateway.ts
rg -n -C2 '\(gateway as any\)\.logger|gateway\[['"'"'logger'"'"'\]' backend/src/rooms/rooms.gateway.spec.ts
rg -n -C2 '\bbuildParticipant\b|participants:\s*\[' backend/src/rooms/rooms.service.spec.ts

Length of output: 2294


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- commit and working tree ---'
git rev-parse --short HEAD
git status --short

echo '--- rooms gateway: rollback, user ID, leave handling ---'
sed -n '1,460p' backend/src/rooms/rooms.gateway.ts

echo '--- shared package manifest ---'
cat shared/package.json

echo '--- backend package and build settings ---'
cat backend/package.json
if [ -f backend/tsconfig.build.json ]; then cat backend/tsconfig.build.json; fi
if [ -f backend/tsconfig.json ]; then cat backend/tsconfig.json; fi
if [ -f backend/nest-cli.json ]; then cat backend/nest-cli.json; fi
if [ -f nest-cli.json ]; then cat nest-cli.json; fi

echo '--- shared imports and module-resolution configuration ---'
rg -n -C3 '`@ft_transcendence/shared/`(game-map|game-constants)|paths|rootDir|outDir|assets|webpack' \
  backend frontend shared \
  -g 'package.json' -g 'tsconfig*.json' -g 'nest-cli.json' -g '*.ts' -g '*.js' \
  | head -n 500

echo '--- lobby service ---'
cat backend/src/rooms/rooms-lobby.service.ts

echo '--- rooms service joinability ---'
sed -n '235,300p' backend/src/rooms/rooms.service.ts

echo '--- lobby page ---'
sed -n '1,100p' frontend/src/pages/LobbyPage.tsx

echo '--- shared game map ---'
cat shared/game-map.ts

echo '--- gateway-spec logger access ---'
rg -n -C2 '\(gateway as any\)\.logger|gateway\[['"'"'logger'"'"'\]' backend/src/rooms/rooms.gateway.spec.ts || true

echo '--- service-spec participant builders/literals in relevant tests ---'
rg -n -C3 '\bbuildParticipant\b|canSubscribe|evictIfWaiting|participants:' backend/src/rooms/rooms.service.spec.ts

Length of output: 38996


@taka2162 現在の Requested Changes は、次の2件です。したがって、現時点では approve できません。

  1. backend/src/rooms/rooms.gateway.ts の leaveCurrentRoomId

    • void client.leave(roomId) が残っています。
    • client.leave() が Promise を返して reject した場合、失敗が記録されません。
    • 同期戻り値と Promise 戻り値の両方を扱い、非同期失敗を logger に記録する必要があります。
  2. shared/package.json の ./game-constants と ./game-map の runtime export

    • 両方の default が .ts ソースを参照しています。
    • 本番起動は node dist/main.js です。
    • backend/tsconfig.build.json は src/**/*.ts だけをビルド対象にするため、shared の TypeScript ソースは backend の dist に出力されません。
    • runtime export を JavaScript 出力へ向け、該当出力が本番成果物に含まれる構成にする必要があります。

確認できた Nitpick は対処済みです。getLobbyRooms の簡素化、JoinRejectionReason、getUserId、非破壊的な rollback 反転、useMemo、buildParticipant、START_POSITIONS の読み取り専用化を確認しました。

You are interacting with an AI system.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="cimura/ft_transcendence"
pr="206"

echo "== PR metadata =="
gh pr view "$pr" --repo "$repo" --json number,title,state,isDraft,mergeable,reviewDecision,headRefName,baseRefName \
  --jq '{number,title,state,isDraft,mergeable,reviewDecision,headRefName,baseRefName}'

echo "== Reviews =="
gh api "repos/$repo/pulls/$pr/reviews?per_page=100" \
  --jq '.[] | {id,user:.user.login,state,submitted_at,body}'

echo "== CodeRabbit review comments =="
gh api "repos/$repo/pulls/$pr/comments?per_page=100" \
  --jq '.[] | select(.user.login | test("coderabbit"; "i")) | {id,path,line,start_line,created_at,body}'

echo "== Changed files =="
gh pr view "$pr" --repo "$repo" --json files \
  --jq '.files[] | {path,additions,deletions}'

Length of output: 53461


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Recent commits on PR `#206` =="
gh pr view 206 --repo cimura/ft_transcendence --json commits \
  --jq '.commits[] | {oid: .oid[0:12], messageHeadline, authoredDate}'

echo "== CI checks =="
gh pr checks 206 --repo cimura/ft_transcendence --json name,state,conclusion,detailsUrl \
  --jq '.[] | {name,state,conclusion,detailsUrl}' || true

echo "== Structure of actionable files =="
ast-grep outline backend/src/rooms/rooms.gateway.ts --items all --type class,method,function --view expanded
ast-grep outline shared/package.json --view expanded || true

echo "== Room leave and rollback implementation =="
rg -n -A14 -B10 'client\.leave\s*\(|runRollbacks\s*\(' backend/src/rooms/rooms.gateway.ts

echo "== Shared exports and build/runtime configuration =="
cat -n shared/package.json
printf '\n-- backend package scripts/dependencies --\n'
python3 - <<'PY'
import json
from pathlib import Path
for filename in ("backend/package.json", "package.json"):
    path = Path(filename)
    if path.exists():
        doc = json.loads(path.read_text())
        print(f"[{filename}]")
        for section in ("scripts", "dependencies", "devDependencies"):
            if section in doc:
                print(section + ":")
                for name, value in doc[section].items():
                    if section == "scripts" or "shared" in name or name in {"typescript", "ts-node", "tsx"}:
                        print(f"  {name}: {value}")
PY
printf '\n-- TypeScript and build configuration candidates --\n'
fd -a -t f -E node_modules -E dist '^(tsconfig.*\.json|nest-cli\.json|Dockerfile.*)$' . | sort

Length of output: 10811


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Current check states =="
gh pr checks 206 --repo cimura/ft_transcendence --json name,state,workflow,description,link \
  --jq '.[] | {name,state,workflow,description,link}' || true

echo "== Backend compiler configuration =="
for file in backend/tsconfig.json backend/tsconfig.build.json backend/nest-cli.json docker/backend/Dockerfile; do
  if [ -f "$file" ]; then
    echo "--- $file ---"
    cat -n "$file"
  fi
done

echo "== Workspace installation and shared-package references =="
rg -n -C3 --glob 'package.json' --glob 'package-lock.json' \
  '"workspaces"|`@ft_transcendence/shared`|file:.*shared|workspace:' .

echo "== Imported runtime shared modules =="
rg -n -C2 \
  "`@ft_transcendence/shared/`(game-map|game-constants)" \
  backend/src frontend/src

Length of output: 12282


@taka2162 確認結果です。CI は成功していますが、2件の Requested Changes は未対応です。そのため、この PR はまだ承認できません。

  1. backend/src/rooms/rooms.gateway.ts Line 379
    void client.leave(roomId) が残っています。Socket#leave() は Promise<void> | void を返します。Promise が reject した場合のログ処理または待機処理が必要です。

  2. shared/package.json Lines 24-30
    ./game-constants と ./game-map の default が .ts を指しています。
    backend/tsconfig.build.json は src/**/*.ts だけをビルド対象にします。rootDir も ./src です。したがって、shared/game-constants.ts と shared/game-map.ts はバックエンドの dist に生成されません。node dist/main.js はこれらの runtime import を解決できません。

Backend CI は lint、format、test を通過しています。ただし、この本番起動時のモジュール解決は検証していません。

You are interacting with an AI system.

Base automatically changed from refactor/game-constants-to-shared to develop August 1, 2026 08:35
@rt6500
rt6500 force-pushed the feature/map-preview-on-room branch from ae68dde to 764fe9f Compare August 1, 2026 08:35

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@shared/package.json`:
- Around line 24-30: Update the package exports for ./game-constants and
./game-map so their default runtime targets point to the compiled JavaScript
files produced by the build, not the TypeScript sources. Change the types
targets to the corresponding generated .d.ts files, preserving the existing
export entries and names.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e1ba02c8-9514-40fe-948d-967716a8a991

📥 Commits

Reviewing files that changed from the base of the PR and between a7cc480 and 074c662.

📒 Files selected for processing (13)
  • backend/src/game/game.service.ts
  • backend/src/game/logic/session/player.logic.ts
  • backend/src/rooms/rooms-lobby.service.ts
  • backend/src/rooms/rooms.gateway.spec.ts
  • backend/src/rooms/rooms.gateway.ts
  • backend/src/rooms/rooms.service.spec.ts
  • backend/src/rooms/rooms.service.ts
  • frontend/src/components/game/preview/BombermanRenderer.ts
  • frontend/src/components/game/preview/GameMapPreview.tsx
  • frontend/src/components/game/preview/map-mock.ts
  • frontend/src/pages/LobbyPage.tsx
  • shared/game-map.ts
  • shared/package.json
💤 Files with no reviewable changes (1)
  • frontend/src/components/game/preview/map-mock.ts
🚧 Files skipped from review as they are similar to previous changes (9)
  • frontend/src/pages/LobbyPage.tsx
  • backend/src/rooms/rooms.service.spec.ts
  • backend/src/game/game.service.ts
  • frontend/src/components/game/preview/GameMapPreview.tsx
  • backend/src/game/logic/session/player.logic.ts
  • shared/game-map.ts
  • frontend/src/components/game/preview/BombermanRenderer.ts
  • backend/src/rooms/rooms.gateway.spec.ts
  • backend/src/rooms/rooms.gateway.ts

Comment thread shared/package.json Outdated

@rt6500 rt6500 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

より本格的になったと思います。ありがとうございます。Jsonファイル関連の指摘だけ直してもらえたらMergeしてください。

…anscendence into feature/map-preview-on-room

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/package.json`:
- Line 15: Update the start:dev script in package.json so the shared package
build runs in continuous tsc watch mode while nest start --watch runs
concurrently. Preserve the existing Prisma generation step and ensure both
watchers start together rather than performing a one-time shared build.

In `@shared/package.json`:
- Around line 29-35: Update the package export entries for ./game-map and
./game-constants so their types fields reference the generated
dist/game-map.d.ts and dist/game-constants.d.ts declarations instead of source
.ts files. Keep the existing browser and default mappings, and ensure the
distribution includes the corresponding dist/*.js files used by default.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f85472ff-4af7-4373-8deb-6e97a7c486ae

📥 Commits

Reviewing files that changed from the base of the PR and between 074c662 and c47fd4a.

📒 Files selected for processing (5)
  • backend/package.json
  • backend/src/rooms/rooms.gateway.spec.ts
  • backend/src/rooms/rooms.gateway.ts
  • shared/package.json
  • shared/tsconfig.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/src/rooms/rooms.gateway.ts

Comment thread backend/package.json
Comment thread shared/package.json
@taka2162
taka2162 merged commit 76b1194 into develop Aug 1, 2026
3 checks passed
@taka2162
taka2162 deleted the feature/map-preview-on-room branch August 1, 2026 15:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Room画面の Map Preview が未実装

2 participants