use std::collections::HashMap;
use std::str::FromStr;
use efb::aircraft::{LoadedStation, Station};
use efb::fp::{
AlteringFactor, FactorOfEffect, MassAndBalance, RunwayAnalysis, TakeoffLandingPerformance,
};
use efb::nd::{Runway, RunwayConditionCode, RunwaySurface};
use efb::{VerticalDistance, Wind};
use efb::measurements::*;
fn rwy_analysis() -> RunwayAnalysis {
let perf = TakeoffLandingPerformance::builder(vec![
(
VerticalDistance::PressureAltitude(0),
Temperature::c(0.0),
Length::ft(845.0),
Length::ft(1510.0),
),
(
VerticalDistance::PressureAltitude(0),
Temperature::c(10.0),
Length::ft(910.0),
Length::ft(1625.0),
),
(
VerticalDistance::PressureAltitude(0),
Temperature::c(20.0),
Length::ft(980.0),
Length::ft(1745.0),
),
(
VerticalDistance::PressureAltitude(0),
Temperature::c(30.0),
Length::ft(1055.0),
Length::ft(1875.0),
),
(
VerticalDistance::PressureAltitude(0),
Temperature::c(40.0),
Length::ft(1135.0),
Length::ft(2015.0),
),
])
.factors(vec![
AlteringFactor::DecreaseHeadwind(FactorOfEffect::Rate {
numerator: 0.1,
denominator: Speed::kt(9.0),
}),
AlteringFactor::IncreaseTailwind(FactorOfEffect::Rate {
numerator: 0.1,
denominator: Speed::kt(2.0),
}),
AlteringFactor::IncreaseRWYCC(HashMap::from([
((None, Some(RunwaySurface::Grass)), 0.15), ])),
])
.build();
let west_grass_rwy = Runway {
designator: String::from("27"),
bearing: Angle::t(270.0),
length: Length::ft(3600.0),
tora: Length::ft(2900.0),
toda: Length::ft(2900.0),
lda: Length::ft(2900.0),
surface: RunwaySurface::Grass,
slope: 0.0,
elev: VerticalDistance::Gnd,
};
let mb = MassAndBalance::new(&vec![LoadedStation {
station: Station::new(Length::m(1.0), None),
on_ramp: Mass::kg(1111.0),
after_landing: Mass::kg(1111.0),
}]);
RunwayAnalysis::takeoff(
&west_grass_rwy,
RunwayConditionCode::Six,
&Wind::from_str("27010KT").unwrap(),
Temperature::c(20.0),
&mb,
&perf,
None,
)
}
#[test]
fn wind_components() {
let rwy_analysis = rwy_analysis();
assert_eq!(rwy_analysis.headwind(), &Speed::kt(10.0));
assert_eq!(rwy_analysis.crosswind(), &Speed::kt(0.0));
}
#[test]
fn ground_roll_and_distance_to_clear_obstacle() {
let rwy_analysis = rwy_analysis();
assert!(
*(*rwy_analysis.ground_roll() - Length::ft(1001.7777)).value() <= f32::EPSILON,
"the ground roll estimated with {} wasn't correct!",
rwy_analysis.ground_roll()
);
assert!(
*(*rwy_analysis.clear_obstacle() - Length::ft(1744.8888)).value() <= f32::EPSILON,
"the distance to clear a 50ft obstacle estimated with {} wasn't correct!",
rwy_analysis.ground_roll()
);
}
#[test]
fn ground_roll_margin() {
let rwy_analysis = rwy_analysis();
assert!(*(*rwy_analysis.margin() - Length::ft(1898.2223)).value() <= f32::EPSILON);
assert_eq!((rwy_analysis.pct_margin() * 100.0).round(), 65.0);
}