fiftytwo 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/gem-push.yml +31 -0
- data/.github/workflows/ruby.yml +35 -0
- data/.gitignore +7 -0
- data/.rspec +2 -0
- data/.yardopts +1 -0
- data/CODE_OF_CONDUCT.md +76 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +151 -0
- data/Rakefile +7 -0
- data/fiftytwo.gemspec +34 -0
- data/lib/fiftytwo.rb +11 -0
- data/lib/fiftytwo/card.rb +60 -0
- data/lib/fiftytwo/deck.rb +33 -0
- data/lib/fiftytwo/hand.rb +9 -0
- data/lib/fiftytwo/has_cards.rb +52 -0
- data/lib/fiftytwo/rank.rb +57 -0
- data/lib/fiftytwo/suit.rb +45 -0
- data/lib/fiftytwo/suit/color.rb +23 -0
- data/lib/fiftytwo/version.rb +5 -0
- data/spec/lib/fiftytwo/card_spec.rb +95 -0
- data/spec/lib/fiftytwo/deck_spec.rb +280 -0
- data/spec/lib/fiftytwo/hand_spec.rb +7 -0
- data/spec/lib/fiftytwo/rank_spec.rb +128 -0
- data/spec/lib/fiftytwo/suit_spec.rb +107 -0
- data/spec/spec_helper.rb +16 -0
- metadata +229 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6c00da0e98ce49dd9546e2936caf0f8b19dea1353ff953e35edf0fa4e8856e97
|
4
|
+
data.tar.gz: bd0ec3c7c3b7bb0305c3b9b8ed534865eee21dd47a9b0e61e69655d9a7d3c8ff
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c2dbb21639b82fe689c8de2ef7033783e9a5ade2fd35372f7e763b09464cec1bc46bac943cd9274499621143922fe7eb7c0d34426b9430f698ea8dcc120b3216
|
7
|
+
data.tar.gz: cebde92a30ff69c21a3244e29588eef325431c0d684cddbb2b7a66c4bf34846a397b8529edc87397862512fbde75bd9a0960ff61c0f83d86e569211aecef6d83
|
@@ -0,0 +1,31 @@
|
|
1
|
+
name: Ruby Gem
|
2
|
+
|
3
|
+
on:
|
4
|
+
release:
|
5
|
+
types: [published]
|
6
|
+
|
7
|
+
jobs:
|
8
|
+
build:
|
9
|
+
name: Build + Publish
|
10
|
+
runs-on: ubuntu-latest
|
11
|
+
permissions:
|
12
|
+
contents: read
|
13
|
+
packages: write
|
14
|
+
|
15
|
+
steps:
|
16
|
+
- uses: actions/checkout@v2
|
17
|
+
- name: Set up Ruby 2.6
|
18
|
+
uses: actions/setup-ruby@v1
|
19
|
+
with:
|
20
|
+
ruby-version: 2.6.x
|
21
|
+
|
22
|
+
- name: Publish to RubyGems
|
23
|
+
run: |
|
24
|
+
mkdir -p $HOME/.gem
|
25
|
+
touch $HOME/.gem/credentials
|
26
|
+
chmod 0600 $HOME/.gem/credentials
|
27
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
28
|
+
gem build *.gemspec
|
29
|
+
gem push *.gem
|
30
|
+
env:
|
31
|
+
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
7
|
+
|
8
|
+
name: Ruby
|
9
|
+
|
10
|
+
on:
|
11
|
+
push:
|
12
|
+
branches: [ master ]
|
13
|
+
pull_request:
|
14
|
+
branches: [ master ]
|
15
|
+
|
16
|
+
jobs:
|
17
|
+
test:
|
18
|
+
|
19
|
+
runs-on: ubuntu-latest
|
20
|
+
strategy:
|
21
|
+
matrix:
|
22
|
+
ruby-version: ['2.6', '2.7', '3.0']
|
23
|
+
|
24
|
+
steps:
|
25
|
+
- uses: actions/checkout@v2
|
26
|
+
- name: Set up Ruby
|
27
|
+
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
28
|
+
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
29
|
+
# uses: ruby/setup-ruby@v1
|
30
|
+
uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
|
31
|
+
with:
|
32
|
+
ruby-version: ${{ matrix.ruby-version }}
|
33
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
34
|
+
- name: Run tests
|
35
|
+
run: bundle exec rspec
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--protected lib/**/*.rb
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
9
|
+
level of experience, education, socio-economic status, nationality, personal
|
10
|
+
appearance, race, religion, or sexual identity and orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at kevinstuffandthings@gmail.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
72
|
+
|
73
|
+
[homepage]: https://www.contributor-covenant.org
|
74
|
+
|
75
|
+
For answers to common questions about this code of conduct, see
|
76
|
+
https://www.contributor-covenant.org/faq
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2021 Kevin McDonald
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
# FiftyTwo ![Build Status](https://github.com/kevinstuffandthings/fiftytwo/actions/workflows/ruby.yml/badge.svg) [![Gem Version](https://badge.fury.io/rb/fiftytwo.svg)](https://badge.fury.io/rb/fiftytwo)
|
2
|
+
|
3
|
+
A [standard 52-card deck](https://en.wikipedia.org/wiki/Standard_52-card_deck), written in Ruby.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
Add this line to your application's Gemfile:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
# update with the version of your choice
|
10
|
+
gem 'fiftytwo'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
```bash
|
16
|
+
$ bundle install
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
```bash
|
22
|
+
$ gem install fiftytwo
|
23
|
+
```
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
Get a deck of cards:
|
27
|
+
```ruby
|
28
|
+
require "fiftytwo"
|
29
|
+
|
30
|
+
deck = FiftyTwo::Deck.standard
|
31
|
+
# => #<FiftyTwo::Deck:0x00007f905c154b10 @cards=[...]>
|
32
|
+
|
33
|
+
deck.count
|
34
|
+
# => 52
|
35
|
+
```
|
36
|
+
|
37
|
+
Examine how neatly organized the cards are, and then do something about it:
|
38
|
+
```ruby
|
39
|
+
deck[0..7].map(&:to_s)
|
40
|
+
# => ["2 of Clubs", "2 of Diamonds", "2 of Hearts", "2 of Spades", "3 of Clubs", "3 of Diamonds", "3 of Hearts", "3 of Spades"]
|
41
|
+
|
42
|
+
deck.shuffle! # you can always deck.sort! later
|
43
|
+
deck[0..7].map(&:to_s)
|
44
|
+
# => ["5 of Diamonds", "Jack of Spades", "Ace of Hearts", "6 of Hearts", "9 of Hearts", "2 of Diamonds", "3 of Spades", "7 of Spades"]
|
45
|
+
```
|
46
|
+
|
47
|
+
Take a deep dive into a card:
|
48
|
+
```ruby
|
49
|
+
card = deck.first
|
50
|
+
# => #<FiftyTwo::Card:0x00007f905c154548 ...>
|
51
|
+
|
52
|
+
card.rank
|
53
|
+
# => #<FiftyTwo::Rank:0x00007f9056a04068 @value=5, @name="5", @category=:pip>
|
54
|
+
|
55
|
+
card.suit
|
56
|
+
# => #<FiftyTwo::Suit:0x00007f9056a1f138 @name="diamonds", @color=#<FiftyTwo::Suit::Color:0x00007f9056a1f638 @name="red", @rgb="ff0000">, @symbol="♦">
|
57
|
+
|
58
|
+
card.red?
|
59
|
+
# => true
|
60
|
+
|
61
|
+
card.spades?
|
62
|
+
# => false
|
63
|
+
|
64
|
+
card.pip?
|
65
|
+
# => true
|
66
|
+
|
67
|
+
card.king?
|
68
|
+
# => false
|
69
|
+
```
|
70
|
+
|
71
|
+
Look for types of cards in your deck, as they are currently ordered:
|
72
|
+
```ruby
|
73
|
+
deck.kings.count
|
74
|
+
# => 4
|
75
|
+
|
76
|
+
deck.faces.reds.count
|
77
|
+
# => 6
|
78
|
+
|
79
|
+
deck.faces.reds.first.name
|
80
|
+
# => "Queen of Hearts"
|
81
|
+
|
82
|
+
deck.locate("AS").name
|
83
|
+
# => "Ace of Spades"
|
84
|
+
|
85
|
+
deck.locate("10C").name
|
86
|
+
# => "Ten of Clubs"
|
87
|
+
```
|
88
|
+
|
89
|
+
Draw a card from the deck, and give it back later:
|
90
|
+
```ruby
|
91
|
+
deck.shuffle!
|
92
|
+
card = deck.draw
|
93
|
+
# => #<FiftyTwo::Card:0x00007fb3d2284960 ...>
|
94
|
+
|
95
|
+
deck.count
|
96
|
+
# => 51
|
97
|
+
card.name
|
98
|
+
# => "9 of Diamonds"
|
99
|
+
|
100
|
+
deck << card
|
101
|
+
deck.count
|
102
|
+
# => 52
|
103
|
+
deck.last.name
|
104
|
+
# => "9 of Diamonds"
|
105
|
+
```
|
106
|
+
|
107
|
+
Deal some cards from the deck to yourself and a friend:
|
108
|
+
```ruby
|
109
|
+
my_hand = FiftyTwo::Hand.new
|
110
|
+
# => #<FiftyTwo::Hand:0x00007fb3d50ca7c0 @cards=[]>
|
111
|
+
your_hand = FiftyTwo::Hand.new
|
112
|
+
# => #<FiftyTwo::Hand:0x00007fb3d21c68c0 @cards=[]>
|
113
|
+
|
114
|
+
deck.deal([my_hand, your_hand], hand_size: 5)
|
115
|
+
"Deck has #{deck.count} cards, I have #{my_hand.count} cards, you have #{your_hand.count} cards"
|
116
|
+
# => "Deck has 42 cards, I have 5 cards, you have 5 cards"
|
117
|
+
|
118
|
+
puts my_hand.render, your_hand.render # by the way renderings are colored red/black in your terminal, just like the suit!
|
119
|
+
3♦ 4♠ 5♦ 7♥ 2♣
|
120
|
+
6♠ A♦ 5♠ 10♦ Q♣
|
121
|
+
```
|
122
|
+
|
123
|
+
Hands, just like the deck, can be shuffled, sorted, searched, etc:
|
124
|
+
```ruby
|
125
|
+
your_hand.sort!
|
126
|
+
puts your_hand.render
|
127
|
+
5♠ 6♠ 10♦ Q♣ A♦
|
128
|
+
|
129
|
+
your_hand.aces.count
|
130
|
+
# => 1
|
131
|
+
```
|
132
|
+
|
133
|
+
Pass your cards around:
|
134
|
+
```ruby
|
135
|
+
my_hand.transfer("4S", your_hand)
|
136
|
+
puts my_hand.render, your_hand.render
|
137
|
+
3♦ 5♦ 7♥ 2♣
|
138
|
+
5♠ 6♠ 10♦ Q♣ A♦ 4♠
|
139
|
+
|
140
|
+
your_hand.transfer("QC") # goes back to the deck
|
141
|
+
puts my_hand.render, your_hand.render
|
142
|
+
3♦ 5♦ 7♥ 2♣
|
143
|
+
5♠ 6♠ 10♦ A♦ 4♠
|
144
|
+
|
145
|
+
deck.count
|
146
|
+
# => 43
|
147
|
+
```
|
148
|
+
|
149
|
+
# Problems?
|
150
|
+
Please submit an [issue](https://github.com/kevinstuffandthings/fiftytwo/issues).
|
151
|
+
We'll figure out how to get you up and running with FiftyTwo as smoothly as possible.
|
data/Rakefile
ADDED
data/fiftytwo.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("../lib", __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require "fiftytwo/version"
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "fiftytwo"
|
9
|
+
spec.version = FiftyTwo::VERSION
|
10
|
+
spec.authors = ["Kevin McDonald"]
|
11
|
+
spec.email = ["kevinstuffandthings@gmail.com"]
|
12
|
+
spec.summary = "A deck of cards, written in Ruby"
|
13
|
+
spec.description = spec.summary
|
14
|
+
spec.homepage = "https://github.com/kevinstuffandthings/fiftytwo"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency "activesupport"
|
23
|
+
spec.add_dependency "colorize"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler"
|
26
|
+
spec.add_development_dependency "pry"
|
27
|
+
spec.add_development_dependency "pry-byebug"
|
28
|
+
spec.add_development_dependency "rack-test"
|
29
|
+
spec.add_development_dependency "rake"
|
30
|
+
spec.add_development_dependency "rspec"
|
31
|
+
spec.add_development_dependency "simplecov"
|
32
|
+
spec.add_development_dependency "standard"
|
33
|
+
spec.add_development_dependency "yard"
|
34
|
+
end
|
data/lib/fiftytwo.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "colorize"
|
4
|
+
|
5
|
+
module FiftyTwo
|
6
|
+
class Card
|
7
|
+
include Comparable
|
8
|
+
|
9
|
+
attr_reader :deck, :rank, :suit
|
10
|
+
delegate :color, to: :suit
|
11
|
+
|
12
|
+
def initialize(deck, rank, suit)
|
13
|
+
@deck = deck
|
14
|
+
@rank = rank
|
15
|
+
@suit = suit
|
16
|
+
end
|
17
|
+
|
18
|
+
def code
|
19
|
+
"#{rank.code}#{suit.code}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
"#{rank} of #{suit}"
|
24
|
+
end
|
25
|
+
alias_method :name, :to_s
|
26
|
+
|
27
|
+
def identifier
|
28
|
+
"#{rank.identifier}#{suit.identifier}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def render
|
32
|
+
code.rjust(3).send(suit.color.name)
|
33
|
+
end
|
34
|
+
|
35
|
+
def <=>(other)
|
36
|
+
[rank, suit] <=> [other.rank, other.suit]
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(name, **args, &block)
|
40
|
+
return super unless name.to_s.ends_with?("?")
|
41
|
+
|
42
|
+
attributes.each do |attribute|
|
43
|
+
return attribute.send(name) if attribute.respond_to?(name)
|
44
|
+
end
|
45
|
+
|
46
|
+
super
|
47
|
+
end
|
48
|
+
|
49
|
+
def respond_to_missing?(name, include_private = false)
|
50
|
+
return false unless name.to_s.ends_with?("?")
|
51
|
+
return false unless attributes.any? { |a| a.respond_to?(name) }
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def attributes
|
57
|
+
[rank, suit]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|