summaryrefslogtreecommitdiff
path: root/webapp/src/card.rs
diff options
context:
space:
mode:
authorKjetil Orbekk <kj@orbekk.com>2022-09-04 19:42:57 -0400
committerKjetil Orbekk <kj@orbekk.com>2022-09-04 19:44:53 -0400
commitab68d26c6b16f973642d378900f5e6ac2be221b7 (patch)
tree357206052643d3ee0b065fd4ee6cb8af928e11f9 /webapp/src/card.rs
parentb7180143745c5ebe571936b0116cca403d082e8d (diff)
Add turn/trick representation
Includes convenience test and parsing utilities
Diffstat (limited to 'webapp/src/card.rs')
-rw-r--r--webapp/src/card.rs86
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,