Sortering, side_fairway-fiks, ny poi_type fairway/stone_fence (ADR-084 del 5-6)
Hindringslisten manglet eksplisitt nærmest-spilleren-først-sortering -- fikset. Kryssjekk mot kildedata avdekket 12 kjente side_fairway-feil, løst via full reimport av Tjømes 194 koordinatpunkter fra et nytt, standardisert CSV-format (kjørt separat mot ekte teecup_db, ikke del av denne commiten). To nye hindringstyper (fairway/stone_fence) med egne ikoner. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
8a1f1f83fa
commit
1bc6b0b74d
7 changed files with 197 additions and 3 deletions
25
082_course_poi_type_fairway_stonefence.sql
Normal file
25
082_course_poi_type_fairway_stonefence.sql
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
-- =====================================================================
|
||||
-- TeeCup — migrasjon 082
|
||||
-- Nye POI-typer "fairway" og "stone_fence" (voll/steingjerde)
|
||||
-- =====================================================================
|
||||
-- Konkret anledning (ADR-084 del 5): full reimport av Tjøme Golfklubb
|
||||
-- sitt koordinat-regneark (standardisert kolonneformat, se ADR-084 del
|
||||
-- 2-4) inneholdt to TYPE-verdier uten tilsvarende poi_type: "Fairway"
|
||||
-- (enkeltpunkt-referanse midt i fairwayen) og "Voll" (jordvoll/
|
||||
-- steingjerde). Bruker lastet opp egne ikoner (fairway.png,
|
||||
-- stonefence.png) og ba om at disse legges til som egne typer.
|
||||
--
|
||||
-- `fairway` og `stone_fence` legges til course_poi_type-domenet
|
||||
-- (migrasjon 079) -- gjelder automatisk begge koordinattabellene.
|
||||
-- =====================================================================
|
||||
|
||||
\set ON_ERROR_STOP on
|
||||
|
||||
ALTER DOMAIN course_poi_type DROP CONSTRAINT course_poi_type_check;
|
||||
ALTER DOMAIN course_poi_type ADD CONSTRAINT course_poi_type_check
|
||||
CHECK (VALUE IN (
|
||||
'green', 'green_bunker', 'fairway_bunker', 'water', 'creek',
|
||||
'trees', 'marker_100', 'marker_150', 'marker_200',
|
||||
'dogleg', 'road', 'tee_front', 'tee_back',
|
||||
'rock', 'layup', 'landmark', 'fairway', 'stone_fence'
|
||||
));
|
||||
|
|
@ -8616,6 +8616,94 @@ teecup_frontend && up -d`, ingen migrasjon. Rene containerlogger,
|
|||
`https://teecup.golf/logg-inn` 200 OK. Ikon-mangel-lista er nå TOM --
|
||||
alle klassifiserte hindringstyper har eget ikon.
|
||||
|
||||
### ADR-084 del 5: sortering, side_fairway-datafeil funnet, standardisert CSV-format (2026-08-18)
|
||||
|
||||
Bruker rapporterte to nye avvik fra ekte bruk: (1) hindringslisten
|
||||
sorteres "motsatt" av forventet, (2) hull 7 sitt vannhinder fremstår
|
||||
som senter selv om det faktisk ligger til venstre.
|
||||
|
||||
**(1) Sorteringsfiks:** `groupDiagramHazards()` (hole-target-
|
||||
distance.tsx) manglet den eksplisitte "nærmest spilleren først"-
|
||||
sorteringen ADR-083 sin opprinnelige flate liste hadde -- falt tilbake
|
||||
til rå API-/innsettingsrekkefølge, som verken reflekterte avstand eller
|
||||
oppdaterte seg når spilleren beveget seg. Fikset med
|
||||
`entities.sort((a, b) => a.below - b.below)`.
|
||||
|
||||
**(2) Data-diagnose:** kryssjekket alle punkter i den gamle CSV-en som
|
||||
eksplisitt oppga venstre/høyre mot databasens `side_fairway` -- fant 12
|
||||
avvik (fjellknaus/vann/trær på hull 4/5/7/13/14/16), alle satt til
|
||||
`center` i databasen når kilden sa noe annet. Mønster: punkter som IKKE
|
||||
fulgte det vanlige "Forkant/Bakkant [side] [type]"-friteksten ble
|
||||
tilsynelatende satt til `center` som fallback ved en tidligere import.
|
||||
Bekreftet at lapping av enkeltpunkter ikke var veien videre -- for
|
||||
upålitelig datagrunnlag til å stole på uten en fullstendig, ren kilde.
|
||||
|
||||
**Standardisert CSV-format avtalt** (kolonner: `ID,HULL,TYPE,PLASS,
|
||||
PUNKT,LAT/LNG`) -- erstatter den gamle friteksten som krevde skjør
|
||||
NLP-aktig parsing. `ID` er kun unik INNENFOR ett hull (samme prinsipp
|
||||
som `hazard_group` allerede var designet for), tom `ID` = enkeltstående
|
||||
punkt (som Tee/Green), ingen ID-kollisjon selv om flere hull gjenbruker
|
||||
samme fysiske hindring (bekreftet mønster fra tidligere runder).
|
||||
|
||||
**Ingen migrasjon denne delen.**
|
||||
|
||||
### ADR-084 del 6: full reimport av Tjøme (194 punkter), to nye poi_type (2026-08-18)
|
||||
|
||||
Bruker leverte hele 18-hulls-fila i det avtalte formatet. Grundig
|
||||
validering før noe ble kjørt (se scratchpad-analyse): fant og avklarte
|
||||
med bruker seks konkrete ting -- to ukjente TYPE-verdier (`Fairway`,
|
||||
`Voll`, løst med nye ikoner + migrasjon 082, se under), ett par uten
|
||||
PUNKT til å skille forkant/bakkant (hull 15 sitt vann -- løst ved
|
||||
brukerens egen regel: punktet som slutter på "683" er bakkant), én
|
||||
tydelig kopier-lim-feil (hull 11 sin andre "Tee"-rad skulle vært
|
||||
"Tre" -- bekreftet), seks rader med fortsatt ugyldige UTM/EPSG:25833-
|
||||
koordinater (denne gangen løst med en ordentlig projeksjons-
|
||||
transformasjon via `pyproj`, EPSG:25833→4326 -- konvergerte på under
|
||||
en millimeters avvik fra forrige rundes elimineringsbaserte gjetning,
|
||||
god kryssbekreftelse av begge metodene), og ett hull 18-veipunkt som
|
||||
bevisst fjernes (fantes i databasen, ikke i den nye fila -- bekreftet
|
||||
riktig av bruker).
|
||||
|
||||
**Migrasjon 082:** `fairway` og `stone_fence` lagt til
|
||||
`course_poi_type`-domenet -- bruker lastet opp egne ikoner
|
||||
(`fairway.png`, `stonefence.png`) for disse. `stone_fence` er den
|
||||
norske "Voll" (jordvoll/steingjerde) sitt engelske domenenavn.
|
||||
|
||||
**Full reimport, ikke patch:** hull 4 sine green-/greenbunker-
|
||||
koordinater viste seg vesentlig endret mellom gammel database og ny
|
||||
fil (bl.a. det jeg i forrige runde identifiserte som "bakre
|
||||
greenbunker" via elimineringslogikk var faktisk feil -- ekte bakre
|
||||
greenbunker har helt andre koordinater i den nye, autoritative fila).
|
||||
Dette gjorde inkrementell patching for risikabelt -- kjørte i stedet
|
||||
`DELETE`+`INSERT` i én transaksjon for HELE banen (180 gamle rader
|
||||
byttet ut med 194 nye), beregnet direkte fra kolonnene (ikke
|
||||
friteksttolkning). Genererings-/valideringsskript i scratchpad
|
||||
(engangs, ikke innsjekket).
|
||||
|
||||
**PLASS="Bakre"** (kun hull 4 sin greenbunker) trengte ingen
|
||||
særbehandling -- beregnet `alongPercent` viste at punktet geometrisk
|
||||
ligger godt innenfor normalsonen (94-97%, ikke bak green sin bakkant
|
||||
på 101%+), så det rendres helt vanlig i midtbanen uten å trigge
|
||||
"bak green"-sonen fra del 2. Verdt å vite: "Bakre" er en beskrivende
|
||||
etikett fra klubben, ikke nødvendigvis bokstavelig "forbi flagget".
|
||||
|
||||
**Verifisert:** `tsc --noEmit` rent, `vitest run` 55/55, full
|
||||
`./scripts/run_backend_tests.sh` 111/111 (migrasjon 082). Egen
|
||||
scratch-database seedet med EKTE Tjøme-data (kopiert fra produksjon,
|
||||
read-only kilde) -- reimport-SQL-en kjørt mot scratch-kopien FØRST,
|
||||
bekreftet 194/39 riktig, `poi_type`-fordeling matchet plan eksakt.
|
||||
Visuell bekreftelse (scratch API+frontend) av `fairway`- og
|
||||
`stone_fence`-ikonene på hull 2/3, samt at sorteringsfiksen virker
|
||||
riktig med ekte reimportert data (stigende avstand bekreftet hull
|
||||
1/2/3). Lys+mørk bekreftet. Scratch-stacken revet ned.
|
||||
|
||||
**Rullet ut 2026-08-18** -- bruker bekreftet migrasjon, full reimport
|
||||
og kode hver for seg. Migrasjon 082 og reimport-SQL (DELETE 180/
|
||||
INSERT 194, én transaksjon) kjørt mot ekte `teecup_db`, deretter
|
||||
`docker compose build teecup_frontend && up -d`. Hull 7 sitt vann
|
||||
bekreftet `side_fairway='left'` etter reimport (matcher kildedataen,
|
||||
rettet fra den kjente `center`-feilen).
|
||||
|
||||
---
|
||||
|
||||
## Utviklingsplan (rekkefølge)
|
||||
|
|
|
|||
45
CHANGELOG.md
45
CHANGELOG.md
|
|
@ -12232,3 +12232,48 @@ Neste steg:
|
|||
build teecup_frontend && up -d`, ingen migrasjon. Rene
|
||||
containerlogger, `https://teecup.golf/logg-inn` 200 OK.
|
||||
Ikon-mangel-lista er nå tom.
|
||||
|
||||
105. **Sortering, side_fairway-diagnose, standardisert CSV-format
|
||||
(ADR-084 del 5) — 2026-08-18.** Hindringslisten manglet en
|
||||
eksplisitt "nærmest spilleren først"-sortering (falt tilbake til
|
||||
rå API-rekkefølge) -- fikset med `sort((a,b) => a.below - b.below)`
|
||||
i `groupDiagramHazards()`. Kryssjekket samtidig alle punkter i den
|
||||
gamle CSV-en med eksplisitt venstre/høyre mot databasens
|
||||
`side_fairway` -- fant 12 avvik (satt til `center` når kilden sa
|
||||
noe annet), som bekreftet at enkeltpunkt-lapping ikke holdt.
|
||||
Avtalte i stedet et standardisert kolonneformat
|
||||
(`ID,HULL,TYPE,PLASS,PUNKT,LAT/LNG`) med bruker for fremtidig
|
||||
reimport -- `ID` unik kun innenfor ett hull, samme prinsipp som
|
||||
`hazard_group`.
|
||||
|
||||
106. **Full reimport av Tjøme, to nye poi_type (ADR-084 del 6) —
|
||||
2026-08-18.** Bruker leverte hele 18-hulls-fila i det avtalte
|
||||
formatet. Validering avdekket og avklarte seks ting: to nye
|
||||
TYPE-verdier (`Fairway`/`Voll`, egne ikoner fra bruker + migrasjon
|
||||
082 for `fairway`/`stone_fence`), ett par uten PUNKT løst via
|
||||
brukerens regel (siste siffer i koordinaten avgjør forkant/
|
||||
bakkant), én bekreftet kopier-lim-feil (hull 11), seks UTM/
|
||||
EPSG:25833-korrupte rader løst med ordentlig `pyproj`-projeksjon
|
||||
(konvergerte på under 1mm avvik fra forrige rundes elimineringsvis
|
||||
gjettede verdier -- god kryssbekreftelse), og ett bevisst fjernet
|
||||
veipunkt (hull 18).
|
||||
|
||||
Hull 4 sine green-/greenbunker-koordinater viste seg vesentlig
|
||||
endret mellom database og ny fil -- inkludert det forrige runde
|
||||
identifiserte som "bakre greenbunker" via eliminasjon, som var feil
|
||||
koordinater. For risikabelt å patche inkrementelt -- kjørte i
|
||||
stedet full `DELETE`+`INSERT` (180 gamle rader → 194 nye) i én
|
||||
transaksjon, beregnet direkte fra kolonnene.
|
||||
|
||||
**Verifisert:** `tsc --noEmit` rent, `vitest run` 55/55, full
|
||||
`pytest` 111/111 (migrasjon 082). Reimport-SQL kjørt FØRST mot en
|
||||
scratch-kopi av ekte Tjøme-data -- 194/39 riktig, fordeling
|
||||
matchet plan eksakt. Visuell bekreftelse av `fairway`/
|
||||
`stone_fence`-ikonene og sorteringsfiksen med ekte reimportert
|
||||
data (hull 1/2/3), lys+mørk. Scratch-stacken revet ned.
|
||||
|
||||
**Rullet ut 2026-08-18** -- bruker bekreftet migrasjon, reimport
|
||||
og kode hver for seg. Migrasjon 082 + reimport (DELETE 180/INSERT
|
||||
194, én transaksjon) kjørt mot ekte `teecup_db`, deretter `docker
|
||||
compose build teecup_frontend && up -d`. Hull 7 sitt vann
|
||||
bekreftet `side_fairway='left'` etter reimport.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,19 @@
|
|||
import { MapPin, TriangleAlert } from "lucide-react"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
export type HazardKind = "sand" | "water" | "creek" | "rock" | "tree" | "dogleg" | "layup" | "landmark" | "road" | "generic"
|
||||
export type HazardKind =
|
||||
| "sand"
|
||||
| "water"
|
||||
| "creek"
|
||||
| "rock"
|
||||
| "tree"
|
||||
| "dogleg"
|
||||
| "layup"
|
||||
| "landmark"
|
||||
| "road"
|
||||
| "fairway"
|
||||
| "stone_fence"
|
||||
| "generic"
|
||||
|
||||
export type DiagramHazard = {
|
||||
key: string
|
||||
|
|
@ -106,6 +118,8 @@ const _ICON_SRC: Partial<Record<HazardKind, string>> = {
|
|||
layup: "/hole-diagram/hazard-layup.png",
|
||||
landmark: "/hole-diagram/hazard-landmark.png",
|
||||
road: "/hole-diagram/hazard-road.png",
|
||||
fairway: "/hole-diagram/hazard-fairway.png",
|
||||
stone_fence: "/hole-diagram/hazard-stonefence.png",
|
||||
}
|
||||
|
||||
function HazardIcon({ kind, size = 32 }: { kind: HazardKind; size?: number }) {
|
||||
|
|
|
|||
|
|
@ -60,12 +60,26 @@ const _HAZARD_LABELS: Record<string, string> = {
|
|||
layup: "Layup-punkt",
|
||||
landmark: "Landemerke",
|
||||
road: "Vei",
|
||||
fairway: "Fairway",
|
||||
stone_fence: "Voll",
|
||||
}
|
||||
|
||||
// ADR-084: hvilket ikon en hindringstype får i diagrammet. "generic"
|
||||
// (typer uten dedikert ikon -- i dag ingen) faller tilbake til lucide
|
||||
// sin TriangleAlert -- se hole-diagram-view.tsx.
|
||||
type HazardKind = "sand" | "water" | "creek" | "rock" | "tree" | "dogleg" | "layup" | "landmark" | "road" | "generic"
|
||||
type HazardKind =
|
||||
| "sand"
|
||||
| "water"
|
||||
| "creek"
|
||||
| "rock"
|
||||
| "tree"
|
||||
| "dogleg"
|
||||
| "layup"
|
||||
| "landmark"
|
||||
| "road"
|
||||
| "fairway"
|
||||
| "stone_fence"
|
||||
| "generic"
|
||||
const _HAZARD_KIND: Record<string, HazardKind> = {
|
||||
green_bunker: "sand",
|
||||
fairway_bunker: "sand",
|
||||
|
|
@ -77,6 +91,8 @@ const _HAZARD_KIND: Record<string, HazardKind> = {
|
|||
layup: "layup",
|
||||
landmark: "landmark",
|
||||
road: "road",
|
||||
fairway: "fairway",
|
||||
stone_fence: "stone_fence",
|
||||
}
|
||||
|
||||
// Grupperer rå hindringspunkter til hindrings-ENTITETER for diagrammet.
|
||||
|
|
@ -157,7 +173,13 @@ function groupDiagramHazards(
|
|||
location: p.location,
|
||||
})
|
||||
}
|
||||
return entities
|
||||
// ADR-083-konvensjonen ("sortert nærmest spilleren først") manglet her --
|
||||
// uten denne falt rekkefølgen tilbake til rå API-/innsettingsrekkefølge,
|
||||
// som ikke sier noe om avstand og heller ikke oppdaterer seg når
|
||||
// spilleren beveger seg. `below` er alltid den nærmeste av forkant/
|
||||
// enkeltpunkt-avstanden, så stigende sortering på den gir riktig
|
||||
// "nærmest spilleren først" for både parrede og enkeltstående hindringer.
|
||||
return entities.sort((a, b) => a.below - b.below)
|
||||
}
|
||||
|
||||
export function HoleTargetDistance({
|
||||
|
|
|
|||
BIN
frontend/public/hole-diagram/hazard-fairway.png
Normal file
BIN
frontend/public/hole-diagram/hazard-fairway.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3 KiB |
BIN
frontend/public/hole-diagram/hazard-stonefence.png
Normal file
BIN
frontend/public/hole-diagram/hazard-stonefence.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
Loading…
Reference in a new issue