vrp_core/models/common/
domain.rs1#[cfg(test)]
2#[path = "../../../tests/unit/models/common/domain_test.rs"]
3mod domain_test;
4
5use crate::models::common::{Duration, Timestamp};
6use rosomaxa::prelude::Float;
7use std::hash::{Hash, Hasher};
8
9pub type Location = usize;
11
12#[derive(Clone, Debug)]
14pub struct Profile {
15 pub index: usize,
17 pub scale: Float,
19}
20
21impl Profile {
22 pub fn new(index: usize, scale: Option<Float>) -> Profile {
24 Self { index, scale: scale.unwrap_or(1.) }
25 }
26}
27
28impl Default for Profile {
29 fn default() -> Self {
30 Self { index: 0, scale: 1. }
31 }
32}
33
34pub type Cost = Float;
36
37#[derive(Clone, Debug, PartialEq)]
39pub struct TimeWindow {
40 pub start: Timestamp,
42 pub end: Timestamp,
44}
45
46#[derive(Clone, Debug, PartialEq)]
48pub struct TimeOffset {
49 pub start: Timestamp,
51 pub end: Timestamp,
53}
54
55#[derive(Clone, Debug)]
57pub enum TimeSpan {
58 Window(TimeWindow),
60 Offset(TimeOffset),
62}
63
64#[derive(Clone, Debug, Default, PartialEq)]
66pub struct TimeInterval {
67 pub earliest: Option<Timestamp>,
69 pub latest: Option<Timestamp>,
71}
72
73impl TimeWindow {
74 pub fn new(start: Timestamp, end: Timestamp) -> Self {
76 Self { start, end }
77 }
78
79 pub fn max() -> Self {
81 Self { start: 0., end: Float::MAX }
82 }
83
84 pub fn intersects(&self, other: &Self) -> bool {
86 self.start <= other.end && other.start <= self.end
87 }
88
89 pub fn intersects_exclusive(&self, other: &Self) -> bool {
91 self.start < other.end && other.start < self.end
92 }
93
94 pub fn contains(&self, time: Timestamp) -> bool {
96 time >= self.start && time <= self.end
97 }
98
99 pub fn distance(&self, other: &Self) -> Timestamp {
101 if self.intersects(other) {
102 0.
103 } else {
104 if self.start > other.start {
106 self.start - other.end
107 } else {
108 other.start - self.end
110 }
111 }
112 }
113
114 pub fn overlapping(&self, other: &Self) -> Option<TimeWindow> {
116 if self.intersects(other) {
117 let start = self.start.max(other.start);
118 let end = self.end.min(other.end);
119
120 Some(TimeWindow::new(start, end))
121 } else {
122 None
123 }
124 }
125
126 pub fn duration(&self) -> Duration {
128 self.end - self.start
129 }
130}
131
132impl Eq for TimeWindow {}
133
134impl Hash for TimeWindow {
135 fn hash<H: Hasher>(&self, state: &mut H) {
136 let start = self.start.to_bits() as i64;
137 let end = self.end.to_bits() as i64;
138
139 start.hash(state);
140 end.hash(state);
141 }
142}
143
144impl TimeOffset {
145 pub fn new(start: Timestamp, end: Timestamp) -> Self {
147 Self { start, end }
148 }
149}
150
151impl TimeSpan {
152 pub fn to_time_window(&self, date: Timestamp) -> TimeWindow {
154 match &self {
155 TimeSpan::Window(window) => window.clone(),
156 TimeSpan::Offset(offset) => TimeWindow::new(date + offset.start, date + offset.end),
157 }
158 }
159
160 pub fn intersects(&self, date: Timestamp, other: &TimeWindow) -> bool {
162 self.to_time_window(date).intersects(other)
163 }
164
165 pub fn as_time_window(&self) -> Option<TimeWindow> {
167 match &self {
168 TimeSpan::Window(window) => Some(window.clone()),
169 _ => None,
170 }
171 }
172}
173
174impl TimeInterval {
175 pub fn to_time_window(&self) -> TimeWindow {
177 TimeWindow { start: self.earliest.unwrap_or(0.), end: self.latest.unwrap_or(Float::MAX) }
178 }
179}
180
181#[derive(Clone, Debug, PartialEq)]
183pub struct Schedule {
184 pub arrival: Timestamp,
186 pub departure: Timestamp,
188}
189
190impl Schedule {
191 pub fn new(arrival: Timestamp, departure: Timestamp) -> Self {
193 Self { arrival, departure }
194 }
195}
196
197impl Eq for Schedule {}
198
199impl Hash for TimeInterval {
200 fn hash<H: Hasher>(&self, state: &mut H) {
201 let earliest = self.earliest.unwrap_or(0.).to_bits() as i64;
202 let latest = self.latest.unwrap_or(Float::MAX).to_bits() as i64;
203
204 earliest.hash(state);
205 latest.hash(state);
206 }
207}
208
209impl Eq for TimeInterval {}