hands 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/lib/hands.rb +2 -2
- data/lib/hands/card.rb +1 -1
- data/lib/hands/hand.rb +41 -13
- data/lib/hands/version.rb +1 -1
- data/spec/models/card_spec.rb +25 -11
- data/spec/models/hand_spec.rb +56 -22
- data/spec/spec_helper.rb +3 -0
- metadata +1 -1
data/Gemfile
CHANGED
data/lib/hands.rb
CHANGED
@@ -3,10 +3,10 @@ require 'hands/card'
|
|
3
3
|
require 'hands/hand'
|
4
4
|
|
5
5
|
module Hands
|
6
|
-
SUITES = %w{ clubs diamonds hearts spades }
|
7
6
|
VALUES = %w{ 2 3 4 5 6 7 8 9 10 j q k a }
|
8
7
|
VALUE_DESCRIPTIONS = %w{ two three four five six seven eight nine ten jack queen king ace }
|
9
8
|
|
10
|
-
#
|
9
|
+
# Reference: http://www.pagat.com/poker/rules/ranking.html
|
10
|
+
SUITES = %w{ clubs diamonds hearts spades } # Reverse alphabetical
|
11
11
|
HAND_ORDER = %w{ high_card pair two_pair three_of_a_kind straight flush full_house four_of_a_kind straight_flush }
|
12
12
|
end
|
data/lib/hands/card.rb
CHANGED
data/lib/hands/hand.rb
CHANGED
@@ -7,7 +7,7 @@ module Hands
|
|
7
7
|
def cards
|
8
8
|
@cards ||= []
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def <=>(other_hand)
|
12
12
|
response = (self.hand_index <=> other_hand.hand_index)
|
13
13
|
|
@@ -52,7 +52,7 @@ module Hands
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def three_of_a_kind
|
55
|
-
|
55
|
+
self.kinds(3)
|
56
56
|
end
|
57
57
|
|
58
58
|
def straight
|
@@ -85,28 +85,41 @@ module Hands
|
|
85
85
|
end
|
86
86
|
cs
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
def flush
|
90
90
|
# If all of the cards are the same suite, we have a flush
|
91
91
|
return nil unless self.suites.length == 1
|
92
92
|
self.cards.sort.reverse
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
def full_house
|
96
|
-
|
97
|
-
nil
|
96
|
+
dupes = self.duplicates
|
97
|
+
return nil unless dupes.length == 2
|
98
|
+
|
99
|
+
a = []
|
100
|
+
b = []
|
101
|
+
|
102
|
+
hand = self.cards.select do |card|
|
103
|
+
if dupes.first == card.value
|
104
|
+
a << card
|
105
|
+
elsif dupes.last == card.value
|
106
|
+
b << card
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
return nil unless a.length + b.length == 5
|
111
|
+
self.cards.sort.reverse
|
98
112
|
end
|
99
|
-
|
113
|
+
|
100
114
|
def four_of_a_kind
|
101
|
-
|
102
|
-
nil
|
115
|
+
self.kinds(4)
|
103
116
|
end
|
104
|
-
|
117
|
+
|
105
118
|
def straight_flush
|
106
|
-
|
107
|
-
|
119
|
+
return nil unless self.flush
|
120
|
+
self.straight
|
108
121
|
end
|
109
|
-
|
122
|
+
|
110
123
|
protected
|
111
124
|
|
112
125
|
def hand_index
|
@@ -132,5 +145,20 @@ module Hands
|
|
132
145
|
hand << (self.cards - hand).sort.reverse
|
133
146
|
hand.flatten
|
134
147
|
end
|
148
|
+
|
149
|
+
def kinds(num)
|
150
|
+
dupes = self.duplicates
|
151
|
+
return nil unless dupes.length == 1
|
152
|
+
|
153
|
+
hand = self.cards.select do |card|
|
154
|
+
dupes.include?(card.value)
|
155
|
+
end
|
156
|
+
|
157
|
+
return nil unless hand.length == num
|
158
|
+
|
159
|
+
hand = hand.sort.reverse
|
160
|
+
hand << (self.cards - hand).sort.reverse
|
161
|
+
hand.flatten
|
162
|
+
end
|
135
163
|
end
|
136
164
|
end
|
data/lib/hands/version.rb
CHANGED
data/spec/models/card_spec.rb
CHANGED
@@ -5,40 +5,45 @@ describe Hands::Card do
|
|
5
5
|
card = Hands::Card.new
|
6
6
|
card.is_valid?.should eq(false)
|
7
7
|
card.is_invalid?.should eq(true)
|
8
|
-
|
8
|
+
|
9
9
|
card.suite = :hearts
|
10
10
|
card.is_valid?.should eq(false)
|
11
|
-
|
11
|
+
|
12
12
|
card.value = 9
|
13
13
|
card.is_valid?.should eq(true)
|
14
|
-
|
14
|
+
|
15
15
|
card.suite = 17
|
16
16
|
card.is_valid?.should eq(false)
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
it 'should allow for integers instead of characters for high cards' do
|
20
20
|
card1 = Hands::Card.new(:value => 11, :suite => :clubs)
|
21
|
-
|
22
21
|
card1.is_valid?.should eq(true)
|
23
22
|
card1.value.should eq('j')
|
24
|
-
|
23
|
+
|
25
24
|
card2 = Hands::Card.new(:value => 'j', :suite => :clubs)
|
26
25
|
card2.should eq(card1)
|
27
26
|
end
|
28
|
-
|
27
|
+
|
28
|
+
it 'should not allow invalid values' do
|
29
|
+
card = Hands::Card.new
|
30
|
+
card.value = 'p'
|
31
|
+
card.value.should eql(nil)
|
32
|
+
end
|
33
|
+
|
29
34
|
it 'should be comparable' do
|
30
35
|
card1 = Hands::Card.new(:value => 2, :suite => :hearts)
|
31
36
|
card2 = Hands::Card.new(:value => 3, :suite => :clubs)
|
32
|
-
|
37
|
+
|
33
38
|
(card2 > card1).should eq(true)
|
34
39
|
(card1 < card2).should eq(true)
|
35
|
-
|
40
|
+
|
36
41
|
card1.value = 3
|
37
42
|
(card1 == card2).should eq(true)
|
38
43
|
(card1.<=>(card2, true)).should eq(1)
|
39
44
|
(card2.<=>(card1, true)).should eq(-1)
|
40
45
|
end
|
41
|
-
|
46
|
+
|
42
47
|
it 'should be sortable' do
|
43
48
|
c2 = Hands::Card.new(:value => 2, :suite => :hearts)
|
44
49
|
c3 = Hands::Card.new(:value => 3, :suite => :hearts)
|
@@ -53,8 +58,17 @@ describe Hands::Card do
|
|
53
58
|
cQ = Hands::Card.new(:value => 'q', :suite => :hearts)
|
54
59
|
cK = Hands::Card.new(:value => 'k', :suite => :hearts)
|
55
60
|
cA = Hands::Card.new(:value => 'a', :suite => :hearts)
|
56
|
-
|
61
|
+
|
57
62
|
cards = [c2, c3, c4, c5, c6, c7, c8, c9, c10, cJ, cQ, cK, cA]
|
58
63
|
cards.sort.should eq(cards)
|
59
64
|
end
|
65
|
+
|
66
|
+
it 'should include description in inspect' do
|
67
|
+
card = Hands::Card[2, :hearts]
|
68
|
+
card.inspect.include?('Two of Hearts').should eql(true)
|
69
|
+
|
70
|
+
card = Hands::Card.new
|
71
|
+
card.description.should eql('invalid')
|
72
|
+
card.inspect.include?('invalid').should eql(false)
|
73
|
+
end
|
60
74
|
end
|
data/spec/models/hand_spec.rb
CHANGED
@@ -5,7 +5,7 @@ describe Hands::Hand do
|
|
5
5
|
pair = Hands::Hand.new
|
6
6
|
pair << Hands::Card[2, :hearts]
|
7
7
|
pair << Hands::Card[2, :clubs]
|
8
|
-
|
8
|
+
|
9
9
|
flush = Hands::Hand.new
|
10
10
|
flush << Hands::Card[6, :hearts]
|
11
11
|
flush << Hands::Card[7, :hearts]
|
@@ -14,24 +14,24 @@ describe Hands::Hand do
|
|
14
14
|
flush << Hands::Card[4, :hearts]
|
15
15
|
(flush > pair).should eq(true)
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
it 'should order same types of hands' do
|
19
19
|
small_pair = Hands::Hand.new
|
20
20
|
small_pair << Hands::Card[2, :hearts]
|
21
21
|
small_pair << Hands::Card[2, :clubs]
|
22
|
-
|
22
|
+
|
23
23
|
large_pair = Hands::Hand.new
|
24
24
|
large_pair << Hands::Card['A', :hearts]
|
25
25
|
large_pair << Hands::Card['A', :clubs]
|
26
26
|
(large_pair > small_pair).should eq(true)
|
27
|
-
|
27
|
+
|
28
28
|
small_kicker = Hands::Hand.new
|
29
29
|
small_kicker << Hands::Card['A', :spades]
|
30
30
|
small_kicker << Hands::Card['A', :diamonds]
|
31
31
|
small_kicker << Hands::Card[2, :diamonds]
|
32
32
|
small_kicker << Hands::Card[3, :diamonds]
|
33
33
|
small_kicker << Hands::Card[4, :diamonds]
|
34
|
-
|
34
|
+
|
35
35
|
big_kicker = Hands::Hand.new
|
36
36
|
big_kicker << Hands::Card['A', :hearts]
|
37
37
|
big_kicker << Hands::Card['A', :clubs]
|
@@ -40,17 +40,17 @@ describe Hands::Hand do
|
|
40
40
|
big_kicker << Hands::Card[7, :diamonds]
|
41
41
|
(big_kicker > small_kicker).should eq(true)
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
it 'should collect suites' do
|
45
45
|
hand = Hands::Hand.new
|
46
46
|
hand << Hands::Card[2, :hearts]
|
47
47
|
hand << Hands::Card[2, :clubs]
|
48
48
|
hand.suites.should eq([:hearts, :clubs])
|
49
|
-
|
49
|
+
|
50
50
|
hand << Hands::Card[3, :clubs]
|
51
51
|
hand.suites.should eq([:hearts, :clubs])
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
it 'should recognize high card' do
|
55
55
|
hand = Hands::Hand.new
|
56
56
|
hand << Hands::Card[2, :hearts]
|
@@ -62,7 +62,7 @@ describe Hands::Hand do
|
|
62
62
|
hand.pair.should eql(nil)
|
63
63
|
hand.two_pair.should eql(nil)
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
it 'should recognize a pair' do
|
67
67
|
hand = Hands::Hand.new
|
68
68
|
hand << Hands::Card[9, :hearts]
|
@@ -73,7 +73,7 @@ describe Hands::Hand do
|
|
73
73
|
hand.pair.collect(&:value).should eq([9, 9, 7, 4, 2])
|
74
74
|
hand.two_pair.should eql(nil)
|
75
75
|
end
|
76
|
-
|
76
|
+
|
77
77
|
it 'should recognize two pair' do
|
78
78
|
hand = Hands::Hand.new
|
79
79
|
hand << Hands::Card[7, :hearts]
|
@@ -84,9 +84,17 @@ describe Hands::Hand do
|
|
84
84
|
hand.two_pair.collect(&:value).should eq([9, 9, 7, 7, 4])
|
85
85
|
hand.two_pair.should eql(hand.pair)
|
86
86
|
end
|
87
|
-
|
88
|
-
it 'should recognize three of a kind'
|
89
|
-
|
87
|
+
|
88
|
+
it 'should recognize three of a kind' do
|
89
|
+
hand = Hands::Hand.new
|
90
|
+
hand << Hands::Card[7, :hearts]
|
91
|
+
hand << Hands::Card[7, :spades]
|
92
|
+
hand << Hands::Card[7, :diamonds]
|
93
|
+
hand << Hands::Card[3, :hearts]
|
94
|
+
hand << Hands::Card[9, :clubs]
|
95
|
+
hand.best_hand[:type].should eq('three_of_a_kind')
|
96
|
+
end
|
97
|
+
|
90
98
|
it 'should recognize a straight' do
|
91
99
|
hand1 = Hands::Hand.new
|
92
100
|
hand1 << Hands::Card[2, :hearts]
|
@@ -95,7 +103,7 @@ describe Hands::Hand do
|
|
95
103
|
hand1 << Hands::Card[5, :hearts]
|
96
104
|
hand1 << Hands::Card[6, :clubs]
|
97
105
|
hand1.best_hand[:type].should eq('straight')
|
98
|
-
|
106
|
+
|
99
107
|
hand2 = Hands::Hand.new
|
100
108
|
hand2 << Hands::Card['A', :hearts]
|
101
109
|
hand2 << Hands::Card[2, :spades]
|
@@ -103,7 +111,7 @@ describe Hands::Hand do
|
|
103
111
|
hand2 << Hands::Card[4, :hearts]
|
104
112
|
hand2 << Hands::Card[5, :clubs]
|
105
113
|
hand2.best_hand[:type].should eq('straight')
|
106
|
-
|
114
|
+
|
107
115
|
hand3 = Hands::Hand.new
|
108
116
|
hand3 << Hands::Card[10, :hearts]
|
109
117
|
hand3 << Hands::Card['J', :spades]
|
@@ -111,7 +119,7 @@ describe Hands::Hand do
|
|
111
119
|
hand3 << Hands::Card['K', :hearts]
|
112
120
|
hand3 << Hands::Card['A', :clubs]
|
113
121
|
hand3.best_hand[:type].should eq('straight')
|
114
|
-
|
122
|
+
|
115
123
|
hand4 = Hands::Hand.new
|
116
124
|
hand4 << Hands::Card['J', :spades]
|
117
125
|
hand4 << Hands::Card['Q', :diamonds]
|
@@ -120,7 +128,7 @@ describe Hands::Hand do
|
|
120
128
|
hand4 << Hands::Card[2, :hearts]
|
121
129
|
hand4.best_hand[:type].should eq('high_card')
|
122
130
|
end
|
123
|
-
|
131
|
+
|
124
132
|
it 'should recognize a flush' do
|
125
133
|
hand = Hands::Hand.new
|
126
134
|
hand << Hands::Card[6, :hearts]
|
@@ -130,11 +138,37 @@ describe Hands::Hand do
|
|
130
138
|
hand << Hands::Card[4, :hearts]
|
131
139
|
hand.best_hand[:type].should eq('flush')
|
132
140
|
end
|
133
|
-
|
134
|
-
it 'should recognize a full house'
|
135
|
-
|
136
|
-
|
137
|
-
|
141
|
+
|
142
|
+
it 'should recognize a full house' do
|
143
|
+
hand = Hands::Hand.new
|
144
|
+
hand << Hands::Card[7, :hearts]
|
145
|
+
hand << Hands::Card[7, :spades]
|
146
|
+
hand << Hands::Card[7, :diamonds]
|
147
|
+
hand << Hands::Card[9, :spades]
|
148
|
+
hand << Hands::Card[9, :clubs]
|
149
|
+
hand.best_hand[:type].should eq('full_house')
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'should recognize four of a kind' do
|
153
|
+
hand = Hands::Hand.new
|
154
|
+
hand << Hands::Card[7, :hearts]
|
155
|
+
hand << Hands::Card[7, :spades]
|
156
|
+
hand << Hands::Card[7, :diamonds]
|
157
|
+
hand << Hands::Card[7, :clubs]
|
158
|
+
hand << Hands::Card[9, :clubs]
|
159
|
+
hand.best_hand[:type].should eq('four_of_a_kind')
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should recognize a straight flush' do
|
163
|
+
hand = Hands::Hand.new
|
164
|
+
hand << Hands::Card[2, :hearts]
|
165
|
+
hand << Hands::Card[3, :hearts]
|
166
|
+
hand << Hands::Card[4, :hearts]
|
167
|
+
hand << Hands::Card[5, :hearts]
|
168
|
+
hand << Hands::Card[6, :hearts]
|
169
|
+
hand.best_hand[:type].should eq('straight_flush')
|
170
|
+
end
|
171
|
+
|
138
172
|
it 'should recognize the best hand' do
|
139
173
|
hand = Hands::Hand.new
|
140
174
|
hand << Hands::Card[7, :hearts]
|
data/spec/spec_helper.rb
CHANGED