If we auto-derived Ord it would look at Pair::0 first, when it should look at Pair::1. Hence the custom implementation.
73 lines
2.2 KiB
Rust
73 lines
2.2 KiB
Rust
use crate::card::{Card, PlayingCard};
|
|
use crate::helper::ordered;
|
|
|
|
#[derive(Eq, Debug, Copy, Clone)]
|
|
pub struct Pair(Card, Card);
|
|
|
|
impl Pair {
|
|
/** Create a new pair utilising two cards, `c1` and `c2`. Will return None
|
|
if a Pair cannot be constructed out of the two cards.
|
|
|
|
NOTE: By construction, if the Pair includes a Joker, that Joker will be the
|
|
first member of the pair.
|
|
*/
|
|
fn new(c1: Card, c2: Card) -> Option<Pair> {
|
|
// Order the cards. This means if xor(c1 is joker, c2 is joker) c1 will
|
|
// be that joker.
|
|
let (c1, c2) = ordered(c1, c2);
|
|
|
|
match (c1, c2) {
|
|
// Can't be a pair if you got two jokers homie.
|
|
(Card::Joker(_), Card::Joker(_)) => None,
|
|
|
|
// NOTE: c2 cannot be a joker because of prev condition. If you've
|
|
// got a joker you're automatically a pair.
|
|
(Card::Joker(_), _) => Some(Pair(c1, c2)),
|
|
|
|
// NOTE: c1 and c2 cannot be jokers. In which case, check their
|
|
// ranks are equivalent.
|
|
(
|
|
Card::PlayingCard(PlayingCard { rank: r1, .. }),
|
|
Card::PlayingCard(PlayingCard { rank: r2, .. }),
|
|
) => (r1 == r2).then_some(Pair(c1, c2)),
|
|
|
|
// Not necessary since the previous patterns technically cover all
|
|
// cases. But I love the compiler too much to tell them... 💔
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
use std::fmt::{Display, Formatter, Result};
|
|
|
|
impl Display for Pair {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
|
write!(f, "Pair({}, {})", self.0, self.1)
|
|
}
|
|
}
|
|
|
|
use std::cmp::Ordering;
|
|
|
|
impl Ord for Pair {
|
|
fn cmp(&self, other: &Self) -> Ordering {
|
|
match (self.0.cmp(&other.0), self.1.cmp(&other.1)) {
|
|
// If Pair::1 are equal, then it's dependent on Pair::0
|
|
(x, Ordering::Equal) => x,
|
|
// Otherwise leave it to Pair::1
|
|
(_, x) => x,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PartialEq for Pair {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.cmp(other) == Ordering::Equal
|
|
}
|
|
}
|
|
|
|
impl PartialOrd for Pair {
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
Some(self.cmp(other))
|
|
}
|
|
}
|