Add end of game status and winner

This commit is contained in:
Jesse C. Fisher 2015-11-07 18:05:11 -08:00
parent cbe99f180e
commit a75631552f
12 changed files with 91 additions and 57 deletions

View File

@ -4,26 +4,22 @@ Thirteen Tien Len
TODO TODO
---- ----
hide play / pass buttons of other players - rename `current_player(_id)` to `controlling_player(_id)`
code end game "winner" - graphics
disable "pass" when not your turn same as "play hand" is disabled - Test `play_hand` of run including face cards
graphics - BUG TODO: First player / lowest card holder should not be able to pass
Test play_hand of run including face cards
BUG TODO: First player / lowest card holder should not be able to pass
first play first play
Fix tests. They mostly pass when run individually. Explore if game_setup - Fix tests. They mostly pass when run individually. Explore if `game_setup`
is causing a bleedover between scenarios is causing a bleedover between scenarios
Bug: Players should not be able to pass outside of their turn. - Bug: Players should not be able to pass outside of their turn.
Validate play: play.player == game.current_player Validate play: play.player == game.current_player
Replace publicly displayed emails with usernames - Replace publicly displayed emails with usernames
## Proposed Schema ## Proposed Schema

View File

@ -91,7 +91,7 @@ var Game = React.createClass({
return ( return (
<div> <div>
<div>Title: {this.state.data.title}</div> <div>Title: {this.state.data.title}</div>
<div>Id: {this.props.id}</div> <div>Id: {this.state.data.id}</div>
<div>Current Player: {this.state.data.current_player_id}</div> <div>Current Player: {this.state.data.current_player_id}</div>
<div>Hand to beat: {this.state.data.play_to_beat_string}</div> <div>Hand to beat: {this.state.data.play_to_beat_string}</div>
<div className='player-list'> <div className='player-list'>
@ -99,7 +99,8 @@ var Game = React.createClass({
game_id={this.props.id} game_id={this.props.id}
players={this.state.data.players} players={this.state.data.players}
onPlayHandSubmit={this.handlePlayHandSubmit} onPlayHandSubmit={this.handlePlayHandSubmit}
current_player_id={this.state.data.current_player_id} /> current_player_id={this.state.data.current_player_id}
current_user_id={this.state.data.current_user_id} />
</div> </div>
<div> <div>
{/* TODO: If not joinable, show why. i.e. game full*/ } {/* TODO: If not joinable, show why. i.e. game full*/ }
@ -108,8 +109,7 @@ var Game = React.createClass({
{this.state.data.is_started ? null : <button onClick={this.handleStart} disabled={this.state.data.is_startable ? null : "disabled" }>Start</button>} {this.state.data.is_started ? null : <button onClick={this.handleStart} disabled={this.state.data.is_startable ? null : "disabled" }>Start</button>}
</div> </div>
<div> <div>
{console.log('is startable?')} {this.state.data.winner_player_id ? "Winner: " + this.state.data.winner_player_id : null}
{console.log(this.state.data.is_startable)}
</div> </div>
</div> </div>
); );

View File

@ -6,48 +6,22 @@ var Player = React.createClass({
render: function() { render: function() {
return ( return (
<div> <div style={{border: '1px solid', margin: '8px', padding: '8px'}}>
<div>Id: {this.props.id}</div> <div>Player Id: {this.props.id}</div>
<div>Email: {this.props.email}</div> <div>Email: {this.props.email}</div>
<div>Inventory count: {this.props.inventory_count}</div> <div>Inventory count: {this.props.inventory_count}</div>
<div>
<PlayerControls {/* Show player controls if player is owned by current_user */}
{this.props.user_id == this.props.current_user_id
? (<PlayerControls
key={this.props.id} key={this.props.id}
onPlayHandSubmit={this.props.onPlayHandSubmit} onPlayHandSubmit={this.props.onPlayHandSubmit}
game_id={this.props.game_id} game_id={this.props.game_id}
player_id={this.props.id} player_id={this.props.id}
inventory={this.props.inventory} inventory={this.props.inventory}
current_player_id={this.props.current_player_id} /> current_player_id={this.props.current_player_id} /> )
</div> : null }
</div> </div>
); );
} }
}); });
var PlayerList = React.createClass({
propTypes: {
players: React.PropTypes.array,
game_id: React.PropTypes.number
},
render: function() {
var playerList = this;
var playerNodes = this.props.players.map(function (player) {
return (
<Player
key={player.id}
onPlayHandSubmit={playerList.props.onPlayHandSubmit}
current_player_id={playerList.props.current_player_id}
game_id={playerList.props.game_id} {...player} />
);
});
return (
<div>
PlayerList:
{playerNodes}
</div>
);
}
});

View File

@ -34,6 +34,7 @@ var PlayerControls = React.createClass({
name="commit"> name="commit">
</input> </input>
<input id={"pass_hand_button_" + this.props.player_id} <input id={"pass_hand_button_" + this.props.player_id}
disabled={this.props.current_player_id == this.props.player_id ? null : 'disabled'}
type="submit" type="submit"
onClick={this.handlePass} onClick={this.handlePass}
value="Pass" value="Pass"

View File

@ -0,0 +1,29 @@
var PlayerList = React.createClass({
propTypes: {
players: React.PropTypes.array,
game_id: React.PropTypes.number
},
render: function() {
var playerList = this;
var playerNodes = this.props.players.map(function (player) {
return (
<Player
key={player.id}
onPlayHandSubmit={playerList.props.onPlayHandSubmit}
current_player_id={playerList.props.current_player_id}
current_user_id={playerList.props.current_user_id}
user_id={player.user_id}
game_id={playerList.props.game_id} {...player} />
);
});
return (
<div>
PlayerList:
{playerNodes}
</div>
);
}
});

View File

@ -119,4 +119,18 @@ class Game < ActiveRecord::Base
def player_to_beat def player_to_beat
self.play_to_beat.try(:play).try(:player) self.play_to_beat.try(:play).try(:player)
end end
def started?
!self.status.nil?
end
def over?
return false unless self.started?
@inventory_counts = []
self.players.each do |player|
@inventory_counts << player.inventory.count
end
@inventory_counts.include? 0
end
end end

View File

@ -9,6 +9,15 @@ class Play < ActiveRecord::Base
validate :hand_valid? validate :hand_valid?
after_save :update_play_to_beat after_save :update_play_to_beat
after_save :check_for_winner
def check_for_winner
if self.game.over?
self.game.winner_player_id = self.player.id
self.game.status = "Player #{self.player.id} wins!"
self.game.save
end
end
def update_play_to_beat def update_play_to_beat
if hand_valid? if hand_valid?

View File

@ -1,4 +1,4 @@
= react_component 'Game', id: @game.id, url: "#{game_path @game}" = react_component 'Game', url: "#{game_path @game}"
-# TODO: Remove deprecated commented out code -# TODO: Remove deprecated commented out code
-#%p -#%p

View File

@ -5,14 +5,18 @@ else
json.play_to_beat_string @game.play_to_beat.try(:play).try(:to_s) json.play_to_beat_string @game.play_to_beat.try(:play).try(:to_s)
end end
json.winner_player_id @game.winner_player_id
json.is_joinable @game.joinable?(current_user) json.is_joinable @game.joinable?(current_user)
json.is_started !@game.status.nil? json.is_started !@game.status.nil?
json.is_startable @game.startable? json.is_startable @game.startable?
json.current_user_id current_user.id
json.players @game.players do |player| json.players @game.players do |player|
json.id player.id json.id player.id
json.email player.user.email json.email player.user.email
json.inventory_count player.inventory.count json.inventory_count player.inventory.count
json.user_id player.user.id
if player.user == current_user if player.user == current_user
json.inventory player.inventory json.inventory player.inventory

View File

@ -0,0 +1,5 @@
class AddWinnerPlayerIdToGame < ActiveRecord::Migration
def change
add_column :games, :winner_player_id, :integer
end
end

View File

@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150810115450) do ActiveRecord::Schema.define(version: 20151107111235) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -23,6 +23,7 @@ ActiveRecord::Schema.define(version: 20150810115450) do
t.string "status" t.string "status"
t.integer "control_player_id" t.integer "control_player_id"
t.integer "play_to_beat_id" t.integer "play_to_beat_id"
t.integer "winner_player_id"
end end
add_index "games", ["play_to_beat_id"], name: "index_games_on_play_to_beat_id", using: :btree add_index "games", ["play_to_beat_id"], name: "index_games_on_play_to_beat_id", using: :btree

View File

@ -1,5 +1,5 @@
RSpec.describe Play, type: :model do RSpec.describe Play, type: :model do
before(:each) do before(:all) do
@game = setup_game @game = setup_game
@play = @game.current_player.plays.new @play = @game.current_player.plays.new
@play.game_id = @game.id @play.game_id = @game.id
@ -14,6 +14,7 @@ RSpec.describe Play, type: :model do
# reset play # reset play
@play.reload @play.reload
@play.errors[:player_cards].clear @play.errors[:player_cards].clear
@play.game = @game
end end
subject { @play } subject { @play }
@ -208,14 +209,14 @@ RSpec.describe Play, type: :model do
end end
it 'becomes the new play_to_beat' do it 'becomes the new play_to_beat' do
expect(@game.play_to_beat).to eq(nil) expect(@play.game.play_to_beat).to eq(nil)
# Play the hand # Play the hand
@cards_to_play = @game.current_player.inventory[0] @cards_to_play = @play.player.inventory.first
@play.hand << @cards_to_play @play.hand << @cards_to_play
expect(@play.hand_valid?).to eq(true) expect(@play.hand_valid?).to eq(true)
@game.reload expect(@play.save)
expect(@game.play_to_beat.play).to eq(@play) expect(@play.game.play_to_beat.play).to eq(@play)
end end
end end
end end