use std::fmt;
use rand::Rng;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BehaviourType {
Undefined,
Block,
Aggressive,
Cooperative,
LimitSpeedByTrip,
}
impl BehaviourType {
pub fn random_vehicle_behaviour_type(ratio_a: f64, ratio_b: f64) -> Self {
let mut rng = rand::rng();
let random_number = rng.random_range(0.0..(ratio_a + ratio_b));
if random_number < ratio_a {
BehaviourType::Aggressive
} else {
BehaviourType::Cooperative
}
}
}
impl fmt::Display for BehaviourType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let as_str = match self {
BehaviourType::Undefined => "undefined",
BehaviourType::Block => "block",
BehaviourType::Aggressive => "aggressive",
BehaviourType::Cooperative => "cooperative",
BehaviourType::LimitSpeedByTrip => "limit_speed",
};
write!(f, "{}", as_str)
}
}
#[derive(Debug, Clone, Copy)]
pub struct BehaviourParameters {
slowdown_factor: f64,
speed_limit: i32,
aggressive_level: f64,
min_safe_distance: i32,
}
impl BehaviourParameters {
pub fn from_behaviour_type(behaviour: BehaviourType) -> Self {
match behaviour {
BehaviourType::Block => Self::new(1.0, 0, 1.0, 0),
BehaviourType::Aggressive => Self::new(0.1, 5, 0.9, 0),
BehaviourType::Cooperative => Self::new(0.5, 4, 0.0, 1),
BehaviourType::LimitSpeedByTrip => Self::new(0.7, 3, 0.1, 1),
BehaviourType::Undefined => Self::new(0.5, 2, 0.5, 0),
}
}
pub fn new(slowdown_factor: f64, speed_limit: i32, aggressive_level: f64, min_safe_distance: i32) -> Self {
Self {
slowdown_factor,
speed_limit,
aggressive_level,
min_safe_distance,
}
}
pub fn speed_limit(&self) -> i32 {
self.speed_limit
}
pub fn slowdown_factor(&self) -> f64 {
self.slowdown_factor
}
pub fn min_safe_distance(&self) -> i32 {
self.min_safe_distance
}
pub fn aggressive_level(&self) -> f64 {
self.aggressive_level
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_behaviour_display() {
assert_eq!(format!("{}", BehaviourType::Aggressive), "aggressive");
assert_eq!(format!("{}", BehaviourType::Cooperative), "cooperative");
}
#[test]
fn test_behaviour_parameters_from() {
let params = BehaviourParameters::from_behaviour_type(BehaviourType::Aggressive);
assert_eq!(params.slowdown_factor(), 0.1);
assert_eq!(params.speed_limit(), 5);
assert_eq!(params.aggressive_level(), 0.9);
assert_eq!(params.min_safe_distance(), 0);
}
#[test]
fn test_random_vehicle_behaviour_type() {
let ratio_a = 0.7;
let ratio_b = 0.3;
for _ in 0..100 {
let random_behaviour: BehaviourType = BehaviourType::random_vehicle_behaviour_type(ratio_a, ratio_b);
assert!(
random_behaviour == BehaviourType::Aggressive || random_behaviour == BehaviourType::Cooperative,
"Random behaviour must be Aggressive or Cooperative. Other have not been implemented yet, got: {:?}",
random_behaviour
);
}
}
}