regionals
This commit is contained in:
103
src/features/tournaments/utils/bracket-generator.ts
Normal file
103
src/features/tournaments/utils/bracket-generator.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
export interface BracketMatch {
|
||||
lid: number;
|
||||
round: number;
|
||||
order: number | null;
|
||||
bye: boolean;
|
||||
home_seed?: number;
|
||||
away_seed?: number;
|
||||
home_from_lid: number | null;
|
||||
home_from_loser: boolean;
|
||||
away_from_lid: number | null;
|
||||
away_from_loser: boolean;
|
||||
reset: boolean;
|
||||
}
|
||||
|
||||
export interface BracketTemplate {
|
||||
winners: BracketMatch[][];
|
||||
losers: BracketMatch[][];
|
||||
}
|
||||
|
||||
export function generateSingleEliminationBracket(teamCount: number): BracketTemplate {
|
||||
if (teamCount < 2) {
|
||||
throw new Error("Need at least 2 teams for a bracket");
|
||||
}
|
||||
|
||||
const nextPowerOf2 = Math.pow(2, Math.ceil(Math.log2(teamCount)));
|
||||
const totalRounds = Math.log2(nextPowerOf2);
|
||||
|
||||
const byesNeeded = nextPowerOf2 - teamCount;
|
||||
const firstRoundMatches = Math.floor(teamCount / 2);
|
||||
|
||||
const winners: BracketMatch[][] = [];
|
||||
let currentLid = 0;
|
||||
let currentOrder = 1;
|
||||
|
||||
for (let round = 0; round < totalRounds; round++) {
|
||||
const roundMatches: BracketMatch[] = [];
|
||||
const matchesInRound = Math.pow(2, totalRounds - round - 1);
|
||||
|
||||
for (let matchIndex = 0; matchIndex < matchesInRound; matchIndex++) {
|
||||
const match: BracketMatch = {
|
||||
lid: currentLid++,
|
||||
round,
|
||||
order: currentOrder++,
|
||||
bye: false,
|
||||
home_from_lid: null,
|
||||
home_from_loser: false,
|
||||
away_from_lid: null,
|
||||
away_from_loser: false,
|
||||
reset: false,
|
||||
};
|
||||
|
||||
if (round === 0) {
|
||||
const homePosition = matchIndex * 2;
|
||||
const awayPosition = matchIndex * 2 + 1;
|
||||
|
||||
if (homePosition < teamCount && awayPosition < teamCount) {
|
||||
match.home_seed = homePosition + 1;
|
||||
match.away_seed = awayPosition + 1;
|
||||
} else if (homePosition < teamCount) {
|
||||
match.home_seed = homePosition + 1;
|
||||
match.bye = true;
|
||||
} else {
|
||||
match.bye = true;
|
||||
}
|
||||
} else {
|
||||
const prevRound = winners[round - 1];
|
||||
const homeFeedIndex = matchIndex * 2;
|
||||
const awayFeedIndex = matchIndex * 2 + 1;
|
||||
|
||||
if (homeFeedIndex < prevRound.length) {
|
||||
match.home_from_lid = prevRound[homeFeedIndex].lid;
|
||||
}
|
||||
if (awayFeedIndex < prevRound.length) {
|
||||
match.away_from_lid = prevRound[awayFeedIndex].lid;
|
||||
}
|
||||
}
|
||||
|
||||
roundMatches.push(match);
|
||||
}
|
||||
|
||||
winners.push(roundMatches);
|
||||
}
|
||||
|
||||
return {
|
||||
winners,
|
||||
losers: [],
|
||||
};
|
||||
}
|
||||
|
||||
export function generateGroupMismatchSeeding(
|
||||
numGroups: number,
|
||||
teamsPerGroup: number
|
||||
): number[] {
|
||||
const seeding: number[] = [];
|
||||
|
||||
for (let rank = 0; rank < teamsPerGroup; rank++) {
|
||||
for (let group = 0; group < numGroups; group++) {
|
||||
seeding.push(group * teamsPerGroup + rank);
|
||||
}
|
||||
}
|
||||
|
||||
return seeding;
|
||||
}
|
||||
Reference in New Issue
Block a user