mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
operation_ids give us better function names when generating the typescript API from the openapi.json. BaseModel.Config.title does the same for type names. Response models (or 204 status codes) need to be explicit or the API will be declared as returning any.
113 lines
3.7 KiB
Python
113 lines
3.7 KiB
Python
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]
|
|
|
|
class Config:
|
|
title = "SupplyRoute"
|
|
|
|
@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
|
|
),
|
|
)
|
|
|
|
@staticmethod
|
|
def all_in_game(game: Game) -> 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
|