mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Un-pydantic FlightWaypoint.
Apparently it's a bad idea to try to make the core data pydantic models, and those should really be treated more as a view-model. Doing otherwise causes odd patterns (like the UI info I had leaked into the core type), and makes it harder to interop with third-party types.
This commit is contained in:
73
game/server/waypoints/models.py
Normal file
73
game/server/waypoints/models.py
Normal file
@@ -0,0 +1,73 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
|
||||
from game.ato import FlightWaypoint
|
||||
from game.ato.flightwaypointtype import FlightWaypointType
|
||||
from game.theater import ConflictTheater, LatLon
|
||||
|
||||
|
||||
@dataclass
|
||||
class FlightWaypointJs:
|
||||
name: str
|
||||
position: LatLon
|
||||
altitude_ft: float
|
||||
altitude_reference: str
|
||||
is_movable: bool
|
||||
should_mark: bool
|
||||
include_in_path: bool
|
||||
|
||||
@staticmethod
|
||||
def for_waypoint(
|
||||
waypoint: FlightWaypoint, theater: ConflictTheater
|
||||
) -> FlightWaypointJs:
|
||||
# Target *points* are the exact location of a unit, whereas the target area is
|
||||
# only the center of the objective. Allow moving the latter since its exact
|
||||
# location isn't very important.
|
||||
#
|
||||
# Landing, and divert should be changed in the flight settings UI, takeoff
|
||||
# cannot be changed because that's where the plane is.
|
||||
#
|
||||
# Moving the bullseye reference only makes it wrong.
|
||||
is_movable = waypoint.waypoint_type not in {
|
||||
FlightWaypointType.BULLSEYE,
|
||||
FlightWaypointType.DIVERT,
|
||||
FlightWaypointType.LANDING_POINT,
|
||||
FlightWaypointType.TAKEOFF,
|
||||
FlightWaypointType.TARGET_POINT,
|
||||
}
|
||||
|
||||
# We don't need a marker for the departure waypoint (and it's likely
|
||||
# coincident with the landing waypoint, so hard to see). We do want to draw
|
||||
# the path from it though.
|
||||
#
|
||||
# We also don't need the landing waypoint since we'll be drawing that path
|
||||
# as well, and it's clear what it is, and only obscured the CP icon.
|
||||
#
|
||||
# The divert waypoint also obscures the CP. We don't draw the path to it,
|
||||
# but it can be seen in the flight settings page, so it's not really a
|
||||
# problem to exclude it.
|
||||
#
|
||||
# Bullseye ought to be (but currently isn't) drawn *once* rather than as a
|
||||
# flight waypoint.
|
||||
should_mark = waypoint.waypoint_type not in {
|
||||
FlightWaypointType.BULLSEYE,
|
||||
FlightWaypointType.DIVERT,
|
||||
FlightWaypointType.LANDING_POINT,
|
||||
FlightWaypointType.TAKEOFF,
|
||||
}
|
||||
|
||||
include_in_path = waypoint.waypoint_type not in {
|
||||
FlightWaypointType.BULLSEYE,
|
||||
FlightWaypointType.DIVERT,
|
||||
}
|
||||
|
||||
return FlightWaypointJs(
|
||||
name=waypoint.name,
|
||||
position=theater.point_to_ll(waypoint.position),
|
||||
altitude_ft=waypoint.alt.feet,
|
||||
altitude_reference=waypoint.alt_type,
|
||||
is_movable=is_movable,
|
||||
should_mark=should_mark,
|
||||
include_in_path=include_in_path,
|
||||
)
|
||||
@@ -4,31 +4,36 @@ from uuid import UUID
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
|
||||
from game import Game
|
||||
from game.ato.flightwaypoint import BaseFlightWaypoint, FlightWaypoint
|
||||
from game.ato.flightwaypoint import FlightWaypoint
|
||||
from game.ato.flightwaypointtype import FlightWaypointType
|
||||
from game.server import GameContext
|
||||
from game.server.waypoints.models import FlightWaypointJs
|
||||
from game.theater import LatLon
|
||||
from game.utils import meters
|
||||
|
||||
router: APIRouter = APIRouter(prefix="/waypoints")
|
||||
|
||||
|
||||
@router.get("/{flight_id}", response_model=list[BaseFlightWaypoint])
|
||||
@router.get("/{flight_id}", response_model=list[FlightWaypointJs])
|
||||
def all_waypoints_for_flight(
|
||||
flight_id: UUID, game: Game = Depends(GameContext.get)
|
||||
) -> list[FlightWaypoint]:
|
||||
) -> list[FlightWaypointJs]:
|
||||
flight = game.db.flights.get(flight_id)
|
||||
departure = FlightWaypoint(
|
||||
FlightWaypointType.TAKEOFF,
|
||||
flight.departure.position.x,
|
||||
flight.departure.position.y,
|
||||
meters(0),
|
||||
departure = FlightWaypointJs.for_waypoint(
|
||||
FlightWaypoint(
|
||||
"TAKEOFF",
|
||||
FlightWaypointType.TAKEOFF,
|
||||
flight.departure.position.x,
|
||||
flight.departure.position.y,
|
||||
meters(0),
|
||||
"RADIO",
|
||||
),
|
||||
game.theater,
|
||||
)
|
||||
departure.alt_type = "RADIO"
|
||||
points = [departure] + flight.flight_plan.waypoints
|
||||
for point in points:
|
||||
point.update_latlng(game.theater)
|
||||
return points
|
||||
return [departure] + [
|
||||
FlightWaypointJs.for_waypoint(w, game.theater)
|
||||
for w in flight.flight_plan.waypoints
|
||||
]
|
||||
|
||||
|
||||
@router.post("/{flight_id}/{waypoint_idx}/position")
|
||||
@@ -43,9 +48,6 @@ def set_position(
|
||||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
|
||||
|
||||
waypoint = flight.flight_plan.waypoints[waypoint_idx - 1]
|
||||
if not waypoint.is_movable:
|
||||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
|
||||
|
||||
point = game.theater.ll_to_point(position)
|
||||
waypoint.x = point.x
|
||||
waypoint.y = point.y
|
||||
|
||||
Reference in New Issue
Block a user