open_pql/functions/
equity.rs1use super::*;
2
3#[allow(clippy::cast_precision_loss)]
4#[pqlfn(arg, rtn, eval)]
5pub fn equity(
6 pid: PQLPlayer,
7 street: PQLStreet,
8 (game, board, player_hands, ratings): (
9 PQLGame,
10 Board,
11 &PlayerHands,
12 &mut BufferRatings,
13 ),
14) -> PQLDouble {
15 if street == PQLStreet::River {
16 fill_ratings(PQLStreet::River, (game, board, player_hands, ratings));
17
18 let max = ratings.max();
19
20 if max == ratings[pid] {
21 1.0 / ratings.iter().filter(|r| **r == max).count() as f64
22 } else {
23 0.0
24 }
25 } else if street == PQLStreet::Turn {
26 let mut eq = 0.0;
27 let mut count = 0;
28 for c in Card::ARR_ALL {
29 if board.contains_card(c) || card_in(player_hands, c) {
30 continue;
31 }
32
33 fill_ratings(
34 PQLStreet::River,
35 (game, board.swap_river(c), player_hands, ratings),
36 );
37
38 let max = ratings.max();
39
40 if max == ratings[pid] {
41 eq +=
42 1.0 / ratings.iter().filter(|r| **r == max).count() as f64;
43 }
44
45 count += 1;
46 }
47
48 eq / f64::from(count)
49 } else {
50 todo!()
51 }
52}
53
54fn card_in(hs: &PlayerHands, c: Card) -> bool {
55 for h in hs {
56 if h.contains(&c) {
57 return true;
58 }
59 }
60
61 false
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67 use crate::*;
68
69 #[quickcheck]
70 fn test_min_outs_to_hand_type(hbg: HandBoardGame, ht: HandType) {
71 let HandBoardGame {
72 game,
73 hand,
74 board,
75 dead,
76 ..
77 } = hbg;
78
79 let ht = PQLHandType::from((ht, game));
80 let outs =
81 outs_to_hand_type(&hand, PQLStreet::Flop, ht, (game, board, dead));
82
83 assert!(min_outs_to_hand_type(
84 &hand,
85 PQLStreet::Flop,
86 ht,
87 outs.saturating_sub(1),
88 (game, board, dead)
89 ));
90
91 assert!(!min_outs_to_hand_type(
92 &hand,
93 PQLStreet::Flop,
94 ht,
95 outs + 1,
96 (game, board, dead)
97 ));
98 }
99}