use std::collections::VecDeque;
use crate::policy::{BoardingPolicy, FifoBoardingPolicy};
use crate::stop::StopId;
use crate::vehicle::TransitVehicle;
use crate::PassengerId;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Waiter {
pub passenger: PassengerId,
pub destination: StopId,
pub arrived_at: f64,
}
#[derive(Debug, Clone, Default)]
pub struct Boarding {
queue: VecDeque<Waiter>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct BoardingResult {
pub boarded: u32,
pub passed_over: u32,
}
impl Boarding {
pub fn new() -> Self {
Self::default()
}
pub fn enqueue(&mut self, waiter: Waiter) {
self.queue.push_back(waiter);
}
pub fn len(&self) -> usize {
self.queue.len()
}
pub fn is_empty(&self) -> bool {
self.queue.is_empty()
}
pub fn board_vehicle(
&mut self,
vehicle: &mut TransitVehicle,
served_stops: &[StopId],
passenger_destinations: &mut Vec<StopId>,
) -> BoardingResult {
self.board_vehicle_with_policy(
vehicle,
served_stops,
passenger_destinations,
&FifoBoardingPolicy::default(),
)
}
pub fn board_vehicle_with_policy<P: BoardingPolicy>(
&mut self,
vehicle: &mut TransitVehicle,
served_stops: &[StopId],
passenger_destinations: &mut Vec<StopId>,
policy: &P,
) -> BoardingResult {
let mut boarded: u32 = 0;
let mut passed: u32 = 0;
let initial = self.queue.len();
for _ in 0..initial {
if !vehicle.has_room() {
break;
}
if policy
.max_boardings()
.is_some_and(|max_boardings| boarded >= max_boardings)
{
break;
}
let Some(w) = self.queue.pop_front() else {
break;
};
if policy.may_board(&w, vehicle, served_stops) {
vehicle.passengers.push(w.passenger);
passenger_destinations.push(w.destination);
boarded += 1;
} else {
self.queue.push_back(w);
passed += 1;
}
}
BoardingResult {
boarded,
passed_over: passed,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn boarding_matches_served_destinations() {
let mut q = Boarding::new();
q.enqueue(Waiter {
passenger: 10,
destination: 3,
arrived_at: 0.0,
});
q.enqueue(Waiter {
passenger: 11,
destination: 99, arrived_at: 0.0,
});
q.enqueue(Waiter {
passenger: 12,
destination: 4,
arrived_at: 0.0,
});
let mut v = TransitVehicle::idle(1, 1, 10);
let mut dests = Vec::new();
let r = q.board_vehicle(&mut v, &[3, 4, 5], &mut dests);
assert_eq!(r.boarded, 2);
assert_eq!(r.passed_over, 1);
assert_eq!(v.passengers, vec![10, 12]);
assert_eq!(dests, vec![3, 4]);
assert_eq!(q.len(), 1);
}
#[test]
fn full_vehicle_stops_boarding() {
let mut q = Boarding::new();
for i in 0..5 {
q.enqueue(Waiter {
passenger: i,
destination: 3,
arrived_at: 0.0,
});
}
let mut v = TransitVehicle::idle(1, 1, 2);
let mut dests = Vec::new();
let r = q.board_vehicle(&mut v, &[3], &mut dests);
assert_eq!(r.boarded, 2);
assert_eq!(q.len(), 3);
}
}