diff --git a/src/components/event/GroupDisplay.svelte b/src/components/event/GroupDisplay.svelte index 9ac8a4b..172ed92 100644 --- a/src/components/event/GroupDisplay.svelte +++ b/src/components/event/GroupDisplay.svelte @@ -15,12 +15,10 @@ config: GroupViewConfig; } = $props(); - // Groups fights into rounds: a round starts at the first fight's start; - // all fights starting within 10 minutes (600_000 ms) of that are in the same round. - function detectRounds(fights: EventFight[]): EventFight[][] { + function detectRounds(fights: EventFight[], groupingTimeMinutes: number): EventFight[][] { if (!fights || fights.length === 0) return []; - const TEN_MIN_MS = 10 * 60 * 1000; + const groupingTimeMs = Math.max(1, Math.floor(groupingTimeMinutes || 10)) * 60 * 1000; const sorted = [...fights].sort((a, b) => a.start - b.start); const rounds: EventFight[][] = []; @@ -28,7 +26,7 @@ let roundStart = sorted[0].start; for (const fight of sorted) { - if (fight.start - roundStart <= TEN_MIN_MS) { + if (fight.start - roundStart <= groupingTimeMs) { currentRound.push(fight); } else { if (currentRound.length) rounds.push(currentRound); @@ -61,8 +59,9 @@ {#each config.groups as groupId} {@const group = event.groups.find((g) => g.id === groupId)!!} {@const fights = event.fights.filter((f) => f.group?.id === groupId)} - {@const rounds = detectRounds(fights)} + {@const rounds = detectRounds(fights, config.roundGroupingTimeMinutes ?? 10)} {@const roundRows = config.roundRows ?? 1} + {@const roundPrefix = config.roundPrefix ?? "Runde"} {@const roundRowsChunked = chunkIntoRows(rounds, roundRows)}
@@ -83,7 +82,7 @@ {@const roundIndex = rounds.indexOf(round)} {@const teams = Array.from(new Set(round.flatMap((f) => [f.redTeam, f.blueTeam])))}
- + {#each round as fight} {/each} diff --git a/src/components/event/types.ts b/src/components/event/types.ts index 853ed25..8b0aa11 100644 --- a/src/components/event/types.ts +++ b/src/components/event/types.ts @@ -4,6 +4,8 @@ export const GroupViewSchema = z.object({ type: z.literal("GROUP"), groups: z.array(z.number()), roundRows: z.number().int().positive().optional().default(1), + roundGroupingTimeMinutes: z.number().int().positive().optional().default(10), + roundPrefix: z.enum(["Runde", "Tag"]).optional().default("Runde"), }); export type GroupViewConfig = z.infer; diff --git a/src/components/moderator/pages/pages/frontmatter/ViewConfigEditor.svelte b/src/components/moderator/pages/pages/frontmatter/ViewConfigEditor.svelte index 05c325a..5b8d33a 100644 --- a/src/components/moderator/pages/pages/frontmatter/ViewConfigEditor.svelte +++ b/src/components/moderator/pages/pages/frontmatter/ViewConfigEditor.svelte @@ -7,10 +7,18 @@ import { Plus, Trash2 } from "lucide-svelte"; type StageType = "GROUP" | "ELEMINATION" | "DOUBLE_ELEMINATION"; + type RoundPrefix = "Runde" | "Tag"; + const roundGroupingTimeOptions = [ + { label: "10 Minutes", value: 10 }, + { label: "30 Minutes", value: 30 }, + { label: "1 Hour", value: 60 }, + { label: "2 Hours", value: 120 }, + { label: "12 Hours", value: 720 }, + ]; type StageConfig = { name: string; view: - | { type: "GROUP"; groups: number[]; roundRows?: number } + | { type: "GROUP"; groups: number[]; roundRows?: number; roundGroupingTimeMinutes?: number; roundPrefix?: RoundPrefix } | { type: "ELEMINATION"; finalFight: number } | { type: "DOUBLE_ELEMINATION"; winnersFinalFight: number; losersFinalFight: number; grandFinalFight: number }; }; @@ -68,7 +76,7 @@ draft[key] = { name: "New stage", - view: { type: "GROUP", groups: [], roundRows: 1 }, + view: { type: "GROUP", groups: [], roundRows: 1, roundGroupingTimeMinutes: 10, roundPrefix: "Runde" }, }; }); } @@ -105,7 +113,7 @@ function setStageType(key: string, type: StageType, event?: ExtendedEvent) { nextConfig((draft) => { if (type === "GROUP") { - draft[key].view = { type, groups: [], roundRows: 1 }; + draft[key].view = { type, groups: [], roundRows: 1, roundGroupingTimeMinutes: 10, roundPrefix: "Runde" }; } else if (type === "ELEMINATION") { draft[key].view = { type, finalFight: event?.fights[0]?.id ?? 0 }; } else { @@ -139,6 +147,24 @@ }); } + function setRoundGroupingTimeMinutes(key: string, value: string) { + nextConfig((draft) => { + const view = draft[key].view; + if (view.type === "GROUP") { + view.roundGroupingTimeMinutes = Math.max(1, Math.floor(Number(value) || 10)); + } + }); + } + + function setRoundPrefix(key: string, value: RoundPrefix) { + nextConfig((draft) => { + const view = draft[key].view; + if (view.type === "GROUP") { + view.roundPrefix = value; + } + }); + } + function setFightParam(key: string, param: "finalFight" | "winnersFinalFight" | "losersFinalFight" | "grandFinalFight", fightId: string) { nextConfig((draft) => { const view = draft[key].view as Record; @@ -235,6 +261,29 @@ setRoundRows(key, (event.currentTarget as HTMLInputElement).value)} />
+
+ + +
+
+ + +
{:else if stage.view.type === "ELEMINATION"}