Spaces:
Sleeping
Sleeping
| //! Delivery problem facts. | |
| //! | |
| //! A delivery is input data, not something SolverForge mutates directly. The | |
| //! solver places delivery ids into each vehicle's list variable. | |
| use serde::{Deserialize, Serialize}; | |
| use solverforge::prelude::*; | |
| use solverforge_maps::{Coord, RoutingError}; | |
| use super::CoordValue; | |
| /// A delivery stop that can be assigned into a vehicle route. | |
| pub struct Delivery { | |
| pub id: usize, | |
| pub label: String, | |
| pub kind: DeliveryKind, | |
| /// Latitude in decimal degrees, wrapped so derived equality stays stable. | |
| pub lat: CoordValue, | |
| /// Longitude in decimal degrees, wrapped so derived equality stays stable. | |
| pub lng: CoordValue, | |
| /// Load consumed from the assigned vehicle capacity. | |
| pub demand: i32, | |
| /// Earliest allowed service start, expressed as seconds after midnight. | |
| pub min_start_time: i64, | |
| /// Latest allowed service end, expressed as seconds after midnight. | |
| pub max_end_time: i64, | |
| /// Time spent at the stop after arrival. | |
| pub service_duration: i64, | |
| } | |
| /// Coarse stop type used to shape demo-data demand and UI icons. | |
| pub enum DeliveryKind { | |
| Residential, | |
| Business, | |
| Restaurant, | |
| Other, | |
| } | |
| impl Delivery { | |
| /// Creates one problem fact from transport-friendly primitive values. | |
| pub fn new( | |
| id: usize, | |
| label: impl Into<String>, | |
| kind: DeliveryKind, | |
| coord: (f64, f64), | |
| demand: i32, | |
| time_window: (i64, i64), | |
| service_duration: i64, | |
| ) -> Self { | |
| Self { | |
| id, | |
| label: label.into(), | |
| kind, | |
| lat: coord.0.into(), | |
| lng: coord.1.into(), | |
| demand, | |
| min_start_time: time_window.0, | |
| max_end_time: time_window.1, | |
| service_duration, | |
| } | |
| } | |
| /// Converts the serialized coordinates into the map library's checked type. | |
| pub fn coord(&self) -> Result<Coord, RoutingError> { | |
| Ok(Coord::try_new(self.lat.get(), self.lng.get())?) | |
| } | |
| } | |
| mod tests { | |
| use super::*; | |
| fn test_delivery_construction() { | |
| let fact = Delivery::new( | |
| 3, | |
| "Test stop", | |
| DeliveryKind::Business, | |
| (43.77, 11.25), | |
| 4, | |
| (9 * 3600, 17 * 3600), | |
| 20 * 60, | |
| ); | |
| assert_eq!(fact.id, 3); | |
| assert_eq!(fact.label, "Test stop"); | |
| assert_eq!(fact.kind, DeliveryKind::Business); | |
| } | |
| } | |