import { database } from "~/database/context"; import * as schema from "~/database/schema"; import { eq, and, notInArray, desc } from "drizzle-orm"; import { getTeamQueue } from "./draft-queue"; import { isParticipantDrafted } from "./draft-pick"; /** * Auto-pick for a team when their timer runs out * 1. Check queue - pick first item if available * 2. If queue empty, pick highest EV participant not drafted */ export async function autoPickForTeam(seasonId: string, teamId: string) { // Check queue first const queue = await getTeamQueue(teamId); if (queue.length > 0) { // Pick first item from queue const firstInQueue = queue[0]; // Verify participant is not already drafted const isDrafted = await isParticipantDrafted(seasonId, firstInQueue.participantId); if (!isDrafted) { return firstInQueue.participantId; } // If first item was drafted, try next items in queue for (const item of queue.slice(1)) { const isDrafted = await isParticipantDrafted(seasonId, item.participantId); if (!isDrafted) { return item.participantId; } } } // Queue is empty or all queued players drafted - pick highest EV available return await getTopAvailableParticipant(seasonId); } /** * Get the highest EV participant that hasn't been drafted yet */ export async function getTopAvailableParticipant(seasonId: string) { const db = database(); // Get all drafted participant IDs const draftedPicks = await db .select({ participantId: schema.draftPicks.participantId }) .from(schema.draftPicks) .where(eq(schema.draftPicks.seasonId, seasonId)); const draftedIds = draftedPicks.map((p: { participantId: string }) => p.participantId); // Get all participants from season sports const seasonSportsData = await db .select({ sportsSeasonId: schema.seasonSports.sportsSeasonId }) .from(schema.seasonSports) .where(eq(schema.seasonSports.seasonId, seasonId)); const sportsSeasonIds = seasonSportsData.map((s: { sportsSeasonId: string }) => s.sportsSeasonId); if (sportsSeasonIds.length === 0) { return null; } // Get top available participant by EV let query = db .select() .from(schema.participants) .where(eq(schema.participants.sportsSeasonId, sportsSeasonIds[0])) .orderBy(desc(schema.participants.expectedValue), schema.participants.name); // Filter out drafted participants if any exist if (draftedIds.length > 0) { query = db .select() .from(schema.participants) .where( and( eq(schema.participants.sportsSeasonId, sportsSeasonIds[0]), notInArray(schema.participants.id, draftedIds) ) ) .orderBy(desc(schema.participants.expectedValue), schema.participants.name); } // Handle multiple sports seasons if (sportsSeasonIds.length > 1) { // For simplicity, we'll query all and sort in memory // In production, might want to optimize this const allParticipants = []; for (const sportsSeasonId of sportsSeasonIds) { let participantQuery = db .select() .from(schema.participants) .where(eq(schema.participants.sportsSeasonId, sportsSeasonId)); if (draftedIds.length > 0) { participantQuery = db .select() .from(schema.participants) .where( and( eq(schema.participants.sportsSeasonId, sportsSeasonId), notInArray(schema.participants.id, draftedIds) ) ); } const seasonParticipants = await participantQuery; allParticipants.push(...seasonParticipants); } // Sort by EV desc, then name allParticipants.sort((a, b) => { if (b.expectedValue !== a.expectedValue) { return b.expectedValue - a.expectedValue; } return a.name.localeCompare(b.name); }); return allParticipants[0]?.id || null; } const [topParticipant] = await query; return topParticipant?.id || null; } /** * Calculate the current pick based on draft order and round */ export function calculatePickInfo( pickNumber: number, teamCount: number ): { round: number; pickInRound: number; teamIndex: number } { const round = Math.ceil(pickNumber / teamCount); const pickInRound = ((pickNumber - 1) % teamCount) + 1; // Snake draft: odd rounds go forward, even rounds go backward const isOddRound = round % 2 === 1; const teamIndex = isOddRound ? pickInRound - 1 : teamCount - pickInRound; return { round, pickInRound, teamIndex }; } /** * Get the team ID for a given pick number based on draft order */ export function getTeamForPick( pickNumber: number, draftOrder: { teamId: string; draftOrder: number }[] ): string | null { const sortedOrder = [...draftOrder].sort((a, b) => a.draftOrder - b.draftOrder); const teamCount = sortedOrder.length; if (teamCount === 0) return null; const { teamIndex } = calculatePickInfo(pickNumber, teamCount); return sortedOrder[teamIndex]?.teamId || null; }