diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 1b46332..2fbe7d1 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -345,7 +345,9 @@ "Bash(sort -t_ -k1 -n)", "Bash(curl -s -o /dev/null -w \"%{http_code}\\\\n\" https://teecup.teeoff.no/)", "Bash(curl -s -o /dev/null -w \"%{http_code}\\\\n\" https://teecup.teeoff.no/account)", - "Bash(curl -s -o /dev/null -w \"%{http_code}\\\\n\" https://teeoff.no/)" + "Bash(curl -s -o /dev/null -w \"%{http_code}\\\\n\" https://teeoff.no/)", + "Bash(sudo apt-get install -y poppler-utils)", + "Bash(sudo -n apt-get install -y poppler-utils)" ], "additionalDirectories": [ "/opt/teeoff/deploy", diff --git a/ARCHITECTURE_DECISIONS.md b/ARCHITECTURE_DECISIONS.md index 6af8f8c..3f46fa6 100644 --- a/ARCHITECTURE_DECISIONS.md +++ b/ARCHITECTURE_DECISIONS.md @@ -5,7 +5,7 @@ > Endre aldri en beslutning uten å legge til en ny ADR som erstatter den — historikken skal bevares. **Status:** Levende dokument -**Sist oppdatert:** 2026-07-18 +**Sist oppdatert:** 2026-07-22 --- @@ -1590,6 +1590,266 @@ upåvirket. --- +## ADR-033: Frittstående rundeføring med detaljert statistikk + +Reist av brukeren 2026-07-21 (se FEATURE_BACKLOG.md), utdypet 2026-07-22 med +konkrete statistikk-felt og en eksplisitt ambisjon: **dette skal bli +appens hovedfokus** — når rundeføring med detaljert statistikk er på +plass, skal turneringsoppsett deretter gjøres ekstremt enkelt. Dette er +den største enkeltbeslutningen i prosjektet siden ADR-001, fordi den +direkte utfordrer tenant-invarianten ("organisasjon er isolasjonsenheten") +CLAUDE.md hittil har krevd en ny ADR for å bryte. + +Fire load-bærende delbeslutninger ble avklart eksplisitt med bruker +(AskUserQuestion) FØR resten av denne ADR-en ble skrevet. De tre +HCP-PDF-ene (se referanse i CLAUDE.md) ble lest i sin helhet som +forberedelse til Beslutning F/G, i tråd med prosjektets stående instruks +om å ikke anta HCP-regler fra hukommelse. + +### Beslutning A — Eierskapsmønster: nytt, parallelt, IKKE en skjult organisasjon + +En frittstående runde eies av en BRUKER (`app_user.id`), ikke en +organisasjon. Ingen ny RLS-policy-familie trengs for dette — prosjektet +har ALLEREDE et etablert, bevist mønster for nøyaktig denne typen data: +personlig profil (migrasjon 015), sekundær e-post (017) og +HCP-historikk (018) bruker alle `plain_connection()` (ingen +`app.current_org` satt) med eksplisitt `WHERE user_id = $1`-filtrering i +hver spørring, i stedet for RLS. Frittstående runder gjenbruker dette +mønsteret uendret — nye tabeller (`round`, `round_participant`, +`round_hole_stat`, se Beslutning B) har en `owner_user_id`-kolonne, INGEN +`organization_id`, og INGEN RLS-policy — autorisasjon håndheves i +app-laget (eier ser/redigerer egne runder; en deltaker uten konto har +ingen egen tilgang, se Beslutning D). + +**Begrunnelse for å avvise "usynlig personlig organisasjon"-alternativet:** +en skjult organisasjon måtte for alltid filtreres bort fra ENHVER +org-listing/-bytter/-medlemsside/fremtidig fakturering — en varig +lekkasjerisiko som vokser for hver ny org-scopet skjerm som bygges +fremover. Det parallelle mønsteret er ikke bare konseptuelt riktigere, +det er også ALLEREDE bygget og bevist for personlig data — dette er +mindre nytt arbeid enn først antatt i brainstorm-runden. + +### Beslutning B — Statistikk-datamodell: fast sett navngitte felt, ikke fri slag-for-slag-logg + +Per hull, i tillegg til slagtall (som i dag): kølle brukt ved utslag, +utslags-resultat (fairway/høyre/venstre — kun relevant på par 4/5), +innspill-resultat (traff/lang/kort/høyre/venstre), antall putter, lengde +på første putt, antall chip, antall bunkerslag, antall straffeslag. + +**Presis definisjon av "innspillsslaget"** (nødvendig for at GIR skal +kunne beregnes automatisk, uavhengig av hullets par): SISTE slag før +første putt. På en par 3 er dette utslaget selv; på en par 4 normalt +2. slag; på en par 5 kan det være 2. ELLER 3. slag (f.eks. ved en +layup) — modellen trenger ikke vite hvilket slagnummer det var, kun at +det faktisk er det siste FØR putting startet. + +**GIR er DERIVERT, ikke tastet inn direkte:** Green In Regulation = sant +hvis innspill-resultat er "traff" OG antall slag brukt til da er ≤ +(hullets par − 2). Utslag-resultat og innspill-resultat er derimot +OBSERVERTE felt spilleren selv taster inn — appen har ingen GPS og kan +ikke oppdage dette selv. + +**UX-prinsipp, ikke bare et skjema-valg:** ALLE detalj-felt er valgfrie +per hull. Rask "bare slagtall"-registrering skal alltid fungere uendret +— dette er bevisst for å unngå at "hovedfokus" i praksis blir for +tungvint til daglig bruk (samme klasse avveining som gjorde at +detaljerte felt ble utsatt fra scorekort-rundene tidligere i prosjektet). + +**Avvist:** fri slag-for-slag-logging (hvert slag = egen rad). Ville +dekket samme behov, men med vesentlig tyngre registrering og et mer +komplekst skjema fra dag én, uten at brukerens beskrevne behov faktisk +krever det. + +### Beslutning C — Banedata for frittstående runder: LIVE oppslag mot teeoff, bekreftet av bruker + +Custom-baner er i dag org-scopet (`course.organization_id`) — dette +fungerer ikke uten organisasjon. **Bekreftet med bruker 2026-07-22:** +offisielle baner slås opp LIVE mot teeoff sitt API ved behov (samme +lesende API som ADR-019, IKKE en importert/kopiert kopi som i +turnering-flyten). ADR-019 sin "importer, ikke slå opp live"-beslutning +var begrunnet i turneringers behov for reproduserbarhet (et resultat skal +ikke endre seg retroaktivt hvis banedata oppdateres) — en frittstående +statistikk-runde har ikke samme behov, og live oppslag unngår i tillegg +dagens duplisering (hver org som importerer "Tjøme Golfklubb" i dag lager +sin egen kopi). Egendefinerte baner som ikke finnes i teeoff: global +banekatalog uten organisasjonstilknytning, søk-før-opprett for å begrense +duplikater (denne delen — selve den globale katalogen for CUSTOM baner — +er fortsatt kun min anbefaling, ikke eksplisitt bekreftet punkt for +punkt, men følger naturlig av at live-oppslag-beslutningen er tatt). + +### Beslutning D — Deltakere i flighten uten TeeCup-konto: gjenbruk eksisterende mønster + +`round_participant` får en nullable `user_id` (ekte TeeCup-bruker som +spiller med) og et `guest_name`-fritekstfelt (ingen konto). Samme +konsept som `player` uten `user_id` i org-sammenheng. E-post-basert +kobling i etterkant (samme mønster som `link_player_by_email`, +migrasjon 008) er en naturlig, men IKKE besluttet, senere utvidelse — +notert som åpent punkt under, ikke bygget i første omgang. + +### Beslutning E — Hullantall og starthull: ingen tvang, kun standardvalg + +18/første ni/siste ni er standardvalg i UI-et, ikke en database- +begrensning. Spilleren velger starthull fritt (gjenbruk av samme +`start_hole`-konsept som `session.start_hole`, ADR-015). En runde kan +avsluttes etter et hvilket som helst antall hull uten et forhånds- +deklarert mål — statistikk og par-sum regnes alltid fra hullene FAKTISK +spilt. + +### Beslutning F — HCP-tellende runde: presist kildebelagt fra WHS Rules of Handicapping 2024 + +Brukeren lastet opp den offisielle kilden 2026-07-22 ("WHS Rules of +Handicapping 2024", USGA/R&A — IKKE en tredjeparts-blogg som de to andre +PDF-ene). Dette erstatter den tidligere, mer omtrentlige "minst 9 +hull"-antakelsen med presise regler (**Rule 2.2**): + +- **18-hulls-type runde:** minimum **10 av 18 hull** må spilles for at + scoren skal være akseptabel. De resterende (inntil 8) uspilte hullene + fylles med en "expected score" (se under), IKKE net par (net par- + metoden ble erstattet av expected-score-metoden i 2024-revisjonen — + et prinsipielt skifte fra tidligere WHS-versjoner, verdt å merke seg + siden eldre kilder/hukommelse fortsatt kan referere net par). +- **9-hulls-type runde:** ALLE 9 hull i det spesifikke, ratede 9-hulls- + settet (front ELLER back, de eneste to som normalt har egen Course/ + Slope Rating) må spilles. Færre enn 9 hull totalt → scoren er IKKE + akseptabel for HCP-formål i det hele tatt, uansett grunn. +- **Konsekvens for Beslutning E (fritt valgt starthull):** den frie + starthull-friheten gjelder fullt ut for CASUAL, ikke-HCP-tellende + logging. For at en runde skal telle mot HCP, må de spilte hullene + derimot samsvare med enten (a) et sammenhengende 10-18-hulls-utsnitt av + banens 18-hulls-rating, eller (b) nøyaktig banens ratede front-9 eller + back-9 — en vilkårlig 9-hulls-strekning (f.eks. hull 5-13) har ingen + egen Course/Slope Rating og kan derfor aldri bli HCP-tellende. Dette må + kommuniseres tydelig i UI-et, ikke bare håndheves stille i motoren. + +### Beslutning G — HCP-indeksberegning bygges NÅ, presist kildebelagt (WHS Rules of Handicapping 2024) + +Full kjede, alle tall/formler hentet direkte fra kilden (Rule 3/5/6), +ikke hukommelse: + +1. **Net Double Bogey** (maks hull-score for HCP-formål) = hullets par + + 2 + spillerens handicapslag på det hullet (Rule 3.1b) — allerede + dekket av eksisterende `allocate_strokes_by_index`/ + `allocate_over_played_holes`, ingen endring. +2. **Uspilte hull** (Rule 3.2b, NY metode i 2024): en "expected score" + beregnes for hvert uspilt hull ut fra spillerens HCP-indeks og banens + standard vanskelighetsgrad, og kombineres med differensialen fra de + faktisk spilte hullene. Kun gyldig når minimumsantallet (Beslutning F) + er oppfylt og grunnen er gyldig (Rule 3.2a — vær/skade/mørke/hull satt + ut av spill; IKKE "unngå en høy score"). +3. **Ikke fullført hull (spilleren plukker opp)** (Rule 3.3): laveste av + "most likely score" (allerede tatte slag + sannsynlig antall til + fullføring, tabell basert på ballens avstand fra hullet + eventuelle + straffeslag) eller net double bogey. +4. **18-hulls Score Differential** (Rule 5.1a) = `(113 ÷ Slope Rating) × + (Adjusted Gross Score − Course Rating − PCC-justering)`, avrundet til + nærmeste tidel (,5 rundes opp). +5. **9-hulls Score Differential** (Rule 5.1b) = `(113 ÷ 9-hulls Slope + Rating) × (9-hulls Adjusted Gross Score − 9-hulls Course Rating − + (0,5 × PCC-justering))` — holdes UAVRUNDET til den er kombinert med + spillerens forventede score over de andre 9 hullene til én 18-hulls- + ekvivalent differensial (avrundes FØRST da). +6. **Handicap Index** (Rule 5.2) = gjennomsnitt av de beste 8 av de siste + 20 Score Differentials, avrundet til nærmeste tidel. For færre enn 20 + runder i historikken brukes en egen opptrappingstabell (f.eks. 3 + runder → laveste 1 med justering −2,0; 9-11 runder → snitt av laveste + 3, ingen justering; osv. — full tabell i Rule 5.2a, IKKE en enkel + "gjennomsnitt av alt"-tilnærming for nye spillere). +7. **Low Handicap Index** (Rule 5.7): laveste indeks siste 365 dager — + nødvendig referansepunkt for cap-mekanismen under, må lagres/spores + per bruker. +8. **Soft cap / hard cap** (Rule 5.8): øker en oppdatert indeks mer enn + 3,0 slag over Low Handicap Index, begrenses overskytende beløp til + 50 %; mer enn 5,0 slag over Low Handicap Index er et absolutt tak. + Ingen nedre grense på hvor mye indeksen kan SYNKE. +9. **Maksimal indeks** (Rule 5.3) = 54,0 — samsvarer med det allerede + satte `le=54`-taket i `ProfileUpdate` fra profil-fullførings-runden + (2026-07-22), god konsistens-bekreftelse. +10. **9-hulls Course Handicap** (Rule 6.1b) — **NY, presis detalj, + AVVIKER fra 18-hulls-formelen:** `(Index ÷ 2, avrundet til nærmeste + tidel) × (9-hulls Slope ÷ 113) + (9-hulls Course Rating − 9-hulls + Par)`. Dette er IKKE det samme som å bruke full indeks mot en + 9-hulls rating — indeksen halveres først. **Denne formelen gjelder + frittstående 9-hulls-RUNDER (denne ADR-en), IKKE det eksisterende + front_9/back_9-øktoppsettet i turnering-flyten** (ADR-008/2026-07-19- + fiksen, som bevisst bruker full_18-rating for HELT ANDRE grunner — + slagfordeling innad i en turneringsmatch, ikke offisiell HCP- + runde-innsending. De to må IKKE forveksles eller slås sammen uten en + egen vurdering.) +11. **18-hulls Course Handicap** (Rule 6.1a) = `Index × (Slope ÷ 113) + + (Course Rating − Par)` — allerede korrekt implementert + (`course_handicap_raw`, verifisert ved grep), ingen endring. +12. **Playing Handicap** (Rule 6.2) — uendret, allerede korrekt dekket av + eksisterende allowance-strategier (ADR-014). + +**Dette er i hovedsak en HELT NY komponent i `handicap_engine.py`** +(punktene 4-9), ikke en utvidelse av det eksisterende — dagens motor tar +alltid indeksen som et KJENT input; den har aldri regnet UT en indeks fra +en historie av runder. Punkt 10 er en presisering/utvidelse av +eksisterende kode for 9-hulls-tilfellet. Holdes ren og testet isolert, +som resten av `handicap_engine.py` (ADR-005). + +**Bevisst UTENFOR omfang i første byggerunde, til tross for at kilden nå +finnes** (for å holde v1 håndterbar — presist avgrenset, ikke bare +utsatt i vage vendinger): +- **Playing Conditions Calculation (PCC)** (Rule 5.6) — full prosedyre + funnet og forstått (statistisk sammenligning av dagens faktiske scorer + mot forventet, justering −1,0 til +3,0, krever minst 8 aksepterte + scorer på banen samme dag blant spillere med indeks ≤36,0). Ikke + bygget nå — krever et helt annet datagrunnlag (ALLE spilte runder på + en bane en gitt dag på tvers av ALLE brukere) enn det en enkelt + frittstående runde naturlig gir. Runder telles inn UTEN PCC-justering + til dette tas som egen, senere runde. +- **Exceptional Score-reduksjon** (Rule 5.9) — funnet og forstått (en + differensial 7,0-9,9 slag bedre enn gjeldende indeks gir automatisk + −1,0 på de siste 20 differensialene, 10,0+ gir −2,0). Ikke bygget i + v1, notert for senere presisjon. +- **Initial indeks fra færre enn 3 runder, Handicap Committee-skjønn** + (Rule 5.2a) — TeeCup har ingen "Handicap Committee"-rolle; en + forenklet, automatisk variant av opptrappingstabellen brukes i stedet, + uten menneskelig overstyring i v1. + +**Åpent, ikke besluttet:** når en reell WHS-indeks kan beregnes fra +runder, skal manuell redigering av `app_user.handicap_index` +(eksisterende `PATCH /auth/profile`, ADR-031) fortsatt tillates ved +siden av (f.eks. for en spiller uten noen TeeCup-runder ennå), eller skal +feltet bli read-only/auto-beregnet så snart minst én HCP-tellende runde +finnes? Påvirker om `handicap_history` (018) skal gjenbrukes uendret +eller trenger en ny kolonne som skiller "manuelt satt" fra "beregnet fra +runde". + +### Beslutning H — Shotgun- vs. fortløpende start: EGEN, separat ADR (ADR-034) + +Bekreftet med bruker: dette er et turnering/økt-konsept (start_hole per +match i stedet for per økt, samme klokkeslett for alle grupper), uten +reell avhengighet til rundeførings-arkitekturen over. Ikke behandlet +videre her. + +### Ikke besluttet, gjenstår før bygging kan starte + +- Den globale banekatalogen for EGENDEFINERTE (ikke-teeoff) baner + (del av Beslutning C) — naturlig konsekvens av live-oppslag- + beslutningen, men ikke bekreftet punkt for punkt ennå. +- Gjest-e-post-kobling (Beslutning D) — notert, ikke designet i detalj. +- Manuell vs. auto-beregnet HCP-indeks etter at motoren finnes + (Beslutning G) — notert, ikke avgjort. +- Skal turnering-scoring til slutt bruke SAMME statistikk-modell (reist i + brainstorm-runden 2026-07-22, FEATURE_BACKLOG.md) — ikke avgjort, ingen + konsekvens for denne ADR-ens omfang uansett. +- Eksakte tabellnavn/skjema (`round`/`round_participant`/ + `round_hole_stat` er arbeidsnavn i denne ADR-en, ikke endelig + fastlagt) — avgjøres ved migrasjonsskriving. + +**Status: 📋 ADR skrevet OG kildebelagt 2026-07-22, IKKE bygget.** Alle +tre store åpne punktene fra første utkast (banedata, WHS 9-hulls-regel, +full HCP-indeksformel) er nå enten eksplisitt bekreftet med bruker +(Beslutning C) eller presist kildebelagt fra den offisielle WHS Rules of +Handicapping 2024 (Beslutning F/G) — ikke lenger antatt eller tilnærmet. +Neste steg: migrasjon + `handicap_engine.py`-utvidelse (Beslutning G, +punkt 4-10) + API + frontend, med samme inkrementelle +scratch-verifiserte rytme som resten av prosjektet. + +--- + ## Åpne spørsmål (ikke besluttet ennå) Disse må avklares før eller under de relevante fasene: diff --git a/CLAUDE.md b/CLAUDE.md index e8935d4..15ed8b4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2266,13 +2266,35 @@ Neste steg: dashbordet — men spørsmålet om HVA dashbordets tom-tilstand skal vise for en bruker som HAR fullført profilen, men ennå ikke har noen organisasjon/turnering, står fortsatt åpent. -3. **Nytt, stort, IKKE designet:** frittstående rundeføring + detaljert - statistikk (putter/chip/bunkerslag/straffeslag/førsteputt-lengde) UTEN - turnering/organisasjon, reist 2026-07-21. Utfordrer tenant-invarianten - (`organization_id` på alle domenetabeller) direkte — trenger en egen, - dedikert ADR-runde, IKKE noe som skal bygges i forlengelsen av en - vanlig funksjonsrunde. Se full analyse og åpne spørsmål i - FEATURE_BACKLOG.md. +3. **Frittstående rundeføring + detaljert statistikk — ADR-033 skrevet + 2026-07-22, IKKE bygget.** Brukeren avklarte 2026-07-22 at dette skal + bli appens HOVEDFOKUS (turneringsoppsett skal bli ekstremt enkelt + ETTER dette er på plass) — den største enkeltbeslutningen i prosjektet + siden ADR-001. Fire load-bærende delbeslutninger avklart eksplisitt + (AskUserQuestion): nytt parallelt eierskapsmønster keyet på `user_id` + (gjenbruker det allerede beviste `plain_connection()`-mønsteret fra + personlig profil/HCP-historikk/sekundær e-post — IKKE en skjult + personlig organisasjon), fast sett navngitte statistikk-felt per hull + (ikke fri slag-for-slag-logg), full WHS HCP-indeksberegning bygges NÅ + (ikke utsatt), shotgun-start blir egen separat ADR-034. De tre + HCP-PDF-ene lest i sin helhet — Score Differential/Course + Handicap/Net Double Bogey-formlene er hentet derfra (kilde, ikke + hukommelse). + **Oppdatert samme dag:** brukeren bekreftet banedata-spørsmålet (LIVE + oppslag mot teeoff, ikke import — Beslutning C) og lastet opp en + FJERDE PDF, den offisielle "WHS Rules of Handicapping 2024" + (USGA/R&A) — lest i sin helhet, løste presist det som manglet: 9- + hulls-minimumsregelen (Rule 2.2, IKKE bare "minst 9 hull" — en + 9-hulls-runde krever ALLE 9 av et faktisk ratet sett, en 18-hulls- + runde krever minst 10 av 18), full HCP-indeks-pipeline (Score + Differential, Net Double Bogey, expected-score for uspilte hull, beste + 8-av-20, Low Handicap Index, soft/hard cap), OG en ny, presis + 9-hulls-Course-Handicap-formel som HALVERER indeksen først (Rule + 6.1b) — bevisst holdt atskilt fra det eksisterende front_9/back_9- + øktoppsettet i turnering-flyten (ADR-008), som løser et annet problem + av andre grunner. ADR-033 er dermed fullt kildebelagt, ingen store + åpne HCP-regelspørsmål gjenstår. Se ADR-033 i ARCHITECTURE_DECISIONS.md + for full detalj. 4. **Del 1 (fri, ukrevd sekundær-e-post) er nå BYGGET OG LIVE** (2026-07-21, se status over). **Del 2 (ekte konto-sammenslåing) fortsatt IKKE designet:** hva skjer hvis den ønskede adressen ALLEREDE tilhører en diff --git a/FEATURE_BACKLOG.md b/FEATURE_BACKLOG.md index c761bab..6d51649 100644 --- a/FEATURE_BACKLOG.md +++ b/FEATURE_BACKLOG.md @@ -1366,12 +1366,104 @@ tom-skjermens endelige form kan bestemmes. --- -## Frittstående rundeføring + detaljert statistikk (uten turnering/organisasjon) — 📋 NOTERT 2026-07-21, IKKE designet/bygget +## Frittstående rundeføring + detaljert statistikk (uten turnering/organisasjon) — 📋 ADR-033 SKREVET OG KILDEBELAGT 2026-07-22, IKKE bygget + +**Se ADR-033 i ARCHITECTURE_DECISIONS.md for den fulle, besluttede +arkitekturen** (eierskapsmønster, statistikk-datamodell, HCP-indeksmotor). +Brukeren bekreftet 2026-07-22 at teeoff-banedata skal hentes via LIVE +oppslag (ikke import), og lastet opp den offisielle "WHS Rules of +Handicapping 2024" (USGA/R&A) som kilde for HCP-indeksberegningen — alle +tre store åpne punktene fra brainstorm-runden er dermed enten bekreftet +eller presist kildebelagt, ikke lenger antatt. Notatene under er +brainstorm-historikken som ledet frem til ADR-en — beholdt for +sporbarhet, ikke lenger den autoritative kilden for dette punktet. Reist av brukeren 2026-07-21, eksplisitt begrunnet som relevant for hvordan dashbordet skal se ut fremover (se punktet over) — derfor fanget grundig her selv om ingenting bygges i denne runden. +**2026-07-22 — brukeren sier dette skal bli HOVEDFOKUS i appen** (det mest +"kontroversielle" premisset i samtalen): når frittstående rundeføring med +detaljert statistikk er på plass, skal det deretter bli ekstremt enkelt å +sette opp turneringer i ulike formater — altså en reell prioritets- +omveltning, ikke bare en ny funksjon ved siden av de eksisterende. +Fortsatt IKKE designet/bygget — dette er en brainstorm-runde (bedt +eksplisitt om av bruker), ikke en beslutningsrunde. Neste steg når +brukeren er klar: en egen, dedikert ADR-runde (se arkitektur-gaffelen +under). + +**Nye statistikk-elementer lagt til 2026-07-22** (i tillegg til de fem fra +2026-07-21 under): kølle brukt ved utslaget, om utslaget traff fairway +eller var til høyre/venstre for den, automatisk beregnet "green in +regulation" (GIR), og utfallet av innspillet til green (traff/lang/kort/ +høyre/venstre). +**Viktig presisering fra min side, IKKE avklart med bruker ennå:** GIR er +en DERIVERT stat (kan regnes ut fra antall slag brukt + om ballen var på +green) — men fairway-treff og innspill-retning krever at SPILLEREN +vurderer og taster inn utfallet etter hvert slag, appen kan ikke "beregne" +dette uten GPS. Dette betyr i praksis SLAG-FOR-SLAG-registrering (hvert +slag = kølle + utfall/posisjon), ikke bare noen aggregerte tall per hull +slik dagens scorekort gjør — en vesentlig UX-heving fra dagens modell. + +**Fire konkrete spørsmål brukeren stilte, med retning:** +- **Egendefinerte baner hvis de ikke finnes i TeeOff:** ja. Åpent + delspørsmål: uten organisasjon, hvor bor en custom-bane? Custom-baner er + i dag org-scopet (`course.organization_id`). Anbefaling: behold + offisiell teeoff-import (ADR-019) som primærvei (gir korrekt rating + "gratis", avgjørende for HCP-matte), og lag en NY, GLOBAL (ikke + org-scopet) pool for egendefinerte baner — med søk-før-opprett for å + unngå tusenvis av private duplikater av samme bane. +- **Tvinge 18/front9/back9:** nei, kun standardvalg. Konsekvens: par-sum + for statistikk må regnes fra hullene FAKTISK spilt, ikke anta 72. + Øktenes `start_hole`-felt (ADR-015, allerede bygget for turneringer) er + direkte gjenbrukbart. Bør også kunne avsluttes midt i (f.eks. 14 hull) + uten forhåndsdeklarert totalt antall. +- **HCP-tellende krever minst 9 hull:** riktig prinsipp (WHS aksepterer + 9-hulls score), MEN WHS sin faktiske konvertering av en 9-hulls-score + til en Score Differential er en EGEN, presis justering — ikke "halvparten + av 18-hulls-formelen". Nøyaktig den typen regel de tre HCP-PDF-ene + (lastet opp 2026-07-19, se CLAUDE.md) er ment å dekke — MÅ leses før + denne logikken bygges. **Strukturelt større gap oppdaget under + drodlingen:** `handicap_engine.py` regner i dag KUN course handicap/ + slagfordeling fra en ALLEREDE KJENT indeks — den regner IKKE ut selve + HCP-indeksen fra en historikk av runder (WHS sin Score Differential + + snitt-av-beste-8-av-20-algoritme). Skal frittstående runder faktisk + oppdatere `app_user.handicap_index` automatisk, er dette en HELT NY + motor-komponent, ikke et lite tillegg til den eksisterende. +- **Spiller velger starthull:** ja, gjenbruk av samme `start_hole`-konsept + som over. + +**Shotgun vs. fortløpende start ved turneringsoppsett (eget spørsmål, +egentlig et TURNERING/økt-konsept, ikke selve rundeførings-pivoten):** +- I dag er `session.start_hole` økt-bredt. Shotgun trenger starthull PER + FLIGHT/MATCH (typisk trukket/tildelt), ikke ett felles for økten. +- Shotgun har samme klokkeslett for alle grupper — ikke en variant av + `tee_interval_minutes` (som gjelder fortløpende start), kun + `start_hole` varierer mellom gruppene. +- Konkret forslag: `session.start_type: 'sequential' | 'shotgun'`, + `start_hole` blir settbart PER MATCH når shotgun velges (økt-nivået + forblir default/fallback for fortløpende). `tee_time`-utledningen + (ADR-015) trenger en egen shotgun-gren. + +**Andre punkter fra drodlingen, ikke avklart med bruker ennå:** +- Spenningen "detaljert statistikk" vs. "ekstremt enkelt": anbefaler at + ALLE detalj-felt er valgfrie per hull — rask "bare slagtall"- + registrering skal alltid fungere, detaljer legges på for dem som vil. + Ellers risikerer man at hovedfokuset blir for tungvint til daglig bruk. +- Personlig køllebag (driver/hybrid/jern/wedge/putter) som naturlig + følgefunksjon til "kølle brukt ved utslag" — kvikk-valg fremfor fritekst + hver gang. +- Flight-partnere uten TeeCup-konto: gjenbruk det allerede etablerte + mønsteret for org-scopede spillere uten konto + senere e-post-kobling + (`link_player_by_email`-familien), ikke finn opp noe nytt. +- Bør turnering-scoring til slutt bruke SAMME rike statistikk-registrering + som frittstående runder (én delt scoring-komponent), i stedet for to + ulike scoring-opplevelser i samme app? Ikke avklart, men verdt å ha i + bakhodet fra design-start siden brukeren kaller dette "hovedfokus". +- Historikk/trender over tid (beste runde, HCP-trend, snitt putter/runde) + — naturlig, senere konsekvens når data finnes, ingen egen beslutning + nødvendig nå. + **Brukerens beskrevne behov, fanget presist:** en bruker skal kunne registrere en golfrunde HELT UAVHENGIG av enhver turnering eller organisasjon — verken tilhørighet til et lag, en turnering, eller en @@ -1384,8 +1476,12 @@ TeeCup-brukere). Statistikk utover selve slagtallet: - Antall bunkerslag - Antall straffeslag - Lengde på første putt -- "og lignende" — trolig flere finkornede stats brukeren vil spesifisere - nærmere når dette faktisk designes +- Kølle brukt ved utslaget (2026-07-22) +- Om utslaget traff fairway, eller var til høyre/venstre for den (2026-07-22) +- "Green in regulation" (GIR), automatisk beregnet (2026-07-22 — se + presisering under om DERIVERT vs. OBSERVERT stat) +- Utfallet av innspillet til green: traff/lang/kort/høyre/venstre + (2026-07-22) **Dette er IKKE en liten dashboard-finpuss — det utfordrer en av arkitektur-invariantene i CLAUDE.md direkte:** "Tenant = organisasjon. diff --git a/WHS_Rules_of_Handicapping_2024.pdf b/WHS_Rules_of_Handicapping_2024.pdf new file mode 100644 index 0000000..cefb18f Binary files /dev/null and b/WHS_Rules_of_Handicapping_2024.pdf differ