From 59756ce14c5dd4f598cac03af8fbe5afdde39b6a Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Sun, 13 Aug 2023 11:16:14 -0700 Subject: [PATCH] Differentiate total time and travel time. There's an ugly special case in flight simulation to handle hold points because we don't differentiate between the total time between two waypoints (which can include delays from actions like holding) and travel time. Split those up and remove the special case. --- game/ato/flightplans/flightplan.py | 12 +++++++++++- game/ato/flightplans/formationattack.py | 8 ++++---- game/ato/flightplans/loiter.py | 4 ++-- game/ato/flightplans/packagerefueling.py | 4 ++-- game/ato/flightplans/sweep.py | 2 +- game/ato/flightstate/inflight.py | 10 +--------- 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/game/ato/flightplans/flightplan.py b/game/ato/flightplans/flightplan.py index 5135601b..c14d66ff 100644 --- a/game/ato/flightplans/flightplan.py +++ b/game/ato/flightplans/flightplan.py @@ -214,7 +214,7 @@ class FlightPlan(ABC, Generic[LayoutT]): ) for previous_waypoint, waypoint in self.edges(until=destination): - total += self.travel_time_between_waypoints(previous_waypoint, waypoint) + total += self.total_time_between_waypoints(previous_waypoint, waypoint) # Trim microseconds. Our simulation tick rate is 1 second, so anything that # takes 100.1 or 100.9 seconds will take 100 seconds. DCS doesn't handle @@ -223,6 +223,16 @@ class FlightPlan(ABC, Generic[LayoutT]): # model. return timedelta(seconds=math.floor(total.total_seconds())) + def total_time_between_waypoints( + self, a: FlightWaypoint, b: FlightWaypoint + ) -> timedelta: + """Returns the total time spent between a and b. + + The total time between waypoints differs from the travel time in that it may + include additional time for actions such as loitering. + """ + return self.travel_time_between_waypoints(a, b) + def travel_time_between_waypoints( self, a: FlightWaypoint, b: FlightWaypoint ) -> timedelta: diff --git a/game/ato/flightplans/formationattack.py b/game/ato/flightplans/formationattack.py index e161aa1b..ce20eca7 100644 --- a/game/ato/flightplans/formationattack.py +++ b/game/ato/flightplans/formationattack.py @@ -57,17 +57,17 @@ class FormationAttackFlightPlan(FormationFlightPlan, ABC): @property def join_time(self) -> datetime: - travel_time = self.travel_time_between_waypoints( + travel_time = self.total_time_between_waypoints( self.layout.join, self.layout.ingress ) return self.ingress_time - travel_time @property def split_time(self) -> datetime: - travel_time_ingress = self.travel_time_between_waypoints( + travel_time_ingress = self.total_time_between_waypoints( self.layout.ingress, self.target_area_waypoint ) - travel_time_egress = self.travel_time_between_waypoints( + travel_time_egress = self.total_time_between_waypoints( self.target_area_waypoint, self.layout.split ) minutes_at_target = 0.75 * len(self.layout.targets) @@ -82,7 +82,7 @@ class FormationAttackFlightPlan(FormationFlightPlan, ABC): @property def ingress_time(self) -> datetime: tot = self.tot - travel_time = self.travel_time_between_waypoints( + travel_time = self.total_time_between_waypoints( self.layout.ingress, self.target_area_waypoint ) return tot - travel_time diff --git a/game/ato/flightplans/loiter.py b/game/ato/flightplans/loiter.py index c2201e35..8b5dc108 100644 --- a/game/ato/flightplans/loiter.py +++ b/game/ato/flightplans/loiter.py @@ -33,10 +33,10 @@ class LoiterFlightPlan(StandardFlightPlan[Any], ABC): return self.push_time return None - def travel_time_between_waypoints( + def total_time_between_waypoints( self, a: FlightWaypoint, b: FlightWaypoint ) -> timedelta: - travel_time = super().travel_time_between_waypoints(a, b) + travel_time = super().total_time_between_waypoints(a, b) if a != self.layout.hold: return travel_time return travel_time + self.hold_duration diff --git a/game/ato/flightplans/packagerefueling.py b/game/ato/flightplans/packagerefueling.py index 0e0b4d86..1698f7c7 100644 --- a/game/ato/flightplans/packagerefueling.py +++ b/game/ato/flightplans/packagerefueling.py @@ -59,10 +59,10 @@ class PackageRefuelingFlightPlan(RefuelingFlightPlan): "REFUEL", FlightWaypointType.REFUEL, refuel, altitude ) - delay_target_to_split: timedelta = self.travel_time_between_waypoints( + delay_target_to_split: timedelta = self.total_time_between_waypoints( self.target_area_waypoint(), split_waypoint ) - delay_split_to_refuel: timedelta = self.travel_time_between_waypoints( + delay_split_to_refuel: timedelta = self.total_time_between_waypoints( split_waypoint, refuel_waypoint ) diff --git a/game/ato/flightplans/sweep.py b/game/ato/flightplans/sweep.py index aba95c2d..93bd2c38 100644 --- a/game/ato/flightplans/sweep.py +++ b/game/ato/flightplans/sweep.py @@ -55,7 +55,7 @@ class SweepFlightPlan(LoiterFlightPlan): @property def sweep_start_time(self) -> datetime: - travel_time = self.travel_time_between_waypoints( + travel_time = self.total_time_between_waypoints( self.layout.sweep_start, self.layout.sweep_end ) return self.sweep_end_time - travel_time diff --git a/game/ato/flightstate/inflight.py b/game/ato/flightstate/inflight.py index c9af70c5..53e4f852 100644 --- a/game/ato/flightstate/inflight.py +++ b/game/ato/flightstate/inflight.py @@ -51,17 +51,9 @@ class InFlight(FlightState, ABC): return index <= self.waypoint_index def travel_time_between_waypoints(self) -> timedelta: - travel_time = self.flight.flight_plan.travel_time_between_waypoints( + return self.flight.flight_plan.travel_time_between_waypoints( self.current_waypoint, self.next_waypoint ) - if self.current_waypoint.waypoint_type is FlightWaypointType.LOITER: - # Loiter time is already built into travel_time_between_waypoints. If we're - # at a loiter point but still a regular InFlight (Loiter overrides this - # method) that means we're traveling from the loiter point but no longer - # loitering. - assert self.flight.flight_plan.is_loiter(self.flight.flight_plan) - travel_time -= self.flight.flight_plan.hold_duration - return travel_time @abstractmethod def estimate_position(self) -> Point: