use crate::models::common::Timestamp;
use crate::utils::compare_floats;
use hashbrown::HashMap;
use std::any::Any;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use std::sync::Arc;
pub type Location = usize;
pub type Profile = i32;
pub type Cost = f64;
#[derive(Clone, Debug)]
pub struct TimeWindow {
pub start: Timestamp,
pub end: Timestamp,
}
#[derive(Clone, Debug)]
pub struct TimeOffset {
pub start: Timestamp,
pub end: Timestamp,
}
#[derive(Clone, Debug)]
pub enum TimeSpan {
Window(TimeWindow),
Offset(TimeOffset),
}
#[derive(Clone, Debug)]
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: std::f64::MAX }
}
pub fn intersects(&self, other: &Self) -> bool {
self.start <= other.end && other.start <= self.end
}
pub fn intersects_all(&self, others: &[Self]) -> bool {
others.iter().all(|other| other.intersects(self))
}
pub fn intersects_any(&self, others: &[Self]) -> bool {
others.iter().any(|other| other.intersects(self))
}
}
impl PartialEq<TimeWindow> for TimeWindow {
fn eq(&self, other: &TimeWindow) -> bool {
compare_floats(self.start, other.start) == Ordering::Equal
&& compare_floats(self.end, other.end) == Ordering::Equal
}
}
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 Default for TimeInterval {
fn default() -> Self {
Self { earliest: None, latest: None }
}
}
impl TimeInterval {
pub fn to_time_window(&self) -> TimeWindow {
TimeWindow { start: self.earliest.unwrap_or(0.), end: self.latest.unwrap_or(std::f64::MAX) }
}
}
#[derive(Clone, Debug)]
pub struct Schedule {
pub arrival: Timestamp,
pub departure: Timestamp,
}
impl Schedule {
pub fn new(arrival: Timestamp, departure: Timestamp) -> Self {
Self { arrival, departure }
}
}
impl PartialEq<Schedule> for Schedule {
fn eq(&self, other: &Schedule) -> bool {
compare_floats(self.arrival, other.arrival) == Ordering::Equal
&& compare_floats(self.departure, other.departure) == Ordering::Equal
}
}
impl Eq for Schedule {}
pub type Dimensions = HashMap<String, Arc<dyn Any + Send + Sync>>;
pub trait ValueDimension {
fn get_value<T: 'static>(&self, key: &str) -> Option<&T>;
fn set_value<T: 'static + Sync + Send>(&mut self, key: &str, value: T);
}
impl ValueDimension for Dimensions {
fn get_value<T: 'static>(&self, key: &str) -> Option<&T> {
self.get(key).and_then(|any| any.downcast_ref::<T>())
}
fn set_value<T: 'static + Sync + Send>(&mut self, key: &str, value: T) {
self.insert(key.to_owned(), Arc::new(value));
}
}
pub trait IdDimension {
fn set_id(&mut self, id: &str) -> &mut Self;
fn get_id(&self) -> Option<&String>;
}
impl IdDimension for Dimensions {
fn set_id(&mut self, id: &str) -> &mut Self {
self.set_value("id", id.to_string());
self
}
fn get_id(&self) -> Option<&String> {
self.get_value("id")
}
}
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(std::f64::MAX).to_bits() as i64;
earliest.hash(state);
latest.hash(state);
}
}
impl Eq for TimeInterval {}
impl PartialEq for TimeInterval {
fn eq(&self, other: &Self) -> bool {
self.earliest == other.earliest && self.latest == other.latest
}
}