Fix WU historical current observation merge

This commit is contained in:
2569718930@qq.com
2026-05-29 17:20:07 +08:00
parent 8f52b1d80c
commit 9e3a4e2f45
13 changed files with 859 additions and 9 deletions
@@ -89,6 +89,10 @@ function formatCityLocalDate(tzOffsetSeconds: number | null | undefined) {
return `${y}-${m}-${d}`;
}
function getWundergroundDailyHigh(hourly: HourlyForecast) {
return validNumber(hourly?.wundergroundCurrent?.max_so_far) ?? null;
}
// ── Main component ─────────────────────────────────────────────────────
export function LiveTemperatureThresholdChart({
@@ -490,7 +494,7 @@ export function LiveTemperatureThresholdChart({
[row, chartHourly, settlementPlate],
);
const displayRunwayTemp = selectDisplayRunwayTemp(liveTemp, currentRunwayTemp, hasRunwayData);
const wundergroundDailyHigh = validNumber(chartHourly?.airportCurrent?.max_so_far ?? chartHourly?.airportPrimary?.max_so_far) ?? null;
const wundergroundDailyHigh = getWundergroundDailyHigh(chartHourly);
const localDateStr = chartLocalDate || new Date().toISOString().slice(0, 10);
const modelSources = (row?.model_cluster_sources && Object.keys(row.model_cluster_sources).length > 0)
@@ -795,6 +799,7 @@ export const __getDebPeakWindowRangeForTest = getDebPeakWindowRange;
export const __getLiveObservationLabelsForTest = getLiveObservationLabels;
export const __getObservationDisplayMetricsForTest = getObservationDisplayMetrics;
export const __getPeakGlowStateForTest = getPeakGlowState;
export const __getWundergroundDailyHighForTest = getWundergroundDailyHigh;
export const __shouldPollLiveChartForTest = shouldPollLiveChart;
export const __mergePatchIntoHourlyForTest = mergePatchIntoHourly;
export const __selectDisplayRunwayTempForTest = selectDisplayRunwayTemp;
@@ -5,6 +5,7 @@ import {
__getLiveObservationLabelsForTest,
__getObservationDisplayMetricsForTest,
__getPeakGlowStateForTest,
__getWundergroundDailyHighForTest,
__getVisibleTemperatureSeriesForTest,
__isTemperatureSeriesVisibleByDefaultForTest,
__mergePatchIntoHourlyForTest,
@@ -102,6 +103,22 @@ export function runTests() {
"morning observations near the intraday observed high should not trigger peak glow before the forecast hot window",
);
assert(
__getWundergroundDailyHighForTest({
wundergroundCurrent: { max_so_far: 26 },
airportCurrent: { max_so_far: 27 },
airportPrimary: { max_so_far: 27 },
} as any) === 26,
"WU display should use Wunderground historical.json high before airport/METAR highs",
);
assert(
__getWundergroundDailyHighForTest({
airportCurrent: { max_so_far: 27 },
airportPrimary: { max_so_far: 27 },
} as any) === null,
"WU display should not fall back to airport/METAR highs when historical.json is missing",
);
const guangzhou = {
city: "guangzhou",
local_date: "2026-05-25",
@@ -784,6 +784,7 @@ type HourlyForecast = {
amos?: AmosData | null;
airportCurrent?: AirportCurrentConditions | null;
airportPrimary?: AirportCurrentConditions | null;
wundergroundCurrent?: AirportCurrentConditions | null;
forecastDaily?: ForecastDay[];
multiModelDaily?: Record<string, DailyModelForecast>;
probabilities?: LegacyGaussianProbabilitySource | null;
@@ -809,6 +810,7 @@ function seedHourlyForecastFromRow(row: ScanOpportunityRow | null): HourlyForeca
amos: null,
airportCurrent: null,
airportPrimary: null,
wundergroundCurrent: (row as any)?.wunderground_current || null,
forecastDaily: [],
multiModelDaily: {},
probabilities: {
@@ -844,6 +846,7 @@ function parseHourlyForecastFromCityDetail(json: CityDetail | null): HourlyForec
amos: json.amos || null,
airportCurrent: json.airport_current || null,
airportPrimary: json.airport_primary || null,
wundergroundCurrent: (json as any).wunderground_current || (json as any)?.official?.wunderground_current || null,
forecastDaily: json.forecast?.daily || [],
multiModelDaily: json.multi_model_daily || {},
probabilities: json.probabilities || null,