Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,15 @@ export const aggregateTournamentData = async (
}

// ---- 3. Convert stats to ranking factors for players and competitors ----
const roundsPlayed = round + 1; // Add 1 to get length rather than index
return {
registrations: Object.entries(registrationStats).map(([key, { results }]) => {
const id = key as Id<'tournamentRegistrations'>;
return {
id,
gamesPlayed: results.length,
opponentIds: Array.from(new Set(results.map((s) => s.opponentId))).filter((id) => id !== null),
rankingFactors: computeRankingFactors(id, registrationStats, defaultBaseStats, round),
rankingFactors: computeRankingFactors(id, registrationStats, defaultBaseStats, roundsPlayed),
rank: -1,
};
}),
Expand All @@ -139,7 +140,7 @@ export const aggregateTournamentData = async (
opponentIds: Array.from(new Set(results.map((s) => s.opponentId))).filter((id) => id !== null),
playedTables: Array.from(playedTables),
byeRounds: Array.from(byeRounds),
rankingFactors: computeRankingFactors(id, competitorStats, defaultBaseStats, round),
rankingFactors: computeRankingFactors(id, competitorStats, defaultBaseStats, roundsPlayed),
rank: -1,
};
}),
Expand Down
37 changes: 37 additions & 0 deletions convex/_model/tournaments/triggers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,43 @@
import isEqual from 'fast-deep-equal/es6';

import { MutationCtx } from '../../_generated/server';
import { TriggerChange } from '../common/types';
import { refreshLeagueRankings as refreshLeagueRankingsHandler } from '../leagues';
import { refreshTournamentResult } from '../tournamentResults';

/**
* Trigger refresh of tournament results when ranking factors change.
*
* Only refreshes when fields that affect ranking change:
* - rankingFactors
*/
export const refreshTournamentResults = async (
ctx: MutationCtx,
change: TriggerChange<'tournaments'>,
): Promise<void> => {
const { newDoc, oldDoc } = change;

if (!newDoc || !oldDoc) {
return;
}

if (newDoc.status === 'draft' || newDoc.status === 'published') {
return;
}

// For updates, skip if no ranking-relevant fields changed:
if (isEqual(newDoc.rankingFactors, oldDoc.rankingFactors)) {
return;
}

const tournamentResults = await ctx.db.query('tournamentResults')
.withIndex('by_tournament_round', (q) => q.eq('tournamentId', change.id))
.collect();

for (const tournamentResult of tournamentResults) {
await refreshTournamentResult(ctx, tournamentResult);
}
};

/**
* Trigger refresh of league rankings when a tournament is archived.
Expand Down
1 change: 1 addition & 0 deletions convex/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,4 @@ triggers.register('tournamentCompetitors', tournamentCompetitorTriggers.refreshT
triggers.register('tournamentRegistrations', tournamentRegistrationTriggers.refreshTournamentResults);
triggers.register('tournamentResults', tournamentResultTriggers.refreshLeagueRankings);
triggers.register('tournaments', tournamentTriggers.refreshLeagueRankings);
triggers.register('tournaments', tournamentTriggers.refreshTournamentResults);
15 changes: 6 additions & 9 deletions convex/migrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,14 @@ export const fixMissingListData = migrations.define({
},
});

export const migrateTournamentResults = migrations.define({
export const refreshTournamentResults = migrations.define({
table: 'tournaments',
migrateOne: async (ctx, doc) => {
if (doc.status === 'archived') {
const rounds = doc.lastRound !== undefined ? doc.lastRound + 1 : doc.roundCount;
for (let i = 0; i < rounds; i++) {
await refreshTournamentResult(ctx, {
tournamentId: doc._id,
round: i,
});
}
const tournamentResults = await ctx.db.query('tournamentResults')
.withIndex('by_tournament_round', (q) => q.eq('tournamentId', doc._id))
.collect();
for (const result of tournamentResults) {
await refreshTournamentResult(ctx, result);
}
},
});
Expand Down