Skip to main content

opql/types/
pql_board_range.rs

1use super::*;
2
3pub struct PQLBoardRange(pub(crate) FnCheckRange, RangeSrc, PQLGame);
4
5impl fmt::Debug for PQLBoardRange {
6    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7        f.debug_tuple("PQLBoardRange")
8            .field(&self.1)
9            .field(&self.2)
10            .finish()
11    }
12}
13
14impl PQLBoardRange {
15    #[inline]
16    pub fn is_satisfied(&self, cs: &[PQLCard]) -> bool {
17        (self.0)(cs)
18    }
19}
20
21/// # Panics
22/// `PQLBoardRange` ensures valid range text
23impl Clone for PQLBoardRange {
24    fn clone(&self) -> Self {
25        (self.2, self.1.as_str()).try_into().unwrap()
26    }
27}
28
29#[cfg(test)]
30impl PQLBoardRange {
31    /// AK != KA but good for assertions in tests
32    pub fn src_eq(&self, other: &Self) -> bool {
33        self.1 == other.1 && self.2 == other.2
34    }
35}
36
37impl Default for PQLBoardRange {
38    fn default() -> Self {
39        Self(Box::new(|_| true), "*".into(), PQLGame::default())
40    }
41}
42
43impl TryFrom<(PQLGame, &str)> for PQLBoardRange {
44    type Error = PQLErrorKind;
45
46    fn try_from((game, src): (PQLGame, &str)) -> Result<Self, Self::Error> {
47        fn create_range<const SD: bool>(
48            checker: BoardRangeChecker<SD>,
49            src: &str,
50            game: PQLGame,
51        ) -> PQLBoardRange {
52            PQLBoardRange(
53                Box::new(move |cs: &[PQLCard]| checker.is_satisfied(cs)),
54                src.to_string(),
55                game,
56            )
57        }
58
59        if game == PQLGame::ShortDeck {
60            Ok(create_range(
61                BoardRangeChecker::<true>::from_src(src)?,
62                src,
63                game,
64            ))
65        } else {
66            Ok(create_range(
67                BoardRangeChecker::<false>::from_src(src)?,
68                src,
69                game,
70            ))
71        }
72    }
73}
74
75#[cfg(test)]
76pub mod tests {
77    use super::*;
78    use crate::*;
79
80    #[test]
81    fn test_err() {
82        for game in [PQLGame::Holdem, PQLGame::Omaha, PQLGame::ShortDeck] {
83            let res = PQLBoardRange::try_from((game, "AAAAKK")).unwrap_err();
84
85            assert_eq!(
86                res,
87                RangeError::TooManyCardsInRange((0, "AAAAKK".len())).into()
88            );
89        }
90    }
91
92    #[quickcheck]
93    fn test_clone(cards: CardN<5, true>) {
94        let res = PQLBoardRange::try_from((PQLGame::default(), "BB")).unwrap();
95        let cloned = res.clone();
96
97        assert_eq!(
98            res.is_satisfied(cards.as_slice()),
99            cloned.is_satisfied(cards.as_slice()),
100        );
101
102        let res = PQLBoardRange::try_from((PQLGame::ShortDeck, "BB")).unwrap();
103        let cloned = res.clone();
104
105        assert_eq!(
106            res.is_satisfied(cards.as_slice()),
107            cloned.is_satisfied(cards.as_slice()),
108        );
109    }
110}