diff --git a/apps/server/src/domains/game/entities/bomb/BombRoomStateStore.ts b/apps/server/src/domains/game/entities/bomb/BombRoomStateStore.ts index d217a95..b0a7aaf 100644 --- a/apps/server/src/domains/game/entities/bomb/BombRoomStateStore.ts +++ b/apps/server/src/domains/game/entities/bomb/BombRoomStateStore.ts @@ -2,7 +2,8 @@ * BombRoomStateStore * ルーム単位の爆弾重複排除状態と採番状態を管理する */ -import { config } from "@repo/shared"; +import { issueServerBombId } from "./bombIdentity.js"; +import { shouldBroadcastBombPlaced } from "./bombDedup.js"; /** ルーム単位の爆弾重複排除状態と採番状態を保持するストア */ export class BombRoomStateStore { @@ -11,28 +12,20 @@ /** 爆弾設置イベントを配信すべきか判定し,配信時は重複排除状態を更新する */ public shouldBroadcastBombPlaced(dedupeKey: string, nowMs: number): boolean { - this.cleanupExpiredBombDedup(nowMs); - - if (this.bombDedupTable.has(dedupeKey)) { - return false; - } - - const ttlMs = config.GAME_CONFIG.BOMB_FUSE_MS + config.GAME_CONFIG.BOMB_DEDUP_EXTRA_TTL_MS; - this.bombDedupTable.set(dedupeKey, nowMs + ttlMs); - return true; + return shouldBroadcastBombPlaced({ + dedupTable: this.bombDedupTable, + dedupeKey, + nowMs, + }); } /** セッション単位の連番からサーバー採番の爆弾IDを生成する */ public issueServerBombId(roomId: string): string { - this.bombSerial += 1; - return `${roomId}:${this.bombSerial}`; - } - - private cleanupExpiredBombDedup(nowMs: number): void { - this.bombDedupTable.forEach((expiresAtMs, dedupeKey) => { - if (expiresAtMs <= nowMs) { - this.bombDedupTable.delete(dedupeKey); - } + const { bombId, nextSerial } = issueServerBombId({ + roomId, + currentSerial: this.bombSerial, }); + this.bombSerial = nextSerial; + return bombId; } } diff --git a/apps/server/src/domains/game/entities/bomb/bombDedup.ts b/apps/server/src/domains/game/entities/bomb/bombDedup.ts new file mode 100644 index 0000000..ff57c39 --- /dev/null +++ b/apps/server/src/domains/game/entities/bomb/bombDedup.ts @@ -0,0 +1,40 @@ +/** + * bombDedup + * 爆弾設置要求の重複排除テーブル操作を提供する + */ +import { config } from "@repo/shared"; + +type ShouldBroadcastBombPlacedParams = { + dedupTable: Map; + dedupeKey: string; + nowMs: number; +}; + +/** 重複排除テーブルの期限切れエントリを削除する */ +export const cleanupExpiredBombDedup = ( + dedupTable: Map, + nowMs: number +): void => { + dedupTable.forEach((expiresAtMs, key) => { + if (expiresAtMs <= nowMs) { + dedupTable.delete(key); + } + }); +}; + +/** 爆弾設置イベントを配信すべきか判定し,配信時は重複排除状態を更新する */ +export const shouldBroadcastBombPlaced = ({ + dedupTable, + dedupeKey, + nowMs, +}: ShouldBroadcastBombPlacedParams): boolean => { + cleanupExpiredBombDedup(dedupTable, nowMs); + + if (dedupTable.has(dedupeKey)) { + return false; + } + + const ttlMs = config.GAME_CONFIG.BOMB_FUSE_MS + config.GAME_CONFIG.BOMB_DEDUP_EXTRA_TTL_MS; + dedupTable.set(dedupeKey, nowMs + ttlMs); + return true; +}; diff --git a/apps/server/src/domains/game/entities/bomb/bombIdentity.ts b/apps/server/src/domains/game/entities/bomb/bombIdentity.ts new file mode 100644 index 0000000..634cf62 --- /dev/null +++ b/apps/server/src/domains/game/entities/bomb/bombIdentity.ts @@ -0,0 +1,21 @@ +/** + * bombIdentity + * 爆弾ID採番ロジックを提供する + */ + +type IssueServerBombIdParams = { + roomId: string; + currentSerial: number; +}; + +/** 次のサーバー採番爆弾IDと更新後シリアルを返す */ +export const issueServerBombId = ({ + roomId, + currentSerial, +}: IssueServerBombIdParams): { bombId: string; nextSerial: number } => { + const nextSerial = currentSerial + 1; + return { + bombId: `${roomId}:${nextSerial}`, + nextSerial, + }; +};