extern crate serde_json;
use hashbrown::HashMap;
use serde::{Deserialize, Serialize};
use vrp_core::construction::enablers::ReservedTimesIndex;
use vrp_core::models::problem::{Fleet as CoreFleet, Job as CoreJob};
use vrp_core::models::Problem as CoreProblem;
use vrp_core::prelude::GenericError;
mod coord_index;
pub use self::coord_index::CoordIndex;
pub mod problem;
pub mod solution;
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum Location {
Coordinate {
lat: f64,
lng: f64,
},
Reference {
index: usize,
},
}
impl Location {
pub fn new_coordinate(lat: f64, lng: f64) -> Self {
Self::Coordinate { lat, lng }
}
pub fn new_reference(index: usize) -> Self {
Self::Reference { index }
}
pub fn to_lat_lng(&self) -> (f64, f64) {
match self {
Self::Coordinate { lat, lng } => (*lat, *lng),
_ => unreachable!("expect coordinate"),
}
}
}
impl std::fmt::Display for Location {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match *self {
Location::Coordinate { lat, lng } => write!(f, "lat={lat}, lng={lng}"),
Location::Reference { index } => write!(f, "index={index}"),
}
}
}
#[derive(Clone, Debug, Serialize)]
pub struct FormatError {
pub code: String,
pub cause: String,
pub action: String,
pub details: Option<String>,
}
impl FormatError {
pub fn new(code: String, cause: String, action: String) -> Self {
Self { code, cause, action, details: None }
}
pub fn new_with_details(code: String, cause: String, action: String, details: String) -> Self {
Self { code, cause, action, details: Some(details) }
}
pub fn to_json(&self) -> String {
serde_json::to_string_pretty(&self).unwrap()
}
}
impl std::error::Error for FormatError {}
impl std::fmt::Display for FormatError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}, cause: '{}', action: '{}'.", self.code, self.cause, self.action)
}
}
#[derive(Debug)]
pub struct MultiFormatError {
pub errors: Vec<FormatError>,
}
impl MultiFormatError {
pub fn to_json(&self) -> String {
serde_json::to_string_pretty(&self.errors).unwrap()
}
}
impl std::error::Error for MultiFormatError {}
impl std::fmt::Display for MultiFormatError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.errors.iter().map(|err| err.to_string()).collect::<Vec<_>>().join("\n"))
}
}
impl From<Vec<FormatError>> for MultiFormatError {
fn from(errors: Vec<FormatError>) -> Self {
MultiFormatError { errors }
}
}
impl From<MultiFormatError> for GenericError {
fn from(value: MultiFormatError) -> Self {
value.to_string().into()
}
}
impl IntoIterator for MultiFormatError {
type Item = FormatError;
type IntoIter = <Vec<FormatError> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.errors.into_iter()
}
}
const TIME_CONSTRAINT_CODE: i32 = 1;
const DISTANCE_LIMIT_CONSTRAINT_CODE: i32 = 2;
const DURATION_LIMIT_CONSTRAINT_CODE: i32 = 3;
const CAPACITY_CONSTRAINT_CODE: i32 = 4;
const BREAK_CONSTRAINT_CODE: i32 = 5;
const SKILL_CONSTRAINT_CODE: i32 = 6;
const LOCKING_CONSTRAINT_CODE: i32 = 7;
const REACHABLE_CONSTRAINT_CODE: i32 = 8;
const AREA_CONSTRAINT_CODE: i32 = 9;
const DISPATCH_CONSTRAINT_CODE: i32 = 10;
const TOUR_SIZE_CONSTRAINT_CODE: i32 = 11;
const TOUR_ORDER_CONSTRAINT_CODE: i32 = 12;
const GROUP_CONSTRAINT_CODE: i32 = 13;
const COMPATIBILITY_CONSTRAINT_CODE: i32 = 14;
const RELOAD_RESOURCE_CONSTRAINT_CODE: i32 = 15;
pub type JobIndex = HashMap<String, CoreJob>;
pub fn get_job_index(problem: &CoreProblem) -> &JobIndex {
problem
.extras
.get("job_index")
.and_then(|s| s.downcast_ref::<JobIndex>())
.unwrap_or_else(|| panic!("cannot get job index!"))
}
pub fn get_coord_index(problem: &CoreProblem) -> &CoordIndex {
problem.extras.get("coord_index").and_then(|s| s.downcast_ref::<CoordIndex>()).expect("cannot get coord index!")
}