use std::collections::BTreeSet;
use crate::ComponentGraph;
use crate::Edge;
use crate::Error;
use crate::Node;
use crate::component_category::CategoryPredicates;
mod expr;
mod fallback;
mod formula;
mod generators;
mod traversal;
use expr::Expr;
pub use formula::Formula;
impl<N, E> ComponentGraph<N, E>
where
N: Node,
E: Edge,
{
pub fn consumer_formula(&self) -> Result<Formula, Error> {
generators::consumer::ConsumerFormulaBuilder::try_new(self)?.build()
}
pub fn grid_formula(&self) -> Result<Formula, Error> {
generators::grid::GridFormulaBuilder::try_new(self)?.build()
}
pub fn producer_formula(&self) -> Result<Formula, Error> {
generators::producer::ProducerFormulaBuilder::try_new(self)?.build()
}
pub fn battery_formula(&self, battery_ids: Option<BTreeSet<u64>>) -> Result<Formula, Error> {
generators::battery::BatteryFormulaBuilder::try_new(self, battery_ids)?.build()
}
pub fn chp_formula(&self, chp_ids: Option<BTreeSet<u64>>) -> Result<Formula, Error> {
generators::category::category_formula(
self,
chp_ids,
|node| node.is_chp(),
"a CHP",
self.config.prefer_meters_in_chp_formula(),
)
}
pub fn pv_formula(&self, pv_inverter_ids: Option<BTreeSet<u64>>) -> Result<Formula, Error> {
generators::category::category_formula(
self,
pv_inverter_ids,
|node| node.is_pv_inverter(),
"a PV inverter",
self.config.prefer_meters_in_pv_formula(),
)
}
pub fn wind_turbine_formula(
&self,
wind_turbine_ids: Option<BTreeSet<u64>>,
) -> Result<Formula, Error> {
generators::category::category_formula(
self,
wind_turbine_ids,
|node| node.is_wind_turbine(),
"a wind turbine",
self.config.prefer_meters_in_wind_turbine_formula(),
)
}
pub fn ev_charger_formula(
&self,
ev_charger_ids: Option<BTreeSet<u64>>,
) -> Result<Formula, Error> {
generators::category::category_formula(
self,
ev_charger_ids,
|node| node.is_ev_charger(),
"an EV charger",
self.config.prefer_meters_in_ev_charger_formula(),
)
}
pub fn component_formula(&self, component_id: u64) -> Result<Formula, Error> {
Ok(Expr::component(component_id).into())
}
pub fn grid_coalesce_formula(&self) -> Result<Formula, Error> {
generators::grid_coalesce::GridCoalesceFormulaBuilder::try_new(self)?.build()
}
pub fn battery_ac_coalesce_formula(
&self,
battery_ids: Option<BTreeSet<u64>>,
) -> Result<Formula, Error> {
generators::battery_ac_coalesce::BatteryAcCoalesceFormulaBuilder::try_new(
self,
battery_ids,
)?
.build()
}
pub fn pv_ac_coalesce_formula(
&self,
pv_inverter_ids: Option<BTreeSet<u64>>,
) -> Result<Formula, Error> {
generators::pv_ac_coalesce::PVAcCoalesceFormulaBuilder::try_new(self, pv_inverter_ids)?
.build()
}
pub fn component_ac_coalesce_formula(&self, component_id: u64) -> Result<Formula, Error> {
Ok(Expr::component(component_id).into())
}
pub fn steam_boiler_formula(
&self,
steam_boiler_ids: Option<BTreeSet<u64>>,
) -> Result<Formula, Error> {
generators::category::category_formula(
self,
steam_boiler_ids,
|node| node.is_steam_boiler(),
"a steam boiler",
self.config.prefer_meters_in_steam_boiler_formula(),
)
}
}
#[cfg(test)]
mod tests {
use crate::{Error, graph::test_utils::ComponentGraphBuilder};
#[test]
fn test_component_formula() -> Result<(), Error> {
let mut builder = ComponentGraphBuilder::new();
let grid = builder.grid();
let meter = builder.meter();
let inverter = builder.battery_inverter();
let battery = builder.battery();
builder.connect(grid, meter);
builder.connect(meter, inverter);
builder.connect(inverter, battery);
let graph = builder.build(None)?;
let inv = inverter.component_id();
assert_eq!(graph.component_formula(inv)?.to_string(), format!("#{inv}"));
assert_eq!(
graph.component_ac_coalesce_formula(inv)?.to_string(),
format!("#{inv}")
);
Ok(())
}
}