bhousel-ruby-poker 0.4.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.
- data/CHANGELOG +54 -0
- data/LICENSE.txt +20 -0
- data/README.md +50 -0
- data/Rakefile +11 -0
- data/examples/deck.rb +48 -0
- data/examples/quick_example.rb +11 -0
- data/lib/ruby-poker.rb +2 -0
- data/lib/ruby-poker/card.rb +142 -0
- data/lib/ruby-poker/poker_hand.rb +487 -0
- data/ruby-poker.gemspec +29 -0
- data/test/test_card.rb +72 -0
- data/test/test_helper.rb +7 -0
- data/test/test_poker_hand.rb +523 -0
- metadata +78 -0
data/ruby-poker.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "bhousel-ruby-poker"
|
3
|
+
s.version = "0.4.0"
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
s.summary = "Poker library in Ruby"
|
6
|
+
s.description = "Ruby library for comparing poker hands and determining the winner."
|
7
|
+
s.author = "Bryan Housel"
|
8
|
+
s.email = "bryan@7thposition.com"
|
9
|
+
s.homepage = "https://github.com/bhousel/ruby-poker"
|
10
|
+
s.files = ["CHANGELOG",
|
11
|
+
"examples/deck.rb",
|
12
|
+
"examples/quick_example.rb",
|
13
|
+
"lib/ruby-poker.rb",
|
14
|
+
"lib/ruby-poker/card.rb",
|
15
|
+
"lib/ruby-poker/poker_hand.rb",
|
16
|
+
"LICENSE.txt",
|
17
|
+
"Rakefile",
|
18
|
+
"README.md",
|
19
|
+
"ruby-poker.gemspec"]
|
20
|
+
s.test_files = ["test/test_helper.rb",
|
21
|
+
"test/test_card.rb",
|
22
|
+
"test/test_poker_hand.rb"]
|
23
|
+
s.require_paths << 'lib'
|
24
|
+
s.rdoc_options << '--title' << 'Ruby Poker Documentation' <<
|
25
|
+
'--main' << 'README.rdoc' <<
|
26
|
+
'--inline-source' << '-q'
|
27
|
+
|
28
|
+
s.add_development_dependency('shoulda', '~> 2.0')
|
29
|
+
end
|
data/test/test_card.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
2
|
+
|
3
|
+
class TestCard < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
# testing various input formats for cards
|
6
|
+
@c1 = Card.new("9c")
|
7
|
+
@c2 = Card.new("TD")
|
8
|
+
@c3 = Card.new("jh")
|
9
|
+
@c4 = Card.new("qS")
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_class_face_value
|
13
|
+
assert_nil(Card.face_value('L'))
|
14
|
+
assert_equal(13, Card.face_value('A'))
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_build_from_card
|
18
|
+
assert_equal("9c", Card.new(@c1).to_s)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_build_from_value
|
22
|
+
assert_equal(@c1, Card.new(7))
|
23
|
+
assert_equal(@c2, Card.new(22))
|
24
|
+
assert_equal(@c3, Card.new(37))
|
25
|
+
assert_equal(@c4, Card.new(52))
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_build_from_face_suit
|
29
|
+
assert_equal(7, Card.new('9', 'c').value)
|
30
|
+
assert_equal(22, Card.new('T', 'd').value)
|
31
|
+
assert_equal(37, Card.new('J', 'h').value)
|
32
|
+
assert_equal(52, Card.new('Q', 's').value)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_face
|
36
|
+
assert_equal(8, @c1.face)
|
37
|
+
assert_equal(9, @c2.face)
|
38
|
+
assert_equal(10, @c3.face)
|
39
|
+
assert_equal(11, @c4.face)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_suit
|
43
|
+
assert_equal(0, @c1.suit)
|
44
|
+
assert_equal(1, @c2.suit)
|
45
|
+
assert_equal(2, @c3.suit)
|
46
|
+
assert_equal(3, @c4.suit)
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_value
|
50
|
+
assert_equal(7, @c1.value)
|
51
|
+
assert_equal(22, @c2.value)
|
52
|
+
assert_equal(37, @c3.value)
|
53
|
+
assert_equal(52, @c4.value)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_natural_value
|
57
|
+
assert_equal(1, Card.new("AC").natural_value)
|
58
|
+
assert_equal(15, Card.new("2D").natural_value)
|
59
|
+
assert_equal(52, Card.new("KS").natural_value)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_comparison
|
63
|
+
assert(@c1 < @c2)
|
64
|
+
assert(@c3 > @c2)
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_equals
|
68
|
+
c = Card.new("9h")
|
69
|
+
assert_not_equal(@c1, c)
|
70
|
+
assert_equal(@c1, @c1)
|
71
|
+
end
|
72
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,523 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/test_helper')
|
2
|
+
|
3
|
+
class TestPokerHand < Test::Unit::TestCase
|
4
|
+
context "A PokerHand instance" do
|
5
|
+
|
6
|
+
setup do
|
7
|
+
@quads = PokerHand.new('Kc Kh Kd Ks Qs')
|
8
|
+
@full_boat = PokerHand.new(["2H", "2D", "4C", "4D", "4S"])
|
9
|
+
@flush = PokerHand.new("3D 6D 7D TD QD 5H 2S")
|
10
|
+
@straight = PokerHand.new("8H 9D TS JH QC AS")
|
11
|
+
@trips = PokerHand.new("2D 9C AS AH AC")
|
12
|
+
@two_pair = PokerHand.new("As Ac Kc Kd 2s")
|
13
|
+
@pair = PokerHand.new("As Ac Kc Qd 2s")
|
14
|
+
@ace_high = PokerHand.new("As Jh 9c 7d 5s")
|
15
|
+
end
|
16
|
+
|
17
|
+
should "handle single card hands" do
|
18
|
+
assert_equal(PokerHand.new('As').rank, @ace_high.rank)
|
19
|
+
end
|
20
|
+
|
21
|
+
should "handle two card hands" do
|
22
|
+
assert_equal(PokerHand.new('As Ac').rank, @pair.rank)
|
23
|
+
end
|
24
|
+
|
25
|
+
should "handle three card hands" do
|
26
|
+
assert_equal(PokerHand.new('As Ac Ah').rank, @trips.rank)
|
27
|
+
end
|
28
|
+
|
29
|
+
should "handle four card hands" do
|
30
|
+
assert_equal(PokerHand.new('As Ac Kd Kh').rank, @two_pair.rank)
|
31
|
+
assert_equal(PokerHand.new('As Ac Ad Ah').rank, @quads.rank)
|
32
|
+
end
|
33
|
+
|
34
|
+
should "handle lower case face card names" do
|
35
|
+
assert_equal(0, PokerHand.new('kc kd') <=> PokerHand.new('Kc Kd'))
|
36
|
+
assert_equal(0, PokerHand.new('kc kd') <=> PokerHand.new('Kc KD'))
|
37
|
+
end
|
38
|
+
|
39
|
+
should "handle hands without space" do
|
40
|
+
assert_equal(0, PokerHand.new('KcKd') <=> PokerHand.new('Kc Kd'))
|
41
|
+
assert_equal(0, PokerHand.new('KcKd9d') <=> PokerHand.new('Kc Kd 9d'))
|
42
|
+
end
|
43
|
+
|
44
|
+
should "raise a clear error with invalid cards" do
|
45
|
+
e = assert_raises(ArgumentError) { PokerHand.new('Fc') }
|
46
|
+
assert_match(/"Fc"/, e.message)
|
47
|
+
e = assert_raises(ArgumentError) { PokerHand.new('Tp') }
|
48
|
+
assert_match(/"Tp"/, e.message)
|
49
|
+
end
|
50
|
+
|
51
|
+
should "sort using rank" do
|
52
|
+
assert_equal("As Ah Ac 9c 2d", @trips.sort_using_rank)
|
53
|
+
assert_equal("4s 4d 4c 2h 2d", @full_boat.sort_using_rank)
|
54
|
+
assert_equal("Qd Td 7d 6d 3d 2s 5h", @flush.sort_using_rank)
|
55
|
+
assert_equal("Qc Jh Ts 9d 8h As", @straight.sort_using_rank)
|
56
|
+
|
57
|
+
assert_equal("As Ah 3d 3c Kd", PokerHand.new("AS AH KD 3D 3C").sort_using_rank)
|
58
|
+
assert_equal("As Ah 3d 3c 2d", PokerHand.new("2D AS AH 3D 3C").sort_using_rank)
|
59
|
+
end
|
60
|
+
|
61
|
+
should "return card sorted by face value" do
|
62
|
+
assert_equal([13, 13, 13, 8, 1], @trips.by_face.hand.collect {|c| c.face})
|
63
|
+
end
|
64
|
+
|
65
|
+
should "return cards sorted by suit" do
|
66
|
+
assert_equal([3, 2, 1, 0, 0], @trips.by_suit.hand.collect {|c| c.suit})
|
67
|
+
end
|
68
|
+
|
69
|
+
should "return just the face values of the cards" do
|
70
|
+
assert_equal([1, 8, 13, 13, 13], @trips.face_values)
|
71
|
+
end
|
72
|
+
|
73
|
+
should "recognize a straight flush" do
|
74
|
+
assert !@flush.straight_flush?
|
75
|
+
assert !@straight.straight_flush?
|
76
|
+
assert PokerHand.new("8H 9H TH JH QH AS").straight_flush?
|
77
|
+
end
|
78
|
+
|
79
|
+
should "recognize a royal flush" do
|
80
|
+
assert !@flush.royal_flush?
|
81
|
+
assert PokerHand.new("AD KD QD JD TD").royal_flush?
|
82
|
+
end
|
83
|
+
|
84
|
+
should "recognize a flush" do
|
85
|
+
assert @flush.flush?
|
86
|
+
assert !@trips.flush?
|
87
|
+
end
|
88
|
+
|
89
|
+
should "recognize a four of a kind" do
|
90
|
+
assert !@trips.four_of_a_kind?
|
91
|
+
assert PokerHand.new("AD 9C AS AH AC")
|
92
|
+
end
|
93
|
+
|
94
|
+
should "recognize a full house" do
|
95
|
+
assert !@trips.full_house?
|
96
|
+
assert @full_boat.full_house?
|
97
|
+
end
|
98
|
+
|
99
|
+
should "recognize a straight" do
|
100
|
+
assert @straight.straight?
|
101
|
+
assert PokerHand.new("AH 2S 3D 4H 5D").straight?
|
102
|
+
end
|
103
|
+
|
104
|
+
should "recognize a three of a kind" do
|
105
|
+
assert @trips.three_of_a_kind?
|
106
|
+
end
|
107
|
+
|
108
|
+
should "recognize a two pair" do
|
109
|
+
assert PokerHand.new("2S 2D TH TD 4S").two_pair?
|
110
|
+
assert !PokerHand.new("6D 7C 5D 5H 3S").two_pair?
|
111
|
+
end
|
112
|
+
|
113
|
+
should "recognize a pair" do
|
114
|
+
assert !PokerHand.new("5C JC 2H 7S 3D").pair?
|
115
|
+
assert PokerHand.new("6D 7C 5D 5H 3S").pair?
|
116
|
+
end
|
117
|
+
|
118
|
+
should "recognize a hand with the rank highest_card" do
|
119
|
+
# hard to test, make sure it does not return null
|
120
|
+
assert PokerHand.new("2D 4S 6C 8C TH").highest_card?
|
121
|
+
end
|
122
|
+
|
123
|
+
should "have an instance variable hand that is an array of Cards" do
|
124
|
+
assert_instance_of Card, @trips.hand[0]
|
125
|
+
end
|
126
|
+
|
127
|
+
should "return the hand's rating as a string" do
|
128
|
+
assert_equal "Three of a kind", @trips.hand_rating
|
129
|
+
assert_equal "Full house", @full_boat.hand_rating
|
130
|
+
end
|
131
|
+
|
132
|
+
should "respond to rank" do
|
133
|
+
# rank is an alias for hand_rating
|
134
|
+
assert_respond_to @trips, :rank
|
135
|
+
end
|
136
|
+
|
137
|
+
should "return the hand as a string" do
|
138
|
+
assert_equal("2d 9c As Ah Ac", @trips.just_cards)
|
139
|
+
end
|
140
|
+
|
141
|
+
should "return the hand's score" do
|
142
|
+
assert_equal([4, 13, 8, 1], @trips.score[0])
|
143
|
+
end
|
144
|
+
|
145
|
+
should "be able to match regular expressions" do
|
146
|
+
assert_match(/9c/, @trips.to_s)
|
147
|
+
assert_no_match(/AD/, @trips.to_s)
|
148
|
+
end
|
149
|
+
|
150
|
+
should "return the correct number of cards in the hand" do
|
151
|
+
assert_equal(0, PokerHand.new.size)
|
152
|
+
assert_equal(1, PokerHand.new("2c").size)
|
153
|
+
assert_equal(2, PokerHand.new("2c 3d").size)
|
154
|
+
end
|
155
|
+
|
156
|
+
should "be comparable to other PokerHands" do
|
157
|
+
hand1 = PokerHand.new("5C JC 2H 5S 3D")
|
158
|
+
hand2 = PokerHand.new("6D 7C 5D 5H 3S")
|
159
|
+
assert_equal(1, hand1 <=> hand2)
|
160
|
+
assert_equal(-1, hand2 <=> hand1)
|
161
|
+
end
|
162
|
+
|
163
|
+
should "be considered equal to other poker hands that contain the same cards" do
|
164
|
+
assert_equal(0, @trips <=> @trips)
|
165
|
+
|
166
|
+
hand1 = PokerHand.new("Ac Qc Ks Kd 9d 3c")
|
167
|
+
hand2 = PokerHand.new("Ah Qs 9h Kh Kc 3s")
|
168
|
+
assert_equal(0, hand1 <=> hand2)
|
169
|
+
end
|
170
|
+
|
171
|
+
should "be able to insert new cards into the hand" do
|
172
|
+
ph = PokerHand.new()
|
173
|
+
ph << "Qd"
|
174
|
+
ph << Card.new("2D")
|
175
|
+
ph << ["3d", "4d"]
|
176
|
+
assert_equal("Qd 2d 3d 4d", ph.just_cards)
|
177
|
+
end
|
178
|
+
|
179
|
+
should "be able to delete a card" do
|
180
|
+
ph = PokerHand.new("Ac")
|
181
|
+
ph.delete("Ac")
|
182
|
+
assert_equal(Array.new, ph.hand)
|
183
|
+
end
|
184
|
+
|
185
|
+
should "detect the two highest pairs when there are more than two" do
|
186
|
+
ph = PokerHand.new("7d 7s 4d 4c 2h 2d")
|
187
|
+
assert_equal([3, 6, 3, 1], ph.two_pair?[0])
|
188
|
+
# Explanation of [3, 6, 3, 1]
|
189
|
+
# 3: the number for a two pair
|
190
|
+
# 6: highest pair is two 7's
|
191
|
+
# 3: second highest pair is two 4's
|
192
|
+
# 1: kicker is a 2
|
193
|
+
end
|
194
|
+
|
195
|
+
context "when duplicates are allowed" do
|
196
|
+
setup do
|
197
|
+
PokerHand.allow_duplicates = true
|
198
|
+
end
|
199
|
+
|
200
|
+
should "create a PokerHand of unique cards" do
|
201
|
+
uniq_ph = PokerHand.new("3s 4s 3s").uniq
|
202
|
+
assert_instance_of(PokerHand, uniq_ph) # want to be sure uniq hands back a PokerHand
|
203
|
+
assert_contains(uniq_ph.hand, Card.new('3s'))
|
204
|
+
assert_contains(uniq_ph.hand, Card.new('4s'))
|
205
|
+
end
|
206
|
+
|
207
|
+
should "allow five of a kind" do
|
208
|
+
# there is no five of a kind. This just tests to make sure
|
209
|
+
# that ruby-poker doesn't crash if given 5 of the same card
|
210
|
+
ph = PokerHand.new("KS KS KS KS KS")
|
211
|
+
assert_equal("Four of a kind", ph.rank)
|
212
|
+
end
|
213
|
+
|
214
|
+
should "allow duplicates on initialize" do
|
215
|
+
assert_nothing_raised RuntimeError do
|
216
|
+
PokerHand.new("3s 3s")
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
should "allow duplicate card to be added after initialize" do
|
221
|
+
ph = PokerHand.new("2d")
|
222
|
+
ph << "2d"
|
223
|
+
assert_equal("2d 2d", ph.just_cards)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
context "when duplicates are not allowed" do
|
228
|
+
setup do
|
229
|
+
PokerHand.allow_duplicates = false
|
230
|
+
end
|
231
|
+
|
232
|
+
should "not allow duplicates on initialize" do
|
233
|
+
PokerHand.allow_duplicates = false
|
234
|
+
|
235
|
+
assert_raise RuntimeError do
|
236
|
+
PokerHand.new("3s 3s")
|
237
|
+
end
|
238
|
+
|
239
|
+
PokerHand.allow_duplicates = true
|
240
|
+
end
|
241
|
+
|
242
|
+
should "not allow duplicates after initialize" do
|
243
|
+
PokerHand.allow_duplicates = false
|
244
|
+
|
245
|
+
ph = PokerHand.new("2d")
|
246
|
+
assert_raise RuntimeError do
|
247
|
+
ph << "2d"
|
248
|
+
end
|
249
|
+
|
250
|
+
PokerHand.allow_duplicates = true
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
should "have an each method" do
|
255
|
+
cards = []
|
256
|
+
@straight.each do |card|
|
257
|
+
cards << card
|
258
|
+
end
|
259
|
+
assert_equal @straight.to_a, cards
|
260
|
+
end
|
261
|
+
|
262
|
+
should "be Enumerable" do
|
263
|
+
assert PokerHand.include?(Enumerable)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
context "addition" do
|
268
|
+
setup do
|
269
|
+
@base = PokerHand.new('Ac Kc')
|
270
|
+
end
|
271
|
+
|
272
|
+
should "work with a string" do
|
273
|
+
assert_equal PokerHand.new('Ac Kc Qc'), @base + 'Qc'
|
274
|
+
end
|
275
|
+
|
276
|
+
should "work with a card" do
|
277
|
+
assert_equal PokerHand.new('Ac Kc Qc'), @base + Card.new('Qc')
|
278
|
+
end
|
279
|
+
|
280
|
+
should "work with a hand" do
|
281
|
+
assert_equal PokerHand.new('Ac Kc Qc'), @base + PokerHand.new('Qc')
|
282
|
+
end
|
283
|
+
|
284
|
+
should "not affect receiver hand" do
|
285
|
+
result = @base + 'Qc'
|
286
|
+
assert_equal PokerHand.new('Ac Kc'), @base
|
287
|
+
end
|
288
|
+
|
289
|
+
should "not affect receiver cards" do
|
290
|
+
result = @base + 'Qc'
|
291
|
+
result.to_a.first.instance_eval { @face = Card.face_value('2') }
|
292
|
+
assert_equal PokerHand.new('Ac Kc'), @base
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
context "PokerHand#pair?" do
|
297
|
+
|
298
|
+
should "return false with one card" do
|
299
|
+
assert !PokerHand.new("2h").pair?
|
300
|
+
end
|
301
|
+
|
302
|
+
context "with a pair" do
|
303
|
+
|
304
|
+
should "return 2, followed by the pair value" do
|
305
|
+
assert_equal [2, 5-1], PokerHand.new("5h 5s").pair?[0]
|
306
|
+
end
|
307
|
+
|
308
|
+
context "with a two card hand" do
|
309
|
+
setup do
|
310
|
+
@ph = PokerHand.new("5h 5s")
|
311
|
+
@scoring = @ph.pair?[0]
|
312
|
+
end
|
313
|
+
|
314
|
+
should "return scoring with 2 entries" do
|
315
|
+
assert_equal 2, @scoring.size
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
context "with a three card hand" do
|
320
|
+
setup do
|
321
|
+
@ph = PokerHand.new("5h 5s 8s")
|
322
|
+
@scoring = @ph.pair?[0]
|
323
|
+
end
|
324
|
+
|
325
|
+
should "return scoring with 3 entries" do
|
326
|
+
assert_equal 3, @scoring.size
|
327
|
+
end
|
328
|
+
|
329
|
+
should "return the value of the kicker" do
|
330
|
+
assert_equal 8-1, @scoring[2]
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
context "with a four card hand" do
|
335
|
+
setup do
|
336
|
+
@ph = PokerHand.new("5h 5s 8s 7s")
|
337
|
+
@scoring = @ph.pair?[0]
|
338
|
+
end
|
339
|
+
|
340
|
+
should "return scoring with 4 entries" do
|
341
|
+
assert_equal 4, @scoring.size
|
342
|
+
end
|
343
|
+
|
344
|
+
should "return the values of the kickers" do
|
345
|
+
assert_equal 8-1, @scoring[2]
|
346
|
+
assert_equal 7-1, @scoring[3]
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
context "with a five (or more) card hand" do
|
351
|
+
setup do
|
352
|
+
@ph = PokerHand.new("5h 5s 8s 7s 6s 2h")
|
353
|
+
@scoring = @ph.pair?[0]
|
354
|
+
end
|
355
|
+
|
356
|
+
should "return scoring with 5 entries" do
|
357
|
+
assert_equal 5, @scoring.size
|
358
|
+
end
|
359
|
+
|
360
|
+
should "return the values of the kickers" do
|
361
|
+
assert_equal 8-1, @scoring[2]
|
362
|
+
assert_equal 7-1, @scoring[3]
|
363
|
+
assert_equal 6-1, @scoring[4]
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
context "without a pair" do
|
369
|
+
should "return false" do
|
370
|
+
assert !PokerHand.new("2h 3h").pair?
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
|
376
|
+
def assert_hand_match(expression, cards)
|
377
|
+
hand = PokerHand.new(cards)
|
378
|
+
assert hand.match?(expression), "#{cards} didn't match #{expression}"
|
379
|
+
end
|
380
|
+
|
381
|
+
def assert_hand_not_match(expression, cards)
|
382
|
+
hand = PokerHand.new(cards)
|
383
|
+
assert !hand.match?(expression), "#{cards} did match #{expression}"
|
384
|
+
end
|
385
|
+
|
386
|
+
context "matching expression" do
|
387
|
+
should "match two faces" do
|
388
|
+
assert_hand_match 'AA', 'Ah Ad'
|
389
|
+
assert_hand_match 'Q8', 'Qc 8d'
|
390
|
+
end
|
391
|
+
|
392
|
+
should "not match two faces" do
|
393
|
+
assert_hand_not_match 'T9', 'Tc 8s'
|
394
|
+
assert_hand_not_match 'QQ', 'Tc 8s'
|
395
|
+
end
|
396
|
+
|
397
|
+
should "match unordered faces" do
|
398
|
+
assert_hand_match 'K7', '7c Ks'
|
399
|
+
end
|
400
|
+
|
401
|
+
should "match suited when suited" do
|
402
|
+
assert_hand_match 'Q8s', 'Qc 8c'
|
403
|
+
assert_hand_match '56s', '5h 6h'
|
404
|
+
end
|
405
|
+
|
406
|
+
should "not match suited when offsuit" do
|
407
|
+
assert_hand_not_match 'Q8s', 'Qc 8d'
|
408
|
+
assert_hand_not_match '56s', '5h 6c'
|
409
|
+
end
|
410
|
+
|
411
|
+
should "match offsuit when offsuited" do
|
412
|
+
assert_hand_match 'Q8o', 'Qc 8h'
|
413
|
+
assert_hand_match '56o', '5h 6s'
|
414
|
+
end
|
415
|
+
|
416
|
+
should "not match offsuit when suited" do
|
417
|
+
assert_hand_not_match 'Q8o', 'Qc 8c'
|
418
|
+
assert_hand_not_match '56o', '5h 6h'
|
419
|
+
end
|
420
|
+
|
421
|
+
should "match pair min" do
|
422
|
+
assert_hand_match 'JJ+', 'Jc Js'
|
423
|
+
assert_hand_match '66+', 'Qc Qh'
|
424
|
+
assert_hand_match 'JJ+', 'Ad Ac'
|
425
|
+
end
|
426
|
+
|
427
|
+
should "not match pair min" do
|
428
|
+
assert_hand_not_match 'JJ+', 'Tc Ts'
|
429
|
+
assert_hand_not_match '66+', 'Qc Kh'
|
430
|
+
assert_hand_not_match 'AA+', '2d 2c'
|
431
|
+
end
|
432
|
+
|
433
|
+
should "match face min" do
|
434
|
+
assert_hand_match 'AJ+', 'Ac Js'
|
435
|
+
assert_hand_match 'AQ+', 'Ac Kc'
|
436
|
+
assert_hand_match 'AJ+', 'Ac As'
|
437
|
+
assert_hand_match 'QT+', 'Qc Ts'
|
438
|
+
assert_hand_match 'QT+', 'Qc Qs'
|
439
|
+
assert_hand_not_match 'QT+', 'Qc Ks' # sure? should be matched with KQ+?
|
440
|
+
assert_hand_not_match 'AJ+', 'Ac Ts'
|
441
|
+
assert_hand_not_match 'AJ+', 'Tc Ts'
|
442
|
+
end
|
443
|
+
|
444
|
+
should "match suited face min" do
|
445
|
+
assert_hand_match 'AJs+', 'Ac Jc'
|
446
|
+
assert_hand_match 'AQs+', 'Ac Kc'
|
447
|
+
assert_hand_not_match 'AJs+', 'Ac As'
|
448
|
+
assert_hand_match 'QTs+', 'Qc Tc'
|
449
|
+
assert_hand_not_match 'QTs+', 'Qc Ts'
|
450
|
+
assert_hand_not_match 'AJs+', 'Ac Qs'
|
451
|
+
end
|
452
|
+
|
453
|
+
should "match offsuit face min" do
|
454
|
+
assert_hand_match 'AJo+', 'Ac Jd'
|
455
|
+
assert_hand_match 'AQo+', 'Ac Kh'
|
456
|
+
assert_hand_match 'AJo+', 'Ac As'
|
457
|
+
assert_hand_match 'QTo+', 'Qc Td'
|
458
|
+
assert_hand_not_match 'QTo+', 'Qc Tc'
|
459
|
+
assert_hand_not_match 'AJo+', 'Ac Qc'
|
460
|
+
end
|
461
|
+
|
462
|
+
should "match face with 1 gap" do
|
463
|
+
assert_hand_match '89+', '8c 9d'
|
464
|
+
assert_hand_match '89+', '9c Td'
|
465
|
+
assert_hand_match '89+', 'Tc Jd'
|
466
|
+
assert_hand_match '89+', 'Ac Kd'
|
467
|
+
assert_hand_not_match '89+', '8c Td'
|
468
|
+
assert_hand_not_match '89+', 'Tc Td'
|
469
|
+
assert_hand_not_match '89+', '7c 8d'
|
470
|
+
end
|
471
|
+
|
472
|
+
should "match face with 2 gaps" do
|
473
|
+
assert_hand_match '8T+', '8c Td'
|
474
|
+
assert_hand_match '8T+', 'Tc 8d'
|
475
|
+
assert_hand_match '24+', '9c Jd'
|
476
|
+
assert_hand_match '79+', 'Ac Qd'
|
477
|
+
assert_hand_not_match '8T+', '8c 9d'
|
478
|
+
assert_hand_not_match '8T+', 'Tc Td'
|
479
|
+
assert_hand_not_match '8T+', 'Jc Ad'
|
480
|
+
assert_hand_not_match '8T+', '7c 9d'
|
481
|
+
end
|
482
|
+
|
483
|
+
should "match face with many gaps" do
|
484
|
+
assert_hand_match '8J+', '9c Qd'
|
485
|
+
assert_hand_match '8Q+', '9c Kd'
|
486
|
+
assert_hand_match '8K+', 'Ac 9d'
|
487
|
+
assert_hand_not_match '8J+', '7c Td'
|
488
|
+
end
|
489
|
+
|
490
|
+
should "match face gap with suit" do
|
491
|
+
assert_hand_match '89s+', '9c Tc'
|
492
|
+
assert_hand_not_match '89s+', '9c Td'
|
493
|
+
assert_hand_match '89o+', '9c Th'
|
494
|
+
assert_hand_not_match '89o+', '9d Td'
|
495
|
+
end
|
496
|
+
|
497
|
+
[
|
498
|
+
%w(),
|
499
|
+
%w(Ac),
|
500
|
+
%w(Ac Kc Qc),
|
501
|
+
%w(Ac Kc Qc Jc Tc),
|
502
|
+
].each do |cards|
|
503
|
+
should "raise an error if the number of cards is #{cards.size}" do
|
504
|
+
hand = PokerHand.new(cards)
|
505
|
+
assert_raises RuntimeError do
|
506
|
+
hand.match?('AA')
|
507
|
+
end
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
should "raise an error with invalid expression" do
|
512
|
+
hand = PokerHand.new("Ac Kc")
|
513
|
+
assert_raises ArgumentError do
|
514
|
+
hand.match? "foo"
|
515
|
+
end
|
516
|
+
|
517
|
+
assert_raises ArgumentError do
|
518
|
+
hand.match? ""
|
519
|
+
end
|
520
|
+
end
|
521
|
+
end
|
522
|
+
|
523
|
+
end
|