1use serde::{Deserialize, Serialize};
2use std::fmt;
3use std::str::FromStr;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
7#[non_exhaustive]
8pub enum GalaxyType {
9 Norm,
10 Lush,
11 Harsh,
12 Empty,
13}
14
15impl fmt::Display for GalaxyType {
16 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17 match self {
18 Self::Norm => write!(f, "Normal"),
19 Self::Lush => write!(f, "Lush"),
20 Self::Harsh => write!(f, "Harsh"),
21 Self::Empty => write!(f, "Empty"),
22 }
23 }
24}
25
26#[derive(Debug, Clone, PartialEq, Eq)]
28pub struct GalaxyTypeParseError(pub String);
29
30impl fmt::Display for GalaxyTypeParseError {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 write!(f, "unknown galaxy type: {}", self.0)
33 }
34}
35
36impl std::error::Error for GalaxyTypeParseError {}
37
38impl FromStr for GalaxyType {
39 type Err = GalaxyTypeParseError;
40
41 fn from_str(s: &str) -> Result<Self, Self::Err> {
42 match s.to_lowercase().as_str() {
43 "norm" | "normal" => Ok(Self::Norm),
44 "lush" => Ok(Self::Lush),
45 "harsh" => Ok(Self::Harsh),
46 "empty" => Ok(Self::Empty),
47 _ => Err(GalaxyTypeParseError(s.to_string())),
48 }
49 }
50}
51
52#[derive(Debug, Clone, PartialEq, Eq, Hash)]
54#[non_exhaustive]
55pub struct Galaxy {
56 pub index: u8,
57 pub name: &'static str,
58 pub galaxy_type: GalaxyType,
59}
60
61impl Galaxy {
62 pub fn by_index(index: u8) -> Self {
64 let (name, galaxy_type) = GALAXIES[index as usize];
65 Self {
66 index,
67 name,
68 galaxy_type,
69 }
70 }
71}
72
73impl fmt::Display for Galaxy {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 write!(f, "{}", self.name)
76 }
77}
78
79use GalaxyType::*;
80
81static GALAXIES: [(&str, GalaxyType); 256] = [
92 ("Euclid", Norm), ("Hilbert Dimension", Norm), ("Calypso", Harsh), ("Hesperius Dimension", Norm), ("Hyades", Norm), ("Ickjamatew", Norm), ("Budullangr", Empty), ("Kikolgallr", Norm), ("Eltiensleen", Norm), ("Eissentam", Lush), ("Elkupalos", Norm), ("Aptarkaba", Empty), ("Ontiniangp", Norm), ("Odiwagiri", Norm), ("Ogtialabi", Harsh), ("Muhacksonto", Norm), ("Hitonskyer", Norm), ("Rerasmutul", Norm), ("Isdoraijung", Lush), ("Doctinawyra", Norm), ("Loychazinq", Norm), ("Zukasizawa", Norm), ("Ekwathore", Harsh), ("Yeberhahne", Norm), ("Twerbetek", Norm), ("Sivarates", Norm), ("Eajerandal", Empty), ("Aldukesci", Norm), ("Wotyarogii", Norm), ("Sudzerbal", Lush), ("Maupenzhay", Norm), ("Sugueziume", Empty), ("Brogoweldian", Norm), ("Ehbogdenbu", Norm), ("Ijsenufryos", Harsh), ("Nipikulha", Norm), ("Autsurabin", Norm), ("Lusontrygiamh", Norm), ("Rewmanawa", Lush), ("Ethiophodhe", Norm), ("Urastrykle", Norm), ("Xobeurindj", Norm), ("Oniijialdu", Harsh), ("Wucetosucc", Norm), ("Ebyeloof", Norm), ("Odyavanta", Norm), ("Milekistri", Empty), ("Waferganh", Norm), ("Agnusopwit", Norm), ("Teyaypilny", Lush), ("Zalienkosm", Norm), ("Ladgudiraf", Empty), ("Mushonponte", Norm), ("Amsentisz", Norm), ("Fladiselm", Harsh), ("Laanawemb", Norm), ("Ilkerloor", Norm), ("Davanossi", Norm), ("Ploehrliou", Lush), ("Corpinyaya", Norm), ("Leckandmeram", Norm), ("Quulngais", Norm), ("Nokokipsechl", Harsh), ("Rinblodesa", Norm), ("Loydporpen", Norm), ("Ibtrevskip", Norm), ("Elkowaldb", Empty), ("Heholhofsko", Norm), ("Yebrilowisod", Norm), ("Husalvangewi", Lush), ("Ovna'uesed", Norm), ("Bahibusey", Empty), ("Nuybeliaure", Norm), ("Doshawchuc", Norm), ("Ruckinarkh", Harsh), ("Thorettac", Norm), ("Nuponoparau", Norm), ("Moglaschil", Norm), ("Uiweupose", Lush), ("Nasmilete", Norm), ("Ekdaluskin", Norm), ("Hakapanasy", Norm), ("Dimonimba", Harsh), ("Cajaccari", Norm), ("Olonerovo", Norm), ("Umlanswick", Norm), ("Henayliszm", Empty), ("Utzenmate", Norm), ("Umirpaiya", Norm), ("Paholiang", Lush), ("Iaereznika", Norm), ("Yudukagath", Empty), ("Boealalosnj", Norm), ("Yaevarcko", Norm), ("Coellosipp", Harsh), ("Wayndohalou", Norm), ("Smoduraykl", Norm), ("Apmaneessu", Norm), ("Hicanpaav", Lush), ("Akvasanta", Norm), ("Tuychelisaor", Norm), ("Rivskimbe", Norm), ("Daksanquix", Harsh), ("Kissonlin", Norm), ("Aediabiel", Norm), ("Ulosaginyik", Norm), ("Roclaytonycar", Empty), ("Kichiaroa", Norm), ("Irceauffey", Norm), ("Nudquathsenfe", Lush), ("Getaizakaal", Norm), ("Hansolmien", Empty), ("Bloytisagra", Norm), ("Ladsenlay", Norm), ("Luyugoslasr", Harsh), ("Ubredhatk", Norm), ("Cidoniana", Norm), ("Jasinessa", Norm), ("Torweierf", Lush), ("Saffneckm", Norm), ("Thnistner", Norm), ("Dotusingg", Norm), ("Luleukous", Harsh), ("Jelmandan", Norm), ("Otimanaso", Norm), ("Enjaxusanto", Norm), ("Sezviktorew", Empty), ("Zikehpm", Norm), ("Bephembah", Norm), ("Broomerrai", Lush), ("Meximicka", Norm), ("Venessika", Empty), ("Gaiteseling", Norm), ("Zosakasiro", Norm), ("Drajayanes", Harsh), ("Ooibekuar", Norm), ("Urckiansi", Norm), ("Dozivadido", Norm), ("Emiekereks", Lush), ("Meykinunukur", Norm), ("Kimycuristh", Norm), ("Roansfien", Norm), ("Isgarmeso", Harsh), ("Daitibeli", Norm), ("Gucuttarik", Norm), ("Enlaythie", Norm), ("Drewweste", Empty), ("Akbulkabi", Norm), ("Homskiw", Norm), ("Zavainlani", Lush), ("Jewijkmas", Norm), ("Itlhotagra", Empty), ("Podalicess", Norm), ("Hiviusauer", Norm), ("Halsebenk", Harsh), ("Puikitoac", Norm), ("Gaybakuaria", Norm), ("Grbodubhe", Norm), ("Rycempler", Lush), ("Indjalala", Norm), ("Fontenikk", Norm), ("Pasycihelwhee", Norm), ("Ikbaksmit", Harsh), ("Telicianses", Norm), ("Oyleyzhan", Norm), ("Uagerosat", Norm), ("Impoxectin", Empty), ("Twoodmand", Norm), ("Hilfsesorbs", Norm), ("Ezdaranit", Lush), ("Wiensanshe", Norm), ("Ewheelonc", Empty), ("Litzmantufa", Norm), ("Emarmatosi", Norm), ("Mufimbomacvi", Harsh), ("Wongquarum", Norm), ("Hapirajua", Norm), ("Igbinduina", Norm), ("Wepaitvas", Lush), ("Sthatigudi", Norm), ("Yekathsebehn", Norm), ("Ebedeagurst", Norm), ("Nolisonia", Harsh), ("Ulexovitab", Norm), ("Iodhinxois", Norm), ("Irroswitzs", Norm), ("Bifredait", Empty), ("Beiraghedwe", Norm), ("Yeonatlak", Norm), ("Cugnatachh", Lush), ("Nozoryenki", Norm), ("Ebralduri", Empty), ("Evcickcandj", Norm), ("Ziybosswin", Norm), ("Heperclait", Harsh), ("Sugiuniam", Norm), ("Aaseertush", Norm), ("Uglyestemaa", Norm), ("Horeroedsh", Lush), ("Drundemiso", Norm), ("Ityanianat", Norm), ("Purneyrine", Norm), ("Dokiessmat", Harsh), ("Nupiacheh", Norm), ("Dihewsonj", Norm), ("Rudrailhik", Norm), ("Tweretnort", Empty), ("Snatreetze", Norm), ("Iwundaracos", Norm), ("Digarlewena", Lush), ("Erquagsta", Norm), ("Logovoloin", Empty), ("Boyaghosganh", Norm), ("Kuolungau", Norm), ("Pehneldept", Harsh), ("Yevettiiqidcon", Norm), ("Sahliacabru", Norm), ("Noggalterpor", Norm), ("Chmageaki", Lush), ("Veticueca", Norm), ("Vittesbursul", Norm), ("Nootanore", Norm), ("Innebdjerah", Harsh), ("Kisvarcini", Norm), ("Cuzcogipper", Norm), ("Pamanhermonsu", Norm), ("Brotoghek", Empty), ("Mibittara", Norm), ("Huruahili", Norm), ("Raldwicarn", Lush), ("Ezdartlic", Norm), ("Badesclema", Empty), ("Isenkeyan", Norm), ("Iadoitesu", Norm), ("Yagrovoisi", Harsh), ("Ewcomechio", Norm), ("Inunnunnoda", Norm), ("Dischiutun", Norm), ("Yuwarugha", Lush), ("Ialmendra", Norm), ("Reponudrle", Norm), ("Rinjanagrbo", Norm), ("Zeziceloh", Harsh), ("Oeileutasc", Norm), ("Zicniijinis", Norm), ("Dugnowarilda", Norm), ("Neuxoisan", Empty), ("Ilmenhorn", Norm), ("Rukwatsuku", Norm), ("Nepitzaspru", Lush), ("Chcehoemig", Norm), ("Haffneyrin", Empty), ("Uliciawai", Norm), ("Tuhgrespod", Norm), ("Iousongola", Harsh), ("Odyalutai", Norm), ];
349
350#[cfg(test)]
351mod tests {
352 use super::*;
353
354 #[test]
355 fn euclid_is_index_zero() {
356 let g = Galaxy::by_index(0);
357 assert_eq!(g.index, 0);
358 assert_eq!(g.name, "Euclid");
359 assert_eq!(g.galaxy_type, GalaxyType::Norm);
360 }
361
362 #[test]
363 fn calypso_is_harsh() {
364 let g = Galaxy::by_index(2);
365 assert_eq!(g.name, "Calypso");
366 assert_eq!(g.galaxy_type, GalaxyType::Harsh);
367 }
368
369 #[test]
370 fn eissentam_is_lush() {
371 let g = Galaxy::by_index(9);
372 assert_eq!(g.name, "Eissentam");
373 assert_eq!(g.galaxy_type, GalaxyType::Lush);
374 }
375
376 #[test]
377 fn budullangr_is_empty() {
378 let g = Galaxy::by_index(6);
379 assert_eq!(g.name, "Budullangr");
380 assert_eq!(g.galaxy_type, GalaxyType::Empty);
381 }
382
383 #[test]
384 fn all_256_valid() {
385 for i in 0..=255u8 {
386 let g = Galaxy::by_index(i);
387 assert_eq!(g.index, i);
388 assert!(!g.name.is_empty());
389 }
390 }
391
392 #[test]
393 fn type_counts() {
394 let mut norm = 0u16;
395 let mut lush = 0u16;
396 let mut harsh = 0u16;
397 let mut empty = 0u16;
398 for i in 0..=255u8 {
399 match Galaxy::by_index(i).galaxy_type {
400 GalaxyType::Norm => norm += 1,
401 GalaxyType::Lush => lush += 1,
402 GalaxyType::Harsh => harsh += 1,
403 GalaxyType::Empty => empty += 1,
404 }
405 }
406 assert_eq!(lush, 25);
407 assert_eq!(harsh, 26);
408 assert_eq!(empty, 26);
409 assert_eq!(norm, 179);
410 }
411
412 #[test]
413 fn last_galaxy() {
414 let g = Galaxy::by_index(255);
415 assert_eq!(g.name, "Odyalutai");
416 }
417
418 #[test]
419 fn galaxy_display() {
420 let g = Galaxy::by_index(0);
421 assert_eq!(format!("{g}"), "Euclid");
422 }
423
424 #[test]
425 fn galaxy_type_display_fromstr_roundtrip() {
426 for gt in [
427 GalaxyType::Norm,
428 GalaxyType::Lush,
429 GalaxyType::Harsh,
430 GalaxyType::Empty,
431 ] {
432 let s = gt.to_string();
433 let parsed: GalaxyType = s.parse().unwrap();
434 assert_eq!(gt, parsed);
435 }
436 }
437
438 #[test]
439 fn galaxy_type_alternate_names() {
440 assert_eq!("norm".parse::<GalaxyType>().unwrap(), GalaxyType::Norm);
441 assert_eq!("normal".parse::<GalaxyType>().unwrap(), GalaxyType::Norm);
442 }
443}