Play hand validations

This commit is contained in:
Jesse C. Fisher 2015-08-17 13:40:20 -07:00
parent 5f2952ccb5
commit 2c678b1a9d
5 changed files with 148 additions and 47 deletions

View File

@ -23,13 +23,20 @@ class GamesController < ApplicationController
def play_hand
# TODO: validate player's turn, current_user == @game.current_player.user
# TODO: move this logic out of controller maybe to model(s)
@cards_to_play = @game.current_player.player_cards.find(params[:player_card_ids])
# If cards are played
if params[:player_card_ids]
@cards_to_play = @game.current_player.player_cards.order(:value).find(params[:player_card_ids])
else
# No cards are played
@cards_to_play = []
end
# Instantiate the play
@play = @game.current_player.plays.new
@play.game_id = @game.id
@play.save
@play.player_cards << @cards_to_play
@play.save
#@cards_to_play.each do |card|
#@play.player_cards << card
@ -41,12 +48,12 @@ class GamesController < ApplicationController
@game.save
else
# If play is invalid, remove the cards from the play
@play.player_cards.map {|card| card.play_id = nil; card.save}
#@play.player_cards.map {|card| card.play_id = nil; card.save}
# Delete play
@play.destroy
#@play.destroy
end
@play.save
#@play.save
@play.errors.messages.each do |key, msg|
flash[key] = msg.join
end

View File

@ -111,4 +111,8 @@ class Game < ActiveRecord::Base
def hand_to_beat
self.play_to_beat.play.hand
end
def player_to_beat
self.play_to_beat.play.player unless self.play_to_beat.play.nil?
end
end

View File

@ -26,6 +26,16 @@ class Play < ActiveRecord::Base
def hand_valid?
@truths = []
# Is there a hand_to_beat ?
if self.game.play_to_beat
# current player is not the player to beat
if (self.game.player_to_beat != self.player)
@truths << (self.hand_type == self.game.play_to_beat.play.hand_type)
# Compare this hand to the hand_to_beat,
@truths << (self.beats? self.game.play_to_beat.play)
end
end
if has_player_cards
@truths << !hand_type.empty?
@ -34,27 +44,26 @@ class Play < ActiveRecord::Base
@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
if @truths.include? false
errors.add(:player_cards, "invalid hand")
end
return (!@truths.include? false)
end
# 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
@truth = self.high_card_value > play_to_beat.high_card_value
return @truth
end
def high_card
self.hand.order(:value).last
self.hand.last unless self.hand.empty?
end
def high_card_value
return self.hand.last.value unless self.hand.empty?
0
end
# TODO: Recognize face cards
@ -167,4 +176,9 @@ class Play < ActiveRecord::Base
def has_player_cards
true unless self.player_cards.empty?
end
def to_s
player_cards.join ' '
end
end

View File

@ -1,5 +1,3 @@
require 'rails_helper'
RSpec.describe Play, type: :model do
before(:each) do
@game = FactoryGirl.create(:game)
@ -17,32 +15,107 @@ RSpec.describe Play, type: :model do
subject { @play }
it { should respond_to(:game_id) }
it { should respond_to(:game) }
it { should respond_to(:player_id) }
it { should respond_to(:player) }
it { should respond_to(:player_cards) }
it { should respond_to(:hand) }
it { should respond_to(:hand_type) }
it { should respond_to(:to_s) }
it '#game_id returns an integer' do
expect(@play.game_id).to match @game.id
it '#game_id returns a game id' do
expect(@play.game).to eq Game.find(@play.game_id)
end
it '#player_id return a player id' do
expect(@play.player).to eq Player.find(@play.player_id)
end
it '#player_cards returns a PlayerCard collection' do
expect(@play.player_cards.class).to eq(PlayerCard::ActiveRecord_Associations_CollectionProxy)
end
it '#hand returns a PlayerCard collection' do
expect(@play.hand.class).to eq(PlayerCard::ActiveRecord_Associations_CollectionProxy)
end
it '#hand_type returns a string' do
@play.player_cards << create_hand(1, 'single')
expect(@play.hand_type).to eq 'single'
end
it '#to_s returns a string of the hand' do
@play.player_cards << create_hand(1, 'single')
expect(@play.to_s).to eq '3 Spade'
end
describe 'validations' do
describe 'first_play' do
context 'when there have been no plays yet' do
it 'valid if it contains the lowest card' do
# expect(@game.plays.count).to eq(1)
# Active player is the lowest card holder
expect(@game.current_player).to eq(@game.lowest_card.player)
# Play the lowest card
@cards_to_play = @game.current_player.player_cards.order(:value).first
@play.player_cards << @cards_to_play
@play.save
expect(@play.player_cards.include? @game.lowest_card).to eq true
#expect(@game.play_to_beat.play).to eq subject
expect(subject.valid?).to eq(true)
end
it 'valid if it contains the lowest card' do
# expect(@game.plays.count).to eq(1)
# Active player is the lowest card holder
expect(@game.current_player).to eq(@game.lowest_card.player)
# Play the lowest card
@cards_to_play = @game.current_player.player_cards.order(:value).first
@play.player_cards << @cards_to_play
@play.save
expect(@play.player_cards.include? @game.lowest_card).to eq true
expect(subject.valid?).to eq(true)
end
end
describe 'wins?' do
context 'valid if it beats the hand_to_beat' do
context 'it does not beat the hand_to_beat' do
it 'single' do
@play_to_beat = Play.new
@play_to_beat.player = @game.players.where.not(id: @game.active_player.id).last
@play_to_beat.game = @game
@play_to_beat.player_cards << @play_to_beat.player.player_cards.order(:value).last
@play_to_beat.save
@play.game.reload
expect(@play.game.play_to_beat.play).to eq(@play_to_beat)
# Losing card
@cards_to_play = @play.player.player_cards.order(:value).first
@play.player_cards << @cards_to_play
@play.save
expect(@game.player_to_beat).to_not eq(@play.player)
expect(@play.hand_valid?).to eq(false)
expect(@play.errors[:player_cards].include?('invalid hand')).to eq(true)
end
it 'double' do
@deck = Deck.new
@cards_to_beat = [
@spade5 = PlayerCard.new(@deck.cards[8].instance_values),
@club5 = PlayerCard.new(@deck.cards[9].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)
expect(play.player_cards.count).to eq(2)
expect(play.hand_type).to eq('double')
end
expect(@play.beats? @play_to_beat).to eq(false)
end
end
context 'it beats the hand_to_beat' do
it 'single' do
@play_to_beat = Play.new
@play_to_beat.player = @game.players.last
@ -79,7 +152,6 @@ RSpec.describe Play, type: :model do
[@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
@ -87,20 +159,19 @@ RSpec.describe Play, type: :model do
expect(@play.beats? @play_to_beat).to eq(true)
end
it 'becomes the new play_to_beat' do
expect(@game.play_to_beat).to eq(nil)
# Play the hand
@cards_to_play = @game.current_player.inventory[0]
@play.hand << @cards_to_play
@play.save
expect(@play.hand_valid?).to eq(true)
@game.reload
expect(@game.play_to_beat.play).to eq(@play)
end
end
end
it 'becomes the new play_to_beat' do
expect(@game.play_to_beat).to eq(nil)
# Play the hand
@cards_to_play = @game.current_player.inventory[0]
@play.hand << @cards_to_play
@play.save
expect(@play.hand_valid?).to eq(true)
@game.reload
expect(@game.play_to_beat.play).to eq(@play)
end
end
describe 'hand_type' do
@ -254,4 +325,5 @@ RSpec.describe Play, type: :model do
end
end
end
end

View File

@ -7,6 +7,9 @@ module Models
end
case type
when /single/
cards[0].rank = Card::RANKS[0]
cards[0].suit = Card::SUITS[0]
when /run/
cards.each.with_index(3) do |c, i|
@ -26,6 +29,7 @@ module Models
end
end
return cards
end
end
end