diff --git a/qt_ui/widgets/QTopPanel.py b/qt_ui/widgets/QTopPanel.py
index 99f0ac9f..fa76910f 100644
--- a/qt_ui/widgets/QTopPanel.py
+++ b/qt_ui/widgets/QTopPanel.py
@@ -1,4 +1,4 @@
-from typing import Optional
+from typing import List, Optional
from PySide2.QtWidgets import (
QFrame,
@@ -11,6 +11,8 @@ from PySide2.QtWidgets import (
import qt_ui.uiconstants as CONST
from game import Game
from game.event import CAP, CAS, FrontlineAttackEvent
+from gen.ato import Package
+from gen.flights.traveltime import TotEstimator
from qt_ui.models import GameModel
from qt_ui.widgets.QBudgetBox import QBudgetBox
from qt_ui.widgets.QFactionsInfos import QFactionsInfos
@@ -117,6 +119,22 @@ class QTopPanel(QFrame):
GameUpdateSignal.get_instance().updateGame(self.game)
self.proceedButton.setEnabled(True)
+ def negative_start_packages(self) -> List[Package]:
+ packages = []
+ for package in self.game_model.ato_model.ato.packages:
+ estimator = TotEstimator(package)
+ for flight in package.flights:
+ if estimator.mission_start_time(flight) < 0:
+ packages.append(package)
+ break
+ return packages
+
+ @staticmethod
+ def fix_tots(packages: List[Package]) -> None:
+ for package in packages:
+ estimator = TotEstimator(package)
+ package.time_over_target = estimator.earliest_tot()
+
def ato_has_clients(self) -> bool:
for package in self.game.blue_ato.packages:
for flight in package.flights:
@@ -142,12 +160,52 @@ class QTopPanel(QFrame):
)
return result == QMessageBox.Yes
+ def confirm_negative_start_time(self,
+ negative_starts: List[Package]) -> bool:
+ formatted = '
'.join(
+ [f"{p.primary_task.name} {p.target.name}" for p in negative_starts]
+ )
+ mbox = QMessageBox(
+ QMessageBox.Question,
+ "Continue with past start times?",
+ ("Some flights in the following packages have start times set "
+ "earlier than mission start time:
"
+ "
"
+ f"{formatted}
"
+ "
"
+ "Flight start times are estimated based on the package TOT, so it "
+ "is possible that not all flights will be able to reach the "
+ "target area at their assigned times.
"
+ "
"
+ "You can either continue with the mission as planned, with the "
+ "misplanned flights potentially flying too fast and/or missing "
+ "their rendezvous; automatically fix negative TOTs; or cancel "
+ "mission start and fix the packages manually."),
+ parent=self
+ )
+ auto = mbox.addButton("Fix TOTs automatically", QMessageBox.ActionRole)
+ ignore = mbox.addButton("Continue without fixing",
+ QMessageBox.DestructiveRole)
+ cancel = mbox.addButton(QMessageBox.Cancel)
+ mbox.setEscapeButton(cancel)
+ mbox.exec_()
+ clicked = mbox.clickedButton()
+ if clicked == auto:
+ self.fix_tots(negative_starts)
+ return True
+ elif clicked == ignore:
+ return True
+ return False
+
def launch_mission(self):
"""Finishes planning and waits for mission completion."""
if not self.ato_has_clients() and not self.confirm_no_client_launch():
return
- # TODO: Verify no negative start times.
+ negative_starts = self.negative_start_packages()
+ if negative_starts:
+ if not self.confirm_negative_start_time(negative_starts):
+ return
# TODO: Refactor this nonsense.
game_event = None