open_pql/base/isomorphic/
mod.rs1use super::{Board, Card, Flop, HandN, Suit};
2
3mod suit_mapping;
4pub use suit_mapping::*;
5
6pub const IDX_TURN: usize = 3;
8pub const IDX_RIVER: usize = 4;
10pub const N_FLOP: usize = 3;
12
13impl<const N: usize> HandN<N> {
14 pub fn new_iso_with_mapping(
15 cards: &[Card],
16 mapping: &mut SuitMapping,
17 ) -> Self {
18 Self::new(create_iso_array(cards, mapping))
19 }
20
21 pub fn new_iso(cards: &[Card]) -> (Self, SuitMapping) {
22 let mut mapping = SuitMapping::default();
23 let iso = Self::new_iso_with_mapping(cards, &mut mapping);
24 (iso, mapping)
25 }
26}
27
28impl Board {
29 pub fn new_iso_with_mapping(
30 cards: &[Card],
31 mapping: &mut SuitMapping,
32 ) -> Self {
33 create_iso_board(cards, mapping)
34 }
35}
36
37fn create_iso_array<const N: usize>(
38 cards: &[Card],
39 mapping: &mut SuitMapping,
40) -> [Card; N] {
41 let mut sorted = cards[..N]
42 .iter()
43 .map(|c| {
44 (
45 cards[..N].iter().filter(|&el| el.suit == c.suit).count(),
46 c.rank,
47 c,
48 )
49 })
50 .collect::<Vec<_>>();
51
52 sorted.sort_unstable();
53
54 let mut res = [Card::default(); N];
55
56 for (i, (_, _, card)) in sorted.into_iter().enumerate() {
57 res[i] = Card::new(card.rank, mapping.map_suit(card.suit));
58 }
59
60 res.sort_unstable();
61
62 res
63}
64
65fn create_iso_board(board_cards: &[Card], mapping: &mut SuitMapping) -> Board {
66 let n = board_cards.len();
67 let mut board = Board::default();
68
69 if n >= N_FLOP {
70 board.flop =
71 Some(Flop::new(create_iso_array(&board_cards[..N_FLOP], mapping)));
72 }
73
74 if n > IDX_TURN {
75 let card = board_cards[IDX_TURN];
76 board.turn = Some(Card::new(card.rank, mapping.map_suit(card.suit)));
77 }
78
79 if n > IDX_RIVER {
80 let card = board_cards[IDX_RIVER];
81 board.river = Some(Card::new(card.rank, mapping.map_suit(card.suit)));
82 }
83
84 board
85}
86
87pub const fn to_suitvar_char(s: Suit) -> char {
89 match s {
90 Suit::S => 'w',
91 Suit::H => 'x',
92 Suit::D => 'y',
93 Suit::C => 'z',
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use std::collections::{HashMap, HashSet};
100
101 use super::*;
102 use crate::*;
103
104 #[test]
105 fn test_to_suitvar_char() {
106 assert_eq!(to_suitvar_char(Suit::S), 'w');
108 assert_eq!(to_suitvar_char(Suit::H), 'x');
109 assert_eq!(to_suitvar_char(Suit::D), 'y');
110 assert_eq!(to_suitvar_char(Suit::C), 'z');
111 }
114
115 #[test]
116 fn test_iso() {
117 assert_eq!(
118 HandN::<5>::new_iso(&cards!("6s8h9dQdQc")).0,
119 HandN::<5>::new_iso(&cards!("6s8h9dQcQd")).0
120 );
121 }
122
123 #[test]
124 fn test_iso_flop() {
125 let mut res: HashMap<HandN<3>, HandN<3>> = HashMap::new();
126 let mut iso_set: HashSet<HandN<3>> = HashSet::default();
127 for hand in HandN::<3>::iter_all_short() {
128 let (iso, _) = HandN::new_iso(&hand.0);
129 res.insert(hand, iso);
130 iso_set.insert(iso);
131 }
132
133 assert_eq!(res.len(), 7140);
134 assert_eq!(iso_set.len(), 573);
135 }
136}