#[cfg(test)]
#[path = "../../../tests/unit/models/common/domain_test.rs"]
mod domain_test;
use crate::models::common::{Duration, Timestamp};
use rosomaxa::prelude::Float;
use std::hash::{Hash, Hasher};
pub type Location = usize;
#[derive(Clone, Debug)]
pub struct Profile {
pub index: usize,
pub scale: Float,
}
impl Profile {
pub fn new(index: usize, scale: Option<Float>) -> Profile {
Self { index, scale: scale.unwrap_or(1.) }
}
}
impl Default for Profile {
fn default() -> Self {
Self { index: 0, scale: 1. }
}
}
pub type Cost = Float;
#[derive(Clone, Debug, PartialEq)]
pub struct TimeWindow {
pub start: Timestamp,
pub end: Timestamp,
}
#[derive(Clone, Debug, PartialEq)]
pub struct TimeOffset {
pub start: Timestamp,
pub end: Timestamp,
}
#[derive(Clone, Debug)]
pub enum TimeSpan {
Window(TimeWindow),
Offset(TimeOffset),
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct TimeInterval {
pub earliest: Option<Timestamp>,
pub latest: Option<Timestamp>,
}
impl TimeWindow {
pub fn new(start: Timestamp, end: Timestamp) -> Self {
Self { start, end }
}
pub fn max() -> Self {
Self { start: 0., end: Float::MAX }
}
pub fn intersects(&self, other: &Self) -> bool {
self.start <= other.end && other.start <= self.end
}
pub fn intersects_exclusive(&self, other: &Self) -> bool {
self.start < other.end && other.start < self.end
}
pub fn contains(&self, time: Timestamp) -> bool {
time >= self.start && time <= self.end
}
pub fn distance(&self, other: &Self) -> Timestamp {
if self.intersects(other) {
0.
} else {
if self.start > other.start {
self.start - other.end
} else {
other.start - self.end
}
}
}
pub fn overlapping(&self, other: &Self) -> Option<TimeWindow> {
if self.intersects(other) {
let start = self.start.max(other.start);
let end = self.end.min(other.end);
Some(TimeWindow::new(start, end))
} else {
None
}
}
pub fn duration(&self) -> Duration {
self.end - self.start
}
}
impl Eq for TimeWindow {}
impl Hash for TimeWindow {
fn hash<H: Hasher>(&self, state: &mut H) {
let start = self.start.to_bits() as i64;
let end = self.end.to_bits() as i64;
start.hash(state);
end.hash(state);
}
}
impl TimeOffset {
pub fn new(start: Timestamp, end: Timestamp) -> Self {
Self { start, end }
}
}
impl TimeSpan {
pub fn to_time_window(&self, date: Timestamp) -> TimeWindow {
match &self {
TimeSpan::Window(window) => window.clone(),
TimeSpan::Offset(offset) => TimeWindow::new(date + offset.start, date + offset.end),
}
}
pub fn intersects(&self, date: Timestamp, other: &TimeWindow) -> bool {
self.to_time_window(date).intersects(other)
}
pub fn as_time_window(&self) -> Option<TimeWindow> {
match &self {
TimeSpan::Window(window) => Some(window.clone()),
_ => None,
}
}
}
impl TimeInterval {
pub fn to_time_window(&self) -> TimeWindow {
TimeWindow { start: self.earliest.unwrap_or(0.), end: self.latest.unwrap_or(Float::MAX) }
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Schedule {
pub arrival: Timestamp,
pub departure: Timestamp,
}
impl Schedule {
pub fn new(arrival: Timestamp, departure: Timestamp) -> Self {
Self { arrival, departure }
}
}
impl Eq for Schedule {}
impl Hash for TimeInterval {
fn hash<H: Hasher>(&self, state: &mut H) {
let earliest = self.earliest.unwrap_or(0.).to_bits() as i64;
let latest = self.latest.unwrap_or(Float::MAX).to_bits() as i64;
earliest.hash(state);
latest.hash(state);
}
}
impl Eq for TimeInterval {}