lib_efo/stats/
implementations.rs

1//! All traits implementatition for the main structs are deffered here
2#![allow(dead_code)]
3
4use crate::stats::{GameStat, GenericStat, ListStats, OverallStats};
5mod from_impl;
6mod symb_impl;
7
8/// Generates an `impl GameStat for <TYPE>` where the only difference between
9/// multiple implementations is the visibility level.
10///
11/// # Parameters
12/// * `$type`: the concrete type that implements `GameStat`
13/// * `$vis`: the enum variant of `VisibilityLevel` to return
14macro_rules! impl_game_stat {
15    ($type:ident) => {
16        impl GameStat for $type {
17            fn get_value(&self) -> isize {
18                self.0
19            }
20
21            fn change_value(&mut self, value: isize) {
22                self.0 = value;
23            }
24
25            fn from_value(value: isize) -> Self
26            where
27                Self: Sized,
28            {
29                Self(value)
30            }
31        }
32    };
33}
34
35/// A field accessor to be able to modify fields on the fly
36macro_rules! field_accessor {
37    ($name:ident { $($field:ident),* }) => {
38        impl $name {
39            fn get_field_from_str(&self, key: &str) -> Option<&dyn GameStat> {
40                match key {
41                    $(
42                        stringify!($field) => Some(&self.$field),
43                    )*
44                    _ => None,
45                }
46            }
47
48            fn get_field_mut_from_str(&mut self, key: &str) -> Option<&mut dyn GameStat> {
49                match key {
50                    $(
51                        stringify!($field) => Some(&mut self.$field),
52                    )*
53                    _ => None,
54                }
55            }
56        }
57    };
58}
59
60impl_game_stat!(GenericStat);
61field_accessor!(OverallStats {
62    demographics,
63    population,
64    growth_rate,
65    crime,
66    happiness,
67    economy,
68    food,
69    industry,
70    science,
71    trade,
72    // social,
73    // culture,
74    // education,
75    // tourism,
76    // influence,
77    military,
78    army,
79    strength,
80    fortification,
81    threat,
82    infrastructure,
83    bureaucracy,
84    transportation,
85    sprawl,
86    health
87});
88
89impl OverallStats {
90    /// Retrieve a reference to a statistic field by its `ListStats` key.
91    ///
92    /// # Arguments
93    ///
94    /// * `field` - The `ListStats` variant that selects which statistic to return.
95    ///
96    /// # Returns
97    ///
98    /// A reference to the selected `GenericStat`.
99    ///
100    /// # Panics
101    ///
102    /// Panics if `field` is one of the variants that are not yet implemented
103    /// (`Social`, `Culture`, `Education`, `Tourism`, `Influence`).
104    pub fn get_field(&self, field: &ListStats) -> &GenericStat {
105        match field {
106            ListStats::Demographics => &self.demographics,
107            ListStats::Population => &self.population,
108            ListStats::Growthrate => &self.growth_rate,
109            ListStats::Crime => &self.crime,
110            ListStats::Happiness => &self.happiness,
111            ListStats::Economy => &self.economy,
112            ListStats::Food => &self.food,
113            ListStats::Industry => &self.industry,
114            ListStats::Science => &self.science,
115            ListStats::Trade => &self.trade,
116            ListStats::Social => unimplemented!("This version doens't implement this stat"), //&self.social,
117            ListStats::Culture => unimplemented!("This version doens't implement this stat"), //&self.culture,
118            ListStats::Education => unimplemented!("This version doens't implement this stat"), //&self.education,
119            ListStats::Tourism => unimplemented!("This version doens't implement this stat"), //&self.tourism,
120            ListStats::Influence => unimplemented!("This version doens't implement this stat"), //&self.influence,
121            ListStats::Military => &self.military,
122            ListStats::Army => &self.army,
123            ListStats::Strength => &self.strength,
124            ListStats::Fortification => &self.fortification,
125            ListStats::Threat => &self.threat,
126            ListStats::Infrastructure => &self.infrastructure,
127            ListStats::Bureaucracy => &self.bureaucracy,
128            ListStats::Transportation => &self.transportation,
129            ListStats::Sprawl => &self.sprawl,
130            ListStats::Health => &self.health,
131        }
132    }
133
134    /// Retrieve a mutable reference to a statistic field by its `ListStats` key.
135    ///
136    /// # Arguments
137    ///
138    /// * `field` - The `ListStats` variant that selects which statistic to modify.
139    ///
140    /// # Returns
141    ///
142    /// A mutable reference to the selected `GenericStat`.
143    ///
144    /// # Panics
145    ///
146    /// Panics if `field` is one of the variants that are not yet implemented
147    /// (`Social`, `Culture`, `Education`, `Tourism`, `Influence`).
148    pub fn get_field_mut(&mut self, field: &ListStats) -> &mut GenericStat {
149        match field {
150            ListStats::Demographics => &mut self.demographics,
151            ListStats::Population => &mut self.population,
152            ListStats::Growthrate => &mut self.growth_rate,
153            ListStats::Crime => &mut self.crime,
154            ListStats::Happiness => &mut self.happiness,
155            ListStats::Economy => &mut self.economy,
156            ListStats::Food => &mut self.food,
157            ListStats::Industry => &mut self.industry,
158            ListStats::Science => &mut self.science,
159            ListStats::Trade => &mut self.trade,
160            ListStats::Social => unimplemented!("This version doens't implement this stat"), //&mut self.social,
161            ListStats::Culture => unimplemented!("This version doens't implement this stat"), //&mut self.culture,
162            ListStats::Education => unimplemented!("This version doens't implement this stat"), //&mut self.education,
163            ListStats::Tourism => unimplemented!("This version doens't implement this stat"), //&mut self.tourism,
164            ListStats::Influence => unimplemented!("This version doens't implement this stat"), //&mut self.influence,
165            ListStats::Military => &mut self.military,
166            ListStats::Army => &mut self.army,
167            ListStats::Strength => &mut self.strength,
168            ListStats::Fortification => &mut self.fortification,
169            ListStats::Threat => &mut self.threat,
170            ListStats::Infrastructure => &mut self.infrastructure,
171            ListStats::Bureaucracy => &mut self.bureaucracy,
172            ListStats::Transportation => &mut self.transportation,
173            ListStats::Sprawl => &mut self.sprawl,
174            ListStats::Health => &mut self.health,
175        }
176    }
177}
178
179/// Thin wrapper that derefs to the inner type.
180///
181/// By default the wrapper derives a common set of traits (`Debug`, `Clone`, `Copy`,
182/// …).  You can optionally provide an extra list of derives - e.g. `Add`,
183/// `Sub`, `FromStr`, or any custom derive - by writing:
184/// ```
185/// # use lib_efo::thin_newtype;
186/// use derive_more::{Add, Sub};
187/// thin_newtype!(MyInt, i32, derives: [Add, Sub]);
188/// ```
189/// (you'll need the corresponding crates - e.g. `derive_more` for `Add`, `Sub`).
190#[macro_export]
191macro_rules! thin_newtype {
192    /* ---- no custom derives ------------------------------------------------- */
193    ($name:ident, $inner:ty) => {
194
195        /// Thin wrapper that derefs to the inner type.
196        /// Ideal for zero-overhead new-type patterns.
197        #[repr(transparent)]
198        #[derive(
199            Debug,
200            Clone,
201            Copy,
202            Default,
203            PartialEq,
204            Eq,
205            PartialOrd,
206            Ord,
207            Hash,
208            Serialize,
209            Deserialize,
210            Display,
211        )]
212        pub struct $name(pub $inner);
213
214        impl std::ops::Deref for $name {
215            type Target = $inner;
216            #[inline]
217            fn deref(&self) -> &Self::Target {
218                &self.0
219            }
220        }
221
222        impl std::ops::DerefMut for $name {
223            #[inline]
224            fn deref_mut(&mut self) -> &mut Self::Target {
225                &mut self.0
226            }
227        }
228
229        impl From<$inner> for $name {
230            #[inline]
231            fn from(v: $inner) -> Self {
232                $name(v)
233            }
234        }
235
236        impl From<$name> for $inner {
237            #[inline]
238            fn from(v: $name) -> Self {
239                v.0
240            }
241        }
242    };
243
244    /* ---- with a custom derive list ---------------------------------------- */
245    ($name:ident, $inner:ty, derives: [ $( $derive:ident ),* $(,)? ]) => {
246        /// Thin wrapper that derefs to the inner type.
247        /// Ideal for zero-overhead new-type patterns.
248        #[repr(transparent)]
249        #[derive(
250            Debug,
251            Clone,
252            Copy,
253            Default,
254            PartialEq,
255            Eq,
256            PartialOrd,
257            Ord,
258            Hash,
259            serde::Serialize,
260            serde::Deserialize,
261            derive_more::Display,
262            $( $derive ),*
263        )]
264        pub struct $name(pub $inner);
265
266        impl std::ops::Deref for $name {
267            type Target = $inner;
268            #[inline]
269            fn deref(&self) -> &Self::Target {
270                &self.0
271            }
272        }
273
274        impl std::ops::DerefMut for $name {
275            #[inline]
276            fn deref_mut(&mut self) -> &mut Self::Target {
277                &mut self.0
278            }
279        }
280
281        impl From<$inner> for $name {
282            #[inline]
283            fn from(v: $inner) -> Self {
284                $name(v)
285            }
286        }
287
288        impl From<$name> for $inner {
289            #[inline]
290            fn from(v: $name) -> Self {
291                v.0
292            }
293        }
294    };
295}
296
297#[cfg(test)]
298pub(crate) mod test;