重构跑道观测系统:全跑道展示、结算跑道标注、热力模型、风场分析

This commit is contained in:
2569718930@qq.com
2026-05-20 18:16:27 +08:00
parent 4e59c41c81
commit 9b2ac614cb
10 changed files with 399 additions and 143 deletions
+97
View File
@@ -403,6 +403,35 @@ class DBManager:
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_airport_obs_log_icao_time ON airport_obs_log(icao, created_at DESC)"
)
conn.execute(
"""
CREATE TABLE IF NOT EXISTS runway_obs_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
icao TEXT NOT NULL,
city TEXT NOT NULL,
runway TEXT NOT NULL,
tdz_temp REAL,
mid_temp REAL,
end_temp REAL,
target_runway_max REAL,
wind_dir INTEGER,
wind_speed REAL,
rvr INTEGER,
mor REAL,
humidity REAL,
otime_utc TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
"""
)
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_runway_obs_log_icao_otime "
"ON runway_obs_log(icao, otime_utc DESC)"
)
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_runway_obs_log_city_time "
"ON runway_obs_log(city, created_at DESC)"
)
self._ensure_column(conn, "users", "daily_points", "INTEGER DEFAULT 0")
self._ensure_column(conn, "users", "daily_points_date", "TEXT")
self._ensure_column(conn, "users", "weekly_points", "INTEGER DEFAULT 0")
@@ -2202,3 +2231,71 @@ class DBManager:
(str(icao).strip().upper(), str(-int(minutes))),
).fetchall()
return [dict(r) for r in rows]
def append_runway_obs(
self,
icao: str,
city: str,
runway: str,
tdz_temp: Optional[float] = None,
mid_temp: Optional[float] = None,
end_temp: Optional[float] = None,
target_runway_max: Optional[float] = None,
wind_dir: Optional[int] = None,
wind_speed: Optional[float] = None,
rvr: Optional[int] = None,
mor: Optional[float] = None,
humidity: Optional[float] = None,
otime_utc: str = "",
) -> None:
"""Insert one runway observation row (deduplicated by icao+runway+otime_utc)."""
safe_icao = str(icao or "").strip().upper()
safe_city = str(city or "").strip().lower()
safe_runway = str(runway or "").strip().upper()
safe_otime = str(otime_utc or "").strip()
if not safe_icao or not safe_runway or not safe_otime:
return
with self._get_connection() as conn:
existing = conn.execute(
"SELECT id FROM runway_obs_log WHERE icao=? AND runway=? AND otime_utc=? LIMIT 1",
(safe_icao, safe_runway, safe_otime),
).fetchone()
if existing:
return
conn.execute(
"""
INSERT INTO runway_obs_log (
icao, city, runway,
tdz_temp, mid_temp, end_temp, target_runway_max,
wind_dir, wind_speed, rvr, mor, humidity,
otime_utc
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
safe_icao, safe_city, safe_runway,
tdz_temp, mid_temp, end_temp, target_runway_max,
wind_dir, wind_speed, rvr, mor, humidity,
safe_otime,
),
)
conn.commit()
def get_runway_obs_recent(
self, icao: str, minutes: int = 60
) -> List[Dict[str, Any]]:
"""Get recent runway observations for trend analysis."""
with self._get_connection() as conn:
conn.row_factory = sqlite3.Row
rows = conn.execute(
"""
SELECT icao, city, runway,
tdz_temp, mid_temp, end_temp, target_runway_max,
wind_dir, wind_speed, rvr, mor, humidity,
otime_utc, created_at
FROM runway_obs_log
WHERE icao = ? AND created_at >= datetime('now', ? || ' minutes')
ORDER BY created_at ASC
""",
(str(icao).strip().upper(), str(-int(minutes))),
).fetchall()
return [dict(r) for r in rows]