mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Make TOT waypoints non-optional for flight plans.
Flights without a meaningful TOT make the code around startup time (and other scheduling behaviors) unnecessarily complicated because they have to handle unpredictable flight plans. We can simplify this by requiring that all flight plans have a waypoint associated with their TOT. For custom flight plans, we can just fall back to the takeoff waypoint. For RTB flight plans (which are only synthetic flight plans injected for aborted flights), we can use the abort point. This also means that all flight plans now have, at the very least, a departure waypoint. Deleting this waypoint is invalid even for custom flights, so that's no a problem.
This commit is contained in:
parent
ad9686947b
commit
07632e2705
@ -8,6 +8,7 @@ from dcs import Point
|
||||
from dcs.planes import C_101CC, C_101EB, Su_33
|
||||
|
||||
from .flightplans.planningerror import PlanningError
|
||||
from .flightplans.waypointbuilder import WaypointBuilder
|
||||
from .flightroster import FlightRoster
|
||||
from .flightstate import FlightState, Navigating, Uninitialized
|
||||
from .flightstate.killed import Killed
|
||||
@ -89,7 +90,11 @@ class Flight(SidcDescribable):
|
||||
from .flightplans.custom import CustomFlightPlan, CustomLayout
|
||||
|
||||
self.flight_plan: FlightPlan[Any] = CustomFlightPlan(
|
||||
self, CustomLayout(custom_waypoints=[])
|
||||
self,
|
||||
CustomLayout(
|
||||
departure=WaypointBuilder(self, self.coalition).takeoff(self.departure),
|
||||
custom_waypoints=[],
|
||||
),
|
||||
)
|
||||
|
||||
def __getstate__(self) -> dict[str, Any]:
|
||||
|
||||
@ -41,7 +41,7 @@ class AirAssaultFlightPlan(StandardFlightPlan[AirAssaultLayout]):
|
||||
return Builder
|
||||
|
||||
@property
|
||||
def tot_waypoint(self) -> FlightWaypoint | None:
|
||||
def tot_waypoint(self) -> FlightWaypoint:
|
||||
return self.layout.drop_off
|
||||
|
||||
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None:
|
||||
|
||||
@ -47,7 +47,7 @@ class AirliftFlightPlan(StandardFlightPlan[AirliftLayout]):
|
||||
return Builder
|
||||
|
||||
@property
|
||||
def tot_waypoint(self) -> FlightWaypoint | None:
|
||||
def tot_waypoint(self) -> FlightWaypoint:
|
||||
return self.layout.drop_off
|
||||
|
||||
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None:
|
||||
|
||||
@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Type
|
||||
|
||||
from .flightplan import FlightPlan, Layout
|
||||
from .ibuilder import IBuilder
|
||||
from .waypointbuilder import WaypointBuilder
|
||||
from ..flightwaypointtype import FlightWaypointType
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -18,6 +19,7 @@ class CustomLayout(Layout):
|
||||
custom_waypoints: list[FlightWaypoint]
|
||||
|
||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||
yield self.departure
|
||||
yield from self.custom_waypoints
|
||||
|
||||
|
||||
@ -27,7 +29,7 @@ class CustomFlightPlan(FlightPlan[CustomLayout]):
|
||||
return Builder
|
||||
|
||||
@property
|
||||
def tot_waypoint(self) -> FlightWaypoint | None:
|
||||
def tot_waypoint(self) -> FlightWaypoint:
|
||||
target_types = (
|
||||
FlightWaypointType.PATROL_TRACK,
|
||||
FlightWaypointType.TARGET_GROUP_LOC,
|
||||
@ -37,7 +39,7 @@ class CustomFlightPlan(FlightPlan[CustomLayout]):
|
||||
for waypoint in self.waypoints:
|
||||
if waypoint in target_types:
|
||||
return waypoint
|
||||
return None
|
||||
return self.layout.departure
|
||||
|
||||
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None:
|
||||
if waypoint == self.tot_waypoint:
|
||||
@ -54,7 +56,8 @@ class CustomFlightPlan(FlightPlan[CustomLayout]):
|
||||
|
||||
class Builder(IBuilder[CustomFlightPlan, CustomLayout]):
|
||||
def layout(self) -> CustomLayout:
|
||||
return CustomLayout([])
|
||||
builder = WaypointBuilder(self.flight, self.coalition)
|
||||
return CustomLayout(builder.takeoff(self.flight.departure), [])
|
||||
|
||||
def build(self) -> CustomFlightPlan:
|
||||
return CustomFlightPlan(self.flight, self.layout())
|
||||
|
||||
@ -34,7 +34,7 @@ class FerryFlightPlan(StandardFlightPlan[FerryLayout]):
|
||||
return Builder
|
||||
|
||||
@property
|
||||
def tot_waypoint(self) -> FlightWaypoint | None:
|
||||
def tot_waypoint(self) -> FlightWaypoint:
|
||||
return self.layout.arrival
|
||||
|
||||
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None:
|
||||
|
||||
@ -10,6 +10,7 @@ from __future__ import annotations
|
||||
import math
|
||||
from abc import ABC
|
||||
from collections.abc import Iterator
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from functools import cached_property
|
||||
from typing import Any, Generic, TYPE_CHECKING, TypeGuard, TypeVar
|
||||
@ -40,7 +41,10 @@ INGRESS_TYPES = {
|
||||
}
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Layout(ABC):
|
||||
departure: FlightWaypoint
|
||||
|
||||
@property
|
||||
def waypoints(self) -> list[FlightWaypoint]:
|
||||
"""A list of all waypoints in the flight plan, in order."""
|
||||
@ -135,7 +139,7 @@ class FlightPlan(ABC, Generic[LayoutT]):
|
||||
return self.flight.unit_type.fuel_consumption.cruise
|
||||
|
||||
@property
|
||||
def tot_waypoint(self) -> FlightWaypoint | None:
|
||||
def tot_waypoint(self) -> FlightWaypoint:
|
||||
"""The waypoint that is associated with the package TOT, or None.
|
||||
|
||||
Note that the only flight plans that should have no target waypoints are
|
||||
@ -246,19 +250,12 @@ class FlightPlan(ABC, Generic[LayoutT]):
|
||||
if waypoint == end:
|
||||
return
|
||||
|
||||
def takeoff_time(self) -> timedelta | None:
|
||||
tot_waypoint = self.tot_waypoint
|
||||
if tot_waypoint is None:
|
||||
return None
|
||||
return self.tot - self._travel_time_to_waypoint(tot_waypoint)
|
||||
def takeoff_time(self) -> timedelta:
|
||||
return self.tot - self._travel_time_to_waypoint(self.tot_waypoint)
|
||||
|
||||
def startup_time(self) -> timedelta | None:
|
||||
takeoff_time = self.takeoff_time()
|
||||
if takeoff_time is None:
|
||||
return None
|
||||
|
||||
start_time: timedelta = (
|
||||
takeoff_time - self.estimate_startup() - self.estimate_ground_ops()
|
||||
self.takeoff_time() - self.estimate_startup() - self.estimate_ground_ops()
|
||||
)
|
||||
|
||||
# In case FP math has given us some barely below zero time, round to
|
||||
|
||||
@ -85,7 +85,7 @@ class PatrollingFlightPlan(StandardFlightPlan[LayoutT], ABC):
|
||||
return {self.layout.patrol_start, self.layout.patrol_end}
|
||||
|
||||
@property
|
||||
def tot_waypoint(self) -> FlightWaypoint | None:
|
||||
def tot_waypoint(self) -> FlightWaypoint:
|
||||
return self.layout.patrol_start
|
||||
|
||||
@property
|
||||
|
||||
@ -40,8 +40,8 @@ class RtbFlightPlan(StandardFlightPlan[RtbLayout]):
|
||||
return 1
|
||||
|
||||
@property
|
||||
def tot_waypoint(self) -> FlightWaypoint | None:
|
||||
return None
|
||||
def tot_waypoint(self) -> FlightWaypoint:
|
||||
return self.layout.abort_location
|
||||
|
||||
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> timedelta | None:
|
||||
return None
|
||||
|
||||
@ -12,7 +12,6 @@ if TYPE_CHECKING:
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class StandardLayout(Layout, ABC):
|
||||
departure: FlightWaypoint
|
||||
arrival: FlightWaypoint
|
||||
divert: FlightWaypoint | None
|
||||
bullseye: FlightWaypoint
|
||||
|
||||
@ -54,7 +54,7 @@ class SweepFlightPlan(LoiterFlightPlan):
|
||||
return {self.layout.sweep_end}
|
||||
|
||||
@property
|
||||
def tot_waypoint(self) -> FlightWaypoint | None:
|
||||
def tot_waypoint(self) -> FlightWaypoint:
|
||||
return self.layout.sweep_end
|
||||
|
||||
@property
|
||||
|
||||
@ -148,7 +148,12 @@ class QFlightWaypointTab(QFrame):
|
||||
if not isinstance(self.flight.flight_plan, CustomFlightPlan):
|
||||
self.flight.flight_plan = CustomFlightPlan(
|
||||
self.flight,
|
||||
CustomLayout(custom_waypoints=self.flight.flight_plan.waypoints),
|
||||
CustomLayout(
|
||||
departure=WaypointBuilder(self.flight, self.coalition).takeoff(
|
||||
self.flight.departure
|
||||
),
|
||||
custom_waypoints=self.flight.flight_plan.waypoints[1:],
|
||||
),
|
||||
)
|
||||
|
||||
def confirm_recreate(self, task: FlightType) -> None:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user