refactor(lib): update schedule and team generators to use player pairings
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
export interface MatchupPairing {
|
export interface MatchupPairing {
|
||||||
team1Id: number
|
player1P1Id: number
|
||||||
team2Id: number
|
player1P2Id: number
|
||||||
|
player2P1Id: number
|
||||||
|
player2P2Id: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RoundSchedule {
|
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 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).
|
* 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
|
* @returns Array of rounds, each containing matchup pairings
|
||||||
*/
|
*/
|
||||||
export function generateRoundRobin(teamIds: number[]): RoundSchedule[] {
|
export function generateRoundRobin(
|
||||||
if (teamIds.length < 2) {
|
teamPairings: { player1Id: number; player2Id: number }[]
|
||||||
|
): RoundSchedule[] {
|
||||||
|
if (teamPairings.length < 2) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use circle method: fix first team, rotate the rest
|
// Use circle method: fix first team, rotate the rest
|
||||||
// If odd number of teams, add a sentinel for byes
|
// If odd number of teams, add a sentinel for byes
|
||||||
const hasOddTeams = teamIds.length % 2 !== 0
|
const hasOddTeams = teamPairings.length % 2 !== 0
|
||||||
const workingTeams = hasOddTeams ? [...teamIds, -1] : [...teamIds]
|
const workingTeams = hasOddTeams
|
||||||
|
? [...teamPairings, { player1Id: -1, player2Id: -1 }]
|
||||||
|
: [...teamPairings]
|
||||||
const n = workingTeams.length
|
const n = workingTeams.length
|
||||||
const numRounds = n - 1
|
const numRounds = n - 1
|
||||||
const matchupsPerRound = n / 2
|
const matchupsPerRound = n / 2
|
||||||
@@ -40,12 +46,17 @@ export function generateRoundRobin(teamIds: number[]): RoundSchedule[] {
|
|||||||
const team1Idx = i
|
const team1Idx = i
|
||||||
const team2Idx = n - 1 - i
|
const team2Idx = n - 1 - i
|
||||||
|
|
||||||
const team1Id = workingTeams[team1Idx]
|
const team1 = workingTeams[team1Idx]
|
||||||
const team2Id = workingTeams[team2Idx]
|
const team2 = workingTeams[team2Idx]
|
||||||
|
|
||||||
// Skip bye matchups (where either team is the sentinel -1)
|
// Skip bye matchups (where either team is the sentinel)
|
||||||
if (team1Id !== -1 && team2Id !== -1) {
|
if (team1.player1Id !== -1 && team2.player1Id !== -1) {
|
||||||
matchups.push({ team1Id, team2Id })
|
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
|
valid: boolean
|
||||||
error?: string
|
error?: string
|
||||||
} {
|
} {
|
||||||
if (teamIds.length < 2) {
|
if (teamPairings.length < 2) {
|
||||||
return { valid: false, error: "At least 2 teams are required to generate a schedule" }
|
return { valid: false, error: "At least 2 teams are required to generate a schedule" }
|
||||||
}
|
}
|
||||||
|
|
||||||
const uniqueIds = new Set(teamIds)
|
// Check for duplicate teams
|
||||||
if (uniqueIds.size !== teamIds.length) {
|
const teamKeys = teamPairings.map(
|
||||||
return { valid: false, error: "Duplicate team IDs found" }
|
(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 }
|
return { valid: true }
|
||||||
|
|||||||
Reference in New Issue
Block a user