import { mulberry32 } from './game/seed'; // Pure deterministic per-airport weather (v0.11.0) — display-only per PLAN.md, no // gameplay effects. The same ICAO always yields the same weather (stable across // polls and sessions); an optional dayKey varies it by sim-day when wanted. export type WeatherCondition = 'Clear' | 'Cloudy' | 'Rain' | 'Fog'; export interface AirportWeather { condition: WeatherCondition; // Meteorological convention: direction the wind blows FROM, degrees true [0, 360). windDirDeg: number; windKt: number; visibilityM: number; } // FNV-1a 32-bit — cheap, stable string hash (no Math.random, no Date anywhere). function fnv1a(s: string): number { let h = 0x811c9dc5; for (let i = 0; i < s.length; i++) { h ^= s.charCodeAt(i); h = Math.imul(h, 0x01000193); } return h >>> 0; } export function weatherFor(icao: string, dayKey?: number): AirportWeather { const seed = (fnv1a(icao) ^ (dayKey === undefined ? 0 : Math.imul(dayKey | 0, 0x9e3779b9))) >>> 0; const rng = mulberry32(seed); const c = rng(); let condition: WeatherCondition; if (c < 0.45) condition = 'Clear'; else if (c < 0.75) condition = 'Cloudy'; else if (c < 0.92) condition = 'Rain'; else condition = 'Fog'; const windDirDeg = Math.floor(rng() * 360); const windKt = Math.round(2 + rng() * 28); // 2–30 kt let visibilityM: number; if (condition === 'Fog') visibilityM = 500 + Math.floor(rng() * 1500); // 0.5–2 km else if (condition === 'Rain') visibilityM = 4000 + Math.floor(rng() * 6000); // 4–10 km else visibilityM = 8000 + Math.floor(rng() * 32000); // 8–40 km return { condition, windDirDeg, windKt, visibilityM }; }