mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Replace debug QObject models with Pydantic.
This requires less duplication and paves the way for us replacing QWebChannel with FastAPI, which in turn gets us closer to not needing Qt.
This commit is contained in:
parent
1adafac35f
commit
6ebda41922
@ -1,67 +1,33 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from PySide2.QtCore import Property, QObject, Signal
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from game import Game
|
||||
from game.ato import Flight
|
||||
from game.flightplan import HoldZoneGeometry
|
||||
from .config import ENABLE_EXPENSIVE_DEBUG_TOOLS
|
||||
from .leaflet import LeafletLatLon, LeafletPoly
|
||||
from .leaflet import LeafletPoly
|
||||
from .shapelyutil import ShapelyUtil
|
||||
|
||||
|
||||
class HoldZonesJs(QObject):
|
||||
homeBubbleChanged = Signal()
|
||||
targetBubbleChanged = Signal()
|
||||
joinBubbleChanged = Signal()
|
||||
excludedZonesChanged = Signal()
|
||||
permissibleZonesChanged = Signal()
|
||||
preferredLinesChanged = Signal()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
home_bubble: LeafletPoly,
|
||||
target_bubble: LeafletPoly,
|
||||
join_bubble: LeafletPoly,
|
||||
excluded_zones: list[LeafletPoly],
|
||||
permissible_zones: list[LeafletPoly],
|
||||
preferred_lines: list[list[LeafletLatLon]],
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self._home_bubble = home_bubble
|
||||
self._target_bubble = target_bubble
|
||||
self._join_bubble = join_bubble
|
||||
self._excluded_zones = excluded_zones
|
||||
self._permissible_zones = permissible_zones
|
||||
self._preferred_lines = preferred_lines
|
||||
|
||||
@Property(list, notify=homeBubbleChanged)
|
||||
def homeBubble(self) -> LeafletPoly:
|
||||
return self._home_bubble
|
||||
|
||||
@Property(list, notify=targetBubbleChanged)
|
||||
def targetBubble(self) -> LeafletPoly:
|
||||
return self._target_bubble
|
||||
|
||||
@Property(list, notify=joinBubbleChanged)
|
||||
def joinBubble(self) -> LeafletPoly:
|
||||
return self._join_bubble
|
||||
|
||||
@Property(list, notify=excludedZonesChanged)
|
||||
def excludedZones(self) -> list[LeafletPoly]:
|
||||
return self._excluded_zones
|
||||
|
||||
@Property(list, notify=permissibleZonesChanged)
|
||||
def permissibleZones(self) -> list[LeafletPoly]:
|
||||
return self._permissible_zones
|
||||
|
||||
@Property(list, notify=preferredLinesChanged)
|
||||
def preferredLines(self) -> list[list[LeafletLatLon]]:
|
||||
return self._preferred_lines
|
||||
class HoldZonesJs(BaseModel):
|
||||
home_bubble: LeafletPoly = Field(alias="homeBubble")
|
||||
target_bubble: LeafletPoly = Field(alias="targetBubble")
|
||||
join_bubble: LeafletPoly = Field(alias="joinBubble")
|
||||
excluded_zones: list[LeafletPoly] = Field(alias="excludedZones")
|
||||
permissible_zones: list[LeafletPoly] = Field(alias="permissibleZones")
|
||||
preferred_lines: list[LeafletPoly] = Field(alias="preferredLines")
|
||||
|
||||
@classmethod
|
||||
def empty(cls) -> HoldZonesJs:
|
||||
return HoldZonesJs([], [], [], [], [], [])
|
||||
return HoldZonesJs(
|
||||
homeBubble=[],
|
||||
targetBubble=[],
|
||||
joinBubble=[],
|
||||
excludedZones=[],
|
||||
permissibleZones=[],
|
||||
preferredLines=[],
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def for_flight(cls, flight: Flight, game: Game) -> HoldZonesJs:
|
||||
@ -77,10 +43,18 @@ class HoldZonesJs(QObject):
|
||||
target.position, home.position, ip, join, game.blue, game.theater
|
||||
)
|
||||
return HoldZonesJs(
|
||||
ShapelyUtil.poly_to_leaflet(geometry.home_bubble, game.theater),
|
||||
ShapelyUtil.poly_to_leaflet(geometry.target_bubble, game.theater),
|
||||
ShapelyUtil.poly_to_leaflet(geometry.join_bubble, game.theater),
|
||||
ShapelyUtil.polys_to_leaflet(geometry.excluded_zones, game.theater),
|
||||
ShapelyUtil.polys_to_leaflet(geometry.permissible_zones, game.theater),
|
||||
ShapelyUtil.lines_to_leaflet(geometry.preferred_lines, game.theater),
|
||||
homeBubble=ShapelyUtil.poly_to_leaflet(geometry.home_bubble, game.theater),
|
||||
targetBubble=ShapelyUtil.poly_to_leaflet(
|
||||
geometry.target_bubble, game.theater
|
||||
),
|
||||
joinBubble=ShapelyUtil.poly_to_leaflet(geometry.join_bubble, game.theater),
|
||||
excludedZones=ShapelyUtil.polys_to_leaflet(
|
||||
geometry.excluded_zones, game.theater
|
||||
),
|
||||
permissibleZones=ShapelyUtil.polys_to_leaflet(
|
||||
geometry.permissible_zones, game.theater
|
||||
),
|
||||
preferredLines=ShapelyUtil.lines_to_leaflet(
|
||||
geometry.preferred_lines, game.theater
|
||||
),
|
||||
)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from PySide2.QtCore import Property, QObject, Signal
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from game import Game
|
||||
from game.ato import Flight
|
||||
@ -10,44 +10,15 @@ from .leaflet import LeafletPoly
|
||||
from .shapelyutil import ShapelyUtil
|
||||
|
||||
|
||||
class IpZonesJs(QObject):
|
||||
homeBubbleChanged = Signal()
|
||||
ipBubbleChanged = Signal()
|
||||
permissibleZoneChanged = Signal()
|
||||
safeZonesChanged = Signal()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
home_bubble: LeafletPoly,
|
||||
ip_bubble: LeafletPoly,
|
||||
permissible_zone: LeafletPoly,
|
||||
safe_zones: list[LeafletPoly],
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self._home_bubble = home_bubble
|
||||
self._ip_bubble = ip_bubble
|
||||
self._permissible_zone = permissible_zone
|
||||
self._safe_zones = safe_zones
|
||||
|
||||
@Property(list, notify=homeBubbleChanged)
|
||||
def homeBubble(self) -> LeafletPoly:
|
||||
return self._home_bubble
|
||||
|
||||
@Property(list, notify=ipBubbleChanged)
|
||||
def ipBubble(self) -> LeafletPoly:
|
||||
return self._ip_bubble
|
||||
|
||||
@Property(list, notify=permissibleZoneChanged)
|
||||
def permissibleZone(self) -> LeafletPoly:
|
||||
return self._permissible_zone
|
||||
|
||||
@Property(list, notify=safeZonesChanged)
|
||||
def safeZones(self) -> list[LeafletPoly]:
|
||||
return self._safe_zones
|
||||
class IpZonesJs(BaseModel):
|
||||
home_bubble: LeafletPoly = Field(alias="homeBubble")
|
||||
ipBubble: LeafletPoly = Field(alias="ipBubble")
|
||||
permissibleZone: LeafletPoly = Field(alias="permissibleZone")
|
||||
safeZones: list[LeafletPoly] = Field(alias="safeZones")
|
||||
|
||||
@classmethod
|
||||
def empty(cls) -> IpZonesJs:
|
||||
return IpZonesJs([], [], [], [])
|
||||
return IpZonesJs(homeBubble=[], ipBubble=[], permissibleZone=[], safeZones=[])
|
||||
|
||||
@classmethod
|
||||
def for_flight(cls, flight: Flight, game: Game) -> IpZonesJs:
|
||||
@ -57,8 +28,10 @@ class IpZonesJs(QObject):
|
||||
home = flight.departure
|
||||
geometry = IpZoneGeometry(target.position, home.position, game.blue)
|
||||
return IpZonesJs(
|
||||
ShapelyUtil.poly_to_leaflet(geometry.home_bubble, game.theater),
|
||||
ShapelyUtil.poly_to_leaflet(geometry.ip_bubble, game.theater),
|
||||
ShapelyUtil.poly_to_leaflet(geometry.permissible_zone, game.theater),
|
||||
ShapelyUtil.polys_to_leaflet(geometry.safe_zones, game.theater),
|
||||
homeBubble=ShapelyUtil.poly_to_leaflet(geometry.home_bubble, game.theater),
|
||||
ipBubble=ShapelyUtil.poly_to_leaflet(geometry.ip_bubble, game.theater),
|
||||
permissibleZone=ShapelyUtil.poly_to_leaflet(
|
||||
geometry.permissible_zone, game.theater
|
||||
),
|
||||
safeZones=ShapelyUtil.polys_to_leaflet(geometry.safe_zones, game.theater),
|
||||
)
|
||||
|
||||
@ -1,67 +1,34 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from PySide2.QtCore import Property, QObject, Signal
|
||||
from pydantic import Field
|
||||
from pydantic.main import BaseModel
|
||||
|
||||
from game import Game
|
||||
from game.ato import Flight
|
||||
from game.flightplan import JoinZoneGeometry
|
||||
from .config import ENABLE_EXPENSIVE_DEBUG_TOOLS
|
||||
from .leaflet import LeafletLatLon, LeafletPoly
|
||||
from .leaflet import LeafletPoly
|
||||
from .shapelyutil import ShapelyUtil
|
||||
|
||||
|
||||
class JoinZonesJs(QObject):
|
||||
homeBubbleChanged = Signal()
|
||||
targetBubbleChanged = Signal()
|
||||
ipBubbleChanged = Signal()
|
||||
excludedZonesChanged = Signal()
|
||||
permissibleZonesChanged = Signal()
|
||||
preferredLinesChanged = Signal()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
home_bubble: LeafletPoly,
|
||||
target_bubble: LeafletPoly,
|
||||
ip_bubble: LeafletPoly,
|
||||
excluded_zones: list[LeafletPoly],
|
||||
permissible_zones: list[LeafletPoly],
|
||||
preferred_lines: list[list[LeafletLatLon]],
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self._home_bubble = home_bubble
|
||||
self._target_bubble = target_bubble
|
||||
self._ip_bubble = ip_bubble
|
||||
self._excluded_zones = excluded_zones
|
||||
self._permissible_zones = permissible_zones
|
||||
self._preferred_lines = preferred_lines
|
||||
|
||||
@Property(list, notify=homeBubbleChanged)
|
||||
def homeBubble(self) -> LeafletPoly:
|
||||
return self._home_bubble
|
||||
|
||||
@Property(list, notify=targetBubbleChanged)
|
||||
def targetBubble(self) -> LeafletPoly:
|
||||
return self._target_bubble
|
||||
|
||||
@Property(list, notify=ipBubbleChanged)
|
||||
def ipBubble(self) -> LeafletPoly:
|
||||
return self._ip_bubble
|
||||
|
||||
@Property(list, notify=excludedZonesChanged)
|
||||
def excludedZones(self) -> list[LeafletPoly]:
|
||||
return self._excluded_zones
|
||||
|
||||
@Property(list, notify=permissibleZonesChanged)
|
||||
def permissibleZones(self) -> list[LeafletPoly]:
|
||||
return self._permissible_zones
|
||||
|
||||
@Property(list, notify=preferredLinesChanged)
|
||||
def preferredLines(self) -> list[list[LeafletLatLon]]:
|
||||
return self._preferred_lines
|
||||
class JoinZonesJs(BaseModel):
|
||||
home_bubble: LeafletPoly = Field(alias="homeBubble")
|
||||
target_bubble: LeafletPoly = Field(alias="targetBubble")
|
||||
ip_bubble: LeafletPoly = Field(alias="ipBubble")
|
||||
excluded_zones: list[LeafletPoly] = Field(alias="excludedZones")
|
||||
permissible_zones: list[LeafletPoly] = Field(alias="permissibleZones")
|
||||
preferred_lines: list[LeafletPoly] = Field(alias="preferredLines")
|
||||
|
||||
@classmethod
|
||||
def empty(cls) -> JoinZonesJs:
|
||||
return JoinZonesJs([], [], [], [], [], [])
|
||||
return JoinZonesJs(
|
||||
homeBubble=[],
|
||||
targetBubble=[],
|
||||
ipBubble=[],
|
||||
excludedZones=[],
|
||||
permissibleZones=[],
|
||||
preferredLines=[],
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def for_flight(cls, flight: Flight, game: Game) -> JoinZonesJs:
|
||||
@ -74,10 +41,18 @@ class JoinZonesJs(QObject):
|
||||
ip = flight.package.waypoints.ingress
|
||||
geometry = JoinZoneGeometry(target.position, home.position, ip, game.blue)
|
||||
return JoinZonesJs(
|
||||
ShapelyUtil.poly_to_leaflet(geometry.home_bubble, game.theater),
|
||||
ShapelyUtil.poly_to_leaflet(geometry.target_bubble, game.theater),
|
||||
ShapelyUtil.poly_to_leaflet(geometry.ip_bubble, game.theater),
|
||||
ShapelyUtil.polys_to_leaflet(geometry.excluded_zones, game.theater),
|
||||
ShapelyUtil.polys_to_leaflet(geometry.permissible_zones, game.theater),
|
||||
ShapelyUtil.lines_to_leaflet(geometry.preferred_lines, game.theater),
|
||||
homeBubble=ShapelyUtil.poly_to_leaflet(geometry.home_bubble, game.theater),
|
||||
targetBubble=ShapelyUtil.poly_to_leaflet(
|
||||
geometry.target_bubble, game.theater
|
||||
),
|
||||
ipBubble=ShapelyUtil.poly_to_leaflet(geometry.ip_bubble, game.theater),
|
||||
excludedZones=ShapelyUtil.polys_to_leaflet(
|
||||
geometry.excluded_zones, game.theater
|
||||
),
|
||||
permissibleZones=ShapelyUtil.polys_to_leaflet(
|
||||
geometry.permissible_zones, game.theater
|
||||
),
|
||||
preferredLines=ShapelyUtil.lines_to_leaflet(
|
||||
geometry.preferred_lines, game.theater
|
||||
),
|
||||
)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
@ -396,17 +397,19 @@ class MapModel(QObject):
|
||||
def unculledZones(self) -> list[UnculledZone]:
|
||||
return self._unculled_zones
|
||||
|
||||
@Property(IpZonesJs, notify=ipZonesChanged)
|
||||
def ipZones(self) -> IpZonesJs:
|
||||
return self._ip_zones
|
||||
@Property(str, notify=ipZonesChanged)
|
||||
def ipZones(self) -> str:
|
||||
return json.dumps(self._ip_zones.dict(by_alias=True))
|
||||
|
||||
@Property(JoinZonesJs, notify=joinZonesChanged)
|
||||
def joinZones(self) -> JoinZonesJs:
|
||||
return self._join_zones
|
||||
@Property(str, notify=joinZonesChanged)
|
||||
def joinZones(self) -> str:
|
||||
# Must be dumped as a string and deserialized in js because QWebChannel can't
|
||||
# handle a dict. Can be cleaned up by switching from QWebChannel to FastAPI.
|
||||
return json.dumps(self._join_zones.dict(by_alias=True))
|
||||
|
||||
@Property(HoldZonesJs, notify=holdZonesChanged)
|
||||
def holdZones(self) -> HoldZonesJs:
|
||||
return self._hold_zones
|
||||
@Property(str, notify=holdZonesChanged)
|
||||
def holdZones(self) -> str:
|
||||
return json.dumps(self._hold_zones.dict(by_alias=True))
|
||||
|
||||
def reset_combats(self) -> None:
|
||||
self._air_combats = []
|
||||
|
||||
@ -25,6 +25,7 @@ platformdirs==2.5.0
|
||||
pluggy==1.0.0
|
||||
pre-commit==2.17.0
|
||||
py==1.11.0
|
||||
pydantic==1.9.0
|
||||
-e git+https://github.com/pydcs/dcs@63863a88e0a43cb0a310dbab3ce2c7800a099dbb#egg=pydcs
|
||||
pyinstaller==4.9
|
||||
pyinstaller-hooks-contrib==2022.1
|
||||
|
||||
@ -1106,25 +1106,27 @@ function drawIpZones() {
|
||||
return;
|
||||
}
|
||||
|
||||
L.polygon(game.ipZones.homeBubble, {
|
||||
const iz = JSON.parse(game.ipZones);
|
||||
|
||||
L.polygon(iz.homeBubble, {
|
||||
color: Colors.Highlight,
|
||||
fillOpacity: 0.1,
|
||||
interactive: false,
|
||||
}).addTo(ipZones);
|
||||
|
||||
L.polygon(game.ipZones.ipBubble, {
|
||||
L.polygon(iz.ipBubble, {
|
||||
color: "#bb89ff",
|
||||
fillOpacity: 0.1,
|
||||
interactive: false,
|
||||
}).addTo(ipZones);
|
||||
|
||||
L.polygon(game.ipZones.permissibleZone, {
|
||||
L.polygon(iz.permissibleZone, {
|
||||
color: "#ffffff",
|
||||
fillOpacity: 0.1,
|
||||
interactive: false,
|
||||
}).addTo(ipZones);
|
||||
|
||||
for (const zone of game.ipZones.safeZones) {
|
||||
for (const zone of iz.safeZones) {
|
||||
L.polygon(zone, {
|
||||
color: Colors.Green,
|
||||
fillOpacity: 0.1,
|
||||
@ -1140,25 +1142,27 @@ function drawJoinZones() {
|
||||
return;
|
||||
}
|
||||
|
||||
L.polygon(game.joinZones.homeBubble, {
|
||||
const jz = JSON.parse(game.joinZones);
|
||||
|
||||
L.polygon(jz.homeBubble, {
|
||||
color: Colors.Highlight,
|
||||
fillOpacity: 0.1,
|
||||
interactive: false,
|
||||
}).addTo(joinZones);
|
||||
|
||||
L.polygon(game.joinZones.targetBubble, {
|
||||
L.polygon(jz.targetBubble, {
|
||||
color: "#bb89ff",
|
||||
fillOpacity: 0.1,
|
||||
interactive: false,
|
||||
}).addTo(joinZones);
|
||||
|
||||
L.polygon(game.joinZones.ipBubble, {
|
||||
L.polygon(jz.ipBubble, {
|
||||
color: "#ffffff",
|
||||
fillOpacity: 0.1,
|
||||
interactive: false,
|
||||
}).addTo(joinZones);
|
||||
|
||||
for (const zone of game.joinZones.excludedZones) {
|
||||
for (const zone of jz.excludedZones) {
|
||||
L.polygon(zone, {
|
||||
color: "#ffa500",
|
||||
fillOpacity: 0.2,
|
||||
@ -1167,14 +1171,14 @@ function drawJoinZones() {
|
||||
}).addTo(joinZones);
|
||||
}
|
||||
|
||||
for (const zone of game.joinZones.permissibleZones) {
|
||||
for (const zone of jz.permissibleZones) {
|
||||
L.polygon(zone, {
|
||||
color: Colors.Green,
|
||||
interactive: false,
|
||||
}).addTo(joinZones);
|
||||
}
|
||||
|
||||
for (const line of game.joinZones.preferredLines) {
|
||||
for (const line of jz.preferredLines) {
|
||||
L.polyline(line, {
|
||||
color: Colors.Green,
|
||||
interactive: false,
|
||||
@ -1189,25 +1193,27 @@ function drawHoldZones() {
|
||||
return;
|
||||
}
|
||||
|
||||
L.polygon(game.holdZones.homeBubble, {
|
||||
const hz = JSON.parse(game.holdZones);
|
||||
|
||||
L.polygon(hz.homeBubble, {
|
||||
color: Colors.Highlight,
|
||||
fillOpacity: 0.1,
|
||||
interactive: false,
|
||||
}).addTo(holdZones);
|
||||
|
||||
L.polygon(game.holdZones.targetBubble, {
|
||||
L.polygon(hz.targetBubble, {
|
||||
color: Colors.Highlight,
|
||||
fillOpacity: 0.1,
|
||||
interactive: false,
|
||||
}).addTo(holdZones);
|
||||
|
||||
L.polygon(game.holdZones.joinBubble, {
|
||||
L.polygon(hz.joinBubble, {
|
||||
color: Colors.Highlight,
|
||||
fillOpacity: 0.1,
|
||||
interactive: false,
|
||||
}).addTo(holdZones);
|
||||
|
||||
for (const zone of game.holdZones.excludedZones) {
|
||||
for (const zone of hz.excludedZones) {
|
||||
L.polygon(zone, {
|
||||
color: "#ffa500",
|
||||
fillOpacity: 0.2,
|
||||
@ -1216,14 +1222,14 @@ function drawHoldZones() {
|
||||
}).addTo(holdZones);
|
||||
}
|
||||
|
||||
for (const zone of game.holdZones.permissibleZones) {
|
||||
for (const zone of hz.permissibleZones) {
|
||||
L.polygon(zone, {
|
||||
color: Colors.Green,
|
||||
interactive: false,
|
||||
}).addTo(holdZones);
|
||||
}
|
||||
|
||||
for (const line of game.holdZones.preferredLines) {
|
||||
for (const line of hz.preferredLines) {
|
||||
L.polyline(line, {
|
||||
color: Colors.Green,
|
||||
interactive: false,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user