Required for T3 rayon-based parallelism. Affected traits: - Time (+ Send + Sync + 'static) - Drift<T> (+ Send + Sync) - Observer<T> (+ Send + Sync) - Factor (+ Send + Sync) - Schedule (+ Send + Sync) All built-in impls (i64, Untimed, ConstantDrift, NullObserver, EpsilonOrMax, TeamSumFactor, RankDiffFactor, TruncFactor, BuiltinFactor) naturally satisfy these bounds via auto-derive. Minor breaking change: downstream custom impls that aren't already thread-safe will need to add the bounds. Part of T3 of docs/superpowers/specs/2026-04-23-trueskill-engine-redesign-design.md.
48 lines
1.6 KiB
Rust
48 lines
1.6 KiB
Rust
//! Observer trait for progress reporting during convergence.
|
|
//!
|
|
//! Replaces the old `verbose: bool` + `println!` path. Callers wire in any
|
|
//! observer that implements the trait; default methods are no-ops so users
|
|
//! override only what they need.
|
|
|
|
use crate::time::Time;
|
|
|
|
/// Receives progress callbacks during `History::converge`.
|
|
///
|
|
/// All methods have default no-op implementations; implement only what's
|
|
/// interesting.
|
|
pub trait Observer<T: Time>: Send + Sync {
|
|
/// Called after each convergence iteration across the whole history.
|
|
fn on_iteration_end(&self, _iter: usize, _max_step: (f64, f64)) {}
|
|
|
|
/// Called after each time slice is processed within an iteration.
|
|
fn on_batch_processed(&self, _time: &T, _slice_idx: usize, _n_events: usize) {}
|
|
|
|
/// Called once when convergence completes (or max iters is reached).
|
|
fn on_converged(&self, _iters: usize, _final_step: (f64, f64), _converged: bool) {}
|
|
}
|
|
|
|
/// ZST no-op observer; the default when none is configured.
|
|
#[derive(Copy, Clone, Debug, Default)]
|
|
pub struct NullObserver;
|
|
|
|
impl<T: Time> Observer<T> for NullObserver {}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn null_observer_compiles_for_i64() {
|
|
let o = NullObserver;
|
|
<NullObserver as Observer<i64>>::on_iteration_end(&o, 1, (0.0, 0.0));
|
|
<NullObserver as Observer<i64>>::on_converged(&o, 5, (1e-6, 1e-6), true);
|
|
}
|
|
|
|
#[test]
|
|
fn null_observer_compiles_for_untimed() {
|
|
use crate::Untimed;
|
|
let o = NullObserver;
|
|
<NullObserver as Observer<Untimed>>::on_iteration_end(&o, 1, (0.0, 0.0));
|
|
}
|
|
}
|