use std::fmt::Debug; use crate::time::Time; /// Governs how much a competitor's skill can drift between two time points. /// /// Generic over `T: Time` so seasonal or calendar-aware drift is expressible /// without going through `i64`. pub trait Drift: Copy + Debug + Send + Sync { /// Variance added to the skill prior for elapsed time `from -> to`. /// /// Called with `from <= to`; returning zero means no drift accumulates. fn variance_delta(&self, from: &T, to: &T) -> f64; /// Variance added for a pre-computed elapsed count (in the same units as /// `T::elapsed_to`). Used where the elapsed is already cached as `i64`. fn variance_for_elapsed(&self, elapsed: i64) -> f64; } /// Simple constant-per-unit-time drift. /// /// For `Time = i64`: variance added is `(to - from) * gamma^2`. /// For `Time = Untimed`: elapsed is always 0, so drift is always 0. #[derive(Clone, Copy, Debug)] pub struct ConstantDrift(pub f64); impl Drift for ConstantDrift { fn variance_delta(&self, from: &T, to: &T) -> f64 { let elapsed = from.elapsed_to(to).max(0) as f64; elapsed * self.0 * self.0 } fn variance_for_elapsed(&self, elapsed: i64) -> f64 { elapsed.max(0) as f64 * self.0 * self.0 } }