From 51e3d5141c21989c515185d6f40779f3cca9dc0f Mon Sep 17 00:00:00 2001 From: yohlo Date: Thu, 11 Sep 2025 16:13:45 -0500 Subject: [PATCH] reset match logic --- src/features/matches/server.ts | 109 +++++++++++++++---------- src/lib/pocketbase/services/matches.ts | 5 ++ 2 files changed, 72 insertions(+), 42 deletions(-) diff --git a/src/features/matches/server.ts b/src/features/matches/server.ts index 8d94f82..0b9f256 100644 --- a/src/features/matches/server.ts +++ b/src/features/matches/server.ts @@ -17,15 +17,18 @@ export const generateTournamentBracket = createServerFn() .middleware([superTokensAdminFunctionMiddleware]) .handler(async ({ data: { tournamentId, orderedTeamIds } }) => toServerResult(async () => { - logger.info('Generating tournament bracket', { tournamentId, teamCount: orderedTeamIds.length }); - + logger.info("Generating tournament bracket", { + tournamentId, + teamCount: orderedTeamIds.length, + }); + const tournament = await pbAdmin.getTournament(tournamentId); if (!tournament) { - throw new Error('Tournament not found'); + throw new Error("Tournament not found"); } if (tournament.matches && tournament.matches.length > 0) { - throw new Error('Tournament already has matches generated'); + throw new Error("Tournament already has matches generated"); } const teamCount = orderedTeamIds.length; @@ -33,13 +36,15 @@ export const generateTournamentBracket = createServerFn() throw new Error(`Bracket not available for ${teamCount} teams`); } - const bracketTemplate = brackets[teamCount as keyof typeof brackets] as any; - + const bracketTemplate = brackets[ + teamCount as keyof typeof brackets + ] as any; + const seedToTeamId = new Map(); orderedTeamIds.forEach((teamId, index) => { seedToTeamId.set(index + 1, teamId); }); - + const matchInputs: MatchInput[] = []; bracketTemplate.winners.forEach((round: any[]) => { @@ -79,7 +84,7 @@ export const generateTournamentBracket = createServerFn() } if (matchInput.home && matchInput.away) { - matchInput.status = "ready" + matchInput.status = "ready"; } matchInputs.push(matchInput); @@ -111,13 +116,13 @@ export const generateTournamentBracket = createServerFn() }); const createdMatches = await pbAdmin.createMatches(matchInputs); - - const matchIds = createdMatches.map(match => match.id); + + const matchIds = createdMatches.map((match) => match.id); await pbAdmin.updateTournamentMatches(tournamentId, matchIds); - - logger.info('Tournament bracket generated', { - tournamentId, - matchCount: createdMatches.length + + logger.info("Tournament bracket generated", { + tournamentId, + matchCount: createdMatches.length, }); return { @@ -133,38 +138,38 @@ export const startMatch = createServerFn() .middleware([superTokensAdminFunctionMiddleware]) .handler(async ({ data }) => toServerResult(async () => { - logger.info('Starting match', data); - + logger.info("Starting match", data); + let match = await pbAdmin.getMatch(data); if (!match) { - throw new Error('Match not found'); + throw new Error("Match not found"); } match = await pbAdmin.updateMatch(data, { start_time: new Date().toISOString(), - status: "started" + status: "started", }); - + return match; - } - )); + }) + ); const endMatchSchema = z.object({ matchId: z.string(), home_cups: z.number(), away_cups: z.number(), - ot_count: z.number() + ot_count: z.number(), }); export const endMatch = createServerFn() .validator(endMatchSchema) .middleware([superTokensAdminFunctionMiddleware]) .handler(async ({ data: { matchId, home_cups, away_cups, ot_count } }) => toServerResult(async () => { - logger.info('Ending match', matchId); - + logger.info("Ending match", matchId); + let match = await pbAdmin.getMatch(matchId); if (!match) { - throw new Error('Match not found'); + throw new Error("Match not found"); } match = await pbAdmin.updateMatch(matchId, { @@ -172,38 +177,58 @@ export const endMatch = createServerFn() status: "ended", home_cups, away_cups, - ot_count - }) + ot_count, + }); const matchWinner = home_cups > away_cups ? match.home : match.away; const matchLoser = home_cups < away_cups ? match.home : match.away; - if (!matchWinner || !matchLoser) throw new Error("Something went wrong") + if (!matchWinner || !matchLoser) throw new Error("Something went wrong"); // winner -> where to send match winner to, loser same - const { winner, loser } = await pbAdmin.getChildMatches(matchId) - + const { winner, loser } = await pbAdmin.getChildMatches(matchId); + + // reset match check + if (winner && winner.reset) { + const awayTeamWon = match.away === matchWinner; + + if (!awayTeamWon) { + // Reset match is not necessary + logger.info("Deleting reset match", { + resetMatchId: winner.id, + currentMatchId: match.id, + reason: "not necessary", + }); + + await pbAdmin.deleteMatch(winner.id); + return match; + } + } + + // advance bracket if (winner) { await pbAdmin.updateMatch(winner.id, { [winner.home_from_lid === match.lid ? "home" : "away"]: matchWinner, - status: - ((winner.home_from_lid === match.lid) && winner.away) - || ((winner.away_from_lid === match.lid) && winner.home) - ? 'ready' : 'tbd' - }) + status: + (winner.home_from_lid === match.lid && winner.away) || + (winner.away_from_lid === match.lid && winner.home) + ? "ready" + : "tbd", + }); } if (loser) { await pbAdmin.updateMatch(loser.id, { [loser.home_from_lid === match.lid ? "home" : "away"]: matchLoser, - status: - ((loser.home_from_lid === match.lid) && loser.away) - || ((loser.away_from_lid === match.lid) && loser.home) - ? 'ready' : 'tbd' - }) + status: + (loser.home_from_lid === match.lid && loser.away) || + (loser.away_from_lid === match.lid && loser.home) + ? "ready" + : "tbd", + }); } // TODO: send SSE return match; - } - )); \ No newline at end of file + }) + ); diff --git a/src/lib/pocketbase/services/matches.ts b/src/lib/pocketbase/services/matches.ts index 94dfb33..b376146 100644 --- a/src/lib/pocketbase/services/matches.ts +++ b/src/lib/pocketbase/services/matches.ts @@ -55,6 +55,11 @@ export function createMatchesService(pb: PocketBase) { return result; }, + async deleteMatch(id: string): Promise { + logger.info("PocketBase | Deleting match", id); + await pb.collection("matches").delete(id); + }, + async deleteMatchesByTournament(tournamentId: string): Promise { logger.info("PocketBase | Deleting matches for tournament", tournamentId); const matches = await pb.collection("matches").getFullList({