Dokumenter konkurranseklasser (ADR-041) i CHANGELOG/FEATURE_BACKLOG
Fullfører dokumentasjonen for klasse-funksjonen (migrasjon 053, rullet ut 2026-08-04): ny ADR-041 med de fire load-bærende beslutningene (fritt navngitte klasser, delt tabell mellom turneringstyper, standardutslag som frontend-bekvemmelighet, egen resultatliste kun i individuelle turneringer), pluss fulle bygge-/verifiseringsoppføringer i CHANGELOG.md og FEATURE_BACKLOG.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
7bda1bf789
commit
38168b2871
3 changed files with 215 additions and 0 deletions
|
|
@ -3819,6 +3819,86 @@ ikke noe brukeren har bedt om.
|
|||
|
||||
---
|
||||
|
||||
## ADR-041: Konkurranseklasser ("Damer fra 44, Herrer fra 50+")
|
||||
|
||||
**Kontekst:** Brukeren spurte om det var mulig å sette opp runder i en
|
||||
turnering slik at f.eks. damer spiller fra utslag 44 mens herrer spiller
|
||||
fra 50+. Undersøkelse viste at DELER allerede virket (hvert
|
||||
`match_participant`/`round_participant` har alltid hatt sitt eget
|
||||
`tee_id`, uavhengig av de andre, med server-side validering av at
|
||||
utslaget har rating for spillerens kjønn, ADR-029) — men det var et
|
||||
manuelt valg per spiller hver gang, ingen gjenbrukbar "klasse"-
|
||||
gruppering. Ingen "klasse"/kategori-konsept for konkurranse fantes fra
|
||||
før noe sted i skjemaet (kun den urelaterte venne-kategoriseringen,
|
||||
ADR-036).
|
||||
|
||||
**Beslutning A — Klasser er fritt navngitte, ikke en fast taksonomi.**
|
||||
Organisator oppretter klasser med eget navn (f.eks. "Damer", "Herrer A",
|
||||
"Junior") og et VALGFRITT standardutslag — ikke en kjønns- eller
|
||||
alders-spesifikk datamodell. Bekreftet eksplisitt med bruker
|
||||
(`AskUserQuestion`) framfor en fast kjønn+alder-kombinasjon: dekker
|
||||
kjønn/alder/HCP eller annet uten at systemet må forstå forskjellen,
|
||||
samme fleksibilitets-prinsipp som `friend_categorization` (ADR-036).
|
||||
|
||||
**Beslutning B — Delt tabell, ikke duplisert per turneringstype.** Ny
|
||||
`tournament_class`-tabell (migrasjon 053) FK'et til `tournament`, ikke
|
||||
en utvidelse av selve `tournament`-raden — samme sidetabell-mønster som
|
||||
`tournament_sponsor`. Siden BÅDE lagturneringer (ADR-011) og
|
||||
individuelle turneringer (ADR-037) peker til samme delte `tournament`-
|
||||
tabell (`format_type`-diskriminator), dekker ÉN tabell begge uten
|
||||
duplisering. Klassetilhørighet lever på `team_roster.class_id`
|
||||
(lagturneringer) og `tournament_participant.class_id` (individuelle
|
||||
turneringer) — begge nullable, `ON DELETE SET NULL` (samme prinsipp som
|
||||
`tournament_round_bbb_hole`s FK-er, migrasjon 044): sletter man en
|
||||
klasse, forsvinner ikke roster-/deltaker-radene, de mister bare
|
||||
merkelappen.
|
||||
|
||||
**Beslutning C — Standardutslag er en frontend-bekvemmelighet, ikke en
|
||||
ny backend-mekanisme.** `tee_id` er ALLEREDE required og satt per
|
||||
deltaker (ikke per økt/runde) ved både `POST .../matches/{id}/
|
||||
participants` og `POST .../rounds/{id}/participants` — klassens
|
||||
standardutslag forhåndsvelger bare dette feltet i UI-et (fortsatt fritt
|
||||
overstyrbart), backend-kontrakten er uendret. Samme mønster som
|
||||
`new-round.tsx`s eksisterende kjønnsfilter/-default for personlige
|
||||
runder. Forhåndsvelgingen sjekker eksplisitt at utslaget faktisk finnes
|
||||
på DEN aktuelle øktens/rundens bane før det brukes — en klasses
|
||||
standardutslag kan tilhøre en annen bane enn den som er i bruk akkurat
|
||||
da.
|
||||
|
||||
**Beslutning D — Egen resultatliste KUN i individuelle turneringer,
|
||||
aldri i lagturneringer.** Den mest substansielle avklaringen
|
||||
(`AskUserQuestion`, med begrunnelse presentert først): i lagturneringer
|
||||
er poeng knyttet til hele KAMPER (lag mot lag, `match.points_side_a/b`),
|
||||
ikke enkeltspillere — å dele opp dette per klasse gir ikke naturlig
|
||||
mening, og brukeren bekreftet eksplisitt at klasse der KUN skal foreslå
|
||||
utslag. Det finnes fra før et smalt, PER-ØKT individuelt leaderboard for
|
||||
singles/fourball-slagspill (`fetch_individual_leaderboard`,
|
||||
`tournaments.py`) — bevisst IKKE utvidet eller gjenbrukt av denne runden,
|
||||
det er en annen, allerede eksisterende funksjon med annet formål
|
||||
(sesjonsscoped, format-begrenset). I individuelle turneringer (flatt
|
||||
felt, ADR-037) er splitting derimot en naturlig match: `individual_
|
||||
leaderboard`-endepunktet fikk `class_id`/`class_name` lagt til i
|
||||
SELECT+respons, men selve summerings-/sorteringslogikken er UENDRET —
|
||||
frontend grupperer den allerede korrekt sorterte listen visuelt (stabil
|
||||
gruppering bevarer riktig rangering per klasse), ingen ny motorlogikk i
|
||||
`handicap_engine.py` trengtes (Copenhagen/BBB var allerede scope-
|
||||
agnostiske på deltaker-mengde).
|
||||
|
||||
**Konsekvens:** `053_tournament_classes.sql`. Ny klasse-CRUD i
|
||||
`tournaments.py` (delt, siden `tournament`-tabellen er delt). `Roster
|
||||
EntryUpdate` (tidligere KUN `is_captain: bool` påkrevd) lagt om til
|
||||
`exclude_unset`-PATCH-semantikk. Ny `PATCH .../participants/{id}` i
|
||||
`individual_tournaments.py` (fantes ikke før). Frontend: "Klasser"-kort
|
||||
i BÅDE `tournament-detail.tsx` og `individual-tournament-detail.tsx`,
|
||||
utslag-forhåndsutfylling i `session-blind-draw.tsx`s `AddSlotForm` og
|
||||
`individual-tournament-detail.tsx`s `AssignRoundParticipantControl`,
|
||||
klasse-gruppert `LeaderboardTab` (individuelle turneringer). Se
|
||||
CHANGELOG.md 2026-08-04 for full bygge-/verifiseringsdetalj (inkl. tall-
|
||||
for-tall-bekreftet leaderboard-rangering per klasse i ekte nettleser).
|
||||
**Rullet ut live 2026-08-04**, bruker bekreftet eksplisitt.
|
||||
|
||||
---
|
||||
|
||||
## Åpne spørsmål (ikke besluttet ennå)
|
||||
|
||||
Disse må avklares før eller under de relevante fasene:
|
||||
|
|
|
|||
88
CHANGELOG.md
88
CHANGELOG.md
|
|
@ -7032,3 +7032,91 @@ Neste steg:
|
|||
så dette er samme build som scratch-verifisert, ikke i tillegg
|
||||
egenhendig bekreftet mot ekte produksjonsdata. Bekreft ved neste
|
||||
faktiske turnering.
|
||||
17. **Konkurranseklasser ("Damer fra 44, Herrer fra 50+") — BYGGET,
|
||||
SCRATCH-VERIFISERT OG LIVE 2026-08-04, migrasjon 053.** Brukeren
|
||||
spurte om det var mulig å sette opp runder i en turnering slik at
|
||||
f.eks. damer spiller fra utslag 44 mens herrer spiller fra 50+.
|
||||
Svaret var at DELER allerede virket (hver deltaker i en match/runde
|
||||
fikk allerede sitt eget `tee_id`, backend validerte allerede at
|
||||
utslaget hadde rating for spillerens kjønn) -- men et manuelt valg
|
||||
per spiller hver gang, ingen gjenbrukbar "klasse". Brukeren ba om en
|
||||
ekte klasse-mekanisme, "samt andre parametre som er relevante i en
|
||||
slik problemstilling."
|
||||
Full plan-modus-runde med to `AskUserQuestion`-avklaringer FØR
|
||||
bygging (samme disiplin som ADR-037/ADR-039): (1) klasser er FRITT
|
||||
NAVNGITTE (ikke bare kjønn) med et valgfritt standardutslag, ikke en
|
||||
fast kjønn+alder-modell -- dekker kjønn/alder/HCP eller annet uten at
|
||||
systemet må forstå forskjellen; (2) klasse gir EGEN RESULTATLISTE --
|
||||
men KUN i individuelle turneringer (ADR-037, flatt felt). I
|
||||
lagturneringer (ADR-011, to lag) er poeng knyttet til hele kamper,
|
||||
ikke enkeltspillere -- brukeren bekreftet eksplisitt at klasse der
|
||||
KUN skal foreslå utslag, ingen leaderboard-splitting (det finnes fra
|
||||
før et smalt per-økt individuelt leaderboard for singles/fourball-
|
||||
slagspill, `fetch_individual_leaderboard` -- IKKE noe denne runden
|
||||
bygger videre på); (3) gjelder org-lagturneringer OG org-individuelle
|
||||
turneringer, ikke frittstående personlige runder.
|
||||
**Skjema** (`053_tournament_classes.sql`): ny delt `tournament_class`-
|
||||
tabell (id/organization_id/tournament_id/name/default_tee_id,
|
||||
`UNIQUE(tournament_id, name)`) -- delt mellom begge turneringstyper
|
||||
siden begge peker til samme `tournament`-tabell (ADR-037s
|
||||
`format_type`-mønster), unngår duplisering. To nye NULLABLE FK-
|
||||
kolonner (`ON DELETE SET NULL`, samme mønster som `tournament_round_
|
||||
bbb_hole`): `team_roster.class_id` og `tournament_participant.
|
||||
class_id`. Samme `org_isolation`-RLS-loop som migrasjon 040.
|
||||
**Backend**: ny klasse-CRUD (`GET/POST/PATCH/DELETE .../classes`) i
|
||||
`tournaments.py` (delt fil, siden `tournament`-tabellen er delt).
|
||||
`RosterEntryCreate`/`RosterEntry` fikk `class_id`/`class_name`;
|
||||
`RosterEntryUpdate` (tidligere KUN `is_captain: bool` påkrevd)
|
||||
lagt om til `exclude_unset`-PATCH-semantikk (samme mønster som
|
||||
`TournamentUpdate`/`SponsorUpdate` fra presentasjons-panel-runden)
|
||||
slik at klasse kan settes uten å tvinge et samtidig kaptein-valg.
|
||||
`TournamentParticipantCreate`/`Out` (individual_tournaments.py) fikk
|
||||
samme felt, pluss en NY `PATCH .../participants/{id}` (fantes ikke
|
||||
før -- kun POST/GET/DELETE). `individual_leaderboard` utvidet med
|
||||
`class_id`/`class_name` i SELECT+respons -- selve summerings-/
|
||||
sorteringslogikken UENDRET, frontend grupperer den allerede sorterte
|
||||
listen visuelt (stabil gruppering bevarer riktig rangering per
|
||||
klasse, ingen ny motorlogikk i `handicap_engine.py` -- verifisert:
|
||||
98/98 eksisterende enhetstester fortsatt grønne, ingen regresjon).
|
||||
**Frontend**: "Klasser"-kort (opprett/slett, kaskaderende bane→
|
||||
utslag-velger for standardutslag) i BÅDE `tournament-detail.tsx`
|
||||
("Lag og spillere"-fanen) og `individual-tournament-detail.tsx`
|
||||
(Oppsett-fanen). Utslag-forhåndsutfylling i to steder --
|
||||
`session-blind-draw.tsx`s `AddSlotForm` (lagturneringer) og
|
||||
`individual-tournament-detail.tsx`s `AssignRoundParticipantControl`
|
||||
(individuelle turneringer) -- begge en `useEffect` som slår opp valgt
|
||||
spillers klasse → standardutslag når spilleren velges, KUN hvis det
|
||||
utslaget faktisk finnes på DENNE øktens/rundens bane (klassens
|
||||
standardutslag kan tilhøre en annen bane), fortsatt fritt
|
||||
overstyrbart. Ren frontend-bekvemmelighet, samme "gjenbruk et
|
||||
eksisterende felt, ikke en ny backend-mekanisme"-prinsipp som
|
||||
`new-round.tsx`s eksisterende kjønnsfilter/-default. `LeaderboardTab`
|
||||
(individuelle turneringer) grupperer den mottatte, allerede sorterte
|
||||
listen på `class_id`, hver klasse får egen seksjonsoverskrift +
|
||||
egen 1/2/3-rangering INNAD i klassen -- ingen klasser opprettet =
|
||||
identisk med tidligere flat visning, bakoverkompatibelt uten
|
||||
migrasjonsflagg.
|
||||
**Scratch-verifisert grundig** (isolert `teecup_app_scratch`-rolle +
|
||||
isolert scratch-MinIO + engangs API-/frontend-container, ekte
|
||||
nettleser-innlogging inkl. 2FA): full API-rundtur (klasse-CRUD,
|
||||
roster-/deltaker-PATCH med class_id, `ON DELETE SET NULL` bekreftet
|
||||
ved klasseslettelse), ekte nettleser-klikk gjennom BEGGE
|
||||
turneringstyper -- lagturnering: opprettet klasser via UI-skjemaet
|
||||
(kaskaderende bane→utslag bekreftet), tildelte klasse via
|
||||
dropdown-menyen, bekreftet utslag forhåndsvalgt korrekt idet en
|
||||
spiller med klasse ble valgt i `AddSlotForm` (Kari→44, Ola→56);
|
||||
individuell turnering: samme mønster i `AssignRoundParticipantControl`
|
||||
(Bjørn Ege→56), pluss det klasse-delte leaderboardet bekreftet
|
||||
visuelt korrekt -- "DAMER"-seksjon viste Kari (72 slag, rang 1) foran
|
||||
Siv (108 slag, rang 2), "HERRER" viste Ola alene (90 slag, rang 1),
|
||||
tallene håndregnet og stemte eksakt (par/+18/+36 mot faktisk
|
||||
innsendt score). `test_isolation.sql` 12/12 uendret, ekte
|
||||
typesjekket produksjonsbuild (fanget og rettet ETT reelt
|
||||
TypeScript-funn under selve verifiseringen: `classes`-propen manglet
|
||||
på `TeamColumn` i `session-blind-draw.tsx` -- `AddSlotForm` ligger i
|
||||
en underkomponent som ikke automatisk arver overordnet komponents
|
||||
state, måtte tres eksplisitt gjennom).
|
||||
**Rullet ut live 2026-08-04**, bruker bekreftet eksplisitt: migrasjon
|
||||
053 mot ekte `teecup_db`, `docker compose up -d --build teecup_api
|
||||
teecup_frontend`, begge containere boot-et rent, `/health`/
|
||||
`/dashboard` → 200.
|
||||
|
|
|
|||
|
|
@ -3967,6 +3967,53 @@ IKKE stilt til V0 ennå. Egen, senere, liten vurdering om ønskelig.
|
|||
|
||||
---
|
||||
|
||||
## Konkurranseklasser ("Damer fra 44, Herrer fra 50+") — ✅ HELT FERDIG, BYGGET, SCRATCH-/BROWSERVERIFISERT OG LIVE 2026-08-04 (ADR-041)
|
||||
|
||||
Brukeren spurte om det var mulig å sette opp runder i en turnering slik
|
||||
at f.eks. damer spiller fra utslag 44 mens herrer spiller fra 50+. Full
|
||||
plan-modus-runde med to `AskUserQuestion`-avklaringer FØR bygging (samme
|
||||
disiplin som ADR-037/039) — se ADR-041 for de fire load-bærende
|
||||
beslutningene (fritt navngitte klasser, delt tabell mellom begge
|
||||
turneringstyper, standardutslag som ren frontend-bekvemmelighet, og —
|
||||
den mest substansielle avklaringen — egen resultatliste KUN i
|
||||
individuelle turneringer, aldri i lagturneringer siden poeng der er
|
||||
knyttet til hele kamper).
|
||||
|
||||
Kort: ny `tournament_class`-tabell (migrasjon 053, org-isolert RLS) +
|
||||
nullable `class_id` på `team_roster`/`tournament_participant` (`ON
|
||||
DELETE SET NULL`). Organisator oppretter klasser med navn + valgfritt
|
||||
standardutslag i et nytt "Klasser"-kort (BÅDE `tournament-detail.tsx` og
|
||||
`individual-tournament-detail.tsx`). Standardutslaget forhåndsvelges
|
||||
automatisk når en spiller med klasse legges til en match/runde (fortsatt
|
||||
overstyrbart) — INGEN endring i selve `tee_id`-kontrakten, som allerede
|
||||
var required og satt per deltaker. I individuelle turneringer deler
|
||||
`individual_leaderboard` seg nå i egne, riktig rangerte seksjoner per
|
||||
klasse; i lagturneringer er klasse bevisst KUN et utslag-forslag, ingen
|
||||
leaderboard-endring (bekreftet med bruker — matchpoeng er lag-mot-lag,
|
||||
ikke enkeltspiller-atomisk).
|
||||
|
||||
**Scratch-/browserverifisert grundig** (isolert `teecup_app_scratch`-
|
||||
rolle + engangs API-/frontend-container, ekte nettleser-innlogging inkl.
|
||||
2FA): full API-rundtur, ekte klikk gjennom BEGGE turneringstyper —
|
||||
kaskaderende bane→utslag-velger ved klasse-opprettelse, dropdown-
|
||||
klassetildeling, utslag-forhåndsutfylling bekreftet i `AddSlotForm` OG
|
||||
`AssignRoundParticipantControl`, og det klasse-delte leaderboardet
|
||||
tall-for-tall bekreftet korrekt (Damer: Kari 72 slag rang 1, Siv 108
|
||||
slag rang 2; Herrer: Ola 90 slag rang 1 — alle mot håndregnet
|
||||
slagsum). 98/98 eksisterende `handicap_engine.py`-enhetstester uendret
|
||||
(ingen ny motorlogikk), `test_isolation.sql` 12/12 uendret. Ett reelt
|
||||
TypeScript-funn under selve verifiseringen (ikke antatt riktig fra
|
||||
implementasjonen alene): `classes`-propen manglet på `TeamColumn` i
|
||||
`session-blind-draw.tsx` (egen underkomponent, arver ikke overordnet
|
||||
komponents state automatisk) — fanget av produksjonsbuildens
|
||||
typesjekk, rettet før utrulling.
|
||||
|
||||
**Rullet ut live 2026-08-04**, bruker bekreftet eksplisitt: migrasjon
|
||||
053 mot ekte `teecup_db`, `docker compose up -d --build teecup_api
|
||||
teecup_frontend`. Full detalj i CHANGELOG.md 2026-08-04 og ADR-041.
|
||||
|
||||
---
|
||||
|
||||
## Bevisst endret fra opprinnelige (Gemini-)råd
|
||||
|
||||
- 🔀 **Banedata:** API mot teeoff (ADR-004), IKKE direkte delt database. Direkte
|
||||
|
|
|
|||
Loading…
Reference in a new issue