mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Estimate TOTs for packages.
We estimate the longest possible time from mission start to TOT for all flights in a package and use that to set the TOT (plus any delay used to stagger flights). This both cuts down on loiter time for shorter flights and ensures that long flights will make it to the target in time. This is also used to compute the start time for the AI, so the explicit delay option is no longer needed.
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
"""Qt data models for game objects."""
|
||||
import datetime
|
||||
from enum import auto, IntEnum
|
||||
from typing import Any, Callable, Dict, Iterator, TypeVar, Optional
|
||||
from typing import Any, Callable, Dict, Iterator, Optional, TypeVar
|
||||
|
||||
from PySide2.QtCore import (
|
||||
QAbstractListModel,
|
||||
@@ -15,6 +14,7 @@ from game import db
|
||||
from game.game import Game
|
||||
from gen.ato import AirTaskingOrder, Package
|
||||
from gen.flights.flight import Flight
|
||||
from gen.flights.traveltime import TotEstimator
|
||||
from qt_ui.uiconstants import AIRCRAFT_ICONS
|
||||
from theater.missiontarget import MissionTarget
|
||||
|
||||
@@ -119,15 +119,15 @@ class PackageModel(QAbstractListModel):
|
||||
return flight
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def text_for_flight(flight: Flight) -> str:
|
||||
def text_for_flight(self, flight: Flight) -> str:
|
||||
"""Returns the text that should be displayed for the flight."""
|
||||
task = flight.flight_type.name
|
||||
count = flight.count
|
||||
name = db.unit_type_name(flight.unit_type)
|
||||
delay = flight.scheduled_in
|
||||
estimator = TotEstimator(self.package)
|
||||
delay = datetime.timedelta(seconds=estimator.mission_start_time(flight))
|
||||
origin = flight.from_cp.name
|
||||
return f"[{task}] {count} x {name} from {origin} in {delay} minutes"
|
||||
return f"[{task}] {count} x {name} from {origin} in {delay}"
|
||||
|
||||
@staticmethod
|
||||
def icon_for_flight(flight: Flight) -> Optional[QIcon]:
|
||||
|
||||
@@ -147,6 +147,8 @@ class QTopPanel(QFrame):
|
||||
if not self.ato_has_clients() and not self.confirm_no_client_launch():
|
||||
return
|
||||
|
||||
# TODO: Verify no negative start times.
|
||||
|
||||
# TODO: Refactor this nonsense.
|
||||
game_event = None
|
||||
for event in self.game.events:
|
||||
|
||||
@@ -24,6 +24,7 @@ from PySide2.QtWidgets import (
|
||||
from game import db
|
||||
from gen.ato import Package
|
||||
from gen.flights.flight import Flight
|
||||
from gen.flights.traveltime import TotEstimator
|
||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||
from ..models import AtoModel, GameModel, NullListModel, PackageModel
|
||||
|
||||
@@ -33,6 +34,10 @@ class FlightDelegate(QStyledItemDelegate):
|
||||
HMARGIN = 4
|
||||
VMARGIN = 4
|
||||
|
||||
def __init__(self, package: Package) -> None:
|
||||
super().__init__()
|
||||
self.package = package
|
||||
|
||||
def get_font(self, option: QStyleOptionViewItem) -> QFont:
|
||||
font = QFont(option.font)
|
||||
font.setPointSize(self.FONT_SIZE)
|
||||
@@ -47,8 +52,9 @@ class FlightDelegate(QStyledItemDelegate):
|
||||
task = flight.flight_type.name
|
||||
count = flight.count
|
||||
name = db.unit_type_name(flight.unit_type)
|
||||
delay = flight.scheduled_in
|
||||
return f"[{task}] {count} x {name} in {delay} minutes"
|
||||
estimator = TotEstimator(self.package)
|
||||
delay = datetime.timedelta(seconds=estimator.mission_start_time(flight))
|
||||
return f"[{task}] {count} x {name} in {delay}"
|
||||
|
||||
def second_row_text(self, index: QModelIndex) -> str:
|
||||
flight = self.flight(index)
|
||||
@@ -128,7 +134,8 @@ class QFlightList(QListView):
|
||||
super().__init__()
|
||||
self.package_model = model
|
||||
self.set_package(model)
|
||||
self.setItemDelegate(FlightDelegate())
|
||||
if model is not None:
|
||||
self.setItemDelegate(FlightDelegate(model.package))
|
||||
self.setIconSize(QSize(91, 24))
|
||||
self.setSelectionBehavior(QAbstractItemView.SelectItems)
|
||||
|
||||
@@ -138,6 +145,7 @@ class QFlightList(QListView):
|
||||
self.disconnect_model()
|
||||
else:
|
||||
self.package_model = model
|
||||
self.setItemDelegate(FlightDelegate(model.package))
|
||||
self.setModel(model)
|
||||
# noinspection PyUnresolvedReferences
|
||||
model.deleted.connect(self.disconnect_model)
|
||||
|
||||
@@ -21,7 +21,8 @@ from game import Game, db
|
||||
from game.data.aaa_db import AAA_UNITS
|
||||
from game.data.radar_db import UNITS_WITH_RADAR
|
||||
from game.utils import meter_to_feet
|
||||
from gen import Conflict, Package, PackageWaypointTiming
|
||||
from gen import Conflict, PackageWaypointTiming
|
||||
from gen.ato import Package
|
||||
from gen.flights.flight import Flight, FlightWaypoint, FlightWaypointType
|
||||
from qt_ui.displayoptions import DisplayOptions
|
||||
from qt_ui.models import GameModel
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
import datetime
|
||||
|
||||
from PySide2.QtGui import QStandardItem, QIcon
|
||||
|
||||
from game import db
|
||||
from gen.ato import Package
|
||||
from gen.flights.flight import Flight
|
||||
from gen.flights.traveltime import TotEstimator
|
||||
from qt_ui.uiconstants import AIRCRAFT_ICONS
|
||||
|
||||
|
||||
# TODO: Replace with QFlightList.
|
||||
class QFlightItem(QStandardItem):
|
||||
|
||||
def __init__(self, flight:Flight):
|
||||
def __init__(self, package: Package, flight: Flight):
|
||||
super(QFlightItem, self).__init__()
|
||||
self.package = package
|
||||
self.flight = flight
|
||||
|
||||
if db.unit_type_name(self.flight.unit_type).replace("/", " ") in AIRCRAFT_ICONS.keys():
|
||||
icon = QIcon((AIRCRAFT_ICONS[db.unit_type_name(self.flight.unit_type)]))
|
||||
self.setIcon(icon)
|
||||
self.setEditable(False)
|
||||
estimator = TotEstimator(self.package)
|
||||
delay = datetime.timedelta(seconds=estimator.mission_start_time(flight))
|
||||
self.setText("["+str(self.flight.flight_type.name[:6])+"] "
|
||||
+ str(self.flight.count) + " x " + db.unit_type_name(self.flight.unit_type)
|
||||
+ " in " + str(self.flight.scheduled_in) + " minutes")
|
||||
|
||||
def update(self, flight):
|
||||
self.flight = flight
|
||||
self.setText("[" + str(self.flight.flight_type.name[:6]) + "] "
|
||||
+ str(self.flight.count) + " x " + db.unit_type_name(self.flight.unit_type)
|
||||
+ " in " + str(self.flight.scheduled_in) + " minutes")
|
||||
+ " in " + str(delay))
|
||||
|
||||
@@ -116,11 +116,14 @@ class QPackageDialog(QDialog):
|
||||
|
||||
self.finished.connect(self.on_close)
|
||||
|
||||
def on_close(self, _result) -> None:
|
||||
@staticmethod
|
||||
def on_close(_result) -> None:
|
||||
GameUpdateSignal.get_instance().redraw_flight_paths()
|
||||
|
||||
def save_tot(self) -> None:
|
||||
time = self.tot_spinner.time()
|
||||
seconds = time.hour() * 3600 + time.minute() * 60 + time.second()
|
||||
self.package_model.update_tot(seconds)
|
||||
GameUpdateSignal.get_instance().redraw_flight_paths()
|
||||
|
||||
def on_selection_changed(self, selected: QItemSelection,
|
||||
_deselected: QItemSelection) -> None:
|
||||
@@ -182,6 +185,7 @@ class QNewPackageDialog(QPackageDialog):
|
||||
Empty packages may be created. They can be modified later, and will have
|
||||
no effect if empty when the mission is generated.
|
||||
"""
|
||||
self.save_tot()
|
||||
self.ato_model.add_package(self.package_model.package)
|
||||
for flight in self.package_model.package.flights:
|
||||
self.game.aircraft_inventory.claim_for_flight(flight)
|
||||
@@ -227,6 +231,7 @@ class QEditPackageDialog(QPackageDialog):
|
||||
|
||||
def on_done(self) -> None:
|
||||
"""Closes the window."""
|
||||
self.save_tot()
|
||||
self.close()
|
||||
|
||||
def on_delete(self) -> None:
|
||||
|
||||
@@ -90,7 +90,11 @@ class QFlightCreator(QDialog):
|
||||
origin = self.airfield_selector.currentData()
|
||||
size = self.flight_size_spinner.value()
|
||||
|
||||
flight = Flight(aircraft, size, origin, task)
|
||||
if self.game.settings.perf_ai_parking_start:
|
||||
start_type = "Cold"
|
||||
else:
|
||||
start_type = "Warm"
|
||||
flight = Flight(aircraft, size, origin, task, start_type)
|
||||
flight.scheduled_in = self.package.delay
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from PySide2.QtWidgets import QLabel, QHBoxLayout, QGroupBox, QSpinBox
|
||||
|
||||
|
||||
# TODO: Remove?
|
||||
class QFlightDepartureEditor(QGroupBox):
|
||||
|
||||
def __init__(self, flight):
|
||||
@@ -15,7 +16,7 @@ class QFlightDepartureEditor(QGroupBox):
|
||||
self.departure_delta = QSpinBox(self)
|
||||
self.departure_delta.setMinimum(0)
|
||||
self.departure_delta.setMaximum(120)
|
||||
self.departure_delta.setValue(self.flight.scheduled_in)
|
||||
self.departure_delta.setValue(self.flight.scheduled_in // 60)
|
||||
self.departure_delta.valueChanged.connect(self.change_scheduled)
|
||||
|
||||
layout.addWidget(self.depart_from)
|
||||
@@ -27,4 +28,4 @@ class QFlightDepartureEditor(QGroupBox):
|
||||
self.changed = self.departure_delta.valueChanged
|
||||
|
||||
def change_scheduled(self):
|
||||
self.flight.scheduled_in = int(self.departure_delta.value())
|
||||
self.flight.scheduled_in = int(self.departure_delta.value() * 60)
|
||||
|
||||
Reference in New Issue
Block a user