Newer
Older
PixelPaintWar / apps / server / src / domains / room / application / services / RoomTeamService.ts
/**
 * RoomTeamService
 * プレイヤーのチーム選択処理(上限チェックを含む)を提供する
 */
import { domain } from "@repo/shared";
import type { SelectTeamResult } from "../ports/roomUseCasePorts";
import type { RoomQueryService } from "./RoomQueryService";

/** プレイヤーのチーム選択処理を担うサービス */
export class RoomTeamService {
  constructor(
    private roomQueryService: RoomQueryService,
  ) {}

  public selectTeam(
    playerId: string,
    preferredTeamId: number | null,
  ): SelectTeamResult {
    const room = this.roomQueryService.getRoomByPlayerId(playerId);
    if (!room || room.status !== domain.room.RoomPhase.WAITING) {
      return { status: "not_found" };
    }

    const member = room.players.find((p) => p.id === playerId);
    if (!member) {
      return { status: "not_found" };
    }

    // チーム指定がある場合は人数上限を確認する(上限 = ゲーム人数 / 4)
    if (preferredTeamId !== null) {
      const maxPerTeam = Math.floor(
        (room.targetPlayerCount ?? room.maxPlayers) / 4,
      );
      const currentCount = room.players.filter(
        (p) => p.preferredTeamId === preferredTeamId && p.id !== playerId,
      ).length;
      if (currentCount >= maxPerTeam) {
        return { status: "team_full", teamId: preferredTeamId };
      }
    }

    member.preferredTeamId = preferredTeamId;
    return { status: "ok", room };
  }
}