Skip to main content

ed_journals/modules/exploration/models/
codex_planet_entry.rs

1use crate::exploration::shared::codex_regex::CODEX_REGEX;
2use crate::from_str_deserialize_impl;
3use serde::Serialize;
4use std::fmt::{Display, Formatter};
5use std::str::FromStr;
6use thiserror::Error;
7
8/// Codex entries related to planet types.
9#[derive(Debug, Serialize, Clone, PartialEq, Eq, Hash)]
10#[cfg_attr(not(feature = "allow-unknown"), non_exhaustive)]
11pub enum CodexPlanetEntry {
12    EarthLike,
13    AmmoniaWorlds,
14    WaterWorlds,
15    WaterGiant,
16    WaterGiantWithLife,
17    SudarskyClassI,
18    SudarskyClassII,
19    SudarskyClassIII,
20    SudarskyClassIV,
21    SudarskyClassV,
22    SupermassiveBlackHoles,
23    Helium,
24    HeliumRich,
25
26    // Unspecified terrestrial planets
27    HighMetalContent,
28    Ice,
29    MetalRich,
30    RockyIce,
31    Rocky,
32
33    // Unspecified no atmosphere planets
34    MetalRichNoAtmosphere,
35    HighMetalContentNoAtmosphere,
36    IceNoAtmosphere,
37    RockyIceNoAtmosphere,
38    RockyNoAtmosphere,
39
40    // Dense non-terrestrial planets
41    DenseAmmoniaWorlds,
42    DenseWaterWorlds,
43
44    // Dense terrestrial planets
45    DenseHighMetalContent,
46    DenseIce,
47    DenseMetalRich,
48    DenseRockyIce,
49    DenseRocky,
50
51    // Standard groups
52    StandardGiants,
53    StandardWaterWorlds,
54    StandardPlanetStandard,
55    StandardPlanetTerraformable,
56
57    // Standard non-terrestrial planets
58    StandardAmmoniaWorlds,
59    StandardGiantWithAmmoniaLife,
60    StandardGiantWithWaterLife,
61    StandardHelium,
62    StandardHeliumRich,
63    StandardWaterGiant,
64    StandardWaterGiantWithLife,
65
66    // Standard planets without an atmosphere
67    StandardHighMetalContentNoAtmosphere,
68    StandardIceNoAtmosphere,
69    StandardMetalRichNoAtmosphere,
70    StandardRockyIceNoAtmosphere,
71    StandardRockyNoAtmosphere,
72
73    // Standard Sudarsky classes
74    StandardSudarskyClassI,
75    StandardSudarskyClassII,
76    StandardSudarskyClassIII,
77    StandardSudarskyClassIV,
78    StandardSudarskyClassV,
79
80    // Standaard terrestrials
81    StandardHighMetalContent,
82    StandardIce,
83    StandardMetalRich,
84    StandardRockyIce,
85    StandardRocky,
86
87    // Light non-terrestrial planets
88    LightAmmoniaWorlds,
89    LightWaterWorlds,
90
91    // Light terrestrial planets
92    LightHighMetalContent,
93    LightIce,
94    LightMetalRich,
95    LightRockyIce,
96    LightRocky,
97
98    // Giants with life
99    GiantWithAmmoniaLife,
100    GiantWithWaterLife,
101
102    // Green giants
103    GreenGiants,
104    GreenGiantWithAmmoniaLife,
105    GreenGiantWithWaterLife,
106    GreenSudarskyClassI,
107    GreenSudarskyClassII,
108    GreenSudarskyClassIII,
109    GreenSudarskyClassIV,
110    GreenSudarskyClassV,
111    GreenWaterGiant,
112    GreenWaterGiantWithLife,
113    GreenHelium,
114    GreenHeliumRich,
115
116    // Terraformable non-terrestrial planets
117    TerraformableAmmoniaWorlds,
118    TerraformableWaterWorlds,
119
120    // Terraformable no atmosphere planets
121    TerraformableHighMetalContentNoAtmosphere,
122    TerraformableIceNoAtmosphere,
123    TerraformableMetalRichNoAtmosphere,
124    TerraformableRockyIceNoAtmosphere,
125    TerraformableRockyNoAtmosphere,
126
127    // Terraformable terrestrial planets
128    TerraformableHighMetalContent,
129    TerraformableIce,
130    TerraformableMetalRich,
131    TerraformableRockyIce,
132    TerraformableRocky,
133
134    #[cfg(feature = "allow-unknown")]
135    #[cfg_attr(docsrs, doc(cfg(feature = "allow-unknown")))]
136    Unknown(String),
137}
138
139impl CodexPlanetEntry {
140    /// Whether the current variant is unknown.
141    #[cfg(feature = "allow-unknown")]
142    #[cfg_attr(docsrs, doc(cfg(feature = "allow-unknown")))]
143    pub fn is_unknown(&self) -> bool {
144        matches!(self, CodexPlanetEntry::Unknown(_))
145    }
146}
147
148#[derive(Debug, Error)]
149pub enum CodexPlanetError {
150    #[error("Failed to parse planet codex entry: '{0}'")]
151    FailedToParse(String),
152
153    #[error("Unknown planet codex entry: '{0}'")]
154    UnknownEntry(String),
155}
156
157impl FromStr for CodexPlanetEntry {
158    type Err = CodexPlanetError;
159
160    fn from_str(s: &str) -> Result<Self, Self::Err> {
161        let Some(captures) = CODEX_REGEX.captures(s) else {
162            return Err(CodexPlanetError::FailedToParse(s.to_string()));
163        };
164
165        let string: &str = &captures
166            .get(1)
167            .expect("Should have been captured already")
168            .as_str()
169            .to_ascii_lowercase();
170
171        // TODO TER might actually stand for 'terrestrial' and TRF might stand for 'terraformable'.
172        Ok(match string {
173            "earth_likes" => CodexPlanetEntry::EarthLike,
174            "ammonia_worlds" => CodexPlanetEntry::AmmoniaWorlds,
175            "water_worlds" => CodexPlanetEntry::WaterWorlds,
176            "water_giant" => CodexPlanetEntry::WaterGiant,
177            "water_giant_with_life" => CodexPlanetEntry::WaterGiantWithLife,
178            "sudarsky_class_i" => CodexPlanetEntry::SudarskyClassI,
179            "sudarsky_class_ii" => CodexPlanetEntry::SudarskyClassII,
180            "sudarsky_class_iii" => CodexPlanetEntry::SudarskyClassIII,
181            "sudarsky_class_iv" => CodexPlanetEntry::SudarskyClassIV,
182            "sudarsky_class_v" => CodexPlanetEntry::SudarskyClassV,
183            "supermassiveblack_holes" => CodexPlanetEntry::SupermassiveBlackHoles,
184            "helium" => CodexPlanetEntry::Helium,
185            "helium_rich" => CodexPlanetEntry::HeliumRich,
186
187            // Unspecified terrestrial planets
188            "ter_high_metal_content" => CodexPlanetEntry::HighMetalContent,
189            "ter_ice" => CodexPlanetEntry::Ice,
190            "ter_metal_rich" => CodexPlanetEntry::MetalRich,
191            "ter_rocky_ice" => CodexPlanetEntry::RockyIce,
192            "ter_rocky" => CodexPlanetEntry::Rocky,
193
194            // Unspecified no atmosphere planets
195            "metal_rich_no_atmos" => CodexPlanetEntry::MetalRichNoAtmosphere,
196            "high_metal_content_no_atmos" => CodexPlanetEntry::HighMetalContentNoAtmosphere,
197            "ice_no_atmos" => CodexPlanetEntry::IceNoAtmosphere,
198            "rocky_ice_no_atmos" => CodexPlanetEntry::RockyIceNoAtmosphere,
199            "rocky_no_atmos" => CodexPlanetEntry::RockyNoAtmosphere,
200
201            // Dense non-terrestrial planets
202            "dense_ammonia_worlds" => CodexPlanetEntry::DenseAmmoniaWorlds,
203            "dense_water_worlds" => CodexPlanetEntry::DenseWaterWorlds,
204
205            // Dense terrestrial planets
206            "dense_ter_high_metal_content" => CodexPlanetEntry::DenseHighMetalContent,
207            "dense_ter_ice" => CodexPlanetEntry::DenseIce,
208            "dense_ter_metal_rich" => CodexPlanetEntry::DenseMetalRich,
209            "dense_ter_rocky_ice" => CodexPlanetEntry::DenseRockyIce,
210            "dense_ter_rocky" => CodexPlanetEntry::DenseRocky,
211
212            // Standard groups
213            "standard_giants" => CodexPlanetEntry::StandardGiants,
214            "standard_planetstandard" => CodexPlanetEntry::StandardPlanetStandard,
215            "standard_planetterraf" => CodexPlanetEntry::StandardPlanetTerraformable,
216            "standard_water_worlds" => CodexPlanetEntry::StandardWaterWorlds,
217
218            // Standard non-terrestrial planets
219            "standard_ammonia_worlds" => CodexPlanetEntry::StandardAmmoniaWorlds,
220            "standard_giant_with_ammonia_life" => CodexPlanetEntry::StandardGiantWithAmmoniaLife,
221            "standard_giant_with_water_life" => CodexPlanetEntry::StandardGiantWithWaterLife,
222            "standard_helium" => CodexPlanetEntry::StandardHelium,
223            "standard_helium_rich" => CodexPlanetEntry::StandardHeliumRich,
224            "standard_water_giant" => CodexPlanetEntry::StandardWaterGiant,
225            "standard_water_giant_with_life" => CodexPlanetEntry::StandardWaterGiantWithLife,
226
227            // Standard planets without an atmosphere
228            "standard_high_metal_content_no_atmos" => {
229                CodexPlanetEntry::StandardHighMetalContentNoAtmosphere
230            }
231            "standard_ice_no_atmos" => CodexPlanetEntry::StandardIceNoAtmosphere,
232            "standard_metal_rich_no_atmos" => CodexPlanetEntry::StandardMetalRichNoAtmosphere,
233            "standard_rocky_ice_no_atmos" => CodexPlanetEntry::StandardRockyIceNoAtmosphere,
234            "standard_rocky_no_atmos" => CodexPlanetEntry::StandardRockyNoAtmosphere,
235
236            // Standard Sudarsky classes
237            "standard_sudarsky_class_i" => CodexPlanetEntry::StandardSudarskyClassI,
238            "standard_sudarsky_class_ii" => CodexPlanetEntry::StandardSudarskyClassII,
239            "standard_sudarsky_class_iii" => CodexPlanetEntry::StandardSudarskyClassIII,
240            "standard_sudarsky_class_iv" => CodexPlanetEntry::StandardSudarskyClassIV,
241            "standard_sudarsky_class_v" => CodexPlanetEntry::StandardSudarskyClassV,
242
243            // Standaard terrestrials
244            "standard_ter_high_metal_content" => CodexPlanetEntry::StandardHighMetalContent,
245            "standard_ter_ice" => CodexPlanetEntry::StandardIce,
246            "standard_ter_metal_rich" => CodexPlanetEntry::StandardMetalRich,
247            "standard_ter_rocky_ice" => CodexPlanetEntry::StandardRockyIce,
248            "standard_ter_rocky" => CodexPlanetEntry::StandardRocky,
249
250            // Light non-terrestrial planets
251            "light_ammonia_worlds" => CodexPlanetEntry::LightAmmoniaWorlds,
252            "light_water_worlds" => CodexPlanetEntry::LightWaterWorlds,
253
254            // Light terrestrial planets
255            "light_ter_high_metal_content" => CodexPlanetEntry::LightHighMetalContent,
256            "light_ter_ice" => CodexPlanetEntry::LightIce,
257            "light_ter_metal_rich" => CodexPlanetEntry::LightMetalRich,
258            "light_ter_rocky_ice" => CodexPlanetEntry::LightRockyIce,
259            "light_ter_rocky" => CodexPlanetEntry::LightRocky,
260
261            // Giants with life
262            "giant_with_ammonia_life" => CodexPlanetEntry::GiantWithAmmoniaLife,
263            "giant_with_water_life" => CodexPlanetEntry::GiantWithWaterLife,
264
265            // Green giants
266            "greengiants" => CodexPlanetEntry::GreenGiants,
267            "green_giant_with_ammonia_life" => CodexPlanetEntry::GreenGiantWithAmmoniaLife,
268            "green_giant_with_water_life" => CodexPlanetEntry::GreenGiantWithWaterLife,
269            "green_sudarsky_class_i" => CodexPlanetEntry::GreenSudarskyClassI,
270            "green_sudarsky_class_ii" => CodexPlanetEntry::GreenSudarskyClassII,
271            "green_sudarsky_class_iii" => CodexPlanetEntry::GreenSudarskyClassIII,
272            "green_sudarsky_class_iv" => CodexPlanetEntry::GreenSudarskyClassIV,
273            "green_sudarsky_class_v" => CodexPlanetEntry::GreenSudarskyClassV,
274            "green_water_giant" => CodexPlanetEntry::GreenWaterGiant,
275            "green_water_giant_with_life" => CodexPlanetEntry::GreenWaterGiantWithLife,
276            "green_helium" => CodexPlanetEntry::GreenHelium,
277            "green_helium_rich" => CodexPlanetEntry::GreenHeliumRich,
278
279            // Terraformable non-terrestrial planets
280            "trf_ammonia_worlds" => CodexPlanetEntry::TerraformableAmmoniaWorlds,
281            "trf_water_worlds" => CodexPlanetEntry::TerraformableWaterWorlds,
282
283            // Terraformable no atmosphere planets
284            "trf_high_metal_content_no_atmos" => {
285                CodexPlanetEntry::TerraformableHighMetalContentNoAtmosphere
286            }
287            "trf_ice_no_atmos" => CodexPlanetEntry::TerraformableIceNoAtmosphere,
288            "trf_metal_rich_no_atmos" => CodexPlanetEntry::TerraformableMetalRichNoAtmosphere,
289            "trf_rocky_ice_no_atmos" => CodexPlanetEntry::TerraformableRockyIceNoAtmosphere,
290            "trf_rocky_no_atmos" => CodexPlanetEntry::TerraformableRockyNoAtmosphere,
291
292            // Terraformable terrestrial planets
293            "trf_ter_high_metal_content" => CodexPlanetEntry::TerraformableHighMetalContent,
294            "trf_ter_ice" => CodexPlanetEntry::TerraformableIce,
295            "trf_ter_metal_rich" => CodexPlanetEntry::TerraformableMetalRich,
296            "trf_ter_rocky_ice" => CodexPlanetEntry::TerraformableRockyIce,
297            "trf_ter_rocky" => CodexPlanetEntry::TerraformableRocky,
298
299            #[cfg(feature = "allow-unknown")]
300            _ => CodexPlanetEntry::Unknown(string.to_string()),
301
302            #[cfg(not(feature = "allow-unknown"))]
303            _ => return Err(CodexPlanetError::UnknownEntry(string.to_string())),
304        })
305    }
306}
307
308from_str_deserialize_impl!(CodexPlanetEntry);
309
310impl Display for CodexPlanetEntry {
311    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
312        write!(
313            f,
314            "{}",
315            match self {
316                CodexPlanetEntry::EarthLike => "earth_like",
317                CodexPlanetEntry::AmmoniaWorlds => "Ammonia World",
318                CodexPlanetEntry::WaterWorlds => "Water Worlds",
319                CodexPlanetEntry::WaterGiant => "Water Giant",
320                CodexPlanetEntry::WaterGiantWithLife => "Water Giant with Life",
321                CodexPlanetEntry::SudarskyClassI => "Sudarsky Class I",
322                CodexPlanetEntry::SudarskyClassII => "Sudarsky Class II",
323                CodexPlanetEntry::SudarskyClassIII => "Sudarsky Class III",
324                CodexPlanetEntry::SudarskyClassIV => "Sudarsky Class IV",
325                CodexPlanetEntry::SudarskyClassV => "Sudarsky Class V",
326                CodexPlanetEntry::SupermassiveBlackHoles => "Supermassive Black Holes",
327                CodexPlanetEntry::Helium => "Helium Planet",
328                CodexPlanetEntry::HeliumRich => "Helium-Rich Planet",
329
330                CodexPlanetEntry::DenseAmmoniaWorlds => "Dense Ammonia World",
331                CodexPlanetEntry::DenseWaterWorlds => "Dense Water Worlds",
332                CodexPlanetEntry::DenseHighMetalContent => "Dense High Metal Content Planet",
333                CodexPlanetEntry::DenseIce => "Dense Ice Planet",
334                CodexPlanetEntry::DenseMetalRich => "Dense Metal-Rich Planet",
335                CodexPlanetEntry::DenseRockyIce => "Dense Rocky Ice Planet",
336                CodexPlanetEntry::DenseRocky => "Dense Rocky Planet",
337
338                CodexPlanetEntry::StandardAmmoniaWorlds => "Standard Ammonia Worlds",
339                CodexPlanetEntry::StandardGiantWithAmmoniaLife =>
340                    "Standard Giant with Ammonia Life",
341                CodexPlanetEntry::StandardGiantWithWaterLife => "Standard Giant with Water Life",
342                CodexPlanetEntry::StandardGiants => "Standard Giants",
343                CodexPlanetEntry::StandardHelium => "Standard Helium",
344                CodexPlanetEntry::StandardHeliumRich => "Standard Helium-Rich",
345                CodexPlanetEntry::StandardHighMetalContentNoAtmosphere =>
346                    "Standard High Metal Content, No Atmosphere",
347                CodexPlanetEntry::StandardIceNoAtmosphere => "Standard Ice, No Atmosphere",
348                CodexPlanetEntry::StandardMetalRichNoAtmosphere =>
349                    "Standard Metal-Rich, No Atmosphere",
350                CodexPlanetEntry::StandardPlanetStandard => "Standard Planet Standard",
351                CodexPlanetEntry::StandardPlanetTerraformable => "Standard Planet Terraformable",
352                CodexPlanetEntry::StandardRockyIceNoAtmosphere =>
353                    "Standard Rocky Ice, No Atmosphere",
354                CodexPlanetEntry::StandardRockyNoAtmosphere => "Standard Rocky, No Atmosphere",
355
356                CodexPlanetEntry::StandardSudarskyClassI => "Standard Sudarsky Class I",
357                CodexPlanetEntry::StandardSudarskyClassII => "Standard Sudarsky Class II",
358                CodexPlanetEntry::StandardSudarskyClassIII => "Standard Sudarsky Class III",
359                CodexPlanetEntry::StandardSudarskyClassIV => "Standard Sudarsky Class IV",
360                CodexPlanetEntry::StandardSudarskyClassV => "Standard Sudarsky Class V",
361
362                CodexPlanetEntry::StandardHighMetalContent => "Standard High Metal Content",
363                CodexPlanetEntry::StandardIce => "Standard Ice",
364                CodexPlanetEntry::StandardMetalRich => "Standard Metal-Rich",
365                CodexPlanetEntry::StandardRockyIce => "Standard Rocky Ice",
366                CodexPlanetEntry::StandardRocky => "Standard Rocky",
367
368                CodexPlanetEntry::StandardWaterGiant => "Standard Water Giant",
369                CodexPlanetEntry::StandardWaterGiantWithLife => "Standard Water Giant with Life",
370                CodexPlanetEntry::StandardWaterWorlds => "Standard Water Worlds",
371
372                CodexPlanetEntry::LightAmmoniaWorlds => "Light Ammonia Worlds",
373                CodexPlanetEntry::LightWaterWorlds => "Light Water Worlds",
374                CodexPlanetEntry::LightHighMetalContent => "Light High Metal Content Planet",
375                CodexPlanetEntry::LightIce => "Light Ice Planet",
376                CodexPlanetEntry::LightMetalRich => "Light Metal-Rich Planet",
377                CodexPlanetEntry::LightRockyIce => "Light Rocky Ice Planet",
378                CodexPlanetEntry::LightRocky => "Light Rocky Planet",
379
380                CodexPlanetEntry::GreenGiants => "Green Giants",
381                CodexPlanetEntry::GiantWithAmmoniaLife => "Giant with Ammonia Life",
382                CodexPlanetEntry::GiantWithWaterLife => "Giant with Water Life",
383                CodexPlanetEntry::GreenGiantWithAmmoniaLife => "Green Giant with Ammonia Life",
384                CodexPlanetEntry::GreenGiantWithWaterLife => "Green Giant with Water Life",
385                CodexPlanetEntry::GreenSudarskyClassI => "Green Sudarsky Class I",
386                CodexPlanetEntry::GreenSudarskyClassII => "Green Sudarsky Class II",
387                CodexPlanetEntry::GreenSudarskyClassIII => "Green Sudarsky Class III",
388                CodexPlanetEntry::GreenSudarskyClassIV => "Green Sudarsky Class IV",
389                CodexPlanetEntry::GreenSudarskyClassV => "Green Sudarsky Class V",
390                CodexPlanetEntry::GreenWaterGiant => "Green Water Giant",
391                CodexPlanetEntry::GreenWaterGiantWithLife => "Green Water Giant with Life",
392                CodexPlanetEntry::GreenHelium => "Green Helium Planet",
393                CodexPlanetEntry::GreenHeliumRich => "Green Helium-Rich Planet",
394
395                CodexPlanetEntry::HighMetalContent => "High Metal Content Planet",
396                CodexPlanetEntry::Ice => "Ice Planet",
397                CodexPlanetEntry::MetalRich => "Metal-Rich Planet",
398                CodexPlanetEntry::RockyIce => "Rocky Ice Planet",
399                CodexPlanetEntry::Rocky => "Rocky Planet",
400
401                CodexPlanetEntry::MetalRichNoAtmosphere => "Metal-Rich, No Atmosphere",
402                CodexPlanetEntry::HighMetalContentNoAtmosphere =>
403                    "High Metal Content Planet, No Atmosphere",
404                CodexPlanetEntry::IceNoAtmosphere => "Ice Planet, No Atmosphere",
405                CodexPlanetEntry::RockyIceNoAtmosphere => "Rocky Ice Planet, No Atmosphere",
406                CodexPlanetEntry::RockyNoAtmosphere => "Rocky Planet, No Atmosphere",
407
408                // Terraformable non-terrestrial planets
409                CodexPlanetEntry::TerraformableAmmoniaWorlds => "Terraformable Ammonia Worlds",
410                CodexPlanetEntry::TerraformableWaterWorlds => "Terraformable Water Worlds",
411
412                // Terraformable no atmosphere planets
413                CodexPlanetEntry::TerraformableHighMetalContentNoAtmosphere =>
414                    "Terraformable High Metal Content Planet, No Atmosphere",
415                CodexPlanetEntry::TerraformableIceNoAtmosphere =>
416                    "Terraformable Ice Planet, No Atmosphere",
417                CodexPlanetEntry::TerraformableMetalRichNoAtmosphere =>
418                    "Terraformable Metal-Rich Planet, No Atmosphere",
419                CodexPlanetEntry::TerraformableRockyIceNoAtmosphere =>
420                    "Terraformable Rocky Ice Planet, No Atmosphere",
421                CodexPlanetEntry::TerraformableRockyNoAtmosphere =>
422                    "Terraformable Rocky Planet, No Atmosphere",
423
424                // Terraformable terrestrial planets
425                CodexPlanetEntry::TerraformableHighMetalContent =>
426                    "Terraformable High Metal Content Planet",
427                CodexPlanetEntry::TerraformableIce => "Terraformable Ice Planet",
428                CodexPlanetEntry::TerraformableMetalRich => "Terraformable Metal-Rich Planet",
429                CodexPlanetEntry::TerraformableRockyIce => "Terraformable Rocky Ice Planet",
430                CodexPlanetEntry::TerraformableRocky => "Terraformable Rocky Planet",
431
432                #[cfg(feature = "allow-unknown")]
433                CodexPlanetEntry::Unknown(unknown) =>
434                    return write!(f, "Unknown planet codex entry: {unknown}"),
435            }
436        )
437    }
438}