Score-fanen: mindre luft under headeren + skjul passerte hindringer i avstandsmåleren
To brukerpåpekte funn: (1) unødvendig stort tomrom mellom RoundHeader og hull-navigatoren når ingen varsel-banner vises -- main sin toppadding stablet seg oppå seksjonens egen mt-5 i stedet for å erstatte den. (2) hindringer skal kun vises når de fortsatt ligger mellom spiller og green -- passerte hindringer var unødvendig støy. Se CHANGELOG.md #136/#137 for detalj og verifisering. Punkt 2 ikke rullet ut ennå. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
839bed4dd9
commit
f10121beaf
3 changed files with 78 additions and 3 deletions
44
CHANGELOG.md
44
CHANGELOG.md
|
|
@ -13388,3 +13388,47 @@ Neste steg:
|
||||||
|
|
||||||
**Rullet ut 2026-08-20** -- bruker bekreftet. Ren frontend.
|
**Rullet ut 2026-08-20** -- bruker bekreftet. Ren frontend.
|
||||||
`docker compose build teecup_frontend && up -d`, rene logger, 200 OK.
|
`docker compose build teecup_frontend && up -d`, rene logger, 200 OK.
|
||||||
|
|
||||||
|
136. **Score-fanen: mindre luft under RoundHeader, 2026-08-20.** Bruker
|
||||||
|
viste et skjermbilde fra live: unødvendig stort tomrom mellom
|
||||||
|
fanerad-headeren og "Hull 1"-boksen når ingen varsel-banner
|
||||||
|
(offline/pending-sync) var synlig. Årsak: `<main>` sin egen
|
||||||
|
`py-6 sm:py-8`-toppadding la seg OVENPÅ hull-seksjonens allerede
|
||||||
|
eksisterende `mt-5` lenger ned i stedet for å erstatte den -- disse
|
||||||
|
stablet seg til 44-52px kombinert, mens resten av siden bruker en
|
||||||
|
tettere rytme (16-20px). Rettet: `round-detail.tsx` sin `<main>`
|
||||||
|
bruker nå `pt-3 sm:pt-4` (matcher RoundHeader sin egen interne
|
||||||
|
`py-3 sm:py-4`-rytme) i stedet for `py-6 sm:py-8` -- kun toppen
|
||||||
|
redusert, bunnpadding uendret.
|
||||||
|
|
||||||
|
137. **Hindringer bak spilleren skal ikke lenger vises, 2026-08-20.**
|
||||||
|
Bruker påpekte (uavhengig av skjermbildet over): avstander til
|
||||||
|
hindringer skal kun vises når hindringen faktisk ligger MELLOM
|
||||||
|
spilleren og greenen -- en hindring spilleren allerede har gått forbi
|
||||||
|
er unødvendig informasjon.
|
||||||
|
|
||||||
|
`hole-target-distance.tsx`:
|
||||||
|
- `groupDiagramHazards()` (brukt av det vanlige diagram-sporet, når
|
||||||
|
banen har tee-koordinater) tar nå imot spillerens `alongPercent`
|
||||||
|
(posisjon langs tee-green-aksen) og filtrerer bort enhver hindring
|
||||||
|
der YTTERSTE kant (bakkanten for et parret forkant+bakkant-hinder,
|
||||||
|
selve punktet for et enkeltstående) ligger BAK spilleren. Et parret
|
||||||
|
hinder regnes altså som passert først når spilleren er forbi BEGGE
|
||||||
|
kantene, ikke bare forkanten. En liten toleranse
|
||||||
|
(`HAZARD_PASSED_TOLERANCE_PCT = 1,5`) hindrer at en hindring rett
|
||||||
|
ved spillerens fot blinker inn/ut mellom to GPS-oppdateringer.
|
||||||
|
- Den sjeldnere fallback-listen (bane uten tee-koordinater, ingen
|
||||||
|
akse å projisere langs) filtrerer med en enklere proxy: hindringen
|
||||||
|
må ligge nærmere green-midten enn spilleren selv gjør.
|
||||||
|
|
||||||
|
**Verifisert i scratch:** en frittstående forhåndsvisning av
|
||||||
|
`HoleTargetDistance` (compact + full) med stubbet `navigator.
|
||||||
|
geolocation.watchPosition` (synkron, deterministisk testposisjon --
|
||||||
|
ikke Chrome DevTools sin posisjons-emulering, som var upålitelig
|
||||||
|
tidligere i denne økten) og to hindringer på rett linje langs hullet,
|
||||||
|
én bak og én foran en fast spillerposisjon. Bekreftet: kun hindringen
|
||||||
|
foran spilleren ("Vannhinder") vises, i BÅDE kompakt liste og fullt
|
||||||
|
diagram -- hindringen bak ("Fjellknaus") er helt fraværende i begge.
|
||||||
|
`tsc --noEmit` rent.
|
||||||
|
|
||||||
|
**Ikke rullet ut ennå** -- venter på bekreftelse fra bruker.
|
||||||
|
|
|
||||||
|
|
@ -95,17 +95,32 @@ const _HAZARD_KIND: Record<string, HazardKind> = {
|
||||||
stone_fence: "stone_fence",
|
stone_fence: "stone_fence",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hvor mange prosent av hull-lengden en hindring får "henge igjen" etter at
|
||||||
|
// spilleren i teorien har passert den (ADR-085, brukerønske 2026-08-20:
|
||||||
|
// hindringer bak spilleren er unødvendig informasjon -- skal ikke lenger
|
||||||
|
// vises). Ren GPS-støy-margin, ikke en spilleregel -- uten denne ville en
|
||||||
|
// hindring rett ved spillerens fot kunne blinke inn/ut av listen mellom to
|
||||||
|
// GPS-oppdateringer idet spilleren går forbi.
|
||||||
|
const HAZARD_PASSED_TOLERANCE_PCT = 1.5
|
||||||
|
|
||||||
// Grupperer rå hindringspunkter til hindrings-ENTITETER for diagrammet.
|
// Grupperer rå hindringspunkter til hindrings-ENTITETER for diagrammet.
|
||||||
// VIKTIG (bruker-rettelse, ADR-084): to punkter er KUN samme fysiske
|
// VIKTIG (bruker-rettelse, ADR-084): to punkter er KUN samme fysiske
|
||||||
// hindring hvis de deler samme, ikke-null hazard_group -- ALDRI basert
|
// hindring hvis de deler samme, ikke-null hazard_group -- ALDRI basert
|
||||||
// på poi_type+side_fairway alene (ville feilaktig slått sammen to
|
// på poi_type+side_fairway alene (ville feilaktig slått sammen to
|
||||||
// atskilte hindringer av samme type på samme side). Punkter med
|
// atskilte hindringer av samme type på samme side). Punkter med
|
||||||
// hazard_group=null forblir alltid enkeltstående.
|
// hazard_group=null forblir alltid enkeltstående.
|
||||||
|
// `playerAlongPercent` (ADR-085) -- en hindring vises KUN hvis den fortsatt
|
||||||
|
// ligger MELLOM spilleren og greenen (brukerønske: passerte hindringer er
|
||||||
|
// unødvendig informasjon). For et parret forkant+bakkant-hinder brukes
|
||||||
|
// bakkanten (den ytterste kanten, nærmest green) -- hele hindringen regnes
|
||||||
|
// som passert først når spilleren er forbi BEGGE kantene, ikke bare
|
||||||
|
// forkanten.
|
||||||
function groupDiagramHazards(
|
function groupDiagramHazards(
|
||||||
hazardPoints: ApiTargetPoint[],
|
hazardPoints: ApiTargetPoint[],
|
||||||
livePosition: LatLng,
|
livePosition: LatLng,
|
||||||
teeRef: LatLng,
|
teeRef: LatLng,
|
||||||
greenRef: LatLng,
|
greenRef: LatLng,
|
||||||
|
playerAlongPercent: number,
|
||||||
) {
|
) {
|
||||||
const grouped = new Map<string, ApiTargetPoint[]>()
|
const grouped = new Map<string, ApiTargetPoint[]>()
|
||||||
const standalone: ApiTargetPoint[] = []
|
const standalone: ApiTargetPoint[] = []
|
||||||
|
|
@ -148,6 +163,8 @@ function groupDiagramHazards(
|
||||||
const kind = _HAZARD_KIND[primary.poi_type]
|
const kind = _HAZARD_KIND[primary.poi_type]
|
||||||
if (!kind) continue
|
if (!kind) continue
|
||||||
const alongValues = [front, back].filter((p): p is ApiTargetPoint => !!p).map(along)
|
const alongValues = [front, back].filter((p): p is ApiTargetPoint => !!p).map(along)
|
||||||
|
const farEdgeAlong = Math.max(...alongValues)
|
||||||
|
if (farEdgeAlong < playerAlongPercent - HAZARD_PASSED_TOLERANCE_PCT) continue
|
||||||
entities.push({
|
entities.push({
|
||||||
key: `group-${groupKey}`,
|
key: `group-${groupKey}`,
|
||||||
kind,
|
kind,
|
||||||
|
|
@ -162,6 +179,7 @@ function groupDiagramHazards(
|
||||||
for (const p of standalone) {
|
for (const p of standalone) {
|
||||||
const kind = _HAZARD_KIND[p.poi_type]
|
const kind = _HAZARD_KIND[p.poi_type]
|
||||||
if (!kind) continue
|
if (!kind) continue
|
||||||
|
if (along(p) < playerAlongPercent - HAZARD_PASSED_TOLERANCE_PCT) continue
|
||||||
entities.push({
|
entities.push({
|
||||||
key: `point-${p.latitude}-${p.longitude}-${p.poi_type}`,
|
key: `point-${p.latitude}-${p.longitude}-${p.poi_type}`,
|
||||||
kind,
|
kind,
|
||||||
|
|
@ -300,7 +318,16 @@ export function HoleTargetDistance({
|
||||||
// spilleren først. Avstandene er ALLTID live fra spilleren, uavhengig av
|
// spilleren først. Avstandene er ALLTID live fra spilleren, uavhengig av
|
||||||
// om et geometrisk diagram kan tegnes under.
|
// om et geometrisk diagram kan tegnes under.
|
||||||
const hazardPoints = points.filter((p) => p.poi_type in _HAZARD_LABELS)
|
const hazardPoints = points.filter((p) => p.poi_type in _HAZARD_LABELS)
|
||||||
const hazards = hazardPoints
|
// ADR-085 (brukerønske 2026-08-20): passerte hindringer skal ikke vises.
|
||||||
|
// Denne (tee-referanse mangler) grenen har ingen akse å projisere langs,
|
||||||
|
// så "mellom spiller og green" tilnærmes med "nærmere green enn
|
||||||
|
// spilleren selv" -- mindre presist enn along-percent-varianten under
|
||||||
|
// (tar ikke hensyn til sideveis avstand), men fungerer som en fornuftig
|
||||||
|
// proxy for det sjeldne tilfellet en bane mangler tee-koordinater.
|
||||||
|
const hazardPointsAhead = hazardPoints.filter(
|
||||||
|
(h) => haversineMeters({ lat: h.latitude, lng: h.longitude }, { lat: middle.latitude, lng: middle.longitude }) < distances.middle,
|
||||||
|
)
|
||||||
|
const hazards = hazardPointsAhead
|
||||||
.map((h) => {
|
.map((h) => {
|
||||||
const base = _HAZARD_LABELS[h.poi_type]
|
const base = _HAZARD_LABELS[h.poi_type]
|
||||||
const label =
|
const label =
|
||||||
|
|
@ -330,7 +357,7 @@ export function HoleTargetDistance({
|
||||||
if (teeRef) {
|
if (teeRef) {
|
||||||
const greenRef = { lat: middle.latitude, lng: middle.longitude }
|
const greenRef = { lat: middle.latitude, lng: middle.longitude }
|
||||||
const player = projectOntoAxis(teeRef, greenRef, livePosition)
|
const player = projectOntoAxis(teeRef, greenRef, livePosition)
|
||||||
const diagramHazards = groupDiagramHazards(hazardPoints, livePosition, teeRef, greenRef)
|
const diagramHazards = groupDiagramHazards(hazardPoints, livePosition, teeRef, greenRef, player.alongPercent)
|
||||||
return (
|
return (
|
||||||
<HoleDiagram
|
<HoleDiagram
|
||||||
size={size}
|
size={size}
|
||||||
|
|
|
||||||
|
|
@ -1494,7 +1494,11 @@ export function RoundDetail({ roundId }: { roundId: string }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RoundPageShell roundId={roundId} activeTab="score">
|
<RoundPageShell roundId={roundId} activeTab="score">
|
||||||
<main className="mx-auto w-full max-w-3xl flex-1 px-5 py-6 sm:py-8">
|
{/* pt redusert fra py-6/py-8 (2026-08-20, brukerfunn: unødvendig
|
||||||
|
luft under RoundHeader når ingen varsel-banner vises -- padding
|
||||||
|
her la seg OVENPÅ hull-seksjonens egen mt-5 lenger ned i stedet
|
||||||
|
for å erstatte den). Kun toppen redusert, bunnen uendret. */}
|
||||||
|
<main className="mx-auto w-full max-w-3xl flex-1 px-5 pb-6 pt-3 sm:pb-8 sm:pt-4">
|
||||||
{conflictNotice && (
|
{conflictNotice && (
|
||||||
<div
|
<div
|
||||||
role="alert"
|
role="alert"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue