use crate::building::Building;
use crate::floors::Floors;
use crate::people::People;
use rand::{Rng, SeedableRng};
use rand::rngs::StdRng;
use rand::distributions::{Distribution, Uniform, Bernoulli};
pub trait ElevatorController {
fn get_building(&mut self) -> &Building;
fn get_building_mut(&mut self) -> &mut Building;
fn clone_building(&mut self) -> Building;
fn can_be_upgraded(&self) -> bool;
fn upgrade(&mut self, incrementation: f64);
fn update_elevators(&mut self);
}
pub struct RandomController {
pub building: Building,
num_floors: usize,
floors_to: Vec<Option<usize>>,
dst_to: Uniform<usize>,
p_rational: f64,
dst_rational: Bernoulli,
upgradable: bool,
rng: StdRng
}
impl RandomController {
pub fn from(building: Building, rng: StdRng, p_rational: f64) -> RandomController {
let num_floors: usize = building.floors.len();
let num_elevators: usize = building.elevators.len();
let floors_to: Vec<Option<usize>> = {
let mut tmp_floors_to: Vec<Option<usize>> = Vec::new();
for _ in 0..num_elevators {
tmp_floors_to.push(None);
}
tmp_floors_to
};
let dst_to: Uniform<usize> = Uniform::new(0_usize, num_floors);
RandomController {
building: building,
num_floors: num_floors,
floors_to: floors_to,
dst_to: dst_to,
p_rational: p_rational,
dst_rational: Bernoulli::new(p_rational).unwrap(),
upgradable: true,
rng: rng
}
}
pub fn from_building(building: Building) -> RandomController {
let rng = StdRng::from_seed(rand::thread_rng().gen());
let p_rational = 0.0_f64;
RandomController::from(building, rng, p_rational)
}
pub fn update_floors_to(&mut self) {
while self.building.elevators.len() > self.floors_to.len() {
self.floors_to.push(None);
}
if self.building.floors.len() != self.num_floors {
self.num_floors = self.building.floors.len();
self.dst_to = Uniform::new(0, self.num_floors);
}
for (i, elevator) in self.building.elevators.iter().enumerate() {
match self.floors_to[i] {
Some(_) => {},
None => {
if self.dst_rational.sample(&mut self.rng) {
if elevator.stopped {
let (nearest_dest_floor, min_dest_floor_dist): (usize, usize) = elevator.get_nearest_dest_floor();
if min_dest_floor_dist != 0_usize {
self.floors_to[i] = Some(nearest_dest_floor);
continue;
}
let (nearest_wait_floor, min_wait_floor_dist): (usize, usize) = self.building.get_nearest_wait_floor(elevator.floor_on);
if min_wait_floor_dist != 0_usize {
self.floors_to[i] = Some(nearest_wait_floor);
continue;
}
}
} else {
self.floors_to[i] = Some(self.dst_to.sample(&mut self.rng));
continue;
}
self.floors_to[i] = Some(elevator.floor_on);
}
}
}
}
pub fn clear_floors_to(&mut self) {
for (i, elevator) in self.building.elevators.iter().enumerate() {
let dest_floor = self.floors_to[i].unwrap();
if dest_floor == elevator.floor_on {
self.floors_to[i] = None;
}
}
}
}
impl ElevatorController for RandomController {
fn get_building(&mut self) -> &Building {
&self.building
}
fn get_building_mut(&mut self) -> &mut Building {
&mut self.building
}
fn clone_building(&mut self) -> Building {
self.building.clone()
}
fn can_be_upgraded(&self) -> bool {
if self.p_rational >= 1.0_f64 {
return false;
}
self.upgradable
}
fn upgrade(&mut self, incrementation: f64) {
let mut new_p_rational: f64 = self.p_rational + incrementation;
if new_p_rational > 1.0_f64 {
new_p_rational = 1.0_f64;
}
self.p_rational = new_p_rational;
self.dst_rational = Bernoulli::new(self.p_rational).unwrap();
}
fn update_elevators(&mut self) {
self.update_floors_to();
for (i, floor_to) in self.floors_to.iter().enumerate() {
let dest_floor: usize = floor_to.unwrap();
self.building.elevators[i].update_direction(dest_floor);
let _new_floor_index = self.building.elevators[i].update_floor();
}
self.clear_floors_to();
}
}
pub struct NearestController {
pub building: Building,
upgradable: bool
}
impl NearestController {
pub fn from(building: Building) -> NearestController {
NearestController {
building: building,
upgradable: false
}
}
pub fn from_building(building: Building) -> NearestController {
NearestController {
building: building,
upgradable: false
}
}
}
impl ElevatorController for NearestController {
fn get_building(&mut self) -> &Building {
&self.building
}
fn get_building_mut(&mut self) -> &mut Building {
&mut self.building
}
fn clone_building(&mut self) -> Building {
self.building.clone()
}
fn can_be_upgraded(&self) -> bool {
self.upgradable
}
fn upgrade(&mut self, _incrementation: f64) {}
fn update_elevators(&mut self) {
let mut elevator_decisions: Vec<usize> = Vec::new();
for elevator in self.building.elevators.iter() {
if elevator.stopped {
let (nearest_dest_floor, min_dest_floor_dist): (usize, usize) = elevator.get_nearest_dest_floor();
if min_dest_floor_dist != 0_usize {
elevator_decisions.push(nearest_dest_floor);
continue;
}
let (nearest_wait_floor, min_wait_floor_dist): (usize, usize) = self.building.get_nearest_wait_floor(elevator.floor_on);
if min_wait_floor_dist != 0_usize {
elevator_decisions.push(nearest_wait_floor);
continue;
}
} else {
if !elevator.moving_up && elevator.floor_on == 0_usize {
elevator_decisions.push(elevator.floor_on);
continue;
}
if elevator.moving_up && elevator.floor_on == (self.building.floors.len() - 1_usize) {
elevator_decisions.push(elevator.floor_on);
continue;
}
if elevator.are_people_going_to_floor(elevator.floor_on) {
elevator_decisions.push(elevator.floor_on);
continue;
}
if self.building.are_people_waiting_on_floor(elevator.floor_on) {
elevator_decisions.push(elevator.floor_on);
continue;
}
}
elevator_decisions.push(elevator.floor_on);
}
for (i, decision) in elevator_decisions.iter().enumerate() {
self.building.elevators[i].update_direction(*decision);
let _new_floor_index = self.building.elevators[i].update_floor();
}
}
}