open_pql/functions/
flop_hand_category.rs

1use super::*;
2#[pqlfn(arg, rtn, eval)]
3/// # Panics
4/// high rank bits from ranking is always non-empty
5pub fn flop_hand_category(
6    hand: &Hand,
7    (game, flop): (PQLGame, Flop),
8) -> PQLFlopHandCategory {
9    let board = Board::from(flop);
10
11    let rating = hi_rating(hand, PQLStreet::Flop, (game, board));
12
13    let (ht, _, high) = rating.to_hand_type_and_low_high_ranks(game);
14
15    (
16        match ht.ht {
17            HandType::StraightFlush => FlopHandCategory::StraightFlush,
18            HandType::Quads => FlopHandCategory::Quads,
19            HandType::FullHouse => FlopHandCategory::FullHouse,
20            HandType::Flush => FlopHandCategory::Flush,
21            HandType::Straight => FlopHandCategory::Straight,
22            HandType::Trips => {
23                let trips_rank = max_rank(high).unwrap();
24
25                if flop.count_by_rank(trips_rank) == 2 {
26                    FlopHandCategory::Trips
27                } else {
28                    FlopHandCategory::Set
29                }
30            }
31            HandType::TwoPair => {
32                let (top, mid, _) = flop.sorted_ranks();
33
34                match (high.contains_rank(top), high.contains_rank(mid)) {
35                    (true, true) => FlopHandCategory::TopTwo,
36                    (true, _) => FlopHandCategory::TopAndBottom,
37                    (_, _) => FlopHandCategory::BottomTwo,
38                }
39            }
40            HandType::Pair => {
41                let pair_rank = max_rank(high).unwrap();
42
43                let (top, mid, btm) = flop.sorted_ranks();
44
45                if pair_rank > top {
46                    FlopHandCategory::Overpair
47                } else if pair_rank == top {
48                    FlopHandCategory::TopPair
49                } else if pair_rank > mid {
50                    FlopHandCategory::Pocket12
51                } else if pair_rank == mid {
52                    FlopHandCategory::SecondPair
53                } else if pair_rank > btm {
54                    FlopHandCategory::Pocket23
55                } else if pair_rank == btm {
56                    FlopHandCategory::ThirdPair
57                } else {
58                    FlopHandCategory::UnderPair
59                }
60            }
61            HandType::HighCard => FlopHandCategory::Nothing,
62        },
63        game,
64    )
65        .into()
66}
67
68#[cfg(test)]
69mod tests {
70    use FlopHandCategory::*;
71
72    use super::*;
73    use crate::*;
74
75    fn assert_flop_cat(g: PQLGame, s: &str, c: FlopHandCategory) {
76        let mut s = s.split('|');
77
78        assert_eq!(
79            flop_hand_category(
80                cards!(s.next().unwrap()).as_ref(),
81                (g, flop!(s.next().unwrap())),
82            ),
83            (c, g).into()
84        );
85    }
86
87    #[test]
88    fn test_flop_hand_category_holdem() {
89        let g = PQLGame::Holdem;
90        assert_flop_cat(g, "8s 9s | 7s 6s Ts", StraightFlush);
91        assert_flop_cat(g, "8s 8h | 8d 8c Ts", Quads);
92        assert_flop_cat(g, "7s 6s | 7h 6h 6c", FullHouse);
93        assert_flop_cat(g, "8s 9s | 7s 6s 2s", Flush);
94        assert_flop_cat(g, "8d 9s | 7s 6h Tc", Straight);
95        assert_flop_cat(g, "7h 7d | 7s 6h Tc", Set);
96        assert_flop_cat(g, "7d 8s | 7s 7h Tc", Trips);
97        assert_flop_cat(g, "8s Ts | 7s 8h Tc", TopTwo);
98        assert_flop_cat(g, "7c Ts | 7s 8h Tc", TopAndBottom);
99        assert_flop_cat(g, "7c 8c | 7s 8h Tc", BottomTwo);
100        assert_flop_cat(g, "Js Jh | 7s 8h Tc", Overpair);
101        assert_flop_cat(g, "Ts Ah | 7s 8h Tc", TopPair);
102        assert_flop_cat(g, "9s 9h | 7s 8h Tc", Pocket12);
103        assert_flop_cat(g, "8s Ah | 7s 8h Tc", SecondPair);
104        assert_flop_cat(g, "7s 7h | 6s 8h Tc", Pocket23);
105        assert_flop_cat(g, "7h Ah | 7s 8h Tc", ThirdPair);
106        assert_flop_cat(g, "4s 4h | 6s 8h Tc", UnderPair);
107        assert_flop_cat(g, "4s 2h | 6s 8h Tc", Nothing);
108    }
109
110    #[test]
111    fn test_flop_hand_category_omaha() {
112        let g = PQLGame::Omaha;
113        assert_flop_cat(g, "3d 6c As Ks | Qs Js Ts", StraightFlush);
114        assert_flop_cat(g, "3d 6c As Ah | Ad Ac Ks", Quads);
115        assert_flop_cat(g, "3d 6c As Ah | Ad Kc Ks", FullHouse);
116        assert_flop_cat(g, "3d 6c As Ks | Qs Js 9s", Flush);
117        assert_flop_cat(g, "3d 6c As Kh | Qd Jc Ts", Straight);
118        assert_flop_cat(g, "3d 6c As Ah | Ad Kc Qs", Set);
119        assert_flop_cat(g, "3d 6c As 2h | Ad Ac Qs", Trips);
120        assert_flop_cat(g, "3d 6c Js Qh | Td Jc Qs", TopTwo);
121        assert_flop_cat(g, "3d 6c Ts Qh | Td Jc Qs", TopAndBottom);
122        assert_flop_cat(g, "3d 6c Js Th | Td Jc Qs", BottomTwo);
123        assert_flop_cat(g, "3d 6c As Ah | Kd Qc Js", Overpair);
124        assert_flop_cat(g, "3d 6c Ks 2h | Kd Qc Js", TopPair);
125        assert_flop_cat(g, "3d 6c Qs Qh | Kd Tc 7s", Pocket12);
126        assert_flop_cat(g, "3d 6c Ts 2h | Kd Tc 7s", SecondPair);
127        assert_flop_cat(g, "3d 6c 9s 9h | Kd Tc 7s", Pocket23);
128        assert_flop_cat(g, "3d 6c 7s 2h | Kd Tc 7s", ThirdPair);
129        assert_flop_cat(g, "3d 6c 2s 2h | Kd Tc 7s", UnderPair);
130        assert_flop_cat(g, "3d 6c As Kh | Qd Jc 9s", Nothing);
131    }
132}