groups init
This commit is contained in:
@@ -148,7 +148,30 @@ export const generateRandomTeams = createServerFn()
|
||||
throw new Error("Need an even number of players to create teams");
|
||||
}
|
||||
|
||||
const playerIds = freeAgents.map(fa => fa.player?.id).filter(Boolean) as string[];
|
||||
const uniqueFreeAgents = Array.from(
|
||||
new Map(
|
||||
freeAgents
|
||||
.filter(fa => fa.player?.id)
|
||||
.map(fa => [fa.player!.id, fa])
|
||||
).values()
|
||||
);
|
||||
|
||||
if (uniqueFreeAgents.length !== freeAgents.length) {
|
||||
logger.warn('Duplicate free agents detected', {
|
||||
freeAgentCount: freeAgents.length,
|
||||
uniquePlayerCount: uniqueFreeAgents.length
|
||||
});
|
||||
}
|
||||
|
||||
if (uniqueFreeAgents.length < 2) {
|
||||
throw new Error("Need at least 2 unique players to create teams");
|
||||
}
|
||||
|
||||
if (uniqueFreeAgents.length % 2 !== 0) {
|
||||
throw new Error("Need an even number of unique players to create teams");
|
||||
}
|
||||
|
||||
const playerIds = uniqueFreeAgents.map(fa => fa.player!.id);
|
||||
|
||||
const allTeams = await pbAdmin.getTeamsWithFilter(
|
||||
playerIds.map(id => `players.id ?= "${id}"`).join(" || "),
|
||||
@@ -222,7 +245,7 @@ export const generateRandomTeams = createServerFn()
|
||||
}
|
||||
|
||||
let currentSeed = seed;
|
||||
const shuffled = [...freeAgents];
|
||||
const shuffled = [...uniqueFreeAgents];
|
||||
for (let i = shuffled.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(seededRandom(currentSeed++) * (i + 1));
|
||||
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
|
||||
@@ -386,3 +409,107 @@ export const adminUnenrollPlayer = createServerFn()
|
||||
logger.info('Admin unenrolled player', { playerId: data.playerId, tournamentId: data.tournamentId });
|
||||
})
|
||||
);
|
||||
|
||||
export const generateGroupStage = createServerFn()
|
||||
.inputValidator(z.object({
|
||||
tournamentId: z.string(),
|
||||
groupConfig: z.object({
|
||||
num_groups: z.number(),
|
||||
teams_per_group: z.number(),
|
||||
advance_per_group: z.number(),
|
||||
matches_guaranteed: z.number(),
|
||||
seeding_method: z.enum(["random", "ranked"]),
|
||||
}),
|
||||
teamAssignments: z.array(z.object({
|
||||
groupIndex: z.number(),
|
||||
groupName: z.string(),
|
||||
teamIds: z.array(z.string())
|
||||
})),
|
||||
seed: z.number().optional()
|
||||
}))
|
||||
.middleware([superTokensAdminFunctionMiddleware, serverFnLoggingMiddleware])
|
||||
.handler(async ({ data }) =>
|
||||
toServerResult(async () => {
|
||||
logger.info('Generating group stage', {
|
||||
tournamentId: data.tournamentId,
|
||||
numGroups: data.groupConfig.num_groups,
|
||||
seed: data.seed
|
||||
});
|
||||
|
||||
const tournament = await pbAdmin.getTournament(data.tournamentId);
|
||||
if (!tournament) {
|
||||
throw new Error("Tournament not found");
|
||||
}
|
||||
|
||||
if (tournament.matches && tournament.matches.length > 0) {
|
||||
throw new Error("Tournament already has matches generated");
|
||||
}
|
||||
|
||||
await pbAdmin.deleteGroupsByTournament(data.tournamentId);
|
||||
|
||||
const createdGroups = [];
|
||||
const allMatches = [];
|
||||
let matchLid = 1;
|
||||
|
||||
for (const assignment of data.teamAssignments) {
|
||||
const group = await pbAdmin.createGroup({
|
||||
tournament: data.tournamentId,
|
||||
name: assignment.groupName,
|
||||
order: assignment.groupIndex,
|
||||
teams: assignment.teamIds
|
||||
});
|
||||
|
||||
createdGroups.push(group);
|
||||
|
||||
const teamIds = assignment.teamIds;
|
||||
for (let i = 0; i < teamIds.length; i++) {
|
||||
for (let j = i + 1; j < teamIds.length; j++) {
|
||||
allMatches.push({
|
||||
lid: matchLid++,
|
||||
round: -1,
|
||||
order: allMatches.length,
|
||||
reset: false,
|
||||
bye: false,
|
||||
home: teamIds[i],
|
||||
away: teamIds[j],
|
||||
home_cups: 0,
|
||||
away_cups: 0,
|
||||
ot_count: 0,
|
||||
home_from_lid: -1,
|
||||
away_from_lid: -1,
|
||||
home_from_loser: false,
|
||||
away_from_loser: false,
|
||||
is_losers_bracket: false,
|
||||
match_type: "group_stage" as const,
|
||||
group: group.id,
|
||||
status: "ready" as const,
|
||||
tournament: data.tournamentId,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const createdMatches = await pbAdmin.createMatches(allMatches);
|
||||
|
||||
const matchIds = createdMatches.map((match) => match.id);
|
||||
await pbAdmin.updateTournamentMatches(data.tournamentId, matchIds);
|
||||
|
||||
await pbAdmin.updateTournament(data.tournamentId, {
|
||||
phase: "group_stage",
|
||||
group_config: data.groupConfig
|
||||
});
|
||||
|
||||
logger.info('Group stage generated', {
|
||||
tournamentId: data.tournamentId,
|
||||
groupCount: createdGroups.length,
|
||||
matchCount: createdMatches.length
|
||||
});
|
||||
|
||||
return {
|
||||
tournament,
|
||||
groups: createdGroups,
|
||||
matchCount: createdMatches.length,
|
||||
matches: createdMatches
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user