use chrono::Datelike;
use crate::weather::Weather;
use super::{
buildup_index, drought_code, duff_moisture_code, fire_weather_index,
hourly_fine_fuel_moisture_code, initial_spread_index,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, Clone)]
pub struct HourlyFwiValues {
pub isi: f64,
pub dc: f64,
pub dmc: f64,
pub ffmc: f64,
pub bui: f64,
pub fwi: f64,
}
impl HourlyFwiValues {
pub fn as_starting_values(&self) -> StartingFwiValues {
StartingFwiValues {
dc: self.dc,
dmc: self.dmc,
ffmc: self.ffmc,
}
}
}
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, Clone)]
pub struct StartingFwiValues {
pub dc: f64,
pub dmc: f64,
pub ffmc: f64,
}
impl StartingFwiValues {
const DEFAULT: StartingFwiValues = StartingFwiValues {
ffmc: 50.,
dmc: 50.,
dc: 50.,
};
}
pub fn calculate_hourly(
weather: &Weather,
previous: Option<&StartingFwiValues>,
) -> HourlyFwiValues {
let previous = previous.unwrap_or(&StartingFwiValues::DEFAULT);
let ffmc = hourly_fine_fuel_moisture_code(
weather.temp,
weather.rh,
weather.ws,
weather.precip,
previous.ffmc,
Some(1.),
);
let dc = drought_code(
previous.dc,
weather.temp,
weather.precip,
weather.location.y(),
weather.time.month() as usize,
Some(true),
);
let dmc = duff_moisture_code(
previous.dmc,
weather.temp,
weather.rh,
weather.precip,
weather.location.y(),
weather.time.month() as usize,
Some(true),
);
let bui = buildup_index(dmc, dc);
let isi = initial_spread_index(ffmc, weather.ws);
let fwi = fire_weather_index(isi, bui);
HourlyFwiValues {
ffmc,
dmc,
dc,
isi,
bui,
fwi,
}
}