use crate::format::Location;
use serde::{Deserialize, Serialize};
use std::io::{BufReader, BufWriter, Error, Read, Write};
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
pub struct Timing {
pub driving: i64,
pub serving: i64,
pub waiting: i64,
#[serde(rename(serialize = "break", deserialize = "break"))]
pub break_time: i64,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
pub struct Statistic {
pub cost: f64,
pub distance: i64,
pub duration: i64,
pub times: Timing,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
pub struct Schedule {
pub arrival: String,
pub departure: String,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
pub struct Interval {
pub start: String,
pub end: String,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Activity {
pub job_id: String,
#[serde(rename(serialize = "type", deserialize = "type"))]
pub activity_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub location: Option<Location>,
#[serde(skip_serializing_if = "Option::is_none")]
pub time: Option<Interval>,
#[serde(skip_serializing_if = "Option::is_none")]
pub job_tag: Option<String>,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
pub struct Stop {
pub location: Location,
pub time: Schedule,
#[serde(default)]
pub distance: i64,
pub load: Vec<i32>,
pub activities: Vec<Activity>,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Tour {
pub vehicle_id: String,
pub type_id: String,
#[serde(default)]
pub shift_index: usize,
pub stops: Vec<Stop>,
pub statistic: Statistic,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
pub struct UnassignedJobReason {
pub code: String,
pub description: String,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct UnassignedJob {
pub job_id: String,
pub reasons: Vec<UnassignedJobReason>,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
#[serde(tag = "type")]
pub enum Violation {
#[serde(rename(deserialize = "break", serialize = "break"))]
Break {
vehicle_id: String,
shift_index: usize,
},
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
pub struct Metrics {
pub duration: usize,
pub generations: usize,
pub speed: f64,
pub evolution: Vec<Generation>,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Generation {
pub number: usize,
pub timestamp: f64,
pub i_all_ratio: f64,
pub i_1000_ratio: f64,
pub is_improvement: bool,
pub population: Population,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Individual {
pub tours: usize,
pub unassigned: usize,
pub cost: f64,
pub improvement: f64,
pub fitness: Vec<f64>,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Population {
pub individuals: Vec<Individual>,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
pub struct Extras {
#[serde(skip_serializing_if = "Option::is_none")]
pub metrics: Option<Metrics>,
}
#[derive(Clone, Deserialize, Serialize, PartialEq, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Solution {
pub statistic: Statistic,
pub tours: Vec<Tour>,
#[serde(skip_serializing_if = "Option::is_none")]
pub unassigned: Option<Vec<UnassignedJob>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub violations: Option<Vec<Violation>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub extras: Option<Extras>,
}
pub fn serialize_solution<W: Write>(writer: BufWriter<W>, solution: &Solution) -> Result<(), Error> {
serde_json::to_writer_pretty(writer, solution).map_err(Error::from)
}
pub fn deserialize_solution<R: Read>(reader: BufReader<R>) -> Result<Solution, Error> {
serde_json::from_reader(reader).map_err(Error::from)
}