Schedule SEAD with a one minute lead time.

This commit is contained in:
Dan Albert 2021-05-25 22:53:37 -07:00
parent 205e4aa707
commit 4939faf5fa
2 changed files with 28 additions and 11 deletions

View File

@ -16,6 +16,7 @@ Saves from 2.5 are not compatible with 3.0.
* **[Flight Planner]** Planned airspeed increased to 0.85 mach for supersonic airframes and 85% of max speed for subsonic. * **[Flight Planner]** Planned airspeed increased to 0.85 mach for supersonic airframes and 85% of max speed for subsonic.
* **[Flight Planner]** Taxi time estimation for airfields increased from 5 minutes to 8 minutes. * **[Flight Planner]** Taxi time estimation for airfields increased from 5 minutes to 8 minutes.
* **[Flight Planner]** Reduce expected error margin for flight plans from 10% to 5%. * **[Flight Planner]** Reduce expected error margin for flight plans from 10% to 5%.
* **[Flight Planner]** SEAD flights are scheduled one minute ahead of the package's TOT so that they can suppress the site ahead of the strike.
* **[Payloads]** AI flights for most air to ground mission types (CAS excluded) will have their guns emptied to prevent strafing fully armed and operational battle stations. Gun-reliant airframes like A-10s and warbirds will keep their bullets. * **[Payloads]** AI flights for most air to ground mission types (CAS excluded) will have their guns emptied to prevent strafing fully armed and operational battle stations. Gun-reliant airframes like A-10s and warbirds will keep their bullets.
* **[Kneeboard]** ATC table overflow alleviated by wrapping long airfield names and splitting ATC frequency and channel into separate rows. * **[Kneeboard]** ATC table overflow alleviated by wrapping long airfield names and splitting ATC frequency and channel into separate rows.
* **[UI]** Added new web based map UI. This is mostly functional but many of the old display options are a WIP. Revert to the old map with --old-map. * **[UI]** Added new web based map UI. This is mostly functional but many of the old display options are a WIP. Revert to the old map with --old-map.

View File

@ -10,14 +10,13 @@ from __future__ import annotations
import logging import logging
import math import math
import random import random
from dataclasses import dataclass from dataclasses import dataclass, field
from datetime import timedelta from datetime import timedelta
from functools import cached_property from functools import cached_property
from typing import Iterator, List, Optional, Set, TYPE_CHECKING, Tuple from typing import Iterator, List, Optional, Set, TYPE_CHECKING, Tuple
from dcs.planes import E_3A, E_2C, A_50, KJ_2000
from dcs.mapping import Point from dcs.mapping import Point
from dcs.planes import E_3A, E_2C, A_50, KJ_2000
from dcs.unit import Unit from dcs.unit import Unit
from shapely.geometry import Point as ShapelyPoint from shapely.geometry import Point as ShapelyPoint
@ -125,6 +124,10 @@ class FlightPlan:
""" """
raise NotImplementedError raise NotImplementedError
@property
def tot(self) -> timedelta:
return self.package.time_over_target + self.tot_offset
@cached_property @cached_property
def bingo_fuel(self) -> int: def bingo_fuel(self) -> int:
"""Bingo fuel value for the FlightPlan""" """Bingo fuel value for the FlightPlan"""
@ -217,10 +220,9 @@ class FlightPlan:
if tot_waypoint is None: if tot_waypoint is None:
return None return None
time = self.tot_for_waypoint(tot_waypoint) time = self.tot
if time is None: if time is None:
return None return None
time += self.tot_offset
return time - self._travel_time_to_waypoint(tot_waypoint) return time - self._travel_time_to_waypoint(tot_waypoint)
def startup_time(self) -> Optional[timedelta]: def startup_time(self) -> Optional[timedelta]:
@ -520,7 +522,7 @@ class TarCapFlightPlan(PatrollingFlightPlan):
start = self.package.escort_start_time start = self.package.escort_start_time
if start is not None: if start is not None:
return start + self.tot_offset return start + self.tot_offset
return super().patrol_start_time + self.tot_offset return self.tot
@property @property
def patrol_end_time(self) -> timedelta: def patrol_end_time(self) -> timedelta:
@ -544,6 +546,7 @@ class StrikeFlightPlan(FormationFlightPlan):
land: FlightWaypoint land: FlightWaypoint
divert: Optional[FlightWaypoint] divert: Optional[FlightWaypoint]
bullseye: FlightWaypoint bullseye: FlightWaypoint
lead_time: timedelta = field(default_factory=timedelta)
def iter_waypoints(self) -> Iterator[FlightWaypoint]: def iter_waypoints(self) -> Iterator[FlightWaypoint]:
yield self.takeoff yield self.takeoff
@ -582,6 +585,13 @@ class StrikeFlightPlan(FormationFlightPlan):
def tot_waypoint(self) -> FlightWaypoint: def tot_waypoint(self) -> FlightWaypoint:
return self.targets[0] return self.targets[0]
@property
def tot_offset(self) -> timedelta:
try:
return -self.lead_time
except AttributeError:
return timedelta()
@property @property
def target_area_waypoint(self) -> FlightWaypoint: def target_area_waypoint(self) -> FlightWaypoint:
return FlightWaypoint( return FlightWaypoint(
@ -626,7 +636,7 @@ class StrikeFlightPlan(FormationFlightPlan):
@property @property
def ingress_time(self) -> timedelta: def ingress_time(self) -> timedelta:
tot = self.package.time_over_target tot = self.tot
travel_time = self.travel_time_between_waypoints( travel_time = self.travel_time_between_waypoints(
self.ingress, self.target_area_waypoint self.ingress, self.target_area_waypoint
) )
@ -634,7 +644,7 @@ class StrikeFlightPlan(FormationFlightPlan):
@property @property
def egress_time(self) -> timedelta: def egress_time(self) -> timedelta:
tot = self.package.time_over_target tot = self.tot
travel_time = self.travel_time_between_waypoints( travel_time = self.travel_time_between_waypoints(
self.target_area_waypoint, self.egress self.target_area_waypoint, self.egress
) )
@ -646,7 +656,7 @@ class StrikeFlightPlan(FormationFlightPlan):
elif waypoint == self.egress: elif waypoint == self.egress:
return self.egress_time return self.egress_time
elif waypoint in self.targets: elif waypoint in self.targets:
return self.package.time_over_target return self.tot
return super().tot_for_waypoint(waypoint) return super().tot_for_waypoint(waypoint)
@ -691,7 +701,7 @@ class SweepFlightPlan(LoiterFlightPlan):
@property @property
def sweep_end_time(self) -> timedelta: def sweep_end_time(self) -> timedelta:
return self.package.time_over_target + self.tot_offset return self.tot
def tot_for_waypoint(self, waypoint: FlightWaypoint) -> Optional[timedelta]: def tot_for_waypoint(self, waypoint: FlightWaypoint) -> Optional[timedelta]:
if waypoint == self.sweep_start: if waypoint == self.sweep_start:
@ -1513,7 +1523,11 @@ class FlightPlanBuilder:
targets.append(StrikeTarget(location.name, target)) targets.append(StrikeTarget(location.name, target))
return self.strike_flightplan( return self.strike_flightplan(
flight, location, FlightWaypointType.INGRESS_SEAD, targets flight,
location,
FlightWaypointType.INGRESS_SEAD,
targets,
lead_time=timedelta(minutes=1),
) )
def generate_escort(self, flight: Flight) -> StrikeFlightPlan: def generate_escort(self, flight: Flight) -> StrikeFlightPlan:
@ -1691,6 +1705,7 @@ class FlightPlanBuilder:
location: MissionTarget, location: MissionTarget,
ingress_type: FlightWaypointType, ingress_type: FlightWaypointType,
targets: Optional[List[StrikeTarget]] = None, targets: Optional[List[StrikeTarget]] = None,
lead_time: timedelta = timedelta(),
) -> StrikeFlightPlan: ) -> StrikeFlightPlan:
assert self.package.waypoints is not None assert self.package.waypoints is not None
builder = WaypointBuilder(flight, self.game, self.is_player, targets) builder = WaypointBuilder(flight, self.game, self.is_player, targets)
@ -1730,6 +1745,7 @@ class FlightPlanBuilder:
land=builder.land(flight.arrival), land=builder.land(flight.arrival),
divert=builder.divert(flight.divert), divert=builder.divert(flight.divert),
bullseye=builder.bullseye(), bullseye=builder.bullseye(),
lead_time=lead_time,
) )
def _retreating_rendezvous_point(self, attack_transition: Point) -> Point: def _retreating_rendezvous_point(self, attack_transition: Point) -> Point: