hands 0.2.1 → 0.3.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 +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +4 -0
- data/Contributing.markdown +19 -0
- data/Gemfile +8 -5
- data/Rakefile +1 -1
- data/Readme.markdown +4 -14
- data/hands.gemspec +3 -0
- data/lib/hands.rb +10 -1
- data/lib/hands/card.rb +26 -9
- data/lib/hands/hand_detection.rb +28 -38
- data/lib/hands/version.rb +1 -1
- data/test/test_helper.rb +9 -3
- data/test/units/card_test.rb +39 -23
- metadata +11 -17
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c2a3b037d84f5c0fbecc3d0d2d7b5828c0aeb00f
|
4
|
+
data.tar.gz: 6f697d707fafae24181d8fc5f0fdc8e69634ca91
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ef5243a890cfb119b0aed00020f7b335778bbfd3e96e2465cbccc5319927e46ce4ff7acd1752a3f5ad2ec0db2f769c1e87dbbf659c5acc071c8046fa2324aa31
|
7
|
+
data.tar.gz: 0878f55fddf5c7ec70b03106327c961808e46de9104143e272469697ab8d81822db7876234f0fb74903ecda591ea67b1a3426033511a8aa9600a2a126523f33b
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
## Submitting a Pull Request
|
2
|
+
|
3
|
+
1. [Fork the repository.][fork]
|
4
|
+
2. [Create a topic branch.][branch]
|
5
|
+
3. Add tests for your unimplemented feature or bug fix.
|
6
|
+
4. Run `bundle exec rake`. If your tests pass, return to step 3.
|
7
|
+
5. Implement your feature or bug fix.
|
8
|
+
6. Run `bundle exec rake`. If your tests fail, return to step 5.
|
9
|
+
7. Run `open coverage/index.html`. If your changes are not completely covered
|
10
|
+
by your tests, return to step 3.
|
11
|
+
8. Add documentation for your feature or bug fix.
|
12
|
+
9. Run `bundle exec rake doc`. If your changes are not 100% documented, go
|
13
|
+
back to step 8.
|
14
|
+
10. Add, commit, and push your changes.
|
15
|
+
11. [Submit a pull request.][pr]
|
16
|
+
|
17
|
+
[fork]: http://help.github.com/fork-a-repo/
|
18
|
+
[branch]: http://learn.github.com/p/branching.html
|
19
|
+
[pr]: http://help.github.com/send-pull-requests/
|
data/Gemfile
CHANGED
@@ -3,14 +3,17 @@ source 'https://rubygems.org'
|
|
3
3
|
gemspec
|
4
4
|
|
5
5
|
# Utility
|
6
|
-
gem 'rake'
|
6
|
+
gem 'rake', :group => [:development, :test]
|
7
7
|
|
8
8
|
# Documentation
|
9
|
-
|
10
|
-
gem '
|
9
|
+
group :development do
|
10
|
+
gem 'yard'
|
11
|
+
gem 'redcarpet', :platform => :ruby
|
12
|
+
end
|
11
13
|
|
14
|
+
# Testing
|
12
15
|
group :test do
|
13
16
|
gem 'minitest'
|
14
|
-
gem 'minitest-wscolor'
|
15
|
-
gem 'simplecov'
|
17
|
+
gem 'minitest-wscolor' if RUBY_VERSION >= '1.9.3'
|
18
|
+
gem 'simplecov', :require => false
|
16
19
|
end
|
data/Rakefile
CHANGED
data/Readme.markdown
CHANGED
@@ -4,8 +4,6 @@ Simple library for calculating poker hands.
|
|
4
4
|
|
5
5
|
Currently this gem is very limited. I plan on adding outs, odds, and other actually useful stuff. I started writing this on a plane as a personal challenge. It's current state is crude, although tested and works.
|
6
6
|
|
7
|
-
[](undefined) [](https://gemnasium.com/soffes/hands) [](https://codeclimate.com/github/soffes/hands)
|
8
|
-
|
9
7
|
## Installation
|
10
8
|
|
11
9
|
Add this line to your application's Gemfile:
|
@@ -58,20 +56,12 @@ card2 = Hands::Card.new(:value => 3, :suit => :clubs)
|
|
58
56
|
card2 > card1 # true
|
59
57
|
```
|
60
58
|
|
61
|
-
##
|
59
|
+
## Supported Ruby Versions
|
62
60
|
|
63
|
-
|
61
|
+
Hands is tested under 1.9.3, 2.0.0, and JRuby (1.9 mode).
|
64
62
|
|
65
|
-
|
66
|
-
$ bundle exec rake
|
67
|
-
```
|
63
|
+
[](https://travis-ci.org/soffes/hands)
|
68
64
|
|
69
65
|
## Contributing
|
70
66
|
|
71
|
-
|
72
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
73
|
-
3. Write passing specs
|
74
|
-
4. Write documentation
|
75
|
-
5. Commit your changes (`git commit -am 'Added some feature'`)
|
76
|
-
6. Push to the branch (`git push origin my-new-feature`)
|
77
|
-
7. Create new Pull Request
|
67
|
+
See the [contributing guide](Contributing.markdown).
|
data/hands.gemspec
CHANGED
@@ -7,6 +7,7 @@ Gem::Specification.new do |gem|
|
|
7
7
|
gem.description = 'Simple library for various poker hands calculations.'
|
8
8
|
gem.summary = 'Simple library for various poker hands calculations.'
|
9
9
|
gem.homepage = 'http://github.com/soffes/hands'
|
10
|
+
gem.license = 'MIT'
|
10
11
|
|
11
12
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
12
13
|
gem.files = `git ls-files`.split("\n")
|
@@ -14,4 +15,6 @@ Gem::Specification.new do |gem|
|
|
14
15
|
gem.name = 'hands'
|
15
16
|
gem.require_paths = ['lib']
|
16
17
|
gem.version = Hands::VERSION
|
18
|
+
|
19
|
+
gem.required_ruby_version = '>= 1.9.2'
|
17
20
|
end
|
data/lib/hands.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
1
3
|
require 'hands/version'
|
2
4
|
require 'hands/card'
|
3
5
|
require 'hands/hand'
|
@@ -13,12 +15,19 @@ module Hands
|
|
13
15
|
# All card value descriptions
|
14
16
|
VALUE_DESCRIPTIONS = %w{two three four five six seven eight nine ten jack queen king ace}
|
15
17
|
|
16
|
-
#
|
18
|
+
# Alphabetically ordered suits (higher index in the array is higher value)
|
17
19
|
SUITS = [:clubs, :diamonds, :hearts, :spades]
|
20
|
+
SUIT_CHARACTERS = %w{♣ ♦ ♥ ♠}
|
18
21
|
|
19
22
|
# Ranks of poker hands
|
20
23
|
HAND_ORDER = [
|
21
24
|
:high_card, :pair, :two_pair, :three_of_a_kind, :straight, :flush, :full_house,
|
22
25
|
:four_of_a_kind, :straight_flush, :royal_flush
|
23
26
|
]
|
27
|
+
|
28
|
+
# Raised when an invalid suit is used
|
29
|
+
class InvalidSuit < StandardError; end
|
30
|
+
|
31
|
+
# Raised when an invalid value is used
|
32
|
+
class InvalidValue < StandardError; end
|
24
33
|
end
|
data/lib/hands/card.rb
CHANGED
@@ -65,14 +65,20 @@ module Hands
|
|
65
65
|
|
66
66
|
# Invalid
|
67
67
|
@value = nil
|
68
|
+
raise InvalidValue, "'#{val}' is an invalid suit."
|
68
69
|
end
|
69
70
|
|
70
71
|
def suit=(suit)
|
71
|
-
|
72
|
-
|
73
|
-
|
72
|
+
# Convert to symbol
|
73
|
+
suit = suit.to_sym if suit.is_a?(String)
|
74
|
+
|
75
|
+
# Make sure it's valid
|
76
|
+
unless suit.is_a?(Symbol) and SUITS.include?(suit)
|
74
77
|
@suit = nil
|
78
|
+
raise InvalidSuit, "'#{suit}' is an invalid suit."
|
75
79
|
end
|
80
|
+
|
81
|
+
@suit = suit
|
76
82
|
end
|
77
83
|
|
78
84
|
# Standard inspect
|
@@ -96,15 +102,24 @@ module Hands
|
|
96
102
|
!self.is_valid?
|
97
103
|
end
|
98
104
|
|
105
|
+
# Get a short string representation of the card
|
106
|
+
#
|
107
|
+
# Example: "♥2"
|
108
|
+
#
|
109
|
+
# @return [String] short string representation of the card
|
110
|
+
def description
|
111
|
+
return 'invalid' unless self.is_valid?
|
112
|
+
self.value.capitalize + SUIT_CHARACTERS[self.suit_index]
|
113
|
+
end
|
114
|
+
|
99
115
|
# Get a string representation of the card
|
100
116
|
#
|
117
|
+
# Example: "Two of Hearts"
|
118
|
+
#
|
101
119
|
# @return [String] string representation of the card
|
102
|
-
def
|
103
|
-
|
104
|
-
|
105
|
-
else
|
106
|
-
'invalid'
|
107
|
-
end
|
120
|
+
def long_description
|
121
|
+
return 'invalid' unless self.is_valid?
|
122
|
+
"#{VALUE_DESCRIPTIONS[self.value_index].capitalize} of #{self.suit.to_s.capitalize}"
|
108
123
|
end
|
109
124
|
|
110
125
|
# Compares the card with another card
|
@@ -129,6 +144,7 @@ module Hands
|
|
129
144
|
# @return [Integer] index of the card's suit
|
130
145
|
# @see SUITS
|
131
146
|
def suit_index
|
147
|
+
return nil unless self.suit
|
132
148
|
SUITS.index(self.suit.downcase)
|
133
149
|
end
|
134
150
|
|
@@ -139,6 +155,7 @@ module Hands
|
|
139
155
|
# @return [Integer] index of the card's value
|
140
156
|
# @see VALUES
|
141
157
|
def value_index
|
158
|
+
return nil unless self.value
|
142
159
|
VALUES.index(self.value.downcase)
|
143
160
|
end
|
144
161
|
end
|
data/lib/hands/hand_detection.rb
CHANGED
@@ -35,60 +35,42 @@ module Hands
|
|
35
35
|
|
36
36
|
# @return [Array, Nil] Array of {Card} objects with the straight in decending order or `nil` if there isn't a straight in the {Hand}
|
37
37
|
def straight
|
38
|
-
|
38
|
+
# Require at least 5 cards
|
39
|
+
return nil unless self.cards.length >= 5
|
40
|
+
|
41
|
+
# Sort
|
39
42
|
cs = self.cards.sort.reverse
|
40
43
|
|
41
44
|
# Ace's low
|
42
|
-
if cs.first.value == 'a' and cs[1].value == '5'
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
next if i == 0
|
52
|
-
return nil unless csr[i].value_index == i - 1
|
53
|
-
end
|
54
|
-
|
55
|
-
# Normal
|
56
|
-
else
|
57
|
-
# Check range
|
58
|
-
return nil unless cs.first.value_index - cs.last.value_index == 4
|
59
|
-
|
60
|
-
# Check succession
|
61
|
-
4.times do |i|
|
62
|
-
return nil unless cs[i].value_index == cs[i + 1].value_index + 1
|
63
|
-
end
|
64
|
-
end
|
45
|
+
return cs if cs.first.value == 'a' and cs[1].value == '5'
|
46
|
+
|
47
|
+
# Check succession
|
48
|
+
return nil unless succession?
|
49
|
+
|
50
|
+
# Avoid wrap-around
|
51
|
+
values = self.cards.collect(&:value)
|
52
|
+
return nil if values.include?('k') and values.include?(2)
|
53
|
+
|
65
54
|
cs
|
66
55
|
end
|
67
56
|
|
68
57
|
# @return [Array, Nil] Array of {Card} objects with the flush in decending order or `nil` if there isn't a flush in the {Hand}
|
69
58
|
def flush
|
70
59
|
# If all of the {Card}s are the same suit, we have a flush
|
71
|
-
return nil unless self.suits.length == 1
|
60
|
+
return nil unless self.cards.length >= 5 and self.suits.length == 1
|
72
61
|
self.cards.sort.reverse
|
73
62
|
end
|
74
63
|
|
75
64
|
# @return [Array, Nil] Array of {Card} objects with the full house in decending order or `nil` if there isn't a full house in the {Hand}
|
76
65
|
def full_house
|
77
66
|
dupes = self.duplicates
|
78
|
-
return nil unless dupes.length == 2
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
hand = self.cards.select do |card|
|
84
|
-
if dupes.first == card.value
|
85
|
-
a << card
|
86
|
-
elsif dupes.last == card.value
|
87
|
-
b << card
|
88
|
-
end
|
67
|
+
return nil unless self.cards.length >= 5 and dupes.length == 2
|
68
|
+
|
69
|
+
# Ensure all {Card}s are one of the duplicates
|
70
|
+
self.cards.each do |card|
|
71
|
+
return nil unless dupes.include? card.value
|
89
72
|
end
|
90
73
|
|
91
|
-
return nil unless a.length + b.length == 5
|
92
74
|
self.cards.sort.reverse
|
93
75
|
end
|
94
76
|
|
@@ -136,7 +118,7 @@ module Hands
|
|
136
118
|
|
137
119
|
def pairs(min)
|
138
120
|
dupes = self.duplicates
|
139
|
-
return nil
|
121
|
+
return nil unless dupes.length >= min
|
140
122
|
|
141
123
|
hand = self.cards.select do |card|
|
142
124
|
dupes.include?(card.value)
|
@@ -161,5 +143,13 @@ module Hands
|
|
161
143
|
hand << (self.cards - hand).sort.reverse
|
162
144
|
hand.flatten
|
163
145
|
end
|
146
|
+
|
147
|
+
def succession?
|
148
|
+
cs = self.cards.sort.reverse
|
149
|
+
4.times do |i|
|
150
|
+
return false unless cs[i].value_index == cs[i + 1].value_index + 1
|
151
|
+
end
|
152
|
+
true
|
153
|
+
end
|
164
154
|
end
|
165
155
|
end
|
data/lib/hands/version.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -1,11 +1,17 @@
|
|
1
|
-
require 'simplecov'
|
2
|
-
SimpleCov.start
|
3
|
-
|
4
1
|
require 'rubygems'
|
5
2
|
require 'bundler'
|
6
3
|
Bundler.require :test
|
4
|
+
|
5
|
+
require 'simplecov'
|
6
|
+
SimpleCov.start
|
7
|
+
|
7
8
|
require 'minitest/autorun'
|
8
9
|
require 'hands'
|
9
10
|
|
11
|
+
# Support files
|
12
|
+
Dir["#{File.expand_path(File.dirname(__FILE__))}/support/*.rb"].each do |file|
|
13
|
+
require file
|
14
|
+
end
|
15
|
+
|
10
16
|
class Hands::TestCase < MiniTest::Unit::TestCase
|
11
17
|
end
|
data/test/units/card_test.rb
CHANGED
@@ -1,6 +1,13 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
require 'test_helper'
|
2
3
|
|
3
4
|
class CardTest < Hands::TestCase
|
5
|
+
def test_shorthand
|
6
|
+
card1 = Hands::Card[4, :hearts]
|
7
|
+
card2 = Hands::Card.new(:value => 4, :suit => :hearts)
|
8
|
+
assert_equal card1, card2
|
9
|
+
end
|
10
|
+
|
4
11
|
def test_that_it_validates_cards
|
5
12
|
card = Hands::Card.new
|
6
13
|
refute card.is_valid?
|
@@ -12,26 +19,31 @@ class CardTest < Hands::TestCase
|
|
12
19
|
card.value = 9
|
13
20
|
assert card.is_valid?
|
14
21
|
|
15
|
-
|
16
|
-
|
22
|
+
assert_raises Hands::InvalidSuit do
|
23
|
+
card.suit = 17
|
24
|
+
end
|
25
|
+
|
26
|
+
assert_raises Hands::InvalidValue do
|
27
|
+
card.value = 19
|
28
|
+
end
|
17
29
|
|
18
30
|
card.suit = :hearts
|
19
|
-
card.value =
|
20
|
-
|
31
|
+
card.value = 5
|
32
|
+
assert card.is_valid?
|
21
33
|
end
|
22
34
|
|
23
35
|
def test_that_it_allows_integers_for_high_cards
|
24
|
-
card1 = Hands::Card
|
36
|
+
card1 = Hands::Card[11, :clubs]
|
25
37
|
assert card1.is_valid?
|
26
38
|
assert_equal 'j', card1.value
|
27
39
|
|
28
|
-
card2 = Hands::Card
|
40
|
+
card2 = Hands::Card['j', :clubs]
|
29
41
|
assert_equal card1, card2
|
30
42
|
end
|
31
43
|
|
32
44
|
def test_that_its_comparable
|
33
|
-
card1 = Hands::Card
|
34
|
-
card2 = Hands::Card
|
45
|
+
card1 = Hands::Card[2, :hearts]
|
46
|
+
card2 = Hands::Card[3, :clubs]
|
35
47
|
|
36
48
|
assert card2 > card1
|
37
49
|
assert card1 < card2
|
@@ -43,30 +55,34 @@ class CardTest < Hands::TestCase
|
|
43
55
|
end
|
44
56
|
|
45
57
|
def test_that_it_is_sortable
|
46
|
-
c2 = Hands::Card
|
47
|
-
c3 = Hands::Card
|
48
|
-
c4 = Hands::Card
|
49
|
-
c5 = Hands::Card
|
50
|
-
c6 = Hands::Card
|
51
|
-
c7 = Hands::Card
|
52
|
-
c8 = Hands::Card
|
53
|
-
c9 = Hands::Card
|
54
|
-
c10 = Hands::Card
|
55
|
-
cJ = Hands::Card
|
56
|
-
cQ = Hands::Card
|
57
|
-
cK = Hands::Card
|
58
|
-
cA = Hands::Card
|
58
|
+
c2 = Hands::Card[2, :hearts]
|
59
|
+
c3 = Hands::Card[3, :hearts]
|
60
|
+
c4 = Hands::Card[4, :hearts]
|
61
|
+
c5 = Hands::Card[5, :hearts]
|
62
|
+
c6 = Hands::Card[6, :hearts]
|
63
|
+
c7 = Hands::Card[7, :hearts]
|
64
|
+
c8 = Hands::Card[8, :hearts]
|
65
|
+
c9 = Hands::Card[9, :hearts]
|
66
|
+
c10 = Hands::Card[10, :hearts]
|
67
|
+
cJ = Hands::Card['j', :hearts]
|
68
|
+
cQ = Hands::Card['q', :hearts]
|
69
|
+
cK = Hands::Card['k', :hearts]
|
70
|
+
cA = Hands::Card['a', :hearts]
|
59
71
|
|
60
72
|
cards = [c2, c3, c4, c5, c6, c7, c8, c9, c10, cJ, cQ, cK, cA]
|
61
73
|
assert_equal cards, cards.sort
|
62
74
|
end
|
63
75
|
|
64
76
|
def test_that_it_includes_the_description_in_inspect
|
65
|
-
card = Hands::Card
|
66
|
-
|
77
|
+
card = Hands::Card[2, :hearts]
|
78
|
+
assert_equal '2♥', card.description
|
79
|
+
assert_includes card.inspect, '2♥'
|
80
|
+
assert_equal 'Two of Hearts', card.long_description
|
67
81
|
|
68
82
|
card = Hands::Card.new
|
69
83
|
assert_equal 'invalid', card.description
|
84
|
+
assert_equal 'invalid', card.description
|
70
85
|
refute_includes card.inspect, 'invalid'
|
86
|
+
assert_equal 'invalid', card.description
|
71
87
|
end
|
72
88
|
end
|
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hands
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.3.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Sam Soffes
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-02-25 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
13
|
description: Simple library for various poker hands calculations.
|
15
14
|
email:
|
@@ -21,6 +20,7 @@ files:
|
|
21
20
|
- .gitignore
|
22
21
|
- .travis.yml
|
23
22
|
- .yardopts
|
23
|
+
- Contributing.markdown
|
24
24
|
- Gemfile
|
25
25
|
- LICENSE
|
26
26
|
- Rakefile
|
@@ -43,34 +43,28 @@ files:
|
|
43
43
|
- test/units/player_test.rb
|
44
44
|
- test/units/table_test.rb
|
45
45
|
homepage: http://github.com/soffes/hands
|
46
|
-
licenses:
|
46
|
+
licenses:
|
47
|
+
- MIT
|
48
|
+
metadata: {}
|
47
49
|
post_install_message:
|
48
50
|
rdoc_options: []
|
49
51
|
require_paths:
|
50
52
|
- lib
|
51
53
|
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
-
none: false
|
53
54
|
requirements:
|
54
|
-
- -
|
55
|
+
- - '>='
|
55
56
|
- !ruby/object:Gem::Version
|
56
|
-
version:
|
57
|
-
segments:
|
58
|
-
- 0
|
59
|
-
hash: 2894117233871191635
|
57
|
+
version: 1.9.2
|
60
58
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
-
none: false
|
62
59
|
requirements:
|
63
|
-
- -
|
60
|
+
- - '>='
|
64
61
|
- !ruby/object:Gem::Version
|
65
62
|
version: '0'
|
66
|
-
segments:
|
67
|
-
- 0
|
68
|
-
hash: 2894117233871191635
|
69
63
|
requirements: []
|
70
64
|
rubyforge_project:
|
71
|
-
rubygems_version:
|
65
|
+
rubygems_version: 2.0.0
|
72
66
|
signing_key:
|
73
|
-
specification_version:
|
67
|
+
specification_version: 4
|
74
68
|
summary: Simple library for various poker hands calculations.
|
75
69
|
test_files:
|
76
70
|
- test/test_helper.rb
|