use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[non_exhaustive]
pub enum GalaxyType {
Norm,
Lush,
Harsh,
Empty,
}
impl fmt::Display for GalaxyType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Norm => write!(f, "Normal"),
Self::Lush => write!(f, "Lush"),
Self::Harsh => write!(f, "Harsh"),
Self::Empty => write!(f, "Empty"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GalaxyTypeParseError(pub String);
impl fmt::Display for GalaxyTypeParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "unknown galaxy type: {}", self.0)
}
}
impl std::error::Error for GalaxyTypeParseError {}
impl FromStr for GalaxyType {
type Err = GalaxyTypeParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"norm" | "normal" => Ok(Self::Norm),
"lush" => Ok(Self::Lush),
"harsh" => Ok(Self::Harsh),
"empty" => Ok(Self::Empty),
_ => Err(GalaxyTypeParseError(s.to_string())),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct Galaxy {
pub index: u8,
pub name: &'static str,
pub galaxy_type: GalaxyType,
}
impl Galaxy {
pub fn by_index(index: u8) -> Self {
let (name, galaxy_type) = GALAXIES[index as usize];
Self {
index,
name,
galaxy_type,
}
}
}
impl fmt::Display for Galaxy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name)
}
}
use GalaxyType::*;
static GALAXIES: [(&str, GalaxyType); 256] = [
("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), ];
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn euclid_is_index_zero() {
let g = Galaxy::by_index(0);
assert_eq!(g.index, 0);
assert_eq!(g.name, "Euclid");
assert_eq!(g.galaxy_type, GalaxyType::Norm);
}
#[test]
fn calypso_is_harsh() {
let g = Galaxy::by_index(2);
assert_eq!(g.name, "Calypso");
assert_eq!(g.galaxy_type, GalaxyType::Harsh);
}
#[test]
fn eissentam_is_lush() {
let g = Galaxy::by_index(9);
assert_eq!(g.name, "Eissentam");
assert_eq!(g.galaxy_type, GalaxyType::Lush);
}
#[test]
fn budullangr_is_empty() {
let g = Galaxy::by_index(6);
assert_eq!(g.name, "Budullangr");
assert_eq!(g.galaxy_type, GalaxyType::Empty);
}
#[test]
fn all_256_valid() {
for i in 0..=255u8 {
let g = Galaxy::by_index(i);
assert_eq!(g.index, i);
assert!(!g.name.is_empty());
}
}
#[test]
fn type_counts() {
let mut norm = 0u16;
let mut lush = 0u16;
let mut harsh = 0u16;
let mut empty = 0u16;
for i in 0..=255u8 {
match Galaxy::by_index(i).galaxy_type {
GalaxyType::Norm => norm += 1,
GalaxyType::Lush => lush += 1,
GalaxyType::Harsh => harsh += 1,
GalaxyType::Empty => empty += 1,
}
}
assert_eq!(lush, 25);
assert_eq!(harsh, 26);
assert_eq!(empty, 26);
assert_eq!(norm, 179);
}
#[test]
fn last_galaxy() {
let g = Galaxy::by_index(255);
assert_eq!(g.name, "Odyalutai");
}
#[test]
fn galaxy_display() {
let g = Galaxy::by_index(0);
assert_eq!(format!("{g}"), "Euclid");
}
#[test]
fn galaxy_type_display_fromstr_roundtrip() {
for gt in [
GalaxyType::Norm,
GalaxyType::Lush,
GalaxyType::Harsh,
GalaxyType::Empty,
] {
let s = gt.to_string();
let parsed: GalaxyType = s.parse().unwrap();
assert_eq!(gt, parsed);
}
}
#[test]
fn galaxy_type_alternate_names() {
assert_eq!("norm".parse::<GalaxyType>().unwrap(), GalaxyType::Norm);
assert_eq!("normal".parse::<GalaxyType>().unwrap(), GalaxyType::Norm);
}
}