use super::TimeDelayLookup;
use bambam_core::model::bambam_state;
use routee_compass_core::{
algorithm::search::SearchTree,
model::{
network::{Edge, Vertex},
state::{InputFeature, StateModel, StateVariable, StateVariableConfig},
traversal::{
EdgeFrontierContext, TraversalModel, TraversalModelError, TraversalModelService,
},
},
};
use std::sync::Arc;
use uom::{si::f64::Time, ConstZero};
pub struct TripArrivalDelayModel(Arc<TimeDelayLookup>);
impl TripArrivalDelayModel {
pub fn new(lookup: Arc<TimeDelayLookup>) -> TripArrivalDelayModel {
TripArrivalDelayModel(lookup)
}
}
impl TraversalModelService for TripArrivalDelayModel {
fn build(
&self,
query: &serde_json::Value,
) -> Result<Arc<dyn TraversalModel>, TraversalModelError> {
let model: Arc<dyn TraversalModel> = Arc::new(Self::new(self.0.clone()));
Ok(model)
}
}
impl TraversalModel for TripArrivalDelayModel {
fn name(&self) -> String {
"Trip Arrival Delay Traversal Model".to_string()
}
fn input_features(&self) -> Vec<InputFeature> {
vec![]
}
fn output_features(&self) -> Vec<(String, StateVariableConfig)> {
vec![(
bambam_state::TRIP_ARRIVAL_DELAY.to_string(),
StateVariableConfig::Time {
initial: Time::ZERO,
output_unit: Some(self.0.config.time_unit),
accumulator: false,
},
)]
}
fn estimate_traversal(
&self,
od: (&Vertex, &Vertex),
state: &mut Vec<StateVariable>,
_tree: &SearchTree,
state_model: &StateModel,
) -> Result<(), TraversalModelError> {
let (_, destination) = od;
add_delay_time(destination, state, state_model, self.0.clone())
}
fn traverse_edge(
&self,
ctx: &EdgeFrontierContext,
state: &mut Vec<StateVariable>,
state_model: &StateModel,
) -> Result<(), TraversalModelError> {
add_delay_time(ctx.dst, state, state_model, self.0.clone())
}
}
fn add_delay_time(
destination: &Vertex,
state: &mut [StateVariable],
state_model: &StateModel,
lookup: Arc<TimeDelayLookup>,
) -> Result<(), TraversalModelError> {
if let Some(delay) = lookup.get_delay_for_vertex(destination) {
state_model.set_time(state, bambam_state::TRIP_ARRIVAL_DELAY, &delay)?;
}
Ok(())
}