diff --git a/src/lib/schedule-generator.ts b/src/lib/schedule-generator.ts index 2db7481..48dcd0a 100644 --- a/src/lib/schedule-generator.ts +++ b/src/lib/schedule-generator.ts @@ -1,6 +1,8 @@ export interface MatchupPairing { - team1Id: number - team2Id: number + player1P1Id: number + player1P2Id: number + player2P1Id: number + player2P2Id: number } export interface RoundSchedule { @@ -15,18 +17,22 @@ export interface RoundSchedule { * team exactly once. If N is odd, a "bye" is added internally so one * team sits out each round (the bye matchup is excluded from output). * - * @param teamIds - Array of team IDs to schedule + * @param teamPairings - Array of player pairings (each with 2 player IDs) * @returns Array of rounds, each containing matchup pairings */ -export function generateRoundRobin(teamIds: number[]): RoundSchedule[] { - if (teamIds.length < 2) { +export function generateRoundRobin( + teamPairings: { player1Id: number; player2Id: number }[] +): RoundSchedule[] { + if (teamPairings.length < 2) { return [] } // Use circle method: fix first team, rotate the rest // If odd number of teams, add a sentinel for byes - const hasOddTeams = teamIds.length % 2 !== 0 - const workingTeams = hasOddTeams ? [...teamIds, -1] : [...teamIds] + const hasOddTeams = teamPairings.length % 2 !== 0 + const workingTeams = hasOddTeams + ? [...teamPairings, { player1Id: -1, player2Id: -1 }] + : [...teamPairings] const n = workingTeams.length const numRounds = n - 1 const matchupsPerRound = n / 2 @@ -40,12 +46,17 @@ export function generateRoundRobin(teamIds: number[]): RoundSchedule[] { const team1Idx = i const team2Idx = n - 1 - i - const team1Id = workingTeams[team1Idx] - const team2Id = workingTeams[team2Idx] + const team1 = workingTeams[team1Idx] + const team2 = workingTeams[team2Idx] - // Skip bye matchups (where either team is the sentinel -1) - if (team1Id !== -1 && team2Id !== -1) { - matchups.push({ team1Id, team2Id }) + // Skip bye matchups (where either team is the sentinel) + if (team1.player1Id !== -1 && team2.player1Id !== -1) { + matchups.push({ + player1P1Id: team1.player1Id, + player1P2Id: team1.player2Id, + player2P1Id: team2.player1Id, + player2P2Id: team2.player2Id, + }) } } @@ -61,19 +72,25 @@ export function generateRoundRobin(teamIds: number[]): RoundSchedule[] { } /** - * Validate that a set of team IDs can be scheduled. + * Validate that a set of player pairings can be scheduled. */ -export function validateScheduleInput(teamIds: number[]): { +export function validateScheduleInput( + teamPairings: { player1Id: number; player2Id: number }[] +): { valid: boolean error?: string } { - if (teamIds.length < 2) { + if (teamPairings.length < 2) { return { valid: false, error: "At least 2 teams are required to generate a schedule" } } - const uniqueIds = new Set(teamIds) - if (uniqueIds.size !== teamIds.length) { - return { valid: false, error: "Duplicate team IDs found" } + // Check for duplicate teams + const teamKeys = teamPairings.map( + (t) => [t.player1Id, t.player2Id].sort().join('-') + ) + const uniqueKeys = new Set(teamKeys) + if (uniqueKeys.size !== teamPairings.length) { + return { valid: false, error: "Duplicate team pairings found" } } return { valid: true }