cross mix knockout seeds
This commit is contained in:
@@ -37,16 +37,31 @@ export const MatchCard: React.FC<MatchCardProps> = ({
|
||||
if (!seed || !groupConfig) return undefined;
|
||||
|
||||
const groupNames = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'];
|
||||
const teamsPerRank = groupConfig.num_groups;
|
||||
const numGroups = groupConfig.num_groups;
|
||||
const advancePerGroup = groupConfig.advance_per_group;
|
||||
|
||||
const rankIndex = Math.floor((seed - 1) / teamsPerRank);
|
||||
const groupIndex = (seed - 1) % teamsPerRank;
|
||||
const pairIndex = Math.floor((seed - 1) / 2);
|
||||
const isFirstInPair = (seed - 1) % 2 === 0;
|
||||
|
||||
const rank = rankIndex + 1;
|
||||
const groupName = groupNames[groupIndex] || `${groupIndex + 1}`;
|
||||
const rankSuffix = rank === 1 ? '1st' : rank === 2 ? '2nd' : rank === 3 ? '3rd' : `${rank}th`;
|
||||
if (isFirstInPair) {
|
||||
const groupIndex = pairIndex % numGroups;
|
||||
const rankIndex = Math.floor(pairIndex / numGroups);
|
||||
|
||||
return `${groupName} ${rankSuffix}`;
|
||||
const rank = rankIndex + 1;
|
||||
const groupName = groupNames[groupIndex] || `${groupIndex + 1}`;
|
||||
const rankSuffix = rank === 1 ? '1st' : rank === 2 ? '2nd' : rank === 3 ? '3rd' : `${rank}th`;
|
||||
|
||||
return `${groupName} ${rankSuffix}`;
|
||||
} else {
|
||||
const groupIndex = (pairIndex + 1) % numGroups;
|
||||
const rankIndex = advancePerGroup - 1 - Math.floor(pairIndex / numGroups);
|
||||
|
||||
const rank = rankIndex + 1;
|
||||
const groupName = groupNames[groupIndex] || `${groupIndex + 1}`;
|
||||
const rankSuffix = rank === 1 ? '1st' : rank === 2 ? '2nd' : rank === 3 ? '3rd' : `${rank}th`;
|
||||
|
||||
return `${groupName} ${rankSuffix}`;
|
||||
}
|
||||
}, [groupConfig]);
|
||||
|
||||
const homeSlot = useMemo(
|
||||
|
||||
@@ -94,13 +94,23 @@ const SetupGroupStage: React.FC<SetupGroupStageProps> = ({
|
||||
const groupNames = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'];
|
||||
const seedLabels: Record<number, string> = {};
|
||||
|
||||
const totalTeams = selectedConfig.num_groups * selectedConfig.advance_per_group;
|
||||
let seedIndex = 1;
|
||||
for (let rank = 1; rank <= selectedConfig.advance_per_group; rank++) {
|
||||
for (let groupIdx = 0; groupIdx < selectedConfig.num_groups; groupIdx++) {
|
||||
const groupName = groupNames[groupIdx] || `Group ${groupIdx + 1}`;
|
||||
const rankSuffix = rank === 1 ? '1st' : rank === 2 ? '2nd' : rank === 3 ? '3rd' : `${rank}th`;
|
||||
seedLabels[seedIndex++] = `${groupName} ${rankSuffix}`;
|
||||
}
|
||||
|
||||
for (let i = 0; i < totalTeams / 2; i++) {
|
||||
const group1 = i % selectedConfig.num_groups;
|
||||
const rankIndex1 = Math.floor(i / selectedConfig.num_groups);
|
||||
const rank1 = rankIndex1 + 1;
|
||||
const groupName1 = groupNames[group1] || `Group ${group1 + 1}`;
|
||||
const rankSuffix1 = rank1 === 1 ? '1st' : rank1 === 2 ? '2nd' : rank1 === 3 ? '3rd' : `${rank1}th`;
|
||||
seedLabels[seedIndex++] = `${groupName1} ${rankSuffix1}`;
|
||||
|
||||
const group2 = (i + 1) % selectedConfig.num_groups;
|
||||
const rankIndex2 = selectedConfig.advance_per_group - 1 - rankIndex1;
|
||||
const rank2 = rankIndex2 + 1;
|
||||
const groupName2 = groupNames[group2] || `Group ${group2 + 1}`;
|
||||
const rankSuffix2 = rank2 === 1 ? '1st' : rank2 === 2 ? '2nd' : rank2 === 3 ? '3rd' : `${rank2}th`;
|
||||
seedLabels[seedIndex++] = `${groupName2} ${rankSuffix2}`;
|
||||
}
|
||||
|
||||
const ordersMap: Record<number, number> = {};
|
||||
|
||||
@@ -502,12 +502,30 @@ export const generateKnockoutBracket = createServerFn()
|
||||
|
||||
const orderedTeamIds: string[] = [];
|
||||
const maxRank = tournament.group_config.advance_per_group;
|
||||
const numGroups = tournament.group_config.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] = [];
|
||||
}
|
||||
|
||||
for (const qualified of qualifiedTeams) {
|
||||
teamsByGroup[qualified.groupOrder][qualified.rank - 1] = qualified.teamId;
|
||||
}
|
||||
|
||||
const totalTeams = numGroups * maxRank;
|
||||
for (let i = 0; i < totalTeams / 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 teamCount = orderedTeamIds.length;
|
||||
@@ -673,6 +691,7 @@ export const generateGroupStage = createServerFn()
|
||||
createdGroups.push(group);
|
||||
|
||||
const teamIds = assignment.teamIds;
|
||||
|
||||
for (let i = 0; i < teamIds.length; i++) {
|
||||
for (let j = i + 1; j < teamIds.length; j++) {
|
||||
groupStageMatches.push({
|
||||
|
||||
@@ -34,7 +34,10 @@ export function calculateGroupConfigurations(teamCount: number): GroupConfigOpti
|
||||
if (remainder > numGroups) continue;
|
||||
|
||||
const groupsWithExtra = remainder;
|
||||
const matchesGuaranteed = teamsPerGroup - 1;
|
||||
|
||||
const groupsAtBaseSize = numGroups - groupsWithExtra;
|
||||
const minGroupSize = groupsAtBaseSize > 0 ? teamsPerGroup : teamsPerGroup + 1;
|
||||
const matchesGuaranteed = minGroupSize - 1;
|
||||
|
||||
for (let advancePerGroup = 1; advancePerGroup <= Math.min(3, teamsPerGroup - 1); advancePerGroup++) {
|
||||
const teamsAdvancing = numGroups * advancePerGroup;
|
||||
@@ -77,7 +80,24 @@ export function calculateGroupConfigurations(teamCount: number): GroupConfigOpti
|
||||
}
|
||||
}
|
||||
|
||||
return configs.sort((a, b) => {
|
||||
const uniqueConfigs = new Map<string, GroupConfigOption>();
|
||||
|
||||
for (const config of configs) {
|
||||
const groupSizes: number[] = [];
|
||||
for (let i = 0; i < config.num_groups; i++) {
|
||||
const size = config.teams_per_group + (i < config.groups_with_extra ? 1 : 0);
|
||||
groupSizes.push(size);
|
||||
}
|
||||
groupSizes.sort((a, b) => b - a);
|
||||
|
||||
const key = `${groupSizes.join(',')}_advance${config.advance_per_group}`;
|
||||
|
||||
if (!uniqueConfigs.has(key)) {
|
||||
uniqueConfigs.set(key, config);
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(uniqueConfigs.values()).sort((a, b) => {
|
||||
if (a.matches_guaranteed !== b.matches_guaranteed) {
|
||||
return b.matches_guaranteed - a.matches_guaranteed;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user