Dan Albert a2e98f485c
Remove bingo estimates from FlightPlan.
This doesn't need to be a part of FlightPlan, and it's easier to test if
it isn't. Move it out and add the tests.

It's pretty misleading to allow this in the core of the flight plan code
anything. This is an extremely unreliable estimate for most aircraft so
it should be more clearly just for briefing purposes.
2023-10-07 23:08:25 +02:00

67 lines
2.3 KiB
Python

from __future__ import annotations
import math
from typing import TYPE_CHECKING
from dcs import Point
from game.utils import Distance, meters
if TYPE_CHECKING:
from game.ato.flightwaypoint import FlightWaypoint
from game.dcs.aircrafttype import FuelConsumption
class BingoEstimator:
"""Estimates bingo/joker fuel values for a flight plan.
The results returned by this class are bogus for most airframes. Only the few
airframes which have fuel consumption data available can provide even moderately
reliable estimates. **Do not use this for flight planning.** This should only be
used in briefing context where it's okay to be wrong.
"""
def __init__(
self,
fuel_consumption: FuelConsumption | None,
arrival: Point,
divert: Point | None,
waypoints: list[FlightWaypoint],
) -> None:
self.fuel_consumption = fuel_consumption
self.arrival = arrival
self.divert = divert
self.waypoints = waypoints
def estimate_bingo(self) -> int:
"""Bingo fuel value for the FlightPlan"""
if (fuel := self.fuel_consumption) is not None:
return self._fuel_consumption_based_estimate(fuel)
return self._legacy_bingo_estimate()
def estimate_joker(self) -> int:
"""Joker fuel value for the FlightPlan"""
return self.estimate_bingo() + 1000
def _fuel_consumption_based_estimate(self, fuel: FuelConsumption) -> int:
distance_to_arrival = self._max_distance_from(self.arrival)
fuel_consumed = fuel.cruise * distance_to_arrival.nautical_miles
bingo = fuel_consumed + fuel.min_safe
return math.ceil(bingo / 100) * 100
def _legacy_bingo_estimate(self) -> int:
distance_to_arrival = self._max_distance_from(self.arrival)
bingo = 1000.0 # Minimum Emergency Fuel
bingo += 500 # Visual Traffic
bingo += 15 * distance_to_arrival.nautical_miles
if self.divert is not None:
max_divert_distance = self._max_distance_from(self.divert)
bingo += 10 * max_divert_distance.nautical_miles
return round(bingo / 100) * 100
def _max_distance_from(self, point: Point) -> Distance:
return max(meters(point.distance_to_point(w.position)) for w in self.waypoints)