bracket fixes ...

This commit is contained in:
2026-06-23 16:26:01 -05:00
parent 82d093fbb4
commit e4d9f901cb
3 changed files with 40 additions and 7 deletions

View File

@@ -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];

View File

@@ -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 {

View File

@@ -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<number, KnockoutMatch> = (() => {
const m = new Map<number, KnockoutMatch>();
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;
}