feat: v0.11.0 — map interactions per PLAN.md: expanded airport popup (approx local time + deterministic generated weather), animated plane markers from /api/state polls with status popups, active contract route lines (pending dashed vs in-flight solid); pure libs lib/weather.ts, lib/localTime.ts, lib/mapData.ts

This commit is contained in:
2026-09-18 07:40:39 +00:00
parent 4c06ed26ff
commit 0208673da7
11 changed files with 874 additions and 14 deletions
+25
View File
@@ -0,0 +1,25 @@
// Approximate local wall-clock from longitude (v0.11.0) — display-only airport
// popup field. The zone is the fixed-offset band N = round(lon/15), no DST and no
// political boundaries — good enough for a game map, labelled approximate in the UI.
// Etc/GMT±N name for the band (POSIX sign flip: UTC+1 is "Etc/GMT-1"). Exported as
// the documented pure mapping; approxLocalTime below does NOT pass it to Intl,
// because some runtimes ship a reduced ICU that lacks the positive-offset zones.
export function approxZoneForLon(lonDeg: number): string {
const n = Math.max(-12, Math.min(12, Math.round(lonDeg / 15)));
return `Etc/GMT${n === 0 ? '' : -n}`;
}
// "HH:MM" in the approximate zone at epoch ms. Implemented as a UTC-format of a
// shifted timestamp (UTC + N hours) so it works on every ICU build, including
// small-icu runtimes missing Etc/GMT+N zones.
export function approxLocalTime(lonDeg: number, atMs: number): string {
const n = Math.max(-12, Math.min(12, Math.round(lonDeg / 15)));
const shifted = new Date(atMs + n * 3_600_000);
return new Intl.DateTimeFormat('en-GB', {
timeZone: 'UTC',
hour: '2-digit',
minute: '2-digit',
hourCycle: 'h23',
}).format(shifted);
}