Label Turkey station observations as MGM

This commit is contained in:
2569718930@qq.com
2026-06-15 21:02:44 +08:00
parent 95b55d4ab3
commit 55cfb202da
5 changed files with 82 additions and 0 deletions
@@ -541,6 +541,34 @@ export function runTests() {
"NOAA MADIS label should be reserved for US airports; non-US airport-primary fallback should use METAR wording",
);
const ankaraScanSeedChart = buildFullDayChartData(
{
city: "ankara",
local_date: "2026-06-14",
local_time: "15:10",
tz_offset_seconds: 3 * 60 * 60,
airport: "Esenboğa 机场",
temp_symbol: "°C",
} as any,
{
localDate: "2026-06-14",
localTime: "15:10",
times: ["00:00", "12:00", "18:00"],
temps: [15, 19, 18],
airportPrimary: {
temp: 19,
obs_time: "2026-06-14T12:10:00Z",
},
airportPrimaryTodayObs: [["2026-06-14T12:10:00Z", 19]],
} as any,
false,
);
const ankaraScanSeedSeries = ankaraScanSeedChart.series.find((item) => item.key === "madis");
assert(
ankaraScanSeedSeries?.label === "MGM",
"Ankara scan-row-seeded airport-primary curve should default to MGM instead of NOAA MADIS when source metadata is missing",
);
const guangzhouRunwayWithBadMadisChart = buildFullDayChartData(
{
city: "guangzhou",
@@ -775,8 +775,12 @@ function airportPrimarySeriesLabel(
row?: ScanOpportunityRow | null,
) {
if (isHKO) return "HKO";
const cityKey = normalizeCityKey(row?.city);
const canonicalLabel = canonicalAirportPrimarySourceLabel(hourly);
if (canonicalLabel === "MGM") return canonicalLabel;
if ((cityKey === "ankara" || cityKey === "istanbul") && (!canonicalLabel || canonicalLabel === "NOAA MADIS")) {
return "MGM";
}
const payloadLabel = String(hourly?.airportPrimary?.source_label || "").trim();
if (payloadLabel && !isGenericAirportPrimaryLabel(payloadLabel)) return payloadLabel;
if (canonicalLabel === "NOAA MADIS" && !isUsAirportCode(airportCodeForSeriesLabel(hourly, row))) {
+7
View File
@@ -533,6 +533,13 @@ export interface ScanOpportunityRow {
current_temp?: number | null;
current_max_so_far?: number | null;
wunderground_current?: AirportCurrentConditions;
icao?: string | null;
station_source_code?: string | null;
station_source_label?: string | null;
station_code?: string | null;
station_label?: string | null;
network_provider?: string | null;
network_provider_label?: string | null;
metar_context?: {
source?: string | null;
station?: string | null;
+34
View File
@@ -603,6 +603,40 @@ def test_scan_terminal_quick_row_compacts_runway_history_for_list_payload():
assert len(str(row["runway_plate_history"])) < len(str(raw_history))
def test_scan_terminal_quick_row_exposes_airport_primary_source_metadata():
row = _build_quick_row(
city="ankara",
data={
"display_name": "Ankara",
"local_date": "2026-06-14",
"local_time": "2026-06-14T15:10:00+03:00",
"temp_symbol": "°C",
"current": {"temp": 19.0, "max_so_far": 19.0},
"risk": {"airport": "Esenboğa", "icao": "LTAC", "level": "medium"},
"airport_primary": {
"station_code": "LTAC",
"station_label": "Esenboğa 机场",
"source_code": "mgm",
"source_label": "MGM",
},
"official_network_source": "turkey_mgm",
"official_network_status": {
"provider_code": "turkey_mgm",
"provider_label": "MGM",
},
"deb": {"prediction": 20.0},
"probabilities": {"distribution": []},
"multi_model": {},
},
)
assert row["icao"] == "LTAC"
assert row["station_source_code"] == "mgm"
assert row["station_source_label"] == "MGM"
assert row["station_code"] == "LTAC"
assert row["network_provider"] == "turkey_mgm"
def test_metar_gate_vetoes_yes_when_observed_breaks_above_bucket():
row = {
"id": "yes-row",
+9
View File
@@ -239,6 +239,8 @@ def _build_quick_row(
) -> Optional[Dict[str, Any]]:
curr = data.get("current") or {}
risk = data.get("risk") or {}
airport_primary = data.get("airport_primary") if isinstance(data.get("airport_primary"), dict) else {}
official_status = data.get("official_network_status") if isinstance(data.get("official_network_status"), dict) else {}
deb = data.get("deb") or {}
probs = data.get("probabilities") or {}
multi = data.get("multi_model") or {}
@@ -274,6 +276,13 @@ def _build_quick_row(
"current_temp": curr.get("temp"),
"current_max_so_far": curr.get("max_so_far"),
"wunderground_current": data.get("wunderground_current") or {},
"icao": str(risk.get("icao") or airport_primary.get("station_code") or ""),
"station_source_code": airport_primary.get("source_code") or data.get("official_network_source"),
"station_source_label": airport_primary.get("source_label") or official_status.get("provider_label"),
"station_code": airport_primary.get("station_code") or risk.get("icao"),
"station_label": airport_primary.get("station_label") or risk.get("airport"),
"network_provider": data.get("official_network_source") or official_status.get("provider_code"),
"network_provider_label": official_status.get("provider_label"),
"deb_prediction": deb.get("prediction"),
"model_cluster_sources": (
daily_entry.get("models")