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*/