Fix First Four appearing out of order in NCAA bracket display (#152)
Use bracket template's canonical round order instead of sorting by match count, which placed First Four (4 matches) after Elite Eight (also 4 matches). Extract getOrderedRoundsFromMatches() into bracket-templates.ts to eliminate identical logic duplicated in the admin bracket component. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
84787c9a4b
commit
b1535b2976
3 changed files with 33 additions and 20 deletions
|
|
@ -582,6 +582,32 @@ export function getAllBracketTemplates(): BracketTemplate[] {
|
|||
return Object.values(BRACKET_TEMPLATES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns round names in chronological order (earliest first) for the given matches.
|
||||
* When a template is provided its defined order is used; otherwise rounds are sorted
|
||||
* by descending match count (more matches = earlier round).
|
||||
*/
|
||||
export function getOrderedRoundsFromMatches(
|
||||
matches: Array<{ round: string }>,
|
||||
template?: BracketTemplate
|
||||
): string[] {
|
||||
const roundsInMatches = new Set(matches.map((m) => m.round));
|
||||
|
||||
if (template) {
|
||||
return template.rounds
|
||||
.map((r) => r.name)
|
||||
.filter((name) => roundsInMatches.has(name));
|
||||
}
|
||||
|
||||
const roundMatchCounts = new Map<string, number>();
|
||||
for (const m of matches) {
|
||||
roundMatchCounts.set(m.round, (roundMatchCounts.get(m.round) || 0) + 1);
|
||||
}
|
||||
return Array.from(roundMatchCounts.keys()).sort(
|
||||
(a, b) => (roundMatchCounts.get(b) || 0) - (roundMatchCounts.get(a) || 0)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to determine scoring round type based on match count in scoring rounds
|
||||
* Used for determining placement sharing (5-8th, 3-4th, 1-2nd)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import {
|
|||
SelectValue,
|
||||
} from "~/components/ui/select";
|
||||
import { ArrowLeft, Plus, Trophy, X, Check, ChevronDown, ChevronRight, Calendar, TrendingUp, Trash2 } from "lucide-react";
|
||||
import { getAllBracketTemplates, getBracketTemplate, buildNCAA68SlotMap, ALL_16_SEEDS, type BracketRegion } from "~/lib/bracket-templates";
|
||||
import { getAllBracketTemplates, getBracketTemplate, getOrderedRoundsFromMatches, buildNCAA68SlotMap, ALL_16_SEEDS, type BracketRegion } from "~/lib/bracket-templates";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
|
|
@ -277,18 +277,8 @@ export default function EventBracket({
|
|||
|
||||
// Memoized: Get available rounds in chronological order
|
||||
const availableRounds = useMemo(() => {
|
||||
const roundsInMatches = Array.from(new Set(matches.map(m => m.round)));
|
||||
|
||||
if (event.bracketTemplateId) {
|
||||
const eventTemplate = getBracketTemplate(event.bracketTemplateId);
|
||||
if (eventTemplate) {
|
||||
return eventTemplate.rounds
|
||||
.map((r) => r.name)
|
||||
.filter((roundName: string) => roundsInMatches.includes(roundName));
|
||||
}
|
||||
}
|
||||
|
||||
return roundsInMatches;
|
||||
const template = event.bracketTemplateId ? getBracketTemplate(event.bracketTemplateId) : undefined;
|
||||
return getOrderedRoundsFromMatches(matches, template);
|
||||
}, [matches, event.bracketTemplateId]);
|
||||
|
||||
// Check if all matches are complete
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import {
|
|||
getUpcomingScoringEvents,
|
||||
getRecentCompletedEvents,
|
||||
} from "~/models/scoring-event";
|
||||
import { getBracketTemplate, getOrderedRoundsFromMatches } from "~/lib/bracket-templates";
|
||||
import { database } from "~/database/context";
|
||||
import * as schema from "~/database/schema";
|
||||
import { eq, and, inArray } from "drizzle-orm";
|
||||
|
|
@ -160,13 +161,9 @@ export async function loader(args: Route.LoaderArgs) {
|
|||
});
|
||||
playoffMatches = matches;
|
||||
|
||||
const roundMatchCounts = new Map<string, number>();
|
||||
for (const m of matches) {
|
||||
roundMatchCounts.set(m.round, (roundMatchCounts.get(m.round) || 0) + 1);
|
||||
}
|
||||
playoffRounds = Array.from(roundMatchCounts.keys()).sort(
|
||||
(a, b) => (roundMatchCounts.get(b) || 0) - (roundMatchCounts.get(a) || 0)
|
||||
);
|
||||
const templateId = events.find((e) => e.bracketTemplateId)?.bracketTemplateId;
|
||||
const template = templateId ? getBracketTemplate(templateId) : undefined;
|
||||
playoffRounds = getOrderedRoundsFromMatches(matches, template);
|
||||
}
|
||||
|
||||
// Fetch group-stage losers and all participant results for bracket scoring
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue