Skip to content

Surface per-user effective max on tournament and league leaderboards - #7

Merged
borland667 merged 1 commit into
ux/closed-group-bracket-seedingfrom
ui/leaderboard-effective-max
Jun 15, 2026
Merged

Surface per-user effective max on tournament and league leaderboards#7
borland667 merged 1 commit into
ux/closed-group-bracket-seedingfrom
ui/leaderboard-effective-max

Conversation

@borland667

Copy link
Copy Markdown
Owner

Summary

Frontend follow-up to PR #6. The Total column on the tournament and league leaderboards now reads as score / per-user maximum, where the maximum is tournament.rules.totalMaximumPoints − forfeitedKnockoutPoints.

  • When no group has closed with corrected seeding yet, every player's max equals the tournament-wide max and the column reads the same for all rows.
  • Once a player has at least one knockout match whose actual participants did not include their stored pick, that player's row drops by the round's pointsPerCorrect and a single explanatory footnote is rendered below the table.

Out of scope (future PRs)

  • Global leaderboard (/leaderboard/global) still shows earned totals only. Its rows aggregate across multiple tournaments and the API doesn't yet expose the user's cross-tournament max-possible.
  • Profile stats still shows earned totals only, same reason.

Both would need an API extension (per-user lifetime max across tournaments) which is a larger change.

Files

  • src/pages/Leaderboard.jsx, src/pages/League.jsx: render score / effective_max per row + conditional footnote
  • src/index.css: .leaderboard-table-footnote
  • src/i18n/messages/{en,es,pt,it,nl}.js: leaderboard.effectiveMaxTooltip + leaderboard.effectiveMaxNote
  • docs/QA_CHECKLIST.md §14 / §15 cover the new display
  • docs/IMPLEMENTATION_STATUS.md notes the current coverage + follow-up

Test plan

  • `npm run verify` — 49/49 tests pass, build clean
  • Tournament/league leaderboard renders `Total: 0 / N` for every player on a fresh tournament where N is `tournament.rules.totalMaximumPoints`
  • Seed a finished group whose real `1A` differs from a user's pick. After the importer or admin saves results, that user's row Total reads e.g. `X / (N − pointsPerCorrect)` and the footnote appears below the table
  • Users with no forfeits continue to read `X / N` (no footnote unless someone else has a forfeit)

Stacking

Based on `ux/closed-group-bracket-seeding` (PR #6) — that PR introduces `Score.forfeitedKnockoutPoints` and exposes it on the API. Once #6 merges to `main`, this PR's base will retarget to `main` automatically on GitHub.

Made with Cursor

Builds on the forfeitedKnockoutPoints field shipped with the
closed-group bracket-seeding change. Each row's Total column now reads
as `score / per-user maximum` where the maximum is
`tournament.rules.totalMaximumPoints − forfeitedKnockoutPoints`.

When no group has closed with corrected seeding yet, every player's
max equals the tournament-wide max and the column reads the same for
all rows. Once a player has at least one knockout match whose actual
participants did not include their stored pick, that player's max
drops by the round's `pointsPerCorrect` and a single explanatory
footnote is rendered below the table.

The global leaderboard and profile still show earned totals only —
they aggregate across multiple tournaments and a cross-tournament
maximum is not yet exposed by the API. Left as a follow-up.

- `src/pages/Leaderboard.jsx`, `src/pages/League.jsx`: render
  `score / effective_max` per row; conditional footnote
- `src/index.css`: `.leaderboard-table-footnote` style
- `src/i18n/messages/{en,es,pt,it,nl}.js`: `leaderboard.effectiveMaxTooltip`
  and `leaderboard.effectiveMaxNote`
- `docs/QA_CHECKLIST.md`: cover the new display in §14 and §15
- `docs/IMPLEMENTATION_STATUS.md`: note current coverage and the
  global/profile follow-up

Co-authored-by: Cursor <cursoragent@cursor.com>
@borland667
borland667 merged commit e96591b into ux/closed-group-bracket-seeding Jun 15, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant