ready for regionals
CI/CD Pipeline / Build and Push App Docker Image (push) Successful in 2m46s
CI/CD Pipeline / Build and Push PocketBase Docker Image (push) Successful in 8s
CI/CD Pipeline / Deploy to Kubernetes (push) Successful in 44s

This commit is contained in:
yohlo
2026-03-07 01:22:21 -06:00
parent 569ea8833b
commit e67f6b073c
9 changed files with 353 additions and 95 deletions
+111 -6
View File
@@ -270,15 +270,120 @@ async function populateKnockoutBracketInternal(tournamentId: string, groupConfig
const orderedTeamIds: string[] = [];
const maxRank = groupConfig.advance_per_group;
const numGroups = groupConfig.num_groups;
for (let rank = 1; rank <= maxRank; rank++) {
const teamsAtRank = qualifiedTeams
.filter(t => t.rank === rank)
.sort((a, b) => a.groupOrder - b.groupOrder);
orderedTeamIds.push(...teamsAtRank.map(t => t.teamId));
const teamsByGroup: string[][] = [];
for (let g = 0; g < numGroups; g++) {
teamsByGroup[g] = [];
}
logger.info('Ordered team IDs', { orderedTeamIds });
for (const qualified of qualifiedTeams) {
teamsByGroup[qualified.groupOrder][qualified.rank - 1] = qualified.teamId;
}
const totalQualifiedTeams = numGroups * maxRank;
for (let i = 0; i < totalQualifiedTeams / 2; i++) {
const group1 = i % numGroups;
const rankIndex1 = Math.floor(i / numGroups);
const group2 = (i + 1) % numGroups;
const rankIndex2 = maxRank - 1 - rankIndex1;
const team1 = teamsByGroup[group1]?.[rankIndex1];
const team2 = teamsByGroup[group2]?.[rankIndex2];
if (team1) orderedTeamIds.push(team1);
if (team2) orderedTeamIds.push(team2);
}
const knockoutTeamCount = orderedTeamIds.length;
const nextPowerOf2 = Math.pow(2, Math.ceil(Math.log2(knockoutTeamCount)));
const wildcardsNeeded = nextPowerOf2 - knockoutTeamCount;
if (wildcardsNeeded > 0) {
logger.info('Wildcards needed', { knockoutTeamCount, nextPowerOf2, wildcardsNeeded });
const allNonQualifiedTeams: Array<{ teamId: string; wins: number; losses: number; cups_for: number; cups_against: number; cup_differential: number }> = [];
const qualifiedTeamIds = new Set(qualifiedTeams.map(t => t.teamId));
for (const group of groups) {
const groupMatches = await pbAdmin.getMatchesByGroup(group.id);
const completedMatches = groupMatches.filter(m => m.status === "ended");
const standings = new Map<string, { teamId: string; wins: number; losses: number; cups_for: number; cups_against: number; cup_differential: number }>();
for (const team of group.teams || []) {
const teamId = typeof team === 'string' ? team : team.id;
if (qualifiedTeamIds.has(teamId)) continue;
standings.set(teamId, {
teamId,
wins: 0,
losses: 0,
cups_for: 0,
cups_against: 0,
cup_differential: 0,
});
}
for (const match of completedMatches) {
if (!match.home || !match.away) continue;
const homeStanding = standings.get(match.home.id);
const awayStanding = standings.get(match.away.id);
if (homeStanding) {
homeStanding.cups_for += match.home_cups;
homeStanding.cups_against += match.away_cups;
homeStanding.cup_differential = homeStanding.cups_for - homeStanding.cups_against;
if (match.home_cups > match.away_cups) {
homeStanding.wins++;
} else {
homeStanding.losses++;
}
}
if (awayStanding) {
awayStanding.cups_for += match.away_cups;
awayStanding.cups_against += match.home_cups;
awayStanding.cup_differential = awayStanding.cups_for - awayStanding.cups_against;
if (match.away_cups > match.home_cups) {
awayStanding.wins++;
} else {
awayStanding.losses++;
}
}
}
allNonQualifiedTeams.push(...Array.from(standings.values()));
}
allNonQualifiedTeams.sort((a, b) => {
if (b.wins !== a.wins) return b.wins - a.wins;
if (b.cup_differential !== a.cup_differential) return b.cup_differential - a.cup_differential;
if (b.cups_for !== a.cups_for) return b.cups_for - a.cups_for;
return a.teamId.localeCompare(b.teamId);
});
const wildcardTeams = allNonQualifiedTeams.slice(0, wildcardsNeeded);
const wildcardTeamIds = wildcardTeams.map(t => t.teamId);
orderedTeamIds.push(...wildcardTeamIds);
logger.info('Added wildcard teams', {
wildcardTeams: wildcardTeams.map(t => ({
teamId: t.teamId,
wins: t.wins,
cupDiff: t.cup_differential,
cupsFor: t.cups_for
}))
});
}
logger.info('Ordered team IDs (with wildcards)', { orderedTeamIds, totalTeams: orderedTeamIds.length });
const tournament = await pbAdmin.getTournament(tournamentId);
const knockoutMatches = (tournament.matches || [])