Repository navigation
Support multiple bracket formats: groundwork + round-robin implementation #146
Copy link
Copy link
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
Summary
Lay the groundwork for supporting multiple tournament/bracket formats and implement the first new format, round-robin, alongside the existing single-elimination support. Double-elimination and Swiss system remain out of scope beyond reserving room for them.
Current State
- Bracket generation/progression logic lives in
TournamentAPI/Brackets/BracketService.cs(staticCreateBracket+CreateNextRoundMatches), called directly fromGenerateBracket/UpdateRoundinBracketMutations.cs. There is no abstraction point — it's single-elimination logic only, no strategy/interface. - No
TournamentFormat/BracketTypeconcept exists anywhere in the domain model. Brackethas a 1:1 FK relationship toTournament(ApplicationDbContextconfiguration) — sufficient for round-robin, but double-elimination will likely need schema changes later (separate ticket/ADR).UpdateRound's progression model assumes elimination: all matches in a round must have a winner, winners get paired into the next round, and having fewer than 2 remaining winners implies the bracket is complete. This doesn't generalize to round-robin, where everyone keeps playing across rounds regardless of individual match outcomes.Match.WinnerIdis a single nullable FK — there's no way to represent a draw distinctly from "not yet played."
Goals
- Introduce a way to add new bracket formats going forward without reworking
GenerateBracket/UpdateRoundfor each new format — exact approach TBD, see Foundation tasks below. - Move existing single-elimination logic to fit that approach with no behavior change.
- Implement round-robin as the first new format, using proper round-robin scheduling (circle method: each participant plays one match per round, no repeat pairings).
- Support draws/ties in match results, since round-robin makes them a real, common case.
Non-Goals (explicitly deferred)
- Double-elimination and Swiss system implementations — only reserve room for them, no working implementation.
- A standings/leaderboard query for ranking round-robin participants — separate follow-up ticket.
- Any schema change to support multiple
Bracketrows perTournament(needed later for double-elimination's winners/losers brackets) — out of scope here. - Frontend/UI changes (API-only).
Tasks
Foundation
- Decide and document the approach for representing tournament/bracket format in the domain model and how format-specific generation/progression logic will be organized
- Represent tournament format in the domain model, set at tournament creation, defaulting to single-elimination
- Adapt existing single-elimination logic to the chosen approach with no behavior change (existing tests must keep passing)
- Add draw support to match results, distinguishing "not yet played" from "played, drawn"
- Write an ADR under
docs/adr/documenting the chosen approach and schema decisions
Round-robin implementation
- Implement round-robin schedule generation via the circle method (N or N-1 rounds depending on odd/even participant count, with byes for odd counts)
- Define round-robin's "completion" semantics (all scheduled rounds/matches played) as distinct from single-elimination's winner-advancement-based completion, and adjust round-progression validation (
BracketMutationValidations) accordingly - Review/adjust participant-count validation for round-robin (e.g. minimum participants) as needed
- Unit/integration tests: schedule generation (even and odd participant counts), recording wins/losses/draws, reaching full-schedule completion
- Update GraphQL schema docs and any published API docs/Postman collection to reflect the new format field and draw support
Acceptance Criteria
- Existing single-elimination tournaments behave exactly as before, with existing tests green
createTournamentaccepts an optional format, defaulting to single-elimination- A round-robin tournament can generate a full round-robin schedule, have match results (including draws) recorded, and reach a completed state without any elimination logic being invoked
- Adding a future format (e.g. double-elimination) is a scoped, isolated change, not a rework of
GenerateBracket/UpdateRound
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity