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
----
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
Test play_hand of run including face cards
BUG TODO: First player / lowest card holder should not be able to pass
- BUG TODO: First player / lowest card holder should not be able to pass
first play
Fix tests. They mostly pass when run individually. Explore if game_setup
is causing a bleedover between scenarios
- Fix tests. They mostly pass when run individually. Explore if `game_setup`
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
Replace publicly displayed emails with usernames
- Replace publicly displayed emails with usernames
## Proposed Schema

View File

@ -91,7 +91,7 @@ var Game = React.createClass({
return (
<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>Hand to beat: {this.state.data.play_to_beat_string}</div>
<div className='player-list'>
@ -99,7 +99,8 @@ var Game = React.createClass({
game_id={this.props.id}
players={this.state.data.players}
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>
{/* 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>}
</div>
<div>
{console.log('is startable?')}
{console.log(this.state.data.is_startable)}
{this.state.data.winner_player_id ? "Winner: " + this.state.data.winner_player_id : null}
</div>
</div>
);

View File

@ -6,48 +6,22 @@ var Player = React.createClass({
render: function() {
return (
<div>
<div>Id: {this.props.id}</div>
<div style={{border: '1px solid', margin: '8px', padding: '8px'}}>
<div>Player Id: {this.props.id}</div>
<div>Email: {this.props.email}</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}
onPlayHandSubmit={this.props.onPlayHandSubmit}
game_id={this.props.game_id}
player_id={this.props.id}
inventory={this.props.inventory}
current_player_id={this.props.current_player_id} />
</div>
current_player_id={this.props.current_player_id} /> )
: null }
</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">
</input>
<input id={"pass_hand_button_" + this.props.player_id}
disabled={this.props.current_player_id == this.props.player_id ? null : 'disabled'}
type="submit"
onClick={this.handlePass}
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
self.play_to_beat.try(:play).try(:player)
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

View File

@ -9,6 +9,15 @@ class Play < ActiveRecord::Base
validate :hand_valid?
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
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
-#%p

View File

@ -5,14 +5,18 @@ else
json.play_to_beat_string @game.play_to_beat.try(:play).try(:to_s)
end
json.winner_player_id @game.winner_player_id
json.is_joinable @game.joinable?(current_user)
json.is_started !@game.status.nil?
json.is_startable @game.startable?
json.current_user_id current_user.id
json.players @game.players do |player|
json.id player.id
json.email player.user.email
json.inventory_count player.inventory.count
json.user_id player.user.id
if player.user == current_user
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.
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
enable_extension "plpgsql"
@ -23,6 +23,7 @@ ActiveRecord::Schema.define(version: 20150810115450) do
t.string "status"
t.integer "control_player_id"
t.integer "play_to_beat_id"
t.integer "winner_player_id"
end
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
before(:each) do
before(:all) do
@game = setup_game
@play = @game.current_player.plays.new
@play.game_id = @game.id
@ -14,6 +14,7 @@ RSpec.describe Play, type: :model do
# reset play
@play.reload
@play.errors[:player_cards].clear
@play.game = @game
end
subject { @play }
@ -208,14 +209,14 @@ RSpec.describe Play, type: :model do
end
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
@cards_to_play = @game.current_player.inventory[0]
@cards_to_play = @play.player.inventory.first
@play.hand << @cards_to_play
expect(@play.hand_valid?).to eq(true)
@game.reload
expect(@game.play_to_beat.play).to eq(@play)
expect(@play.save)
expect(@play.game.play_to_beat.play).to eq(@play)
end
end
end