use std::collections::HashMap;
use cobre_core::{SystemBuilder, scenario::CorrelationModel};
use crate::{
LoadError,
resolution::{resolve_bounds, resolve_penalties},
scenarios::assembly::{assemble_inflow_models, assemble_load_models},
validation::{
ValidationContext,
dimensional::validate_dimensional_consistency,
referential::validate_referential_integrity,
schema::validate_schema,
semantic::{validate_semantic_hydro_thermal, validate_semantic_stages_penalties_scenarios},
structural::validate_structure,
},
};
use cobre_core::System;
use std::path::Path;
pub(crate) fn run_pipeline(path: &Path) -> Result<System, LoadError> {
let mut ctx = ValidationContext::new();
let manifest = validate_structure(path, &mut ctx);
let data = validate_schema(path, &manifest, &mut ctx);
let Some(data) = data else {
return ctx.into_result().and(Err(LoadError::ConstraintError {
description: "schema validation failed but no errors were collected".to_string(),
}));
};
validate_referential_integrity(&data, &mut ctx);
validate_dimensional_consistency(&data, &mut ctx);
validate_semantic_hydro_thermal(&data, &mut ctx);
validate_semantic_stages_penalties_scenarios(&data, &mut ctx);
ctx.into_result()?;
let study_stages: Vec<_> = data.stages.stages.iter().filter(|s| s.id >= 0).collect();
let n_stages = study_stages.len();
let stage_index: HashMap<i32, usize> = study_stages
.iter()
.enumerate()
.map(|(idx, s)| (s.id, idx))
.collect();
let penalties = resolve_penalties(
&data.hydros,
&data.buses,
&data.lines,
&data.non_controllable_sources,
n_stages,
&stage_index,
&data.penalty_overrides_hydro,
&data.penalty_overrides_bus,
&data.penalty_overrides_line,
&data.penalty_overrides_ncs,
);
let bounds = resolve_bounds(
&data.hydros,
&data.thermals,
&data.lines,
&data.pumping_stations,
&data.energy_contracts,
n_stages,
&stage_index,
&data.hydro_bounds,
&data.thermal_bounds,
&data.line_bounds,
&data.pumping_bounds,
&data.contract_bounds,
);
let inflow_models =
assemble_inflow_models(data.inflow_seasonal_stats, data.inflow_ar_coefficients)?;
let load_models = assemble_load_models(data.load_seasonal_stats);
let system = SystemBuilder::new()
.buses(data.buses)
.lines(data.lines)
.hydros(data.hydros)
.thermals(data.thermals)
.pumping_stations(data.pumping_stations)
.contracts(data.energy_contracts)
.non_controllable_sources(data.non_controllable_sources)
.stages(data.stages.stages)
.policy_graph(data.stages.policy_graph)
.penalties(penalties)
.bounds(bounds)
.inflow_models(inflow_models)
.load_models(load_models)
.correlation(data.correlation.unwrap_or_else(CorrelationModel::default))
.initial_conditions(data.initial_conditions)
.generic_constraints(data.generic_constraints)
.scenario_source(data.stages.scenario_source)
.build()
.map_err(|errs| LoadError::ConstraintError {
description: errs
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join("\n"),
})?;
Ok(system)
}