Files
PolyWeather/frontend/lib/polymarket-market-links.ts
T
2569718930@qq.com 89a71d1bc0 Add Qingdao to the tradable city network
Qingdao needs the same airport-settlement path as the other Wunderground-backed APAC cities, so the registry, aliases, timezone, prewarm, official links, market focus, and tests now point to ZSQD / Qingdao Jiaodong International Airport.

Constraint: User supplied Wunderground Qingdao/ZSQD settlement URL.
Rejected: Add a partial registry-only entry | it would show in APIs without frontend links, prewarm coverage, or alias support.
Confidence: high
Scope-risk: narrow
Reversibility: clean
Tested: pytest tests/test_country_networks.py tests/test_web_observability.py::test_cities_endpoint_includes_new_wunderground_cities -q
Tested: npm run build
Not-tested: Live Wunderground fetch for ZSQD in production.
2026-04-28 07:08:33 +08:00

124 lines
2.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { CityDetail } from "@/lib/dashboard-types";
import type { Locale } from "@/lib/i18n";
const CITY_TO_MARKET_SLUG: Record<string, string> = {
ankara: "ankara",
atlanta: "atlanta",
austin: "austin",
beijing: "beijing",
"buenos aires": "buenos-aires",
chengdu: "chengdu",
chicago: "chicago",
chongqing: "chongqing",
dallas: "dallas",
houston: "houston",
"hong kong": "hong-kong",
istanbul: "istanbul",
london: "london",
"los angeles": "los-angeles",
lucknow: "lucknow",
madrid: "madrid",
mexico: "mexico-city",
"mexico city": "mexico-city",
miami: "miami",
milan: "milan",
munich: "munich",
"new york": "nyc",
paris: "paris",
qingdao: "qingdao",
"san francisco": "san-francisco",
"sao paulo": "sao-paulo",
seattle: "seattle",
seoul: "seoul",
shanghai: "shanghai",
shenzhen: "shenzhen",
singapore: "singapore",
taipei: "taipei",
"tel aviv": "tel-aviv",
tokyo: "tokyo",
toronto: "toronto",
warsaw: "warsaw",
wellington: "wellington",
wuhan: "wuhan",
};
const MONTHS = [
"january",
"february",
"march",
"april",
"may",
"june",
"july",
"august",
"september",
"october",
"november",
"december",
];
function normalizeCityKey(detail?: CityDetail | null) {
return String(detail?.name || detail?.display_name || "")
.trim()
.toLowerCase();
}
function slugifyCityName(cityKey: string) {
return cityKey
.trim()
.toLowerCase()
.replace(/['.]/g, "")
.replace(/&/g, " and ")
.replace(/\s+/g, "-");
}
function normalizeDateParts(localDate?: string | null) {
const value = String(localDate || "").trim();
const match = value.match(/^(\d{4})-(\d{2})-(\d{2})$/);
if (!match) return null;
const year = Number(match[1]);
const monthIndex = Number(match[2]) - 1;
const day = Number(match[3]);
if (
!Number.isFinite(year) ||
!Number.isFinite(monthIndex) ||
!Number.isFinite(day) ||
monthIndex < 0 ||
monthIndex > 11
) {
return null;
}
return {
year,
month: MONTHS[monthIndex],
day,
};
}
export function getTodayPolymarketUrl(
detail?: CityDetail | null,
locale: Locale = "en-US",
) {
const directMarketUrl = String(
detail?.market_scan?.market_url ||
detail?.market_scan?.primary_market_url ||
detail?.market_scan?.primary_market?.market_url ||
"",
).trim();
if (directMarketUrl) {
return directMarketUrl;
}
const cityKey = normalizeCityKey(detail);
const citySlug = CITY_TO_MARKET_SLUG[cityKey] || slugifyCityName(cityKey);
const dateParts = normalizeDateParts(detail?.local_date);
if (!citySlug || !dateParts) return null;
const prefix =
locale === "zh-CN"
? "https://polymarket.com/zh/event/"
: "https://polymarket.com/event/";
return `${prefix}highest-temperature-in-${citySlug}-on-${dateParts.month}-${dateParts.day}-${dateParts.year}`;
}