cards_lib 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +14 -0
- data/.rubocop.yml +1156 -0
- data/.travis.yml +8 -3
- data/Gemfile +5 -1
- data/Guardfile +30 -26
- data/README.md +9 -9
- data/cards_lib.gemspec +2 -2
- data/lib/cards_lib.rb +1 -1
- data/lib/cards_lib/card.rb +9 -9
- data/lib/cards_lib/deck.rb +6 -2
- data/lib/cards_lib/is_set.rb +3 -3
- data/lib/cards_lib/ranker.rb +13 -8
- data/lib/cards_lib/refinements.rb +1 -1
- data/lib/cards_lib/standard/evaluators/blackjack_evaluator.rb +3 -5
- data/lib/cards_lib/standard/rankers/blackjack_ranker.rb +0 -1
- data/lib/cards_lib/standard/rules/poker_rule.rb +9 -9
- data/lib/cards_lib/version.rb +1 -1
- metadata +5 -3
data/.travis.yml
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
- 2.2.
|
4
|
-
- 2.3.
|
5
|
-
script: bundle exec rake test
|
3
|
+
- 2.2.6
|
4
|
+
- 2.3.3
|
6
5
|
env:
|
7
6
|
global:
|
8
7
|
secure: kAw1KW3iTB3rqMur/U1RM7C/MTWJx17T6Xyc+NEcrvE0PtYuIAOfZ/Qn262PWEE34OHCdmkhfHbBY1ZbzwaVDg+5LTlnwikLREMYH5ddf+yLE39lZkoALQDQeNwXNdJG/s/tS2I7c+/+vE8Xk5fZJZmNxiZIFPuFseZUvruO8HnvRpLKdlb7HLJAXq1ITRBWYbCe2jkFhgYEQCBqs3gwIPeAoxXAOn3ILUJ3xDxC/G/eSU+GbLTraJIyrhJApsUw4xSWr+fFumYFRK/PnJlcx4FR64D49B2mEdRSmHvZcBPo0KUWwr+1CVhkPtsTgnO8OJsFkq6FYH1aTmP/5W46wnOe8rPHd1GsY6pgXYTiMisTXk5gLUmcdSWriqbIdeTaBdNDKYzejwRwitR9iPSb1iQXjoCRRvcS1G6dHVjrZq9SSkScpSqJAXvAgr2DeCCY9PejaXdVtyTyOvZYH2ql440+DoEkb4nK9mkhy93CmzoIHNFKWYqNKPCTpK2O7YdL9+wPFc8Kmaobu6Iht9hA0uShLooiF0SnnU0twcEWbVepU9tx5pI65DT46M3PGfLO0KQtXUZscytkstdXmwyWwzFPUMW2EXFeXVW3f9o77z5npe/5b6nBeHIrHTNOdw57fMPzKjmsv0v6EbeVL9xajdHkbJ9G9zOSJd0b+PIPfJc=
|
8
|
+
addons:
|
9
|
+
code_climate:
|
10
|
+
repo_token: ecf8c246bcc2fdad42590f78c7b214bc19abf212eee0979427477e9c6a510320
|
11
|
+
script: bundle exec rake test
|
12
|
+
after_success:
|
13
|
+
- bundle exec codeclimate-test-reporter
|
data/Gemfile
CHANGED
@@ -6,7 +6,11 @@ gem "codeclimate-test-reporter", group: :test, require: nil
|
|
6
6
|
group :development do
|
7
7
|
gem "guard"
|
8
8
|
gem "guard-minitest"
|
9
|
+
gem "guard-rubocop"
|
9
10
|
end
|
10
|
-
|
11
|
+
|
12
|
+
if Gem::Dependency.new('', "~> 2.4.0").match?('', RUBY_VERSION)
|
11
13
|
gem "json", git: 'https://github.com/flori/json', branch: 'v1.8'
|
14
|
+
else
|
15
|
+
gem "json"
|
12
16
|
end
|
data/Guardfile
CHANGED
@@ -15,33 +15,37 @@
|
|
15
15
|
#
|
16
16
|
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
18
|
+
group :red_green_refactor, halt_on_fail: true do
|
19
|
+
guard :minitest do
|
20
|
+
# with Minitest::Unit
|
21
|
+
watch(%r{^test/(.*)\/?(.*)_test\.rb$})
|
22
|
+
watch(%r{^lib/cards_lib/([^/]+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
|
23
|
+
watch(%r{^lib/cards_lib/standard/([^/]+)\.rb$}) { |m| "test/standard/#{m[1]}_test.rb" }
|
24
|
+
watch(%r{^lib/cards_lib/standard/evaluators/([^/]+)\.rb$}) { |m| "test/standard/evaluators/#{m[1]}_test.rb" }
|
25
|
+
watch(%r{^lib/cards_lib/standard/rules/([^/]+)\.rb$}) { |m| "test/standard/rules/#{m[1]}_test.rb" }
|
26
|
+
watch(%r{^lib/cards_lib/standard/rankers/([^/]+)\.rb$}) { |m| "test/standard/rankers/#{m[1]}_test.rb" }
|
27
|
+
watch(%r{^test/minitest_helper\.rb$}) { 'test' }
|
28
|
+
watch(%r{^lib/cards_lib/card.rb$}) { 'test' }
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
# with Minitest::Spec
|
31
|
+
# watch(%r{^spec/(.*)_spec\.rb$})
|
32
|
+
# watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
33
|
+
# watch(%r{^spec/spec_helper\.rb$}) { 'spec' }
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
35
|
+
# Rails 4
|
36
|
+
# watch(%r{^app/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
|
37
|
+
# watch(%r{^app/controllers/application_controller\.rb$}) { 'test/controllers' }
|
38
|
+
# watch(%r{^app/controllers/(.+)_controller\.rb$}) { |m| "test/integration/#{m[1]}_test.rb" }
|
39
|
+
# watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" }
|
40
|
+
# watch(%r{^lib/(.+)\.rb$}) { |m| "test/lib/#{m[1]}_test.rb" }
|
41
|
+
# watch(%r{^test/.+_test\.rb$})
|
42
|
+
# watch(%r{^test/test_helper\.rb$}) { 'test' }
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
# Rails < 4
|
45
|
+
# watch(%r{^app/controllers/(.*)\.rb$}) { |m| "test/functional/#{m[1]}_test.rb" }
|
46
|
+
# watch(%r{^app/helpers/(.*)\.rb$}) { |m| "test/helpers/#{m[1]}_test.rb" }
|
47
|
+
# watch(%r{^app/models/(.*)\.rb$}) { |m| "test/unit/#{m[1]}_test.rb" }
|
48
|
+
end
|
49
|
+
|
50
|
+
guard :rubocop, all_on_start: true
|
47
51
|
end
|
data/README.md
CHANGED
@@ -15,7 +15,7 @@ I'm willing to bet you that there is no other Ruby card game library
|
|
15
15
|
out there as easy to use, as well thought out, and as simple to
|
16
16
|
understand as mine. Come on, I dare you to use it and review it! ;-)
|
17
17
|
|
18
|
-
##Scope
|
18
|
+
## Scope
|
19
19
|
|
20
20
|
The scope of this project aims to be a game agnostic card management
|
21
21
|
and evaluation system. Game logic itself will not be provided with
|
@@ -25,14 +25,14 @@ cards is the sole purpose of this gem.
|
|
25
25
|
Feel free to contribute or raise suggestions via the issue tracker.
|
26
26
|
I welcome participation of all kinds! :-)
|
27
27
|
|
28
|
-
##Install
|
28
|
+
## Install
|
29
29
|
|
30
30
|
```
|
31
31
|
gem install 'cards_lib'
|
32
32
|
```
|
33
33
|
Requires Ruby 2 or greater.
|
34
34
|
|
35
|
-
##Usage
|
35
|
+
## Usage
|
36
36
|
|
37
37
|
Create a Card with Card.new(face)
|
38
38
|
|
@@ -64,7 +64,7 @@ CardsLib::IsSet.verify(
|
|
64
64
|
)
|
65
65
|
```
|
66
66
|
|
67
|
-
##Goodies
|
67
|
+
## Goodies
|
68
68
|
|
69
69
|
* **lib/cards_lib/is_set.rb** is a golden tool in card hand verification.
|
70
70
|
|
@@ -74,7 +74,7 @@ CardsLib::IsSet.verify(
|
|
74
74
|
|
75
75
|
* In **lib/cards_lib/standard/evaluators/blackjack_evaluator.rb** there is a Blackjack hand worth evaluation tool. See the **test/standard/evaluators/blackjack_evaluator_test.rb** for examples.
|
76
76
|
|
77
|
-
##Definitions
|
77
|
+
## Definitions
|
78
78
|
|
79
79
|
The main difference between **Rules** and **Evaluators** is Rules are purposed
|
80
80
|
for exact precedence and exact given matches (eg: two_pair only accepts
|
@@ -101,9 +101,9 @@ entire hand evaluation where-as Rules are specific scenarios.
|
|
101
101
|
the Cards are first initialized. Each Card holds its own Ranker
|
102
102
|
object.
|
103
103
|
|
104
|
-
#Example Usage
|
104
|
+
# Example Usage
|
105
105
|
|
106
|
-
###High Card
|
106
|
+
### High Card
|
107
107
|
|
108
108
|
```ruby
|
109
109
|
include CardsLib
|
@@ -144,11 +144,11 @@ as a simple list from least to greatest value. If you want to use a Hash (in ca
|
|
144
144
|
of different ranks may be the same value) you may, but you must then also define a Proc for
|
145
145
|
lookup. See [lib/cards_lib/standard/rankers/blackjack_ranker.rb](https://github.com/danielpclark/CardsLib/blob/master/lib/cards_lib/standard/rankers/blackjack_ranker.rb) for an example of how to implement that.
|
146
146
|
|
147
|
-
##License
|
147
|
+
## License
|
148
148
|
|
149
149
|
The MIT License (MIT)
|
150
150
|
|
151
|
-
Copyright (c) 2015-
|
151
|
+
Copyright (c) 2015-2017 by Daniel P. Clark
|
152
152
|
|
153
153
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
154
154
|
|
data/cards_lib.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Daniel P. Clark"]
|
10
10
|
spec.email = ["6ftdan@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary =
|
13
|
-
spec.description =
|
12
|
+
spec.summary = 'OO Card Game Library'
|
13
|
+
spec.description = 'Card Game Library. Testable and Object Oriented.'
|
14
14
|
spec.homepage = "http://github.com/danielpclark/CardsLib"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
data/lib/cards_lib.rb
CHANGED
data/lib/cards_lib/card.rb
CHANGED
@@ -6,9 +6,9 @@ module CardsLib
|
|
6
6
|
@suit = if_hash_then_fetch(face, :suit)
|
7
7
|
@rank = if_hash_then_fetch(face, :rank)
|
8
8
|
@face = face_from_rank_and_suit(@rank, @suit) if face.is_a? Hash
|
9
|
-
|
9
|
+
|
10
10
|
@face ||= face
|
11
|
-
@ranker = ranker.new(
|
11
|
+
@ranker = ranker.new(rank)
|
12
12
|
end
|
13
13
|
|
14
14
|
def inspect
|
@@ -16,7 +16,7 @@ module CardsLib
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def face
|
19
|
-
@face
|
19
|
+
@face
|
20
20
|
end
|
21
21
|
|
22
22
|
def suit
|
@@ -32,12 +32,12 @@ module CardsLib
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def pair?(other)
|
35
|
-
|
35
|
+
rank == other.rank
|
36
36
|
end
|
37
37
|
|
38
38
|
# equal by both rank and suit
|
39
39
|
def ==(other)
|
40
|
-
pair?(other) &&
|
40
|
+
pair?(other) && suit == other.suit
|
41
41
|
end
|
42
42
|
|
43
43
|
# equal by value
|
@@ -52,20 +52,20 @@ module CardsLib
|
|
52
52
|
def sequential?(other)
|
53
53
|
@ranker.sequential?(other)
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
# return other if true
|
57
57
|
def paired?(other)
|
58
|
-
(
|
58
|
+
(rank == other.rank) ? other : nil
|
59
59
|
end
|
60
60
|
|
61
61
|
# return other if true
|
62
62
|
def suited?(other)
|
63
|
-
(
|
63
|
+
(suit == other.suit) ? other : nil
|
64
64
|
end
|
65
65
|
|
66
66
|
# returns other if true
|
67
67
|
def ordered?(other)
|
68
|
-
|
68
|
+
sequential?(other) ? other : nil
|
69
69
|
end
|
70
70
|
|
71
71
|
private
|
data/lib/cards_lib/deck.rb
CHANGED
@@ -3,9 +3,13 @@ module CardsLib
|
|
3
3
|
def initialize(options = {})
|
4
4
|
cards = options.fetch(:cards) { Standard::PLAYING_CARDS }
|
5
5
|
ranker = options.fetch(:ranker){ Ranker }
|
6
|
-
@seed = options.fetch(:seed)
|
6
|
+
@seed = options.fetch(:seed) { Random.new.seed }
|
7
7
|
@top = 0
|
8
|
-
@cards = cards.
|
8
|
+
@cards = if cards.all? {|c| c.is_a? Card }
|
9
|
+
cards
|
10
|
+
else
|
11
|
+
cards.map {|c| Card.new(c, ranker) }
|
12
|
+
end.shuffle(random: Random.new(@seed)).to_enum
|
9
13
|
end
|
10
14
|
|
11
15
|
def inspect
|
data/lib/cards_lib/is_set.rb
CHANGED
@@ -7,9 +7,9 @@ module CardsLib
|
|
7
7
|
rules.all? {|r| send(r, cards) } && (min..max).include?(cards.count)
|
8
8
|
end
|
9
9
|
|
10
|
-
private
|
10
|
+
private
|
11
11
|
def unique(cards)
|
12
|
-
cards.combination(2).all? {|a,b| a != b }
|
12
|
+
cards.combination(2).all? {|a, b| a != b }
|
13
13
|
end
|
14
14
|
|
15
15
|
using Refinements::InjectWhile
|
@@ -17,7 +17,7 @@ module CardsLib
|
|
17
17
|
def paired(cards)
|
18
18
|
cards.inject_while?(:paired?)
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def suited(cards)
|
22
22
|
cards.inject_while?(:suited?)
|
23
23
|
end
|
data/lib/cards_lib/ranker.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
module CardsLib
|
2
2
|
class Ranker
|
3
3
|
include Comparable
|
4
|
-
|
4
|
+
attr_reader :rank, :rank_lookup
|
5
5
|
# Initialize's arguments:
|
6
6
|
# rank - is whatever part of the object, or the object itself you choose to use.
|
7
7
|
# ranks - is a simple hash to lookup a cards value with the keys matching the rank object.
|
8
8
|
# rank_lookup - is an optional Proc to redefine how you will lookup a cards value.
|
9
9
|
def initialize(rank = nil, ranks = nil, rank_lookup = nil)
|
10
|
-
@rank
|
10
|
+
@rank = rank
|
11
|
+
@ranks = ranks
|
12
|
+
@rank_lookup = rank_lookup
|
11
13
|
end
|
12
14
|
|
13
15
|
def ranks
|
@@ -15,16 +17,19 @@ module CardsLib
|
|
15
17
|
end
|
16
18
|
|
17
19
|
def ranker(rank_face = @rank)
|
18
|
-
|
19
|
-
|
20
|
+
if @rank_lookup
|
21
|
+
@rank_lookup.(rank_face)
|
22
|
+
else
|
23
|
+
ranks.index(rank_face).to_i + 1
|
24
|
+
end
|
20
25
|
end
|
21
26
|
|
22
|
-
def <=>(
|
23
|
-
ranker(
|
27
|
+
def <=>(other)
|
28
|
+
ranker(rank) <=> ranker(other.rank)
|
24
29
|
end
|
25
30
|
|
26
|
-
def sequential?(
|
27
|
-
(ranker(
|
31
|
+
def sequential?(other)
|
32
|
+
(ranker(rank) - ranker(other.rank)).abs == 1
|
28
33
|
end
|
29
34
|
end
|
30
35
|
end
|
@@ -6,15 +6,13 @@ module CardsLib
|
|
6
6
|
@cards = cards
|
7
7
|
@reduced_ace_count = 0
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def worth
|
11
11
|
@worth ||= @cards.map(&:value).inject(:+)
|
12
12
|
if @worth > 21
|
13
13
|
attempt = reduce_by_ace
|
14
|
-
until @worth < 22 || !attempt
|
15
|
-
|
16
|
-
end
|
17
|
-
end
|
14
|
+
attempt = reduce_by_ace until @worth < 22 || !attempt
|
15
|
+
end
|
18
16
|
@worth
|
19
17
|
end
|
20
18
|
|
@@ -10,7 +10,7 @@ module CardsLib
|
|
10
10
|
:high_card
|
11
11
|
]
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def self.royal_flush(cards)
|
15
15
|
cards if IsSet.verify(cards, [:suited]) && straight_to_ace(cards)
|
16
16
|
end
|
@@ -18,16 +18,16 @@ module CardsLib
|
|
18
18
|
def self.straight_flush(cards)
|
19
19
|
cards if IsSet.verify(cards, [:unique, :ordered, :suited], {min: 5, max: 5})
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
def self.four_of_a_kind(cards)
|
23
23
|
cards if IsSet.verify(cards, [:unique, :paired], {min: 4, max: 4})
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def self.full_house(cards)
|
27
27
|
pair, set = cards.group_by(&:rank).values.sort
|
28
|
-
cards if pair.inject(:pair?) && IsSet.verify(set, [:unique, :paired], {min:3, max: 3})
|
28
|
+
cards if pair.inject(:pair?) && IsSet.verify(set, [:unique, :paired], {min: 3, max: 3})
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
def self.flush(cards)
|
32
32
|
cards if IsSet.verify(cards, [:unique, :suited], {min: 5, max: 5})
|
33
33
|
end
|
@@ -38,7 +38,7 @@ module CardsLib
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def self.three_of_a_kind(cards)
|
41
|
-
cards if IsSet.verify(cards, [:unique, :paired], {min:3, max: 3})
|
41
|
+
cards if IsSet.verify(cards, [:unique, :paired], {min: 3, max: 3})
|
42
42
|
end
|
43
43
|
|
44
44
|
def self.two_pair(cards)
|
@@ -47,16 +47,16 @@ module CardsLib
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def self.one_pair(cards)
|
50
|
-
cards if IsSet.verify(cards, [:unique, :paired], {min:2, max: 2})
|
50
|
+
cards if IsSet.verify(cards, [:unique, :paired], {min: 2, max: 2})
|
51
51
|
end
|
52
52
|
|
53
53
|
def self.high_card(cards)
|
54
54
|
cards.detect {|c| c.rank[/\AA/]} || cards.sort.pop
|
55
55
|
end
|
56
56
|
|
57
|
-
class << self
|
57
|
+
class << self
|
58
58
|
def straight_to_ace(cards)
|
59
|
-
cards.sort.map(&:rank) == Cards[*%w
|
59
|
+
cards.sort.map(&:rank) == Cards[*%w(As Ks Qs Js Ts)].sort.map(&:rank)
|
60
60
|
end
|
61
61
|
private :straight_to_ace
|
62
62
|
end
|
data/lib/cards_lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cards_lib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel P. Clark
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-04-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -87,7 +87,9 @@ executables: []
|
|
87
87
|
extensions: []
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
|
+
- ".codeclimate.yml"
|
90
91
|
- ".gitignore"
|
92
|
+
- ".rubocop.yml"
|
91
93
|
- ".travis.yml"
|
92
94
|
- CODE_OF_CONDUCT.md
|
93
95
|
- Gemfile
|
@@ -132,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
132
134
|
version: '0'
|
133
135
|
requirements: []
|
134
136
|
rubyforge_project:
|
135
|
-
rubygems_version: 2.6.
|
137
|
+
rubygems_version: 2.6.11
|
136
138
|
signing_key:
|
137
139
|
specification_version: 4
|
138
140
|
summary: OO Card Game Library
|