deck_of_cards_handler 0.1.4 → 0.1.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9bb4b9ad9eeda85ab0251a2d2a0d1030ad1713956582d204726402254d1b423b
4
- data.tar.gz: 61b9a15a482800bc77b55f3e81402314ad1668fdfb0d8d1076bec4388ab05cb6
3
+ metadata.gz: ada5266ea6fced842e0110cfb42413202aecd0344b6e50d7e03284b148a3de12
4
+ data.tar.gz: 69e43292eb8d3476afd899093ec29391e96dcc97cc52c0378c08830c5b35b47e
5
5
  SHA512:
6
- metadata.gz: f10d2d29dabdd04098c987d992e06c303cb3a142097973aceb4f0e11cbfaf52feeea8d23418f488167fa645742accfb44ac6841efc71b84cada89b5362275865
7
- data.tar.gz: aa06d832d4e713cade2a60cd8a06fc7d7da776e3f86b9b1ce62c6101448c91c930f4248efd7a82c84587add52de9d3d08c05205a623eca53dde2d7c5f4fcb95a
6
+ metadata.gz: b65f41b901b72be9ad9e8978b34cc2ada7f886ed5e6fe704d8fb630cd02cba94bbee162e9e09097b4496663e41cd50d251b653ed77ac9ff92bb7bb5f1458d19f
7
+ data.tar.gz: 62ce89b3c2cf352ad82a8fd3f8c2c86cfbe731cfe4c9f633b53dbd3ff6183d822d48916f6e1b5b66647c85e1e96a75038e1b00916f201119e51dc118e3cfc155
data/README.md CHANGED
@@ -46,6 +46,62 @@ gem install deck_of_cards_handler
46
46
  # assign a position value to the cards
47
47
  deck.set_cards_positions
48
48
 
49
+ deck
50
+ # =>
51
+ # <Packet:0x000000012ae2b848
52
+ # @cards=
53
+ [#<Card:0x000000012ae2bd20 @position=1, @suit="S", @value="4">,
54
+ #<Card:0x000000012ae2cae0 @position=2, @suit="H", @value="2">,
55
+ #<Card:0x000000012ae2c220 @position=3, @suit="D", @value="7">,
56
+ #<Card:0x000000012ae2bd98 @position=4, @suit="S", @value="3">,
57
+ #<Card:0x000000012ae2c9f0 @position=5, @suit="H", @value="4">,
58
+ #<Card:0x000000012ae2c298 @position=6, @suit="D", @value="6">,
59
+ #<Card:0x000000012ae2df08 @position=7, @suit="C", @value="A">,
60
+ #<Card:0x000000012ae2c978 @position=8, @suit="H", @value="5">,
61
+ #<Card:0x000000012ae2ce00 @position=9, @suit="C", @value="9">,
62
+ #<Card:0x000000012ae2d260 @position=10, @suit="C", @value="2">,
63
+ #<Card:0x000000012ae2c630 @position=11, @suit="H", @value="Q">,
64
+ #<Card:0x000000012ae2c400 @position=12, @suit="D", @value="3">,
65
+ #<Card:0x000000012ae2b960 @position=13, @suit="S", @value="Q">,
66
+ #<Card:0x000000012ae2c810 @position=14, @suit="H", @value="8">,
67
+ #<Card:0x000000012ae2cf68 @position=15, @suit="C", @value="6">,
68
+ #<Card:0x000000012ae2cfe0 @position=16, @suit="C", @value="5">,
69
+ #<Card:0x000000012ae2c798 @position=17, @suit="H", @value="9">,
70
+ #<Card:0x000000012ae2b8e8 @position=18, @suit="S", @value="K">,
71
+ #<Card:0x000000012ae2c478 @position=19, @suit="D", @value="2">,
72
+ #<Card:0x000000012ae2c6a8 @position=20, @suit="H", @value="J">,
73
+ #<Card:0x000000012ae2d0d0 @position=21, @suit="C", @value="3">,
74
+ #<Card:0x000000012ae2ce78 @position=22, @suit="C", @value="8">,
75
+ #<Card:0x000000012ae2c900 @position=23, @suit="H", @value="6">,
76
+ #<Card:0x000000012ae2ba50 @position=24, @suit="S", @value="10">,
77
+ #<Card:0x000000012ae2c310 @position=25, @suit="D", @value="5">,
78
+ #<Card:0x000000012ae2bf50 @position=26, @suit="D", @value="K">,
79
+ #<Card:0x000000012ae2be10 @position=27, @suit="S", @value="2">,
80
+ #<Card:0x000000012ae2ca68 @position=28, @suit="H", @value="3">,
81
+ #<Card:0x000000012ae2c1a8 @position=29, @suit="D", @value="8">,
82
+ #<Card:0x000000012ae2bca8 @position=30, @suit="S", @value="5">,
83
+ #<Card:0x000000012ae2cc20 @position=31, @suit="C", @value="K">,
84
+ #<Card:0x000000012ae2c040 @position=32, @suit="D", @value="J">,
85
+ #<Card:0x000000012ae2bb40 @position=33, @suit="S", @value="8">,
86
+ #<Card:0x000000012ae2cd88 @position=34, @suit="C", @value="10">,
87
+ #<Card:0x000000012ae2c5b8 @position=35, @suit="H", @value="K">,
88
+ #<Card:0x000000012ae2b9d8 @position=36, @suit="S", @value="J">,
89
+ #<Card:0x000000012ae2cef0 @position=37, @suit="C", @value="7">,
90
+ #<Card:0x000000012ae2c720 @position=38, @suit="H", @value="10">,
91
+ #<Card:0x000000012ae2c4f0 @position=39, @suit="D", @value="A">,
92
+ #<Card:0x000000012ae2d058 @position=40, @suit="C", @value="4">,
93
+ #<Card:0x000000012ae2c888 @position=41, @suit="H", @value="7">,
94
+ #<Card:0x000000012ae2c388 @position=42, @suit="D", @value="4">,
95
+ #<Card:0x000000012ae2be88 @position=43, @suit="S", @value="A">,
96
+ #<Card:0x000000012ae2bac8 @position=44, @suit="S", @value="9">,
97
+ #<Card:0x000000012ae2cd10 @position=45, @suit="C", @value="J">,
98
+ #<Card:0x000000012ae2bfc8 @position=46, @suit="D", @value="Q">,
99
+ #<Card:0x000000012ae2bbb8 @position=47, @suit="S", @value="7">,
100
+ #<Card:0x000000012ae2cc98 @position=48, @suit="C", @value="Q">,
101
+ #<Card:0x000000012ae2c0b8 @position=49, @suit="D", @value="10">,
102
+ #<Card:0x000000012ae2bc30 @position=50, @suit="S", @value="6">,
103
+ #<Card:0x000000012ae2cb58 @position=51, @suit="H", @value="A">,
104
+ #<Card:0x000000012ae2c130 @position=52, @suit="D", @value="9">]>
49
105
  ```
50
106
 
51
107
  </details>
@@ -68,6 +124,9 @@ gem install deck_of_cards_handler
68
124
  deck.shuffle
69
125
 
70
126
  hands = deck.deal_into_piles(number_of_piles: 5, number_of_cards: 5)
127
+
128
+ hands.map(&:to_s)
129
+ # => [["5 of D", "8 of C", "6 of S", "10 of D", "5 of C"], ["7 of C", "5 of S", "4 of C", "2 of D", "Q of D"], ["3 of S", "8 of D", "A of D", "2 of C", "7 of D"], ["Q of H", "4 of S", "3 of D", "J of S", "9 of S"], ["6 of C", "6 of H", "10 of C", "4 of D", "A of H"]]
71
130
  ```
72
131
 
73
132
  </details>
@@ -50,28 +50,20 @@ class Card
50
50
  other.suit == suit && other.value == value
51
51
  end
52
52
 
53
- sig { returns(T::Array[Integer]) }
54
- def rank
53
+ sig { params(low_ace: T::Boolean).returns(Integer) }
54
+ def rank(low_ace: false)
55
55
  case value
56
- when "A" then [1, 14]
57
- when "J" then [11]
58
- when "Q" then [12]
59
- when "K" then [13]
60
- else [value.to_i]
56
+ when "A" then low_ace ? 1 : 14
57
+ when "J" then 11
58
+ when "Q" then 12
59
+ when "K" then 13
60
+ else value.to_i
61
61
  end
62
62
  end
63
63
 
64
64
  sig { params(other: Card).returns(Integer) }
65
65
  def <=>(other)
66
- # compare by all possible ranks (Ace flexible)
67
- my_ranks = rank
68
- other_ranks = other.rank
69
-
70
- # check if any ranks overlap (Ace == 1 or 14)
71
- return 0 if (my_ranks & other_ranks).any?
72
-
73
- # otherwise compare by highest possible
74
- T.must(my_ranks.max) <=> T.must(other_ranks.max)
66
+ rank <=> other.rank
75
67
  end
76
68
 
77
69
  class << self
@@ -52,9 +52,9 @@ class Packet
52
52
  packet
53
53
  end
54
54
 
55
- sig { params(string: String).returns(Packet) }
55
+ sig { overridable.params(string: String).returns(Packet) }
56
56
  def build_from_string(string:) # rubocop:disable Metrics
57
- content = string.split(",")
57
+ content = string.split(",").map(&:strip)
58
58
  cards = []
59
59
  cards_set = Set.new
60
60
 
@@ -0,0 +1,123 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # This represents a poker hands raking
5
+ class PokerHand < Packet
6
+ extend T::Sig
7
+ extend T::Helpers
8
+
9
+ sig { params(cards: T::Array[Card]).void }
10
+ def initialize(cards:)
11
+ raise ArgumentError if cards.size != 5
12
+
13
+ super
14
+ end
15
+
16
+ class << self
17
+ sig { override.params(string: String).returns(PokerHand) }
18
+ def build_from_string(string:)
19
+ result = super
20
+ PokerHand.new(cards: result.cards)
21
+ end
22
+ end
23
+
24
+ HAND_RANKS = T.let(
25
+ {
26
+ nothing: 0,
27
+ pair: 1,
28
+ two_pairs: 2,
29
+ three_of_a_kind: 3,
30
+ straight: 4,
31
+ flush: 5,
32
+ full_house: 6,
33
+ four_of_a_kind: 7,
34
+ straight_flush: 8
35
+ }.freeze, T::Hash[Symbol, Integer]
36
+ )
37
+
38
+ sig { returns(Integer) }
39
+ def rank # rubocop:disable Metrics
40
+ return T.must(HAND_RANKS[:straight_flush]) if straight_flush?
41
+ return T.must(HAND_RANKS[:four_of_a_kind]) if four_of_a_kind?
42
+ return T.must(HAND_RANKS[:full_house]) if full_house?
43
+ return T.must(HAND_RANKS[:flush]) if flush?
44
+ return T.must(HAND_RANKS[:straight]) if straight?
45
+ return T.must(HAND_RANKS[:three_of_a_kind]) if three_of_a_kind?
46
+ return T.must(HAND_RANKS[:two_pairs]) if two_pairs?
47
+ return T.must(HAND_RANKS[:pair]) if pair?
48
+
49
+ T.must(HAND_RANKS[:nothing])
50
+ end
51
+
52
+ sig { returns(T::Boolean) }
53
+ def pair?
54
+ validate_hand_size
55
+
56
+ counts = cards.map(&:rank).flatten.tally
57
+ counts.values.count(2) == 1
58
+ end
59
+
60
+ sig { returns(T::Boolean) }
61
+ def two_pairs?
62
+ validate_hand_size
63
+
64
+ counts = cards.map(&:rank).flatten.tally
65
+ counts.values.count(2) == 2
66
+ end
67
+
68
+ sig { returns(T::Boolean) }
69
+ def three_of_a_kind?
70
+ validate_hand_size
71
+
72
+ counts = cards.map(&:rank).flatten.tally
73
+ counts.values.count(3) == 1
74
+ end
75
+
76
+ sig { returns(T::Boolean) }
77
+ def straight? # rubocop:disable Metrics/AbcSize
78
+ validate_hand_size
79
+
80
+ ranks = cards.map(&:rank).sort
81
+ return true if ranks.each_cons(2).all? { |a, b| b == T.must(a) + 1 }
82
+
83
+ ranks = cards.map { _1.rank(low_ace: true) }
84
+ ranks.each_cons(2).all? { |a, b| b == T.must(a) + 1 }
85
+ end
86
+
87
+ sig { returns(T::Boolean) }
88
+ def flush?
89
+ validate_hand_size
90
+
91
+ suit = T.must(cards.first).suit
92
+ cards.all? { _1.suit == suit }
93
+ end
94
+
95
+ sig { returns(T::Boolean) }
96
+ def full_house?
97
+ validate_hand_size
98
+
99
+ three_of_a_kind? && pair?
100
+ end
101
+
102
+ sig { returns(T::Boolean) }
103
+ def four_of_a_kind?
104
+ validate_hand_size
105
+
106
+ counts = cards.map(&:rank).flatten.tally
107
+ counts.values.count(4) == 1
108
+ end
109
+
110
+ sig { returns(T::Boolean) }
111
+ def straight_flush?
112
+ validate_hand_size
113
+
114
+ straight? && flush?
115
+ end
116
+
117
+ private
118
+
119
+ sig { void }
120
+ def validate_hand_size
121
+ raise StandardError unless size == 5
122
+ end
123
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DeckOfCardsHandler
4
- VERSION = "0.1.4"
4
+ VERSION = "0.1.5"
5
5
  end
@@ -4,3 +4,4 @@ require "sorbet-runtime"
4
4
  require_relative "deck_of_cards_handler/version"
5
5
  require_relative "deck_of_cards_handler/card"
6
6
  require_relative "deck_of_cards_handler/packet"
7
+ require_relative "deck_of_cards_handler/poker_hand"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deck_of_cards_handler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Bernard
@@ -75,6 +75,7 @@ files:
75
75
  - lib/deck_of_cards_handler/packet/deals.rb
76
76
  - lib/deck_of_cards_handler/packet/packet.rb
77
77
  - lib/deck_of_cards_handler/packet/shuffles.rb
78
+ - lib/deck_of_cards_handler/poker_hand.rb
78
79
  - lib/deck_of_cards_handler/version.rb
79
80
  - sig/deck_of_cards.rbs
80
81
  - sorbet/config