sorting_race/models/
config.rs

1//! Configuration types for sorting race simulation
2
3/// Data distribution patterns for generated arrays
4#[derive(Debug, Clone, PartialEq, Default)]
5pub enum Distribution {
6    /// Random shuffled array
7    #[default]
8    Shuffled,
9    /// Nearly sorted array with few out-of-place elements
10    NearlySorted,
11    /// Reverse sorted array
12    Reversed,
13    /// Array with few unique values
14    FewUnique,
15    /// Already sorted array (best case)
16    Sorted,
17    /// Array with duplicates
18    WithDuplicates,
19}
20
21/// Fairness model configuration
22#[derive(Debug, Clone, PartialEq)]
23pub enum FairnessMode {
24    /// Equal comparison budget for all algorithms
25    ComparisonBudget { k: usize },
26    /// Weighted fairness based on algorithm complexity
27    Weighted { alpha: f32, beta: f32 },
28    /// Wall-clock time based fairness
29    WallTime { slice_ms: u64 },
30    /// Adaptive fairness that learns algorithm efficiency
31    Adaptive { learning_rate: f32 },
32    /// Equal steps (one operation per algorithm)
33    EqualSteps,
34}
35
36impl Default for FairnessMode {
37    fn default() -> Self {
38        FairnessMode::ComparisonBudget { k: 10 }
39    }
40}
41
42/// Complete configuration for a sorting race run
43#[derive(Debug, Clone)]
44pub struct RunConfiguration {
45    /// Size of the array to sort
46    pub array_size: usize,
47    /// Distribution pattern for array generation
48    pub distribution: Distribution,
49    /// Random seed for deterministic generation
50    pub seed: u64,
51    /// Fairness model to use
52    pub fairness_mode: FairnessMode,
53    /// Target frames per second for visualization
54    pub target_fps: u32,
55}
56
57impl Default for RunConfiguration {
58    fn default() -> Self {
59        Self {
60            array_size: 100,
61            distribution: Distribution::default(),
62            seed: 42,
63            fairness_mode: FairnessMode::default(),
64            target_fps: 30,
65        }
66    }
67}
68
69impl RunConfiguration {
70    /// Create a new run configuration with default values
71    pub fn new() -> Self {
72        Self::default()
73    }
74
75    /// Set array size
76    pub fn with_array_size(mut self, size: usize) -> Self {
77        self.array_size = size;
78        self
79    }
80
81    /// Set distribution pattern
82    pub fn with_distribution(mut self, distribution: Distribution) -> Self {
83        self.distribution = distribution;
84        self
85    }
86
87    /// Set random seed
88    pub fn with_seed(mut self, seed: u64) -> Self {
89        self.seed = seed;
90        self
91    }
92
93    /// Set fairness mode
94    pub fn with_fairness_mode(mut self, fairness_mode: FairnessMode) -> Self {
95        self.fairness_mode = fairness_mode;
96        self
97    }
98
99    /// Set target FPS
100    pub fn with_target_fps(mut self, fps: u32) -> Self {
101        self.target_fps = fps;
102        self
103    }
104
105    /// Validate configuration parameters
106    pub fn validate(&self) -> Result<(), String> {
107        if self.array_size == 0 {
108            return Err("Array size must be greater than 0".to_string());
109        }
110
111        if self.target_fps == 0 {
112            return Err("Target FPS must be greater than 0".to_string());
113        }
114
115        match &self.fairness_mode {
116            FairnessMode::ComparisonBudget { k } => {
117                if *k == 0 {
118                    return Err("Comparison budget must be greater than 0".to_string());
119                }
120            }
121            FairnessMode::WallTime { slice_ms } => {
122                if *slice_ms == 0 {
123                    return Err("Wall time limit must be greater than 0".to_string());
124                }
125            }
126            FairnessMode::Weighted { alpha, beta } => {
127                if *alpha < 0.0 || *beta < 0.0 {
128                    return Err("Weights must be non-negative".to_string());
129                }
130            }
131            FairnessMode::Adaptive { learning_rate } => {
132                if *learning_rate < 0.0 || *learning_rate > 1.0 {
133                    return Err("Learning rate must be between 0.0 and 1.0".to_string());
134                }
135            }
136            FairnessMode::EqualSteps => {}
137        }
138
139        Ok(())
140    }
141}
142
143/// Configuration for visual appearance
144#[derive(Debug, Clone)]
145pub struct VisualConfiguration {
146    /// Width of visualization window
147    pub window_width: u32,
148    /// Height of visualization window
149    pub window_height: u32,
150    /// Whether to show comparison highlights
151    pub show_comparisons: bool,
152    /// Whether to show algorithm names
153    pub show_names: bool,
154    /// Whether to show performance metrics
155    pub show_metrics: bool,
156    /// Animation speed multiplier
157    pub animation_speed: f32,
158}
159
160impl Default for VisualConfiguration {
161    fn default() -> Self {
162        Self {
163            window_width: 800,
164            window_height: 600,
165            show_comparisons: true,
166            show_names: true,
167            show_metrics: true,
168            animation_speed: 1.0,
169        }
170    }
171}