hands 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Build Status](https://travis-ci.org/soffes/hands.png?branch=master)](undefined) [![Dependency Status](https://gemnasium.com/soffes/hands.png)](https://gemnasium.com/soffes/hands) [![Code Climate](https://codeclimate.com/badge.png)](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
|
+
[![Build Status](https://travis-ci.org/soffes/hands.png?branch=master)](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
|