fix(weather): keep absent observations unknown instead of reporting clear skies

This commit is contained in:
Rudy Celekli committed 2026-10-14 14:17:48 -04:00
1 parent 6dd4d0156f
commit c86c1a4cce
4 files changed
+48 -2

No files matched your search

+2
View File
@@ -15,6 +15,8 @@
the five borough cores load and `CCTV_NYC_MAX_SOURCES` changes the cap. The catalog-wide ceiling is
unchanged; extra cameras share it round-robin with the other packs.
- Weather records keep missing conditions unknown and refuse summaries without a measured temperature.
- Treat explicitly current, complete empty vessel coverage as a successful update,
clearing obsolete contacts while retaining stale or incomplete snapshots.
+5
View File
@@ -5310,3 +5310,8 @@ datacenters, dams and the Nepal locator retain that shared credit while displaye
Military fragments stitch by source identity. Different mapped parcels merge only
when their footprints touch or contain one another, never across a seam tolerance gap.
### fix(weather): keep absent observations unknown instead of reporting clear skies
Refuse absent or boolean primary temperatures and keep absent/boolean weather codes explicitly CONDITIONS UNKNOWN while retaining valid numeric strings and real zero observations.
+21 -2
View File
@@ -90,9 +90,22 @@ export function normalizeRegionalArticles(payload, limit = MAX_ARTICLES) {
/** Normalize Open-Meteo current conditions into a small source-stamped record. */
export function normalizeRegionalWeather(payload) {
const current = payload?.current;
if (!current || !Number.isFinite(Number(current.temperature_2m))) return null;
if (
!current ||
current.temperature_2m == null ||
typeof current.temperature_2m === 'boolean' ||
(typeof current.temperature_2m === 'string' &&
!current.temperature_2m.trim()) ||
!Number.isFinite(Number(current.temperature_2m))
)
return null;
const numberOrNull = (value) => {
if (value === null || value === undefined || value === '') return null;
if (
value == null ||
typeof value === 'boolean' ||
(typeof value === 'string' && !value.trim())
)
return null;
return Number.isFinite(Number(value)) ? Number(value) : null;
};
// Open-Meteo reports zone-naive timestamps ("2026-08-17T00:15") that are UTC,
@@ -119,6 +132,12 @@ export function normalizeRegionalWeather(payload) {
/** Translate the WMO weather code used by Open-Meteo into concise cockpit copy. */
export function weatherCodeLabel(code) {
if (
code == null ||
typeof code === 'boolean' ||
(typeof code === 'string' && !code.trim())
)
return 'CONDITIONS UNKNOWN';
const value = Number(code);
if (!Number.isFinite(value)) return 'CONDITIONS UNKNOWN';
if (value === 0) return 'CLEAR';
@@ -0,0 +1,20 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { normalizeRegionalWeather, weatherCodeLabel } from './regionalModel.js';
test('missing weather observations never assert clear conditions', () => {
for (const value of [null, undefined, '', ' ', false, true]) {
assert.equal(weatherCodeLabel(value), 'CONDITIONS UNKNOWN');
assert.equal(
normalizeRegionalWeather({ current: { temperature_2m: value } }),
null,
);
}
assert.equal(weatherCodeLabel(0), 'CLEAR');
assert.equal(weatherCodeLabel('0'), 'CLEAR');
const record = normalizeRegionalWeather({
current: { temperature_2m: 0, weather_code: null, wind_speed_10m: false },
});
assert.equal(record.temperatureC, 0);
assert.equal(record.weatherCode, null);
assert.equal(record.windKph, null);
});