Alle 5 punktene i planen bestått mot scratch-databasen:
Gjenskapte en avgjort match ("10&8 (A)")
Nytt hull (14) på avgjort match → 409 ✓
Korrigering av allerede talt hull (1) → 409 ✓
GET scorecard fortsatt leselig for avgjort match ✓
Fersk, ikke-avgjort match tar fortsatt imot hull normalt ✓
8.5 KiB
8.5 KiB
TeeCup — Funksjons-backlog
Formål: fange ALT som er ønsket for TeeCup på ett sted, slik at intet krav går tapt mellom økter, modeller eller samtaler. Kilder: de to opprinnelige Gemini-samtalene (funksjonalitet + Docker) og arbeidet gjort med Claude.
Status-koder: ✅ ferdig · 🔨 pågår · 📋 planlagt/fanget · ❓ trenger beslutning · 🔀 endret fra opprinnelig råd · 💤 utsatt (bevisst)
Sist oppdatert: 2026-07-16
Fundament (bygget)
| Funksjon | Status | Notat |
|---|---|---|
| Handicap-/matchmotor (testet) | ✅ | 24 tester, R&A-verifisert. Erstatter Geminis løse JS-funksjon. |
| Formater: singles, fourball, foursome, greensome, scramble | ✅ | I motoren, allowance som konfig. |
| Brutto/netto + prosent-allowance (75 %, 90 %, 3/4) | ✅ | ADR-005. Prosentene bekreftet mot Golf GameBook (ADR-014). |
| 9-hulls (front/back) slagfordeling | ✅ | ADR-008, egen funksjon + test. |
| Miksede formater per turnering (økter) | ✅ | ADR-007. Ryder Cup-strukturen. |
| Spiller-pool m/ reserver, delvis deltakelse | ✅ | ADR-007. |
| Multi-tenant skjema + RLS | ✅ | ADR-001/003. Isolasjon bevist med oppførselstest. |
| Dedikert app-rolle (ingen superuser/BYPASSRLS) | ✅ | migrasjon 002. |
| API: oppsett (spillere/lag/roster/økter/matcher/blind draw) | ✅ | Verifisert for ekte mot scratch-db + engangscontainer. |
| API: scoring (hole_score/match_hole_result, matchstatus, handicap-beregning) | ✅ | ADR-012/014. Verifisert for ekte, inkl. fourball better-ball og race-sikker recompute. |
| Banedata fra teeoff via API | 🔀 | ADR-004. Endret fra Geminis «delt database direkte». |
| Konfigurerbar handicap-pipeline (4 brytere) | ✅ | ADR-014. Bygget i app/handicap.py, brukt av scoring-runden. |
Ønsket, men IKKE fanget før nå (fra Gemini-samtalene)
Brukerroller (utover org-medlemskap)
- Status: ❓ trenger beslutning
- De opprinnelige samtalene beskriver: turneringsadmin, lagkaptein, spiller, tilskuer (les-only, følger live uten skriverettigheter).
- Vi har i dag org-roller (owner/admin/member) +
is_captainpå roster. - Mangler: «tilskuer» som begrep. Henger sammen med hvem som ser den offentlige feeden (se Kommunikasjon). Kaptein-rollen bør kanskje gi spesifikke rettigheter (sette oppstilling), ikke bare være et flagg.
Scoring-autorisasjon: hvem fører, hvem korrigerer, hvem lukker (rejst 2026-07-16)
- Status: ❓ trenger beslutning — direkte oppfølger av «Brukerroller» over.
- Hvem fører score i dag: alle med en
team_roster-rad på laget (samme minimale grense som deltaker/lås, se ADR-013-relatert kode). Ikke kaptein-only, ikke begrenset til de(n) som faktisk spiller matchen. - Hvem kan korrigere en ført score i dag: akkurat de samme — skriving er en
upsert (
ON CONFLICT ... DO UPDATE), så en korrigering er ikke skilt fra en førstegangs-innføring. Ingen godkjenning fra motstanderen, ingen audit-trail (forrige verdi overskrives sporløst). - Match-lås ved avgjørelse: ✅ FIKSET 2026-07-16.
submit_hole_scoreogsubmit_hole_result(app/routers/scoring.py) avviser nå med 409 («Matchen er avgjort og kan ikke lenger endres.») FØR upserten kjøres, hvismatch.points_side_a IS NOT NULL— dette er allerede et pålitelig, entydig signal siden kolonnen kun settes nårcompute_match_statesier matchen er avgjort. Gjelder BÅDE nye hull og korrigering av allerede talte hull. Verifisert: hull etter avgjørelse avvist, korrigering av et talt hull avvist, GET scorecard fortsatt leselig, ikke-avgjorte matcher upåvirket. Bevisst IKKE bygget: ingen manuell «avslutt match før den er avgjort»-handling (det grenser mot walkover under, fortsatt utsatt). Turnering har etstatus-felt (draft/active/completed/archived) men INGEN endepunkt endrer det ennå — organisator kan ikke markere en turnering ferdig via API-et i dag (eget, senere punkt). - Manglende WO/konsesjon: hvis en side aldri stiller nok spillere
(
match_participant-antallet når aldri det økten krever), beregnes handicap ALDRI (seapp/handicap.py), og matchen kan derfor ALDRI få et hull-resultat — den blir hengende uavgjort for alltid. Det finnes ingen «gi bort hullet/matchen/turneringen»-mekanisme (walkover/konsesjon) i det hele tatt ennå — verken datamodell eller endepunkt. - Avgjort 2026-07-16:
- Match-lås ved avgjørelse: ✅ bygget — se eget punkt over. Automatisk (ikke en handling noen utfører), så «hvem får låse» ble aldri et spørsmål som trengte avklaring.
- Walkover/konsesjon VENTER til brukerroller (kaptein/organisator, punktet over) er avgjort — å bygge den nå på dagens løse «rostret på laget»-grense betyr sannsynligvis å bygge den om senere.
- Fortsatt åpent: (a) skal score-føring begrenses til faktiske matchdeltakere (ikke bare «noen på laget»)? (b) skal korrigering kreve motpartens godkjenning, eller er upsert-modellen god nok for v1? (c) skal turnering-status (draft/active/completed/archived) kunne settes via API?
Blind draw (skjult lagoppstilling)
- Status: ✅ skjema (migrasjon 003,
lineup_lock) + API bygget og verifisert (app/routers/matches.py: synlighetsfilter i SQL, ikke Python-filter — se ADR-013). - Kapteinene låser oppstillingen skjult; matchene avsløres samtidig når begge er ferdige.
- Gjenstår: hvem som FÅR låse et lag er i dag bare «rostret på laget», ikke kaptein-spesifikt — se «Brukerroller» over.
Forenklet scoreføring (uten slagtall)
- Status: ✅ skjema (migrasjon 003) + API bygget og verifisert
(
app/routers/scoring.py:hole-scoresforstroke-modus,hole-resultsforhole_result-modus, begge mater sammecompute_match_state).
Bøtekasse (Kangaroo Court)
- Status: 📋 planlagt
- Meld inn overtramp med bøter («kastet kølla på hull 4»).
- Henger sammen med Kommunikasjon: bøter deles i feeden. Sannsynligvis en egen post-type i meldingsmodellen.
Flerårig statistikk / historikk / MVP
- Status: 📋 planlagt (datamodell støtter det allerede)
- Seiersprosent i singelmatcher, historisk MVP, statistikk over år.
- Datamodellen tillater dette fordi spillere lever på org-nivå og gjenbrukes på tvers av turneringer, og handicap fryses per turnering (reproduserbart).
Push-varsler
- Status: 📋 planlagt (infrastruktur)
- «BREAKING: X vant matchen». PWA push. Egen infrastruktur-bit.
Sanntid (WebSockets)
- Status: ❓ trenger beslutning
- Live leaderboard og chat som oppdateres uten refresh. Vi har leaderboard-viewet, men ikke sanntidsleveringen. Valg: WebSockets vs. polling.
Knockout / cup-turnering (egen turneringstype)
- Status: 💤 utsatt (egen fremtidig type, ADR-011)
- Utslagsmatcher: 128 spillere → finale + bronsefinale. Rundene er avhengige (vinner går videre), krever bracket/progresjon, seeding, fripass. IKKE i v1.
- v1 er låst til nøyaktig to lag (Ryder Cup-format). Match-modellen er generell, så denne typen kan legges til senere uten dataomskriving — den legger bare til et progresjons-lag.
Kommunikasjon (under design)
| Del | Status | Notat |
|---|---|---|
| Lag-intern chat («det hemmelige rommet») | 🔨 | Bekreftet ønsket. Kanal m/ scope team. |
| Offentlig runde-feed («Banter Board») | ❓ | Synlighetsnivå ikke besluttet (deltakere/org/offentlig lenke). |
| Bilder i feed/chat | 📋 | v1. Objektlagring (MinIO), presigned opplasting. |
| Video | 💤 | Arkitekt for det, bygg senere (ADR-forslag). |
| 1-til-1 direktemeldinger | 💤 | Gemini frarådet for v1; ikke etterspurt av deg. |
| Moderering (for offentlig innhold) | ❓ | Kreves hvis «alle med lenken». Mønster finnes i teeoff. |
UX / frontend (senere fase)
- 📋 Høy kontrast, dark/light, store +/- knapper, stor «Neste hull»-knapp (banebruk i sollys/med solbriller).
- ✅ Offline-first (ADR-006) — prinsipp besluttet; implementasjon senere.
- 📋 PWA: manifest, service workers, «Legg til på hjemskjerm».
Bevisst endret fra opprinnelige (Gemini-)råd
- 🔀 Banedata: API mot teeoff (ADR-004), IKKE direkte delt database. Direkte DB-kobling ville låst TeeCup til teeoffs skjemaendringer.
- 🔀 Handicap-motor: egen testet Python-modul, ikke den innlimte JS-funksjonen (som bl.a. ikke håndterte 9-hull eller konfigurerbare allowances korrekt).
- 🔀 Tenant-modell: organisasjon som tenant med RLS, ikke bare «turnering-ID».
- 🔀 Sesjons-secret: egne secrets for TeeCup, ikke fallback til teeoffs (teeoff selv bruker en slik fallback — bevisst unngått her).