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
This commit is contained in:
Dan Albert 2020-11-01 13:09:33 -08:00
parent ab67a38ca5
commit 5ba633c8a1
2 changed files with 42 additions and 22 deletions

View File

@ -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)

View File

@ -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.