modes:pair: use impl_cmp_eq_on_ord macro for ordering.

This commit is contained in:
2026-04-12 06:37:08 +01:00
committed by oreodave
parent 76f180d4c6
commit 6e94f05443

View File

@@ -1,6 +1,6 @@
use crate::{card::Card, helper::ordered}; use crate::{card::Card, helper::ordered};
#[derive(Eq, Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct Pair(Card, Card); pub struct Pair(Card, Card);
impl Pair { impl Pair {
@@ -12,8 +12,6 @@ impl Pair {
playing card. playing card.
*/ */
pub fn new(c1: Card, c2: Card) -> Option<Pair> { pub 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]); let [c1, c2] = ordered([c1, c2]);
match [c1, c2].map(|c| c.rank()) { match [c1, c2].map(|c| c.rank()) {
@@ -26,44 +24,7 @@ impl Pair {
} }
} }
use crate::modes::{single::Single, Footstool, Hand}; use crate::helper::impl_cmp_eq_on_ord;
impl Hand for Pair {
fn is_proper(&self) -> bool {
matches!(self.0, Card::PlayingCard(_))
}
fn footstool(&self, b: &Self) -> Footstool {
match self.cmp(b) {
// There is no footstool if self is beaten by other.
Ordering::Less => Footstool::None,
// We can only full footstool if we have equivalent pairs.
Ordering::Equal => Footstool::Full,
// Half footstools can proc if self.1 footstools other.1 (full or
// half).
Ordering::Greater => {
// By construction, Pair::1 is always a playing card so we may
// safely unwrap here.
let s1 = Single::new(self.1).unwrap();
let s2 = Single::new(b.1).unwrap();
if s1.footstool(&s2) != Footstool::None {
Footstool::Half
} else {
Footstool::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; use std::cmp::Ordering;
impl Ord for Pair { impl Ord for Pair {
@@ -77,15 +38,42 @@ impl Ord for Pair {
} }
} }
impl PartialEq for Pair { impl_cmp_eq_on_ord!(Pair);
fn eq(&self, other: &Self) -> bool {
self.cmp(other) == Ordering::Equal use crate::modes::{single::Single, Footstool, Hand};
impl Hand for Pair {
fn is_proper(&self) -> bool {
!self.0.is_joker()
}
fn footstool(&self, b: &Self) -> Footstool {
match self.cmp(b) {
// There is no footstool if self is beaten by other.
Ordering::Less => Footstool::None,
// We can only full footstool if we have equivalent pairs.
Ordering::Equal => Footstool::Full,
// Half footstools can proc if self.1 footstools other.1 (full or
// half) using Single rules.
Ordering::Greater => {
// By construction, Pair::1 is always a playing card so we may
// safely unwrap here.
let s1 = Single::new(self.1).unwrap();
let s2 = Single::new(b.1).unwrap();
match s1.footstool(&s2) {
Footstool::None => Footstool::None,
_ => Footstool::Half,
}
}
}
} }
} }
impl PartialOrd for Pair { use std::fmt::{Display, Formatter, Result};
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other)) impl Display for Pair {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
write!(f, "Pair[{}, {}]", self.0, self.1)
} }
} }
@@ -162,7 +150,7 @@ mod tests {
// TEST: Improper pairs have a playing card in Pair::1. // TEST: Improper pairs have a playing card in Pair::1.
assert!( assert!(
matches!(pair.1, Card::PlayingCard(_)), !pair.1.is_joker(),
"Expected {} to be a playing card", "Expected {} to be a playing card",
pair.1 pair.1
); );