X7KNY5KWCOLA2V345PUT4EVXVNHL6RGSJK3NNR6DHPOUC33HHCCAC use regex::Regex;use std::{collections::{HashMap, HashSet},sync::{Arc, Mutex, OnceLock},};#[derive(Debug, Clone)]pub enum Card {Magister {},Fragment {},}#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]pub enum FragmentProperties {/// Is not sent to the graveyard on resolutionLingering,/// Must be Set before it can be activatedPrepared,/// Can be activated during any time GES is half-closed/// (as compared to the default of whes GES is open during *your* Main Phase(s))Impulse,/// Can be activated the turn it is set.Rush,}
pub enum Card {}
pub struct Subtype(HashSet<Arc<str>>);impl Subtype {pub fn new<S: AsRef<str>>(subtype: S) -> Self {Self(subtype.as_ref().trim().to_lowercase().split_whitespace().map(|s| Arc::from(s)).collect(),)}/// Provide an [`Iterator`] of all subtypespub fn subtypes(&self) -> impl ExactSizeIterator<Item = &str> {self.0.iter().map(|s| s.as_ref())}/// Check if this subtype is a member of a given subtype grouppub fn is_member<S: AsRef<str>>(&self, member: S) -> bool {let member = member.as_ref().to_lowercase();self.0.iter().any(|sm| sm.as_ref() == member)}/// Check if this subtype is a quasimember of a given subtype grouppub fn is_quasimember<S: AsRef<str>>(&self, quasimember: S) -> bool {static SUBTYPE_REGEXES: OnceLock<Mutex<HashMap<Arc<str>, Regex>>> = OnceLock::new();let mut subtype_regex_map = SUBTYPE_REGEXES.get_or_init(|| Mutex::new(HashMap::new())).lock().unwrap();let subtype_regex = subtype_regex_map.entry(Arc::from(quasimember.as_ref())).or_insert(Regex::new(&format!(r"\b{}\b",regex::escape(&quasimember.as_ref().to_lowercase()))).unwrap(),);self.0.iter().any(|sm| subtype_regex.is_match(&sm))}}
#[cfg(test)]mod tests {use super::Subtype;#[test]fn membership_will_only_match_whole_subtypes() {let subtype = Subtype::new("Mad Relic");let subtype2 = Subtype::new("Mad-Devouring Dragon");assert!(subtype.is_member("Mad"));assert!(!subtype2.is_member("Mad"));}#[test]fn quasimembership_matches_words_in_subtypes() {let subtype = Subtype::new("Mad Relic");let subtype2 = Subtype::new("Mad-Devouring Dragon");assert!(subtype.is_quasimember("Mad"));assert!(subtype2.is_quasimember("Mad"));assert!(!subtype2.is_quasimember("evo"));}#[test]fn membership_and_quasimembership_are_caseinsensitive() {let subtype = Subtype::new("Magic-Spellcaster Ruler");assert!(subtype.is_member("MAGIC-SPELLCASTER"));assert!(subtype.is_quasimember("SPELLcAsTeR"));}}