diff --git a/docs/PRODUCT_WORKFLOWS.md b/docs/PRODUCT_WORKFLOWS.md index df78538..27aee1a 100644 --- a/docs/PRODUCT_WORKFLOWS.md +++ b/docs/PRODUCT_WORKFLOWS.md @@ -62,7 +62,7 @@ Fixed positions: | 4 | Rīga | | 5 | Jelgava | | 6 | Ainaži | -| 7 | Valmiera | +| 7 | Valmiera, sourced from Priekuļi (temporary substitute, see below) | | 8 | Madona | | 9 | Alūksne | | 10 | Zīlāni (temporary substitute for Jēkabpils) | @@ -83,7 +83,7 @@ Completed Faktiskā checkpoint: - automatic badge-relative image placement using consistent 256×256 asset geometry; - guarded 3840×1440 export using the fixed wind production artwork. -Confirmed Monda Regular/Bold files are now bundled and used. The export dimensions are locked, but final pixel-level placement must still be compared against the production masters after the font change. As of 2026-08-23 the 12 other fixed positions load real station data; Valmiera has no matching real open-data station yet, so it currently still shows the last synthetic row generated before synthetic data generation was stopped (increasingly stale, since nothing refreshes it). Once the old synthetic rows are wiped from `weather` (a still-pending step — see `docs/UPDATE_ROADMAP.md` Phase 7), Valmiera will show no data until a real source is found. +Confirmed Monda Regular/Bold files are now bundled and used. The export dimensions are locked, but final pixel-level placement must still be compared against the production masters after the font change. All 13 fixed positions now load real station data. Valmiera itself has no matching LVĢMC open-data station (confirmed live 2026-08-23); as of 2026-08-25 that position queries Priekuļi's reading instead, chosen as the closest currently-reporting station by measuring against the app's own calibrated map coordinates (~56px away vs. the next-closest candidate's ~81px). Valmiera's marker position and on-map label are unaffected — only the underlying data source for that slot changed. This is a provisional stand-in pending direct confirmation from LVĢMC. ## Ūdens @@ -151,7 +151,6 @@ Development limitation: representative forecast CSV fixtures are not currently i ## Decisions still required - Whether weather conditions can eventually be populated automatically and which provider field is authoritative. -- Whether Stende and Zīlāni remain the production feeds after users test real provider data. -- Confirm how Valmiera is named and sourced when authorized provider data is available. +- Whether Stende, Zīlāni, and now Priekuļi (for Valmiera) remain the production feeds after users test real provider data — Priekuļi is a provisional pick pending direct confirmation from LVĢMC. - Apply the same native-resolution production comparison to additional broadcast products as they are finalized. - Required authentication and role separation for analytical, production, and administrative workspaces. diff --git a/web/src/pages/map-graphics/MapGraphics.tsx b/web/src/pages/map-graphics/MapGraphics.tsx index 778d8b8..16e350c 100644 --- a/web/src/pages/map-graphics/MapGraphics.tsx +++ b/web/src/pages/map-graphics/MapGraphics.tsx @@ -7,10 +7,26 @@ import type { FaktiskaTemplate } from "./faktiskaTemplates"; import "./mapGraphics.css"; type LatestTemperature = { city: FaktiskaStation; observedAt: string; value: number | null }; +type RawLatestTemperature = { city: string; observedAt: string; value: number | null }; const emptyValues = (): Record => Object.fromEntries(faktiskaStations.map(city => [city, ""])) as Record; +// LVĢMC's open-data station list has no station in or near Valmiera at all +// (confirmed live 2026-08-23, see OpenDataStationService.scala). Priekuļi is +// the closest currently-reporting station (verified against the app's own +// calibrated map coordinates: ~56px away vs. the next-closest candidate's +// ~81px). Valmiera's marker position and on-map label stay exactly where +// they are -- only the queried data source for that one slot changes. +// Temporary, same pattern as Stende/Zīlāni substituting for Talsi/Jēkabpils +// (see PRODUCT_WORKFLOWS.md); pending confirmation directly from LVĢMC. +const stationSubstitutes: Partial> = { + "Valmiera": "Priekuļi", +}; +const substituteToStation = new Map( + Object.entries(stationSubstitutes).map(([station, substitute]) => [substitute, station as FaktiskaStation]) +); + export function Faktiska() { const [values, setValues] = createSignal(emptyValues()); const [overrides, setOverrides] = createSignal>(new Set()); @@ -21,9 +37,14 @@ export function Faktiska() { : { width: 3840, height: 1440 }; const fetchLatest = async (): Promise => { - const response = await fetch(`${apiHost}/api/query/latest-temperatures/${faktiskaStations.join(",")}`); + const queryCities = faktiskaStations.map(city => stationSubstitutes[city] ?? city); + const response = await fetch(`${apiHost}/api/query/latest-temperatures/${queryCities.join(",")}`); if (!response.ok) throw new Error(`Latest observations failed (${response.status})`); - return response.json(); + const observations: RawLatestTemperature[] = await response.json(); + return observations.map(observation => ({ + ...observation, + city: substituteToStation.get(observation.city) ?? observation.city as FaktiskaStation, + })); }; const [latest, { refetch }] = createResource(fetchLatest);