brackt/app/lib/standings-display.ts
Chris Parsons 611e1ccf0a
Show tied ranks with T prefix across standings and Discord (#239)
* Show tied ranks with T prefix across standings and Discord notifications, fixes #197

- Add buildTiedRankChecker() utility to standings-display.ts; replaces
  four copies of inline rank-count logic spread across components,
  the league home route, and the Discord service
- Prefix shared ranks with "T" (e.g. "T3") in StandingsTable (league
  panel), StandingsTable (full standings), the league home preview, and
  Discord webhook notifications
- Add useMemo wrapping in StandingsTable components so tie detection
  does not recompute on every render
- Fix compareTeamsForRanking to round total points to hundredths before
  comparing, preventing floating-point noise from producing spurious
  non-ties in the standings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Fix discord test to expect escaped period in rank display

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 20:45:15 -07:00

37 lines
1.5 KiB
TypeScript

/**
* Returns a function that reports whether a given rank is shared by more than
* one team. Pass an array of all the rank values in the standings.
*
* @example
* const isTied = buildTiedRankChecker(standings.map(s => s.currentRank));
* isTied(3); // true if two or more teams share rank 3
*/
export function buildTiedRankChecker(ranks: number[]): (rank: number) => boolean {
const counts = new Map<number, number>();
for (const rank of ranks) counts.set(rank, (counts.get(rank) ?? 0) + 1);
return (rank) => (counts.get(rank) ?? 1) > 1;
}
/**
* Returns the display rank for a team on the league home standings preview.
*
* Rules:
* - If the team has a standing, return its numeric rank, prefixed with "T" if
* the rank is shared by more than one team.
* - If the team has no standing, it is tied at the position just after all
* ranked teams. For example, if 3 teams have standings the unranked teams
* show "T4". If no team has standings yet (scores haven't been calculated)
* every team is genuinely tied at zero and shows "T1".
*
* @param standing - The team's standing record, or undefined if none exists.
* @param standingsCount - Total number of teams that have a standing record.
* @param isTied - Whether this team's rank is shared with another team.
*/
export function getDisplayRank(
standing: { currentRank: number } | undefined,
standingsCount: number,
isTied?: boolean
): number | string {
if (standing) return isTied ? `T${standing.currentRank}` : standing.currentRank;
return `T${standingsCount + 1}`;
}