From 525fe65a7a78786969c08b5cdaa49ea50ab8776e Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 10:37:01 -0500 Subject: [PATCH 01/47] Change namespace from to-poker to poker --- lib/poker.rb | 4 ++++ lib/to-poker.rb | 5 ----- spec/spec_helper.rb | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) create mode 100644 lib/poker.rb delete mode 100644 lib/to-poker.rb diff --git a/lib/poker.rb b/lib/poker.rb new file mode 100644 index 0000000..4bdeb66 --- /dev/null +++ b/lib/poker.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true +# Poker Top Level Library +module Poker +end diff --git a/lib/to-poker.rb b/lib/to-poker.rb deleted file mode 100644 index 44ba628..0000000 --- a/lib/to-poker.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -# ToPoker Top Level Library -module ToPoker -end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a5e55ba..7e230f4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,6 +1,6 @@ -# frozen_string_literal: true -require 'to-poker' +# frozen_string_literal: true +require 'poker' # This file was generated by the `rspec --init` command. Conventionally, all # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. From 2c9535f93fedefa176cbdf7eabf0aa59ec9c3473 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 10:38:04 -0500 Subject: [PATCH 02/47] Set up base Poker::Card model with specs --- lib/poker.rb | 1 + lib/poker/card.rb | 10 ++++++++++ spec/poker/card_spec.rb | 16 ++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 lib/poker/card.rb create mode 100644 spec/poker/card_spec.rb diff --git a/lib/poker.rb b/lib/poker.rb index 4bdeb66..2977a19 100644 --- a/lib/poker.rb +++ b/lib/poker.rb @@ -1,3 +1,4 @@ +require 'poker/card' # frozen_string_literal: true # Poker Top Level Library module Poker diff --git a/lib/poker/card.rb b/lib/poker/card.rb new file mode 100644 index 0000000..2fe0594 --- /dev/null +++ b/lib/poker/card.rb @@ -0,0 +1,10 @@ +module Poker + class Card + attr_reader :rank, :suit + + def initialize(rank, suit) + @rank = rank + @suit = suit + end + end +end diff --git a/spec/poker/card_spec.rb b/spec/poker/card_spec.rb new file mode 100644 index 0000000..9beabff --- /dev/null +++ b/spec/poker/card_spec.rb @@ -0,0 +1,16 @@ +require 'rspec' +require 'spec_helper' + +RSpec.describe Poker::Card, type: :model do + it 'has class variable of suit' do + card = Poker::Card.new('Queen', 'Hearts') + + expect(card.suit).to eq('Hearts') + end + + it 'has class variable of rank' do + card = Poker::Card.new('Queen', 'Hearts') + + expect(card.rank).to eq('Queen') + end +end From a99294ec4d9072c220ce25b54f8d364447828679 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 11:00:53 -0500 Subject: [PATCH 03/47] Added constants SUITS and RANKS with specs --- lib/poker/card.rb | 3 +++ spec/poker/card_spec.rb | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/lib/poker/card.rb b/lib/poker/card.rb index 2fe0594..9c42d3f 100644 --- a/lib/poker/card.rb +++ b/lib/poker/card.rb @@ -2,6 +2,9 @@ module Poker class Card attr_reader :rank, :suit + RANKS = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'] + SUITS = ['Hearts', 'Spades', 'Diamonds', 'Clubs'] + def initialize(rank, suit) @rank = rank @suit = suit diff --git a/spec/poker/card_spec.rb b/spec/poker/card_spec.rb index 9beabff..612d900 100644 --- a/spec/poker/card_spec.rb +++ b/spec/poker/card_spec.rb @@ -13,4 +13,24 @@ expect(card.rank).to eq('Queen') end + + describe 'SUITS' do + it 'should include Hearts, Diamonds, Clubs, and Spades' do + suits = ["Hearts", "Diamonds", "Clubs", "Spades"] + + expect(Poker::Card::SUITS).to include(*suits) + end + end + + describe 'RANKS' do + it 'should include numbers 2 through 10' do + expect(Poker::Card::RANKS).to include(*(2..10).to_a.map(&:to_s)) + end + + it 'should include J, Q, K, A' do + face_cards = ['J', 'Q', 'K', 'A'] + + expect(Poker::Card::RANKS).to include(*face_cards) + end + end end From 0cc265fcb4512cc0e5e714edba1f4272144af809 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 11:26:13 -0500 Subject: [PATCH 04/47] Add deck file and require it --- lib/poker.rb | 1 + lib/poker/deck.rb | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 lib/poker/deck.rb diff --git a/lib/poker.rb b/lib/poker.rb index 2977a19..38fcab3 100644 --- a/lib/poker.rb +++ b/lib/poker.rb @@ -1,4 +1,5 @@ require 'poker/card' +require 'poker/deck' # frozen_string_literal: true # Poker Top Level Library module Poker diff --git a/lib/poker/deck.rb b/lib/poker/deck.rb new file mode 100644 index 0000000..f4ce44c --- /dev/null +++ b/lib/poker/deck.rb @@ -0,0 +1,5 @@ +module Poker + class Deck + + end +end From d87336777c01b658070cbfbad75c261b1cf4a7bc Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 11:28:00 -0500 Subject: [PATCH 05/47] Make create! happen immediately on initialize. Added specs --- lib/poker/deck.rb | 17 +++++++++++++++++ spec/poker/deck_spec.rb | 24 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 spec/poker/deck_spec.rb diff --git a/lib/poker/deck.rb b/lib/poker/deck.rb index f4ce44c..2b00890 100644 --- a/lib/poker/deck.rb +++ b/lib/poker/deck.rb @@ -1,5 +1,22 @@ module Poker class Deck + attr_accessor :contents + + def initialize + @contents = [] + return create! + end + + private + + def create! + Poker::Card::RANKS.each do |rank| + Poker::Card::SUITS.each do |suit| + @contents << Poker::Card.new(rank, suit) + end + end + @contents + end end end diff --git a/spec/poker/deck_spec.rb b/spec/poker/deck_spec.rb new file mode 100644 index 0000000..7511b55 --- /dev/null +++ b/spec/poker/deck_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + + +RSpec.describe Poker::Deck, type: :model do + describe '#initialize' do + it 'has class variable of contents' do + deck = Poker::Deck.new + + expect(deck.contents).to_not be_nil + expect(deck.contents).to be_kind_of(Array) + end + it 'receives create on initialize' do + expect_any_instance_of(Poker::Deck).to receive(:create!) + + Poker::Deck.new + end + + it 'contents has length of 52' do + deck = Poker::Deck.new + + expect(deck.contents.length).to eq(52) + end + end +end From 10ff6cb4776a76885b8c6415026fded38d87dd98 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 11:28:19 -0500 Subject: [PATCH 06/47] Add shuffle method with specs --- lib/poker/deck.rb | 4 ++++ spec/poker/deck_spec.rb | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/lib/poker/deck.rb b/lib/poker/deck.rb index 2b00890..bb6fb7c 100644 --- a/lib/poker/deck.rb +++ b/lib/poker/deck.rb @@ -8,6 +8,10 @@ def initialize return create! end + def shuffle + @contents.shuffle! + end + private def create! diff --git a/spec/poker/deck_spec.rb b/spec/poker/deck_spec.rb index 7511b55..4f0e2b9 100644 --- a/spec/poker/deck_spec.rb +++ b/spec/poker/deck_spec.rb @@ -21,4 +21,12 @@ expect(deck.contents.length).to eq(52) end end + + describe 'shuffle' do + it 'changes the contents positions' do + deck = Poker::Deck.new + + expect { deck.shuffle }.to change{ deck.contents } + end + end end From a8ece762cadda525c8033c904f936c4b014718db Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 13:01:13 -0500 Subject: [PATCH 07/47] Create number_value method --- lib/poker/card.rb | 4 ++++ spec/poker/card_spec.rb | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/lib/poker/card.rb b/lib/poker/card.rb index 9c42d3f..05e5143 100644 --- a/lib/poker/card.rb +++ b/lib/poker/card.rb @@ -9,5 +9,9 @@ def initialize(rank, suit) @rank = rank @suit = suit end + + def number_value + RANKS.index(rank) + 1 + end end end diff --git a/spec/poker/card_spec.rb b/spec/poker/card_spec.rb index 612d900..3ddfeed 100644 --- a/spec/poker/card_spec.rb +++ b/spec/poker/card_spec.rb @@ -33,4 +33,12 @@ expect(Poker::Card::RANKS).to include(*face_cards) end end + + describe '#number_value' do + it 'returns number value of card' do + card = Poker::Card.new('Q', 'Hearts') + + expect(card.number_value).to eq(11) + end + end end From d0299d7f806a50569844f71d7ee28525158a934d Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 13:05:31 -0500 Subject: [PATCH 08/47] Set up hand model and #sets method to organize hand cards --- lib/poker.rb | 2 ++ lib/poker/hand.rb | 64 +++++++++++++++++++++++++++++++++++++++++ spec/poker/hand_spec.rb | 27 +++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 lib/poker/hand.rb create mode 100644 spec/poker/hand_spec.rb diff --git a/lib/poker.rb b/lib/poker.rb index 38fcab3..c26adb6 100644 --- a/lib/poker.rb +++ b/lib/poker.rb @@ -1,5 +1,7 @@ +require 'pry' require 'poker/card' require 'poker/deck' +require 'poker/hand' # frozen_string_literal: true # Poker Top Level Library module Poker diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb new file mode 100644 index 0000000..a01b3cd --- /dev/null +++ b/lib/poker/hand.rb @@ -0,0 +1,64 @@ +module Poker + class Hand + + def initialize(cards) + @cards = cards + @sets = sets + end + + def straight_flush? + # same suit, ranks in a row + end + + def four_of_a_kind? + end + + def full_house? + # 3 cards of one rank, 2 cards of another rank + end + + def flush? + # 5 cards of all the same suit + end + + def straight? + # any suit, ranks in a row + end + + def three_of_a_kind? + end + + def two_pair? + # two of one rank, two of another rank, and one of a different rank + end + + def one_pair? + # two of one rank, rest of other ranks + end + + def high_card? + # research more later + end + + + def sets + sets = {} + @cards.each {|c| sets[c.number_value] = [] } + @cards.each do |c| + sets[c.number_value] << c + end + sets.sort_by {|k,v| k}.to_h + end + end +end + + +# straight flush +# four of a kind +# full house +# flush +# straight +# three of a kind +# two pair +# one pair +# high card diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb new file mode 100644 index 0000000..cb5404d --- /dev/null +++ b/spec/poker/hand_spec.rb @@ -0,0 +1,27 @@ +require 'spec_helper' + +RSpec.describe Poker::Hand, type: :model do + describe '#sets' do + it 'places cards into their ranking slots' do + cards = cyo_cards('three_of_a_kind') + hand = Poker::Hand.new(cards) + + expect(hand.sets[2].length).to eq(3) + expect(hand.sets[2].first.rank).to eq("3") + end + end + + def cyo_cards(type) + cards = [] + case type + when 'three_of_a_kind' + 3.times do |i| + cards << Poker::Card.new('3', Poker::Card::SUITS[i]) + end + cards << Poker::Card.new('5', 'Hearts') + cards << Poker::Card.new('10', 'Spades') + end + + cards + end +end From 5d437c066f448d0bbe1f3625d39d9a9f9ebceadf Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 13:26:42 -0500 Subject: [PATCH 09/47] Set up four_of_a_kind, three_of_a_kind and one pair with specs --- lib/poker/hand.rb | 8 +++- spec/poker/hand_spec.rb | 97 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 98 insertions(+), 7 deletions(-) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index a01b3cd..7039bf6 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -11,6 +11,7 @@ def straight_flush? end def four_of_a_kind? + of_a_kind?(4) end def full_house? @@ -26,6 +27,7 @@ def straight? end def three_of_a_kind? + of_a_kind?(3) end def two_pair? @@ -33,13 +35,17 @@ def two_pair? end def one_pair? - # two of one rank, rest of other ranks + of_a_kind?(2) end def high_card? # research more later end + def of_a_kind?(number) + @sets.values.any? { |s| s.length == number } + end + def sets sets = {} diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index cb5404d..43bed00 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -3,7 +3,7 @@ RSpec.describe Poker::Hand, type: :model do describe '#sets' do it 'places cards into their ranking slots' do - cards = cyo_cards('three_of_a_kind') + cards = cyo_cards(3) hand = Poker::Hand.new(cards) expect(hand.sets[2].length).to eq(3) @@ -11,15 +11,100 @@ end end + describe '#straight_flush?' do + end + + describe '#four_of_a_kind?' do + let(:cards) { cyo_cards(4) } + let(:hand) { Poker::Hand.new(cards) } + + it 'returns true when there are four of the same rank' do + expect(hand.four_of_a_kind?).to be_truthy + end + + it 'returns false when there are not four of the same rank' do + cards = cyo_cards(2) + hand = Poker::Hand.new(cards) + + expect(hand.four_of_a_kind?).to be_falsey + end + + it 'receives of_a_kind?' do + expect(hand).to receive(:of_a_kind?) + + hand.four_of_a_kind? + end + end + + describe '#full_house?' do + end + + describe '#flush?' do + end + + describe '#straight?' do + end + + describe '#three_of_a_kind?' do + let(:cards) { cyo_cards(3) } + let(:hand) { Poker::Hand.new(cards) } + + it 'returns true when there are three of the same rank' do + expect(hand.three_of_a_kind?).to be_truthy + end + + it 'returns false when there are not three of the same rank' do + cards = cyo_cards(2) + hand = Poker::Hand.new(cards) + + expect(hand.three_of_a_kind?).to be_falsey + end + + it 'receives of_a_kind?' do + expect(hand).to receive(:of_a_kind?) + + hand.three_of_a_kind? + end + end + + describe '#two_pair?' do + end + + describe '#one_pair?' do + let(:cards) { cyo_cards(2) } + let(:hand) { Poker::Hand.new(cards) } + + it 'returns true when there are two of the same rank' do + expect(hand.one_pair?).to be_truthy + end + + it 'returns false when there are not two of the same rank' do + cards = cyo_cards(3) + hand = Poker::Hand.new(cards) + + expect(hand.one_pair?).to be_falsey + end + + it 'receives of_a_kind?' do + expect(hand).to receive(:of_a_kind?) + + hand.one_pair? + end + end + + def cyo_cards(type) cards = [] - case type - when 'three_of_a_kind' - 3.times do |i| + + if type.is_a? Integer + type.times do |i| cards << Poker::Card.new('3', Poker::Card::SUITS[i]) end - cards << Poker::Card.new('5', 'Hearts') - cards << Poker::Card.new('10', 'Spades') + cards_left = (5 - type) + + cards_left.times do |i| + cards << Poker::Card.new((4..10).to_a.map(&:to_s).sample, Poker::Card::SUITS[i]) + end end cards From 391b4d1a73d54b8d7404462f193126bdeaaf5f71 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 13:43:47 -0500 Subject: [PATCH 10/47] Add two_pair? method with specs --- lib/poker/hand.rb | 2 +- spec/poker/hand_spec.rb | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index 7039bf6..232f734 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -31,7 +31,7 @@ def three_of_a_kind? end def two_pair? - # two of one rank, two of another rank, and one of a different rank + one_pair? && @sets.select {|k,v| v.length == 2}.length == 2 end def one_pair? diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index 43bed00..bab8b2c 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -68,6 +68,20 @@ end describe '#two_pair?' do + let(:cards) { cyo_cards('two_pair') } + let(:hand) { Poker::Hand.new(cards) } + + it 'returns true when there are two different pairs in the hand' do + + expect(hand.two_pair?).to be_truthy + end + + it 'returns true when there is only one pair in the hand' do + cards = cyo_cards(2) + hand = Poker::Hand.new(cards) + + expect(hand.two_pair?).to be_falsey + end end describe '#one_pair?' do @@ -105,6 +119,15 @@ def cyo_cards(type) cards_left.times do |i| cards << Poker::Card.new((4..10).to_a.map(&:to_s).sample, Poker::Card::SUITS[i]) end + else + case type + when 'two_pair' + ranks = ['2', '2', '3', '3'] + 4.times do |i| + cards << Poker::Card.new(ranks[i], Poker::Card::SUITS[i]) + end + cards << Poker::Card.new('10', 'Spades') + end end cards From f292d201cafd5e170d4c11af28bca8234a4c9ee7 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 13:59:31 -0500 Subject: [PATCH 11/47] Add #straight? method with specs Also added return in specs for cyo_cards since without it caused an issue with the case statement --- lib/poker/hand.rb | 2 +- spec/poker/hand_spec.rb | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index 232f734..7411220 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -23,7 +23,7 @@ def flush? end def straight? - # any suit, ranks in a row + @sets.keys == (@sets.keys.first..@sets.keys.last).to_a end def three_of_a_kind? diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index bab8b2c..005b138 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -43,6 +43,19 @@ end describe '#straight?' do + let(:cards) { cyo_cards('straight') } + let(:hand) { Poker::Hand.new(cards) } + + it 'returns true when cards rank in a row' do + expect(hand.straight?).to be_truthy + end + + it 'returns false when cards do not rank in a row' do + cards = cyo_cards(2) + hand = Poker::Hand.new(cards) + + expect(hand.straight?).to be_falsey + end end describe '#three_of_a_kind?' do @@ -127,9 +140,13 @@ def cyo_cards(type) cards << Poker::Card.new(ranks[i], Poker::Card::SUITS[i]) end cards << Poker::Card.new('10', 'Spades') + when 'straight' + 5.times do |i| + cards << Poker::Card.new(Poker::Card::RANKS[i], Poker::Card::SUITS.sample) + end end end - cards + return cards end end From 97463827e23d458965c783b7f58b16ef6ecfa06e Mon Sep 17 00:00:00 2001 From: Gregor MacDougall Date: Thu, 8 Dec 2016 14:23:15 -0500 Subject: [PATCH 12/47] Refactor one pair spec This refactors the one pair spec to remove a random failure caused by the generated card set occasionally having a pair (approx. one of out every 13 tries) and removes the reliance on the `cyo_cards` method. We're going to do this refactoring on some of the other tests soon. --- spec/poker/hand_spec.rb | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index 005b138..38dcbfe 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' RSpec.describe Poker::Hand, type: :model do + let(:hand) { Poker::Hand.new(cards) } + describe '#sets' do it 'places cards into their ranking slots' do cards = cyo_cards(3) @@ -98,24 +100,34 @@ end describe '#one_pair?' do - let(:cards) { cyo_cards(2) } - let(:hand) { Poker::Hand.new(cards) } - - it 'returns true when there are two of the same rank' do - expect(hand.one_pair?).to be_truthy - end - - it 'returns false when there are not two of the same rank' do - cards = cyo_cards(3) - hand = Poker::Hand.new(cards) + subject { hand.one_pair? } + + context 'when there are two of the same rank' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('2', 'Clubs'), + ] + end - expect(hand.one_pair?).to be_falsey + it { is_expected.to be_truthy } end - it 'receives of_a_kind?' do - expect(hand).to receive(:of_a_kind?) + context 'when there are not two of the same rank' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('6', 'Clubs'), + ] + end - hand.one_pair? + it { is_expected.to be_falsey } end end From 616dfbbc2aad2d59e4abe20e2c571bf59ac0de52 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 14:32:55 -0500 Subject: [PATCH 13/47] Move sets to private and remove its specs --- lib/poker/hand.rb | 1 + spec/poker/hand_spec.rb | 10 ---------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index 7411220..b667da9 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -46,6 +46,7 @@ def of_a_kind?(number) @sets.values.any? { |s| s.length == number } end + private def sets sets = {} diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index 38dcbfe..7083e7f 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -3,16 +3,6 @@ RSpec.describe Poker::Hand, type: :model do let(:hand) { Poker::Hand.new(cards) } - describe '#sets' do - it 'places cards into their ranking slots' do - cards = cyo_cards(3) - hand = Poker::Hand.new(cards) - - expect(hand.sets[2].length).to eq(3) - expect(hand.sets[2].first.rank).to eq("3") - end - end - describe '#straight_flush?' do end From d761a5e970d389a4c6370e8ca97d39d348a32c23 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 14:33:10 -0500 Subject: [PATCH 14/47] Refactor four_of_a_kind? specs --- spec/poker/hand_spec.rb | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index 7083e7f..fdafbcf 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -7,24 +7,33 @@ end describe '#four_of_a_kind?' do - let(:cards) { cyo_cards(4) } - let(:hand) { Poker::Hand.new(cards) } - - it 'returns true when there are four of the same rank' do - expect(hand.four_of_a_kind?).to be_truthy - end - - it 'returns false when there are not four of the same rank' do - cards = cyo_cards(2) - hand = Poker::Hand.new(cards) - - expect(hand.four_of_a_kind?).to be_falsey + subject { hand.four_of_a_kind? } + let(:cards) { + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('2', 'Spades'), + Poker::Card.new('2', 'Hearts'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('2', 'Clubs'), + ] + } + + context 'when there are four of the same rank' do + it { is_expected.to be_truthy } end - it 'receives of_a_kind?' do - expect(hand).to receive(:of_a_kind?) + context 'when there are not four of the same rank' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('6', 'Clubs'), + ] + end - hand.four_of_a_kind? + it { is_expected.to be_falsey } end end From f8054524b2faa2f8161e0d60cf25fd9eef6714b6 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 14:35:19 -0500 Subject: [PATCH 15/47] Refactor straight? specs --- spec/poker/hand_spec.rb | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index fdafbcf..adbf171 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -44,18 +44,34 @@ end describe '#straight?' do - let(:cards) { cyo_cards('straight') } - let(:hand) { Poker::Hand.new(cards) } + subject { hand.straight? } + + context 'when cards rank in a row' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('6', 'Clubs'), + ] + end - it 'returns true when cards rank in a row' do - expect(hand.straight?).to be_truthy + it { is_expected.to be_truthy } end - it 'returns false when cards do not rank in a row' do - cards = cyo_cards(2) - hand = Poker::Hand.new(cards) + context 'when cards do not rank in a row' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('9', 'Diamonds'), + Poker::Card.new('6', 'Clubs'), + ] + end - expect(hand.straight?).to be_falsey + it { is_expected.to be_falsey } end end From 6f028bb7b58cac90180f4ca74a5e720ff1c297f0 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 14:40:16 -0500 Subject: [PATCH 16/47] Refactored three_of_a_kind? spec --- spec/poker/hand_spec.rb | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index adbf171..d0eae9b 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -76,24 +76,34 @@ end describe '#three_of_a_kind?' do - let(:cards) { cyo_cards(3) } - let(:hand) { Poker::Hand.new(cards) } - - it 'returns true when there are three of the same rank' do - expect(hand.three_of_a_kind?).to be_truthy - end + subject { hand.three_of_a_kind? } - it 'returns false when there are not three of the same rank' do - cards = cyo_cards(2) - hand = Poker::Hand.new(cards) + context 'when there are three of the same rank' do + let(:cards) { + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('2', 'Spades'), + Poker::Card.new('4', 'Hearts'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('2', 'Clubs'), + ] + } - expect(hand.three_of_a_kind?).to be_falsey + it { is_expected.to be_truthy } end - it 'receives of_a_kind?' do - expect(hand).to receive(:of_a_kind?) + context 'when there are not three of the same rank' do + let(:cards) { + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('8', 'Spades'), + Poker::Card.new('4', 'Hearts'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('2', 'Clubs'), + ] + } - hand.three_of_a_kind? + it { is_expected.to be_falsey } end end From 537ce51696aee03f831ffa64fb438f53fc53d8e6 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 14:40:37 -0500 Subject: [PATCH 17/47] Refactored two_pair? spec --- spec/poker/hand_spec.rb | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index d0eae9b..73c69b7 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -108,19 +108,34 @@ end describe '#two_pair?' do - let(:cards) { cyo_cards('two_pair') } - let(:hand) { Poker::Hand.new(cards) } + subject { hand.two_pair? } - it 'returns true when there are two different pairs in the hand' do + context 'when there are two different pairs in the hand' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('3', 'Hearts'), + Poker::Card.new('2', 'Clubs'), + ] + end - expect(hand.two_pair?).to be_truthy + it { is_expected.to be_truthy } end - it 'returns true when there is only one pair in the hand' do - cards = cyo_cards(2) - hand = Poker::Hand.new(cards) + context 'when there is only one pair in the hand' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('2', 'Clubs'), + ] + end - expect(hand.two_pair?).to be_falsey + it { is_expected.to be_falsey } end end From 7632db0a4735a848097b985595267538b866c7cd Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 14:40:50 -0500 Subject: [PATCH 18/47] Remove unused cyo_card method from specs --- spec/poker/hand_spec.rb | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index 73c69b7..66b9201 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -170,35 +170,4 @@ it { is_expected.to be_falsey } end end - - - def cyo_cards(type) - cards = [] - - if type.is_a? Integer - type.times do |i| - cards << Poker::Card.new('3', Poker::Card::SUITS[i]) - end - cards_left = (5 - type) - - cards_left.times do |i| - cards << Poker::Card.new((4..10).to_a.map(&:to_s).sample, Poker::Card::SUITS[i]) - end - else - case type - when 'two_pair' - ranks = ['2', '2', '3', '3'] - 4.times do |i| - cards << Poker::Card.new(ranks[i], Poker::Card::SUITS[i]) - end - cards << Poker::Card.new('10', 'Spades') - when 'straight' - 5.times do |i| - cards << Poker::Card.new(Poker::Card::RANKS[i], Poker::Card::SUITS.sample) - end - end - end - - return cards - end end From d720b2dd4104d5f58eb096990cd45591397b47c7 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 14:49:24 -0500 Subject: [PATCH 19/47] Add #flush? with specs --- lib/poker/hand.rb | 2 +- spec/poker/hand_spec.rb | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index b667da9..44065da 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -19,7 +19,7 @@ def full_house? end def flush? - # 5 cards of all the same suit + @cards.map { |c| c.suit }.uniq.length == 1 end def straight? diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index 66b9201..bf312f0 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -41,6 +41,36 @@ end describe '#flush?' do + + subject { hand.flush? } + + context 'when all the cards are the same suit' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('6', 'Diamonds'), + ] + end + + it { is_expected.to be_truthy } + end + + context 'when all the cards are not the same suit' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('6', 'Clubs'), + ] + end + + it { is_expected.to be_falsey } + end end describe '#straight?' do From 273f059abe0657c1267375cdf1e514ef172c5c8a Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 14:53:33 -0500 Subject: [PATCH 20/47] Set up specs for full_house? --- spec/poker/hand_spec.rb | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index bf312f0..4971d87 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -38,6 +38,36 @@ end describe '#full_house?' do + subject { hand.full_house? } + + + context 'when 3 cards are of one rank and two of another' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('2', 'Hearts'), + Poker::Card.new('2', 'Spades'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('5', 'Spades'), + ] + end + + it { is_expected.to be_truthy } + end + + context 'when there arent 3 cards of the same rank nor two of another' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Hearts'), + Poker::Card.new('4', 'Spades'), + Poker::Card.new('6', 'Diamonds'), + Poker::Card.new('5', 'Spades'), + ] + end + + it { is_expected.to be_falsey } + end end describe '#flush?' do From 2ac80f3f7ecb35c532bd10b93b881c7dca96acec Mon Sep 17 00:00:00 2001 From: Gregor MacDougall Date: Thu, 8 Dec 2016 14:58:22 -0500 Subject: [PATCH 21/47] Full house implementation with testing We discovered a lacking context within our full house which has been amended to make sure that three of a kind will not be considered a full house on its own. --- lib/poker/hand.rb | 2 +- spec/poker/hand_spec.rb | 43 +++++++++++++++++++++++++++-------------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index 44065da..46febba 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -15,7 +15,7 @@ def four_of_a_kind? end def full_house? - # 3 cards of one rank, 2 cards of another rank + three_of_a_kind? && one_pair? end def flush? diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index 4971d87..9a2d7e4 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -40,28 +40,43 @@ describe '#full_house?' do subject { hand.full_house? } - - context 'when 3 cards are of one rank and two of another' do - let(:cards) do - [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('2', 'Hearts'), - Poker::Card.new('2', 'Spades'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('5', 'Spades'), - ] + context 'when there are three cards of one rank' do + context 'when the other two cards are the same rank' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('2', 'Hearts'), + Poker::Card.new('2', 'Spades'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('5', 'Spades'), + ] + end + + it { is_expected.to be_truthy } end - it { is_expected.to be_truthy } + context 'when the other two cards are a different rank' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('2', 'Hearts'), + Poker::Card.new('2', 'Spades'), + Poker::Card.new('8', 'Diamonds'), + Poker::Card.new('5', 'Spades'), + ] + end + + it { is_expected.to be_falsey } + end end - context 'when there arent 3 cards of the same rank nor two of another' do + context 'when there are not three cards of one rank' do let(:cards) do [ Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('3', 'Hearts'), + Poker::Card.new('2', 'Hearts'), Poker::Card.new('4', 'Spades'), - Poker::Card.new('6', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), Poker::Card.new('5', 'Spades'), ] end From e464e380d46843eafb4f3e236dabb52ec723d222 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 15:05:19 -0500 Subject: [PATCH 22/47] Implemented #straight_flush? with specs --- lib/poker/hand.rb | 2 +- spec/poker/hand_spec.rb | 43 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index 46febba..dafb2e0 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -7,7 +7,7 @@ def initialize(cards) end def straight_flush? - # same suit, ranks in a row + straight? && flush? end def four_of_a_kind? diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index 9a2d7e4..3c7da44 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -4,6 +4,49 @@ let(:hand) { Poker::Hand.new(cards) } describe '#straight_flush?' do + subject { hand.straight_flush? } + + context 'all five cards are the same suit and they rank in a row' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('6', 'Diamonds'), + ] + end + + it { is_expected.to be_truthy } + end + + context 'when the hand is not the same suit' do + let(:cards) do + [ + Poker::Card.new('2', 'Spades'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('6', 'Diamonds'), + ] + end + + it { is_expected.to be_falsey } + end + + context 'when the hand does not rank in a row' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('Q', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('6', 'Diamonds'), + ] + end + + it { is_expected.to be_falsey } + end end describe '#four_of_a_kind?' do From 989ca151ac2d584b46253b070519530754cb2309 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 15:19:56 -0500 Subject: [PATCH 23/47] Fix #straight? method by checking for set key length to eq 5 --- lib/poker/hand.rb | 2 +- spec/poker/hand_spec.rb | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index dafb2e0..e36570f 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -23,7 +23,7 @@ def flush? end def straight? - @sets.keys == (@sets.keys.first..@sets.keys.last).to_a + @sets.keys.length == 5 && @sets.keys == (@sets.keys.first..@sets.keys.last).to_a end def three_of_a_kind? diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index 3c7da44..ee53b95 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -191,6 +191,20 @@ it { is_expected.to be_falsey } end + + context 'when cards do not rank in a row' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('2', 'Hearts'), + Poker::Card.new('2', 'Spades'), + Poker::Card.new('2', 'Clubs'), + Poker::Card.new('3', 'Clubs'), + ] + end + + it { is_expected.to be_falsey } + end end describe '#three_of_a_kind?' do From cea868f0b86b7d784be5947e1bae60a90ad68d26 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 15:42:17 -0500 Subject: [PATCH 24/47] Refactor straight? to consider low ace options --- lib/poker/hand.rb | 10 +++++++++- spec/poker/hand_spec.rb | 28 ++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index e36570f..ad100b2 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -23,7 +23,7 @@ def flush? end def straight? - @sets.keys.length == 5 && @sets.keys == (@sets.keys.first..@sets.keys.last).to_a + standard_straight? || ace_low_straight? end def three_of_a_kind? @@ -48,6 +48,14 @@ def of_a_kind?(number) private + def standard_straight? + @sets.keys.length == 5 && @sets.keys == (@sets.keys.first..@sets.keys.last).to_a + end + + def ace_low_straight? + sets.keys == [1, 2, 3, 4, 13] + end + def sets sets = {} @cards.each {|c| sets[c.number_value] = [] } diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index ee53b95..87498a2 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -205,6 +205,34 @@ it { is_expected.to be_falsey } end + + context 'when Ace is involved and a straight' do + let(:cards) do + [ + Poker::Card.new('A', 'Clubs'), + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + ] + end + + it { is_expected.to be_truthy } + end + + context 'when Ace is involved but not a straight' do + let(:cards) do + [ + Poker::Card.new('A', 'Clubs'), + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('K', 'Diamonds'), + ] + end + + it { is_expected.to be_falsey } + end end describe '#three_of_a_kind?' do From 9c847dd0ef2818c097b6bba6b30b08166a28e52b Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 15:52:27 -0500 Subject: [PATCH 25/47] Add #level to determine hand type --- lib/poker/hand.rb | 22 ++++++++++++++++++++++ spec/poker/hand_spec.rb | 19 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index ad100b2..5c067fc 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -46,6 +46,28 @@ def of_a_kind?(number) @sets.values.any? { |s| s.length == number } end + def level + if straight_flush? + 8 + elsif four_of_a_kind? + 7 + elsif full_house? + 6 + elsif flush? + 5 + elsif straight? + 4 + elsif three_of_a_kind? + 3 + elsif two_pair? + 2 + elsif one_pair? + 1 + else + 0 + end + end + private def standard_straight? diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index 87498a2..46cbe15 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -330,4 +330,23 @@ it { is_expected.to be_falsey } end end + + describe '#level' do + + context 'when the hand is a straight flush' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('6', 'Diamonds'), + ] + end + + it 'returns a number associating the level of the hand' do + expect(hand.level).to eq(8) + end + end + end end From d455e03dafd62ebdb39d852316b282761bcbccdf Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 16:11:27 -0500 Subject: [PATCH 26/47] Change contents to cards to make more sense and remove shuffle method, move it inside of create method --- lib/poker/deck.rb | 12 ++++-------- spec/poker/deck_spec.rb | 18 +++++------------- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/lib/poker/deck.rb b/lib/poker/deck.rb index bb6fb7c..60f31da 100644 --- a/lib/poker/deck.rb +++ b/lib/poker/deck.rb @@ -1,26 +1,22 @@ module Poker class Deck - attr_accessor :contents + attr_reader :cards def initialize - @contents = [] + @cards = [] return create! end - def shuffle - @contents.shuffle! - end - private def create! Poker::Card::RANKS.each do |rank| Poker::Card::SUITS.each do |suit| - @contents << Poker::Card.new(rank, suit) + @cards << Poker::Card.new(rank, suit) end end - @contents + @cards.shuffle! end end end diff --git a/spec/poker/deck_spec.rb b/spec/poker/deck_spec.rb index 4f0e2b9..3a37376 100644 --- a/spec/poker/deck_spec.rb +++ b/spec/poker/deck_spec.rb @@ -3,11 +3,11 @@ RSpec.describe Poker::Deck, type: :model do describe '#initialize' do - it 'has class variable of contents' do + it 'has class variable of cards' do deck = Poker::Deck.new - expect(deck.contents).to_not be_nil - expect(deck.contents).to be_kind_of(Array) + expect(deck.cards).to_not be_nil + expect(deck.cards).to be_kind_of(Array) end it 'receives create on initialize' do expect_any_instance_of(Poker::Deck).to receive(:create!) @@ -15,18 +15,10 @@ Poker::Deck.new end - it 'contents has length of 52' do + it 'cards has length of 52' do deck = Poker::Deck.new - expect(deck.contents.length).to eq(52) - end - end - - describe 'shuffle' do - it 'changes the contents positions' do - deck = Poker::Deck.new - - expect { deck.shuffle }.to change{ deck.contents } + expect(deck.cards.length).to eq(52) end end end From 504ca8e5a85ebec5ee8aafe122d2ccdc30022a55 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 16:18:11 -0500 Subject: [PATCH 27/47] Raise error if not enough cards are delt --- lib/poker/hand.rb | 2 ++ spec/poker/hand_spec.rb | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index 5c067fc..23bff37 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -4,6 +4,8 @@ class Hand def initialize(cards) @cards = cards @sets = sets + + raise "Hey! I don't have enough cards" if @cards.length != 5 end def straight_flush? diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index 46cbe15..a69d9a1 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -3,6 +3,16 @@ RSpec.describe Poker::Hand, type: :model do let(:hand) { Poker::Hand.new(cards) } + it 'raises error if not enough cards are delt' do + cards = [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + ] + + expect { Poker::Hand.new(cards) }.to raise_error + end + describe '#straight_flush?' do subject { hand.straight_flush? } From f1c002c82df7a73bd4becba3444f9a15731ab985 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 16:31:59 -0500 Subject: [PATCH 28/47] Set up dealer, selects an array of winners in the case that there is a tie, added specs --- lib/poker.rb | 1 + lib/poker/dealer.rb | 38 +++++++++++++++++++++++ spec/poker/dealer_spec.rb | 65 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 lib/poker/dealer.rb create mode 100644 spec/poker/dealer_spec.rb diff --git a/lib/poker.rb b/lib/poker.rb index c26adb6..e28a562 100644 --- a/lib/poker.rb +++ b/lib/poker.rb @@ -2,6 +2,7 @@ require 'poker/card' require 'poker/deck' require 'poker/hand' +require 'poker/dealer' # frozen_string_literal: true # Poker Top Level Library module Poker diff --git a/lib/poker/dealer.rb b/lib/poker/dealer.rb new file mode 100644 index 0000000..93c3d3f --- /dev/null +++ b/lib/poker/dealer.rb @@ -0,0 +1,38 @@ +module Poker + class Dealer + attr_reader :deck, :hands + + def initialize(num_players) + @num_players = num_players + @deck = Poker::Deck.new + @hands = [] + end + + def deal_round + @num_players.times do + @hands << deal + end + end + + def winner + hand_rankings = {} + + @hands.each {|h| hand_rankings[h.level] = [] } + @hands.each do |h| + hand_rankings[h.level] << h + end + + max_key = hand_rankings.keys.max + hand_rankings.select! { |k,v| k == max_key } + + hand_rankings[max_key] + end + + + private + + def deal + Poker::Hand.new(@deck.cards.pop(5)) + end + end +end diff --git a/spec/poker/dealer_spec.rb b/spec/poker/dealer_spec.rb new file mode 100644 index 0000000..059ec22 --- /dev/null +++ b/spec/poker/dealer_spec.rb @@ -0,0 +1,65 @@ +require 'spec_helper' + + +RSpec.describe Poker::Dealer, type: :model do + let(:dealer) { Poker::Dealer.new(3) } + + describe '#deal_round' do + subject { dealer.deal_round } + + it 'creates 3 hands' do + expect{ subject }.to change { dealer.hands.length }.from(0).to(3) + end + end + + describe '#winner' do + let(:straight_flush) { + Poker::Hand.new([ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('6', 'Diamonds'), + ]) + } + before do + dealer.deal_round + end + it 'returns the hand of the winner' do + dealer.instance_variable_set("@hands", [ + straight_flush, + Poker::Hand.new([ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('8', 'Spades'), + Poker::Card.new('4', 'Hearts'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('2', 'Clubs'), + ]), + Poker::Hand.new([ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('2', 'Hearts'), + Poker::Card.new('2', 'Spades'), + Poker::Card.new('8', 'Diamonds'), + Poker::Card.new('5', 'Spades'), + ]), + ]) + + expect(dealer.winner).to eq([straight_flush]) + end + it 'returns a tie of winners' do + dealer.instance_variable_set("@hands", [ + straight_flush, + straight_flush, + Poker::Hand.new([ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('2', 'Hearts'), + Poker::Card.new('2', 'Spades'), + Poker::Card.new('8', 'Diamonds'), + Poker::Card.new('5', 'Spades'), + ]), + ]) + + expect(dealer.winner).to eq([straight_flush, straight_flush]) + end + end +end From a01fb9b0b5014d7f25c75ce6b9343c5ea8d156c5 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Thu, 8 Dec 2016 17:20:28 -0500 Subject: [PATCH 29/47] Cleaning up unused code/comments --- lib/poker/hand.rb | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index 23bff37..4a875cb 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -40,10 +40,6 @@ def one_pair? of_a_kind?(2) end - def high_card? - # research more later - end - def of_a_kind?(number) @sets.values.any? { |s| s.length == number } end @@ -90,14 +86,3 @@ def sets end end end - - -# straight flush -# four of a kind -# full house -# flush -# straight -# three of a kind -# two pair -# one pair -# high card From 2410bc17242fefa8958cbd1ec9e726459f9ed1b8 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 09:26:44 -0500 Subject: [PATCH 30/47] Move frozen_string_literal to top line --- lib/poker.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/poker.rb b/lib/poker.rb index e28a562..8369b67 100644 --- a/lib/poker.rb +++ b/lib/poker.rb @@ -1,9 +1,9 @@ +# frozen_string_literal: true require 'pry' require 'poker/card' require 'poker/deck' require 'poker/hand' require 'poker/dealer' -# frozen_string_literal: true # Poker Top Level Library module Poker end From 525de7b4c8b8071d74e4c79aab5f219da36b8b5d Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 09:28:20 -0500 Subject: [PATCH 31/47] Refactor deal_round --- lib/poker/dealer.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/poker/dealer.rb b/lib/poker/dealer.rb index 93c3d3f..cc36459 100644 --- a/lib/poker/dealer.rb +++ b/lib/poker/dealer.rb @@ -9,9 +9,7 @@ def initialize(num_players) end def deal_round - @num_players.times do - @hands << deal - end + @hands = Array.new(@num_players) { deal } end def winner From 4924ea5faa1c8854516242f5ac173746edf7133b Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 09:31:15 -0500 Subject: [PATCH 32/47] Move creation of cards to initialize and remove create spec --- lib/poker/deck.rb | 17 +++++------------ spec/poker/deck_spec.rb | 5 ----- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/lib/poker/deck.rb b/lib/poker/deck.rb index 60f31da..4380a39 100644 --- a/lib/poker/deck.rb +++ b/lib/poker/deck.rb @@ -4,19 +4,12 @@ class Deck attr_reader :cards def initialize - @cards = [] - return create! - end - - private - - def create! - Poker::Card::RANKS.each do |rank| - Poker::Card::SUITS.each do |suit| - @cards << Poker::Card.new(rank, suit) + @cards = Poker::Card::RANKS.flat_map do |rank| + Poker::Card::SUITS.flat_map do |suit| + Poker::Card.new(rank, suit) end - end - @cards.shuffle! + end.shuffle! end + end end diff --git a/spec/poker/deck_spec.rb b/spec/poker/deck_spec.rb index 3a37376..383caae 100644 --- a/spec/poker/deck_spec.rb +++ b/spec/poker/deck_spec.rb @@ -9,11 +9,6 @@ expect(deck.cards).to_not be_nil expect(deck.cards).to be_kind_of(Array) end - it 'receives create on initialize' do - expect_any_instance_of(Poker::Deck).to receive(:create!) - - Poker::Deck.new - end it 'cards has length of 52' do deck = Poker::Deck.new From 9aa83c2b6913b4d7579b873d87f4a64b62d4ba58 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 09:33:01 -0500 Subject: [PATCH 33/47] Include enumerable to add more methods to deck --- lib/poker/deck.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/poker/deck.rb b/lib/poker/deck.rb index 4380a39..1a5fbc6 100644 --- a/lib/poker/deck.rb +++ b/lib/poker/deck.rb @@ -1,5 +1,6 @@ module Poker class Deck + include Enumerable attr_reader :cards @@ -11,5 +12,9 @@ def initialize end.shuffle! end + def each(&block) + @cards.each(&block) + end + end end From 75f69743efe34039fe993bf6cf9fc3a9302d5343 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 09:46:19 -0500 Subject: [PATCH 34/47] Remove error from poker hand and add custom error to poker dealer --- lib/poker/dealer.rb | 4 ++++ lib/poker/hand.rb | 2 -- spec/poker/hand_spec.rb | 10 ---------- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/lib/poker/dealer.rb b/lib/poker/dealer.rb index cc36459..30e8f97 100644 --- a/lib/poker/dealer.rb +++ b/lib/poker/dealer.rb @@ -1,5 +1,7 @@ module Poker class Dealer + class EmptyDeckError < StandardError; end + attr_reader :deck, :hands def initialize(num_players) @@ -31,6 +33,8 @@ def winner def deal Poker::Hand.new(@deck.cards.pop(5)) + + raise EmptyDeckError if @deck.cards.empty? end end end diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index 4a875cb..82d7a64 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -4,8 +4,6 @@ class Hand def initialize(cards) @cards = cards @sets = sets - - raise "Hey! I don't have enough cards" if @cards.length != 5 end def straight_flush? diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index a69d9a1..46cbe15 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -3,16 +3,6 @@ RSpec.describe Poker::Hand, type: :model do let(:hand) { Poker::Hand.new(cards) } - it 'raises error if not enough cards are delt' do - cards = [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('3', 'Diamonds'), - Poker::Card.new('4', 'Diamonds'), - ] - - expect { Poker::Hand.new(cards) }.to raise_error - end - describe '#straight_flush?' do subject { hand.straight_flush? } From 944131c18fd55ec9a59c078130cf74e45b4a9cd3 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 10:04:16 -0500 Subject: [PATCH 35/47] Refactored sets and fixed all methods affected by refactor --- lib/poker/hand.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index 82d7a64..741fdc2 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -31,7 +31,7 @@ def three_of_a_kind? end def two_pair? - one_pair? && @sets.select {|k,v| v.length == 2}.length == 2 + one_pair? && @sets.select { |k,v| v == 2 }.length == 2 end def one_pair? @@ -39,7 +39,7 @@ def one_pair? end def of_a_kind?(number) - @sets.values.any? { |s| s.length == number } + @sets.values.any? {|s| s == number } end def level @@ -75,12 +75,12 @@ def ace_low_straight? end def sets - sets = {} - @cards.each {|c| sets[c.number_value] = [] } - @cards.each do |c| - sets[c.number_value] << c + sets = @cards.inject(Hash.new(0)) do |hash, card| + hash[card.number_value] += 1 + hash end - sets.sort_by {|k,v| k}.to_h + + Hash[sets.sort] end end end From e45d987b68edb90eabd2593ac64c293f22f7d889 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 10:05:45 -0500 Subject: [PATCH 36/47] Change spec to match_array instead of include with wild card so it is sure to match all contents of array --- spec/poker/card_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/poker/card_spec.rb b/spec/poker/card_spec.rb index 3ddfeed..1f0a054 100644 --- a/spec/poker/card_spec.rb +++ b/spec/poker/card_spec.rb @@ -18,7 +18,7 @@ it 'should include Hearts, Diamonds, Clubs, and Spades' do suits = ["Hearts", "Diamonds", "Clubs", "Spades"] - expect(Poker::Card::SUITS).to include(*suits) + expect(Poker::Card::SUITS).to match_array(suits) end end From fdb106b67db3ccb6dddb3f9573bef51160fd0cfb Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 11:15:10 -0500 Subject: [PATCH 37/47] Refactor #winner method significantly --- lib/poker/dealer.rb | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/lib/poker/dealer.rb b/lib/poker/dealer.rb index 30e8f97..889c6f3 100644 --- a/lib/poker/dealer.rb +++ b/lib/poker/dealer.rb @@ -15,17 +15,9 @@ def deal_round end def winner - hand_rankings = {} + max_key = @hands.map { |h| h.level }.max - @hands.each {|h| hand_rankings[h.level] = [] } - @hands.each do |h| - hand_rankings[h.level] << h - end - - max_key = hand_rankings.keys.max - hand_rankings.select! { |k,v| k == max_key } - - hand_rankings[max_key] + @hands.select { |h| h.level == max_key } end From 1775059879a83af855a82c49da4f55c7bc5d4d64 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 11:44:33 -0500 Subject: [PATCH 38/47] Add comparable method to compare a hands rank to another, also added specs --- lib/poker/hand.rb | 13 ++++++++ spec/poker/hand_spec.rb | 68 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index 741fdc2..8d6e628 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -1,5 +1,6 @@ module Poker class Hand + include Comparable def initialize(cards) @cards = cards @@ -64,6 +65,18 @@ def level end end + def <=>(other_hand) + other_sets = other_hand.send(:sets) + lvl_compare = level <=> other_hand.level + + return lvl_compare unless lvl_compare == 0 + + total = sets.map {|k,v| k*v}.reduce(0, :+) + other_hand_total = other_sets.map {|k,v| k*v}.reduce(0, :+) + + total <=> other_hand_total + end + private def standard_straight? diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index 46cbe15..ce34dfe 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -349,4 +349,72 @@ end end end + + describe '<=>' do + context 'when the hands are not the same level' do + + let(:cards) do + [ + Poker::Card.new('2', 'Hearts'), + Poker::Card.new('Q', 'Diamonds'), + Poker::Card.new('2', 'Clubs'), + Poker::Card.new('7', 'Diamonds'), + Poker::Card.new('2', 'Spades'), + ] + end + let(:cards2) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('2', 'Clubs'), + ] + end + let(:hand2) { Poker::Hand.new(cards2) } + + it 'returns false with ==' do + expect(hand == hand2).to be_falsey + end + + it 'returns false with <' do + expect(hand < hand2).to be_falsey + end + + it 'returns true with >' do + expect(hand > hand2).to be_truthy + end + end + + context 'when both hand levels are the same but one has higher cards' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('2', 'Clubs'), + ] + end + let(:cards2) do + [ + Poker::Card.new('2', 'Hearts'), + Poker::Card.new('Q', 'Diamonds'), + Poker::Card.new('3', 'Clubs'), + Poker::Card.new('7', 'Diamonds'), + Poker::Card.new('2', 'Spades'), + ] + end + let(:hand2) { Poker::Hand.new(cards2) } + + + it 'returns false when asking if first hand is greater' do + expect(hand > hand2).to be_falsey + end + + it 'returns true when asking if second hand is greater' do + expect(hand < hand2).to be_truthy + end + end + end end From b963ee58eb27e5b8e01ac90e3cd5780540cb4e62 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 12:44:16 -0500 Subject: [PATCH 39/47] Install factory_girl --- Gemfile.lock | 17 +++++++++++++++++ spec/spec_helper.rb | 3 +++ to-poker.gemspec | 1 + 3 files changed, 21 insertions(+) diff --git a/Gemfile.lock b/Gemfile.lock index 478b95d..ac5db9d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,13 +7,23 @@ PATH GEM remote: https://rubygems.org/ specs: + activesupport (5.0.0.1) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (~> 0.7) + minitest (~> 5.1) + tzinfo (~> 1.1) binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) coderay (1.1.1) + concurrent-ruby (1.0.2) debug_inspector (0.0.2) diff-lcs (1.2.5) + factory_girl (4.7.0) + activesupport (>= 3.0.0) + i18n (0.7.0) interception (0.5) method_source (0.8.2) + minitest (5.10.1) pry (0.10.4) coderay (~> 1.1.0) method_source (~> 0.8.1) @@ -39,6 +49,9 @@ GEM rspec-support (~> 3.5.0) rspec-support (3.5.0) slop (3.6.0) + thread_safe (0.3.5) + tzinfo (1.2.2) + thread_safe (~> 0.1) yard (0.9.5) PLATFORMS @@ -46,9 +59,13 @@ PLATFORMS DEPENDENCIES binding_of_caller + factory_girl pry pry-rescue pry-stack_explorer rspec (>= 3.5.0) to-poker! yard + +BUNDLED WITH + 1.13.6 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 7e230f4..6fb3b76 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,6 +1,9 @@ # frozen_string_literal: true require 'poker' +require 'factory_girl' + +Dir[File.join(File.dirname(__FILE__), 'factories/*.rb')].each { |f| require f } # This file was generated by the `rspec --init` command. Conventionally, all # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. diff --git a/to-poker.gemspec b/to-poker.gemspec index deb3a6b..d978b45 100644 --- a/to-poker.gemspec +++ b/to-poker.gemspec @@ -12,6 +12,7 @@ Gem::Specification.new do |gem| gem.add_dependency('rake') gem.add_development_dependency('rspec', [">= 3.5.0"]) + gem.add_development_dependency('factory_girl') # ensure the gem is built out of versioned files gem.files = Dir['Rakefile', '{bin,lib,man,test,spec}/**/*', 'README*', 'LICENSE*'] & `git ls-files -z`.split("\0") From 2e189e53560008bb5d908e65557311ae792b24ef Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 12:44:28 -0500 Subject: [PATCH 40/47] Set up hand factory --- spec/factories/hand_factory.rb | 143 +++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 spec/factories/hand_factory.rb diff --git a/spec/factories/hand_factory.rb b/spec/factories/hand_factory.rb new file mode 100644 index 0000000..4eaa646 --- /dev/null +++ b/spec/factories/hand_factory.rb @@ -0,0 +1,143 @@ +FactoryGirl.define do + factory :hand, class: Poker::Hand do + initialize_with do + ranks = Poker::Card::RANKS.shuffle + suits = Poker::Card::SUITS + new((0..4).map {|c| Poker::Card.new(ranks.pop, suits.sample) }) + end + end + + factory :straight_flush, class: Poker::Hand do + initialize_with do + new( + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + Poker::Card.new('6', 'Diamonds'), + ] + ) + end + end + + factory :four_of_a_kind, class: Poker::Hand do + initialize_with do + new( + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('2', 'Spades'), + Poker::Card.new('2', 'Hearts'), + Poker::Card.new('5', 'Clubs'), + Poker::Card.new('2', 'Clubs'), + ] + ) + end + end + + factory :full_house, class: Poker::Hand do + initialize_with do + new( + [ + Poker::Card.new('7', 'Diamonds'), + Poker::Card.new('7', 'Hearts'), + Poker::Card.new('7', 'Spades'), + Poker::Card.new('8', 'Diamonds'), + Poker::Card.new('8', 'Spades'), + ] + ) + end + end + + factory :flush, class: Poker::Hand do + initialize_with do + new( + [ + Poker::Card.new('2', 'Spades'), + Poker::Card.new('3', 'Hearts'), + Poker::Card.new('4', 'Hearts'), + Poker::Card.new('5', 'Hearts'), + Poker::Card.new('6', 'Hearts'), + ] + ) + end + end + + factory :straight, class: Poker::Hand do + initialize_with do + new( + [ + Poker::Card.new('2', 'Spades'), + Poker::Card.new('3', 'Spades'), + Poker::Card.new('4', 'Spades'), + Poker::Card.new('5', 'Spades'), + Poker::Card.new('6', 'Clubs'), + ] + ) + end + end + + factory :straight_with_ace, class: Poker::Hand do + initialize_with do + new( + Poker::Card.new('A', 'Clubs'), + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + ) + end + end + + factory :three_of_a_kind, class: Poker::Hand do + transient do + match_rank nil + high_card nil + end + + initialize_with do + new( + [ + Poker::Card.new(match_rank || '4', 'Diamonds'), + Poker::Card.new(match_rank || '4', 'Spades'), + Poker::Card.new(match_rank || '4', 'Hearts'), + Poker::Card.new(high_card || '5', 'Clubs'), + Poker::Card.new('2', 'Clubs'), + ] + ) + end + end + + factory :two_pair, class: Poker::Hand do + transient do + one_pair_rank nil + high_card nil + end + + initialize_with do + new( + [ + Poker::Card.new(one_pair_rank || '7', 'Diamonds'), + Poker::Card.new('J', 'Spades'), + Poker::Card.new('J', 'Hearts'), + Poker::Card.new(high_card || '5', 'Clubs'), + Poker::Card.new(one_pair_rank || '7', 'Clubs'), + ] + ) + end + end + + factory :one_pair, class: Poker::Hand do + initialize_with do + new( + [ + Poker::Card.new('K', 'Diamonds'), + Poker::Card.new('Q', 'Spades'), + Poker::Card.new('J', 'Hearts'), + Poker::Card.new('4', 'Clubs'), + Poker::Card.new('Q', 'Clubs'), + ] + ) + end + end +end From 2c8ad0243b2bde76e7e1ee06f1b53b12d3735411 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 13:39:31 -0500 Subject: [PATCH 41/47] Add specs to level --- spec/poker/hand_spec.rb | 45 +++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index ce34dfe..069ad4f 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -2,6 +2,14 @@ RSpec.describe Poker::Hand, type: :model do let(:hand) { Poker::Hand.new(cards) } + let(:straight_flush) { FactoryGirl.build(:straight_flush) } + let(:four_of_a_kind) { FactoryGirl.build(:four_of_a_kind) } + let(:full_house) { FactoryGirl.build(:full_house) } + let(:flush) { FactoryGirl.build(:flush) } + let(:straight) { FactoryGirl.build(:straight) } + let(:three_of_a_kind) { FactoryGirl.build(:three_of_a_kind) } + let(:two_pair) { FactoryGirl.build(:two_pair) } + let(:one_pair) { FactoryGirl.build(:one_pair) } describe '#straight_flush?' do subject { hand.straight_flush? } @@ -332,20 +340,35 @@ end describe '#level' do - context 'when the hand is a straight flush' do - let(:cards) do - [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('3', 'Diamonds'), - Poker::Card.new('4', 'Diamonds'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('6', 'Diamonds'), - ] + subject { straight_flush.level } + + context 'comparing if greater than a full_house' do + it { is_expected.to be > full_house.level } + end + + context 'comparing if greater than a straight' do + it { is_expected.to be > straight.level } + end + + context 'comparing if greater than a flush' do + it { is_expected.to be > flush.level } + end + + context 'comparing if greater than a four_of_a_kind' do + it { is_expected.to be > four_of_a_kind.level } + end + + context 'comparing if greater than a three_of_a_kind' do + it { is_expected.to be > three_of_a_kind.level } + end + + context 'comparing if greater than a two_pair' do + it { is_expected.to be > two_pair.level } end - it 'returns a number associating the level of the hand' do - expect(hand.level).to eq(8) + context 'comparing if greater than a one_pair' do + it { is_expected.to be > one_pair.level } end end end From a841989276da64fef02a9ad024b28128eaad55cd Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 15:10:30 -0500 Subject: [PATCH 42/47] Refactor <=> method and add sorted_sets method, add passing specs --- lib/poker/hand.rb | 8 +-- spec/poker/hand_spec.rb | 156 +++++++++++++++++++++++++++++++--------- 2 files changed, 125 insertions(+), 39 deletions(-) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index 8d6e628..36e429f 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -66,15 +66,15 @@ def level end def <=>(other_hand) - other_sets = other_hand.send(:sets) lvl_compare = level <=> other_hand.level return lvl_compare unless lvl_compare == 0 - total = sets.map {|k,v| k*v}.reduce(0, :+) - other_hand_total = other_sets.map {|k,v| k*v}.reduce(0, :+) + sorted_sets <=> other_hand.sorted_sets + end - total <=> other_hand_total + def sorted_sets + @sets.sort_by { |rank,matches| rank*100+matches }.reverse.to_h.keys end private diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index 069ad4f..b097854 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -376,67 +376,153 @@ describe '<=>' do context 'when the hands are not the same level' do - let(:cards) do - [ - Poker::Card.new('2', 'Hearts'), - Poker::Card.new('Q', 'Diamonds'), - Poker::Card.new('2', 'Clubs'), - Poker::Card.new('7', 'Diamonds'), - Poker::Card.new('2', 'Spades'), - ] + it 'returns true with >' do + hand1 = FactoryGirl.build(:straight_flush) + hand2 = FactoryGirl.build(:straight) + + expect(hand1).to be > hand2 end - let(:cards2) do - [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('3', 'Diamonds'), - Poker::Card.new('4', 'Diamonds'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('2', 'Clubs'), - ] + + it 'returns false with ==' do + hand1 = FactoryGirl.build(:straight_flush) + hand2 = FactoryGirl.build(:straight) + + expect(hand1).to_not be == hand2 end - let(:hand2) { Poker::Hand.new(cards2) } it 'returns false with ==' do - expect(hand == hand2).to be_falsey + hand1 = FactoryGirl.build(:straight_flush) + hand2 = FactoryGirl.build(:straight) + + expect(hand1).to_not be < hand2 end + end + + context 'when both hand levels are the same' do + context 'hand2 has higher match cards' do + + it 'returns true' do + hand1 = FactoryGirl.build(:two_pair) + hand2 = FactoryGirl.build(:two_pair, one_pair_rank: 'Q') - it 'returns false with <' do - expect(hand < hand2).to be_falsey + expect(hand1).to be < hand2 + end end - it 'returns true with >' do - expect(hand > hand2).to be_truthy + context 'hand2 has a higher high card' do + it 'returns true' do + hand1 = FactoryGirl.build(:two_pair) + hand2 = FactoryGirl.build(:two_pair, high_card: 'Q') + + expect(hand1).to be < hand2 + end + end + end + + context 'when both hands ranks are exactly the same' do + # Crazy scenario + it 'returns true' do + hand1 = FactoryGirl.build(:flush) + hand2 = FactoryGirl.build(:flush) + + expect(hand1).to be == hand2 + end + end + + context 'when there are no matches' do + context 'when all the cards are the same except one' do + let(:cards) do + [ + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('2', 'Hearts'), + Poker::Card.new('8', 'Hearts'), + Poker::Card.new('5', 'Spades'), + Poker::Card.new('K', 'Hearts'), + ] + end + let(:cards2) do + [ + Poker::Card.new('2', 'Hearts'), + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('8', 'Spades'), + Poker::Card.new('5', 'Clubs'), + Poker::Card.new('Q', 'Diamonds'), + ] + end + + let(:hand2) { Poker::Hand.new(cards2) } + + it 'returns true for hand1 being greater than hand2' do + expect(hand).to be > hand2 + end end end - context 'when both hand levels are the same but one has higher cards' do + context 'when hands are same level but one hand has a higher match' do let(:cards) do [ Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('3', 'Diamonds'), - Poker::Card.new('4', 'Diamonds'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('2', 'Clubs'), + Poker::Card.new('2', 'Hearts'), + Poker::Card.new('8', 'Hearts'), + Poker::Card.new('5', 'Spades'), + Poker::Card.new('K', 'Hearts'), ] end let(:cards2) do [ - Poker::Card.new('2', 'Hearts'), + Poker::Card.new('3', 'Hearts'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('8', 'Spades'), + Poker::Card.new('5', 'Clubs'), Poker::Card.new('Q', 'Diamonds'), - Poker::Card.new('3', 'Clubs'), - Poker::Card.new('7', 'Diamonds'), - Poker::Card.new('2', 'Spades'), ] end let(:hand2) { Poker::Hand.new(cards2) } + it 'returns true for hand2 being greater than hand1' do + expect(hand).to be < hand2 + end + end + end + + describe '#sorted_sets' do + context 'with no matches' do + let(:hand) do + Poker::Hand.new( + [ + Poker::Card.new('3', 'Hearts'), + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('8', 'Spades'), + Poker::Card.new('5', 'Clubs'), + Poker::Card.new('Q', 'Diamonds'), + ] + ) + end + + it 'match decesending array' do + sorted_set_array = [11, 7, 4, 2, 1] + + expect(hand.sorted_sets).to match_array(sorted_set_array) + end + + it 'array equals sets highest key' do + expect(hand.sorted_sets[0]).to eq(hand.send(:sets).keys.last) + end + end + + context 'with two pair' do + let(:hand) { FactoryGirl.build(:two_pair) } - it 'returns false when asking if first hand is greater' do - expect(hand > hand2).to be_falsey + it 'sorts to put the highest rank with the most matches first' do + highest_rank = hand.sorted_sets[0] + + expect(hand.send(:sets)[highest_rank]).to eq(2) end - it 'returns true when asking if second hand is greater' do - expect(hand < hand2).to be_truthy + it 'sorts to put the second rank with the most matches second' do + second_highest = hand.sorted_sets[1] + + expect(hand.send(:sets)[second_highest]).to eq(2) end end end From 06c3a8f9a1402ff10291a7bf6c185a89f735f738 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 15:32:01 -0500 Subject: [PATCH 43/47] Fix sorted_sets since it was not always sorting correctly --- lib/poker/hand.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index 36e429f..c1961bd 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -74,7 +74,8 @@ def <=>(other_hand) end def sorted_sets - @sets.sort_by { |rank,matches| rank*100+matches }.reverse.to_h.keys + # &:reverse makes sure that the hash sorts by value first then key + @sets.sort_by(&:reverse).reverse.to_h.keys end private From db1504a985b51108ca6bd792f0fab42e7d47f613 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 15:42:47 -0500 Subject: [PATCH 44/47] Fix #winner method to utilize .max enumerable to select the winner --- lib/poker/dealer.rb | 4 +-- spec/poker/dealer_spec.rb | 73 +++++++++++++++++++++++---------------- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/lib/poker/dealer.rb b/lib/poker/dealer.rb index 889c6f3..7ac502d 100644 --- a/lib/poker/dealer.rb +++ b/lib/poker/dealer.rb @@ -15,9 +15,7 @@ def deal_round end def winner - max_key = @hands.map { |h| h.level }.max - - @hands.select { |h| h.level == max_key } + @hands.select { |hand| hand == @hands.max } end diff --git a/spec/poker/dealer_spec.rb b/spec/poker/dealer_spec.rb index 059ec22..70dbb0d 100644 --- a/spec/poker/dealer_spec.rb +++ b/spec/poker/dealer_spec.rb @@ -3,6 +3,9 @@ RSpec.describe Poker::Dealer, type: :model do let(:dealer) { Poker::Dealer.new(3) } + let(:straight_flush) { FactoryGirl.build(:straight_flush) } + let(:three_of_a_kind) { FactoryGirl.build(:three_of_a_kind) } + let(:one_pair) { FactoryGirl.build(:one_pair) } describe '#deal_round' do subject { dealer.deal_round } @@ -13,53 +16,63 @@ end describe '#winner' do - let(:straight_flush) { - Poker::Hand.new([ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('3', 'Diamonds'), - Poker::Card.new('4', 'Diamonds'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('6', 'Diamonds'), - ]) - } before do dealer.deal_round end + it 'returns the hand of the winner' do dealer.instance_variable_set("@hands", [ straight_flush, - Poker::Hand.new([ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('8', 'Spades'), - Poker::Card.new('4', 'Hearts'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('2', 'Clubs'), - ]), - Poker::Hand.new([ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('2', 'Hearts'), - Poker::Card.new('2', 'Spades'), - Poker::Card.new('8', 'Diamonds'), - Poker::Card.new('5', 'Spades'), - ]), + one_pair, + three_of_a_kind, ]) expect(dealer.winner).to eq([straight_flush]) end + it 'returns a tie of winners' do dealer.instance_variable_set("@hands", [ straight_flush, straight_flush, - Poker::Hand.new([ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('2', 'Hearts'), - Poker::Card.new('2', 'Spades'), - Poker::Card.new('8', 'Diamonds'), - Poker::Card.new('5', 'Spades'), - ]), + three_of_a_kind, ]) expect(dealer.winner).to eq([straight_flush, straight_flush]) end + + context 'all hands have no matches' do + let(:hand) do + Poker::Hand.new( + [ + Poker::Card.new('3', 'Hearts'), + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('8', 'Spades'), + Poker::Card.new('5', 'Clubs'), + Poker::Card.new('Q', 'Diamonds'), + ] + ) + end + let(:hand2) do + Poker::Hand.new( + [ + Poker::Card.new('3', 'Hearts'), + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('8', 'Spades'), + Poker::Card.new('5', 'Clubs'), + Poker::Card.new('K', 'Diamonds'), + ] + ) + end + + it 'picks the hand with the highest card' do + dealer.instance_variable_set("@hands", [ + hand, + hand, + hand2 + ]) + + expect(dealer.winner).to eq([hand2]) + end + end end end From e06d69701bfa8dd3c39bacf3e7244849fbd28015 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 16:01:16 -0500 Subject: [PATCH 45/47] Fix errors in factories --- spec/factories/hand_factory.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/spec/factories/hand_factory.rb b/spec/factories/hand_factory.rb index 4eaa646..dd4c545 100644 --- a/spec/factories/hand_factory.rb +++ b/spec/factories/hand_factory.rb @@ -53,9 +53,9 @@ initialize_with do new( [ - Poker::Card.new('2', 'Spades'), + Poker::Card.new('2', 'Hearts'), Poker::Card.new('3', 'Hearts'), - Poker::Card.new('4', 'Hearts'), + Poker::Card.new('8', 'Hearts'), Poker::Card.new('5', 'Hearts'), Poker::Card.new('6', 'Hearts'), ] @@ -80,11 +80,13 @@ factory :straight_with_ace, class: Poker::Hand do initialize_with do new( - Poker::Card.new('A', 'Clubs'), - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('3', 'Diamonds'), - Poker::Card.new('4', 'Diamonds'), - Poker::Card.new('5', 'Diamonds'), + [ + Poker::Card.new('A', 'Clubs'), + Poker::Card.new('2', 'Diamonds'), + Poker::Card.new('3', 'Diamonds'), + Poker::Card.new('4', 'Diamonds'), + Poker::Card.new('5', 'Diamonds'), + ] ) end end From 394fd9df7d07128557b3c89662b7e350ca3aef68 Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 16:01:44 -0500 Subject: [PATCH 46/47] Refactor specs to be cleaner --- spec/poker/hand_spec.rb | 142 +++++----------------------------------- 1 file changed, 16 insertions(+), 126 deletions(-) diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index b097854..47d94b1 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -7,6 +7,7 @@ let(:full_house) { FactoryGirl.build(:full_house) } let(:flush) { FactoryGirl.build(:flush) } let(:straight) { FactoryGirl.build(:straight) } + let(:straight_with_ace) { FactoryGirl.build(:straight_with_ace) } let(:three_of_a_kind) { FactoryGirl.build(:three_of_a_kind) } let(:two_pair) { FactoryGirl.build(:two_pair) } let(:one_pair) { FactoryGirl.build(:one_pair) } @@ -15,15 +16,7 @@ subject { hand.straight_flush? } context 'all five cards are the same suit and they rank in a row' do - let(:cards) do - [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('3', 'Diamonds'), - Poker::Card.new('4', 'Diamonds'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('6', 'Diamonds'), - ] - end + let(:hand) { straight_flush } it { is_expected.to be_truthy } end @@ -59,17 +52,10 @@ describe '#four_of_a_kind?' do subject { hand.four_of_a_kind? } - let(:cards) { - [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('2', 'Spades'), - Poker::Card.new('2', 'Hearts'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('2', 'Clubs'), - ] - } context 'when there are four of the same rank' do + let(:hand) { four_of_a_kind } + it { is_expected.to be_truthy } end @@ -93,44 +79,20 @@ context 'when there are three cards of one rank' do context 'when the other two cards are the same rank' do - let(:cards) do - [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('2', 'Hearts'), - Poker::Card.new('2', 'Spades'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('5', 'Spades'), - ] - end + let(:hand) { full_house } it { is_expected.to be_truthy } end context 'when the other two cards are a different rank' do - let(:cards) do - [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('2', 'Hearts'), - Poker::Card.new('2', 'Spades'), - Poker::Card.new('8', 'Diamonds'), - Poker::Card.new('5', 'Spades'), - ] - end + let(:hand) { three_of_a_kind } it { is_expected.to be_falsey } end end context 'when there are not three cards of one rank' do - let(:cards) do - [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('2', 'Hearts'), - Poker::Card.new('4', 'Spades'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('5', 'Spades'), - ] - end + let(:hand) { one_pair } it { is_expected.to be_falsey } end @@ -141,15 +103,7 @@ subject { hand.flush? } context 'when all the cards are the same suit' do - let(:cards) do - [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('3', 'Diamonds'), - Poker::Card.new('4', 'Diamonds'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('6', 'Diamonds'), - ] - end + let(:hand) { flush } it { is_expected.to be_truthy } end @@ -173,15 +127,7 @@ subject { hand.straight? } context 'when cards rank in a row' do - let(:cards) do - [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('3', 'Diamonds'), - Poker::Card.new('4', 'Diamonds'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('6', 'Clubs'), - ] - end + let(:hand) { straight } it { is_expected.to be_truthy } end @@ -215,15 +161,7 @@ end context 'when Ace is involved and a straight' do - let(:cards) do - [ - Poker::Card.new('A', 'Clubs'), - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('3', 'Diamonds'), - Poker::Card.new('4', 'Diamonds'), - Poker::Card.new('5', 'Diamonds'), - ] - end + let(:hand) { straight_with_ace } it { is_expected.to be_truthy } end @@ -247,29 +185,13 @@ subject { hand.three_of_a_kind? } context 'when there are three of the same rank' do - let(:cards) { - [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('2', 'Spades'), - Poker::Card.new('4', 'Hearts'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('2', 'Clubs'), - ] - } + let(:hand) { three_of_a_kind } it { is_expected.to be_truthy } end context 'when there are not three of the same rank' do - let(:cards) { - [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('8', 'Spades'), - Poker::Card.new('4', 'Hearts'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('2', 'Clubs'), - ] - } + let(:hand) { straight } # straights cant have same rank it { is_expected.to be_falsey } end @@ -279,29 +201,13 @@ subject { hand.two_pair? } context 'when there are two different pairs in the hand' do - let(:cards) do - [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('3', 'Diamonds'), - Poker::Card.new('4', 'Diamonds'), - Poker::Card.new('3', 'Hearts'), - Poker::Card.new('2', 'Clubs'), - ] - end + let(:hand) { two_pair } it { is_expected.to be_truthy } end context 'when there is only one pair in the hand' do - let(:cards) do - [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('3', 'Diamonds'), - Poker::Card.new('4', 'Diamonds'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('2', 'Clubs'), - ] - end + let(:hand) { one_pair } it { is_expected.to be_falsey } end @@ -311,29 +217,13 @@ subject { hand.one_pair? } context 'when there are two of the same rank' do - let(:cards) do - [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('3', 'Diamonds'), - Poker::Card.new('4', 'Diamonds'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('2', 'Clubs'), - ] - end + let(:hand) { one_pair } it { is_expected.to be_truthy } end context 'when there are not two of the same rank' do - let(:cards) do - [ - Poker::Card.new('2', 'Diamonds'), - Poker::Card.new('3', 'Diamonds'), - Poker::Card.new('4', 'Diamonds'), - Poker::Card.new('5', 'Diamonds'), - Poker::Card.new('6', 'Clubs'), - ] - end + let(:hand) { straight } # straights cant have same rank it { is_expected.to be_falsey } end From 182bd8354521cab3d80aff03dcafaf9a5b09bd6d Mon Sep 17 00:00:00 2001 From: "Allison C. Reilly" Date: Fri, 9 Dec 2016 16:44:43 -0500 Subject: [PATCH 47/47] Add adjust_ace to sorted sets in case of low ace straight --- lib/poker/hand.rb | 11 ++++++++++- spec/poker/dealer_spec.rb | 15 +++++++++++++++ spec/poker/hand_spec.rb | 15 ++++++++++++++- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/lib/poker/hand.rb b/lib/poker/hand.rb index c1961bd..7cb08a8 100644 --- a/lib/poker/hand.rb +++ b/lib/poker/hand.rb @@ -75,7 +75,11 @@ def <=>(other_hand) def sorted_sets # &:reverse makes sure that the hash sorts by value first then key - @sets.sort_by(&:reverse).reverse.to_h.keys + @sorted_sets = @sets.sort_by(&:reverse).reverse.to_h.keys + + adjust_ace if ace_low_straight? + + @sorted_sets end private @@ -88,6 +92,11 @@ def ace_low_straight? sets.keys == [1, 2, 3, 4, 13] end + def adjust_ace + @sorted_sets.shift + @sorted_sets.push(0) + end + def sets sets = @cards.inject(Hash.new(0)) do |hash, card| hash[card.number_value] += 1 diff --git a/spec/poker/dealer_spec.rb b/spec/poker/dealer_spec.rb index 70dbb0d..28952ec 100644 --- a/spec/poker/dealer_spec.rb +++ b/spec/poker/dealer_spec.rb @@ -4,6 +4,8 @@ RSpec.describe Poker::Dealer, type: :model do let(:dealer) { Poker::Dealer.new(3) } let(:straight_flush) { FactoryGirl.build(:straight_flush) } + let(:straight) { FactoryGirl.build(:straight) } + let(:straight_with_ace) { FactoryGirl.build(:straight_with_ace) } let(:three_of_a_kind) { FactoryGirl.build(:three_of_a_kind) } let(:one_pair) { FactoryGirl.build(:one_pair) } @@ -74,5 +76,18 @@ expect(dealer.winner).to eq([hand2]) end end + + context 'with ace low straight and normal straight' do + + it 'picks the straight to win' do + dealer.instance_variable_set("@hands", [ + straight, + straight_with_ace, + one_pair, + ]) + + expect(dealer.winner).to eq([straight]) + end + end end end diff --git a/spec/poker/hand_spec.rb b/spec/poker/hand_spec.rb index 47d94b1..07bbd36 100644 --- a/spec/poker/hand_spec.rb +++ b/spec/poker/hand_spec.rb @@ -396,7 +396,10 @@ end it 'array equals sets highest key' do - expect(hand.sorted_sets[0]).to eq(hand.send(:sets).keys.last) + highest_sorted_key = hand.sorted_sets[0] + sets = highest_sets_key = hand.send(:sets).keys.last + + expect(highest_sorted_key).to eq(highest_sets_key) end end @@ -415,5 +418,15 @@ expect(hand.send(:sets)[second_highest]).to eq(2) end end + + context 'with ace low straight' do + let(:hand) { FactoryGirl.build(:straight_with_ace) } + + it 'matches the adjust ace low straight array' do + adj_ace_low_straight_array = [0, 1, 2, 3, 4] + + expect(hand.sorted_sets).to match_array(adj_ace_low_straight_array) + end + end end end