| """Local airport coordinate lookup (IATA/ICAO -> lat/lon). |
| |
| The FlightRadar24 plan in use cannot return airport coordinates (the /full |
| endpoint is 403, /light has no lat/lon), so we resolve destinations from the |
| bundled OpenFlights table (airports.dat) instead. This makes the estimated-path |
| arcs target the real destination rather than dead-reckoning to a random point. |
| """ |
| from __future__ import annotations |
|
|
| import csv |
| import os |
| from functools import lru_cache |
|
|
| _DAT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "airports.dat") |
|
|
|
|
| @lru_cache(maxsize=1) |
| def _index(): |
| """Build {CODE: (lat, lon)} for both IATA and ICAO codes.""" |
| idx = {} |
| try: |
| with open(_DAT, encoding="utf-8") as fh: |
| for row in csv.reader(fh): |
| if len(row) < 8: |
| continue |
| iata, icao, lat, lon = row[4], row[5], row[6], row[7] |
| try: |
| coords = (float(lat), float(lon)) |
| except (TypeError, ValueError): |
| continue |
| if iata and iata not in ("", "\\N"): |
| idx[iata.upper()] = coords |
| if icao and icao not in ("", "\\N"): |
| idx[icao.upper()] = coords |
| except FileNotFoundError: |
| return {} |
| return idx |
|
|
|
|
| def coords(code: str): |
| """Return (lat, lon) for an IATA or ICAO code, or None if unknown.""" |
| if not code: |
| return None |
| return _index().get(code.strip().upper()) |
|
|