osint-dashboard/app/chokepoints.py
Sirius DevOps ef8b877d21 feat(map): chokepoint preset catalog + vessels ?src= filter
- 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.
2026-08-29 14:03:15 -04:00

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]