use serde::Serialize;
use crate::{
models::{foundation::Foundation, point_load_test::PointLoadTest},
validation::{validate_field, ValidationError},
};
#[derive(Debug, Serialize)]
pub struct Output {
pub is50: f64,
pub ucs: f64,
pub c: f64,
pub d: f64,
pub allowable_bearing_capacity: f64,
pub qmax: f64,
pub df: f64,
pub is_safe: bool,
pub safety_factor: f64,
}
pub fn validate_input(
point_load_test: &PointLoadTest,
foundation: &Foundation,
foundation_pressure: f64,
safety_factor: f64,
) -> Result<(), ValidationError> {
point_load_test.validate(&["is50", "d"])?;
foundation.validate(&["foundation_depth"])?;
validate_field(
"foundation_pressure",
Some(foundation_pressure),
Some(0.0),
None,
"loads",
)?;
validate_field(
"safety_factor",
Some(safety_factor),
Some(1.),
None,
"safety_factor",
)?;
Ok(())
}
pub fn get_generalized_c_value(d: f64) -> f64 {
let diameters = [
(20., 17.5),
(30., 19.),
(40., 21.),
(50., 23.),
(54., 24.),
(60., 24.5),
];
if d <= diameters[0].0 {
return diameters[0].1;
}
if d >= diameters.last().unwrap().0 {
return diameters.last().unwrap().1;
}
for i in 0..diameters.len() - 1 {
let (d_lower, c_lower) = diameters[i];
let (d_upper, c_upper) = diameters[i + 1];
if d >= d_lower && d <= d_upper {
let fraction = (d - d_lower) / (d_upper - d_lower);
return c_lower + fraction * (c_upper - c_lower);
}
}
unreachable!()
}
pub fn calc_bearing_capacity(
point_load_test: PointLoadTest,
foundation: Foundation,
foundation_pressure: f64,
safety_factor: f64,
) -> Result<Output, ValidationError> {
validate_input(
&point_load_test,
&foundation,
foundation_pressure,
safety_factor,
)?;
let df = foundation.foundation_depth.unwrap();
let point_load_test_exp = point_load_test.get_idealized_exp("idealized".to_string());
const MPA_TO_TON: f64 = 101.97162; let sample = point_load_test_exp.get_sample_at_depth(df);
let is50 = sample.is50.unwrap();
let d = sample.d.unwrap();
let c = get_generalized_c_value(d);
let ucs = is50 * c * MPA_TO_TON;
let allowable_bearing_capacity = ucs / safety_factor;
let is_safe = allowable_bearing_capacity >= foundation_pressure;
Ok(Output {
is50,
ucs,
c,
d,
allowable_bearing_capacity,
is_safe,
safety_factor,
qmax: foundation_pressure,
df,
})
}