Skip to content

M3: Double-Elimination (Winner/Loser-Bracket + Grand Final) - #5

Open
TimGoldbach wants to merge 1 commit into
feat/m2_1-polishfrom
feat/m3-double-elim
Open

M3: Double-Elimination (Winner/Loser-Bracket + Grand Final)#5
TimGoldbach wants to merge 1 commit into
feat/m2_1-polishfrom
feat/m3-double-elim

Conversation

@TimGoldbach

Copy link
Copy Markdown
Owner

Erste Scheibe von M3 (Format-Breite): Double-Elimination. Test-getrieben über einen Workflow + 3-Perspektiven-Review gebaut. 0 Blocker — das Review fand nur Test-Qualitäts-Punkte, keine Code-Bugs. Verifiziert: tsc grün, vitest 22/22.

ℹ️ Gestapelt auf #4 (M2.1). Base feat/m2_1-polish → Diff M3-DE-only.
⚠️ Merge-Hinweis bleibt: origin/main hat bisher nur #1 — der Stack #2#3#4→dieser muss noch nach main durchgereicht werden.

Was drin ist

  • Generator (bracket-generator.service.ts): echter double_elimination-Generator für Power-of-2-Felder — ein Stage/eine Group mit sequentiellen Runden (WB 1..k, LB 2(k-1) Runden, ein Grand Final, kein Reset), within-group winner_of/loser_of-Quellen. Trifft die kanonische N=4 (6 Matches) und N=8 (14 Matches) Struktur exakt; allgemein 2N-2. Nicht-Zweierpotenz wirft NotImplemented (→ M3.1).
  • Progression (progression.ts): loserAdvancement (Spiegel von winnerAdvancement für loser_of).
  • Scoring (tournaments.service.ts): bei Elimination wird zusätzlich der Verlierer via loserAdvancement ins Loser-Bracket gesetzt (No-op für Single-Elim; Round-Robin unverändert).

Tests (ausgeführt, grün)

Exakte Struktur-Asserts N=4/N=8, 2N-2 für N=4/8/16, Nicht-Zweierpotenz wirft, loserAdvancement-Unit-Test — plus eine deterministische Voll-Simulation: spielt jedes Match aus und prüft, dass das Grand Final den ungeschlagenen WB-Finalisten krönt und der LB-Finalist genau eine Niederlage trägt (beweist das Loser-Bracket-Wiring).

Review-Fix

Eine tautologische „single champion"-Assertion (Simulator setzt Sieger=opponent1, Test prüfte genau das) durch echte Constraints ersetzt: GF = genau ein Match, Champion hat 0 Niederlagen.

Verschoben (in docs/PLAN.md)

  • M3.1: DE-Nicht-Zweierpotenz/Byes (LB-Bye-Kaskade) + optionaler Bracket-Reset im Grand Final.
  • M3.2: Gruppen+KO mit Cross-Stage-Seeding. M3.3: Swiss + Buchholz.
  • Service-Layer-DB-Test für den DE-score()/reseed()-Pfad, sobald eine DB verfügbar ist (offline nicht möglich).

🤖 Generated with Claude Code

First slice of M3 (format breadth), built test-driven via a workflow + a 3-lens
adversarial review (0 blockers; the review found only test-quality issues, no
code bugs). Verified: tsc clean, vitest 22/22.

- bracket-generator: real double_elimination generator for power-of-two fields —
  one stage/one group with sequential rounds (WB 1..k, LB 2(k-1) rounds, single
  Grand Final, no reset), within-group winner_of/loser_of sources. Matches the
  canonical N=4 (6 matches) and N=8 (14 matches) structures; 2N-2 in general.
  Non-power-of-two throws NotImplemented (byes/odd fields are M3.1).
- progression: loserAdvancement (mirror of winnerAdvancement for loser_of).
- tournaments.service.score(): for elimination, also drop the loser via
  loserAdvancement (no-op for single-elim; round-robin unchanged).
- tests: exact-structure asserts for N=4/N=8, 2N-2 for N=4/8/16, non-pow2 throws,
  loserAdvancement unit test, and a deterministic full-tournament simulation that
  plays every match to completion and asserts the Grand Final crowns the
  undefeated WB finalist while the LB finalist carries exactly one loss (proves
  the loser-bracket wiring).

Deferred (docs/PLAN.md): DE non-pow2/byes + bracket reset (M3.1), groups+KO with
cross-stage seeding (M3.2), Swiss + Buchholz (M3.3), and a service-layer DB test
for the score()/reseed() DE path once a database is available.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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