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