diff options
| author | Kjetil Orbekk <kj@orbekk.com> | 2022-09-04 19:42:57 -0400 |
|---|---|---|
| committer | Kjetil Orbekk <kj@orbekk.com> | 2022-09-04 19:44:53 -0400 |
| commit | ab68d26c6b16f973642d378900f5e6ac2be221b7 (patch) | |
| tree | 357206052643d3ee0b065fd4ee6cb8af928e11f9 /webapp/src/card.rs | |
| parent | b7180143745c5ebe571936b0116cca403d082e8d (diff) | |
Add turn/trick representation
Includes convenience test and parsing utilities
Diffstat (limited to 'webapp/src/card.rs')
| -rw-r--r-- | webapp/src/card.rs | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/webapp/src/card.rs b/webapp/src/card.rs index 4fda0a7..174676f 100644 --- a/webapp/src/card.rs +++ b/webapp/src/card.rs @@ -40,6 +40,33 @@ impl fmt::Display for Suit { } } +#[derive(Debug, PartialEq, Eq)] +pub enum ParseError { + InvalidSuit(String), + InvalidRank(String), + MissingParts(String), +} + +impl std::str::FromStr for Suit { + type Err = ParseError; + + fn from_str(s: &str) -> std::result::Result<Self, ParseError> { + match s.trim() { + "♣" => Ok(Suit::Club), + "C" => Ok(Suit::Club), + "♢" => Ok(Suit::Diamond), + "♦" => Ok(Suit::Diamond), + "D" => Ok(Suit::Diamond), + "♡" => Ok(Suit::Heart), + "♥" => Ok(Suit::Heart), + "H" => Ok(Suit::Heart), + "♠" => Ok(Suit::Spade), + "S" => Ok(Suit::Spade), + _ => Err(ParseError::InvalidSuit(s.to_string())), + } + } +} + impl fmt::Debug for Suit { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { write!(f, "{}", self) @@ -72,6 +99,30 @@ impl fmt::Debug for Rank { } } +impl std::str::FromStr for Rank { + type Err = ParseError; + + fn from_str(s: &str) -> std::result::Result<Self, ParseError> { + match s.trim().to_ascii_uppercase().as_str() { + "A" => Ok(Rank::Ace), + "K" => Ok(Rank::King), + "Q" => Ok(Rank::Queen), + "J" => Ok(Rank::Jack), + "10" => Ok(Rank::Ten), + "T" => Ok(Rank::Ten), + "9" => Ok(Rank::Nine), + "8" => Ok(Rank::Eight), + "7" => Ok(Rank::Seven), + "6" => Ok(Rank::Six), + "5" => Ok(Rank::Five), + "4" => Ok(Rank::Four), + "3" => Ok(Rank::Three), + "2" => Ok(Rank::Two), + _ => Err(ParseError::InvalidRank(s.to_string())), + } + } +} + #[derive(PartialEq, Eq, Clone, Copy)] pub struct Card(pub Suit, pub Rank); @@ -88,6 +139,22 @@ impl fmt::Debug for Card { } } +impl std::str::FromStr for Card { + type Err = ParseError; + + fn from_str(s: &str) -> std::result::Result<Self, ParseError> { + let stripped = s.replace(" ", ""); + let mut chars = stripped.chars(); + let suit = chars + .next() + .ok_or(ParseError::MissingParts(s.to_string()))? + .to_string() + .parse()?; + let rank = chars.collect::<String>().parse()?; + Ok(Card(suit, rank)) + } +} + fn make_deck() -> Vec<Card> { let mut result = vec![]; for suit in Suit::iter() { @@ -98,6 +165,25 @@ fn make_deck() -> Vec<Card> { result } +#[cfg(test)] +mod tests { + use super::*; + use log::info; + + #[test] + fn string_conversion() { + crate::tests::test_setup(); + info!("deck: {:?}", make_deck()); + assert_eq!( + make_deck(), + make_deck() + .iter() + .map(|card| format!("{}", card).parse().unwrap()) + .collect::<Vec<Card>>(), + ); + } +} + pub fn shuffle_deck<R>(rng: &mut R) -> (Vec<Card>, Vec<Card>, Vec<Card>, Vec<Card>) where R: Rng, |
