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:
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user