Draw supply routes on the react map.

https://github.com/dcs-liberation/dcs_liberation/issues/2039
This commit is contained in:
Dan Albert
2022-03-02 23:10:11 -08:00
parent 0bdb4ac894
commit 9a2c10a98f
15 changed files with 280 additions and 1 deletions

View File

@@ -8,6 +8,7 @@ from . import (
flights,
mapzones,
navmesh,
supplyroutes,
tgos,
waypoints,
)
@@ -25,6 +26,7 @@ app.include_router(eventstream.router)
app.include_router(flights.router)
app.include_router(mapzones.router)
app.include_router(navmesh.router)
app.include_router(supplyroutes.router)
app.include_router(tgos.router)
app.include_router(waypoints.router)

View File

@@ -0,0 +1 @@
from .routes import router

View File

@@ -0,0 +1,83 @@
from __future__ import annotations
from typing import Any, TYPE_CHECKING
from dcs import Point
from pydantic import BaseModel
from game.server.leaflet import LeafletPoint
if TYPE_CHECKING:
from game import Game
from game.theater import ControlPoint
from game.transfers import MultiGroupTransport, TransportMap
class TransportFinder:
def __init__(
self, game: Game, control_point_a: ControlPoint, control_point_b: ControlPoint
) -> None:
self.game = game
self.control_point_a = control_point_a
self.control_point_b = control_point_b
def find_in_transport_map(
self, transport_map: TransportMap[Any]
) -> list[MultiGroupTransport]:
transports = []
transport = transport_map.find_transport(
self.control_point_a, self.control_point_b
)
if transport is not None:
transports.append(transport)
transport = transport_map.find_transport(
self.control_point_b, self.control_point_a
)
if transport is not None:
transports.append(transport)
return transports
def find_transports(self, sea_route: bool) -> list[MultiGroupTransport]:
if sea_route:
return self.find_in_transport_map(
self.game.blue.transfers.cargo_ships
) + self.find_in_transport_map(self.game.red.transfers.cargo_ships)
return self.find_in_transport_map(
self.game.blue.transfers.convoys
) + self.find_in_transport_map(self.game.red.transfers.convoys)
def describe_active_transports(self, sea_route: bool) -> list[str]:
transports = self.find_transports(sea_route)
if not transports:
return []
descriptions = []
for transport in transports:
units = "units" if transport.size > 1 else "unit"
descriptions.append(
f"{transport.size} {units} transferring from {transport.origin} to "
f"{transport.destination}"
)
return descriptions
class SupplyRouteJs(BaseModel):
points: list[LeafletPoint]
front_active: bool
is_sea: bool
blue: bool
active_transports: list[str]
@staticmethod
def for_link(
game: Game, a: ControlPoint, b: ControlPoint, points: list[Point], sea: bool
) -> SupplyRouteJs:
return SupplyRouteJs(
points=[p.latlng() for p in points],
front_active=not sea and a.front_is_active(b),
is_sea=sea,
blue=a.captured,
active_transports=TransportFinder(game, a, b).describe_active_transports(
sea
),
)

View File

@@ -0,0 +1,34 @@
from fastapi import APIRouter, Depends
from game import Game
from .models import SupplyRouteJs
from ..dependencies import GameContext
router: APIRouter = APIRouter(prefix="/supply-routes")
@router.get("/")
def list_supply_routes(game: Game = Depends(GameContext.get)) -> list[SupplyRouteJs]:
seen = set()
routes = []
for control_point in game.theater.controlpoints:
seen.add(control_point)
for destination, route in control_point.convoy_routes.items():
if destination in seen:
continue
routes.append(
SupplyRouteJs.for_link(
game, control_point, destination, list(route), sea=False
)
)
for destination, route in control_point.shipping_lanes.items():
if destination in seen:
continue
if not destination.is_friendly_to(control_point):
continue
routes.append(
SupplyRouteJs.for_link(
game, control_point, destination, list(route), sea=True
)
)
return routes