- GET /api/map/chokepoints: static five-strait fly-to catalog (Hormuz, Bab el-Mandeb, Suez, Malacca, Taiwan) with bbox/center/zoom/vesselapi. No VesselAPI calls; only Hormuz flags vesselapi=true. - GET /api/vessels?src=aisstream|vesselapi|all (default all) filters the union store by provider so a Hormuz view skips ~5k CONUS AISStream rows. - Tests: span validation of all five boxes, catalog 200 shape, src filter.
62 lines
1.7 KiB
Python
62 lines
1.7 KiB
Python
"""Static chokepoint preset catalog — one-tap fly-to targets for the map.
|
|
|
|
Pure data, no upstream calls and no VesselAPI quota spend. ``vesselapi`` is
|
|
``True`` only for Hormuz (the single box the VesselAPI poller already covers);
|
|
every other strait is AISStream-only until a human later spends quota. Never
|
|
call VesselAPI from here.
|
|
|
|
Bounding boxes are ``minlat,minlon,maxlat,maxlon`` (VesselAPI order) and each
|
|
stays within the ``|dLat|+|dLon| <= 4`` span rule enforced by
|
|
``vesselapi.validate_bbox_span``.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
# id → preset. ``center`` is ``[lat, lon]`` for Leaflet ``setView``.
|
|
_CHOKEPOINTS: tuple[dict, ...] = (
|
|
{
|
|
"id": "hormuz",
|
|
"title": "Strait of Hormuz",
|
|
"bbox": "25.5,55.4,27.3,57.2",
|
|
"center": [26.4, 56.5],
|
|
"zoom": 9,
|
|
"vesselapi": True,
|
|
},
|
|
{
|
|
"id": "bab_el_mandeb",
|
|
"title": "Bab el-Mandeb",
|
|
"bbox": "12.0,42.8,13.5,44.3",
|
|
"center": [12.7, 43.4],
|
|
"zoom": 9,
|
|
"vesselapi": False,
|
|
},
|
|
{
|
|
"id": "suez",
|
|
"title": "Suez / N. Red Sea",
|
|
"bbox": "29.5,32.0,31.0,33.5",
|
|
"center": [30.0,32.5],
|
|
"zoom": 9,
|
|
"vesselapi": False,
|
|
},
|
|
{
|
|
"id": "malacca",
|
|
"title": "Malacca / Singapore",
|
|
"bbox": "1.0,103.0,2.5,104.5",
|
|
"center": [1.3, 103.8],
|
|
"zoom": 9,
|
|
"vesselapi": False,
|
|
},
|
|
{
|
|
"id": "taiwan",
|
|
"title": "Taiwan Strait",
|
|
"bbox": "23.5,119.0,25.0,120.5",
|
|
"center": [24.2, 119.8],
|
|
"zoom": 9,
|
|
"vesselapi": False,
|
|
},
|
|
)
|
|
|
|
|
|
def chokepoints() -> list[dict]:
|
|
"""Return a fresh copy of the catalog (callers must not mutate the source)."""
|
|
return [dict(p) for p in _CHOKEPOINTS]
|