use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
pub struct Velocity {
pub last_1h: u32,
pub last_4h: u32,
pub last_24h: u32,
pub baseline_1h: Option<f64>,
}
impl Velocity {
#[must_use]
pub fn ratio_to_baseline(&self) -> Option<f64> {
self.baseline_1h
.filter(|b| *b > 0.0)
.map(|b| f64::from(self.last_1h) / b)
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
pub struct Deviation {
pub overrides_last_10: u32,
pub verdicts_last_10: u32,
pub overrides_last_50: u32,
pub verdicts_last_50: u32,
}
impl Deviation {
#[must_use]
pub fn rate_last_10(&self) -> f64 {
if self.verdicts_last_10 == 0 {
0.0
} else {
f64::from(self.overrides_last_10) / f64::from(self.verdicts_last_10)
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
pub struct Session {
pub active_duration_ms: u64,
pub longest_focus_ms: u64,
pub since_last_break_ms: u64,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
pub struct LossReaction {
pub median_last_10_ms: u64,
pub fastest_session_ms: u64,
pub baseline_ms: Option<u64>,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
pub struct ReEntry {
pub within_15m: u32,
pub within_30m: u32,
pub within_2h: u32,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
pub struct SleepProxy {
pub hours_since_rest_ended: Option<u32>,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct StateVector {
pub velocity: Velocity,
pub deviation: Deviation,
pub session: Session,
pub loss_reaction: LossReaction,
pub re_entry: ReEntry,
pub sleep_proxy: SleepProxy,
pub on_break: bool,
}