Stash moar
This commit is contained in:
parent
b344e9a816
commit
fd5158e712
17
README.md
17
README.md
@ -4,23 +4,24 @@ Thirteen Tien Len
|
|||||||
TODO
|
TODO
|
||||||
----
|
----
|
||||||
|
|
||||||
|
- flexbox layout: http://codepen.io/anon/pen/ojJOjq
|
||||||
|
|
||||||
- graphics
|
- graphics
|
||||||
|
|
||||||
- Remove PlayToBeat model and table.
|
- 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
|
- 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`
|
|
||||||
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
|
||||||
|
|
||||||
|
- Review attributions and license compliance
|
||||||
|
|
||||||
## Proposed Schema
|
## Proposed Schema
|
||||||
|
|
||||||
Table
|
Table
|
||||||
@ -114,3 +115,11 @@ Rails Composer is open source and supported by subscribers. Please join RailsApp
|
|||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
Attributions
|
||||||
|
------------
|
||||||
|
|
||||||
|
## Felt subtle pattern
|
||||||
|
|
||||||
|
Source: http://subtlepatterns.com/felt/
|
||||||
|
Author: http://atle.co/
|
||||||
|
|||||||
@ -89,31 +89,28 @@ var Game = React.createClass({
|
|||||||
return <div>Loading...</div>;
|
return <div>Loading...</div>;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div id="game_show_container" style={{
|
<div id='game-component'>
|
||||||
display: 'flex',
|
<h1>{this.state.data.title}</h1>
|
||||||
flexDirection: 'column'
|
|
||||||
}}>
|
{this.state.data.is_started
|
||||||
<div>Title: {this.state.data.title}</div>
|
?
|
||||||
<div>Game Id: {this.state.data.id}</div>
|
null
|
||||||
<div>Current Player: {this.state.data.controlling_player_id}</div>
|
:
|
||||||
<div>Hand to beat: {this.state.data.play_to_beat_string}</div>
|
<section id='game-controls'>
|
||||||
<div className='player-list'>
|
{/* TODO: If not joinable, show why. i.e. game full*/ }
|
||||||
<PlayerList
|
{this.state.data.is_joinable ? <button onClick={this.handleJoin}>Join</button> : null }
|
||||||
game_id={this.props.id}
|
{/* TODO: If not startable, show why. i.e. need more players */}
|
||||||
players={this.state.data.players}
|
<div id='start'>
|
||||||
onPlayHandSubmit={this.handlePlayHandSubmit}
|
{this.state.data.is_started ? null : <button onClick={this.handleStart} disabled={this.state.data.is_startable ? null : "disabled" }>Start</button>}
|
||||||
controlling_player_id={this.state.data.controlling_player_id}
|
</div>
|
||||||
current_user_id={this.state.data.current_user_id} />
|
</section>
|
||||||
</div>
|
}
|
||||||
<div>
|
|
||||||
{/* TODO: If not joinable, show why. i.e. game full*/ }
|
<PlayerList
|
||||||
{this.state.data.is_joinable ? <button onClick={this.handleJoin}>Join</button> : null }
|
game={this.state.data}
|
||||||
{/* TODO: If not startable, show why. i.e. need more players */}
|
onPlayHandSubmit={this.handlePlayHandSubmit} />
|
||||||
{this.state.data.is_started ? null : <button onClick={this.handleStart} disabled={this.state.data.is_startable ? null : "disabled" }>Start</button>}
|
|
||||||
</div>
|
{this.state.data.winner_player_id ? "Winner: " + this.state.data.winner_player_id : null}
|
||||||
<div>
|
|
||||||
{this.state.data.winner_player_id ? "Winner: " + this.state.data.winner_player_id : null}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,9 +12,9 @@ var Inventory = React.createClass({
|
|||||||
render: function() {
|
render: function() {
|
||||||
if (this.props.cards) {
|
if (this.props.cards) {
|
||||||
return (
|
return (
|
||||||
<ul style={{ display: 'flex', flexDirection: 'row', justifyContent: 'center', listStyle: 'none' }} >
|
<ul>
|
||||||
{this.props.cards.map(function(card) {
|
{this.props.cards.map(function(card) {
|
||||||
return <li key={card.id} style={{ paddingLeft: '16px' }}>
|
return <li key={card.id}>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
form={"player_controls_" + card.player_id}
|
form={"player_controls_" + card.player_id}
|
||||||
|
|||||||
@ -6,20 +6,22 @@ var Player = React.createClass({
|
|||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
<div style={{border: '1px solid', margin: '8px', padding: '8px'}}>
|
<div id={"player-" + this.props.id} className={"player " + (this.props.game.controlling_player_id == this.props.id ? 'has-control' : '')}>
|
||||||
<div>Player Id: {this.props.id}</div>
|
<div className='email'>{this.props.email}</div>
|
||||||
<div>Email: {this.props.email}</div>
|
{this.props.game.is_started
|
||||||
<div>Inventory count: {this.props.inventory_count}</div>
|
?
|
||||||
|
<div>Inventory count: {this.props.inventory_count}</div>
|
||||||
|
: null }
|
||||||
|
|
||||||
{/* Show player controls if player is owned by current_user */}
|
{/* 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
|
? (<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}
|
||||||
controlling_player_id={this.props.controlling_player_id} /> )
|
controlling_player_id={this.props.game.controlling_player_id} /> )
|
||||||
: null }
|
: null }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -4,24 +4,35 @@ var PlayerList = React.createClass({
|
|||||||
game_id: React.PropTypes.number
|
game_id: React.PropTypes.number
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function() {
|
playerNodes: function() {
|
||||||
var playerList = this;
|
var playerList = this;
|
||||||
var playerNodes = this.props.players.map(function (player) {
|
var playerNodes = this.props.game.players.map(function (player) {
|
||||||
return (
|
return (
|
||||||
<Player
|
<Player
|
||||||
key={player.id}
|
key={player.id}
|
||||||
onPlayHandSubmit={playerList.props.onPlayHandSubmit}
|
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}
|
user_id={player.user_id}
|
||||||
game_id={playerList.props.game_id} {...player} />
|
game={playerList.props.game}
|
||||||
|
{...player} />
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
return playerNodes;
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div id="playerList">
|
||||||
PlayerList:
|
<div id="top">
|
||||||
{playerNodes}
|
{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>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
38
app/assets/javascripts/header-scroll.js
Normal file
38
app/assets/javascripts/header-scroll.js
Normal 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;
|
||||||
|
}
|
||||||
@ -16,17 +16,18 @@
|
|||||||
|
|
||||||
html
|
html
|
||||||
box-sizing: border-box
|
box-sizing: border-box
|
||||||
display: flex
|
//display: flex
|
||||||
justify-content: center
|
justify-content: center
|
||||||
min-height: 100vh
|
min-height: 100vh
|
||||||
|
|
||||||
body
|
body
|
||||||
flex: 1 1 auto
|
//flex: 1 1 auto
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
min-height: 100vmin
|
min-height: 100vh
|
||||||
margin: 0
|
margin: 0
|
||||||
background: darkgreen
|
background: url('backgrounds/felt-green.png')
|
||||||
|
font-size: 4vmin
|
||||||
|
|
||||||
a
|
a
|
||||||
text-decoration: none
|
text-decoration: none
|
||||||
@ -35,22 +36,30 @@ a
|
|||||||
|
|
||||||
h1
|
h1
|
||||||
font-size: 7vmin
|
font-size: 7vmin
|
||||||
|
margin: 0 0 5vmin 0
|
||||||
|
|
||||||
header
|
header
|
||||||
flex: 1 1 auto
|
|
||||||
font-size: 3vmin
|
font-size: 3vmin
|
||||||
|
margin-bottom: 10vmin
|
||||||
nav
|
nav
|
||||||
padding: 1vmin
|
padding: 1vmin
|
||||||
background: #222
|
background: #222
|
||||||
|
position: fixed
|
||||||
|
top: 0
|
||||||
|
transition: top 0.2s ease-in-out
|
||||||
|
width: 100%
|
||||||
|
&.nav-up
|
||||||
|
top: -40px
|
||||||
ul
|
ul
|
||||||
margin: 0
|
margin: 0
|
||||||
display: flex
|
display: flex
|
||||||
li
|
li
|
||||||
flex: 1 1 auto
|
flex: 1 1 auto
|
||||||
|
text-align: center
|
||||||
|
|
||||||
#content
|
#content
|
||||||
flex: 3 1 auto
|
flex: 3 1 auto
|
||||||
background: darkgreen
|
//background: hotpink
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
flex-wrap: wrap
|
flex-wrap: wrap
|
||||||
@ -62,6 +71,7 @@ header
|
|||||||
text-align: center
|
text-align: center
|
||||||
h1
|
h1
|
||||||
font-size: 10vmin
|
font-size: 10vmin
|
||||||
|
color: #111
|
||||||
background: green
|
background: green
|
||||||
padding: 5vmin
|
padding: 5vmin
|
||||||
margin: 0
|
margin: 0
|
||||||
|
|||||||
@ -10,3 +10,105 @@
|
|||||||
display: inline-block
|
display: inline-block
|
||||||
width: 40%
|
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
|
||||||
|
|||||||
@ -2,10 +2,6 @@
|
|||||||
// They will automatically be included in application.css.
|
// They will automatically be included in application.css.
|
||||||
// You can use Sass (SCSS) here: http://sass-lang.com/
|
// You can use Sass (SCSS) here: http://sass-lang.com/
|
||||||
|
|
||||||
#content
|
|
||||||
h1
|
|
||||||
flex: 1 1 auto
|
|
||||||
|
|
||||||
.games-container
|
.games-container
|
||||||
flex: 1 1 auto
|
flex: 1 1 auto
|
||||||
display: flex
|
display: flex
|
||||||
@ -20,9 +16,8 @@
|
|||||||
padding: 2vmin
|
padding: 2vmin
|
||||||
|
|
||||||
.button
|
.button
|
||||||
flex: 1 1 auto
|
|
||||||
text-align: center
|
text-align: center
|
||||||
font-size: 4vmin
|
font-size: 4vmin
|
||||||
padding: 2vmin 4vmin
|
padding: 2vmin 4vmin
|
||||||
background: black
|
background: black
|
||||||
margin-bottom: 2vmin
|
margin-bottom: 5vmin
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
.form-inputs
|
.form-inputs
|
||||||
= f.input :title
|
= 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
|
.form-actions
|
||||||
= f.button :submit
|
= f.button :submit
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
%h1 New game
|
%h1 New game
|
||||||
|
|
||||||
= render 'form'
|
= render 'form'
|
||||||
|
|
||||||
= link_to 'Back', games_path
|
|
||||||
|
|||||||
@ -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
|
-# TODO: Remove deprecated commented out code
|
||||||
-#%p
|
-#%p
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<nav>
|
<nav>
|
||||||
<ul>
|
<ul>
|
||||||
<li><%= link_to 'Main Menu', root_path %></li>
|
<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? %>
|
<% if user_signed_in? %>
|
||||||
<li><%= link_to 'Edit account', edit_user_registration_path %></li>
|
<li><%= link_to 'Edit account', edit_user_registration_path %></li>
|
||||||
<li><%= link_to 'Sign out', destroy_user_session_path, :method=>'delete' %></li>
|
<li><%= link_to 'Sign out', destroy_user_session_path, :method=>'delete' %></li>
|
||||||
|
|||||||
@ -120,7 +120,7 @@ feature 'Play a hand', type: :feature, js: true do
|
|||||||
# next player is now the active player
|
# next player is now the active player
|
||||||
#expect(@game.controlling_player_id).to_not eq(@controlling_player_id)
|
#expect(@game.controlling_player_id).to_not eq(@controlling_player_id)
|
||||||
#expect(@game.controlling_player_id).to eq(@next_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
|
end
|
||||||
|
|
||||||
# Scenario: Player can not play an invalid hand on their turn
|
# Scenario: Player can not play an invalid hand on their turn
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user