#[macro_use]
pub mod macros;
pub mod flight_plan;
pub mod itinerary;
pub mod schedule;
pub mod vehicle;
pub mod vertiport;
use crate::grpc::client::GrpcClients;
use svc_gis_client_grpc::prelude::{gis::*, *};
pub enum BestPathError {
ClientError,
NoPathFound,
}
impl std::fmt::Display for BestPathError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
BestPathError::ClientError => write!(f, "Client error"),
BestPathError::NoPathFound => write!(f, "No path found"),
}
}
}
pub async fn best_path(
request: &BestPathRequest,
clients: &GrpcClients,
) -> Result<Vec<(Vec<PointZ>, f64)>, BestPathError> {
let mut paths = match clients.gis.best_path(request.clone()).await {
Ok(response) => response.into_inner().paths,
Err(e) => {
router_error!("(best_path) Failed to get best path: {e}");
return Err(BestPathError::ClientError);
}
};
if paths.is_empty() {
router_error!("(best_path) No path found.");
return Err(BestPathError::NoPathFound);
}
paths.sort_by(|a, b| {
if a.distance_meters == b.distance_meters {
std::cmp::Ordering::Equal
} else if a.distance_meters < b.distance_meters {
std::cmp::Ordering::Less
} else {
std::cmp::Ordering::Greater
}
});
router_debug!("(best_path) svc-gis paths: {:?}", paths);
let mut result: Vec<(Vec<PointZ>, f64)> = vec![];
for path in paths {
let Ok(points) = path
.path
.into_iter()
.map(|node| match node.geom {
Some(geom) => Ok(geom),
None => {
router_error!("(best_path) No geometry found for node: {:#?}", node);
Err(BestPathError::NoPathFound)
}
})
.collect::<Result<Vec<PointZ>, BestPathError>>()
else {
continue;
};
result.push((points, path.distance_meters.into()));
}
Ok(result)
}