sorting_race/services/
snapshot.rs1use crate::models::traits::{Sorter, Telemetry};
4use crate::models::metrics::MetricsSnapshot;
5use std::time::SystemTime;
6
7#[derive(Debug, Clone)]
9pub struct RaceSnapshot {
10 pub timestamp: SystemTime,
12 pub algorithm_snapshots: Vec<AlgorithmSnapshot>,
14 pub step: usize,
16 pub race_complete: bool,
18}
19
20#[derive(Debug, Clone)]
22pub struct AlgorithmSnapshot {
23 pub name: String,
25 pub array_state: Vec<i32>,
27 pub telemetry: Telemetry,
29 pub is_complete: bool,
31 pub metrics: MetricsSnapshot,
33}
34
35#[derive(Debug, Default)]
37pub struct SnapshotService {
38 snapshots: Vec<RaceSnapshot>,
39 max_snapshots: usize,
40}
41
42impl SnapshotService {
43 pub fn new(max_snapshots: usize) -> Self {
45 Self {
46 snapshots: Vec::new(),
47 max_snapshots: max_snapshots.max(1),
48 }
49 }
50
51 pub fn take_snapshot(&mut self, algorithms: &[Box<dyn Sorter>], step: usize) -> &RaceSnapshot {
53 let race_complete = algorithms.iter().all(|alg| alg.is_complete());
54
55 let algorithm_snapshots = algorithms
56 .iter()
57 .map(|algorithm| {
58 let telemetry = algorithm.get_telemetry();
59 let metrics = crate::models::metrics::Metrics {
60 comparisons: telemetry.total_comparisons,
61 moves: telemetry.total_moves,
62 execution_time_us: 0, peak_memory_bytes: telemetry.memory_peak,
64 current_memory_bytes: telemetry.memory_current,
65 steps: step,
66 array_accesses: telemetry.total_comparisons + telemetry.total_moves,
67 recursive_calls: 0, };
69
70 AlgorithmSnapshot {
71 name: algorithm.name().to_string(),
72 array_state: algorithm.get_array().to_vec(),
73 telemetry,
74 is_complete: algorithm.is_complete(),
75 metrics: MetricsSnapshot::new(
76 metrics,
77 SystemTime::now()
78 .duration_since(SystemTime::UNIX_EPOCH)
79 .unwrap()
80 .as_micros() as u64,
81 algorithm.name().to_string(),
82 ),
83 }
84 })
85 .collect();
86
87 let snapshot = RaceSnapshot {
88 timestamp: SystemTime::now(),
89 algorithm_snapshots,
90 step,
91 race_complete,
92 };
93
94 self.snapshots.push(snapshot);
96 if self.snapshots.len() > self.max_snapshots {
97 self.snapshots.remove(0);
98 }
99
100 self.snapshots.last().unwrap()
101 }
102
103 pub fn get_snapshots(&self) -> &[RaceSnapshot] {
105 &self.snapshots
106 }
107
108 pub fn get_latest_snapshot(&self) -> Option<&RaceSnapshot> {
110 self.snapshots.last()
111 }
112
113 pub fn get_snapshot(&self, index: usize) -> Option<&RaceSnapshot> {
115 self.snapshots.get(index)
116 }
117
118 pub fn clear(&mut self) {
120 self.snapshots.clear();
121 }
122
123 pub fn len(&self) -> usize {
125 self.snapshots.len()
126 }
127
128 pub fn is_empty(&self) -> bool {
130 self.snapshots.is_empty()
131 }
132
133 pub fn set_max_snapshots(&mut self, max: usize) {
135 self.max_snapshots = max.max(1);
136
137 while self.snapshots.len() > self.max_snapshots {
139 self.snapshots.remove(0);
140 }
141 }
142
143 pub fn get_max_snapshots(&self) -> usize {
145 self.max_snapshots
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152 use crate::services::sorters::bubble::BubbleSort;
153
154 #[test]
155 fn test_snapshot_service_creation() {
156 let service = SnapshotService::new(10);
157 assert_eq!(service.len(), 0);
158 assert!(service.is_empty());
159 assert_eq!(service.get_max_snapshots(), 10);
160 }
161
162 #[test]
163 fn test_take_snapshot() {
164 let mut service = SnapshotService::new(5);
165 let mut bubble = BubbleSort::new();
166 bubble.reset(vec![3, 1, 2]);
167
168 let algorithms: Vec<Box<dyn Sorter>> = vec![Box::new(bubble)];
169
170 let snapshot = service.take_snapshot(&algorithms, 1);
171 assert_eq!(snapshot.step, 1);
172 assert_eq!(snapshot.algorithm_snapshots.len(), 1);
173 assert_eq!(service.len(), 1);
174 }
175
176 #[test]
177 fn test_max_snapshots_limit() {
178 let mut service = SnapshotService::new(3);
179 let bubble = BubbleSort::new();
180 let algorithms: Vec<Box<dyn Sorter>> = vec![Box::new(bubble)];
181
182 for i in 0..5 {
184 service.take_snapshot(&algorithms, i);
185 }
186
187 assert_eq!(service.len(), 3); let snapshots = service.get_snapshots();
191 assert_eq!(snapshots[0].step, 2);
192 assert_eq!(snapshots[1].step, 3);
193 assert_eq!(snapshots[2].step, 4);
194 }
195}