sorting_race/services/sorters/
bubble.rs1use crate::models::traits::{Sorter, StepResult, Telemetry, Markers};
4use std::any::Any;
5
6#[derive(Debug)]
8pub struct BubbleSort {
9 data: Vec<i32>,
10 current_pass: usize,
11 current_pos: usize,
12 comparisons: u64,
13 moves: u64,
14 complete: bool,
15}
16
17impl BubbleSort {
18 pub fn new() -> Self {
20 Self {
21 data: Vec::new(),
22 current_pass: 0,
23 current_pos: 0,
24 comparisons: 0,
25 moves: 0,
26 complete: false,
27 }
28 }
29}
30
31impl Default for BubbleSort {
32 fn default() -> Self {
33 Self::new()
34 }
35}
36
37impl Sorter for BubbleSort {
38 fn step(&mut self, budget: usize) -> StepResult {
39 if self.complete || self.data.len() <= 1 {
40 return StepResult {
41 comparisons_used: 0,
42 moves_made: 0,
43 continued: false,
44 };
45 }
46
47 let mut comparisons_used = 0;
48 let mut moves_made = 0;
49 let n = self.data.len();
50
51 while comparisons_used < budget {
52 if self.current_pos < n - 1 - self.current_pass {
53 comparisons_used += 1;
55 self.comparisons += 1;
56
57 if self.data[self.current_pos] > self.data[self.current_pos + 1] {
58 self.data.swap(self.current_pos, self.current_pos + 1);
60 moves_made += 1;
61 self.moves += 1;
62 }
63
64 self.current_pos += 1;
65 } else {
66 self.current_pass += 1;
68 self.current_pos = 0;
69
70 if self.current_pass >= n - 1 {
71 self.complete = true;
72 break;
73 }
74 }
75 }
76
77 StepResult {
78 comparisons_used,
79 moves_made,
80 continued: !self.complete,
81 }
82 }
83
84 fn is_complete(&self) -> bool {
85 self.complete
86 }
87
88 fn get_telemetry(&self) -> Telemetry {
89 let mut markers = Markers::default();
90
91 if !self.complete && self.current_pos < self.data.len() {
92 markers.cursors = vec![self.current_pos];
93 if self.current_pos + 1 < self.data.len() {
94 markers.cursors.push(self.current_pos + 1);
95 }
96 }
97
98 Telemetry {
99 total_comparisons: self.comparisons,
100 total_moves: self.moves,
101 memory_current: self.get_memory_usage(),
102 memory_peak: self.get_memory_usage(),
103 highlights: markers.cursors.clone(),
104 markers,
105 status_text: if self.complete {
106 "Completed".to_string()
107 } else {
108 format!("Pass {}, Position {}", self.current_pass + 1, self.current_pos)
109 },
110 progress_hint: if self.data.len() <= 1 {
111 1.0
112 } else {
113 let progress = (self.current_pass as f32) / (self.data.len() - 1) as f32;
114 progress.min(1.0).max(0.0) },
116 }
117 }
118
119 fn reset(&mut self, data: Vec<i32>) {
120 self.data = data;
121 self.current_pass = 0;
122 self.current_pos = 0;
123 self.comparisons = 0;
124 self.moves = 0;
125 self.complete = self.data.len() <= 1;
126 }
127
128 fn name(&self) -> &str {
129 "Bubble Sort"
130 }
131
132 fn get_array(&self) -> &[i32] {
133 &self.data
134 }
135
136 fn get_memory_usage(&self) -> usize {
137 self.data.len() * std::mem::size_of::<i32>()
139 }
140
141 fn as_any(&self) -> &dyn Any {
142 self
143 }
144
145 fn as_any_mut(&mut self) -> &mut dyn Any {
146 self
147 }
148}