rsnaker/controls/
speed.rs

1//! # Speed Enum with Static Configuration
2//!
3//! This module implements a Speed enum that uses static pre-configured values to avoid
4//! repeated match expressions and improve performance. The configuration for each speed
5//! level is defined once in static constants, which are accessed through accessor methods.
6//!
7//! # Design Choice
8//! This implements the "enum with static data" pattern where:
9//! - The enum is kept simple for Clap integration
10//! - Associated data is stored in static constants (optional, can be plain after match, but it is less structured)
11//! - Accessor methods avoid repeated match statements by using a `config()` method (optional)
12//! - Provide an easy way to get all parameters at once, using `config()`
13//!
14//! A variant will look like: same enum, in `get_name` fn matches self and returns "fast" for fast variant etc.
15//! => (no const or associated struct, but less structured (no named variant of parameters))
16//!
17//! # Example
18//! ```rust
19//! use rsnaker::controls::speed::Speed;
20//!
21//! let fast_speed = Speed::Fast;
22//! println!("Speed value: {}", fast_speed.ms_value());
23//! assert_eq!("Fast", fast_speed.name());
24//! ```
25//!
26
27use clap::ValueEnum;
28use serde::{Deserialize, Serialize};
29
30/// Contains all configuration data for a speed level
31#[derive(Debug, Copy, Clone)]
32pub struct SpeedConfig {
33    /// Delay in milliseconds between moves
34    pub ms_value: u64,
35    /// Human-readable name of the speed level
36    pub name: &'static str,
37    /// Score multiplier for this speed level
38    pub score_modifier: u16,
39    /// Symbol representing this speed level
40    pub symbol: &'static str,
41}
42
43// Static configuration for each speed level
44const SLOW_CONFIG: SpeedConfig = SpeedConfig {
45    ms_value: 150,
46    name: "Slow",
47    score_modifier: 1,
48    symbol: "🐢",
49};
50
51const NORMAL_CONFIG: SpeedConfig = SpeedConfig {
52    ms_value: 125,
53    name: "Normal",
54    score_modifier: 2,
55    symbol: "🐍",
56};
57
58const FAST_CONFIG: SpeedConfig = SpeedConfig {
59    ms_value: 100,
60    name: "Fast",
61    score_modifier: 3,
62    symbol: "🐉",
63};
64
65const TREMENDOUS_CONFIG: SpeedConfig = SpeedConfig {
66    ms_value: 80,
67    name: "Tremendous",
68    score_modifier: 4,
69    symbol: "🦖",
70};
71
72/// Represents speed levels with embedded properties
73#[derive(Debug, Copy, Clone, Serialize, Deserialize, ValueEnum, Default)]
74pub enum Speed {
75    Slow,
76    #[default]
77    Normal,
78    Fast,
79    Tremendous,
80}
81
82impl Speed {
83    /// Returns the configuration for this speed level
84    #[must_use]
85    pub fn config(&self) -> &'static SpeedConfig {
86        match self {
87            Speed::Slow => &SLOW_CONFIG,
88            Speed::Normal => &NORMAL_CONFIG,
89            Speed::Fast => &FAST_CONFIG,
90            Speed::Tremendous => &TREMENDOUS_CONFIG,
91        }
92    }
93
94    /// Returns the speed value in milliseconds
95    #[must_use]
96    pub fn ms_value(&self) -> u64 {
97        self.config().ms_value
98    }
99
100    /// Returns the name of the speed level
101    #[must_use]
102    pub fn name(&self) -> &'static str {
103        self.config().name
104    }
105
106    /// Returns the symbol representing this speed level
107    #[must_use]
108    pub fn symbol(&self) -> &'static str {
109        self.config().symbol
110    }
111
112    /// Returns the score modifier for this speed level
113    #[must_use]
114    pub fn score_modifier(&self) -> u16 {
115        self.config().score_modifier
116    }
117}
118
119/*Returns all speed variants for UI or configuration purposes
120Useless as ValueEnum derive does the same (for Clap initially but can be reused elsewhere)
121#[must_use]
122pub fn iter_speed_variants() -> Vec<Speed> {
123    vec![Speed::Slow, Speed::Normal, Speed::Fast, Speed::Tremendous]
124}
125*/