All files / web/src/lib/arcade player-manager.ts

0% Statements 0/131
0% Branches 0/1
0% Functions 0/1
0% Lines 0/131

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132                                                                                                                                                                                                                                                                       
/**
 * Player manager for arcade rooms
 * Handles fetching and validating player participation in rooms
 */

import { and, eq } from 'drizzle-orm'
import { db, schema } from '@/db'
import type { Player } from '@/db/schema/players'

// Re-export ownership utilities for convenience
export {
  buildPlayerOwnershipMap,
  type PlayerOwnershipMap,
} from './player-ownership'

/**
 * Get all players for a user (regardless of isActive status)
 * @param userId - The database user.id (from getUserId())
 */
export async function getAllPlayers(userId: string): Promise<Player[]> {
  return await db.query.players.findMany({
    where: eq(schema.players.userId, userId),
    orderBy: schema.players.createdAt,
  })
}

/**
 * Get a user's active players (solo mode)
 * These are the players that will participate when the user joins a solo game
 * @param userId - The database user.id (from getUserId())
 */
export async function getActivePlayers(userId: string): Promise<Player[]> {
  return await db.query.players.findMany({
    where: and(eq(schema.players.userId, userId), eq(schema.players.isActive, true)),
    orderBy: schema.players.createdAt,
  })
}

/**
 * Get active players for all members in a room
 * Returns only players marked isActive=true from each room member
 * Returns a map of userId -> Player[]
 */
export async function getRoomActivePlayers(roomId: string): Promise<Map<string, Player[]>> {
  // Get all room members
  const members = await db.query.roomMembers.findMany({
    where: eq(schema.roomMembers.roomId, roomId),
  })

  // Fetch active players for each member (respects isActive flag)
  const playerMap = new Map<string, Player[]>()
  for (const member of members) {
    const players = await getActivePlayers(member.userId)
    playerMap.set(member.userId, players)
  }

  return playerMap
}

/**
 * Get all player IDs that should participate in a room game
 * Flattens the player lists from all room members
 */
export async function getRoomPlayerIds(roomId: string): Promise<string[]> {
  const playerMap = await getRoomActivePlayers(roomId)
  const allPlayers: string[] = []

  for (const players of playerMap.values()) {
    allPlayers.push(...players.map((p) => p.id))
  }

  return allPlayers
}

/**
 * Validate that a player ID belongs to a user who is a member of a room
 */
export async function validatePlayerInRoom(playerId: string, roomId: string): Promise<boolean> {
  // Get the player
  const player = await db.query.players.findFirst({
    where: eq(schema.players.id, playerId),
  })

  if (!player) return false

  // Check if the player's user is a member of the room
  const member = await db.query.roomMembers.findFirst({
    where: and(eq(schema.roomMembers.roomId, roomId), eq(schema.roomMembers.userId, player.userId)),
  })

  return !!member
}

/**
 * Get player details by ID
 */
export async function getPlayer(playerId: string): Promise<Player | undefined> {
  return await db.query.players.findFirst({
    where: eq(schema.players.id, playerId),
  })
}

/**
 * Get multiple players by IDs
 */
export async function getPlayers(playerIds: string[]): Promise<Player[]> {
  if (playerIds.length === 0) return []

  const players: Player[] = []
  for (const id of playerIds) {
    const player = await getPlayer(id)
    if (player) players.push(player)
  }

  return players
}

/**
 * Set a player's active status
 * @param playerId - The player ID
 * @param isActive - The new active status
 * @returns The updated player
 */
export async function setPlayerActiveStatus(
  playerId: string,
  isActive: boolean
): Promise<Player | undefined> {
  await db.update(schema.players).set({ isActive }).where(eq(schema.players.id, playerId))

  return await getPlayer(playerId)
}