From b1356551c69421d5dfe9b3f3694e29bd5edef105 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Tue, 22 Feb 2022 19:59:29 -0800 Subject: [PATCH] Move threat zones out of MapModel. --- game/coalition.py | 3 +- game/game.py | 4 +- game/server/eventstream/models.py | 2 + game/server/mapzones/models.py | 25 ++++++++- game/server/mapzones/routes.py | 10 +++- game/sim/gameupdateevents.py | 5 ++ qt_ui/widgets/map/model/mapmodel.py | 26 +-------- .../map/model/threatzonecontainerjs.py | 23 -------- qt_ui/widgets/map/model/threatzonesjs.py | 56 ------------------- resources/ui/map/map.js | 50 ++++++----------- 10 files changed, 62 insertions(+), 142 deletions(-) delete mode 100644 qt_ui/widgets/map/model/threatzonecontainerjs.py delete mode 100644 qt_ui/widgets/map/model/threatzonesjs.py diff --git a/game/coalition.py b/game/coalition.py index 52ddfc95..4f3a8051 100644 --- a/game/coalition.py +++ b/game/coalition.py @@ -119,8 +119,9 @@ class Coalition: def adjust_budget(self, amount: float) -> None: self.budget += amount - def compute_threat_zones(self) -> None: + def compute_threat_zones(self, events: GameUpdateEvents) -> None: self._threat_zone = ThreatZones.for_faction(self.game, self.player) + events.update_threat_zones() def compute_nav_meshes(self, events: GameUpdateEvents) -> None: self._navmesh = NavMesh.from_threat_zones( diff --git a/game/game.py b/game/game.py index e2ee6379..4cea586c 100644 --- a/game/game.py +++ b/game/game.py @@ -421,8 +421,8 @@ class Game: return TransitNetworkBuilder(self.theater, player).build() def compute_threat_zones(self, events: GameUpdateEvents) -> None: - self.blue.compute_threat_zones() - self.red.compute_threat_zones() + self.blue.compute_threat_zones(events) + self.red.compute_threat_zones(events) self.blue.compute_nav_meshes(events) self.red.compute_nav_meshes(events) diff --git a/game/server/eventstream/models.py b/game/server/eventstream/models.py index 3db18479..b2aa1d0a 100644 --- a/game/server/eventstream/models.py +++ b/game/server/eventstream/models.py @@ -19,6 +19,7 @@ class GameUpdateEventsJs(BaseModel): updated_combats: list[FrozenCombatJs] = [] navmesh_updates: set[bool] = set() unculled_zones_updated: bool = False + threat_zones_updated: bool = False @classmethod def from_events(cls, events: GameUpdateEvents, game: Game) -> GameUpdateEventsJs: @@ -35,4 +36,5 @@ class GameUpdateEventsJs(BaseModel): ], navmesh_updates=events.navmesh_updates, unculled_zones_updated=events.unculled_zones_updated, + threat_zones_updated=events.threat_zones_updated, ) diff --git a/game/server/mapzones/models.py b/game/server/mapzones/models.py index 44c1b41d..8aef605c 100644 --- a/game/server/mapzones/models.py +++ b/game/server/mapzones/models.py @@ -3,7 +3,9 @@ from __future__ import annotations from dcs.mapping import LatLng from pydantic import BaseModel -from game.server.leaflet import LeafletPoly +from game.server.leaflet import LeafletPoly, ShapelyUtil +from game.theater import ConflictTheater +from game.threatzones import ThreatZones class MapZonesJs(BaseModel): @@ -15,3 +17,24 @@ class MapZonesJs(BaseModel): class UnculledZoneJs(BaseModel): position: LatLng radius: float + + +class ThreatZonesJs(BaseModel): + full: list[LeafletPoly] + aircraft: list[LeafletPoly] + air_defenses: list[LeafletPoly] + radar_sams: list[LeafletPoly] + + @classmethod + def from_zones(cls, zones: ThreatZones, theater: ConflictTheater) -> ThreatZonesJs: + return ThreatZonesJs( + full=ShapelyUtil.polys_to_leaflet(zones.all, theater), + aircraft=ShapelyUtil.polys_to_leaflet(zones.airbases, theater), + air_defenses=ShapelyUtil.polys_to_leaflet(zones.air_defenses, theater), + radar_sams=ShapelyUtil.polys_to_leaflet(zones.radar_sam_threats, theater), + ) + + +class ThreatZoneContainerJs(BaseModel): + blue: ThreatZonesJs + red: ThreatZonesJs diff --git a/game/server/mapzones/routes.py b/game/server/mapzones/routes.py index 96d608b9..fa69b012 100644 --- a/game/server/mapzones/routes.py +++ b/game/server/mapzones/routes.py @@ -2,7 +2,7 @@ from fastapi import APIRouter, Depends, HTTPException, status from game import Game from game.server import GameContext -from .models import MapZonesJs, UnculledZoneJs +from .models import MapZonesJs, ThreatZoneContainerJs, ThreatZonesJs, UnculledZoneJs from ..leaflet import ShapelyUtil router: APIRouter = APIRouter(prefix="/map-zones") @@ -29,3 +29,11 @@ def get_unculled_zones(game: Game = Depends(GameContext.get)) -> list[UnculledZo ) for zone in game.get_culling_zones() ] + + +@router.get("/threats") +def get_threat_zones(game: Game = Depends(GameContext.get)) -> ThreatZoneContainerJs: + return ThreatZoneContainerJs( + blue=ThreatZonesJs.from_zones(game.threat_zone_for(player=True), game.theater), + red=ThreatZonesJs.from_zones(game.threat_zone_for(player=False), game.theater), + ) diff --git a/game/sim/gameupdateevents.py b/game/sim/gameupdateevents.py index 0c7990f5..c0b727de 100644 --- a/game/sim/gameupdateevents.py +++ b/game/sim/gameupdateevents.py @@ -17,6 +17,7 @@ class GameUpdateEvents: self.updated_flights: list[tuple[Flight, Point]] = [] self.navmesh_updates: set[bool] = set() self.unculled_zones_updated: bool = False + self.threat_zones_updated: bool = False @property def empty(self) -> bool: @@ -28,6 +29,7 @@ class GameUpdateEvents: self.updated_flights, self.navmesh_updates, self.unculled_zones_updated, + self.threat_zones_updated, ] ) @@ -48,3 +50,6 @@ class GameUpdateEvents: def update_unculled_zones(self) -> None: self.unculled_zones_updated = True + + def update_threat_zones(self) -> None: + self.threat_zones_updated = True diff --git a/qt_ui/widgets/map/model/mapmodel.py b/qt_ui/widgets/map/model/mapmodel.py index 37c071f0..4f7f9efe 100644 --- a/qt_ui/widgets/map/model/mapmodel.py +++ b/qt_ui/widgets/map/model/mapmodel.py @@ -21,8 +21,6 @@ from .flightjs import FlightJs from .frontlinejs import FrontLineJs from .groundobjectjs import GroundObjectJs from .supplyroutejs import SupplyRouteJs -from .threatzonecontainerjs import ThreatZoneContainerJs -from .threatzonesjs import ThreatZonesJs # **EVERY PROPERTY NEEDS A NOTIFY SIGNAL** @@ -51,7 +49,6 @@ class MapModel(QObject): supplyRoutesChanged = Signal() flightsChanged = Signal() frontLinesChanged = Signal() - threatZonesChanged = Signal() selectedFlightChanged = Signal(str) def __init__(self, game_model: GameModel) -> None: @@ -63,9 +60,7 @@ class MapModel(QObject): self._supply_routes = [] self._flights: dict[tuple[bool, int, int], FlightJs] = {} self._front_lines = [] - self._threat_zones = ThreatZoneContainerJs( - ThreatZonesJs.empty(), ThreatZonesJs.empty() - ) + self._selected_flight_index: Optional[Tuple[int, int]] = None GameUpdateSignal.get_instance().game_loaded.connect(self.on_game_load) @@ -84,9 +79,6 @@ class MapModel(QObject): self._ground_objects = [] self._flights = {} self._front_lines = [] - self._threat_zones = ThreatZoneContainerJs( - ThreatZonesJs.empty(), ThreatZonesJs.empty() - ) self.cleared.emit() def set_package_selection(self, index: int) -> None: @@ -149,7 +141,6 @@ class MapModel(QObject): self.reset_routes() self.reset_atos() self.reset_front_lines() - self.reset_threat_zones() def on_game_load(self, game: Optional[Game]) -> None: if game is not None: @@ -266,21 +257,6 @@ class MapModel(QObject): def frontLines(self) -> List[FrontLineJs]: return self._front_lines - def reset_threat_zones(self) -> None: - self._threat_zones = ThreatZoneContainerJs( - ThreatZonesJs.from_zones( - self.game.threat_zone_for(player=True), self.game.theater - ), - ThreatZonesJs.from_zones( - self.game.threat_zone_for(player=False), self.game.theater - ), - ) - self.threatZonesChanged.emit() - - @Property(ThreatZoneContainerJs, notify=threatZonesChanged) - def threatZones(self) -> ThreatZoneContainerJs: - return self._threat_zones - @property def game(self) -> Game: if self.game_model.game is None: diff --git a/qt_ui/widgets/map/model/threatzonecontainerjs.py b/qt_ui/widgets/map/model/threatzonecontainerjs.py deleted file mode 100644 index 288f5730..00000000 --- a/qt_ui/widgets/map/model/threatzonecontainerjs.py +++ /dev/null @@ -1,23 +0,0 @@ -from __future__ import annotations - -from PySide2.QtCore import Property, QObject, Signal - -from .threatzonesjs import ThreatZonesJs - - -class ThreatZoneContainerJs(QObject): - blueChanged = Signal() - redChanged = Signal() - - def __init__(self, blue: ThreatZonesJs, red: ThreatZonesJs) -> None: - super().__init__() - self._blue = blue - self._red = red - - @Property(ThreatZonesJs, notify=blueChanged) - def blue(self) -> ThreatZonesJs: - return self._blue - - @Property(ThreatZonesJs, notify=redChanged) - def red(self) -> ThreatZonesJs: - return self._red diff --git a/qt_ui/widgets/map/model/threatzonesjs.py b/qt_ui/widgets/map/model/threatzonesjs.py deleted file mode 100644 index a10565f8..00000000 --- a/qt_ui/widgets/map/model/threatzonesjs.py +++ /dev/null @@ -1,56 +0,0 @@ -from __future__ import annotations - -from PySide2.QtCore import Property, QObject, Signal - -from game.server.leaflet import LeafletPoly, ShapelyUtil -from game.theater import ConflictTheater -from game.threatzones import ThreatZones - - -class ThreatZonesJs(QObject): - fullChanged = Signal() - aircraftChanged = Signal() - airDefensesChanged = Signal() - radarSamsChanged = Signal() - - def __init__( - self, - full: list[LeafletPoly], - aircraft: list[LeafletPoly], - air_defenses: list[LeafletPoly], - radar_sams: list[LeafletPoly], - ) -> None: - super().__init__() - self._full = full - self._aircraft = aircraft - self._air_defenses = air_defenses - self._radar_sams = radar_sams - - @Property(list, notify=fullChanged) - def full(self) -> list[LeafletPoly]: - return self._full - - @Property(list, notify=aircraftChanged) - def aircraft(self) -> list[LeafletPoly]: - return self._aircraft - - @Property(list, notify=airDefensesChanged) - def airDefenses(self) -> list[LeafletPoly]: - return self._air_defenses - - @Property(list, notify=radarSamsChanged) - def radarSams(self) -> list[LeafletPoly]: - return self._radar_sams - - @classmethod - def from_zones(cls, zones: ThreatZones, theater: ConflictTheater) -> ThreatZonesJs: - return ThreatZonesJs( - ShapelyUtil.polys_to_leaflet(zones.all, theater), - ShapelyUtil.polys_to_leaflet(zones.airbases, theater), - ShapelyUtil.polys_to_leaflet(zones.air_defenses, theater), - ShapelyUtil.polys_to_leaflet(zones.radar_sam_threats, theater), - ) - - @classmethod - def empty(cls) -> ThreatZonesJs: - return ThreatZonesJs([], [], [], []) diff --git a/resources/ui/map/map.js b/resources/ui/map/map.js index ca208194..ec8f1f2c 100644 --- a/resources/ui/map/map.js +++ b/resources/ui/map/map.js @@ -383,7 +383,6 @@ new QWebChannel(qt.webChannelTransport, function (channel) { game.supplyRoutesChanged.connect(drawSupplyRoutes); game.frontLinesChanged.connect(drawFrontLines); game.flightsChanged.connect(drawAircraft); - game.threatZonesChanged.connect(drawThreatZones); game.mapZonesChanged.connect(drawMapZones); game.selectedFlightChanged.connect(updateSelectedFlight); }); @@ -404,6 +403,9 @@ function handleStreamedEvents(events) { if (events.unculled_zones_updated) { drawUnculledZones(); } + if (events.threat_zones_updated) { + drawThreatZones(); + } } function recenterMap(center) { @@ -1063,39 +1065,21 @@ function drawThreatZones() { redAirDefenseThreatZones.clearLayers(); redRadarSamThreatZones.clearLayers(); - _drawThreatZones(game.threatZones.blue.full, blueFullThreatZones, true); - _drawThreatZones( - game.threatZones.blue.aircraft, - blueAircraftThreatZones, - true - ); - _drawThreatZones( - game.threatZones.blue.airDefenses, - blueAirDefenseThreatZones, - true - ); - _drawThreatZones( - game.threatZones.blue.radarSams, - blueRadarSamThreatZones, - true - ); + getJson("/map-zones/threats").then((threats) => { + _drawThreatZones(threats.blue.full, blueFullThreatZones, true); + _drawThreatZones(threats.blue.aircraft, blueAircraftThreatZones, true); + _drawThreatZones( + threats.blue.air_defenses, + blueAirDefenseThreatZones, + true + ); + _drawThreatZones(threats.blue.radar_sams, blueRadarSamThreatZones, true); - _drawThreatZones(game.threatZones.red.full, redFullThreatZones, false); - _drawThreatZones( - game.threatZones.red.aircraft, - redAircraftThreatZones, - false - ); - _drawThreatZones( - game.threatZones.red.airDefenses, - redAirDefenseThreatZones, - false - ); - _drawThreatZones( - game.threatZones.red.radarSams, - redRadarSamThreatZones, - false - ); + _drawThreatZones(threats.red.full, redFullThreatZones, false); + _drawThreatZones(threats.red.aircraft, redAircraftThreatZones, false); + _drawThreatZones(threats.red.air_defenses, redAirDefenseThreatZones, false); + _drawThreatZones(threats.red.radar_sams, redRadarSamThreatZones, false); + }); } function drawNavmesh(player) {