CHANGELOG: logg for cut-kaskade, sorterbare kolonner, Ny runde-fiksene og Score-fane-rettelsene
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
e940e932c1
commit
a3f306c388
1 changed files with 252 additions and 0 deletions
252
CHANGELOG.md
252
CHANGELOG.md
|
|
@ -13667,3 +13667,255 @@ Neste steg:
|
||||||
Ren frontend. `docker compose build teecup_frontend && up -d`, rene
|
Ren frontend. `docker compose build teecup_frontend && up -d`, rene
|
||||||
logger. Ekstra oppmerksomhet på akkurat denne (automatisk
|
logger. Ekstra oppmerksomhet på akkurat denne (automatisk
|
||||||
hull-fremgang etter siste spiller) anbefalt i faktisk bruk.
|
hull-fremgang etter siste spiller) anbefalt i faktisk bruk.
|
||||||
|
|
||||||
|
144. **Cut-overlevere kaskaderes automatisk til alle senere runder,
|
||||||
|
2026-08-20 (ADR-095).** Bruker: "I eksempelturneringen vår opererer
|
||||||
|
vi med cut etter runde 1. På et vis burde de som har klart cut'en
|
||||||
|
autoselekteres på runde 2?" Undersøkt (read-only, Explore-agent) før
|
||||||
|
bygging: `tournament_round_participant`-rader opprettes kun på
|
||||||
|
forespørsel, aldri på forhånd for alle runder -- ingen eksisterende
|
||||||
|
mekanisme for dette.
|
||||||
|
|
||||||
|
To designbeslutninger bekreftet av bruker etter at jeg foreslo en
|
||||||
|
snevrere variant: (1) kaskade til ALLE runder etter cut, ikke bare
|
||||||
|
den neste -- "Har du klart cut'en spiller du alle påfølgende
|
||||||
|
runder." (2) fjern kuttede spilleres rundedeltakelse i senere runder
|
||||||
|
(ikke bare la stå blokkert) -- "Jo, fjern de. Dette får vi heller
|
||||||
|
reversere om det viser seg å være en dårlig beslutning," etter at
|
||||||
|
jeg opplyste at sletting kaskaderer til `tournament_round_hole`
|
||||||
|
(migrasjon 040, `ON DELETE CASCADE`).
|
||||||
|
|
||||||
|
Ny `_sync_post_cut_round_participation`-funksjon
|
||||||
|
(`app/routers/individual_tournaments.py`), kalt fra `apply_cut` i
|
||||||
|
samme transaksjon: for hver runde etter cut -- overlevere som
|
||||||
|
mangler en rad får én auto-INSERT-et (tee kopiert fra cut-runden,
|
||||||
|
handicap regnet ut med samme funksjon `add_round_participant`
|
||||||
|
bruker); kuttede spilleres eksisterende rad SLETTES, MEN kun hvis
|
||||||
|
den ikke allerede har registrert score (beskytter ekte data mot
|
||||||
|
kaskade-sletting). Idempotent, som resten av `apply_cut`.
|
||||||
|
`CutResult` fikk nytt felt `added_to_later_rounds`, vist i "Anvend
|
||||||
|
cut"-bekreftelsen. `SetupTab` nullstiller nå hele
|
||||||
|
`roundParticipantsByRound` etter "Anvend cut" (flere runder kan
|
||||||
|
endres samtidig) i stedet for å refreshe kun én.
|
||||||
|
|
||||||
|
**Testet, ikke bare gjennomgått:** 5 nye tester lagt til
|
||||||
|
`tests/test_cut.py`, kjørt mot en isolert scratch-database
|
||||||
|
(`./scripts/run_backend_tests.sh`) -- auto-tillegg med riktig
|
||||||
|
kopiert tee, fjerning av kuttede spilleres rad, IKKE-fjerning når
|
||||||
|
scorer finnes (+ bekreftet at 403-sperren fortsatt fungerer der),
|
||||||
|
kaskade til runde 3 uten runde 2 i mellom. Én eksisterende test
|
||||||
|
fikk sin forventning riktig oppdatert fra 403 til 404 (raden
|
||||||
|
slettes nå, blokkeres ikke lenger). Alle 156 backend-tester grønne.
|
||||||
|
|
||||||
|
**Rullet ut 2026-08-20** -- bruker bekreftet ("Suprt! Da kjører vi
|
||||||
|
på!"), etter en presiseringsrunde om hva "fjernes" faktisk betyr
|
||||||
|
(deselekteres fra runden, IKKE fjernet fra deltakerlisten eller
|
||||||
|
spillerpoolen). `docker compose build teecup_api teecup_frontend &&
|
||||||
|
up -d`, begge containere friske, rene logger. Ingen migrasjon
|
||||||
|
nødvendig.
|
||||||
|
|
||||||
|
145. **Sorterbare kolonner i Spillere-tabellen (turneringsoppsett),
|
||||||
|
2026-08-20.** V0-prompt (`v0-prompt-players-table-sort.md`, sortering
|
||||||
|
ALENE -- en tidligere prompt som også inkluderte en bulk-
|
||||||
|
utslagssted-flyt ble uttrykkelig trukket av bruker: "Jeg glemmer at
|
||||||
|
sjekkboksene er for HVEM SOM SKAL SPILLE RUNDEN. Ikke gjør hva jeg
|
||||||
|
ba deg om (med unntak av sorteringsmuligheten)"). V0-mønsteret
|
||||||
|
(klikk header -> stigende -> synkende -> opprinnelig rekkefølge,
|
||||||
|
`aria-sort`, pil-indikator kun på aktiv kolonne, ekte fokuserbar
|
||||||
|
knapp) integrert i den ekte `tournament-players-table.tsx` for de syv
|
||||||
|
ikke-runde-kolonnene (Spiller/Hcp/Klasse/Statistikknivå/Status/
|
||||||
|
Kjønn/Alder) -- runde-kolonnene og handlingskolonnen forblir
|
||||||
|
usorterbare, urørt.
|
||||||
|
|
||||||
|
Klasse-sortering slår opp klassenavn via `classId` (`classNameById`,
|
||||||
|
utledet fra `classes`-proppen); statistikknivå/status sorteres etter
|
||||||
|
en meningsfull rangering (mengde sporing / alvorlighet), ikke
|
||||||
|
alfabetisk. Null-verdier sorteres alltid sist, uansett retning.
|
||||||
|
|
||||||
|
**Verifisert i scratch mot den EKTE komponenten** (ikke V0-mocken):
|
||||||
|
egen `tmp-preview`-rute som monterer `TournamentPlayersTable` direkte
|
||||||
|
med realistisk mock-data, `evaluate_script`-sjekker av faktisk
|
||||||
|
radrekkefølge OG `aria-sort`-verdi gjennom alle tre klikk-sykluser
|
||||||
|
(stigende/synkende/opprinnelig) for både numerisk (Hcp) og
|
||||||
|
oppslags-basert (Klasse) sortering -- begge korrekte, inkludert
|
||||||
|
null-sist-oppførsel. `tsc --noEmit` rent. Scratch-ruten slettet
|
||||||
|
etterpå, bekreftet med `git status --short`.
|
||||||
|
|
||||||
|
**Rullet ut 2026-08-20** -- samlet med #144. Ren frontend, samme
|
||||||
|
`docker compose build teecup_frontend && up -d`, rene logger.
|
||||||
|
|
||||||
|
146. **Flytende "Registrer score" forsvant helt ved mange hindringer,
|
||||||
|
2026-08-20.** Bruker viste skjermbilde: knappen manglet når hullet
|
||||||
|
hadde mange registrerte hindringer -- selv om banekartet ALDRI ble
|
||||||
|
utvidet.
|
||||||
|
|
||||||
|
Rot-årsak: den flytende knappens synlighet var styrt av `mapExpanded`
|
||||||
|
alene (#140-#142). Feil premiss -- ADR-083 gjorde at
|
||||||
|
"compact"-visningen (kartet IKKE utvidet) OGSÅ viser hele
|
||||||
|
hindringslisten, ikke bare nærmeste. På et hull med mange hindringer
|
||||||
|
(7 i brukerens tilfelle) blir denne listen alene høy nok til å dytte
|
||||||
|
den vanlige side-flyt-knappen utenfor synlig område -- akkurat den
|
||||||
|
situasjonen den flytende knappen skulle dekke, men trigget aldri
|
||||||
|
fordi `mapExpanded` fortsatt var `false`.
|
||||||
|
|
||||||
|
Rettet ved å bytte ut det indirekte signalet (`mapExpanded`) med et
|
||||||
|
direkte: er selve side-flyt-knappen faktisk synlig akkurat nå. Ny
|
||||||
|
`inFlowButtonRef` + `inFlowButtonVisible`-tilstand, målt med samme
|
||||||
|
`getBoundingClientRect()` + scroll/resize-lytter-mønster som
|
||||||
|
`playerListReached` (ikke IntersectionObserver, se begrunnelse i
|
||||||
|
kodekommentaren fra #141). Side-flyt-knappen fjernet fra sin
|
||||||
|
`{!mapExpanded && ...}`-betingelse -- ligger nå ALLTID i normal flyt,
|
||||||
|
uansett kart-tilstand. Den flytende knappen vises når
|
||||||
|
`!inFlowButtonVisible && !playerListReached` (før: `mapExpanded &&
|
||||||
|
!playerListReached`).
|
||||||
|
|
||||||
|
**Verifisert i scratch, ikke bare gjennomgått:** egen
|
||||||
|
`tmp-preview`-rute som monterer den EKTE `RoundDetail` (kun
|
||||||
|
`roundId`-prop, ingen egen mock-versjon), med `window.fetch`-mock for
|
||||||
|
runde/deltakere/hull-data og et hindringssett som gjenskaper
|
||||||
|
brukerens skjermdump nøyaktig (7 hindringer, samme typer/avstander).
|
||||||
|
`evaluate_script`-målt gjennom fire scenarioer: (1) mange hindringer,
|
||||||
|
kart ALDRI utvidet -- flytende knapp korrekt synlig
|
||||||
|
(`aria-hidden="false"`) siden side-flyt-knappen satt bak headeren;
|
||||||
|
(2) scroll til side-flyt-knappen faktisk er fri av headeren -- flytende
|
||||||
|
knapp korrekt skjult; (3) hull UTEN hindringer -- flytende knapp
|
||||||
|
forblir skjult hele veien, ingen regresjon; (4) kart utvidet (det
|
||||||
|
opprinnelige brukstilfellet) -- samme korrekte oppførsel som før,
|
||||||
|
pluss `playerListReached`-skjuling ved scroll til spillerlisten
|
||||||
|
fortsatt intakt. `tsc --noEmit` rent. Scratch-ruten slettet etterpå,
|
||||||
|
bekreftet med `git status --short`.
|
||||||
|
|
||||||
|
**Rullet ut 2026-08-20** -- bruker bekreftet ("Bygg og deploy").
|
||||||
|
`docker compose build teecup_frontend && up -d`, container frisk,
|
||||||
|
rene logger. Ingen migrasjon, ren frontend.
|
||||||
|
|
||||||
|
147. **Tre ting i "Ny runde"-veiviseren, 2026-08-20 (bruker, skjermdump av
|
||||||
|
Spillere-steget).**
|
||||||
|
|
||||||
|
1. **"Administrer runde"-overleggsmenyen lukket seg ikke selv etter
|
||||||
|
"Spillere og runde" ble trykket** -- måtte lukkes manuelt for å se
|
||||||
|
siden under. Rot-årsak: `<Link href={manageHref}>` i
|
||||||
|
`ManageRoundDialog` (round-header.tsx) navigerer ofte KUN til en
|
||||||
|
søkeparameter-endring (`?tab=manage`) på samme rute -- ingen
|
||||||
|
remount, så dialogens lokale `manageOpen`-state (eid av
|
||||||
|
`RoundHeader`) forble uendret. Rettet med `onClick={onClose}` på
|
||||||
|
selve lenken, i tillegg til navigasjonen.
|
||||||
|
|
||||||
|
2. **Kunne ikke overstyre HCP for en nylig lagt til, kontokoblet
|
||||||
|
medspiller i selve veiviseren** -- feltet viste kun en read-only
|
||||||
|
"X · hentes fra profilen"-tekst. Fungerte allerede via "Runde og
|
||||||
|
runde" (PATCH .../participants/{id}) senere i runden, men ikke fra
|
||||||
|
start. To lag:
|
||||||
|
- **Backend** (`add_participant`, app/routers/rounds.py): POST-
|
||||||
|
endepunktet ignorerte `body.handicap_index` HELT for en
|
||||||
|
`user_id`-koblet deltaker (brukte alltid profilens verdi
|
||||||
|
direkte) -- ulikt PATCH-endepunktet (`update_participant`), som
|
||||||
|
allerede æret en eksplisitt overstyring for enhver deltaker,
|
||||||
|
ikke bare gjester (bekreftet i kode: `guest_only_fields`-sperren
|
||||||
|
ekskluderer bevisst `handicap_index`). Rettet til `body.
|
||||||
|
handicap_index if body.handicap_index is not None else target
|
||||||
|
["handicap_index"]`, i tråd med ADR-038 sin allerede dokumenterte
|
||||||
|
"MANUELT satt ... med mindre eksplisitt overstyrt"-modell.
|
||||||
|
- **Frontend** (`step3-players.tsx`): HCP-feltet for en
|
||||||
|
kontokoblet, ikke-eier-spiller gjort redigerbart (samme `Field`/
|
||||||
|
`TextInput`-mønster som allerede brukt for gjester i samme fil),
|
||||||
|
forhåndsutfylt med profilverdien, urørt betyr fortsatt "bruk
|
||||||
|
profilen". `wizard-context.tsx` sin `submit()` sender nå
|
||||||
|
`handicap_index: p.hcp ?? null` også for kontokoblede
|
||||||
|
deltakere (uendret verdi er en trygg no-op, siden backend
|
||||||
|
faller tilbake til profilen når feltet er urørt).
|
||||||
|
- Ny backend-test `test_add_participant_hcp_override.py` (2 tester
|
||||||
|
-- overstyring æres, OG regresjonsvern: uendret oppførsel når
|
||||||
|
ingen overstyring gis), kjørt mot scratch-database
|
||||||
|
(`./scripts/run_backend_tests.sh`), alle 158 tester grønne.
|
||||||
|
|
||||||
|
3. **Standard statistikknivå for en NY medspiller var "Alt", skal
|
||||||
|
være "Kun slag"** -- `defaultStat`-proppen til `AddPlayerPanel`
|
||||||
|
speilet feilaktig `state.statLevel` (scoreførerens EGET valgte
|
||||||
|
nivå fra "Spilleform"-steget), ikke et fast "Kun slag"-utgangs-
|
||||||
|
punkt for ANDRE spillere. Bekreftet ved kodegjennomgang: en
|
||||||
|
tilstøtende kommentar i wizard-context.tsx (fra en tidligere,
|
||||||
|
urelatert rettelse 2026-08-15) dokumenterer eksplisitt at
|
||||||
|
`defaultStat` alltid var MENT som "default for NYE medspillere",
|
||||||
|
atskilt fra eierens eget felt -- speilingen var en glipp, ikke et
|
||||||
|
bevisst valg. Rettet til en fast `"score"` i `step3-players.tsx`.
|
||||||
|
Organisatoren kan fortsatt sette et høyere nivå manuelt per
|
||||||
|
medspiller.
|
||||||
|
|
||||||
|
**Verifisert i scratch, ikke bare gjennomgått, for alle tre:**
|
||||||
|
(1) egen `tmp-preview`-rute som monterer den EKTE `RoundHeader`,
|
||||||
|
bekreftet via `evaluate_script` at dialogen (`[role="dialog"]`) er
|
||||||
|
borte fra DOM-en umiddelbart etter klikk+navigasjon, ingen manuell
|
||||||
|
lukking nødvendig. (2)+(3) egen `tmp-preview`-rute som monterer den
|
||||||
|
EKTE `WizardProvider` + `Step3Players` (med `window.fetch`-mock for
|
||||||
|
`/auth/me` og `/people/search`), drevet gjennom hele den ekte søk-og-
|
||||||
|
legg-til-flyten (søkte "Morten", la til kontoen, ekspanderte kortet)
|
||||||
|
-- bekreftet HCP-feltet er en ekte, redigerbar `<input>` forhånds-
|
||||||
|
utfylt med 11.1, aksepterer et desimaltall (satt direkte via
|
||||||
|
`dispatchEvent` for å utelukke en `fill`-verktøy-særegenhet som først
|
||||||
|
strippet punktumet), OG at "Kun slag" er forhåndsvalgt for den nylig
|
||||||
|
lagte-til spilleren. `tsc --noEmit` rent gjennom hele. Begge
|
||||||
|
scratch-rutene slettet etterpå, bekreftet med `git status --short`.
|
||||||
|
|
||||||
|
**Rullet ut 2026-08-20** -- bruker bekreftet ("Ja takk").
|
||||||
|
`docker compose build teecup_api teecup_frontend && up -d`, begge
|
||||||
|
containere friske, rene logger. Ingen migrasjon.
|
||||||
|
|
||||||
|
148. **Hindringslisten sortert feil vei + kartretning ved slagmåling nå
|
||||||
|
styrt av ekte utslag→green-geometri, 2026-08-21.** Bruker, med
|
||||||
|
skjermdump: holdes telefonen loddrett for avstandsmåling, bør det
|
||||||
|
som er lengst unna (greenen) stå øverst i lista og det nærmeste
|
||||||
|
(utslaget) nederst, med hindringene sortert i SAMME rekkefølge
|
||||||
|
imellom -- listen viste tidligere motsatt (nærmeste hindring øverst,
|
||||||
|
rett attmed greenen). Presisert: der en hindring har både forkant og
|
||||||
|
bakkant vist, er det BAKKANTEN (fjerneste kant) som skal styre
|
||||||
|
sorteringen.
|
||||||
|
|
||||||
|
To sorteringssteder i `hole-target-distance.tsx` rettet fra stigende
|
||||||
|
til synkende (lengst unna FØRST): `groupDiagramHazards()` sin
|
||||||
|
`entities.sort(...)` (den parrede forkant/bakkant-visningen, brukt av
|
||||||
|
`HoleDiagram` -- nøkkel endret fra alltid `below` til `above ?? below`,
|
||||||
|
altså bakkanten når en finnes), og den enklere flate listen (`hazards
|
||||||
|
.sort(...)`, brukt når banen mangler tee-koordinater -- ingen
|
||||||
|
forkant/bakkant-parring der, kun ett tall per punkt).
|
||||||
|
|
||||||
|
**Samme runde, andre delen av brukerønsket:** på baner med BÅDE
|
||||||
|
utslags- OG green-koordinater kjent, skal selve satellittkartet i
|
||||||
|
slagmåleren ("Mål et slag") vises med greenen opp/utslaget ned, ikke
|
||||||
|
nord opp. `initialBearing`-mekanismen fantes allerede (bygget
|
||||||
|
2026-08-10, roterte kartet etter spillerens EGEN forrige slag-
|
||||||
|
retning på hullet, `bearingDegrees(forrige slag start, slutt)`) --
|
||||||
|
denne er nå supplert med en NY, mer pålitelig kilde: `ShotMeasurement
|
||||||
|
Entry` (fellet-komponenten brukt fra alle tre stedene i filen
|
||||||
|
slagmåling kan åpnes fra: kompakt spillerkort, delt-ball-sidebadge,
|
||||||
|
og full-skjerm-veiviserens "Retning"-steg) henter nå selv hullets
|
||||||
|
`target-points`, regner ut `bearingDegrees(midtpunkt(utslag front/
|
||||||
|
bakkant), green senter)`, og lar DENNE vinne over forrige-slag-
|
||||||
|
gjetningen når den finnes -- ekte banegeometri er mer pålitelig enn
|
||||||
|
en tilfeldig sleng/hook på forrige slag. Egen, liten fetch per
|
||||||
|
spillerkort (i stedet for å prop-drille et tall gjennom RoundDetail/
|
||||||
|
PlayerHoleCards/ScoringWizard for å dele HoleTargetDistance sin
|
||||||
|
allerede-eksisterende henting) -- en akseptert kostnad for at ALLE
|
||||||
|
tre inngangene til kartet får riktig retning samtidig, ikke bare én.
|
||||||
|
|
||||||
|
**Verifisert i scratch, presist, ikke bare gjennomgått:** egen
|
||||||
|
`tmp-preview`-rute som monterer den EKTE `RoundDetail`, med
|
||||||
|
`window.fetch`-mock for `target-points` (utslag+green forskjøvet til
|
||||||
|
en bevisst IKKE-kardinal (ikke nord/øst/sør/vest) retning, for å
|
||||||
|
fange opp en feil som ved et uhell falt tilbake til "ingen
|
||||||
|
rotasjon"). Ekte `NEXT_PUBLIC_MAPBOX_TOKEN` lest fra `.env` inn i
|
||||||
|
scratch-serverens miljø (aldri skrevet i klartekst noe sted).
|
||||||
|
`mapboxgl.Map`-konstruktøren instrumentert (kun i scratch, aldri i
|
||||||
|
kildekoden) til å fange opp `bearing`-verdien den faktisk mottok.
|
||||||
|
Gikk gjennom hele den ekte flyten (ekspander spillerkort -> "Mål et
|
||||||
|
slag" -> "Velg punkt på kart") og bekreftet numerisk: forventet
|
||||||
|
`19.02°` (regnet uavhengig, samme formel, i selve scratch-siden) mot
|
||||||
|
faktisk mottatt `19.016306...°` -- match. Selve korttavlerenderingen
|
||||||
|
feilet med "Kunne ikke laste kartet" pga. manglende ekte nettverks-
|
||||||
|
tilgang til Mapbox sine tile-servere i dette sandkasse-miljøet
|
||||||
|
(urelatert til retting -- `bearing`-argumentet appliseres synkront
|
||||||
|
ved konstruksjon, uavhengig av om selve kart-flisene faktisk laster).
|
||||||
|
`tsc --noEmit` rent. Scratch-ruten slettet etterpå, bekreftet med
|
||||||
|
`git status --short`.
|
||||||
|
|
||||||
|
**Ikke rullet ut ennå.**
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue