use rust_decimal::Decimal;
use crate::interval::MeterInterval;
#[derive(Debug, Clone)]
pub struct GasConversionParams {
pub hs_kwh_per_m3: Decimal,
pub zustandszahl: Decimal,
}
impl GasConversionParams {
#[must_use]
pub fn default_erdgas_h() -> Self {
Self {
hs_kwh_per_m3: Decimal::from_str_exact("10.55").unwrap_or(Decimal::from(10u32)),
zustandszahl: Decimal::ONE,
}
}
}
#[must_use]
pub fn gas_m3_to_kwh_hs(
volume_m3: Decimal,
hs_kwh_per_m3: Decimal,
zustandszahl: Decimal,
) -> Decimal {
volume_m3 * hs_kwh_per_m3 * zustandszahl
}
#[must_use]
pub fn normalize_interval_to_kwh(
interval: &MeterInterval,
unit: &str,
gas_params: Option<&GasConversionParams>,
) -> Decimal {
match unit.to_lowercase().as_str() {
"m3" | "m³" => {
let p = gas_params
.map(|p| (p.hs_kwh_per_m3, p.zustandszahl))
.unwrap_or_else(|| {
let d = GasConversionParams::default_erdgas_h();
(d.hs_kwh_per_m3, d.zustandszahl)
});
gas_m3_to_kwh_hs(interval.value_kwh, p.0, p.1)
}
"kw" => {
let dur_h = Decimal::from(interval.duration_secs()) / Decimal::from(3600u32);
interval.value_kwh * dur_h
}
_ => interval.value_kwh, }
}
#[cfg(test)]
mod tests {
use super::*;
use rust_decimal_macros::dec;
#[test]
fn gas_conversion_exact() {
let kwh = gas_m3_to_kwh_hs(dec!(100), dec!(10.55), dec!(1.0));
assert_eq!(kwh, dec!(1055.00));
}
#[test]
fn gas_conversion_with_zustandszahl() {
let kwh = gas_m3_to_kwh_hs(dec!(50), dec!(10.80), dec!(0.9800));
assert_eq!(kwh, dec!(529.2000));
}
#[test]
fn gas_conversion_zero_volume() {
assert_eq!(gas_m3_to_kwh_hs(dec!(0), dec!(10.55), dec!(1.0)), dec!(0));
}
#[test]
fn default_erdgas_h_params() {
let p = GasConversionParams::default_erdgas_h();
assert_eq!(p.hs_kwh_per_m3, dec!(10.55));
assert_eq!(p.zustandszahl, Decimal::ONE);
}
}