use super::compass::{CompassApp, CompassAppError};
use crate::app::search::SearchAppGraphOps;
use itertools::Itertools;
use routee_compass_core::{
algorithm::search::Direction,
model::{
network::{EdgeId, EdgeListId, VertexId},
unit::DistanceUnit,
},
};
use std::str::FromStr;
pub trait CompassAppBindings {
fn from_config_toml_string(
config_string: String,
original_file_path: String,
) -> Result<Self, CompassAppError>
where
Self: Sized;
fn app(&self) -> &CompassApp;
fn graph_edge_origin(
&self,
edge_list_id: Option<usize>,
edge_id: usize,
) -> Result<usize, CompassAppError> {
let edge_list_id = EdgeListId(edge_list_id.unwrap_or_default());
let edge_id_internal = EdgeId(edge_id);
self.app()
.search_app
.get_edge_origin(&edge_list_id, &edge_id_internal)
.map(|o| o.0)
}
fn graph_edge_destination(
&self,
edge_list_id: Option<usize>,
edge_id: usize,
) -> Result<usize, CompassAppError> {
let edge_list_id = EdgeListId(edge_list_id.unwrap_or_default());
let edge_id_internal = EdgeId(edge_id);
self.app()
.search_app
.get_edge_destination(&edge_list_id, &edge_id_internal)
.map(|o| o.0)
}
fn graph_edge_distance(
&self,
edge_list_id: Option<usize>,
edge_id: usize,
distance_unit: Option<String>,
) -> Result<f64, CompassAppError> {
let edge_list_id = EdgeListId(edge_list_id.unwrap_or_default());
let du_internal: Option<DistanceUnit> = match distance_unit {
Some(du_str) => {
let du = DistanceUnit::from_str(du_str.as_str()).map_err(|_| {
CompassAppError::InternalError(format!(
"could not deserialize distance unit '{du_str}'"
))
})?;
Some(du)
}
None => None,
};
let edge_id_internal = EdgeId(edge_id);
let edge_distance_internal = self
.app()
.search_app
.get_edge_distance(&edge_list_id, &edge_id_internal)?;
match du_internal {
Some(du) => Ok(du.from_uom(edge_distance_internal)),
None => Ok(DistanceUnit::Meters.from_uom(edge_distance_internal)),
}
}
fn graph_get_out_edge_ids(&self, vertex_id: usize) -> Vec<(usize, usize)> {
let vertex_id_internal = VertexId(vertex_id);
self.app()
.search_app
.get_incident_edge_ids(&vertex_id_internal, &Direction::Forward)
.into_iter()
.map(|e| (e.0 .0, e.1 .0))
.collect_vec()
}
fn graph_get_in_edge_ids(&self, vertex_id: usize) -> Vec<(usize, usize)> {
let vertex_id_internal = VertexId(vertex_id);
self.app()
.search_app
.get_incident_edge_ids(&vertex_id_internal, &Direction::Reverse)
.into_iter()
.map(|e| (e.0 .0, e.1 .0))
.collect_vec()
}
fn run_queries(
&self,
queries: Vec<String>,
config: Option<String>,
) -> Result<Vec<String>, CompassAppError> {
let config_inner: Option<serde_json::Value> = match config {
Some(c) => {
let c_serde: serde_json::Value = serde_json::from_str(&c)?;
Some(c_serde)
}
None => None,
};
let mut json_queries = queries
.iter()
.map(|q| serde_json::from_str(q))
.collect::<Result<Vec<serde_json::Value>, serde_json::Error>>()?;
let results = self.app().run(&mut json_queries, config_inner.as_ref())?;
let string_results: Vec<String> = results.iter().map(|r| r.to_string()).collect();
Ok(string_results)
}
fn map_match(
&self,
queries: Vec<String>,
config: Option<String>,
) -> Result<Vec<String>, CompassAppError> {
let config_inner: Option<serde_json::Value> = match config {
Some(c) => {
let c_serde: serde_json::Value = serde_json::from_str(&c)?;
Some(c_serde)
}
None => None,
};
let json_queries = queries
.iter()
.map(|q| serde_json::from_str(q))
.collect::<Result<Vec<serde_json::Value>, serde_json::Error>>()?;
let results = self.app().map_match(&json_queries, config_inner.as_ref())?;
let string_results: Vec<String> = results.iter().map(|r| r.to_string()).collect();
Ok(string_results)
}
fn run_calculate_path(
&self,
queries: Vec<String>,
config: Option<String>,
) -> Result<Vec<String>, CompassAppError> {
let config_inner: Option<serde_json::Value> = match config {
Some(c) => {
let c_serde: serde_json::Value = serde_json::from_str(&c)?;
Some(c_serde)
}
None => None,
};
let json_queries = queries
.iter()
.map(|q| serde_json::from_str(q))
.collect::<Result<Vec<serde_json::Value>, serde_json::Error>>()?;
let results = self
.app()
.run_calculate_path(&json_queries, config_inner.as_ref())?;
let string_results: Vec<String> = results.iter().map(|r| r.to_string()).collect();
Ok(string_results)
}
}