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};
29use std::fmt;
30use std::fmt::{Display, Formatter};
31
32/// Contains all configuration data for a speed level
33#[derive(Debug, Copy, Clone)]
34pub struct SpeedConfig {
35    /// Delay in milliseconds between moves
36    pub ms_value: u64,
37    /// Human-readable name of the speed level
38    pub name: &'static str,
39    /// Score multiplier for this speed level
40    pub score_modifier: u16,
41    /// Symbol representing this speed level
42    pub symbol: &'static str,
43}
44
45// Static configuration for each speed level
46const SLOW_CONFIG: SpeedConfig = SpeedConfig {
47    ms_value: 150,
48    name: "Slow",
49    score_modifier: 1,
50    symbol: "🐢",
51};
52
53const NORMAL_CONFIG: SpeedConfig = SpeedConfig {
54    ms_value: 125,
55    name: "Normal",
56    score_modifier: 2,
57    symbol: "🐍",
58};
59
60const FAST_CONFIG: SpeedConfig = SpeedConfig {
61    ms_value: 100,
62    name: "Fast",
63    score_modifier: 3,
64    symbol: "🐉",
65};
66
67const CRAZY_CONFIG: SpeedConfig = SpeedConfig {
68    ms_value: 80,
69    name: "Crazy",
70    score_modifier: 4,
71    symbol: "🦖",
72};
73
74/// Represents speed levels with embedded properties
75#[derive(Debug, Copy, Clone, Serialize, Deserialize, ValueEnum, Default)]
76pub enum Speed {
77    Slow,
78    #[default]
79    Normal,
80    Fast,
81    Crazy,
82}
83impl Display for Speed {
84    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
85        write!(f, "{}{}", self.name(), self.symbol())
86    }
87}
88
89impl Speed {
90    /// Returns the configuration for this speed level
91    #[must_use]
92    pub fn config(&self) -> &'static SpeedConfig {
93        match self {
94            Speed::Slow => &SLOW_CONFIG,
95            Speed::Normal => &NORMAL_CONFIG,
96            Speed::Fast => &FAST_CONFIG,
97            Speed::Crazy => &CRAZY_CONFIG,
98        }
99    }
100
101    /// Returns the speed value in milliseconds
102    #[must_use]
103    pub fn ms_value(&self) -> u64 {
104        self.config().ms_value
105    }
106
107    /// Returns the name of the speed level
108    #[must_use]
109    pub fn name(&self) -> &'static str {
110        self.config().name
111    }
112
113    /// Returns the symbol representing this speed level
114    #[must_use]
115    pub fn symbol(&self) -> &'static str {
116        self.config().symbol
117    }
118
119    /// Returns the score modifier for this speed level
120    #[must_use]
121    pub fn score_modifier(&self) -> u16 {
122        self.config().score_modifier
123    }
124}
125
126/*Returns all speed variants for UI or configuration purposes
127Useless as ValueEnum derive does the same (for Clap initially but can be reused elsewhere)
128#[must_use]
129pub fn iter_speed_variants() -> Vec<Speed> {
130    vec![Speed::Slow, Speed::Normal, Speed::Fast, Speed::Crazy]
131}
132*/