acpc_poker_types 0.0.10 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +7 -4
- data/acpc_poker_types.gemspec +4 -2
- data/lib/acpc_poker_types.rb +13 -12
- data/lib/acpc_poker_types/acpc_dealer_data.rb +9 -0
- data/lib/acpc_poker_types/acpc_dealer_data/action_messages.rb +133 -0
- data/lib/acpc_poker_types/acpc_dealer_data/hand_data.rb +182 -0
- data/lib/acpc_poker_types/acpc_dealer_data/hand_results.rb +79 -0
- data/lib/acpc_poker_types/acpc_dealer_data/log_file.rb +5 -0
- data/lib/acpc_poker_types/acpc_dealer_data/match_definition.rb +54 -0
- data/lib/acpc_poker_types/acpc_dealer_data/poker_match_data.rb +393 -0
- data/lib/acpc_poker_types/board_cards.rb +4 -4
- data/lib/acpc_poker_types/card.rb +16 -16
- data/lib/acpc_poker_types/chip_stack.rb +1 -1
- data/lib/acpc_poker_types/game_definition.rb +34 -38
- data/lib/acpc_poker_types/hand.rb +5 -5
- data/lib/acpc_poker_types/match_state.rb +31 -32
- data/lib/acpc_poker_types/pile_of_cards.rb +1 -1
- data/lib/acpc_poker_types/player.rb +16 -15
- data/lib/acpc_poker_types/poker_action.rb +6 -6
- data/lib/acpc_poker_types/rank.rb +2 -2
- data/lib/acpc_poker_types/suit.rb +4 -4
- data/lib/acpc_poker_types/version.rb +1 -1
- data/spec/action_messages_spec.rb +450 -0
- data/spec/board_cards_spec.rb +9 -9
- data/spec/card_spec.rb +20 -20
- data/spec/chip_stack_spec.rb +28 -29
- data/spec/game_definition_spec.rb +11 -11
- data/spec/hand_data_spec.rb +295 -0
- data/spec/hand_results_spec.rb +292 -0
- data/spec/hand_spec.rb +11 -11
- data/spec/match_definition_spec.rb +95 -0
- data/spec/match_state_spec.rb +105 -287
- data/spec/pile_of_cards_spec.rb +14 -14
- data/spec/player_spec.rb +61 -61
- data/spec/poker_action_spec.rb +49 -49
- data/spec/poker_match_data_spec.rb +388 -0
- data/spec/rank_spec.rb +19 -19
- data/spec/suit_spec.rb +19 -19
- data/spec/support/spec_helper.rb +28 -6
- metadata +55 -10
@@ -0,0 +1,292 @@
|
|
1
|
+
|
2
|
+
# Spec helper (must include first to track code coverage with SimpleCov)
|
3
|
+
require_relative 'support/spec_helper'
|
4
|
+
|
5
|
+
require 'mocha/setup'
|
6
|
+
|
7
|
+
require 'acpc_dealer'
|
8
|
+
|
9
|
+
require 'acpc_poker_types/acpc_dealer_data/hand_results'
|
10
|
+
require 'acpc_poker_types/acpc_dealer_data/match_definition'
|
11
|
+
|
12
|
+
describe AcpcPokerTypes::AcpcDealerData::HandResults do
|
13
|
+
before do
|
14
|
+
@patient = nil
|
15
|
+
@data = nil
|
16
|
+
@final_score = nil
|
17
|
+
@player_names = nil
|
18
|
+
@match_def = nil
|
19
|
+
@no_final_score = false
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '::parse_state' do
|
23
|
+
it 'properly parses a ACPC log "STATE. . ." line' do
|
24
|
+
[
|
25
|
+
"STATE:0:rc/rrrrc/rc/crrrc:5d5c|9hQd/8dAs8s/4h/6d:28|-28:p1|p2\n" =>
|
26
|
+
{p1: 28, p2: -28},
|
27
|
+
"STATE:9:cc/cc/r165c/cc:4cKh|Kd7d/Ah9h9c/6s/Ks:0|0:p1|p2\n" =>
|
28
|
+
{p1: 0, p2: 0},
|
29
|
+
"STATE:18:rfrrc/cc/rrc/rrrrc:5d5c|9hQd|8dAs/8s4h6d/5s/Js:-5|-160|165:p1|p2|p3\n" =>
|
30
|
+
{p1: -5, p2: -160, p3: 165},
|
31
|
+
"STATE:1:cr13057cr20000cc///:Ks6h|Qs5d|Tc4d/Ah3dTd/8c/Qd:-20000|40000|-20000:p2|p3|p1\n" =>
|
32
|
+
{p1: -20000, p2: -20000, p3: 40000}
|
33
|
+
].each do |state_to_player_results|
|
34
|
+
state_to_player_results.each do |state_string, expected_values|
|
35
|
+
AcpcPokerTypes::AcpcDealerData::HandResults.parse_state(state_string).must_equal expected_values
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
it 'returns nil if asked to parse an improperly formatted string' do
|
40
|
+
AcpcPokerTypes::AcpcDealerData::HandResults.parse_state("improperly formatted string").must_be_nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
describe '::parse_score' do
|
44
|
+
it 'properly parses a ACPC log "SCORE. . ." line' do
|
45
|
+
[
|
46
|
+
"SCORE:100|-100:p1|p2\n" => {p1: 100, p2: -100},
|
47
|
+
'SCORE:19835|621.5|-20455.5:p1|p2|p3' => {p1: 19835, p2: 621.5, p3: -20455.5}
|
48
|
+
].each do |score_to_player_results|
|
49
|
+
score_to_player_results.each do |score_string, expected_values|
|
50
|
+
AcpcPokerTypes::AcpcDealerData::HandResults.parse_score(score_string).must_equal expected_values
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
it 'returns nil if asked to parse an improperly formatted string' do
|
55
|
+
AcpcPokerTypes::AcpcDealerData::HandResults.parse_score("improperly formatted string").must_be_nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'properly parses ACPC log statements' do
|
60
|
+
describe 'from file' do
|
61
|
+
it 'when every hand is desired' do
|
62
|
+
init_data do |log_statements|
|
63
|
+
file_name = 'file_name'
|
64
|
+
AcpcPokerTypes::AcpcDealerData::LogFile.stubs(:open).with(file_name, 'r').yields(
|
65
|
+
log_statements
|
66
|
+
).returns(
|
67
|
+
AcpcPokerTypes::AcpcDealerData::HandResults.parse(
|
68
|
+
log_statements,
|
69
|
+
@player_names,
|
70
|
+
AcpcDealer::DEALER_DIRECTORY
|
71
|
+
)
|
72
|
+
)
|
73
|
+
|
74
|
+
@patient = AcpcPokerTypes::AcpcDealerData::HandResults.parse_file(
|
75
|
+
file_name,
|
76
|
+
@player_names,
|
77
|
+
AcpcDealer::DEALER_DIRECTORY
|
78
|
+
)
|
79
|
+
|
80
|
+
check_patient
|
81
|
+
end
|
82
|
+
end
|
83
|
+
it 'when a particular number of hands is desired' do
|
84
|
+
@no_final_score = true
|
85
|
+
num_hands = 3
|
86
|
+
init_data do |log_statements|
|
87
|
+
file_name = 'file_name'
|
88
|
+
AcpcPokerTypes::AcpcDealerData::LogFile.stubs(:open).with(file_name, 'r').yields(
|
89
|
+
log_statements
|
90
|
+
).returns(
|
91
|
+
AcpcPokerTypes::AcpcDealerData::HandResults.parse(
|
92
|
+
log_statements,
|
93
|
+
@player_names,
|
94
|
+
AcpcDealer::DEALER_DIRECTORY,
|
95
|
+
num_hands
|
96
|
+
)
|
97
|
+
)
|
98
|
+
|
99
|
+
@patient = AcpcPokerTypes::AcpcDealerData::HandResults.parse_file(
|
100
|
+
file_name,
|
101
|
+
@player_names,
|
102
|
+
AcpcDealer::DEALER_DIRECTORY,
|
103
|
+
num_hands
|
104
|
+
)
|
105
|
+
|
106
|
+
# Fix data to check patient against
|
107
|
+
@final_score = nil
|
108
|
+
@data = @data[0..num_hands-1]
|
109
|
+
|
110
|
+
check_patient
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
describe 'from array' do
|
115
|
+
it 'when every hand is desired' do
|
116
|
+
init_data do |log_statements|
|
117
|
+
@patient = AcpcPokerTypes::AcpcDealerData::HandResults.parse(
|
118
|
+
log_statements,
|
119
|
+
@player_names,
|
120
|
+
AcpcDealer::DEALER_DIRECTORY
|
121
|
+
)
|
122
|
+
|
123
|
+
check_patient
|
124
|
+
end
|
125
|
+
end
|
126
|
+
it 'when a particular number of hands is desired' do
|
127
|
+
@no_final_score = true
|
128
|
+
num_hands = 3
|
129
|
+
init_data do |log_statements|
|
130
|
+
@patient = AcpcPokerTypes::AcpcDealerData::HandResults.parse(
|
131
|
+
log_statements,
|
132
|
+
@player_names,
|
133
|
+
AcpcDealer::DEALER_DIRECTORY,
|
134
|
+
num_hands
|
135
|
+
)
|
136
|
+
|
137
|
+
# Fix data to check patient against
|
138
|
+
@final_score = nil
|
139
|
+
@data = @data[0..num_hands-1]
|
140
|
+
|
141
|
+
check_patient
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def check_patient
|
148
|
+
@patient.data.must_equal @data
|
149
|
+
@patient.final_score.must_equal @final_score unless @no_final_score
|
150
|
+
@patient.match_def.must_equal @match_def
|
151
|
+
end
|
152
|
+
|
153
|
+
def init_data
|
154
|
+
all_data.each do |game, data_hash|
|
155
|
+
@final_score = data_hash[:final_score]
|
156
|
+
@data = data_hash[:data]
|
157
|
+
@player_names = data_hash[:player_names]
|
158
|
+
@match_def = AcpcPokerTypes::AcpcDealerData::MatchDefinition.parse(
|
159
|
+
data_hash[:log_statements].first,
|
160
|
+
@player_names,
|
161
|
+
AcpcDealer::DEALER_DIRECTORY
|
162
|
+
)
|
163
|
+
|
164
|
+
yield data_hash[:log_statements]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def all_data
|
169
|
+
{
|
170
|
+
two_player_limit: {
|
171
|
+
log_statements: [
|
172
|
+
"# name/game/hands/seed 2p.limit.h1000.r0 holdem.limit.2p.reverse_blinds.game 1000 0\n",
|
173
|
+
"STATE:0:crrrc/rrc/rf:3s5d|Td2s/4d5c4s/Kd:60|-60:p1|p2\n",
|
174
|
+
"STATE:1:rc/crrrrc/rrc/rc:7d5s|Kh9c/As3hTs/Jh/Js:-120|120:p2|p1\n",
|
175
|
+
"STATE:2:cc/cc/rc/rc:Kh6h|As2h/Qd2c2d/7d/3d:-50|50:p1|p2\n",
|
176
|
+
"STATE:3:cc/rrrc/rc/rc:8c7d|QcKc/Ac6hTd/9h/3d:80|-80:p2|p1\n",
|
177
|
+
"STATE:4:rf:6s9d|4dQd:-10|10:p1|p2\n",
|
178
|
+
"STATE:5:cc/crc/cc/cc:6c2d|9cKs/4dKc7d/Td/Ah:-20|20:p2|p1\n",
|
179
|
+
"STATE:6:rrrc/rc/cc/rc:9h7h|3d8s/JcAc5c/Ah/Ks:70|-70:p1|p2\n",
|
180
|
+
"STATE:7:rrrf:5s9c|8dJh:-30|30:p2|p1\n",
|
181
|
+
"STATE:8:rrrc/cc/rc/rrc:Kc6h|Qc3s/QhAh8d/Th/9d:-100|100:p1|p2\n",
|
182
|
+
"STATE:9:crc/cc/cc/rc:Jc8d|TdQd/As6d6h/7h/4s:-40|40:p2|p1\n",
|
183
|
+
'SCORE:100|-100:p1|p2'
|
184
|
+
],
|
185
|
+
data: [
|
186
|
+
{p1: 60, p2: -60},
|
187
|
+
{p1: 120, p2: -120},
|
188
|
+
{p1: -50, p2: 50},
|
189
|
+
{p1: -80, p2: 80},
|
190
|
+
{p1: -10, p2: 10},
|
191
|
+
{p1: 20, p2: -20},
|
192
|
+
{p1: 70, p2: -70},
|
193
|
+
{p1: 30, p2: -30},
|
194
|
+
{p1: -100, p2: 100},
|
195
|
+
{p1: 40, p2: -40}
|
196
|
+
],
|
197
|
+
final_score: {p1: 100, p2: -100},
|
198
|
+
player_names: ['p1', 'p2']
|
199
|
+
},
|
200
|
+
two_player_nolimit: {
|
201
|
+
log_statements: [
|
202
|
+
"# name/game/hands/seed 2p.nolimit.h1000.r0 holdem.nolimit.2p.reverse_blinds.game 1000 0\n",
|
203
|
+
"STATE:0:r5924c/r17356c/cc/r19718c:3s5d|Td2s/4d5c4s/Kd/2c:19718|-19718:p1|p2\n",
|
204
|
+
"STATE:1:cc/r7485r16652c/r17998r19429r20000c/:7d5s|Kh9c/As3hTs/Jh/Js:-20000|20000:p2|p1\n",
|
205
|
+
"STATE:2:r18810c/r19264r19774c/cr19995r20000c/:Kh6h|As2h/Qd2c2d/7d/3d:-20000|20000:p1|p2\n",
|
206
|
+
"STATE:3:cr281c/r18446r20000c//:8c7d|QcKc/Ac6hTd/9h/3d:20000|-20000:p2|p1\n",
|
207
|
+
"STATE:4:r13583r20000f:6s9d|4dQd:13583|-13583:p1|p2\n",
|
208
|
+
"STATE:5:cc/r15416f:6c2d|9cKs/4dKc7d:100|-100:p2|p1\n",
|
209
|
+
"STATE:6:r15542r20000c///:9h7h|3d8s/JcAc5c/Ah/Ks:20000|-20000:p1|p2\n",
|
210
|
+
"STATE:7:r1147c/cc/cr5404f:5s9c|8dJh/TdQc9d/Jd:-1147|1147:p2|p1\n",
|
211
|
+
"STATE:8:cc/r5841r19996r20000c//:Kc6h|Qc3s/QhAh8d/Th/9d:-20000|20000:p1|p2\n",
|
212
|
+
"STATE:9:f:Jc8d|TdQd:50|-50:p2|p1\n",
|
213
|
+
'SCORE:14298|-14298:p1|p2'
|
214
|
+
],
|
215
|
+
data: [
|
216
|
+
{p1: 19718, p2: -19718},
|
217
|
+
{p1: 20000, p2: -20000},
|
218
|
+
{p1: -20000, p2: 20000},
|
219
|
+
{p1: -20000, p2: 20000},
|
220
|
+
{p1: 13583, p2: -13583},
|
221
|
+
{p1: -100, p2: 100},
|
222
|
+
{p1: 20000, p2: -20000},
|
223
|
+
{p1: 1147, p2: -1147},
|
224
|
+
{p1: -20000, p2: 20000},
|
225
|
+
{p1: -50, p2: 50}
|
226
|
+
],
|
227
|
+
final_score: {p1: 14298, p2: -14298},
|
228
|
+
player_names: ['p1', 'p2']
|
229
|
+
},
|
230
|
+
three_player_limit: {
|
231
|
+
log_statements: [
|
232
|
+
"# name/game/hands/seed 3p.limit.h1000.r0 holdem.limit.3p.game 1000 0\n",
|
233
|
+
"STATE:0:ccc/rrcrcrcc/rcrrcc/crcrcrcrfc:Kd2d|6c2s|8hTh/2c4h9s/Ad/As:360|-190|-170:p1|p2|p3\n",
|
234
|
+
"STATE:1:rrcrcc/rrrcf/rrrrc/cc:Td7s|4c5s|Qc4s/5dAd7c/6c/2c:210|-60|-150:p2|p3|p1\n",
|
235
|
+
"STATE:2:fcc/crc/crrc/rrc:Jh9d|8hAh|As6c/3dKc3c/2d/Kh:-100|100|0:p3|p1|p2\n",
|
236
|
+
"STATE:3:rcrcrcf/rc/cc/rc:Qd2h|5c4d|6s2d/As8s6d/7d/2c:-70|100|-30:p1|p2|p3\n",
|
237
|
+
"STATE:4:rrcc/rrrrcf/rrc/rc:8d4c|6sQd|Ts2s/2d9hTh/8c/5h:190|-130|-60:p2|p3|p1\n",
|
238
|
+
"STATE:5:rrrcc/crrfrrc/crc/cc:7cKh|3s2h|Js4h/KcQc2s/5h/4s:-40|-100|140:p3|p1|p2\n",
|
239
|
+
"STATE:6:rrcrcc/rrrcc/ccrrcrcrcc/crrrrfc:QhQd|3cQc|2cTh/Jc8hTs/9c/3s:95|95|-190:p1|p2|p3\n",
|
240
|
+
"STATE:7:crrcrcc/crrfrc/cc/rrc:Qd2s|KdTs|6dQh/6h6sTc/3h/Jd:-40|-110|150:p2|p3|p1\n",
|
241
|
+
"STATE:8:frc/cc/rc/rrc:6hKc|6cAd|6d2c/QdTd9h/7h/Jc:80|-80|0:p3|p1|p2\n",
|
242
|
+
"STATE:9:ccc/ccc/rrcc/rrrfrc:QsAs|3s8h|Qd3c/4d6d2d/5d/2c:-70|-130|200:p1|p2|p3\n",
|
243
|
+
'SCORE:105|375|-550:p1|p2|p3'
|
244
|
+
],
|
245
|
+
data: [
|
246
|
+
{p1: 360, p2: -190, p3: -170},
|
247
|
+
{p1: -150, p2: 210, p3: -60},
|
248
|
+
{p1: 100, p2: 0, p3: -100},
|
249
|
+
{p1: -70, p2: 100, p3: -30},
|
250
|
+
{p1: -60, p2: 190, p3: -130},
|
251
|
+
{p1: -100, p2: 140, p3: -40},
|
252
|
+
{p1: 95, p2: 95, p3: -190},
|
253
|
+
{p1: 150, p2: -40, p3: -110},
|
254
|
+
{p1: -80, p2: 0, p3: 80},
|
255
|
+
{p1: -70, p2: -130, p3: 200}
|
256
|
+
],
|
257
|
+
final_score: {p1: 105, p2: 375, p3: -550},
|
258
|
+
player_names: ['p1', 'p2', 'p3']
|
259
|
+
},
|
260
|
+
three_player_nolimit: {
|
261
|
+
log_statements: [
|
262
|
+
"# name/game/hands/seed 3p.nolimit.h1000.r0 holdem.nolimit.3p.game 1000 0\n",
|
263
|
+
"STATE:0:ccc/ccc/r4881cr14955cr20000cc/:Kd2d|6c2s|8hTh/2c4h9s/Ad/As:40000|-20000|-20000:p1|p2|p3\n",
|
264
|
+
"STATE:1:ccc/cr7400r17645r20000cc//:Td7s|4c5s|Qc4s/5dAd7c/6c/2c:40000|-20000|-20000:p2|p3|p1\n",
|
265
|
+
"STATE:2:r7187r19832cc/cr19953fc/cr20000c/:Jh9d|8hAh|As6c/3dKc3c/2d/Kh:-20000|39832|-19832:p3|p1|p2\n",
|
266
|
+
"STATE:3:r3610cr8213r19531r20000cc///:Qd2h|5c4d|6s2d/As8s6d/7d/2c:-20000|40000|-20000:p1|p2|p3\n",
|
267
|
+
"STATE:4:fcc/r1348c/r8244r18929r20000c/:8d4c|6sQd|Ts2s/2d9hTh/8c/5h:20000|-20000|0:p2|p3|p1\n",
|
268
|
+
"STATE:5:r15492cc/ccr17275cc/r19597cc/r19947cf:7cKh|3s2h|Js4h/KcQc2s/5h/4s:39544|-19947|-19597:p3|p1|p2\n",
|
269
|
+
"STATE:6:r10322fc/r10577r18645r20000c//:QhQd|3cQc|2cTh/Jc8hTs/9c/3s:-50|20050|-20000:p1|p2|p3\n",
|
270
|
+
"STATE:7:ccr8533r17298r20000cc///:Qd2s|KdTs|6dQh/6h6sTc/3h/Jd:-20000|-20000|40000:p2|p3|p1\n",
|
271
|
+
"STATE:8:cr18231r20000cc///:6hKc|6cAd|6d2c/QdTd9h/7h/Jc:40000|-20000|-20000:p3|p1|p2\n",
|
272
|
+
"STATE:9:ccr12926r20000cc///:QsAs|3s8h|Qd3c/4d6d2d/5d/2c:-20000|-20000|40000:p1|p2|p3\n",
|
273
|
+
'SCORE:19835|621|-20456:p1|p2|p3'
|
274
|
+
],
|
275
|
+
data: [
|
276
|
+
{p1: 40000, p2: -20000, p3: -20000},
|
277
|
+
{p1: -20000, p2: 40000, p3: -20000},
|
278
|
+
{p1: 39832, p2: -19832, p3: -20000},
|
279
|
+
{p1: -20000, p2: 40000, p3: -20000},
|
280
|
+
{p1: 0, p2: 20000, p3: -20000},
|
281
|
+
{p1: -19947, p2: -19597, p3: 39544},
|
282
|
+
{p1: -50, p2: 20050, p3: -20000},
|
283
|
+
{p1: 40000, p2: -20000, p3: -20000},
|
284
|
+
{p1: -20000, p2: -20000, p3: 40000},
|
285
|
+
{p1: -20000, p2: -20000, p3: 40000}
|
286
|
+
],
|
287
|
+
final_score: {p1: 19835, p2: 621, p3: -20456},
|
288
|
+
player_names: ['p1', 'p2', 'p3']
|
289
|
+
}
|
290
|
+
}
|
291
|
+
end
|
292
|
+
end
|
data/spec/hand_spec.rb
CHANGED
@@ -3,13 +3,13 @@
|
|
3
3
|
require File.expand_path('../support/spec_helper', __FILE__)
|
4
4
|
|
5
5
|
|
6
|
-
require
|
6
|
+
require 'acpc_poker_types/hand'
|
7
7
|
|
8
|
-
describe Hand do
|
8
|
+
describe AcpcPokerTypes::Hand do
|
9
9
|
describe '#initialize' do
|
10
10
|
it 'understands every possible card combination' do
|
11
11
|
for_every_two_cards! do |card_1, card_2|
|
12
|
-
@patient = Hand.new [card_1, card_2]
|
12
|
+
@patient = AcpcPokerTypes::Hand.new [card_1, card_2]
|
13
13
|
|
14
14
|
check_patient
|
15
15
|
end
|
@@ -18,7 +18,7 @@ describe Hand do
|
|
18
18
|
describe '#from_acpc' do
|
19
19
|
it 'understands every possible ACPC string hand' do
|
20
20
|
for_every_two_cards! do |card_1, card_2|
|
21
|
-
@patient = Hand.from_acpc @acpc
|
21
|
+
@patient = AcpcPokerTypes::Hand.from_acpc @acpc
|
22
22
|
|
23
23
|
check_patient
|
24
24
|
end
|
@@ -27,7 +27,7 @@ describe Hand do
|
|
27
27
|
describe '#draw_cards' do
|
28
28
|
it 'understands every possible card combination' do
|
29
29
|
for_every_two_cards! do |card_1, card_2|
|
30
|
-
@patient = Hand.draw_cards card_1, card_2
|
30
|
+
@patient = AcpcPokerTypes::Hand.draw_cards card_1, card_2
|
31
31
|
|
32
32
|
check_patient
|
33
33
|
end
|
@@ -35,18 +35,18 @@ describe Hand do
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def check_patient
|
38
|
-
@patient.to_s.
|
39
|
-
@patient.to_acpc.
|
38
|
+
@patient.to_s.must_equal @string
|
39
|
+
@patient.to_acpc.must_equal @acpc
|
40
40
|
end
|
41
41
|
def for_every_card
|
42
|
-
Rank::DOMAIN.map do |rank, rank_properties|
|
43
|
-
Suit::DOMAIN.map do |suit, suit_properties|
|
44
|
-
yield Card.from_components(rank, suit)
|
42
|
+
AcpcPokerTypes::Rank::DOMAIN.map do |rank, rank_properties|
|
43
|
+
AcpcPokerTypes::Suit::DOMAIN.map do |suit, suit_properties|
|
44
|
+
yield AcpcPokerTypes::Card.from_components(rank, suit)
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
48
48
|
def for_every_two_cards!
|
49
|
-
for_every_card do |first_card|
|
49
|
+
for_every_card do |first_card|
|
50
50
|
for_every_card do |second_card|
|
51
51
|
@string = first_card.to_s + second_card.to_s
|
52
52
|
@acpc = first_card.to_acpc + second_card.to_acpc
|
@@ -0,0 +1,95 @@
|
|
1
|
+
|
2
|
+
# Spec helper (must include first to track code coverage with SimpleCov)
|
3
|
+
require_relative 'support/spec_helper'
|
4
|
+
|
5
|
+
require 'acpc_poker_types/game_definition'
|
6
|
+
require 'acpc_dealer'
|
7
|
+
|
8
|
+
require 'acpc_poker_types/acpc_dealer_data/match_definition'
|
9
|
+
|
10
|
+
describe AcpcPokerTypes::AcpcDealerData::MatchDefinition do
|
11
|
+
before do
|
12
|
+
@name = nil
|
13
|
+
@game_def = nil
|
14
|
+
@number_of_hands = nil
|
15
|
+
@random_seed = nil
|
16
|
+
@player_names = nil
|
17
|
+
@patient = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'raises an exception if the number of player names does not match the number of players' do
|
21
|
+
init_components do
|
22
|
+
->() do
|
23
|
+
@patient = AcpcPokerTypes::AcpcDealerData::MatchDefinition.new(
|
24
|
+
@name,
|
25
|
+
@game_def,
|
26
|
+
@number_of_hands,
|
27
|
+
@random_seed,
|
28
|
+
@player_names + ['extra player']
|
29
|
+
)
|
30
|
+
end.must_raise AcpcPokerTypes::AcpcDealerData::MatchDefinition::IncorrectNumberOfPlayerNames
|
31
|
+
|
32
|
+
->() do
|
33
|
+
@patient = AcpcPokerTypes::AcpcDealerData::MatchDefinition.new(
|
34
|
+
@name,
|
35
|
+
@game_def,
|
36
|
+
@number_of_hands,
|
37
|
+
@random_seed,
|
38
|
+
[@player_names.first]
|
39
|
+
)
|
40
|
+
end.must_raise AcpcPokerTypes::AcpcDealerData::MatchDefinition::IncorrectNumberOfPlayerNames
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'can be created by providing components' do
|
45
|
+
it 'separately' do
|
46
|
+
init_components do
|
47
|
+
@patient = AcpcPokerTypes::AcpcDealerData::MatchDefinition.new(
|
48
|
+
@name,
|
49
|
+
@game_def,
|
50
|
+
@number_of_hands,
|
51
|
+
@random_seed,
|
52
|
+
@player_names
|
53
|
+
)
|
54
|
+
|
55
|
+
check_patient
|
56
|
+
end
|
57
|
+
end
|
58
|
+
it 'in string format "# name/game/hands/seed ..."' do
|
59
|
+
init_components do
|
60
|
+
string = "# name/game/hands/seed #{@name} #{@game_def_file_name} #{@number_of_hands} #{@random_seed}\n"
|
61
|
+
@patient = AcpcPokerTypes::AcpcDealerData::MatchDefinition.parse(string, @player_names, File.dirname(@game_def_file_name))
|
62
|
+
|
63
|
+
check_patient
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
it 'returns nil if asked to parse an improperly formatted string' do
|
68
|
+
string = 'improperly formatted string'
|
69
|
+
@patient = AcpcPokerTypes::AcpcDealerData::MatchDefinition.parse(string, ['p1', 'p2'], 'game def directory').must_be_nil
|
70
|
+
end
|
71
|
+
|
72
|
+
def init_components
|
73
|
+
@name = 'match_name'
|
74
|
+
AcpcDealer::GAME_DEFINITION_FILE_PATHS.each do |number_of_players, game_def_hash|
|
75
|
+
game_def_hash.each do |betting_type, file_name|
|
76
|
+
@game_def_file_name = file_name
|
77
|
+
@game_def = AcpcPokerTypes::GameDefinition.parse_file(@game_def_file_name)
|
78
|
+
@number_of_hands = 100
|
79
|
+
@random_seed = 9001
|
80
|
+
@player_names = number_of_players.times.inject([]) do |names, i|
|
81
|
+
names << "p#{i}"
|
82
|
+
end
|
83
|
+
|
84
|
+
yield
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
def check_patient
|
89
|
+
@patient.name.must_equal @name
|
90
|
+
Set.new(@patient.game_def.to_a).must_equal Set.new(@game_def.to_a)
|
91
|
+
@patient.number_of_hands.must_equal @number_of_hands
|
92
|
+
@patient.random_seed.must_equal @random_seed
|
93
|
+
@patient.player_names.must_equal @player_names
|
94
|
+
end
|
95
|
+
end
|
data/spec/match_state_spec.rb
CHANGED
@@ -2,11 +2,14 @@
|
|
2
2
|
# Spec helper (must include first to track code coverage with SimpleCov)
|
3
3
|
require File.expand_path('../support/spec_helper', __FILE__)
|
4
4
|
|
5
|
-
require "
|
6
|
-
require "
|
7
|
-
require "
|
8
|
-
|
9
|
-
|
5
|
+
require "acpc_poker_types/match_state"
|
6
|
+
require "acpc_poker_types/poker_action"
|
7
|
+
require "acpc_poker_types/rank"
|
8
|
+
require "acpc_poker_types/suit"
|
9
|
+
require "acpc_poker_types/hand"
|
10
|
+
require "acpc_poker_types/card"
|
11
|
+
|
12
|
+
describe AcpcPokerTypes::MatchState do
|
10
13
|
describe '#parse' do
|
11
14
|
describe 'raises an exception if ' do
|
12
15
|
describe 'the raw matchstate string' do
|
@@ -19,29 +22,29 @@ describe MatchState do
|
|
19
22
|
end
|
20
23
|
|
21
24
|
it 'does not contain a position' do
|
22
|
-
test_match_state_initialization_error MatchState::LABEL + "::0::AhKd"
|
25
|
+
test_match_state_initialization_error AcpcPokerTypes::MatchState::LABEL + "::0::AhKd"
|
23
26
|
end
|
24
27
|
|
25
28
|
it 'does not contain a hand number' do
|
26
|
-
test_match_state_initialization_error MatchState::LABEL + ":0:::AsKc"
|
29
|
+
test_match_state_initialization_error AcpcPokerTypes::MatchState::LABEL + ":0:::AsKc"
|
27
30
|
end
|
28
31
|
|
29
32
|
it 'does not contain cards' do
|
30
|
-
test_match_state_initialization_error MatchState::LABEL + ":0:0::"
|
33
|
+
test_match_state_initialization_error AcpcPokerTypes::MatchState::LABEL + ":0:0::"
|
31
34
|
end
|
32
35
|
end
|
33
36
|
end
|
34
37
|
it "parses every possible limit action" do
|
35
|
-
partial_match_state = MatchState::LABEL + ":1:1:"
|
38
|
+
partial_match_state = AcpcPokerTypes::MatchState::LABEL + ":1:1:"
|
36
39
|
hole_cards = arbitrary_hole_card_hand
|
37
|
-
PokerAction::LEGAL_ACPC_CHARACTERS.each do |action|
|
40
|
+
AcpcPokerTypes::PokerAction::LEGAL_ACPC_CHARACTERS.each do |action|
|
38
41
|
match_state = partial_match_state + action + ":" + hole_cards.to_acpc
|
39
42
|
patient = test_match_state_success match_state
|
40
|
-
patient.last_action.to_acpc.
|
43
|
+
patient.last_action.to_acpc.must_equal action
|
41
44
|
end
|
42
45
|
end
|
43
46
|
it "parses every possible hole card hand" do
|
44
|
-
partial_match_state = MatchState::LABEL + ":2:2::"
|
47
|
+
partial_match_state = AcpcPokerTypes::MatchState::LABEL + ":2:2::"
|
45
48
|
for_every_hand do |hand|
|
46
49
|
match_state = partial_match_state + hand.to_acpc + '|'
|
47
50
|
|
@@ -49,7 +52,7 @@ describe MatchState do
|
|
49
52
|
end
|
50
53
|
end
|
51
54
|
it "parses opponent hole card hands in a two player game where the user is not the dealer" do
|
52
|
-
partial_match_state = MatchState::LABEL + ":0:2::"
|
55
|
+
partial_match_state = AcpcPokerTypes::MatchState::LABEL + ":0:2::"
|
53
56
|
for_every_hand do |hand|
|
54
57
|
match_state = partial_match_state + arbitrary_hole_card_hand.to_acpc + '|' + hand.to_acpc
|
55
58
|
|
@@ -57,11 +60,11 @@ describe MatchState do
|
|
57
60
|
|
58
61
|
(patient.list_of_opponents_hole_cards.map do |opponent_hand|
|
59
62
|
opponent_hand.to_acpc
|
60
|
-
end).
|
63
|
+
end).must_equal [hand.to_acpc]
|
61
64
|
end
|
62
65
|
end
|
63
66
|
it "parses opponent hole card hands in a two player game where the user is the dealer" do
|
64
|
-
partial_match_state = MatchState::LABEL + ":1:2::"
|
67
|
+
partial_match_state = AcpcPokerTypes::MatchState::LABEL + ":1:2::"
|
65
68
|
for_every_hand do |hand|
|
66
69
|
match_state = partial_match_state + hand.to_acpc + '|' + arbitrary_hole_card_hand.to_acpc
|
67
70
|
|
@@ -69,50 +72,40 @@ describe MatchState do
|
|
69
72
|
|
70
73
|
(patient.list_of_opponents_hole_cards.map do |opponent_hand|
|
71
74
|
opponent_hand.to_acpc
|
72
|
-
end).
|
75
|
+
end).must_equal [hand.to_acpc]
|
73
76
|
end
|
74
77
|
end
|
75
78
|
it 'parses board cards properly for the flop' do
|
76
|
-
partial_match_state = MatchState::LABEL + ":2:2::" + arbitrary_hole_card_hand.to_acpc
|
79
|
+
partial_match_state = AcpcPokerTypes::MatchState::LABEL + ":2:2::" + arbitrary_hole_card_hand.to_acpc
|
77
80
|
|
78
81
|
board_cards = '/AhKdQc'
|
79
82
|
flop_match_state = partial_match_state + board_cards
|
80
83
|
|
81
|
-
patient = MatchState.parse flop_match_state
|
84
|
+
patient = AcpcPokerTypes::MatchState.parse flop_match_state
|
82
85
|
|
83
|
-
patient.board_cards.to_acpc.
|
86
|
+
patient.board_cards.to_acpc.must_equal board_cards
|
84
87
|
end
|
85
88
|
it 'parses board cards properly for the turn' do
|
86
|
-
partial_match_state = MatchState::LABEL + ":2:2::" + arbitrary_hole_card_hand.to_acpc
|
89
|
+
partial_match_state = AcpcPokerTypes::MatchState::LABEL + ":2:2::" + arbitrary_hole_card_hand.to_acpc
|
87
90
|
board_cards = '/AhKdQc/Jd'
|
88
91
|
turn_match_state = partial_match_state + board_cards
|
89
92
|
|
90
|
-
patient = MatchState.parse turn_match_state
|
93
|
+
patient = AcpcPokerTypes::MatchState.parse turn_match_state
|
91
94
|
|
92
|
-
patient.board_cards.to_acpc.
|
95
|
+
patient.board_cards.to_acpc.must_equal board_cards
|
93
96
|
end
|
94
97
|
it 'parses board cards properly for the river' do
|
95
|
-
partial_match_state = MatchState::LABEL + ":2:2::" + arbitrary_hole_card_hand.to_acpc
|
98
|
+
partial_match_state = AcpcPokerTypes::MatchState::LABEL + ":2:2::" + arbitrary_hole_card_hand.to_acpc
|
96
99
|
board_cards = '/AhKdQc/Jd/Th'
|
97
100
|
river_match_state = partial_match_state + board_cards
|
98
101
|
|
99
|
-
patient = MatchState.parse river_match_state
|
100
|
-
|
101
|
-
patient.board_cards.to_acpc.should be == board_cards
|
102
|
-
end
|
103
|
-
it "parses valid limit match states in all rounds" do
|
104
|
-
pending 'need to look at this test'
|
105
|
-
|
106
|
-
test_all_rounds_with_given_action_string PokerAction::LEGAL_ACPC_CHARACTERS.to_a.join ''
|
107
|
-
end
|
108
|
-
it "parses valid no-limit match states in all rounds" do
|
109
|
-
pending 'need to look at this test'
|
102
|
+
patient = AcpcPokerTypes::MatchState.parse river_match_state
|
110
103
|
|
111
|
-
|
104
|
+
patient.board_cards.to_acpc.must_equal board_cards
|
112
105
|
end
|
113
106
|
it "parses a valid two player final match state" do
|
114
|
-
partial_match_state = MatchState::LABEL + ":20:22:"
|
115
|
-
all_actions = PokerAction::LEGAL_ACPC_CHARACTERS.to_a.join ''
|
107
|
+
partial_match_state = AcpcPokerTypes::MatchState::LABEL + ":20:22:"
|
108
|
+
all_actions = AcpcPokerTypes::PokerAction::LEGAL_ACPC_CHARACTERS.to_a.join ''
|
116
109
|
betting = all_actions
|
117
110
|
number_of_rounds = 100
|
118
111
|
(number_of_rounds-1).times do
|
@@ -120,14 +113,14 @@ describe MatchState do
|
|
120
113
|
end
|
121
114
|
board_cards = arbitrary_roll_out number_of_rounds
|
122
115
|
hands = arbitrary_hole_card_hand.to_acpc + "|" + arbitrary_hole_card_hand.to_acpc
|
123
|
-
|
116
|
+
|
124
117
|
match_state = partial_match_state + betting + ":" + hands + board_cards
|
125
118
|
|
126
119
|
test_match_state_success match_state
|
127
120
|
end
|
128
121
|
it "parses a valid three player final match state" do
|
129
|
-
partial_match_state = MatchState::LABEL + ":20:22:"
|
130
|
-
all_actions = PokerAction::LEGAL_ACPC_CHARACTERS.to_a.join ''
|
122
|
+
partial_match_state = AcpcPokerTypes::MatchState::LABEL + ":20:22:"
|
123
|
+
all_actions = AcpcPokerTypes::PokerAction::LEGAL_ACPC_CHARACTERS.to_a.join ''
|
131
124
|
betting = all_actions
|
132
125
|
number_of_rounds = 100
|
133
126
|
(number_of_rounds-1).times do
|
@@ -136,7 +129,7 @@ describe MatchState do
|
|
136
129
|
board_cards = arbitrary_roll_out number_of_rounds
|
137
130
|
hands = arbitrary_hole_card_hand.to_s + "|" +
|
138
131
|
arbitrary_hole_card_hand.to_s + "|" + arbitrary_hole_card_hand.to_s
|
139
|
-
|
132
|
+
|
140
133
|
match_state = partial_match_state + betting + ":" + hands + board_cards
|
141
134
|
|
142
135
|
test_match_state_success match_state
|
@@ -145,13 +138,13 @@ describe MatchState do
|
|
145
138
|
|
146
139
|
describe '#round' do
|
147
140
|
it "properly reports the current round number" do
|
148
|
-
partial_match_state = MatchState::LABEL + ":0:0:"
|
141
|
+
partial_match_state = AcpcPokerTypes::MatchState::LABEL + ":0:0:"
|
149
142
|
betting = ""
|
150
143
|
hand = arbitrary_hole_card_hand
|
151
144
|
100.times do |i|
|
152
145
|
match_state = partial_match_state + betting + ':|' + hand
|
153
146
|
patient = test_match_state_success match_state
|
154
|
-
patient.round.
|
147
|
+
patient.round.must_equal i
|
155
148
|
|
156
149
|
betting += "c/"
|
157
150
|
end
|
@@ -170,287 +163,112 @@ describe MatchState do
|
|
170
163
|
end
|
171
164
|
hands.push arbitrary_hole_card_hand.to_acpc
|
172
165
|
end
|
173
|
-
match_state = MatchState::LABEL + ':1:1::' + hands.join('|')
|
166
|
+
match_state = AcpcPokerTypes::MatchState::LABEL + ':1:1::' + hands.join('|')
|
174
167
|
|
175
168
|
patient = test_match_state_success match_state
|
176
|
-
patient.number_of_players.
|
169
|
+
patient.number_of_players.must_equal expected_number_of_players
|
177
170
|
end
|
178
171
|
end
|
179
172
|
|
180
173
|
describe '#last_action, #round_in_which_last_action_taken, and #first_state_of_first_round' do
|
181
174
|
it 'returns +nil+ if no previous action exists, or true in the case of #first_state_of_first_round' do
|
182
|
-
initial_match_state = "#{MatchState::LABEL}:1:1::#{arbitrary_hole_card_hand}"
|
183
|
-
patient = MatchState.parse initial_match_state
|
184
|
-
patient.last_action.
|
185
|
-
patient.round_in_which_last_action_taken.
|
186
|
-
patient.first_state_of_first_round?.
|
175
|
+
initial_match_state = "#{AcpcPokerTypes::MatchState::LABEL}:1:1::#{arbitrary_hole_card_hand}"
|
176
|
+
patient = AcpcPokerTypes::MatchState.parse initial_match_state
|
177
|
+
patient.last_action.must_be_nil
|
178
|
+
patient.round_in_which_last_action_taken.must_be_nil
|
179
|
+
patient.first_state_of_first_round?.must_equal true
|
187
180
|
end
|
188
181
|
it 'works properly if a previous action exists' do
|
189
|
-
PokerAction::LEGAL_ACPC_CHARACTERS.each do |first_action|
|
190
|
-
PokerAction::LEGAL_ACPC_CHARACTERS.each do |second_action|
|
191
|
-
PokerAction::LEGAL_ACPC_CHARACTERS.each do |third_action|
|
192
|
-
partial_match_state = "#{MatchState::LABEL}:1:1:"
|
182
|
+
AcpcPokerTypes::PokerAction::LEGAL_ACPC_CHARACTERS.each do |first_action|
|
183
|
+
AcpcPokerTypes::PokerAction::LEGAL_ACPC_CHARACTERS.each do |second_action|
|
184
|
+
AcpcPokerTypes::PokerAction::LEGAL_ACPC_CHARACTERS.each do |third_action|
|
185
|
+
partial_match_state = "#{AcpcPokerTypes::MatchState::LABEL}:1:1:"
|
193
186
|
|
194
187
|
partial_match_state += first_action
|
195
188
|
match_state = "#{partial_match_state}:#{arbitrary_hole_card_hand}"
|
196
189
|
|
197
|
-
patient = MatchState.parse match_state
|
198
|
-
patient.last_action.
|
199
|
-
patient.round_in_which_last_action_taken.
|
200
|
-
patient.first_state_of_first_round?.
|
190
|
+
patient = AcpcPokerTypes::MatchState.parse match_state
|
191
|
+
patient.last_action.must_equal AcpcPokerTypes::PokerAction.new(first_action)
|
192
|
+
patient.round_in_which_last_action_taken.must_equal 0
|
193
|
+
patient.first_state_of_first_round?.must_equal false
|
201
194
|
|
202
195
|
partial_match_state += "#{second_action}/"
|
203
196
|
match_state = "#{partial_match_state}:#{arbitrary_hole_card_hand}"
|
204
197
|
|
205
|
-
patient = MatchState.parse match_state
|
206
|
-
patient.last_action.
|
207
|
-
patient.round_in_which_last_action_taken.
|
208
|
-
patient.first_state_of_first_round?.
|
198
|
+
patient = AcpcPokerTypes::MatchState.parse match_state
|
199
|
+
patient.last_action.must_equal AcpcPokerTypes::PokerAction.new(second_action)
|
200
|
+
patient.round_in_which_last_action_taken.must_equal 0
|
201
|
+
patient.first_state_of_first_round?.must_equal false
|
209
202
|
|
210
203
|
partial_match_state += third_action
|
211
204
|
match_state = "#{partial_match_state}:#{arbitrary_hole_card_hand}"
|
212
205
|
|
213
|
-
patient = MatchState.parse match_state
|
214
|
-
patient.last_action.
|
215
|
-
patient.round_in_which_last_action_taken.
|
216
|
-
patient.first_state_of_first_round?.
|
206
|
+
patient = AcpcPokerTypes::MatchState.parse match_state
|
207
|
+
patient.last_action.must_equal AcpcPokerTypes::PokerAction.new(third_action)
|
208
|
+
patient.round_in_which_last_action_taken.must_equal 1
|
209
|
+
patient.first_state_of_first_round?.must_equal false
|
217
210
|
end
|
218
211
|
end
|
219
212
|
end
|
220
213
|
end
|
221
214
|
end
|
215
|
+
end
|
222
216
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
users_hole_cards = arbitrary_hole_card_hand
|
229
|
-
list_of_opponents_hole_cards = [[]]
|
230
|
-
|
231
|
-
(betting_string, list_of_betting_actions) = generate_betting_sequence action_string + raise_amount.to_s
|
232
|
-
number_of_actions_this_round = list_of_betting_actions.length
|
233
|
-
|
234
|
-
list_of_board_cards = []
|
235
|
-
board_cards_string = ""
|
236
|
-
|
237
|
-
number_of_rounds = 100
|
238
|
-
(1..number_of_rounds-1).each do |round|
|
239
|
-
match_state = partial_match_state + betting_string + ":|#{users_hole_cards}#{board_cards_string}"
|
240
|
-
|
241
|
-
round_index = round - 1
|
242
|
-
|
243
|
-
test_full_information(match_state, list_of_betting_actions,
|
244
|
-
last_action(list_of_betting_actions), users_hole_cards,
|
245
|
-
list_of_opponents_hole_cards, list_of_board_cards, round_index,
|
246
|
-
number_of_actions_this_round)
|
247
|
-
|
248
|
-
# Make an interesting raise amount if the caller specified a raise amount in the first place
|
249
|
-
raise_amount += 10**round + round*3 unless raise_amount.to_s.empty?
|
250
|
-
|
251
|
-
betting_string = generate_betting_sequence(
|
252
|
-
betting_string,
|
253
|
-
list_of_betting_actions,
|
254
|
-
action_string + raise_amount.to_s
|
255
|
-
)
|
256
|
-
|
257
|
-
list_of_board_cards << (if round > 1
|
258
|
-
(round+1).to_s + Suit::DOMAIN[:spades][:acpc_character]
|
259
|
-
else
|
260
|
-
arbitrary_flop
|
261
|
-
end)
|
262
|
-
board_cards_string += "/" + list_of_board_cards[round]
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
def for_every_card
|
267
|
-
Rank::DOMAIN.map do |rank, rank_properties|
|
268
|
-
Suit::DOMAIN.map do |suit, suit_properties|
|
269
|
-
yield Card.from_components(rank, suit)
|
270
|
-
end
|
271
|
-
end
|
272
|
-
end
|
273
|
-
def for_every_hand
|
274
|
-
for_every_card do |first_card|
|
275
|
-
for_every_card do |second_card|
|
276
|
-
yield Hand.draw_cards(first_card, second_card)
|
277
|
-
end
|
278
|
-
end
|
279
|
-
end
|
280
|
-
|
281
|
-
def generate_betting_sequence(betting_string = "", list_of_betting_actions = [], action_string)
|
282
|
-
betting_string += if betting_string.empty?
|
283
|
-
action_string
|
284
|
-
else
|
285
|
-
"/#{action_string}"
|
286
|
-
end
|
287
|
-
(list_of_betting_actions << action_string.scan(/[^\/]\d*/)).flatten!
|
288
|
-
|
289
|
-
[betting_string, list_of_betting_actions]
|
290
|
-
end
|
291
|
-
|
292
|
-
def last_action(list_of_betting_actions)
|
293
|
-
list_of_betting_actions[-1]
|
294
|
-
end
|
295
|
-
|
296
|
-
def test_full_information(match_state, list_of_betting_actions,
|
297
|
-
last_action, users_hole_cards, list_of_opponents_hole_cards,
|
298
|
-
list_of_board_cards, round, number_of_actions_this_round)
|
299
|
-
|
300
|
-
patient = test_match_state_success match_state
|
301
|
-
|
302
|
-
patient.betting_sequence.should be == list_of_betting_actions
|
303
|
-
patient.last_action.should be == last_action
|
304
|
-
patient.users_hole_cards.to_s.should be == users_hole_cards.to_s
|
305
|
-
patient.list_of_opponents_hole_cards.should be == list_of_opponents_hole_cards
|
306
|
-
(if patient.board_cards.join.empty? then [] else [patient.board_cards.join] end).should be == list_of_board_cards
|
307
|
-
patient.round.should be == round
|
308
|
-
patient.number_of_actions_this_round.should be == number_of_actions_this_round
|
309
|
-
end
|
310
|
-
|
311
|
-
def test_match_state_initialization_error(incomplete_match_state)
|
312
|
-
expect{MatchState.parse incomplete_match_state}.to raise_exception(MatchState::IncompleteMatchState)
|
313
|
-
end
|
314
|
-
def test_match_state_success(match_state)
|
315
|
-
patient = MatchState.parse match_state
|
316
|
-
patient.to_s.should be == match_state
|
317
|
-
|
318
|
-
patient
|
319
|
-
end
|
320
|
-
def arbitrary_flop
|
321
|
-
flop = ""
|
322
|
-
rank = 2
|
323
|
-
(Suit::DOMAIN.values.map { |suit| suit[:acpc_character] }).each do |suit|
|
324
|
-
flop += rank.to_s + suit unless Suit::DOMAIN[:clubs][:acpc_character] == suit
|
325
|
-
rank += 1
|
217
|
+
def for_every_card
|
218
|
+
AcpcPokerTypes::Rank::DOMAIN.map do |rank, rank_properties|
|
219
|
+
AcpcPokerTypes::Suit::DOMAIN.map do |suit, suit_properties|
|
220
|
+
yield AcpcPokerTypes::Card.from_components(rank, suit)
|
326
221
|
end
|
327
|
-
flop
|
328
222
|
end
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
'2' + Suit::DOMAIN[:spades][:acpc_character]
|
335
|
-
else
|
336
|
-
arbitrary_flop
|
337
|
-
end
|
223
|
+
end
|
224
|
+
def for_every_hand
|
225
|
+
for_every_card do |first_card|
|
226
|
+
for_every_card do |second_card|
|
227
|
+
yield AcpcPokerTypes::Hand.draw_cards(first_card, second_card)
|
338
228
|
end
|
339
|
-
|
340
|
-
board_cards
|
341
229
|
end
|
230
|
+
end
|
342
231
|
|
232
|
+
def test_match_state_initialization_error(incomplete_match_state)
|
233
|
+
->{AcpcPokerTypes::MatchState.parse incomplete_match_state}.must_raise(AcpcPokerTypes::MatchState::IncompleteMatchState)
|
234
|
+
end
|
235
|
+
def test_match_state_success(match_state)
|
236
|
+
patient = AcpcPokerTypes::MatchState.parse match_state
|
237
|
+
patient.to_s.must_equal match_state
|
343
238
|
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
hand_number = 0
|
353
|
-
hole_card_hand = arbitrary_hole_card_hand
|
354
|
-
initial_match_state = mock('MatchState')
|
355
|
-
initial_match_state.stubs(:position_relative_to_dealer).returns(user_position)
|
356
|
-
initial_match_state.stubs(:hand_number).returns(hand_number)
|
357
|
-
initial_match_state.stubs(:list_of_board_cards).returns([])
|
358
|
-
initial_match_state.stubs(:list_of_betting_actions).returns([])
|
359
|
-
initial_match_state.stubs(:users_hole_cards).returns(hole_card_hand)
|
360
|
-
initial_match_state.stubs(:list_of_opponents_hole_cards).returns([])
|
361
|
-
initial_match_state.stubs(:list_of_hole_card_hands).returns(list_of_hole_card_hands(user_position, hole_card_hand, number_of_players))
|
362
|
-
initial_match_state.stubs(:last_action).returns(nil)
|
363
|
-
initial_match_state.stubs(:round).returns(0)
|
364
|
-
initial_match_state.stubs(:number_of_actions_in_current_round).returns(0)
|
365
|
-
|
366
|
-
raw_match_state = MatchState::LABEL + ":#{user_position}:#{hand_number}::" + hole_card_hand
|
367
|
-
initial_match_state.stubs(:to_s).returns(raw_match_state)
|
368
|
-
|
369
|
-
[initial_match_state, user_position]
|
239
|
+
patient
|
240
|
+
end
|
241
|
+
def arbitrary_flop
|
242
|
+
flop = ""
|
243
|
+
rank = 2
|
244
|
+
(AcpcPokerTypes::Suit::DOMAIN.values.map { |suit| suit[:acpc_character] }).each do |suit|
|
245
|
+
flop += rank.to_s + suit unless AcpcPokerTypes::Suit::DOMAIN[:clubs][:acpc_character] == suit
|
246
|
+
rank += 1
|
370
247
|
end
|
248
|
+
flop
|
249
|
+
end
|
371
250
|
|
372
|
-
|
373
|
-
|
374
|
-
|
251
|
+
def arbitrary_roll_out(rounds)
|
252
|
+
board_cards = ""
|
253
|
+
(1..rounds-1).each do |round|
|
254
|
+
board_cards += "/" + if round > 1
|
255
|
+
'2' + AcpcPokerTypes::Suit::DOMAIN[:spades][:acpc_character]
|
375
256
|
else
|
376
|
-
|
377
|
-
end)
|
378
|
-
|
379
|
-
number_of_entries_in_the_list.times.inject([]) do |i|
|
380
|
-
hole_card_sets << (if i == user_position then user_hole_card_hand else '' end)
|
257
|
+
arbitrary_flop
|
381
258
|
end
|
382
259
|
end
|
383
260
|
|
384
|
-
|
385
|
-
game_definition = mock('GameDefinition')
|
386
|
-
game_definition.stubs(:number_of_players).returns(3)
|
387
|
-
game_definition.stubs(:minimum_wager_in_each_round).returns([10, 10, 20, 20])
|
388
|
-
game_definition.stubs(:first_player_position_in_each_round).returns([2, 1, 1, 1])
|
389
|
-
game_definition.stubs(:max_raise_in_each_round).returns([3, 4, 4, 4])
|
390
|
-
game_definition.stubs(:list_of_player_stacks).returns([20000, 20000, 20000])
|
391
|
-
game_definition.stubs(:big_blind).returns(10)
|
392
|
-
game_definition.stubs(:small_blind).returns(5)
|
393
|
-
|
394
|
-
game_definition
|
395
|
-
end
|
396
|
-
|
397
|
-
def create_player_manager(game_definition)
|
398
|
-
player_manager = mock('PlayerManager')
|
399
|
-
|
400
|
-
(player_who_submitted_big_blind, player_who_submitted_small_blind, other_player) = create_players game_definition.big_blind, game_definition.small_blind
|
401
|
-
|
402
|
-
player_manager.stubs(:player_who_submitted_big_blind).returns(player_who_submitted_big_blind)
|
403
|
-
player_manager.stubs(:player_who_submitted_small_blind).returns(player_who_submitted_small_blind)
|
404
|
-
player_manager.stubs(:players_who_did_not_submit_a_blind).returns([other_player])
|
405
|
-
|
406
|
-
list_of_player_stacks = game_definition.list_of_player_stacks.dup
|
407
|
-
player_manager.stubs(:list_of_player_stacks).returns(list_of_player_stacks)
|
408
|
-
|
409
|
-
player_manager
|
410
|
-
end
|
411
|
-
|
412
|
-
def create_players(big_blind, small_blind)
|
413
|
-
player_who_submitted_big_blind = mock('Player')
|
414
|
-
player_who_submitted_big_blind.stubs(:current_wager_faced=).with(0)
|
415
|
-
player_who_submitted_big_blind.stubs(:current_wager_faced).returns(0)
|
416
|
-
player_who_submitted_big_blind.stubs(:name).returns('big_blind_player')
|
417
|
-
|
418
|
-
player_who_submitted_small_blind = mock('Player')
|
419
|
-
player_who_submitted_small_blind.stubs(:current_wager_faced=).with(big_blind - small_blind)
|
420
|
-
player_who_submitted_small_blind.stubs(:current_wager_faced).returns(big_blind - small_blind)
|
421
|
-
player_who_submitted_small_blind.stubs(:name).returns('small_blind_player')
|
422
|
-
|
423
|
-
other_player = mock('Player')
|
424
|
-
other_player.stubs(:current_wager_faced=).with(big_blind)
|
425
|
-
other_player.stubs(:current_wager_faced).returns(big_blind)
|
426
|
-
other_player.stubs(:name).returns('other_player')
|
427
|
-
|
428
|
-
[player_who_submitted_big_blind, player_who_submitted_small_blind, other_player]
|
429
|
-
end
|
430
|
-
|
431
|
-
def setup_action_test(match_state, action_type, action_argument = '')
|
432
|
-
action = action_argument + action_type
|
433
|
-
expected_string = raw_match_state match_state, action
|
434
|
-
|
435
|
-
expected_string
|
436
|
-
end
|
437
|
-
|
438
|
-
|
439
|
-
# Helper methods -----------------------------------------------------------
|
440
|
-
|
441
|
-
def raw_match_state(match_state, action)
|
442
|
-
"#{match_state}:#{action}"
|
443
|
-
end
|
444
|
-
|
445
|
-
# Construct an arbitrary hole card hand.
|
446
|
-
#
|
447
|
-
# @return [Mock Hand] An arbitrary hole card hand.
|
448
|
-
def arbitrary_hole_card_hand
|
449
|
-
Hand.from_acpc(
|
450
|
-
Rank::DOMAIN[:two][:acpc_character] +
|
451
|
-
Suit::DOMAIN[:spades][:acpc_character] +
|
452
|
-
Rank::DOMAIN[:three][:acpc_character] +
|
453
|
-
Suit::DOMAIN[:hearts][:acpc_character]
|
454
|
-
)
|
455
|
-
end
|
261
|
+
board_cards
|
456
262
|
end
|
263
|
+
|
264
|
+
# Construct an arbitrary hole card hand.
|
265
|
+
#
|
266
|
+
# @return [Mock AcpcPokerTypes::Hand] An arbitrary hole card hand.
|
267
|
+
def arbitrary_hole_card_hand
|
268
|
+
AcpcPokerTypes::Hand.from_acpc(
|
269
|
+
AcpcPokerTypes::Rank::DOMAIN[:two][:acpc_character] +
|
270
|
+
AcpcPokerTypes::Suit::DOMAIN[:spades][:acpc_character] +
|
271
|
+
AcpcPokerTypes::Rank::DOMAIN[:three][:acpc_character] +
|
272
|
+
AcpcPokerTypes::Suit::DOMAIN[:hearts][:acpc_character]
|
273
|
+
)
|
274
|
+
end
|