Ensure DEB chart path covers full day
This commit is contained in:
@@ -69,6 +69,15 @@ export function runTests() {
|
|||||||
ankaraChartData?.datasets.debSeries.some((point) => point.labelTime === "13:00"),
|
ankaraChartData?.datasets.debSeries.some((point) => point.labelTime === "13:00"),
|
||||||
"Ankara chart should build the DEB original path from MGM hourly data when Open-Meteo hourly is unavailable",
|
"Ankara chart should build the DEB original path from MGM hourly data when Open-Meteo hourly is unavailable",
|
||||||
);
|
);
|
||||||
|
assert(
|
||||||
|
ankaraChartData?.datasets.debSeries.length === 48,
|
||||||
|
"DEB original path must cover the full 00:00-23:30 chart day even when city hourly data is partial",
|
||||||
|
);
|
||||||
|
assert(
|
||||||
|
ankaraChartData?.datasets.debSeries.some((point) => point.labelTime === "00:00") &&
|
||||||
|
ankaraChartData?.datasets.debSeries.some((point) => point.labelTime === "23:30"),
|
||||||
|
"DEB original path must include both start-of-day and end-of-day points",
|
||||||
|
);
|
||||||
assert(
|
assert(
|
||||||
ankaraChartData?.datasets.calibratedFutureSeries.length,
|
ankaraChartData?.datasets.calibratedFutureSeries.length,
|
||||||
"Ankara chart should still expose a calibrated path when observation points exist",
|
"Ankara chart should still expose a calibrated path when observation points exist",
|
||||||
|
|||||||
@@ -119,6 +119,25 @@ function buildObservationPoints(items: Array<{ time?: string; temp?: number | nu
|
|||||||
.filter((point): point is { labelTime: string; x: number; y: number } => point != null);
|
.filter((point): point is { labelTime: string; x: number; y: number } => point != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fillTemperaturePathForFullDay(
|
||||||
|
times: string[],
|
||||||
|
values: Array<number | null>,
|
||||||
|
) {
|
||||||
|
if (!times.length) return values;
|
||||||
|
const hasAnyValue = values.some((value) => value != null && Number.isFinite(value));
|
||||||
|
if (!hasAnyValue) return values;
|
||||||
|
return times.map((time, index) => {
|
||||||
|
const value = values[index];
|
||||||
|
if (value != null && Number.isFinite(value)) return value;
|
||||||
|
const minute = hmToMinutes(time);
|
||||||
|
if (minute == null) return null;
|
||||||
|
const interpolated = interpolateSeriesAtMinutes(times, values, minute);
|
||||||
|
return interpolated != null && Number.isFinite(interpolated)
|
||||||
|
? interpolated
|
||||||
|
: null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function clampTemperatureDelta(value: number, min = -4, max = 4) {
|
function clampTemperatureDelta(value: number, min = -4, max = 4) {
|
||||||
return Math.min(Math.max(value, min), max);
|
return Math.min(Math.max(value, min), max);
|
||||||
}
|
}
|
||||||
@@ -408,12 +427,10 @@ export function getTemperatureChartData(
|
|||||||
const hh = String(h).padStart(2, "0");
|
const hh = String(h).padStart(2, "0");
|
||||||
times.push(`${hh}:00`);
|
times.push(`${hh}:00`);
|
||||||
temps.push(getHourTemp(h));
|
temps.push(getHourTemp(h));
|
||||||
if (h < 23) {
|
const a = getHourTemp(h);
|
||||||
const a = getHourTemp(h);
|
const b = h < 23 ? getHourTemp(h + 1) : null;
|
||||||
const b = getHourTemp(h + 1);
|
times.push(`${hh}:30`);
|
||||||
times.push(`${hh}:30`);
|
temps.push(a != null && b != null ? Number((a + (b - a) * 0.5).toFixed(1)) : a ?? b);
|
||||||
temps.push(a != null && b != null ? Number((a + (b - a) * 0.5).toFixed(1)) : a ?? b);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const suppressAnkaraMgmObservation = isTurkishMgmCity(detail);
|
const suppressAnkaraMgmObservation = isTurkishMgmCity(detail);
|
||||||
|
|
||||||
@@ -431,7 +448,8 @@ export function getTemperatureChartData(
|
|||||||
const debMax = detail.deb?.prediction;
|
const debMax = detail.deb?.prediction;
|
||||||
const offset =
|
const offset =
|
||||||
debMax != null && omMax != null ? Number(debMax) - Number(omMax) : 0;
|
debMax != null && omMax != null ? Number(debMax) - Number(omMax) : 0;
|
||||||
const debTemps = temps.map((temp) =>
|
const debBaseTemps = fillTemperaturePathForFullDay(times, temps);
|
||||||
|
const debTemps = debBaseTemps.map((temp) =>
|
||||||
temp != null && Number.isFinite(temp)
|
temp != null && Number.isFinite(temp)
|
||||||
? Number((temp + offset).toFixed(1))
|
? Number((temp + offset).toFixed(1))
|
||||||
: null,
|
: null,
|
||||||
|
|||||||
Reference in New Issue
Block a user