use crate::route::RouteId;
use crate::stop::StopId;
use crate::PassengerId;
pub type VehicleId = u64;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VehiclePhase {
Idle,
InTransit,
Dwelling,
Finished,
}
#[derive(Debug, Clone)]
pub struct TransitVehicle {
pub id: VehicleId,
pub route: RouteId,
pub current_stop: usize,
pub phase: VehiclePhase,
pub capacity: u32,
pub passengers: Vec<PassengerId>,
pub time_remaining: f64,
}
impl TransitVehicle {
pub fn idle(id: VehicleId, route: RouteId, capacity: u32) -> Self {
Self {
id,
route,
current_stop: 0,
phase: VehiclePhase::Idle,
capacity,
passengers: Vec::new(),
time_remaining: 0.0,
}
}
pub fn has_room(&self) -> bool {
(self.passengers.len() as u32) < self.capacity
}
pub fn free_capacity(&self) -> u32 {
self.capacity.saturating_sub(self.passengers.len() as u32)
}
pub fn add_passenger(&mut self, id: PassengerId) -> bool {
if self.has_room() {
self.passengers.push(id);
true
} else {
false
}
}
pub fn alight_at(&mut self, stop: StopId, destinations: &[StopId]) -> Vec<PassengerId> {
assert_eq!(self.passengers.len(), destinations.len());
let mut out = Vec::new();
let mut kept_dests = Vec::new();
let mut kept_pax = Vec::new();
for (p, d) in self.passengers.iter().zip(destinations.iter()) {
if *d == stop {
out.push(*p);
} else {
kept_pax.push(*p);
kept_dests.push(*d);
}
}
self.passengers = kept_pax;
let _ = kept_dests;
out
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn capacity_tracking() {
let mut v = TransitVehicle::idle(1, 42, 3);
assert!(v.add_passenger(10));
assert!(v.add_passenger(11));
assert!(v.add_passenger(12));
assert!(!v.add_passenger(13));
assert_eq!(v.free_capacity(), 0);
}
#[test]
fn alight_removes_targeted_passengers() {
let mut v = TransitVehicle::idle(1, 42, 10);
v.add_passenger(10);
v.add_passenger(11);
v.add_passenger(12);
let dests = vec![5, 7, 5];
let out = v.alight_at(5, &dests);
assert_eq!(out, vec![10, 12]);
assert_eq!(v.passengers, vec![11]);
}
}