1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
use std::fmt;
use crate::Rank;
/// A utility enumeration type for pattern matching against the result of
/// [`Eval::class`](super::Eval::class). Each variant represents a class of
/// poker hand. Royal flush is not included, but can be matched against
/// `EvalClass:StraightFlush { high_card: Rank::Ace }` if desired.
///
/// # Example
///
/// ```
/// use poker::{cards, Evaluator, EvalClass, Rank};
///
/// let hand = cards!(
/// Ace of Clubs,
/// Two of Spades,
/// Three of Diamonds,
/// Four of Diamonds,
/// Five of Clubs,
/// );
/// let eval = Evaluator::new();
/// let result = eval.evaluate(&hand).expect("couldn't evaluate hand");
/// assert!(matches!(result.class(), EvalClass::Straight { high_rank: Rank::Five }));
/// ```
///
/// [`Eval::class`]: crate::Eval::class
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum EvalClass {
/// A high card, or no hand.
HighCard {
/// The high card rank.
high_rank: Rank,
},
/// A pair, two cards of the same rank
Pair {
/// The ranks of the pair.
pair: Rank,
},
/// Two pair. two cards of the same rank and two other cards of the same but
/// distinct rank
TwoPair {
/// The ranks of the first pair.
first_pair: Rank,
/// The ranks of the second pair.
second_pair: Rank,
},
/// Three of a kind, three cards of the same rank. Sometimes called trips.
ThreeOfAKind {
/// The ranks of the trips.
trips: Rank,
},
/// A straight, five cards in rank order. Straights go from A2345 to TJQKA.
Straight {
/// The rank of the highest card in the straight.
high_rank: Rank,
},
/// A flush, five cards of the same suit.
Flush {
/// The rank of the highest card in the flush.
high_rank: Rank,
},
/// A full house, one pair and one three of a kind
FullHouse {
/// The rank of the trips of the full house.
trips: Rank,
/// The rank of the pair of the full house.
pair: Rank,
},
/// Four of a kind, four cards of the same rank. Sometimes called quads.
FourOfAKind {
/// The rank of the quads.
quads: Rank,
},
/// A straight flush, like a straight but all the cards are of the same
/// suit.
StraightFlush {
/// The rank of the highest card in the straight flush.
high_rank: Rank,
},
}
impl fmt::Display for EvalClass {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Self::HighCard { high_rank } => write!(f, "High card, {}", high_rank.as_str_name()),
Self::Pair { pair } => write!(f, "Pair, {}", pair.as_str_name_plural()),
Self::TwoPair {
first_pair: high_pair,
second_pair: low_pair,
..
} => write!(
f,
"Two pair, {} and {}",
high_pair.as_str_name_plural(),
low_pair.as_str_name_plural(),
),
Self::ThreeOfAKind { trips } => {
write!(f, "Three of a kind, {}", trips.as_str_name_plural())
}
Self::Straight { high_rank } => {
write!(f, "Straight, {}-high", high_rank.as_str_name())
}
Self::Flush { high_rank } => write!(f, "Flush, {}-high", high_rank.as_str_name()),
Self::FullHouse { trips, pair } => write!(
f,
"Full house, {} over {}",
trips.as_str_name_plural(),
pair.as_str_name_plural()
),
Self::FourOfAKind { quads, .. } => {
write!(f, "Four of a kind, {}", quads.as_str_name_plural())
}
Self::StraightFlush { high_rank, .. } => match high_rank {
Rank::Ace => write!(f, "Royal flush"),
high_rank => write!(f, "Straight flush, {}-high", high_rank.as_str_name()),
},
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn eval_class_derived_ord_works() {
let class1 = EvalClass::HighCard {
high_rank: Rank::Ace,
};
let class2 = EvalClass::HighCard {
high_rank: Rank::King,
};
assert!(class1 > class2);
let class3 = EvalClass::Pair { pair: Rank::Two };
assert!(class3 > class1);
}
}