use std::time::{Duration, Instant};
#[derive(Debug, Clone, Copy, Default)]
pub struct SolverTelemetry {
pub elapsed_ms: u64,
pub step_count: u64,
pub moves_evaluated: u64,
pub moves_accepted: u64,
pub score_calculations: u64,
pub moves_per_second: u64,
pub acceptance_rate: f64,
}
#[derive(Debug, Default)]
pub struct SolverStats {
start_time: Option<Instant>,
pub step_count: u64,
pub moves_evaluated: u64,
pub moves_accepted: u64,
pub score_calculations: u64,
}
impl SolverStats {
pub fn start(&mut self) {
self.start_time = Some(Instant::now());
}
pub fn elapsed(&self) -> Duration {
self.start_time.map(|t| t.elapsed()).unwrap_or_default()
}
pub fn record_move(&mut self, accepted: bool) {
self.moves_evaluated += 1;
if accepted {
self.moves_accepted += 1;
}
}
pub fn record_step(&mut self) {
self.step_count += 1;
}
pub fn record_score_calculation(&mut self) {
self.score_calculations += 1;
}
pub fn moves_per_second(&self) -> f64 {
let secs = self.elapsed().as_secs_f64();
if secs > 0.0 {
self.moves_evaluated as f64 / secs
} else {
0.0
}
}
pub fn acceptance_rate(&self) -> f64 {
if self.moves_evaluated == 0 {
0.0
} else {
self.moves_accepted as f64 / self.moves_evaluated as f64
}
}
pub fn snapshot(&self) -> SolverTelemetry {
SolverTelemetry {
elapsed_ms: self.elapsed().as_millis() as u64,
step_count: self.step_count,
moves_evaluated: self.moves_evaluated,
moves_accepted: self.moves_accepted,
score_calculations: self.score_calculations,
moves_per_second: self.moves_per_second() as u64,
acceptance_rate: self.acceptance_rate(),
}
}
}
#[derive(Debug)]
pub struct PhaseStats {
pub phase_index: usize,
pub phase_type: &'static str,
start_time: Instant,
pub step_count: u64,
pub moves_evaluated: u64,
pub moves_accepted: u64,
}
impl PhaseStats {
pub fn new(phase_index: usize, phase_type: &'static str) -> Self {
Self {
phase_index,
phase_type,
start_time: Instant::now(),
step_count: 0,
moves_evaluated: 0,
moves_accepted: 0,
}
}
pub fn elapsed(&self) -> Duration {
self.start_time.elapsed()
}
pub fn elapsed_ms(&self) -> u64 {
self.start_time.elapsed().as_millis() as u64
}
pub fn record_step(&mut self) {
self.step_count += 1;
}
pub fn record_move(&mut self, accepted: bool) {
self.moves_evaluated += 1;
if accepted {
self.moves_accepted += 1;
}
}
pub fn moves_per_second(&self) -> u64 {
let secs = self.elapsed().as_secs_f64();
if secs > 0.0 {
(self.moves_evaluated as f64 / secs) as u64
} else {
0
}
}
pub fn acceptance_rate(&self) -> f64 {
if self.moves_evaluated == 0 {
0.0
} else {
self.moves_accepted as f64 / self.moves_evaluated as f64
}
}
}