poker_odds 0.1.1 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 727beb1f40c45f4ab9b77d0a2b7c21da81b8fc8105414f516fdb04bed4e4bded
4
- data.tar.gz: 107c85dabd7f0c4a68900fef7fe91e1d55604422e58403d5b95dfc3323838478
3
+ metadata.gz: f204234da42a8bd00fd9d1407dc188a9ea79856591b1bedb2e9c7d2d9c22cb34
4
+ data.tar.gz: b0884f1224a3e5655b92b3d602551c42fd42a89d9d0779d4331da8585c03f767
5
5
  SHA512:
6
- metadata.gz: 41eecbb09877d4da4e99adacacb539f620b3616ace9584ad8c6cdc0a5d952b2db48e33f6b34fbecf4b36c8e9a0300541762c43ddf77871f4e9ffc848eaab89f5
7
- data.tar.gz: b0e379b966eab71eb0d1eddac1f43cc54ff59f2357daf7f371598a8467b77d8da6ed63a6581685bf2c1cd9ad7cb4341a686df68c6d2147fa2d3bb231a196a1ab
6
+ metadata.gz: 2d980e663b61d2a91c6f7a68e5d8ab58873f927260f208162040dcee38043988ca3581a68b4253f78f32fa046ac0426ba59234357e4cdef5f6577cd203445b0f
7
+ data.tar.gz: 11738e7f2a97870f45c7db7aa9c33b12409780d971d513aef0ec7f6cfc85d1541a762f0ecfc8fdc8e4bc3e4649356753386733f57bb7c958546dcafd676b2cc6
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/poker_odds`. To experiment with that code, run `bin/console` for an interactive prompt.
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ ポーカーのエクイティが分かる
6
6
 
7
7
  ## Installation
8
8
 
@@ -23,22 +23,14 @@ Or install it yourself as:
23
23
  ## Usage
24
24
 
25
25
  ```
26
- round = PokerOdds::Round.new(flop: 'Ah 9h Jd', turn: '3d')
27
- round.add_hand("9d 9c")
28
- round.add_hand("Kd Kc")
26
+ round = PokerOdds::Hand.new(flop: 'Ah 9h Jd', turn: '3d')
27
+ round.player='9d 9c, Kd Kc'
29
28
 
30
29
  round.equities
31
30
  # =>
32
- [{:hand=>[{:rank=>"K", :suit=>:d}, {:rank=>"K", :suit=>:c}],
33
- :win_rate=>0.045454545454545456,
34
- :lose_rate=>0.9545454545454546,
35
- :tie_rate=>0.0,
36
- :outs=>[{:suit=>:s, :rank=>"K"}, {:suit=>:h, :rank=>"K"}]},
37
- {:hand=>[{:rank=>"9", :suit=>:d}, {:rank=>"9", :suit=>:c}],
38
- :win_rate=>0.9545454545454546,
39
- :lose_rate=>0.045454545454545456,
40
- :tie_rate=>0.0,
41
- :outs=>[]}]
31
+ {[#<PokerTrump::Card:0x00007fedc3889ab0 @rank="9", @suit=:d>, #<PokerTrump::Card:0x00007fedc38898f8 @rank="9", @suit=:c>]=>{:win_rate=>0.9545454545454546, :lose_rate=>0.045454545454545456, :tie_rate=>0.0},
32
+ [#<PokerTrump::Card:0x00007fedc3889650 @rank="K", @suit=:d>, #<PokerTrump::Card:0x00007fedc38894e8 @rank="K", @suit=:c>]=>
33
+ {:win_rate=>0.045454545454545456, :lose_rate=>0.9545454545454546, :tie_rate=>0.0, :outs=>[#<PokerTrump::Card:0x00007feda08a3208 @rank="K", @suit=:s>, #<PokerTrump::Card:0x00007feda08a2bc8 @rank="K", @suit=:h>]}}
42
34
 
43
35
  ```
44
36
 
@@ -0,0 +1,165 @@
1
+ module PokerOdds
2
+ class Hand
3
+ include Virtus.model
4
+
5
+ attribute :player_hands, Array, default: []
6
+ attribute :flop_cards, PokerTrump::Cards
7
+ attribute :turn_card, PokerTrump::Card
8
+ attribute :river_card, PokerTrump::Card
9
+
10
+ attribute :expose_cards, PokerTrump::Cards
11
+
12
+ def player=(str)
13
+ self.player_hands = str.split(',').map do |s|
14
+ PokerTrump::Cards.from_string(s.lstrip)
15
+ end
16
+ self
17
+ end
18
+
19
+ def flop=(str)
20
+ self.flop_cards = PokerTrump::Cards.from_string(str)
21
+ self
22
+ end
23
+
24
+ def turn=(str)
25
+ self.turn_card = PokerTrump::Card.from_string(str)
26
+ self
27
+ end
28
+
29
+ def river=(s)
30
+ self.river_cards = PokerTrump::Card.from_string(str)
31
+ self
32
+ end
33
+
34
+ def equities
35
+ z = deck.each_with_object({}) do |card, a|
36
+ scores = player_hands.each_with_object({}) do |player_hand, h|
37
+ cards = player_hand
38
+ cards = cards.add_cards(flop_cards)
39
+ cards = cards.add_card(turn_card)
40
+ cards = cards.add_card(card)
41
+
42
+ h[cards.score] ||= []
43
+ h[cards.score] << player_hand
44
+ end
45
+
46
+ a[card] = {}
47
+ if scores.keys.size == 1
48
+ a[card][:tie_hands] = player_hands
49
+ else
50
+ mk = scores.keys.max
51
+ a[card][:win_hands] = scores[mk]
52
+ a[card][:lose_hands] = scores.each_with_object([]) do |(k,v), a|
53
+ next if k == mk
54
+
55
+ a.concat(v)
56
+ end
57
+ end
58
+ end
59
+
60
+ s = z.size.to_f
61
+
62
+ player_hands.each_with_object({}) do |player_hand, h|
63
+ win_hands = z.select { |a,b| b[:win_hands]&.include?(player_hand) }
64
+ win_rate = win_hands.size / s
65
+ h[player_hand] = {}
66
+ h[player_hand][:win_rate] = win_rate
67
+ h[player_hand][:lose_rate] = z.count { |a,b| b[:lose_hands]&.include?(player_hand) } / s
68
+ h[player_hand][:tie_rate] = z.count { |a,b| b[:tie_hands]&.include?(player_hand) } / s
69
+ h[player_hand][:outs] = win_hands.keys if win_rate < 0.5
70
+ end
71
+ end
72
+
73
+ def flop_equities
74
+ z = deck.combination(2).each_with_object({}) do |cs, a|
75
+ scores = player_hands.each_with_object({}) do |player_hand, h|
76
+ cards = player_hand
77
+ cards = cards.add_cards(flop_cards)
78
+
79
+ cs.each { |c| cards = cards.add_card(c) }
80
+
81
+ h[cards.score] ||= []
82
+ h[cards.score] << player_hand
83
+ end
84
+
85
+ a[cs] = {}
86
+ if scores.keys.size == 1
87
+ a[cs][:tie_hands] = player_hands
88
+ else
89
+ mk = scores.keys.max
90
+ a[cs][:win_hands] = scores[mk]
91
+ a[cs][:lose_hands] = scores.each_with_object([]) do |(k,v), a|
92
+ next if k == mk
93
+
94
+ a.concat(v)
95
+ end
96
+ end
97
+ end
98
+
99
+ s = z.size.to_f
100
+
101
+ player_hands.each_with_object({}) do |player_hand, h|
102
+ win_hands = z.select { |a,b| b[:win_hands]&.include?(player_hand) }
103
+ win_rate = win_hands.size / s
104
+ h[player_hand] = {}
105
+ h[player_hand][:win_rate] = win_rate
106
+ h[player_hand][:lose_rate] = z.count { |a,b| b[:lose_hands]&.include?(player_hand) } / s
107
+ h[player_hand][:tie_rate] = z.count { |a,b| b[:tie_hands]&.include?(player_hand) } / s
108
+ h[player_hand][:outs] = win_hands.keys if win_rate < 0.5
109
+ end
110
+ end
111
+
112
+ def preflop_equities
113
+ ran = deck.combination(5).to_a
114
+ z = 10000.times.with_object({}) do |i, a|
115
+ cs = ran.sample
116
+ scores = player_hands.each_with_object({}) do |player_hand, h|
117
+ cards = player_hand
118
+
119
+ cs.each { |c| cards = cards.add_card(c) }
120
+
121
+ h[cards.score] ||= []
122
+ h[cards.score] << player_hand
123
+ end
124
+
125
+ a[cs] = {}
126
+ if scores.keys.size == 1
127
+ a[cs][:tie_hands] = player_hands
128
+ else
129
+ mk = scores.keys.max
130
+ a[cs][:win_hands] = scores[mk]
131
+ a[cs][:lose_hands] = scores.each_with_object([]) do |(k,v), a|
132
+ next if k == mk
133
+
134
+ a.concat(v)
135
+ end
136
+ end
137
+ end
138
+
139
+ s = z.size.to_f
140
+
141
+ player_hands.each_with_object({}) do |player_hand, h|
142
+ win_hands = z.select { |a,b| b[:win_hands]&.include?(player_hand) }
143
+ win_rate = win_hands.size / s
144
+ h[player_hand] = {}
145
+ h[player_hand][:win_rate] = win_rate
146
+ h[player_hand][:lose_rate] = z.count { |a,b| b[:lose_hands]&.include?(player_hand) } / s
147
+ h[player_hand][:tie_rate] = z.count { |a,b| b[:tie_hands]&.include?(player_hand) } / s
148
+ h[player_hand][:outs] = win_hands.keys if win_rate < 0.5
149
+ end
150
+ end
151
+
152
+ def deck
153
+ cards = PokerTrump::Cards.new_deck
154
+ cards.delete_cards!(expose_cards) unless expose_cards.size == 0
155
+ player_hands.each do |player_hand|
156
+ cards.delete_cards!(player_hand)
157
+ end
158
+ cards.delete_cards!(flop_cards) unless flop_cards.size == 0
159
+ cards.delete_card!(turn_card) if !!turn_card
160
+ cards.delete_card!(river_card) if !!river_card
161
+
162
+ cards
163
+ end
164
+ end
165
+ end
@@ -1,3 +1,3 @@
1
1
  module PokerOdds
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.4"
3
3
  end
data/lib/poker_odds.rb CHANGED
@@ -1,9 +1,8 @@
1
- require 'hashie'
2
- require 'active_support/all'
1
+ require 'virtus'
2
+ require 'poker_trump'
3
+
3
4
  require_relative "poker_odds/version"
4
- require_relative 'poker_odds/card'
5
- require_relative 'poker_odds/cards'
6
- require_relative 'poker_odds/round'
5
+ require_relative 'poker_odds/hand'
7
6
 
8
7
  module PokerOdds
9
8
  class Error < StandardError; end
data/poker_odds.gemspec CHANGED
@@ -40,6 +40,7 @@ Gem::Specification.new do |spec|
40
40
  spec.add_development_dependency "rake"
41
41
  spec.add_development_dependency "rspec"
42
42
  spec.add_development_dependency "pry"
43
- spec.add_dependency "hashie"
44
- spec.add_dependency 'activesupport'
43
+
44
+ spec.add_dependency 'virtus'
45
+ spec.add_dependency 'poker_trump'
45
46
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: poker_odds
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - kyohah
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-07-07 00:00:00.000000000 Z
11
+ date: 2022-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: hashie
70
+ name: virtus
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: activesupport
84
+ name: poker_trump
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -112,9 +112,7 @@ files:
112
112
  - bin/console
113
113
  - bin/setup
114
114
  - lib/poker_odds.rb
115
- - lib/poker_odds/card.rb
116
- - lib/poker_odds/cards.rb
117
- - lib/poker_odds/round.rb
115
+ - lib/poker_odds/hand.rb
118
116
  - lib/poker_odds/version.rb
119
117
  - poker_odds.gemspec
120
118
  homepage: https://github.com/kyohah/poker_odds
@@ -123,7 +121,7 @@ licenses:
123
121
  metadata:
124
122
  homepage_uri: https://github.com/kyohah/poker_odds
125
123
  source_code_uri: https://github.com/kyohah/poker_odds
126
- post_install_message:
124
+ post_install_message:
127
125
  rdoc_options: []
128
126
  require_paths:
129
127
  - lib
@@ -138,8 +136,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
136
  - !ruby/object:Gem::Version
139
137
  version: '0'
140
138
  requirements: []
141
- rubygems_version: 3.0.3.1
142
- signing_key:
139
+ rubygems_version: 3.2.32
140
+ signing_key:
143
141
  specification_version: 4
144
142
  summary: Write a short summary, because RubyGems requires one.
145
143
  test_files: []
@@ -1,39 +0,0 @@
1
- module PokerOdds
2
- class Card < Hash
3
- include Hashie::Extensions::Coercion
4
- include Hashie::Extensions::MergeInitializer
5
- include Hashie::Extensions::MethodAccess
6
-
7
- RANKS = %w[A 2 3 4 5 6 7 8 9 T J Q K].freeze
8
- SUITS = %i[s h d c].freeze
9
-
10
- RANK_VALUE = {
11
- '2' => 2,
12
- '3' => 3,
13
- '4' => 4,
14
- '5' => 5,
15
- '6' => 6,
16
- '7' => 7,
17
- '8' => 8,
18
- '9' => 9,
19
- 'T' => 10,
20
- 'J' => 11,
21
- 'Q' => 12,
22
- 'K' => 13,
23
- 'A' => 14
24
- }
25
-
26
- coerce_key :rank, String
27
- coerce_key :suit, Symbol
28
-
29
- class << self
30
- def string_parse(string)
31
- Card.new(rank: string[0], suit: string[1])
32
- end
33
- end
34
-
35
- def rank_value
36
- RANK_VALUE[rank]
37
- end
38
- end
39
- end
@@ -1,232 +0,0 @@
1
- module PokerOdds
2
- class Cards < Array
3
- include Comparable
4
- DeleteError = Class.new(StandardError)
5
-
6
- STRAIGHT_PATTERNS = (6..14).to_a.reverse.map { |i| (0..4).map {|j| i - j } }.push([5,4,3,2,14]).map { |a| /#{a[0]}.+#{a[1]}.+#{a[2]}.+#{a[3]}.+#{a[4]}/ }.freeze
7
-
8
- class << self
9
- def new_deck
10
- new(Card::RANKS.flat_map do |rank|
11
- Card::SUITS.map do |suit|
12
- Card.new(suit: suit, rank: rank)
13
- end
14
- end)
15
- end
16
-
17
- def string_parse(string)
18
- a = string.split.map do |s|
19
- Card.new(rank: s[0], suit: s[1])
20
- end
21
-
22
- new(a)
23
- end
24
-
25
- def json_parse(json)
26
- h = JSON.parse(json)
27
-
28
- b = h.map { |a| Card.new(rank: a['rank'].to_sym, suit: a['suit'].to_sym) }
29
-
30
- Hands.new(b)
31
- end
32
- end
33
-
34
- def delete_card!(card)
35
- i = index(card)
36
- raise DeleteError if i.nil?
37
-
38
- delete_at(i)
39
- self
40
- end
41
-
42
- def delete_card(card)
43
- i = index(card)
44
- raise DeleteError if i.nil?
45
-
46
- clone_cards = clone
47
- clone_cards.delete_at(i)
48
-
49
- clone_cards
50
- end
51
-
52
- def delete_cards!(cards)
53
- cards.each { |t| delete_card!(t) }
54
- self
55
- end
56
-
57
- def delete_cards(cards)
58
- clone_cards = clone
59
- cards.each { |t| clone_cards.delete_card!(t) }
60
- clone_cards
61
- end
62
-
63
- def add_card(card)
64
- clone_cards = clone
65
- clone_cards.push(card)
66
- end
67
-
68
- def add_card!(card)
69
- push(card)
70
- end
71
-
72
- def add_cards(cards)
73
- clone_cards = clone
74
-
75
- cards.each { |card| clone_cards.add_card!(card) }
76
- clone_cards
77
- end
78
-
79
- def add_cards!(cards)
80
- cards.each { |card| add_card!(card) }
81
- self
82
- end
83
-
84
- def sort_by_suit
85
- @sort_by_suit ||= self.class.new(sort_by { |card| [card.suit, card.rank_value] }.reverse)
86
- end
87
-
88
- def sort_by_rank
89
- @sort_by_rank ||= self.class.new(sort_by { |card| [card.rank_value, card.suit] }.reverse)
90
- rescue => e
91
- binding.pry
92
- end
93
-
94
- def to_s
95
- map { |c| "#{c.rank}#{c.suit}" }.join(' ')
96
- end
97
-
98
- def to_s_rank_value
99
- map(&:rank_value).join(' ')
100
- end
101
-
102
- def group_by_suit
103
- @group_by_suit ||= group_by(&:suit).each_with_object({}) { |(k, v), h| h[k] = self.class.new(v).sort_by_rank }
104
- end
105
-
106
- def royal_flush_rate
107
- [10, 0,0,0,0,0] if /A(.) K\1 Q\1 J\1 T\1/.match?(sort_by_suit.to_s)
108
- end
109
-
110
- def straight_flush_rate
111
- group_by_suit.each do |k, v|
112
- next if v.size < 5
113
-
114
- a = v.straight_rate
115
- if a
116
- return [9, a[1], a[2], a[3], a[4], a[5]]
117
- end
118
- end
119
- nil
120
- end
121
-
122
- def four_of_a_kind_rate
123
- a = sort_by_rank.to_s.match(/(.). \1. \1. \1./)
124
-
125
- if a
126
- b = (a.pre_match + a.post_match).match(/(\S)/).to_s
127
-
128
- [8, PokerOdds::Card::RANK_VALUE[a[1]], PokerOdds::Card::RANK_VALUE[b.to_s], 0, 0,0]
129
- end
130
- end
131
-
132
- def full_house_rate
133
- case sort_by_rank.to_s
134
- when /(.). \1. \1. (.*)(.). \3./
135
- [7, PokerOdds::Card::RANK_VALUE[$1], PokerOdds::Card::RANK_VALUE[$3], 0, 0,0]
136
- when /((.). \2.) (.*)((.). \5. \5.)/
137
- [7, PokerOdds::Card::RANK_VALUE[$5], PokerOdds::Card::RANK_VALUE[$2], 0, 0,0]
138
- else
139
- nil
140
- end
141
- end
142
-
143
- def flush_rate
144
- group_by_suit.each do |k, v|
145
- next if v.size < 5
146
-
147
- return [6, v[0].rank_value, v[1].rank_value, v[2].rank_value, v[3].rank_value, v[4].rank_value]
148
- end
149
-
150
- nil
151
- end
152
-
153
- def straight_rate
154
- a = sort_by_rank.to_s.match(/(?<_A>A.+K.+Q.+J.+T)|(?<_K>K.+Q.+J.+T.+9)|(?<_Q>Q.+J.+T.+9.+8)|(?<_J>J.+T.+9.+8.+7)|(?<_T>T.+9.+8.+7.+6)|(?<_9>9.+8.+7.+6.+5)|(?<_8>8.+7.+6.+5.+4)|(?<_7>7.+6.+5.+4.+3)|(?<_6>6.+5.+4.+3.+2)|(?<_5>A.+5.+4.+3.+2)/)
155
- if a
156
- case k
157
- when :_A
158
- [5, *PokerOdds::Card::RANK_VALUE.values_at('A', 'K', 'Q','J', 'T')]
159
- when :_K
160
- [5, *PokerOdds::Card::RANK_VALUE.values_at('K', 'Q', 'J','T', '9')]
161
- when :_Q
162
- [5, *PokerOdds::Card::RANK_VALUE.values_at('Q', 'J', 'T','9', '8')]
163
- when :_J
164
- [5, *PokerOdds::Card::RANK_VALUE.values_at('J', 'T', '9','8', '7')]
165
- when :_T
166
- [5, *PokerOdds::Card::RANK_VALUE.values_at('T', '9', '8','7', '6')]
167
- when :_9
168
- [5, *PokerOdds::Card::RANK_VALUE.values_at('9', '8', '7','6', '5')]
169
- when :_8
170
- [5, *PokerOdds::Card::RANK_VALUE.values_at('8', '7', '6','5', '4')]
171
- when :_7
172
- [5, *PokerOdds::Card::RANK_VALUE.values_at('7', '6', '5','4', '3')]
173
- when :_6
174
- [5, *PokerOdds::Card::RANK_VALUE.values_at('6', '5', '4','3', '2')]
175
- when :_5
176
- [5, *PokerOdds::Card::RANK_VALUE.values_at('5', '4', '3','2', 'A')]
177
- end
178
- else
179
- nil
180
- end
181
- end
182
-
183
- def three_of_a_kind_rate
184
- md = sort_by_rank.to_s.match(/(.). \1. \1./)
185
-
186
- if md
187
- arranged_hand = (md.pre_match + md.post_match).strip.squeeze(" ")
188
-
189
- [4, PokerOdds::Card::RANK_VALUE[md[1]], PokerOdds::Card::RANK_VALUE[arranged_hand[0]], PokerOdds::Card::RANK_VALUE[arranged_hand[3]], 0, 0]
190
- else
191
- nil
192
- end
193
- end
194
-
195
- def two_pair_rate
196
- md = sort_by_rank.to_s.match(/(.). \1.(.*?) (.). \3./)
197
-
198
- if md
199
- arranged_hand = (md.pre_match + ' ' + md[2] + ' ' + md.post_match).strip.squeeze(" ")
200
- [3, PokerOdds::Card::RANK_VALUE[md[1]], PokerOdds::Card::RANK_VALUE[md[3]], PokerOdds::Card::RANK_VALUE[arranged_hand[0]], 0, 0]
201
- else
202
- nil
203
- end
204
- end
205
-
206
- def one_pair_rate
207
- md = sort_by_rank.to_s.match(/(.). \1./)
208
-
209
- if md
210
- arranged_hand = (md.pre_match + ' ' + md.post_match).strip.squeeze(" ")
211
-
212
- [2, PokerOdds::Card::RANK_VALUE[md[1]], PokerOdds::Card::RANK_VALUE[arranged_hand[0]], PokerOdds::Card::RANK_VALUE[arranged_hand[3]], PokerOdds::Card::RANK_VALUE[arranged_hand[6]], 0]
213
- else
214
- nil
215
- end
216
- end
217
-
218
- def high_card_rate
219
- arranged_hand = sort_by_rank.to_s
220
-
221
- [1, PokerOdds::Card::RANK_VALUE[arranged_hand[0]], PokerOdds::Card::RANK_VALUE[arranged_hand[3]], PokerOdds::Card::RANK_VALUE[arranged_hand[6]], PokerOdds::Card::RANK_VALUE[arranged_hand[9]], PokerOdds::Card::RANK_VALUE[arranged_hand[12]]]
222
- end
223
-
224
- def score
225
- @score ||= royal_flush_rate || straight_flush_rate || four_of_a_kind_rate || full_house_rate || flush_rate || straight_flush_rate || three_of_a_kind_rate || two_pair_rate || one_pair_rate || high_card_rate
226
- end
227
-
228
- def <=>(other_cards)
229
- score <=> other_cards.score
230
- end
231
- end
232
- end
@@ -1,108 +0,0 @@
1
- module PokerOdds
2
- class Round < Hash
3
- include Hashie::Extensions::Coercion
4
- include Hashie::Extensions::MergeInitializer
5
- include Hashie::Extensions::MethodAccess
6
-
7
- coerce_key :hands, Array
8
- coerce_key :flop_cards, PokerOdds::Cards
9
- coerce_key :turn_card, PokerOdds::Card
10
- coerce_key :river_card, PokerOdds::Card
11
-
12
- coerce_key :expose_cards, PokerOdds::Cards
13
-
14
- # class << self
15
- # def flop =(h)
16
-
17
- # end
18
- # end
19
-
20
- def initialize(**arg)
21
- self.flop=arg[:flop] if arg[:flop]
22
- self.turn=arg[:turn] if arg[:turn]
23
- self.river=arg[:river] if arg[:river]
24
-
25
- self[:hands] ||= []
26
- self[:expose_cards] ||= PokerOdds::Cards.new
27
- self[:flop_cards] ||= PokerOdds::Cards.new
28
- self[:turn_card] ||= PokerOdds::Card.new
29
- self[:river_card] ||= PokerOdds::Card.new
30
- end
31
-
32
- def add_hand(s)
33
- self[:hands] << PokerOdds::Cards.string_parse(s)
34
- self
35
- end
36
-
37
- def flop=(s)
38
- self[:flop_cards] = PokerOdds::Cards.string_parse(s)
39
- self
40
- end
41
-
42
- def turn=(s)
43
- self[:turn_card] = PokerOdds::Card.string_parse(s)
44
- self
45
- end
46
-
47
- def river=(s)
48
- self[:river_cards] = PokerOdds::Card.string_parse(s)
49
- self
50
- end
51
-
52
- def equities
53
- z = deck.each_with_object({}) do |card, a|
54
- scores = hands.each_with_object({}) do |hand, h|
55
- cards = hand
56
- cards = cards.add_cards(flop_cards)
57
- cards = cards.add_card(turn_card)
58
- cards = cards.add_card(card)
59
-
60
- if h[cards.score].present?
61
- h[cards.score] << hand
62
- else
63
- h[cards.score] = [hand]
64
- end
65
- end
66
-
67
- a[card] = {}
68
- if scores.keys.size == 1
69
- a[card][:tie_hands] = hands
70
- else
71
- mk = scores.keys.max
72
- a[card][:win_hands] = scores[mk]
73
- a[card][:lose_hands] = scores.each_with_object([]) do |(k,v), a|
74
- next if k == mk
75
-
76
- a.concat(v)
77
- end
78
- end
79
- end
80
-
81
- s = z.size.to_f
82
-
83
- hands.each_with_object({}) do |hand, h|
84
- win_hands = z.select { |a,b| b[:win_hands]&.include?(hand) }
85
- win_rate = win_hands.size / s
86
- h = {}
87
- h[:hand] = hand
88
- h[:win_rate] = win_rate
89
- h[:lose_rate] = z.count { |a,b| b[:lose_hands]&.include?(hand) } / s
90
- h[:tie_rate] = z.count { |a,b| b[:tie_hands]&.include?(hand) } / s
91
- h[:outs] = win_hands.keys if win_rate > 0.5
92
- end
93
- end
94
-
95
- def deck
96
- cards = Cards.new_deck
97
- cards.delete_cards!(expose_cards) if expose_cards
98
- hands.each do |hand|
99
- cards.delete_cards!(hand)
100
- end
101
- cards.delete_cards!(flop_cards) if flop_cards.present?
102
- cards.delete_card!(turn_card) if turn_card.present?
103
- cards.delete_card!(river_card) if river_card.present?
104
-
105
- cards
106
- end
107
- end
108
- end