use std::time::Duration;
use crate::reservoir::DRAIN;
use crate::shimmer::QUANTA;
use crate::{Intensity, Spell};
#[derive(Clone, Copy)]
enum Work {
Busy { rate: f64 },
Wait { lump: f64 },
Idle,
}
struct Segment {
caption: &'static str,
length: f64,
work: Work,
}
static CYCLE: [Segment; 5] = [
Segment {
caption: "Working",
length: 2.5,
work: Work::Busy { rate: 60.0 },
},
Segment {
caption: "Tracing shimmer cadence",
length: 3.5,
work: Work::Busy { rate: 80.0 },
},
Segment {
caption: "Drafting the fix",
length: 4.0,
work: Work::Busy { rate: 50.0 },
},
Segment {
caption: "Waiting for background terminal",
length: 7.0,
work: Work::Wait { lump: 600.0 },
},
Segment {
caption: "Finished",
length: 3.0,
work: Work::Idle,
},
];
fn length() -> f64 {
CYCLE.iter().map(|segment| segment.length).sum()
}
fn segment(t: f64) -> &'static Segment {
let mut end = 0.0;
for segment in &CYCLE[..CYCLE.len() - 1] {
end += segment.length;
if t < end {
return segment;
}
}
&CYCLE[CYCLE.len() - 1]
}
fn inflow(t: f64) -> f64 {
let length = length();
let echoes = 1.0 / -(-length / DRAIN).exp_m1();
let mut end = 0.0;
let mut drained = 0.0;
for segment in &CYCLE {
end += segment.length;
if let Work::Wait { lump } = segment.work {
drained += lump / DRAIN * (-(t - end).rem_euclid(length) / DRAIN).exp() * echoes;
}
}
match segment(t).work {
Work::Busy { rate } => rate + drained,
Work::Wait { .. } | Work::Idle => drained,
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Cue {
pub spell: Spell,
pub caption: &'static str,
pub intensity: Intensity,
}
pub fn cue(at: Duration) -> Cue {
let t = at.as_secs_f64() % length();
let segment = segment(t);
Cue {
spell: match segment.work {
Work::Busy { .. } => Spell::Busy,
Work::Wait { .. } => Spell::Wait,
Work::Idle => Spell::Idle,
},
caption: segment.caption,
intensity: Intensity::new(inflow(t) / QUANTA),
}
}