From 5ba633c8a1340a91a2e698b522f9215fa734b8a6 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Sun, 1 Nov 2020 13:09:33 -0800 Subject: [PATCH] Round TOT/start time as needed. The increased precision that we had everywhere except the UI and the interface with DCS was causing issues with ASAP creating barely negative start times. The main cause of this was that we'd compute the earliest possible TOT, it would result in, for example, 23:10.002. When we then set the QTimeEdit for the TOT, we have to round because it does not support (nor do we really want to display) sub-second values, which then caused the previously 0 start time to be -0.002. Instead, since the sub-second values aren't really interesting anyway, we now just round TOTs up and start times down. This should prevent negative start times from occurring (except when they've been manually planned as such), and also prevents start times of 00:00:01. Also rounds the package waypoint times to avoid the same issues, but it's not really important which direction we round these. Fixes https://github.com/Khopa/dcs_liberation/issues/295 --- gen/flights/flightplan.py | 43 +++++++++++++++++++++------------------ gen/flights/traveltime.py | 21 +++++++++++++++++-- 2 files changed, 42 insertions(+), 22 deletions(-) diff --git a/gen/flights/flightplan.py b/gen/flights/flightplan.py index bbc954d8..a8cccf9a 100644 --- a/gen/flights/flightplan.py +++ b/gen/flights/flightplan.py @@ -7,6 +7,7 @@ generating the waypoints for the mission. """ from __future__ import annotations +import math from datetime import timedelta from functools import cached_property import logging @@ -93,29 +94,31 @@ class PackageWaypointTiming: if group_ground_speed is None: return None - ingress = package.time_over_target - TravelTime.between_points( - package.waypoints.ingress, - package.target.position, - group_ground_speed - ) + # Round each waypoint TOT since DCS doesn't support sub-second timing + # and it's not interesting to the user. + ingress = timedelta(seconds=math.floor( + (package.time_over_target - TravelTime.between_points( + package.waypoints.ingress, + package.target.position, + group_ground_speed)).total_seconds())) - join = ingress - TravelTime.between_points( - package.waypoints.join, - package.waypoints.ingress, - group_ground_speed - ) + join = timedelta(seconds=math.floor( + (ingress - TravelTime.between_points( + package.waypoints.join, + package.waypoints.ingress, + group_ground_speed)).total_seconds())) - egress = package.time_over_target + TravelTime.between_points( - package.target.position, - package.waypoints.egress, - group_ground_speed - ) + egress = timedelta(seconds=math.floor( + (package.time_over_target + TravelTime.between_points( + package.target.position, + package.waypoints.egress, + group_ground_speed)).total_seconds())) - split = egress + TravelTime.between_points( - package.waypoints.egress, - package.waypoints.split, - group_ground_speed - ) + split = timedelta(seconds=math.floor( + (egress + TravelTime.between_points( + package.waypoints.egress, + package.waypoints.split, + group_ground_speed)).total_seconds())) return cls(package, join, ingress, egress, split) diff --git a/gen/flights/traveltime.py b/gen/flights/traveltime.py index 644e9851..ee9a6c7e 100644 --- a/gen/flights/traveltime.py +++ b/gen/flights/traveltime.py @@ -98,7 +98,17 @@ class TotEstimator: takeoff_time = self.takeoff_time_for_flight(flight) startup_time = self.estimate_startup(flight) ground_ops_time = self.estimate_ground_ops(flight) - return takeoff_time - startup_time - ground_ops_time + start_time = takeoff_time - startup_time - ground_ops_time + # In case FP math has given us some barely below zero time, round to + # zero. + if math.isclose(start_time.total_seconds(), 0): + return timedelta() + # Trim microseconds. DCS doesn't handle sub-second resolution for tasks, + # and they're not interesting from a mission planning perspective so we + # don't want them in the UI. + # + # Round down so *barely* above zero start times are just zero. + return timedelta(seconds=math.floor(start_time.total_seconds())) def takeoff_time_for_flight(self, flight: Flight) -> timedelta: travel_time = self.travel_time_to_rendezvous_or_target(flight) @@ -122,10 +132,17 @@ class TotEstimator: return tot - travel_time - self.HOLD_TIME def earliest_tot(self) -> timedelta: - return max(( + earliest_tot = max(( self.earliest_tot_for_flight(f) for f in self.package.flights )) + self.HOLD_TIME + # Trim microseconds. DCS doesn't handle sub-second resolution for tasks, + # and they're not interesting from a mission planning perspective so we + # don't want them in the UI. + # + # Round up so we don't get negative start times. + return timedelta(seconds=math.ceil(earliest_tot.total_seconds())) + def earliest_tot_for_flight(self, flight: Flight) -> timedelta: """Estimate fastest time from mission start to the target position.