diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index df31d12..e1e0072 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -5409,6 +5409,35 @@ function TournamentMatchList({ sides, navigate }) { ) } +// Swiss tournaments often have round: null on every match because the bot doesn't +// populate that field. Matches ARE returned in round order (sorted by time_start / +// match_id), so we can infer round boundaries: floor(uniqueTeams / 2) matches per +// round. Only kicks in when a list side has exactly one column (all-null rounds). +function inferSwissRounds(sides) { + return sides.map((side) => { + if (side.kind !== 'list' || side.columns.length !== 1) return side + const allMatches = side.columns[0].matches + if (!allMatches.length) return side + const teams = new Set() + allMatches.forEach((m) => { + if (m.team_a_name) teams.add(m.team_a_name) + if (m.team_b_name) teams.add(m.team_b_name) + }) + const matchesPerRound = Math.floor(teams.size / 2) + if (matchesPerRound <= 0 || allMatches.length <= matchesPerRound) return side + const columns = [] + for (let i = 0; i < allMatches.length; i += matchesPerRound) { + const roundNum = columns.length + 1 + columns.push({ + id: `${side.key}:inferred:${roundNum}`, + label: `Round ${roundNum}`, + matches: allMatches.slice(i, i + matchesPerRound), + }) + } + return { ...side, columns } + }) +} + function TournamentDetailPage({ tournamentId, navigate }) { const [state, setState] = useState({ status: 'loading', data: null, error: null }) @@ -5431,7 +5460,10 @@ function TournamentDetailPage({ tournamentId, navigate }) { const data = state.data const matches = useMemo(() => data?.matches || [], [data]) const format = useMemo(() => tournamentFormatMeta(data?.format, matches), [data?.format, matches]) - const { sides } = useMemo(() => buildBracket(matches), [matches]) + const { sides } = useMemo(() => { + const result = buildBracket(matches) + return { ...result, sides: inferSwissRounds(result.sides) } + }, [matches]) const bracketSides = sides.filter((side) => side.kind === 'bracket') const listSides = sides.filter((side) => side.kind === 'list') const standings = data?.standings || []