Skip to content

Add entrant slot descriptors to knockout stages - #49

Merged
ylynfatt merged 1 commit into
mainfrom
knockout-entrant-slots
Jul 19, 2026
Merged

ylynfatt merged 1 commit into
mainfrom
knockout-entrant-slots

Conversation

@ylynfatt

Copy link
Copy Markdown
Owner

Summary

Phase ② of World Cup–style advancement (follows #48). A knockout stage can now declare where each round-1 slot's team comes from via config.entrants — an ordered descriptor list where consecutive pairs are the round-1 matchups, so the list is the pairing template (1A v 2B, 1C v 3rd-placed, …).

  • EntrantSlot value object: validates/normalizes the two descriptor shapes (group+position, best_placed+rank) and renders labels — Winner Group A, Runner-up Group B, 3rd Group C, Best-placed Phase 3a: Stage + Group domain (schema, models, policies) #4.
  • SingleEliminationGenerator entrant mode: with entrants configured, fixtures generate as an all-TBD bracket sized to the list (power-of-two enforced) instead of seeding from season teams. AdvanceBracketWinner needs zero changes — same round/bracket_position coordinates.
  • Bracket view: unfilled round-1 slots show their descriptor label in italics instead of bare TBD.
  • Stage edit page: entrant builder for bracket stages, fed by the previous grouped stage (new sourceStage prop) — Classic template (1A v 2B …, group-mates in opposite halves), Seeded template (winners → runners-up → best-placed with standard bracket seeding, works for any power-of-two shape incl. 12 groups + 8 thirds = 32), and per-slot select editing.
  • Validation: entrants only stick on bracket formats (silent drop otherwise, same pattern as other config keys); power-of-two count and per-slot shape enforced with clear messages.

Phase ③ (next PR): SeedStageFromGroups — resolving these descriptors against the group-stage standings with an admin confirm step, plus draw-mode pairing.

Testing

  • 8 new EntrantSlot unit tests (labels, normalization, malformed shapes)
  • 3 new generator entrant-mode tests (TBD bracket shape, coordinates, power-of-two guard)
  • 8 new feature tests (validation, format gating, generation, bracket placeholder labels, sourceStage prop)
  • Full suite: 421 passed; existing World Cup knockout page verified rendering with no regressions

🤖 Generated with Claude Code

Phase 2 of World Cup style advancement. A knockout stage can now declare
where each round-1 slot's team comes from instead of pulling raw season
teams, via config.entrants — an ordered descriptor list where consecutive
pairs are the round-1 matchups:

  ['type' => 'group', 'group' => 'Group A', 'position' => 1]  Winner Group A
  ['type' => 'best_placed', 'rank' => 2]                      2nd-best placed

- EntrantSlot value object validates/normalizes descriptors and renders
  labels (Winner Group A / Runner-up Group B / Best-placed #4)
- SingleEliminationGenerator gains an entrant mode: all-TBD bracket sized
  to the list (power of two enforced), filled later by the seeding action
- Bracket view shows descriptor labels on unfilled round-1 slots
- Stage edit page gains an entrant builder for bracket stages: classic
  cross-pair and seeded templates computed from the previous grouped
  stage, plus per-slot select editing

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ylynfatt
ylynfatt merged commit b98fa9f into main Jul 19, 2026
1 check passed
@ylynfatt
ylynfatt deleted the knockout-entrant-slots branch July 19, 2026 20:30
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