Another stash

This commit is contained in:
Jesse C. Fisher 2015-08-13 19:44:17 -07:00
parent 63ff0afb67
commit abffc4248d
4 changed files with 262 additions and 157 deletions

View File

@ -4,7 +4,7 @@ class Game < ActiveRecord::Base
has_many :users, through: :players has_many :users, through: :players
has_many :player_cards, through: :players has_many :player_cards, through: :players
has_many :plays, through: :players has_many :plays, through: :players
has_one :play_to_beat belongs_to :play_to_beat
accepts_nested_attributes_for :players accepts_nested_attributes_for :players
validates :title, presence: true validates :title, presence: true
@ -107,4 +107,8 @@ class Game < ActiveRecord::Base
def control_user def control_user
self.players.find(self.control_player_id).user self.players.find(self.control_player_id).user
end end
def hand_to_beat
self.play_to_beat.play.hand
end
end end

View File

@ -2,6 +2,7 @@ class Play < ActiveRecord::Base
belongs_to :game, foreign_key: 'game_id' belongs_to :game, foreign_key: 'game_id'
belongs_to :player, foreign_key: 'player_id' belongs_to :player, foreign_key: 'player_id'
has_many :player_cards, foreign_key: 'play_id' has_many :player_cards, foreign_key: 'play_id'
alias_attribute :hand, :player_cards
validates :game, presence: true validates :game, presence: true
validates :player, presence: true validates :player, presence: true
@ -15,26 +16,54 @@ class Play < ActiveRecord::Base
@pb.game = self.game @pb.game = self.game
@pb.play = self @pb.play = self
@pb.save @pb.save
self.game.play_to_beat = @pb
self.game.save!
end end
end end
# Validation methods # Validation methods
def hand_valid? def hand_valid?
@truths = []
if has_player_cards if has_player_cards
first_play?
# Open table / first play / no play to beat OR hand type matches OR play is back to the original active player @truths << !hand_type.empty?
self.game.play_to_beat == nil || self.hand_type == self.game.play_to_beat.play.hand_type || self.player == self.game.play_to_beat.player
if first_play?
@truths << contains_lowest_card?
end
# Is there a hand_to_beat ?
if self.game.play_to_beat
# current player is not the player to beat
if (self.game.play_to_beat.try('play').player != self.player)
@truths << (self.hand_type == self.game.play_to_beat.hand_type)
# Compare this hand to the hand_to_beat,
@truths << (self.beats? self.game.play_to_beat)
end
end
end end
return (!@truths.include? false)
end end
# TODO: Recognize all valid hand types # Check if the value of this hand is higher than the hand_to_beat
def beats?(play_to_beat)
@truth = self.high_card.value > play_to_beat.high_card.value
return @truth
end
def high_card
self.hand.order(:value).last
end
# TODO: Recognize face cards
def hand_type def hand_type
case self.player_cards.length case self.player_cards.length
when 1 when 1
@hand_type = 'single' @hand_type = 'single'
when 2 when 2
@hand_type = 'pair' @hand_type = 'double'
if (self.player_cards[0].rank != self.player_cards[1].rank) if (self.player_cards[0].rank != self.player_cards[1].rank)
errors.add(:player_cards, "Invalid pair. Rank must match.") errors.add(:player_cards, "Invalid pair. Rank must match.")
end end
@ -119,10 +148,19 @@ class Play < ActiveRecord::Base
def first_play? def first_play?
# First play of the game # First play of the game
if self.game.plays.empty? || ( self.game.plays.length == 1 && self.game.plays.first == self ) if self.game.plays.empty? || ( self.game.plays.length == 1 && self.game.plays.first == self )
# Cards being played must include the lowest card true
if (self.player_cards.include? self.game.lowest_card) == false else
errors.add(:player_cards, "First hand must contain the lowest card: #{game.lowest_card.to_s}") false
end end
end
def contains_lowest_card?
# Cards being played must include the lowest card
if (self.player_cards.include? self.game.lowest_card) == false
errors.add(:player_cards, "First hand must contain the lowest card: #{game.lowest_card.to_s}")
return false
else
return true
end end
end end

View File

@ -29,7 +29,8 @@
= "Me" if player.user == current_user = "Me" if player.user == current_user
// Show whose turn it is // Show whose turn it is
%strong= "My Turn " if @game.control_player == player - if @game.active_player_id
%strong= "My Turn " if @game.active_player == player
// Show the players' cards // Show the players' cards
- unless player.inventory.empty? - unless player.inventory.empty?
@ -46,11 +47,12 @@
- unless @game.status == nil - unless @game.status == nil
.table .table
- if @game.play_to_beat - if @game.play_to_beat
%h1 - if @game.play_to_beat.play
Hand to beat %h1
- @game.play_to_beat.play.player_cards.each do |card| Hand to beat
= card.to_s - @game.play_to_beat.play.player_cards.each do |card|
= @game.play_to_beat.play.player.user.email = card.to_s
= @game.play_to_beat.play.player.user.email
- else - else
%h1 Open table %h1 Open table

View File

@ -28,7 +28,7 @@ RSpec.describe Play, type: :model do
describe 'first_play' do describe 'first_play' do
context 'when there have been no plays yet' do context 'when there have been no plays yet' do
it 'valid if it contains the lowest card' do it 'valid if it contains the lowest card' do
#expect(@game.plays.count).to eq(1) # expect(@game.plays.count).to eq(1)
# Active player is the lowest card holder # Active player is the lowest card holder
expect(@game.current_player).to eq(@game.lowest_card.player) expect(@game.current_player).to eq(@game.lowest_card.player)
# Play the lowest card # Play the lowest card
@ -36,158 +36,219 @@ RSpec.describe Play, type: :model do
@play.player_cards << @cards_to_play @play.player_cards << @cards_to_play
@play.save @play.save
expect(@play.player_cards.include? @game.lowest_card).to eq true expect(@play.player_cards.include? @game.lowest_card).to eq true
expect(@game.play_to_beat.play).to eq subject #expect(@game.play_to_beat.play).to eq subject
expect(subject.valid?).to eq(true)
end
end
end
describe 'wins?' do
context 'valid if it beats the hand_to_beat' do
it 'single' do
@play_to_beat = Play.new
@play_to_beat.player = @game.players.last
@play_to_beat.game = @game
@play_to_beat.player_cards << @play_to_beat.player.player_cards.order(:value).first
@play_to_beat.save
@cards_to_play = @play.player.player_cards.order(:value).last
@play.player_cards << @cards_to_play
@play.save
expect(@play.valid?).to eq(true)
expect(@play.errors[:player_cards]).to eq([])
end
it 'double' do
@deck = Deck.new
@cards_to_beat = [
@spade3 = PlayerCard.new(@deck.cards[0].instance_values),
@club3 = PlayerCard.new(@deck.cards[1].instance_values)
]
@play_to_beat = Play.new
@play_to_beat.player = @game.players.first
@play_to_beat.player_cards << @cards_to_beat
@play_to_beat.game = @game
@play_to_beat.save
@play.player_cards = [
@spade4 = PlayerCard.new(@deck.cards[4].instance_values),
@club4 = PlayerCard.new(@deck.cards[5].instance_values)
]
# Shared tests
[@play_to_beat,@play].each do |play|
expect(play.errors[:player_cards]).to eq([])
expect(play.valid?).to eq(true)
puts play
expect(play.player_cards.count).to eq(2)
expect(play.hand_type).to eq('double')
end
expect(@play.beats? @play_to_beat).to eq(true)
end end
end end
end end
describe 'hand_type' do it 'becomes the new play_to_beat' do
context 'when a single card is played' do expect(@game.play_to_beat).to eq(nil)
it 'single' do # Play the hand
@cards_to_play = @game.current_player.player_cards.order(:value).first @cards_to_play = @game.current_player.inventory[0]
@play.player_cards << @cards_to_play @play.hand << @cards_to_play
expect(@play.hand_type).to eq('single') @play.save
end expect(@play.hand_valid?).to eq(true)
end @game.reload
expect(@game.play_to_beat.play).to eq(@play)
end
context 'when two cards are played' do end
it 'valid pair' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club3 = PlayerCard.new(rank: "3", suit: "Club")
@cards_to_play = [@spade3, @club3]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('pair')
expect(@play.errors[:player_cards]).to eq([])
end
it 'invalid pair' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club4 = PlayerCard.new(rank: "4", suit: "Club")
@cards_to_play = [@spade3, @club4]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('pair')
expect(@play.errors[:player_cards]).to eq(['Invalid pair. Rank must match.'])
end
end
context 'when three cards are played' do describe 'hand_type' do
it 'valid triple' do context 'when a single card is played' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade") it 'single' do
@club3 = PlayerCard.new(rank: "3", suit: "Club") @cards_to_play = @game.current_player.player_cards.order(:value).first
@diamond3 = PlayerCard.new(rank: "3", suit: "Diamond") @play.player_cards << @cards_to_play
@cards_to_play = [@spade3, @club3, @diamond3] expect(@play.hand_type).to eq('single')
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('triple')
end
it 'invalid triple' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club3 = PlayerCard.new(rank: "3", suit: "Club")
@diamond4 = PlayerCard.new(rank: "4", suit: "Diamond")
@cards_to_play = [@spade3, @club3, @diamond4]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('triple')
expect(@play.errors[:player_cards]).to eq(['Invalid triple. Rank must match.'])
end
it 'valid run of 3' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club4 = PlayerCard.new(rank: "4", suit: "Club")
@diamond5 = PlayerCard.new(rank: "5", suit: "Diamond")
@cards_to_play = [@spade3, @club4, @diamond5]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('triple run')
end
it 'valid run of 3 suited' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club4 = PlayerCard.new(rank: "4", suit: "Spade")
@diamond5 = PlayerCard.new(rank: "5", suit: "Spade")
@cards_to_play = [@spade3, @club4, @diamond5]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('triple run suited')
end
end end
end
context 'when four cards are played' do context 'when two cards are played' do
it 'valid bomb' do it 'valid pair' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade") @spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club3 = PlayerCard.new(rank: "3", suit: "Club") @club3 = PlayerCard.new(rank: "3", suit: "Club")
@diamond3 = PlayerCard.new(rank: "3", suit: "Diamond") @cards_to_play = [@spade3, @club3]
@heart3 = PlayerCard.new(rank: "3", suit: "Heart") @play.player_cards << @cards_to_play
@cards_to_play = [@spade3, @club3, @diamond3, @heart3] expect(@play.hand_type).to eq('double')
@play.player_cards << @cards_to_play expect(@play.errors[:player_cards]).to eq([])
expect(@play.hand_type).to eq('bomb')
end
it 'valid run of 4' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club4 = PlayerCard.new(rank: "4", suit: "Club")
@diamond5 = PlayerCard.new(rank: "5", suit: "Diamond")
@diamond6 = PlayerCard.new(rank: "6", suit: "Diamond")
@cards_to_play = [@spade3, @club4, @diamond5, @diamond6]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('run of 4')
end
it 'valid run of 4 suited' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club4 = PlayerCard.new(rank: "4", suit: "Spade")
@diamond5 = PlayerCard.new(rank: "5", suit: "Spade")
@diamond6 = PlayerCard.new(rank: "6", suit: "Spade")
@cards_to_play = [@spade3, @club4, @diamond5, @diamond6]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('run of 4 suited')
end
end end
it 'invalid pair' do
context 'when five cards are played' do @spade3 = PlayerCard.new(rank: "3", suit: "Spade")
it 'valid run of 5' do @club4 = PlayerCard.new(rank: "4", suit: "Club")
@spade3 = PlayerCard.new(rank: "3", suit: "Spade") @cards_to_play = [@spade3, @club4]
@club4 = PlayerCard.new(rank: "4", suit: "Club") @play.player_cards << @cards_to_play
@diamond5 = PlayerCard.new(rank: "5", suit: "Diamond") expect(@play.hand_type).to eq('double')
@diamond6 = PlayerCard.new(rank: "6", suit: "Diamond") expect(@play.errors[:player_cards]).to eq(['Invalid pair. Rank must match.'])
@diamond7 = PlayerCard.new(rank: "7", suit: "Diamond")
@cards_to_play = [@spade3, @club4, @diamond5, @diamond6, @diamond7]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('run of 5')
end
it 'invalid run of 5' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club4 = PlayerCard.new(rank: "4", suit: "Club")
@diamond5 = PlayerCard.new(rank: "5", suit: "Diamond")
@diamond6 = PlayerCard.new(rank: "6", suit: "Diamond")
@diamond8 = PlayerCard.new(rank: "8", suit: "Diamond")
@cards_to_play = [@spade3, @club4, @diamond5, @diamond6, @diamond8]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('run of 5')
expect(@play.errors[:player_cards]).to eq(['Invalid run of 5'])
end
it 'valid run of 5 suited' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club4 = PlayerCard.new(rank: "4", suit: "Spade")
@diamond5 = PlayerCard.new(rank: "5", suit: "Spade")
@diamond6 = PlayerCard.new(rank: "6", suit: "Spade")
@diamond7 = PlayerCard.new(rank: "7", suit: "Spade")
@cards_to_play = [@spade3, @club4, @diamond5, @diamond6, @diamond7]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('run of 5 suited')
end
end end
end
(5..13).each do |i| context 'when three cards are played' do
context "when #{i} cards are played" do it 'valid triple' do
it "run of #{i}" do @spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@cards_to_play = create_hand(i, 'run') @club3 = PlayerCard.new(rank: "3", suit: "Club")
@diamond3 = PlayerCard.new(rank: "3", suit: "Diamond")
@cards_to_play = [@spade3, @club3, @diamond3]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('triple')
end
it 'invalid triple' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club3 = PlayerCard.new(rank: "3", suit: "Club")
@diamond4 = PlayerCard.new(rank: "4", suit: "Diamond")
@cards_to_play = [@spade3, @club3, @diamond4]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('triple')
expect(@play.errors[:player_cards]).to eq(['Invalid triple. Rank must match.'])
end
it 'valid run of 3' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club4 = PlayerCard.new(rank: "4", suit: "Club")
@diamond5 = PlayerCard.new(rank: "5", suit: "Diamond")
@cards_to_play = [@spade3, @club4, @diamond5]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('triple run')
end
it 'valid run of 3 suited' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club4 = PlayerCard.new(rank: "4", suit: "Spade")
@diamond5 = PlayerCard.new(rank: "5", suit: "Spade")
@cards_to_play = [@spade3, @club4, @diamond5]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('triple run suited')
end
end
context 'when four cards are played' do
it 'valid bomb' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club3 = PlayerCard.new(rank: "3", suit: "Club")
@diamond3 = PlayerCard.new(rank: "3", suit: "Diamond")
@heart3 = PlayerCard.new(rank: "3", suit: "Heart")
@cards_to_play = [@spade3, @club3, @diamond3, @heart3]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('bomb')
end
it 'valid run of 4' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club4 = PlayerCard.new(rank: "4", suit: "Club")
@diamond5 = PlayerCard.new(rank: "5", suit: "Diamond")
@diamond6 = PlayerCard.new(rank: "6", suit: "Diamond")
@cards_to_play = [@spade3, @club4, @diamond5, @diamond6]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('run of 4')
end
it 'valid run of 4 suited' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club4 = PlayerCard.new(rank: "4", suit: "Spade")
@diamond5 = PlayerCard.new(rank: "5", suit: "Spade")
@diamond6 = PlayerCard.new(rank: "6", suit: "Spade")
@cards_to_play = [@spade3, @club4, @diamond5, @diamond6]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('run of 4 suited')
end
end
context 'when five cards are played' do
it 'valid run of 5' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club4 = PlayerCard.new(rank: "4", suit: "Club")
@diamond5 = PlayerCard.new(rank: "5", suit: "Diamond")
@diamond6 = PlayerCard.new(rank: "6", suit: "Diamond")
@diamond7 = PlayerCard.new(rank: "7", suit: "Diamond")
@cards_to_play = [@spade3, @club4, @diamond5, @diamond6, @diamond7]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('run of 5')
end
it 'invalid run of 5' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club4 = PlayerCard.new(rank: "4", suit: "Club")
@diamond5 = PlayerCard.new(rank: "5", suit: "Diamond")
@diamond6 = PlayerCard.new(rank: "6", suit: "Diamond")
@diamond8 = PlayerCard.new(rank: "8", suit: "Diamond")
@cards_to_play = [@spade3, @club4, @diamond5, @diamond6, @diamond8]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('run of 5')
expect(@play.errors[:player_cards]).to eq(['Invalid run of 5'])
end
it 'valid run of 5 suited' do
@spade3 = PlayerCard.new(rank: "3", suit: "Spade")
@club4 = PlayerCard.new(rank: "4", suit: "Spade")
@diamond5 = PlayerCard.new(rank: "5", suit: "Spade")
@diamond6 = PlayerCard.new(rank: "6", suit: "Spade")
@diamond7 = PlayerCard.new(rank: "7", suit: "Spade")
@cards_to_play = [@spade3, @club4, @diamond5, @diamond6, @diamond7]
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq('run of 5 suited')
end
end
(5..13).each do |i|
context "when #{i} cards are played" do
it "run of #{i}" do
@cards_to_play = create_hand(i, 'run')
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq("run of #{i}")
end
it "run of #{i} suited" do
@cards_to_play = create_hand(i, 'run suited')
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq("run of #{i} suited")
end
if [6, 8, 10].include? i
it "double run of #{i}" do
@cards_to_play = create_hand(i, 'double run')
@play.player_cards << @cards_to_play @play.player_cards << @cards_to_play
expect(@play.hand_type).to eq("run of #{i}") expect(@play.hand_type).to eq("double run of #{i}")
end expect(@play.errors[:player_cards]).to eq([])
it "run of #{i} suited" do
@cards_to_play = create_hand(i, 'run suited')
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq("run of #{i} suited")
end
if [6, 8, 10].include? i
it "double run of #{i}" do
@cards_to_play = create_hand(i, 'double run')
@play.player_cards << @cards_to_play
expect(@play.hand_type).to eq("double run of #{i}")
expect(@play.errors[:player_cards]).to eq([])
end
end end
end end
end end