fix: align hong kong compact hko stat
This commit is contained in:
@@ -31,6 +31,7 @@ import {
|
||||
normObs,
|
||||
prefersHighFrequencyRunwayResolution,
|
||||
readSessionCache,
|
||||
selectCompactSecondaryTemp,
|
||||
selectDisplayRunwayTemp,
|
||||
seedHourlyForecastFromRow,
|
||||
shouldPollLiveChart,
|
||||
@@ -635,6 +636,7 @@ export function LiveTemperatureThresholdChart({
|
||||
}, [chartSeries, userToggledKeys, city, showRunwayDetails]);
|
||||
|
||||
const {
|
||||
isHKO,
|
||||
isShenzhen,
|
||||
metarHeaderLabel,
|
||||
metarHighLabel,
|
||||
@@ -642,11 +644,17 @@ export function LiveTemperatureThresholdChart({
|
||||
runwayHighLabel,
|
||||
} = useMemo(() => getLiveObservationLabels(row, chartHourly), [row, chartHourly]);
|
||||
|
||||
const { currentRunwayTemp, observedHighMetar, observedHighRunway } = useMemo(
|
||||
const { currentMetarTemp, currentRunwayTemp, observedHighMetar, observedHighRunway } = useMemo(
|
||||
() => getObservationDisplayMetrics(row, chartHourly, settlementPlate),
|
||||
[row, chartHourly, settlementPlate],
|
||||
);
|
||||
const displayRunwayTemp = selectDisplayRunwayTemp(liveTemp, currentRunwayTemp, hasRunwayData);
|
||||
const displayMetarTemp = selectCompactSecondaryTemp({
|
||||
isHKO,
|
||||
isShenzhen,
|
||||
displayMetarTemp: currentMetarTemp,
|
||||
observedHighMetar,
|
||||
});
|
||||
const wundergroundDailyHigh = getWundergroundDailyHigh(chartHourly);
|
||||
|
||||
const localDateStr = chartLocalDate || new Date().toISOString().slice(0, 10);
|
||||
@@ -805,6 +813,7 @@ export function LiveTemperatureThresholdChart({
|
||||
visible_series: activeSeries.map((item) => item.key),
|
||||
live_temp: liveTemp,
|
||||
current_runway_temp: currentRunwayTemp,
|
||||
current_metar_temp: currentMetarTemp,
|
||||
observed_high_metar: observedHighMetar,
|
||||
observed_high_runway: observedHighRunway,
|
||||
});
|
||||
@@ -814,6 +823,7 @@ export function LiveTemperatureThresholdChart({
|
||||
chartSeries,
|
||||
city,
|
||||
compact,
|
||||
currentMetarTemp,
|
||||
currentRunwayTemp,
|
||||
detailError,
|
||||
hasRunwayData,
|
||||
@@ -960,6 +970,7 @@ export function LiveTemperatureThresholdChart({
|
||||
metarHighLabel={metarHighLabel}
|
||||
isShenzhen={isShenzhen}
|
||||
displayRunwayTemp={displayRunwayTemp}
|
||||
displayMetarTemp={displayMetarTemp}
|
||||
observedHighMetar={observedHighMetar}
|
||||
observedHighRunway={observedHighRunway}
|
||||
wundergroundDailyHigh={wundergroundDailyHigh}
|
||||
@@ -1034,4 +1045,5 @@ export const __getInitialDetailLoadDelayMsForTest = getInitialDetailLoadDelayMs;
|
||||
export const __shouldFetchCityDetailForChartForTest = shouldFetchCityDetailForChart;
|
||||
export const __shouldPollLiveChartForTest = shouldPollLiveChart;
|
||||
export const __mergePatchIntoHourlyForTest = mergePatchIntoHourly;
|
||||
export const __selectCompactSecondaryTempForTest = selectCompactSecondaryTemp;
|
||||
export const __selectDisplayRunwayTempForTest = selectDisplayRunwayTemp;
|
||||
|
||||
@@ -76,6 +76,7 @@ export function TemperatureStatsBars({
|
||||
metarHighLabel,
|
||||
isShenzhen,
|
||||
displayRunwayTemp,
|
||||
displayMetarTemp,
|
||||
observedHighMetar,
|
||||
observedHighRunway,
|
||||
wundergroundDailyHigh,
|
||||
@@ -97,6 +98,7 @@ export function TemperatureStatsBars({
|
||||
metarHighLabel: string;
|
||||
isShenzhen: boolean;
|
||||
displayRunwayTemp: number | null;
|
||||
displayMetarTemp: number | null;
|
||||
observedHighMetar: number | null;
|
||||
observedHighRunway: number | null;
|
||||
wundergroundDailyHigh: number | null;
|
||||
@@ -129,7 +131,7 @@ export function TemperatureStatsBars({
|
||||
<span className="text-slate-300">|</span>
|
||||
<span className="font-semibold text-slate-500">
|
||||
{labels.compactSecondary}:{" "}
|
||||
<strong className="text-blue-600 font-mono">{temp(observedHighMetar, tempSymbol)}</strong>
|
||||
<strong className="text-blue-600 font-mono">{temp(displayMetarTemp, tempSymbol)}</strong>
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
+63
@@ -9,6 +9,7 @@ import {
|
||||
__getVisibleTemperatureSeriesForTest,
|
||||
__isTemperatureSeriesVisibleByDefaultForTest,
|
||||
__mergePatchIntoHourlyForTest,
|
||||
__selectCompactSecondaryTempForTest,
|
||||
__selectDisplayRunwayTempForTest,
|
||||
} from "@/components/dashboard/scan-terminal/LiveTemperatureThresholdChart";
|
||||
import { __buildTemperatureTooltipRowsForTest } from "@/components/dashboard/scan-terminal/TemperatureTooltipContent";
|
||||
@@ -976,6 +977,68 @@ export function runTests() {
|
||||
"runway header should prefer runway-history current temp even when the latest detail payload lacks runway_obs snapshot",
|
||||
);
|
||||
|
||||
const hongKongMetrics = __getObservationDisplayMetricsForTest(
|
||||
{
|
||||
city: "hong kong",
|
||||
local_date: "2026-06-06",
|
||||
local_time: "16:48",
|
||||
tz_offset_seconds: 8 * 60 * 60,
|
||||
current_temp: 30.4,
|
||||
current_max_so_far: 30.4,
|
||||
temp_symbol: "°C",
|
||||
} as any,
|
||||
{
|
||||
localTime: "16:48",
|
||||
times: ["00:00", "12:00", "18:00", "23:00"],
|
||||
temps: [28.0, 31.0, 29.0, 28.0],
|
||||
settlementTodayObs: [
|
||||
{ time: "14:00", temp: 30.4 },
|
||||
{ time: "16:40", temp: 28.1 },
|
||||
],
|
||||
airportPrimary: {
|
||||
temp: 28.7,
|
||||
obs_time: "2026-06-06T16:48:00+08:00",
|
||||
source_code: "cowin_obs",
|
||||
source_label: "CoWIN 6087",
|
||||
},
|
||||
airportPrimaryTodayObs: [
|
||||
{ time: "16:47", temp: 28.6 },
|
||||
{ time: "16:48", temp: 28.7 },
|
||||
],
|
||||
} as any,
|
||||
null,
|
||||
);
|
||||
assert(
|
||||
hongKongMetrics.currentRunwayTemp === 28.7,
|
||||
"Hong Kong primary compact stat should stay on the latest CoWIN reference-station point",
|
||||
);
|
||||
assert(
|
||||
(hongKongMetrics as any).currentMetarTemp === 28.1,
|
||||
"Hong Kong secondary compact stat should have the latest HKO point separate from the HKO daily high",
|
||||
);
|
||||
assert(
|
||||
hongKongMetrics.observedHighMetar === 30.4,
|
||||
"Hong Kong HKO daily high should still be available for expanded daily-high summaries",
|
||||
);
|
||||
assert(
|
||||
__selectCompactSecondaryTempForTest({
|
||||
isHKO: true,
|
||||
isShenzhen: false,
|
||||
displayMetarTemp: (hongKongMetrics as any).currentMetarTemp,
|
||||
observedHighMetar: hongKongMetrics.observedHighMetar,
|
||||
}) === 28.1,
|
||||
"Hong Kong compact HKO stat should render the latest HKO point, not the HKO daily high",
|
||||
);
|
||||
assert(
|
||||
__selectCompactSecondaryTempForTest({
|
||||
isHKO: false,
|
||||
isShenzhen: false,
|
||||
displayMetarTemp: 72.0,
|
||||
observedHighMetar: 73.9,
|
||||
}) === 73.9,
|
||||
"non-HKO compact secondary stat should keep the existing daily-high behavior",
|
||||
);
|
||||
|
||||
const wuhanRunwayChart = __buildTemperatureChartDataForTest(
|
||||
{
|
||||
city: "wuhan",
|
||||
|
||||
@@ -845,9 +845,14 @@ function getObservationDisplayMetrics(
|
||||
null;
|
||||
}
|
||||
|
||||
const currentMetarTemp =
|
||||
latestSettlement ??
|
||||
latestMetar ??
|
||||
airportCurrentTemp ??
|
||||
null;
|
||||
const observedHighMetar = airportHigh ?? highSettlement ?? highMetar ?? rowMetarHigh ?? null;
|
||||
|
||||
return { currentRunwayTemp, observedHighMetar, observedHighRunway };
|
||||
return { currentMetarTemp, currentRunwayTemp, observedHighMetar, observedHighRunway };
|
||||
}
|
||||
|
||||
function selectDisplayRunwayTemp(
|
||||
@@ -859,6 +864,23 @@ function selectDisplayRunwayTemp(
|
||||
return liveTemp;
|
||||
}
|
||||
|
||||
function selectCompactSecondaryTemp({
|
||||
isHKO,
|
||||
isShenzhen,
|
||||
displayMetarTemp,
|
||||
observedHighMetar,
|
||||
}: {
|
||||
isHKO: boolean;
|
||||
isShenzhen: boolean;
|
||||
displayMetarTemp: number | null;
|
||||
observedHighMetar: number | null;
|
||||
}) {
|
||||
if (isHKO && !isShenzhen && displayMetarTemp !== null) {
|
||||
return displayMetarTemp;
|
||||
}
|
||||
return observedHighMetar;
|
||||
}
|
||||
|
||||
function isSettlementRunway(row: ScanOpportunityRow | null, rwy: string) {
|
||||
const cityKey = normalizeCityKey(row?.city);
|
||||
const settlementPairs = SETTLEMENT_RUNWAY_PAIRS[cityKey] || [];
|
||||
@@ -2485,6 +2507,7 @@ export {
|
||||
normalizeCityKey,
|
||||
prefersHighFrequencyRunwayResolution,
|
||||
readSessionCache,
|
||||
selectCompactSecondaryTemp,
|
||||
selectDisplayRunwayTemp,
|
||||
seedHourlyForecastFromRow,
|
||||
seriesStats,
|
||||
|
||||
Reference in New Issue
Block a user