Add winner feature to games
This commit is contained in:
parent
c0d84b30ba
commit
eb2c38c9d3
@ -7,6 +7,7 @@ class Game < ActiveRecord::Base
|
|||||||
has_many :player_cards, through: :players
|
has_many :player_cards, through: :players
|
||||||
has_many :plays, through: :players
|
has_many :plays, through: :players
|
||||||
has_one :controlling_player
|
has_one :controlling_player
|
||||||
|
has_one :winner, :class_name => "Player", :primary_key => "winner_player_id"
|
||||||
belongs_to :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
|
||||||
|
|||||||
@ -7,9 +7,11 @@ class Play < ActiveRecord::Base
|
|||||||
validates :game, presence: true
|
validates :game, presence: true
|
||||||
validates :player, presence: true
|
validates :player, presence: true
|
||||||
validate :hand_valid?
|
validate :hand_valid?
|
||||||
|
validate :player_has_control?
|
||||||
|
|
||||||
after_save :update_play_to_beat
|
|
||||||
after_save :check_for_winner
|
after_save :check_for_winner
|
||||||
|
after_save :update_play_to_beat
|
||||||
|
after_save :set_controlling_player
|
||||||
|
|
||||||
def check_for_winner
|
def check_for_winner
|
||||||
if self.game.over?
|
if self.game.over?
|
||||||
@ -30,8 +32,22 @@ class Play < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_controlling_player
|
||||||
|
self.game.set_controlling_player 'next'
|
||||||
|
self.game.save
|
||||||
|
end
|
||||||
|
|
||||||
# Validation methods
|
# Validation methods
|
||||||
|
|
||||||
|
def player_has_control?
|
||||||
|
if self.player == self.game.controlling_player
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
errors.add(:player, "it's not your turn")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def hand_valid?
|
def hand_valid?
|
||||||
return false if self.hand_type == nil
|
return false if self.hand_type == nil
|
||||||
# Gather the truths about the hand
|
# Gather the truths about the hand
|
||||||
|
|||||||
@ -18,4 +18,17 @@ class Player < ActiveRecord::Base
|
|||||||
self.try(:user).try(:email) || "Guest#{self.soft_token[0..5]}"
|
self.try(:user).try(:email) || "Guest#{self.soft_token[0..5]}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def play_hand(cards)
|
||||||
|
self.plays.create(game_id: self.game.id, player_cards: cards)
|
||||||
|
end
|
||||||
|
|
||||||
|
def pass
|
||||||
|
#TODO: Create a Play instead of modifying the controlling player directly
|
||||||
|
# Then you won't need this return/fail validation
|
||||||
|
return false unless self.game.controlling_player == self
|
||||||
|
|
||||||
|
self.game.set_controlling_player 'next'
|
||||||
|
self.game.save
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -20,6 +20,10 @@ class User < ActiveRecord::Base
|
|||||||
self.email || "Guest#{self.soft_token[0..5]}"
|
self.email || "Guest#{self.soft_token[0..5]}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sit_in(seat)
|
||||||
|
seat.sit self
|
||||||
|
end
|
||||||
|
|
||||||
def stand_from(table)
|
def stand_from(table)
|
||||||
@seats = []
|
@seats = []
|
||||||
if self.id
|
if self.id
|
||||||
|
|||||||
43
spec/features/end_of_games_spec.rb
Normal file
43
spec/features/end_of_games_spec.rb
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.feature "EndOfGames", type: :feature, js: true do
|
||||||
|
# Given I am in a started game
|
||||||
|
before do
|
||||||
|
@game = setup_game
|
||||||
|
@game.reload
|
||||||
|
@player = @game.controlling_player
|
||||||
|
signin(@player.user.email,'password')
|
||||||
|
visit table_path @game.table
|
||||||
|
end
|
||||||
|
# And it is my turn
|
||||||
|
# And I play my last cards
|
||||||
|
# Then I win the game
|
||||||
|
scenario 'I win the game' do
|
||||||
|
|
||||||
|
# Play lowest card
|
||||||
|
# Other players always pass
|
||||||
|
# Play next lowest card
|
||||||
|
# Repeat until out of cards
|
||||||
|
@player.inventory.each do |card|
|
||||||
|
find_card(card).click
|
||||||
|
click_button "Play Hand"
|
||||||
|
sleep 1
|
||||||
|
visit current_url
|
||||||
|
@game.reload
|
||||||
|
@game.controlling_player_id = @player.id
|
||||||
|
@game.save
|
||||||
|
@game.reload
|
||||||
|
sleep 1
|
||||||
|
visit current_url
|
||||||
|
end
|
||||||
|
|
||||||
|
# Play my last card(s)
|
||||||
|
# Expect that I am the winner
|
||||||
|
expect(@game.winner).to eq @player
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'I lose the game' do
|
||||||
|
# Another player plays their last card(s)
|
||||||
|
# Expect that they are the winner
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -11,14 +11,35 @@ RSpec.describe Game, type: :model do
|
|||||||
|
|
||||||
it { should respond_to(:title) }
|
it { should respond_to(:title) }
|
||||||
it { should respond_to(:play_to_beat) }
|
it { should respond_to(:play_to_beat) }
|
||||||
|
it { should respond_to(:winner) }
|
||||||
|
|
||||||
it '#title returns a string' do
|
it '#title returns a string' do
|
||||||
expect(@game.title).to match 'Test Game'
|
expect(@game.title).to match 'Test Game'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'has a winner' do
|
||||||
|
# Start the game
|
||||||
|
@player1 = @user1.sit_in(@game.seats.first)
|
||||||
|
@player2 = @user2.sit_in(@game.seats.last)
|
||||||
|
@game.start
|
||||||
|
|
||||||
|
# controlling player plays all their cards
|
||||||
|
@player = @game.controlling_player
|
||||||
|
@player.inventory.each do |card|
|
||||||
|
@player.play_hand [card]
|
||||||
|
@game.reload
|
||||||
|
while (@game.controlling_player != @player) do
|
||||||
|
@game.controlling_player.pass
|
||||||
|
@game.reload
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(@game.winner).to eq @player
|
||||||
|
end
|
||||||
|
|
||||||
describe 'validations' do
|
describe 'validations' do
|
||||||
describe 'player_count' do
|
describe 'player_count' do
|
||||||
context 'when there are between 2 and 4 players' do
|
context 'when there are 2 to 4 players' do
|
||||||
it 'is startable' do
|
it 'is startable' do
|
||||||
@game.add_player_from_user(@user1)
|
@game.add_player_from_user(@user1)
|
||||||
@game.add_player_from_user(@user2)
|
@game.add_player_from_user(@user2)
|
||||||
|
|||||||
@ -3,3 +3,6 @@ require 'rails_helper'
|
|||||||
RSpec.describe Player, type: :model do
|
RSpec.describe Player, type: :model do
|
||||||
pending "add some examples to (or delete) #{__FILE__}"
|
pending "add some examples to (or delete) #{__FILE__}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#TODO: Player can play_hand cards
|
||||||
|
#TODO: Player can not play_hand if not game.controlling_player
|
||||||
|
|||||||
@ -47,4 +47,6 @@ RSpec.configure do |config|
|
|||||||
# The different available types are documented in the features, such as in
|
# The different available types are documented in the features, such as in
|
||||||
# https://relishapp.com/rspec/rspec-rails/docs
|
# https://relishapp.com/rspec/rspec-rails/docs
|
||||||
config.infer_spec_type_from_file_location!
|
config.infer_spec_type_from_file_location!
|
||||||
|
|
||||||
|
config.include GameHelpers
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,4 +1,52 @@
|
|||||||
|
module GameHelpers
|
||||||
|
def setup_game
|
||||||
|
# Default game has 4 players
|
||||||
|
game = FactoryGirl.create :game
|
||||||
|
user1 = FactoryGirl.create :user
|
||||||
|
user2 = FactoryGirl.create :user
|
||||||
|
user3 = FactoryGirl.create :user
|
||||||
|
user4 = FactoryGirl.create :user
|
||||||
|
game.seats[0].sit user1
|
||||||
|
game.seats[1].sit user2
|
||||||
|
game.seats[2].sit user3
|
||||||
|
game.seats[3].sit user4
|
||||||
|
game.start
|
||||||
|
return game
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup_visitor_game
|
||||||
|
# Default game has 3 players
|
||||||
|
game = FactoryGirl.create :game
|
||||||
|
|
||||||
|
u = FactoryGirl.build :user
|
||||||
|
game.seats[0].sit u
|
||||||
|
|
||||||
|
u = FactoryGirl.build :user
|
||||||
|
game.seats[1].sit u
|
||||||
|
|
||||||
|
u = FactoryGirl.build :user
|
||||||
|
game.seats[2].sit u
|
||||||
|
|
||||||
|
return game
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_card card
|
||||||
|
find("[data-card-name='#{card.to_s}'] ~ img")
|
||||||
|
end
|
||||||
|
|
||||||
|
def cards_to_beat
|
||||||
|
@cards = find("#cards-to-beat")
|
||||||
|
if @cards
|
||||||
|
@cards = @cards.find_all('img')
|
||||||
|
end
|
||||||
|
@array = []
|
||||||
|
@cards.map {|c| @array << c[:alt]}
|
||||||
|
return @array.join " "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
module Features
|
module Features
|
||||||
|
#DEPRECATED Features module. Use top level GameHelpers
|
||||||
module GameHelpers
|
module GameHelpers
|
||||||
def setup_game
|
def setup_game
|
||||||
# Default game has 4 players
|
# Default game has 4 players
|
||||||
@ -47,6 +95,7 @@ module Features
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# DEPRECATED Models module. Use top level GameHelpers
|
||||||
# TODO: DRY up this repetition
|
# TODO: DRY up this repetition
|
||||||
module Models
|
module Models
|
||||||
module GameHelpers
|
module GameHelpers
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user