feat: Implement PolyWeather web application with FastAPI backend for weather data analysis and a Leaflet-based frontend.
This commit is contained in:
@@ -9,6 +9,7 @@ CITY_REGISTRY = {
|
|||||||
"icao": "LTAC",
|
"icao": "LTAC",
|
||||||
"tz_offset": 10800,
|
"tz_offset": 10800,
|
||||||
"use_fahrenheit": False,
|
"use_fahrenheit": False,
|
||||||
|
"is_major": False,
|
||||||
"risk_level": "medium",
|
"risk_level": "medium",
|
||||||
"risk_emoji": "🟡",
|
"risk_emoji": "🟡",
|
||||||
"airport_name": "Esenboğa 机场",
|
"airport_name": "Esenboğa 机场",
|
||||||
@@ -22,6 +23,7 @@ CITY_REGISTRY = {
|
|||||||
"icao": "EGLC",
|
"icao": "EGLC",
|
||||||
"tz_offset": 0,
|
"tz_offset": 0,
|
||||||
"use_fahrenheit": False,
|
"use_fahrenheit": False,
|
||||||
|
"is_major": True,
|
||||||
"risk_level": "low",
|
"risk_level": "low",
|
||||||
"risk_emoji": "🟢",
|
"risk_emoji": "🟢",
|
||||||
"airport_name": "London City 机场",
|
"airport_name": "London City 机场",
|
||||||
@@ -35,6 +37,7 @@ CITY_REGISTRY = {
|
|||||||
"icao": "LFPG",
|
"icao": "LFPG",
|
||||||
"tz_offset": 3600,
|
"tz_offset": 3600,
|
||||||
"use_fahrenheit": False,
|
"use_fahrenheit": False,
|
||||||
|
"is_major": True,
|
||||||
"risk_level": "medium",
|
"risk_level": "medium",
|
||||||
"risk_emoji": "🟡",
|
"risk_emoji": "🟡",
|
||||||
"airport_name": "Charles de Gaulle 机场",
|
"airport_name": "Charles de Gaulle 机场",
|
||||||
@@ -48,6 +51,7 @@ CITY_REGISTRY = {
|
|||||||
"icao": "RKSI",
|
"icao": "RKSI",
|
||||||
"tz_offset": 32400,
|
"tz_offset": 32400,
|
||||||
"use_fahrenheit": False,
|
"use_fahrenheit": False,
|
||||||
|
"is_major": True,
|
||||||
"risk_level": "high",
|
"risk_level": "high",
|
||||||
"risk_emoji": "🔴",
|
"risk_emoji": "🔴",
|
||||||
"airport_name": "仁川国际机场",
|
"airport_name": "仁川国际机场",
|
||||||
@@ -61,6 +65,7 @@ CITY_REGISTRY = {
|
|||||||
"icao": "CYYZ",
|
"icao": "CYYZ",
|
||||||
"tz_offset": -18000,
|
"tz_offset": -18000,
|
||||||
"use_fahrenheit": False,
|
"use_fahrenheit": False,
|
||||||
|
"is_major": True,
|
||||||
"risk_level": "low",
|
"risk_level": "low",
|
||||||
"risk_emoji": "🟢",
|
"risk_emoji": "🟢",
|
||||||
"airport_name": "Pearson 国际机场",
|
"airport_name": "Pearson 国际机场",
|
||||||
@@ -74,6 +79,7 @@ CITY_REGISTRY = {
|
|||||||
"icao": "SAEZ",
|
"icao": "SAEZ",
|
||||||
"tz_offset": -10800,
|
"tz_offset": -10800,
|
||||||
"use_fahrenheit": False,
|
"use_fahrenheit": False,
|
||||||
|
"is_major": True,
|
||||||
"risk_level": "medium",
|
"risk_level": "medium",
|
||||||
"risk_emoji": "🟡",
|
"risk_emoji": "🟡",
|
||||||
"airport_name": "Ezeiza 国际机场",
|
"airport_name": "Ezeiza 国际机场",
|
||||||
@@ -87,6 +93,7 @@ CITY_REGISTRY = {
|
|||||||
"icao": "NZWN",
|
"icao": "NZWN",
|
||||||
"tz_offset": 46800,
|
"tz_offset": 46800,
|
||||||
"use_fahrenheit": False,
|
"use_fahrenheit": False,
|
||||||
|
"is_major": False,
|
||||||
"risk_level": "low",
|
"risk_level": "low",
|
||||||
"risk_emoji": "🟢",
|
"risk_emoji": "🟢",
|
||||||
"airport_name": "惠灵顿国际机场",
|
"airport_name": "惠灵顿国际机场",
|
||||||
@@ -100,6 +107,7 @@ CITY_REGISTRY = {
|
|||||||
"icao": "KLGA",
|
"icao": "KLGA",
|
||||||
"tz_offset": -18000,
|
"tz_offset": -18000,
|
||||||
"use_fahrenheit": True,
|
"use_fahrenheit": True,
|
||||||
|
"is_major": True,
|
||||||
"risk_level": "low",
|
"risk_level": "low",
|
||||||
"risk_emoji": "🟢",
|
"risk_emoji": "🟢",
|
||||||
"airport_name": "LaGuardia 机场",
|
"airport_name": "LaGuardia 机场",
|
||||||
@@ -113,6 +121,7 @@ CITY_REGISTRY = {
|
|||||||
"icao": "KORD",
|
"icao": "KORD",
|
||||||
"tz_offset": -21600,
|
"tz_offset": -21600,
|
||||||
"use_fahrenheit": True,
|
"use_fahrenheit": True,
|
||||||
|
"is_major": False,
|
||||||
"risk_level": "high",
|
"risk_level": "high",
|
||||||
"risk_emoji": "🔴",
|
"risk_emoji": "🔴",
|
||||||
"airport_name": "O'Hare 国际机场",
|
"airport_name": "O'Hare 国际机场",
|
||||||
@@ -126,6 +135,7 @@ CITY_REGISTRY = {
|
|||||||
"icao": "KDAL",
|
"icao": "KDAL",
|
||||||
"tz_offset": -21600,
|
"tz_offset": -21600,
|
||||||
"use_fahrenheit": True,
|
"use_fahrenheit": True,
|
||||||
|
"is_major": False,
|
||||||
"risk_level": "medium",
|
"risk_level": "medium",
|
||||||
"risk_emoji": "🟡",
|
"risk_emoji": "🟡",
|
||||||
"airport_name": "Dallas Love Field 机场",
|
"airport_name": "Dallas Love Field 机场",
|
||||||
@@ -139,6 +149,7 @@ CITY_REGISTRY = {
|
|||||||
"icao": "KMIA",
|
"icao": "KMIA",
|
||||||
"tz_offset": -18000,
|
"tz_offset": -18000,
|
||||||
"use_fahrenheit": True,
|
"use_fahrenheit": True,
|
||||||
|
"is_major": False,
|
||||||
"risk_level": "low",
|
"risk_level": "low",
|
||||||
"risk_emoji": "🟢",
|
"risk_emoji": "🟢",
|
||||||
"airport_name": "Miami 国际机场",
|
"airport_name": "Miami 国际机场",
|
||||||
@@ -152,6 +163,7 @@ CITY_REGISTRY = {
|
|||||||
"icao": "KATL",
|
"icao": "KATL",
|
||||||
"tz_offset": -18000,
|
"tz_offset": -18000,
|
||||||
"use_fahrenheit": True,
|
"use_fahrenheit": True,
|
||||||
|
"is_major": False,
|
||||||
"risk_level": "low",
|
"risk_level": "low",
|
||||||
"risk_emoji": "🟢",
|
"risk_emoji": "🟢",
|
||||||
"airport_name": "Hartsfield-Jackson 机场",
|
"airport_name": "Hartsfield-Jackson 机场",
|
||||||
@@ -165,6 +177,7 @@ CITY_REGISTRY = {
|
|||||||
"icao": "KSEA",
|
"icao": "KSEA",
|
||||||
"tz_offset": -28800,
|
"tz_offset": -28800,
|
||||||
"use_fahrenheit": True,
|
"use_fahrenheit": True,
|
||||||
|
"is_major": False,
|
||||||
"risk_level": "low",
|
"risk_level": "low",
|
||||||
"risk_emoji": "🟢",
|
"risk_emoji": "🟢",
|
||||||
"airport_name": "Sea-Tac 国际机场",
|
"airport_name": "Sea-Tac 国际机场",
|
||||||
@@ -178,6 +191,7 @@ CITY_REGISTRY = {
|
|||||||
"icao": "VILK",
|
"icao": "VILK",
|
||||||
"tz_offset": 19800,
|
"tz_offset": 19800,
|
||||||
"use_fahrenheit": False,
|
"use_fahrenheit": False,
|
||||||
|
"is_major": False,
|
||||||
"risk_level": "medium",
|
"risk_level": "medium",
|
||||||
"risk_emoji": "🟡",
|
"risk_emoji": "🟡",
|
||||||
"airport_name": "Chaudhary Charan Singh 国际机场",
|
"airport_name": "Chaudhary Charan Singh 国际机场",
|
||||||
@@ -191,6 +205,7 @@ CITY_REGISTRY = {
|
|||||||
"icao": "SBGR",
|
"icao": "SBGR",
|
||||||
"tz_offset": -10800,
|
"tz_offset": -10800,
|
||||||
"use_fahrenheit": False,
|
"use_fahrenheit": False,
|
||||||
|
"is_major": True,
|
||||||
"risk_level": "high",
|
"risk_level": "high",
|
||||||
"risk_emoji": "🔴",
|
"risk_emoji": "🔴",
|
||||||
"airport_name": "São Paulo/Guarulhos 机场",
|
"airport_name": "São Paulo/Guarulhos 机场",
|
||||||
@@ -204,6 +219,7 @@ CITY_REGISTRY = {
|
|||||||
"icao": "EDDM",
|
"icao": "EDDM",
|
||||||
"tz_offset": 3600,
|
"tz_offset": 3600,
|
||||||
"use_fahrenheit": False,
|
"use_fahrenheit": False,
|
||||||
|
"is_major": False,
|
||||||
"risk_level": "high",
|
"risk_level": "high",
|
||||||
"risk_emoji": "🔴",
|
"risk_emoji": "🔴",
|
||||||
"airport_name": "Munich 机场",
|
"airport_name": "Munich 机场",
|
||||||
|
|||||||
@@ -548,6 +548,7 @@ async def list_cities():
|
|||||||
"airport": risk.get("airport_name", ""),
|
"airport": risk.get("airport_name", ""),
|
||||||
"icao": risk.get("icao", ""),
|
"icao": risk.get("icao", ""),
|
||||||
"temp_unit": "fahrenheit" if info["f"] else "celsius",
|
"temp_unit": "fahrenheit" if info["f"] else "celsius",
|
||||||
|
"is_major": CITY_REGISTRY.get(name, {}).get("is_major", True),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return {"cities": out}
|
return {"cities": out}
|
||||||
|
|||||||
@@ -71,6 +71,33 @@ function initMap() {
|
|||||||
map.on("click", () => {
|
map.on("click", () => {
|
||||||
closePanel();
|
closePanel();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Handle zoom-based visibility for local stations and minor cities
|
||||||
|
map.on("zoomend", updateMapVisibility);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateMapVisibility() {
|
||||||
|
if (!map) return;
|
||||||
|
const zoom = map.getZoom();
|
||||||
|
|
||||||
|
// 1. Handle Nearby Individual Stations (very high zoom only)
|
||||||
|
// These are the "Ankara-style" local station markers
|
||||||
|
if (zoom < 7) {
|
||||||
|
if (map.hasLayer(nearbyLayerGroup)) map.removeLayer(nearbyLayerGroup);
|
||||||
|
} else {
|
||||||
|
if (!map.hasLayer(nearbyLayerGroup)) map.addLayer(nearbyLayerGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Handle Primary City Markers (Major vs Minor)
|
||||||
|
Object.values(markers).forEach(({ marker, city }) => {
|
||||||
|
const isMajor = city.is_major !== false;
|
||||||
|
// Hide minor cities (like Ankara/Atlanta) when zoomed way out
|
||||||
|
if (zoom < 4 && !isMajor) {
|
||||||
|
if (map.hasLayer(marker)) map.removeLayer(marker);
|
||||||
|
} else {
|
||||||
|
if (!map.hasLayer(marker)) map.addLayer(marker);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ──────────────────────────────────────────────────────────
|
// ──────────────────────────────────────────────────────────
|
||||||
@@ -109,6 +136,7 @@ function addCityMarkers(cities) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById("cityCount").textContent = cities.length;
|
document.getElementById("cityCount").textContent = cities.length;
|
||||||
|
updateMapVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateMarkerTemp(cityName, temp) {
|
function updateMarkerTemp(cityName, temp) {
|
||||||
|
|||||||
Reference in New Issue
Block a user