Stash moar

This commit is contained in:
Jesse C. Fisher 2015-11-20 17:52:18 -08:00
parent b344e9a816
commit fd5158e712
14 changed files with 226 additions and 64 deletions

View File

@ -4,23 +4,24 @@ Thirteen Tien Len
TODO
----
- flexbox layout: http://codepen.io/anon/pen/ojJOjq
- graphics
- Remove PlayToBeat model and table.
- Implement run including face cards
- Implement run including face cards (done?)
- 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
- 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
- Review attributions and license compliance
## Proposed Schema
Table
@ -114,3 +115,11 @@ Rails Composer is open source and supported by subscribers. Please join RailsApp
License
-------
Attributions
------------
## Felt subtle pattern
Source: http://subtlepatterns.com/felt/
Author: http://atle.co/

View File

@ -89,31 +89,28 @@ var Game = React.createClass({
return <div>Loading...</div>;
}
return (
<div id="game_show_container" style={{
display: 'flex',
flexDirection: 'column'
}}>
<div>Title: {this.state.data.title}</div>
<div>Game Id: {this.state.data.id}</div>
<div>Current Player: {this.state.data.controlling_player_id}</div>
<div>Hand to beat: {this.state.data.play_to_beat_string}</div>
<div className='player-list'>
<PlayerList
game_id={this.props.id}
players={this.state.data.players}
onPlayHandSubmit={this.handlePlayHandSubmit}
controlling_player_id={this.state.data.controlling_player_id}
current_user_id={this.state.data.current_user_id} />
</div>
<div>
{/* TODO: If not joinable, show why. i.e. game full*/ }
{this.state.data.is_joinable ? <button onClick={this.handleJoin}>Join</button> : null }
{/* TODO: If not startable, show why. i.e. need more players */}
{this.state.data.is_started ? null : <button onClick={this.handleStart} disabled={this.state.data.is_startable ? null : "disabled" }>Start</button>}
</div>
<div>
{this.state.data.winner_player_id ? "Winner: " + this.state.data.winner_player_id : null}
</div>
<div id='game-component'>
<h1>{this.state.data.title}</h1>
{this.state.data.is_started
?
null
:
<section id='game-controls'>
{/* TODO: If not joinable, show why. i.e. game full*/ }
{this.state.data.is_joinable ? <button onClick={this.handleJoin}>Join</button> : null }
{/* TODO: If not startable, show why. i.e. need more players */}
<div id='start'>
{this.state.data.is_started ? null : <button onClick={this.handleStart} disabled={this.state.data.is_startable ? null : "disabled" }>Start</button>}
</div>
</section>
}
<PlayerList
game={this.state.data}
onPlayHandSubmit={this.handlePlayHandSubmit} />
{this.state.data.winner_player_id ? "Winner: " + this.state.data.winner_player_id : null}
</div>
);
}

View File

@ -12,9 +12,9 @@ var Inventory = React.createClass({
render: function() {
if (this.props.cards) {
return (
<ul style={{ display: 'flex', flexDirection: 'row', justifyContent: 'center', listStyle: 'none' }} >
<ul>
{this.props.cards.map(function(card) {
return <li key={card.id} style={{ paddingLeft: '16px' }}>
return <li key={card.id}>
<label>
<input
form={"player_controls_" + card.player_id}

View File

@ -6,20 +6,22 @@ var Player = React.createClass({
render: function() {
return (
<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 id={"player-" + this.props.id} className={"player " + (this.props.game.controlling_player_id == this.props.id ? 'has-control' : '')}>
<div className='email'>{this.props.email}</div>
{this.props.game.is_started
?
<div>Inventory count: {this.props.inventory_count}</div>
: null }
{/* Show player controls if player is owned by current_user */}
{this.props.user_id == this.props.current_user_id
{(this.props.user_id == this.props.game.current_user_id) && (this.props.game.is_started == true)
? (<PlayerControls
key={this.props.id}
onPlayHandSubmit={this.props.onPlayHandSubmit}
game_id={this.props.game_id}
game_id={this.props.game.id}
player_id={this.props.id}
inventory={this.props.inventory}
controlling_player_id={this.props.controlling_player_id} /> )
controlling_player_id={this.props.game.controlling_player_id} /> )
: null }
</div>
);

View File

@ -4,24 +4,35 @@ var PlayerList = React.createClass({
game_id: React.PropTypes.number
},
render: function() {
playerNodes: function() {
var playerList = this;
var playerNodes = this.props.players.map(function (player) {
var playerNodes = this.props.game.players.map(function (player) {
return (
<Player
key={player.id}
onPlayHandSubmit={playerList.props.onPlayHandSubmit}
controlling_player_id={playerList.props.controlling_player_id}
current_user_id={playerList.props.current_user_id}
user_id={player.user_id}
game_id={playerList.props.game_id} {...player} />
game={playerList.props.game}
{...player} />
);
});
return playerNodes;
},
render: function() {
return (
<div>
PlayerList:
{playerNodes}
<div id="playerList">
<div id="top">
{this.playerNodes()[0]}
</div>
<div id="mid">
{this.playerNodes()[1]}
<div id="play-to-beat">Hand to beat: {this.props.game.play_to_beat_string}</div>
{this.playerNodes()[2]}
</div>
<div id="bot">
{this.playerNodes()[3]}
</div>
</div>
);
}

View File

@ -0,0 +1,38 @@
// Hide Header on on scroll down
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('header > nav').outerHeight();
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled() {
var st = $(this).scrollTop();
// Make sure they scroll more than delta
if(Math.abs(lastScrollTop - st) <= delta)
return;
// If they scrolled down and are past the navbar, add class .nav-up.
// This is necessary so you never see what is "behind" the navbar.
if (st > lastScrollTop && st > navbarHeight){
// Scroll Down
$('header > nav').removeClass('nav-down').addClass('nav-up');
} else {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('header > nav').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}

View File

@ -16,17 +16,18 @@
html
box-sizing: border-box
display: flex
//display: flex
justify-content: center
min-height: 100vh
body
flex: 1 1 auto
//flex: 1 1 auto
display: flex
flex-direction: column
min-height: 100vmin
min-height: 100vh
margin: 0
background: darkgreen
background: url('backgrounds/felt-green.png')
font-size: 4vmin
a
text-decoration: none
@ -35,22 +36,30 @@ a
h1
font-size: 7vmin
margin: 0 0 5vmin 0
header
flex: 1 1 auto
font-size: 3vmin
margin-bottom: 10vmin
nav
padding: 1vmin
background: #222
position: fixed
top: 0
transition: top 0.2s ease-in-out
width: 100%
&.nav-up
top: -40px
ul
margin: 0
display: flex
li
flex: 1 1 auto
text-align: center
#content
flex: 3 1 auto
background: darkgreen
//background: hotpink
display: flex
flex-direction: column
flex-wrap: wrap
@ -62,6 +71,7 @@ header
text-align: center
h1
font-size: 10vmin
color: #111
background: green
padding: 5vmin
margin: 0

View File

@ -10,3 +10,105 @@
display: inline-block
width: 40%
//// New Game#new
.simple_form
background: green
padding: 5vmin
outline: 2px solid black
label
font-size: 4vmin
display: block
input.string
font-size: 6vmin
margin-bottom: 2vmin
input.btn
font-size: 4vmin
//// Show Game#show
button
font-size: 4vmin
#game-component-container-container
display: flex
flex-direction: column
flex: 1 1 auto
align-self: stretch
#game-component-container
flex: 1 1 auto
display: flex
#game-component
flex: 1 1 auto
flex-direction: column
align-self: stretch
display: flex
h1
font-size: 4vmin
#game-controls
display: flex
flex-direction: row
margin-bottom: 5vh
align-self: stretch
align-items: flex-start
div
flex: 1 1 auto
#start
align-self: flex-end
text-align: right
.player-list
display: flex
.player
background: green
padding: 2vmin
outline: 2px solid black
position: relative
&.has-control
background: lightgreen
#playerList
display: flex
flex-direction: row
flex-wrap: wrap
align-items: flex-start
text-align: center
#top
flex: 0 0 100%
display: flex
.player
flex: 1 1 auto
#mid
flex: 0 0 100%
align-self: center
align-items: flex-start
display: flex
.player
flex: 1 1 auto
.email
//position: absolute
//background: green
&:first-of-type
.email
//left: -18.5vmin
//transform: rotate(-90deg)
&:last-of-type
.email
//transform: rotate(90deg)
//right: -17vmin
#play-to-beat
flex: 1 1 auto
#bot
flex: 0 0 100%
align-self: flex-end
////// Inventory
.player form
ul
display: flex
flex-wrap: wrap
text-align: left
li
flex: 1 1 auto

View File

@ -2,10 +2,6 @@
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
#content
h1
flex: 1 1 auto
.games-container
flex: 1 1 auto
display: flex
@ -20,9 +16,8 @@
padding: 2vmin
.button
flex: 1 1 auto
text-align: center
font-size: 4vmin
padding: 2vmin 4vmin
background: black
margin-bottom: 2vmin
margin-bottom: 5vmin

View File

@ -3,7 +3,7 @@
.form-inputs
= f.input :title
= f.association :players, as: :select, collection: User.all.map {|u| u.id}, include_blank: false, include_hidden: false
-#= f.association :players, as: :select, collection: User.all.map {|u| u.id}, include_blank: false, include_hidden: false
.form-actions
= f.button :submit

View File

@ -1,5 +1,3 @@
%h1 New game
= render 'form'
= link_to 'Back', games_path

View File

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

View File

@ -1,7 +1,7 @@
<nav>
<ul>
<li><%= link_to 'Main Menu', root_path %></li>
<li><%= link_to 'Browse', games_path %></li>
<li><%= link_to 'Games', games_path %></li>
<% if user_signed_in? %>
<li><%= link_to 'Edit account', edit_user_registration_path %></li>
<li><%= link_to 'Sign out', destroy_user_session_path, :method=>'delete' %></li>

View File

@ -120,7 +120,7 @@ feature 'Play a hand', type: :feature, js: true do
# next player is now the active player
#expect(@game.controlling_player_id).to_not eq(@controlling_player_id)
#expect(@game.controlling_player_id).to eq(@next_player_id)
expect(page).to have_content("Current Player: #{@next_player_id}")
expect(page).to have_selector("#player-#{@next_player_id}.has-control")
end
# Scenario: Player can not play an invalid hand on their turn