use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AlkalinityResult {
pub alkalinity_meq_l: f64,
pub alkalinity_mg_l_caco3: f64,
}
#[must_use]
pub fn gran_titration(
sample_weight_g: f64,
acid_normality: f64,
titrant_volume_ml: f64,
) -> AlkalinityResult {
let sample_volume_ml = sample_weight_g; let alkalinity_meq_l = if sample_volume_ml == 0.0 {
f64::NAN
} else {
(acid_normality * titrant_volume_ml) / sample_volume_ml
};
let alkalinity_mg_l_caco3 = alkalinity_meq_l * 50.04;
AlkalinityResult {
alkalinity_meq_l,
alkalinity_mg_l_caco3,
}
}
#[cfg(test)]
mod tests {
use super::*;
const TOL: f64 = 1e-4;
#[test]
fn test_gran_titration_basic() {
let result = gran_titration(50.0, 0.02, 5.0);
assert!(
(result.alkalinity_meq_l - 0.002).abs() < TOL,
"expected 0.002, got {}",
result.alkalinity_meq_l
);
assert!(
(result.alkalinity_mg_l_caco3 - 0.002 * 50.04).abs() < TOL,
"expected {}, got {}",
0.002 * 50.04,
result.alkalinity_mg_l_caco3
);
}
#[test]
fn test_gran_titration_zero_sample() {
let result = gran_titration(0.0, 0.02, 5.0);
assert!(result.alkalinity_meq_l.is_nan());
}
}