mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Fix NotImplementedError for some flight plans.
Implement custom behavior for some of the flight plans but also add a base implementation that just returns the empty set. Use ABC for FlightPlan so that we can fail-fast on these kinds of problems. Fixes https://github.com/dcs-liberation/dcs_liberation/issues/1711
This commit is contained in:
parent
de0b267568
commit
1944a172a3
@ -10,6 +10,7 @@ from __future__ import annotations
|
|||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
import random
|
import random
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
@ -75,7 +76,7 @@ class InvalidObjectiveLocation(PlanningError):
|
|||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class FlightPlan:
|
class FlightPlan(ABC):
|
||||||
package: Package
|
package: Package
|
||||||
flight: Flight
|
flight: Flight
|
||||||
|
|
||||||
@ -84,9 +85,10 @@ class FlightPlan:
|
|||||||
"""A list of all waypoints in the flight plan, in order."""
|
"""A list of all waypoints in the flight plan, in order."""
|
||||||
return list(self.iter_waypoints())
|
return list(self.iter_waypoints())
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||||
"""Iterates over all waypoints in the flight plan, in order."""
|
"""Iterates over all waypoints in the flight plan, in order."""
|
||||||
raise NotImplementedError
|
...
|
||||||
|
|
||||||
def edges(
|
def edges(
|
||||||
self, until: Optional[FlightWaypoint] = None
|
self, until: Optional[FlightWaypoint] = None
|
||||||
@ -128,7 +130,7 @@ class FlightPlan:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def combat_speed_waypoints(self) -> set[FlightWaypoint]:
|
def combat_speed_waypoints(self) -> set[FlightWaypoint]:
|
||||||
raise NotImplementedError
|
return set()
|
||||||
|
|
||||||
def fuel_consumption_between_points(
|
def fuel_consumption_between_points(
|
||||||
self, a: FlightWaypoint, b: FlightWaypoint
|
self, a: FlightWaypoint, b: FlightWaypoint
|
||||||
@ -151,6 +153,7 @@ class FlightPlan:
|
|||||||
return self.flight.unit_type.fuel_consumption.cruise
|
return self.flight.unit_type.fuel_consumption.cruise
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@abstractmethod
|
||||||
def tot_waypoint(self) -> Optional[FlightWaypoint]:
|
def tot_waypoint(self) -> Optional[FlightWaypoint]:
|
||||||
"""The waypoint that is associated with the package TOT, or None.
|
"""The waypoint that is associated with the package TOT, or None.
|
||||||
|
|
||||||
@ -158,7 +161,7 @@ class FlightPlan:
|
|||||||
user-planned missions without any useful waypoints and flight plans that
|
user-planned missions without any useful waypoints and flight plans that
|
||||||
failed to generate. Nevertheless, we have to defend against it.
|
failed to generate. Nevertheless, we have to defend against it.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tot(self) -> timedelta:
|
def tot(self) -> timedelta:
|
||||||
@ -236,11 +239,13 @@ class FlightPlan:
|
|||||||
a.position, b.position, self.speed_between_waypoints(a, b)
|
a.position, b.position, self.speed_between_waypoints(a, b)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> Optional[timedelta]:
|
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> Optional[timedelta]:
|
||||||
raise NotImplementedError
|
...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
def depart_time_for_waypoint(self, waypoint: FlightWaypoint) -> Optional[timedelta]:
|
def depart_time_for_waypoint(self, waypoint: FlightWaypoint) -> Optional[timedelta]:
|
||||||
raise NotImplementedError
|
...
|
||||||
|
|
||||||
def request_escort_at(self) -> Optional[FlightWaypoint]:
|
def request_escort_at(self) -> Optional[FlightWaypoint]:
|
||||||
return None
|
return None
|
||||||
@ -316,9 +321,10 @@ class FlightPlan:
|
|||||||
return timedelta(minutes=8)
|
return timedelta(minutes=8)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@abstractmethod
|
||||||
def mission_departure_time(self) -> timedelta:
|
def mission_departure_time(self) -> timedelta:
|
||||||
"""The time that the mission is complete and the flight RTBs."""
|
"""The time that the mission is complete and the flight RTBs."""
|
||||||
raise NotImplementedError
|
...
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
@ -326,19 +332,23 @@ class LoiterFlightPlan(FlightPlan):
|
|||||||
hold: FlightWaypoint
|
hold: FlightWaypoint
|
||||||
hold_duration: timedelta
|
hold_duration: timedelta
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||||
raise NotImplementedError
|
...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@abstractmethod
|
||||||
def tot_waypoint(self) -> Optional[FlightWaypoint]:
|
def tot_waypoint(self) -> Optional[FlightWaypoint]:
|
||||||
raise NotImplementedError
|
...
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> Optional[timedelta]:
|
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> Optional[timedelta]:
|
||||||
raise NotImplementedError
|
...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@abstractmethod
|
||||||
def push_time(self) -> timedelta:
|
def push_time(self) -> timedelta:
|
||||||
raise NotImplementedError
|
...
|
||||||
|
|
||||||
def depart_time_for_waypoint(self, waypoint: FlightWaypoint) -> Optional[timedelta]:
|
def depart_time_for_waypoint(self, waypoint: FlightWaypoint) -> Optional[timedelta]:
|
||||||
if waypoint == self.hold:
|
if waypoint == self.hold:
|
||||||
@ -354,8 +364,9 @@ class LoiterFlightPlan(FlightPlan):
|
|||||||
return travel_time + self.hold_duration
|
return travel_time + self.hold_duration
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@abstractmethod
|
||||||
def mission_departure_time(self) -> timedelta:
|
def mission_departure_time(self) -> timedelta:
|
||||||
raise NotImplementedError
|
...
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
@ -363,20 +374,23 @@ class FormationFlightPlan(LoiterFlightPlan):
|
|||||||
join: FlightWaypoint
|
join: FlightWaypoint
|
||||||
split: FlightWaypoint
|
split: FlightWaypoint
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||||
raise NotImplementedError
|
...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@abstractmethod
|
||||||
def package_speed_waypoints(self) -> set[FlightWaypoint]:
|
def package_speed_waypoints(self) -> set[FlightWaypoint]:
|
||||||
raise NotImplementedError
|
...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def combat_speed_waypoints(self) -> set[FlightWaypoint]:
|
def combat_speed_waypoints(self) -> set[FlightWaypoint]:
|
||||||
return self.package_speed_waypoints
|
return self.package_speed_waypoints
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@abstractmethod
|
||||||
def tot_waypoint(self) -> Optional[FlightWaypoint]:
|
def tot_waypoint(self) -> Optional[FlightWaypoint]:
|
||||||
raise NotImplementedError
|
...
|
||||||
|
|
||||||
def request_escort_at(self) -> Optional[FlightWaypoint]:
|
def request_escort_at(self) -> Optional[FlightWaypoint]:
|
||||||
return self.join
|
return self.join
|
||||||
@ -415,12 +429,14 @@ class FormationFlightPlan(LoiterFlightPlan):
|
|||||||
return self._travel_time_to_waypoint(self.join)
|
return self._travel_time_to_waypoint(self.join)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@abstractmethod
|
||||||
def join_time(self) -> timedelta:
|
def join_time(self) -> timedelta:
|
||||||
raise NotImplementedError
|
...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@abstractmethod
|
||||||
def split_time(self) -> timedelta:
|
def split_time(self) -> timedelta:
|
||||||
raise NotImplementedError
|
...
|
||||||
|
|
||||||
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> Optional[timedelta]:
|
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> Optional[timedelta]:
|
||||||
if waypoint == self.join:
|
if waypoint == self.join:
|
||||||
@ -482,8 +498,9 @@ class PatrollingFlightPlan(FlightPlan):
|
|||||||
return self.patrol_end_time
|
return self.patrol_end_time
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
def iter_waypoints(self) -> Iterator[FlightWaypoint]:
|
||||||
raise NotImplementedError
|
...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def package_speed_waypoints(self) -> Set[FlightWaypoint]:
|
def package_speed_waypoints(self) -> Set[FlightWaypoint]:
|
||||||
@ -541,6 +558,10 @@ class CasFlightPlan(PatrollingFlightPlan):
|
|||||||
yield self.divert
|
yield self.divert
|
||||||
yield self.bullseye
|
yield self.bullseye
|
||||||
|
|
||||||
|
@property
|
||||||
|
def combat_speed_waypoints(self) -> set[FlightWaypoint]:
|
||||||
|
return {self.patrol_start, self.target, self.patrol_end}
|
||||||
|
|
||||||
def request_escort_at(self) -> Optional[FlightWaypoint]:
|
def request_escort_at(self) -> Optional[FlightWaypoint]:
|
||||||
return self.patrol_start
|
return self.patrol_start
|
||||||
|
|
||||||
@ -569,6 +590,10 @@ class TarCapFlightPlan(PatrollingFlightPlan):
|
|||||||
yield self.divert
|
yield self.divert
|
||||||
yield self.bullseye
|
yield self.bullseye
|
||||||
|
|
||||||
|
@property
|
||||||
|
def combat_speed_waypoints(self) -> set[FlightWaypoint]:
|
||||||
|
return {self.patrol_start, self.patrol_end}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tot_offset(self) -> timedelta:
|
def tot_offset(self) -> timedelta:
|
||||||
return -self.lead_time
|
return -self.lead_time
|
||||||
@ -732,6 +757,10 @@ class SweepFlightPlan(LoiterFlightPlan):
|
|||||||
yield self.divert
|
yield self.divert
|
||||||
yield self.bullseye
|
yield self.bullseye
|
||||||
|
|
||||||
|
@property
|
||||||
|
def combat_speed_waypoints(self) -> set[FlightWaypoint]:
|
||||||
|
return {self.sweep_end}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tot_waypoint(self) -> Optional[FlightWaypoint]:
|
def tot_waypoint(self) -> Optional[FlightWaypoint]:
|
||||||
return self.sweep_end
|
return self.sweep_end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user