* Don't show Game #1 label for single-game matchups in calendar When a matchup has only one game, showing "Game #1" is redundant and unhelpful. Only show game numbers when there are multiple games in a matchup (gameKeys.size > 1). For single-game matchups, show just the round name (or null if it matches the event name). Closes #198 https://claude.ai/code/session_01CRrqu43FKHshpJt1NyrDdX * Show game number for Game #2+ in series, hide Game #1 for single-game matchups If a matchup has only one game (game #1), the number is redundant — show just the round name. If game #2 or higher is upcoming, it clearly belongs to a multi-game series, so show the game number to distinguish it. https://claude.ai/code/session_01CRrqu43FKHshpJt1NyrDdX * Fix Game #1 label for multi-game series when only Game #1 is in date window Previously, Game #1 of a multi-game series showed no game number (e.g. "Semifinals") if Game #2 fell outside the calendar date range. Since at least 2 games are always entered for a series from the start, a second un-date-filtered query now checks the max game number per event. If max > 1, the event is a series and Game #1 is labelled accordingly (e.g. "Semifinals Game #1"). https://claude.ai/code/session_01CRrqu43FKHshpJt1NyrDdX * Show game number when multiple games from same series are in date window The gameKeys.size > 1 branch previously showed only the round name, contradicting the rule that multi-game series always show "Game #x". Now shows the lowest game number visible in the window (e.g. both Game #1 and #2 upcoming → "Semifinals Game #1"). https://claude.ai/code/session_01CRrqu43FKHshpJt1NyrDdX * Split series games into individual calendar entries, each showing Game #x Each game in a multi-game bracket series (e.g. Game #1 on Mar 23, Game #2 on Mar 25) now appears as its own row on the calendar with its own date and "Round Game #x" label. Single-game matchups are unchanged. Grouping key changes from eventId to eventId|gameNumber for series events. The max-game-number lookup now runs before grouping so the correct key can be determined while processing each row. https://claude.ai/code/session_01CRrqu43FKHshpJt1NyrDdX * Cache isSeries per entry to avoid re-deriving it in the finalization loop https://claude.ai/code/session_01CRrqu43FKHshpJt1NyrDdX --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
8c5389909d
commit
88e18412ec
2 changed files with 179 additions and 57 deletions
|
|
@ -142,6 +142,7 @@ describe("getUpcomingEventsForDraftedParticipants — all-compete sports", () =>
|
|||
|
||||
// ── Bracket patterns ───────────────────────────────────────────────────────
|
||||
describe("getUpcomingEventsForDraftedParticipants — bracket sports", () => {
|
||||
// Main query chain: resolves on orderBy (has leftJoin, orderBy)
|
||||
function makeSelectChain(rows: unknown[]) {
|
||||
const chain = {
|
||||
from: vi.fn().mockReturnThis(),
|
||||
|
|
@ -153,8 +154,21 @@ describe("getUpcomingEventsForDraftedParticipants — bracket sports", () => {
|
|||
return chain;
|
||||
}
|
||||
|
||||
// Second query chain (max game lookup): resolves on where (no leftJoin, no orderBy)
|
||||
function makeMaxGameChain(rows: unknown[]) {
|
||||
const chain = {
|
||||
from: vi.fn().mockReturnThis(),
|
||||
innerJoin: vi.fn().mockReturnThis(),
|
||||
where: vi.fn().mockResolvedValue(rows),
|
||||
};
|
||||
return chain;
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
// Default for the second selectDistinct call (max-game-number lookup).
|
||||
// Individual tests override the first call with mockReturnValueOnce.
|
||||
mockDb.selectDistinct.mockReturnValue(makeMaxGameChain([]));
|
||||
});
|
||||
|
||||
it("returns [] when draftedParticipants is empty", async () => {
|
||||
|
|
@ -172,7 +186,7 @@ describe("getUpcomingEventsForDraftedParticipants — bracket sports", () => {
|
|||
participant1Id: "man-city", participant2Id: "bayern",
|
||||
round: "Quarterfinals", gameNumber: 1, scheduledAt: null,
|
||||
}];
|
||||
mockDb.selectDistinct.mockReturnValue(makeSelectChain(rows));
|
||||
mockDb.selectDistinct.mockReturnValueOnce(makeSelectChain(rows));
|
||||
|
||||
const result = await getUpcomingEventsForDraftedParticipants(
|
||||
SPORTS_SEASON_ID, "playoff_bracket",
|
||||
|
|
@ -197,7 +211,7 @@ describe("getUpcomingEventsForDraftedParticipants — bracket sports", () => {
|
|||
round: "Quarterfinals", gameNumber: 1, scheduledAt: null,
|
||||
},
|
||||
];
|
||||
mockDb.selectDistinct.mockReturnValue(makeSelectChain(rows));
|
||||
mockDb.selectDistinct.mockReturnValueOnce(makeSelectChain(rows));
|
||||
|
||||
const result = await getUpcomingEventsForDraftedParticipants(
|
||||
SPORTS_SEASON_ID, "playoff_bracket",
|
||||
|
|
@ -227,7 +241,7 @@ describe("getUpcomingEventsForDraftedParticipants — bracket sports", () => {
|
|||
round: "Quarterfinals", gameNumber: 1, scheduledAt: null,
|
||||
},
|
||||
];
|
||||
mockDb.selectDistinct.mockReturnValue(makeSelectChain(rows));
|
||||
mockDb.selectDistinct.mockReturnValueOnce(makeSelectChain(rows));
|
||||
|
||||
const result = await getUpcomingEventsForDraftedParticipants(
|
||||
SPORTS_SEASON_ID, "playoff_bracket",
|
||||
|
|
@ -247,7 +261,7 @@ describe("getUpcomingEventsForDraftedParticipants — bracket sports", () => {
|
|||
participant1Id: "man-city", participant2Id: "real-madrid",
|
||||
round: "Quarterfinals", gameNumber: 1, scheduledAt: null,
|
||||
}];
|
||||
mockDb.selectDistinct.mockReturnValue(makeSelectChain(rows));
|
||||
mockDb.selectDistinct.mockReturnValueOnce(makeSelectChain(rows));
|
||||
|
||||
const result = await getUpcomingEventsForDraftedParticipants(
|
||||
SPORTS_SEASON_ID, "playoff_bracket",
|
||||
|
|
@ -261,7 +275,7 @@ describe("getUpcomingEventsForDraftedParticipants — bracket sports", () => {
|
|||
});
|
||||
|
||||
it("works for ucl_bracket pattern", async () => {
|
||||
mockDb.selectDistinct.mockReturnValue(makeSelectChain([{
|
||||
mockDb.selectDistinct.mockReturnValueOnce(makeSelectChain([{
|
||||
id: "e1", name: "UCL SF", eventDate: "2025-04-29",
|
||||
eventType: "playoff_game", sportsSeasonId: SPORTS_SEASON_ID,
|
||||
participant1Id: "man-city", participant2Id: "arsenal",
|
||||
|
|
@ -286,7 +300,7 @@ describe("getUpcomingEventsForDraftedParticipants — bracket sports", () => {
|
|||
participant1Id: "barcelona", participant2Id: "sporting",
|
||||
round: "Knockout Stage", gameNumber: 1, scheduledAt: null,
|
||||
}];
|
||||
mockDb.selectDistinct.mockReturnValue(makeSelectChain(rows));
|
||||
mockDb.selectDistinct.mockReturnValueOnce(makeSelectChain(rows));
|
||||
|
||||
const result = await getUpcomingEventsForDraftedParticipants(
|
||||
SPORTS_SEASON_ID, "playoff_bracket",
|
||||
|
|
@ -309,7 +323,7 @@ describe("getUpcomingEventsForDraftedParticipants — bracket sports", () => {
|
|||
participant1Id: "barcelona", participant2Id: "sporting",
|
||||
round: "Knockout Stage", gameNumber: 1, scheduledAt: gameTime,
|
||||
}];
|
||||
mockDb.selectDistinct.mockReturnValue(makeSelectChain(rows));
|
||||
mockDb.selectDistinct.mockReturnValueOnce(makeSelectChain(rows));
|
||||
|
||||
const result = await getUpcomingEventsForDraftedParticipants(
|
||||
SPORTS_SEASON_ID, "playoff_bracket",
|
||||
|
|
@ -321,24 +335,29 @@ describe("getUpcomingEventsForDraftedParticipants — bracket sports", () => {
|
|||
expect(result[0].eventDate).toBeNull();
|
||||
});
|
||||
|
||||
it("picks the earliest scheduledAt when multiple game rows exist for an event", async () => {
|
||||
it("series with both games in window produces two entries, each with correct time and label", async () => {
|
||||
const gameTime1 = new Date("2025-04-09T13:00:00.000Z");
|
||||
const gameTime2 = new Date("2025-04-09T15:00:00.000Z");
|
||||
const gameTime2 = new Date("2025-04-11T15:00:00.000Z");
|
||||
const rows = [
|
||||
{
|
||||
id: "e1", name: "UCL QF", eventDate: null,
|
||||
eventType: "playoff_game", sportsSeasonId: SPORTS_SEASON_ID,
|
||||
participant1Id: "barcelona", participant2Id: "sporting",
|
||||
round: "Knockout Stage", gameNumber: 1, scheduledAt: gameTime2,
|
||||
round: "Knockout Stage", gameNumber: 1, scheduledAt: gameTime1,
|
||||
},
|
||||
{
|
||||
id: "e1", name: "UCL QF", eventDate: null,
|
||||
eventType: "playoff_game", sportsSeasonId: SPORTS_SEASON_ID,
|
||||
participant1Id: "barcelona", participant2Id: "sporting",
|
||||
round: "Knockout Stage", gameNumber: 2, scheduledAt: gameTime1,
|
||||
round: "Knockout Stage", gameNumber: 2, scheduledAt: gameTime2,
|
||||
},
|
||||
];
|
||||
mockDb.selectDistinct.mockReturnValue(makeSelectChain(rows));
|
||||
mockDb.selectDistinct
|
||||
.mockReturnValueOnce(makeSelectChain(rows))
|
||||
.mockReturnValueOnce(makeMaxGameChain([
|
||||
{ eventId: "e1", gameNumber: 1 },
|
||||
{ eventId: "e1", gameNumber: 2 },
|
||||
]));
|
||||
|
||||
const result = await getUpcomingEventsForDraftedParticipants(
|
||||
SPORTS_SEASON_ID, "playoff_bracket",
|
||||
|
|
@ -346,18 +365,23 @@ describe("getUpcomingEventsForDraftedParticipants — bracket sports", () => {
|
|||
DATE_FROM, DATE_TO
|
||||
);
|
||||
|
||||
// Should use the earlier time
|
||||
expect(result[0].earliestGameTime).toBe(gameTime1.toISOString());
|
||||
expect(result).toHaveLength(2);
|
||||
const game1 = result.find((r) => r.id === "e1|1")!;
|
||||
const game2 = result.find((r) => r.id === "e1|2")!;
|
||||
expect(game1.earliestGameTime).toBe(gameTime1.toISOString());
|
||||
expect(game1.matchLabel).toBe("Knockout Stage Game #1");
|
||||
expect(game2.earliestGameTime).toBe(gameTime2.toISOString());
|
||||
expect(game2.matchLabel).toBe("Knockout Stage Game #2");
|
||||
});
|
||||
|
||||
it("sets matchLabel to round+game when single game key (non-redundant)", async () => {
|
||||
it("sets matchLabel to round name only (no game number) for single-game matchup", async () => {
|
||||
const rows = [{
|
||||
id: "e1", name: "PDC World Championship", eventDate: "2025-04-09",
|
||||
eventType: "playoff_game", sportsSeasonId: SPORTS_SEASON_ID,
|
||||
participant1Id: "man-city", participant2Id: "arsenal",
|
||||
round: "Semifinals", gameNumber: 1, scheduledAt: null,
|
||||
}];
|
||||
mockDb.selectDistinct.mockReturnValue(makeSelectChain(rows));
|
||||
mockDb.selectDistinct.mockReturnValueOnce(makeSelectChain(rows));
|
||||
|
||||
const result = await getUpcomingEventsForDraftedParticipants(
|
||||
SPORTS_SEASON_ID, "playoff_bracket",
|
||||
|
|
@ -365,19 +389,19 @@ describe("getUpcomingEventsForDraftedParticipants — bracket sports", () => {
|
|||
DATE_FROM, DATE_TO
|
||||
);
|
||||
|
||||
expect(result[0].matchLabel).toBe("Semifinals Game #1");
|
||||
expect(result[0].matchLabel).toBe("Semifinals");
|
||||
});
|
||||
|
||||
it("omits redundant round prefix when round name matches event name", async () => {
|
||||
it("sets matchLabel to null when round name matches event name (single game)", async () => {
|
||||
// e.g. event named "Knockout Stage", round also "Knockout Stage", single game
|
||||
// → show "Game #1" rather than the redundant "Knockout Stage Game #1"
|
||||
// → show null rather than redundant label
|
||||
const rows = [{
|
||||
id: "e1", name: "Knockout Stage", eventDate: null,
|
||||
eventType: "playoff_game", sportsSeasonId: SPORTS_SEASON_ID,
|
||||
participant1Id: "barcelona", participant2Id: "sporting",
|
||||
round: "Knockout Stage", gameNumber: 1, scheduledAt: null,
|
||||
}];
|
||||
mockDb.selectDistinct.mockReturnValue(makeSelectChain(rows));
|
||||
mockDb.selectDistinct.mockReturnValueOnce(makeSelectChain(rows));
|
||||
|
||||
const result = await getUpcomingEventsForDraftedParticipants(
|
||||
SPORTS_SEASON_ID, "playoff_bracket",
|
||||
|
|
@ -385,7 +409,56 @@ describe("getUpcomingEventsForDraftedParticipants — bracket sports", () => {
|
|||
DATE_FROM, DATE_TO
|
||||
);
|
||||
|
||||
expect(result[0].matchLabel).toBe("Game #1");
|
||||
expect(result[0].matchLabel).toBeNull();
|
||||
});
|
||||
|
||||
it("shows game number when only game #2 is in the window (game #1 already played)", async () => {
|
||||
const rows = [{
|
||||
id: "e1", name: "PDC World Championship", eventDate: "2025-04-10",
|
||||
eventType: "playoff_game", sportsSeasonId: SPORTS_SEASON_ID,
|
||||
participant1Id: "man-city", participant2Id: "arsenal",
|
||||
round: "Semifinals", gameNumber: 2, scheduledAt: null,
|
||||
}];
|
||||
mockDb.selectDistinct
|
||||
.mockReturnValueOnce(makeSelectChain(rows))
|
||||
.mockReturnValueOnce(makeMaxGameChain([
|
||||
{ eventId: "e1", gameNumber: 1 },
|
||||
{ eventId: "e1", gameNumber: 2 },
|
||||
]));
|
||||
|
||||
const result = await getUpcomingEventsForDraftedParticipants(
|
||||
SPORTS_SEASON_ID, "playoff_bracket",
|
||||
[makeParticipant("man-city", "Man City")],
|
||||
DATE_FROM, DATE_TO
|
||||
);
|
||||
|
||||
expect(result[0].matchLabel).toBe("Semifinals Game #2");
|
||||
});
|
||||
|
||||
it("shows Game #1 label when game #1 is upcoming but series has multiple games", async () => {
|
||||
// Game #2 exists in DB but is outside the date window — only Game #1 appears
|
||||
// in the main query. The second (un-date-filtered) query reveals it's a series.
|
||||
const mainRows = [{
|
||||
id: "e1", name: "NBA Finals", eventDate: "2025-04-10",
|
||||
eventType: "playoff_game", sportsSeasonId: SPORTS_SEASON_ID,
|
||||
participant1Id: "lakers", participant2Id: "celtics",
|
||||
round: "Finals", gameNumber: 1, scheduledAt: null,
|
||||
}];
|
||||
const allGameRows = [
|
||||
{ eventId: "e1", gameNumber: 1 },
|
||||
{ eventId: "e1", gameNumber: 2 },
|
||||
];
|
||||
mockDb.selectDistinct
|
||||
.mockReturnValueOnce(makeSelectChain(mainRows))
|
||||
.mockReturnValueOnce(makeMaxGameChain(allGameRows));
|
||||
|
||||
const result = await getUpcomingEventsForDraftedParticipants(
|
||||
SPORTS_SEASON_ID, "playoff_bracket",
|
||||
[makeParticipant("lakers", "Lakers")],
|
||||
DATE_FROM, DATE_TO
|
||||
);
|
||||
|
||||
expect(result[0].matchLabel).toBe("Finals Game #1");
|
||||
});
|
||||
|
||||
it("all-compete events have null earliestGameTime and matchLabel", async () => {
|
||||
|
|
@ -486,11 +559,21 @@ describe("getUpcomingEventsForDraftedParticipants — bracket misc", () => {
|
|||
};
|
||||
}
|
||||
|
||||
function makeMaxGameChain(rows: unknown[]) {
|
||||
return {
|
||||
from: vi.fn().mockReturnThis(),
|
||||
innerJoin: vi.fn().mockReturnThis(),
|
||||
where: vi.fn().mockResolvedValue(rows),
|
||||
};
|
||||
}
|
||||
|
||||
beforeEach(() => vi.clearAllMocks());
|
||||
|
||||
it("uses leftJoin so events without any games are still considered", async () => {
|
||||
const chain = makeSelectChain([]);
|
||||
mockDb.selectDistinct.mockReturnValue(chain);
|
||||
mockDb.selectDistinct
|
||||
.mockReturnValueOnce(chain)
|
||||
.mockReturnValueOnce(makeMaxGameChain([]));
|
||||
|
||||
await getUpcomingEventsForDraftedParticipants(
|
||||
SPORTS_SEASON_ID, "playoff_bracket",
|
||||
|
|
|
|||
|
|
@ -472,18 +472,52 @@ export async function getUpcomingEventsForDraftedParticipants(
|
|||
)
|
||||
.orderBy(asc(schema.scoringEvents.eventDate));
|
||||
|
||||
// Group rows by event, collecting relevant participants, earliest game time, and match label.
|
||||
const eventMap = new Map<string, UpcomingParticipantEvent>();
|
||||
const participantsByEvent = new Map<string, Map<string, { id: string; name: string }>>();
|
||||
// Unique "round|gameNumber" combos per event — used to build matchLabel
|
||||
const gameKeysByEvent = new Map<string, Set<string>>();
|
||||
// Min scheduledAt per event
|
||||
const earliestTimeByEvent = new Map<string, Date>();
|
||||
// Determine max game number per event across ALL games (not date-filtered)
|
||||
// so we can distinguish single-game matchups from multi-game series.
|
||||
const eventIdsFromRows = [...new Set(rows.map((r) => r.id))];
|
||||
const maxGameNumberByEvent = new Map<string, number>();
|
||||
if (eventIdsFromRows.length > 0) {
|
||||
const allGameRows = await db
|
||||
.selectDistinct({
|
||||
eventId: schema.scoringEvents.id,
|
||||
gameNumber: schema.playoffMatchGames.gameNumber,
|
||||
})
|
||||
.from(schema.scoringEvents)
|
||||
.innerJoin(
|
||||
schema.playoffMatches,
|
||||
eq(schema.playoffMatches.scoringEventId, schema.scoringEvents.id)
|
||||
)
|
||||
.innerJoin(
|
||||
schema.playoffMatchGames,
|
||||
eq(schema.playoffMatchGames.playoffMatchId, schema.playoffMatches.id)
|
||||
)
|
||||
.where(inArray(schema.scoringEvents.id, eventIdsFromRows));
|
||||
|
||||
for (const row of allGameRows) {
|
||||
if (row.gameNumber !== null) {
|
||||
const current = maxGameNumberByEvent.get(row.eventId) ?? 0;
|
||||
maxGameNumberByEvent.set(row.eventId, Math.max(current, row.gameNumber));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Group rows into calendar entries.
|
||||
// Series events (max game number > 1) get one entry per game so each game
|
||||
// appears as its own row on the calendar. Single-game events get one entry.
|
||||
const entryMap = new Map<string, UpcomingParticipantEvent>();
|
||||
const participantsByEntry = new Map<string, Map<string, { id: string; name: string }>>();
|
||||
const gameKeysByEntry = new Map<string, Set<string>>();
|
||||
const earliestTimeByEntry = new Map<string, Date>();
|
||||
const isSeriesByEntry = new Map<string, boolean>();
|
||||
|
||||
for (const row of rows) {
|
||||
if (!eventMap.has(row.id)) {
|
||||
eventMap.set(row.id, {
|
||||
id: row.id,
|
||||
const isSeries = (maxGameNumberByEvent.get(row.id) ?? 1) > 1;
|
||||
const entryKey =
|
||||
isSeries && row.gameNumber !== null ? `${row.id}|${row.gameNumber}` : row.id;
|
||||
|
||||
if (!entryMap.has(entryKey)) {
|
||||
entryMap.set(entryKey, {
|
||||
id: entryKey,
|
||||
name: row.name,
|
||||
eventDate: row.eventDate,
|
||||
earliestGameTime: null,
|
||||
|
|
@ -492,11 +526,12 @@ export async function getUpcomingEventsForDraftedParticipants(
|
|||
sportsSeasonId: row.sportsSeasonId,
|
||||
relevantParticipants: [],
|
||||
});
|
||||
participantsByEvent.set(row.id, new Map());
|
||||
gameKeysByEvent.set(row.id, new Set());
|
||||
participantsByEntry.set(entryKey, new Map());
|
||||
gameKeysByEntry.set(entryKey, new Set());
|
||||
isSeriesByEntry.set(entryKey, isSeries);
|
||||
}
|
||||
|
||||
const pMap = participantsByEvent.get(row.id);
|
||||
const pMap = participantsByEntry.get(entryKey);
|
||||
if (pMap) {
|
||||
if (row.participant1Id) {
|
||||
const p1 = draftedMap.get(row.participant1Id);
|
||||
|
|
@ -509,44 +544,48 @@ export async function getUpcomingEventsForDraftedParticipants(
|
|||
}
|
||||
|
||||
if (row.round && row.gameNumber !== null) {
|
||||
gameKeysByEvent.get(row.id)?.add(`${row.round}|${row.gameNumber}`);
|
||||
gameKeysByEntry.get(entryKey)?.add(`${row.round}|${row.gameNumber}`);
|
||||
}
|
||||
|
||||
if (row.scheduledAt) {
|
||||
const prev = earliestTimeByEvent.get(row.id);
|
||||
const prev = earliestTimeByEntry.get(entryKey);
|
||||
if (!prev || row.scheduledAt < prev) {
|
||||
earliestTimeByEvent.set(row.id, row.scheduledAt);
|
||||
earliestTimeByEntry.set(entryKey, row.scheduledAt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const [eventId, event] of eventMap) {
|
||||
event.relevantParticipants = Array.from(participantsByEvent.get(eventId)?.values() ?? []);
|
||||
for (const [entryKey, event] of entryMap) {
|
||||
event.relevantParticipants = Array.from(participantsByEntry.get(entryKey)?.values() ?? []);
|
||||
|
||||
const earliest = earliestTimeByEvent.get(eventId);
|
||||
const earliest = earliestTimeByEntry.get(entryKey);
|
||||
event.earliestGameTime = earliest ? earliest.toISOString() : null;
|
||||
|
||||
// Build matchLabel from game keys
|
||||
const gameKeys = gameKeysByEvent.get(eventId) ?? new Set<string>();
|
||||
if (gameKeys.size === 1) {
|
||||
const [round, gameNumberStr] = [...gameKeys][0].split("|");
|
||||
// When round name duplicates the event name, omit the round to avoid
|
||||
// "Knockout Stage — Knockout Stage Game #1"; just show "Game #1" instead.
|
||||
event.matchLabel =
|
||||
round === event.name
|
||||
? `Game #${gameNumberStr}`
|
||||
: `${round} Game #${gameNumberStr}`;
|
||||
} else if (gameKeys.size > 1) {
|
||||
// Multiple games — use just the round if it differs from the event name
|
||||
const rounds = new Set([...gameKeys].map((k) => k.split("|")[0]));
|
||||
if (rounds.size === 1) {
|
||||
const round = [...rounds][0];
|
||||
const isSeries = isSeriesByEntry.get(entryKey) ?? false;
|
||||
const gameKeys = gameKeysByEntry.get(entryKey) ?? new Set<string>();
|
||||
|
||||
if (isSeries) {
|
||||
if (gameKeys.size >= 1) {
|
||||
const [round, gameNumberStr] = [...gameKeys][0].split("|");
|
||||
event.matchLabel =
|
||||
round === event.name ? `Game #${gameNumberStr}` : `${round} Game #${gameNumberStr}`;
|
||||
}
|
||||
} else {
|
||||
// Single-game: omit the game number, just show the round name.
|
||||
if (gameKeys.size === 1) {
|
||||
const [round] = [...gameKeys][0].split("|");
|
||||
event.matchLabel = round === event.name ? null : round;
|
||||
} else if (gameKeys.size > 1) {
|
||||
const rounds = new Set([...gameKeys].map((k) => k.split("|")[0]));
|
||||
if (rounds.size === 1) {
|
||||
const round = [...rounds][0];
|
||||
event.matchLabel = round === event.name ? null : round;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(eventMap.values());
|
||||
return Array.from(entryMap.values());
|
||||
}
|
||||
|
||||
export interface DashboardScoringEvent {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue