aerocontext-core 0.4.1

Provider-neutral aeronautical-context model and the pluggable ContextProvider contract
Documentation
//! Pilot-supplied aircraft performance, the input a route brief needs to
//! turn distance into time, altitude, and fuel.
//!
//! Every figure here is **advisory** and comes from the operator's POH/AFM
//! — this crate computes a simplified, no-wind estimate to drive briefing
//! requests (which forecast hour to ask for, how the route climbs and
//! descends), never a performance or fuel guarantee. The performance ring
//! is the highest-criticality advisory arithmetic in the system; treat its
//! outputs as planning hints, not dispatch numbers.

use serde::{Deserialize, Serialize};

/// Speed/rate/burn figures for one aircraft, loaded from the operator's
/// own data (e.g. a JSON profile file).
///
/// Non-exhaustive: future fields (per-altitude burn tables, weight-based
/// climb, true-vs-indicated correction) are additive.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct AircraftProfile {
    /// Cruise true airspeed, knots.
    pub cruise_tas_kt: f64,
    /// Average climb rate to cruise, feet per minute.
    pub climb_rate_fpm: f64,
    /// True airspeed during climb, knots.
    pub climb_tas_kt: f64,
    /// Average descent rate from cruise, feet per minute.
    pub descent_rate_fpm: f64,
    /// True airspeed during descent, knots.
    pub descent_tas_kt: f64,
    /// Cruise fuel burn, gallons (or pounds) per hour — the unit is the
    /// operator's; this crate only divides and multiplies it.
    pub cruise_burn_per_hour: f64,
    /// Fuel burned starting, taxiing, and taking off, same unit.
    pub taxi_fuel: f64,
    /// Usable fuel capacity, same unit.
    pub fuel_capacity: f64,
    /// Required reserve, minutes of cruise burn (91.167/91.151 inputs).
    pub reserve_minutes: f64,
}

impl AircraftProfile {
    /// Hours to climb from `from_ft` to `to_ft` at the profile's climb
    /// rate; zero when already at or above the target.
    #[must_use]
    pub fn climb_hours(&self, from_ft: f64, to_ft: f64) -> f64 {
        if self.climb_rate_fpm <= 0.0 || to_ft <= from_ft {
            return 0.0;
        }
        (to_ft - from_ft) / self.climb_rate_fpm / 60.0
    }

    /// Hours to descend from `from_ft` to `to_ft` at the profile's
    /// descent rate; zero when already at or below the target.
    #[must_use]
    pub fn descent_hours(&self, from_ft: f64, to_ft: f64) -> f64 {
        if self.descent_rate_fpm <= 0.0 || from_ft <= to_ft {
            return 0.0;
        }
        (from_ft - to_ft) / self.descent_rate_fpm / 60.0
    }

    /// Reserve fuel implied by [`Self::reserve_minutes`] at cruise burn.
    #[must_use]
    pub fn reserve_fuel(&self) -> f64 {
        self.cruise_burn_per_hour * self.reserve_minutes / 60.0
    }
}