extern crate itertools;
use itertools::Itertools;
use super::Scenario;
use serde::Deserialize;
use std::path::PathBuf;
#[derive(Clone)]
pub struct CustomScenario {
points: Vec<Point>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct Point {
time: usize,
rate: f32,
}
impl Scenario for CustomScenario {
fn rate(&self, time_elasped: std::time::Duration) -> f32 {
let time = time_elasped.as_millis() as usize;
for (p1, p2) in self.points.iter().tuple_windows() {
if p1.time <= time && p2.time >= time {
return CustomScenario::lerp(p1, p2, time);
}
}
0.
}
fn duration(&self) -> u128 {
match self.points.last() {
Some(p) => p.time as u128,
None => 0,
}
}
fn max_rate(&self) -> f32 {
let mut max = 0.;
for p in self.points.iter() {
if p.rate > max {
max = p.rate;
}
}
max
}
}
impl CustomScenario {
pub fn new(mut points: Vec<Point>) -> Self {
points.sort_by(|a, b| a.time.partial_cmp(&b.time).unwrap());
CustomScenario { points }
}
pub fn from_csv(filename: PathBuf) -> Self {
let mut points = Vec::new();
let mut rdr = csv::Reader::from_path(filename).unwrap();
for result in rdr.deserialize() {
let p: Point = result.unwrap();
points.push(p);
}
points.sort_by(|a, b| a.time.partial_cmp(&b.time).unwrap());
CustomScenario { points }
}
fn lerp(p1: &Point, p2: &Point, time: usize) -> f32 {
let dt = (p2.time - p1.time) * 1000;
let tau = (time - p1.time) as f32 / dt as f32;
p1.rate + (p2.rate * tau)
}
}