use std::collections::HashMap;
use std::str::FromStr;
use efb::fp::{AlteringFactor, AlteringFactors, FactorOfEffect, Influences};
use efb::measurements::{Angle, Length, Mass, Speed, Temperature};
use efb::nd::{Runway, RunwayConditionCode, RunwaySurface};
use efb::{VerticalDistance, Wind};
fn west_grass_rwy(elev: VerticalDistance) -> Runway {
Runway {
designator: String::from("27"),
bearing: Angle::t(270.0),
length: Length::m(1100.0),
tora: Length::m(900.0),
toda: Length::m(900.0),
lda: Length::m(900.0),
surface: RunwaySurface::Grass,
slope: 0.0,
elev,
}
}
#[test]
fn factor_for_winds() {
fn influences_with_wind(wind: &str) -> Influences {
Influences::new(
Mass::kg(0.0),
&west_grass_rwy(VerticalDistance::Gnd),
&Wind::from_str(wind).unwrap(),
Temperature::c(15.0),
RunwayConditionCode::Six,
)
}
let headwind_factor = AlteringFactor::DecreaseHeadwind(FactorOfEffect::Rate {
numerator: 0.1,
denominator: Speed::kt(9.0),
});
assert_eq!(
headwind_factor.ground_roll_factor(&influences_with_wind("27018KT")),
0.8 );
let tailwind_factor = AlteringFactor::IncreaseTailwind(FactorOfEffect::Rate {
numerator: 0.1,
denominator: Speed::kt(2.0),
});
assert_eq!(
tailwind_factor.ground_roll_factor(&influences_with_wind("09006KT")),
1.3 );
}
#[test]
fn factor_for_rwycc_and_surface() {
fn influences_with_rwycc(rwycc: RunwayConditionCode) -> Influences {
Influences::new(
Mass::kg(0.0),
&west_grass_rwy(VerticalDistance::Gnd),
&Wind::from_str("00000KT").unwrap(),
Temperature::c(15.0),
rwycc,
)
}
let grass_factor = AlteringFactor::IncreaseRWYCC(HashMap::from([
(
(Some(RunwayConditionCode::Six), Some(RunwaySurface::Grass)),
0.2,
),
(
(Some(RunwayConditionCode::Five), Some(RunwaySurface::Grass)),
0.33,
),
((None, Some(RunwaySurface::Grass)), 0.2),
((Some(RunwayConditionCode::Four), None), 0.4),
]));
assert!(
grass_factor.ground_roll_factor(&influences_with_rwycc(RunwayConditionCode::Six)) - 1.2
<= f32::EPSILON
);
assert!(
grass_factor.ground_roll_factor(&influences_with_rwycc(RunwayConditionCode::Five)) - 1.33
<= f32::EPSILON
);
assert!(
grass_factor.ground_roll_factor(&influences_with_rwycc(RunwayConditionCode::One)) - 1.2
<= f32::EPSILON
);
assert!(
grass_factor.ground_roll_factor(&influences_with_rwycc(RunwayConditionCode::Four)) - 1.4
<= f32::EPSILON
);
}
#[test]
fn factor_for_pressure_altitude() {
fn influences_with_elev(elev: VerticalDistance) -> Influences {
Influences::new(
Mass::kg(0.0),
&west_grass_rwy(elev),
&Wind::from_str("00000KT").unwrap(),
Temperature::c(15.0),
RunwayConditionCode::Six,
)
}
let factor = AlteringFactor::IncreaseAltitude(FactorOfEffect::Range(vec![
(..=VerticalDistance::PressureAltitude(1000), 0.1),
(..=VerticalDistance::PressureAltitude(3000), 0.13),
(..=VerticalDistance::Unlimited, 0.18),
]));
assert!(
factor.ground_roll_factor(&influences_with_elev(VerticalDistance::PressureAltitude(
1000
))) - 1.1
<= f32::EPSILON
);
assert!(
factor.ground_roll_factor(&influences_with_elev(VerticalDistance::PressureAltitude(
2000
))) - 1.13
<= f32::EPSILON
);
assert!(
factor.ground_roll_factor(&influences_with_elev(VerticalDistance::PressureAltitude(
20_000
))) - 1.18
<= f32::EPSILON
);
}
#[test]
fn product_of_factors() {
let influences = Influences::new(
Mass::kg(0.0),
&west_grass_rwy(VerticalDistance::Gnd),
&Wind::from_str("27010KT").unwrap(),
Temperature::c(15.0),
RunwayConditionCode::Six,
);
let factors = AlteringFactors::new(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), ])),
]);
assert!(factors.ground_roll_factor(&influences) - 1.0222222 <= f32::EPSILON);
}