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 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
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .ruby-version
data/.travis.yml CHANGED
@@ -1,3 +1,7 @@
1
1
  language: ruby
2
+ bundler_args: --without development
2
3
  rvm:
4
+ - 1.8.7
3
5
  - 1.9.3
6
+ - 2.0.0
7
+ - jruby-19mode
@@ -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
- gem 'yard'
10
- gem 'redcarpet'
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
@@ -5,7 +5,7 @@ Rake::TestTask.new(:test) do |t|
5
5
  t.libs << 'test'
6
6
  t.pattern = 'test/**/*_test.rb'
7
7
  end
8
- task default: :test
8
+ task :default => :test
9
9
 
10
10
  task :coverage do
11
11
  `open coverage/index.html`
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
- ## Running Tests
59
+ ## Supported Ruby Versions
62
60
 
63
- Running and reading the tests is (for now) the best way to see the functionality of this gem.
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
- 1. Fork it
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
- # Reverse alphabetically ordered suits
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
- if (suit.is_a?(String) or suit.is_a?(Symbol)) and SUITS.include?(suit.to_sym)
72
- @suit = suit.to_sym
73
- else
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 description
103
- if self.is_valid?
104
- "#{VALUE_DESCRIPTIONS[self.value_index].capitalize} of #{self.suit.to_s.capitalize}"
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
@@ -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
- return nil unless self.cards.length == 5
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
- # Move ace to end
44
- ace = cs.first
45
- cs = cs[1..4]
46
- cs << ace
47
-
48
- # Check succession
49
- csr = cs.reverse
50
- 4.times do |i|
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
- a = []
81
- b = []
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 if dupes.length < min
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
@@ -1,4 +1,4 @@
1
1
  module Hands
2
2
  # Gem version
3
- VERSION = '0.2.1'
3
+ VERSION = '0.3.0'
4
4
  end
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
@@ -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
- card.suit = 17
16
- refute card.is_valid?
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 = 19
20
- refute card.is_valid?
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.new(value: 11, suit: :clubs)
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.new(value: 'j', suit: :clubs)
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.new(value: 2, suit: :hearts)
34
- card2 = Hands::Card.new(value: 3, suit: :clubs)
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.new(value: 2, suit: :hearts)
47
- c3 = Hands::Card.new(value: 3, suit: :hearts)
48
- c4 = Hands::Card.new(value: 4, suit: :hearts)
49
- c5 = Hands::Card.new(value: 5, suit: :hearts)
50
- c6 = Hands::Card.new(value: 6, suit: :hearts)
51
- c7 = Hands::Card.new(value: 7, suit: :hearts)
52
- c8 = Hands::Card.new(value: 8, suit: :hearts)
53
- c9 = Hands::Card.new(value: 9, suit: :hearts)
54
- c10 = Hands::Card.new(value: 10, suit: :hearts)
55
- cJ = Hands::Card.new(value: 'j', suit: :hearts)
56
- cQ = Hands::Card.new(value: 'q', suit: :hearts)
57
- cK = Hands::Card.new(value: 'k', suit: :hearts)
58
- cA = Hands::Card.new(value: 'a', suit: :hearts)
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.new(value: 2, suit: :hearts)
66
- assert_includes card.inspect, 'Two of Hearts'
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.2.1
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-01-22 00:00:00.000000000 Z
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: '0'
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: 1.8.23
65
+ rubygems_version: 2.0.0
72
66
  signing_key:
73
- specification_version: 3
67
+ specification_version: 4
74
68
  summary: Simple library for various poker hands calculations.
75
69
  test_files:
76
70
  - test/test_helper.rb