From e4d9f901cb39ec553a19d9da88087001c2bf2d72 Mon Sep 17 00:00:00 2001 From: Andreas Knuth Date: Tue, 23 Jun 2026 16:26:01 -0500 Subject: [PATCH] bracket fixes ... --- app/components/Bracket.tsx | 21 +++++++++++++++------ app/globals.css | 3 ++- lib/bracket.ts | 23 +++++++++++++++++++++++ 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/app/components/Bracket.tsx b/app/components/Bracket.tsx index ad3f706..b90f211 100644 --- a/app/components/Bracket.tsx +++ b/app/components/Bracket.tsx @@ -1,7 +1,7 @@ "use client"; import { GroupTable, Match, Team, ThirdPlaceRow } from "@/lib/types"; -import { ThirdAssignment } from "@/lib/bracket"; +import { ThirdAssignment, orderedRound } from "@/lib/bracket"; import { resolveBracket, ResolvedSide, ResolvedTie } from "@/lib/resolve-bracket"; import Flag from "./Flag"; @@ -48,14 +48,23 @@ export default function Bracket({ matches: Match[]; teams: Team[]; tables: GroupTable[]; thirds: ThirdPlaceRow[]; assignment: ThirdAssignment | null; annexResolved: boolean; }) { - const { r32, later } = resolveBracket( + const { r32: r32Array, later } = resolveBracket( matches, teams, tables, thirds, assignment, annexResolved, ); - const pick = (nums: number[]) => nums.map((n) => later[n]).filter(Boolean); - const r16 = pick([89, 90, 91, 92, 93, 94, 95, 96]); - const qf = pick([97, 98, 99, 100]); - const sf = pick([101, 102]); + const r32ByNum = new Map(r32Array.map((t) => [t.matchNumber, t])); + + // Korrekte Baum-Reihenfolge: von der Wurzel (Finale) rekursiv die Quellen + // jeder Runde ermitteln, damit die Spalten vertikal ausgerichtet sind. + const sfOrder = orderedRound([104]); + const qfOrder = orderedRound(sfOrder); + const r16Order = orderedRound(qfOrder); + const r32Order = orderedRound(r16Order); + + const r32 = r32Order.map((n) => r32ByNum.get(n)).filter(Boolean) as ResolvedTie[]; + const r16 = r16Order.map((n) => later[n]).filter(Boolean); + const qf = qfOrder.map((n) => later[n]).filter(Boolean); + const sf = sfOrder.map((n) => later[n]).filter(Boolean); const fin = later[104]; const third = later[103]; diff --git a/app/globals.css b/app/globals.css index fff1de9..ed0f651 100644 --- a/app/globals.css +++ b/app/globals.css @@ -189,9 +189,10 @@ table.standings { width: 100%; border-collapse: collapse; } font-family: var(--font-mono); font-size: 12px; color: var(--ink-dim); } .bracket-banner .v { font-family: var(--font-mono); font-size: 12px; color: var(--turf); } -.bracket-scroll { overflow-x: auto; padding-bottom: 28px; } +.bracket-scroll { overflow-x: auto; padding-bottom: 36px; } .bracket { display: flex; gap: 26px; min-width: max-content; align-items: stretch; + padding-bottom: 16px; } .round { display: flex; flex-direction: column; min-width: 220px; } .round-label { diff --git a/lib/bracket.ts b/lib/bracket.ts index 2954f16..dd9edfd 100644 --- a/lib/bracket.ts +++ b/lib/bracket.ts @@ -109,3 +109,26 @@ export function slotLabel( } return `3. ${slot.thirdPool?.join("/") ?? "?"}`; } + +// Lookup: matchNumber → Quellspiele (fromHome, fromAway, losers). +// Exkludiert "Spiel um Platz 3" (losers: true), weil es nicht im Siegerbaum mitläuft. +const SOURCE_MAP: Map = (() => { + const m = new Map(); + for (const km of LATER_ROUNDS) { + if (!km.losers) m.set(km.matchNumber, km); + } + return m; +})(); + +// Berechnet die vertikale Anzeige-Reihenfolge einer früheren Runde aus der +// Reihenfolge der Folgerunde. parentRound sind die Match-Nummern der Folgerunde +// in Anzeige-Reihenfolge. Gibt die Nummern der Quellspiele in korrekter +// Baum-Topologie-Reihenfolge zurück. +export function orderedRound(parentRound: number[]): number[] { + const result: number[] = []; + for (const parent of parentRound) { + const src = SOURCE_MAP.get(parent); + if (src) result.push(src.fromHome, src.fromAway); + } + return result; +}