Skip to content

Commit

Permalink
fix timing issue with keyboard submissions, add min version
Browse files Browse the repository at this point in the history
  • Loading branch information
tublitzed committed Jan 24, 2016
1 parent 51a7c1b commit 53d9395
Show file tree
Hide file tree
Showing 17 changed files with 343 additions and 116 deletions.
10 changes: 9 additions & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,24 @@ module.exports = function(grunt) {
run: true
}
}
},
uglify: {
main: {
files: {
'./public/js/app.bundle.min.js': ['./public/js/app.bundle.js']
}
}
}
});

grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-mocha');
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-eslint');

grunt.registerTask('default', ['sass', 'eslint', 'browserify', 'mocha:test']);
grunt.registerTask('default', ['sass', 'eslint', 'browserify', 'mocha:test', 'uglify']);
grunt.registerTask('w', ['watch']);
grunt.registerTask('test', ['browserify:test', 'mocha:test']);
grunt.registerTask('lint', ['eslint']);
Expand Down
9 changes: 5 additions & 4 deletions assets/js/classes/deck/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class Deck {
.then((data, textStatus, jqXHR) => {
if (data.success) {
this.update(data);
this.vent.pub('drawCard');
this.vent.pub('drawCardComplete');
} else {
this.vent.pub('error', 'Unable to draw a new card.');
}
Expand Down Expand Up @@ -113,7 +113,7 @@ class Deck {
* @param {number} pointsOnTheLine
*/
render(pointsOnTheLine) {
this.renderPointsOtl(pointsOnTheLine);
this.renderPointsOnTheLine(pointsOnTheLine);
this.renderCardsLeft();
this.renderDiscardPile();
}
Expand All @@ -123,7 +123,7 @@ class Deck {
*
* @param {number} pointsOnTheLine
*/
renderPointsOtl(pointsOnTheLine) {
renderPointsOnTheLine(pointsOnTheLine) {
var $pointsOnTheLineWrapper = this.$el.find('.points-otl');
$pointsOnTheLineWrapper.find('.points-otl__point-value').html(pointsOnTheLine);
$pointsOnTheLineWrapper.find('.points-otl__text').text(pointsOnTheLine === 1 ? 'point' : 'points');
Expand All @@ -146,7 +146,8 @@ class Deck {
var $pile = $('.deck__card--discard-pile');
if (this.activeCard) {
let card = this.activeCard;
let $cardImg = $('<img>').prop('src', card.images.png).prop('alt', card.value + ' ' + card.suit.toLowerCase());
let altText = card.value.toLowerCase() + ' of ' + card.suit.toLowerCase();
let $cardImg = $('<img>').prop('src', card.images.png).prop('alt', altText);
$cardImg.addClass('deck__card-img');
$pile.addClass('deck__card--discard-pile--has-card').find('.card').html($cardImg);
} else {
Expand Down
97 changes: 76 additions & 21 deletions assets/js/classes/game/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const playerCount = 2;
const GUESS_HI = 'hi';
const GUESS_LO = 'lo';
const GAME_OVER_CLASS = 'body--game-over';
const TURN_IN_PROGRESS_CLASS = 'body--turn-in-progress';
const DIALOG_CONFIRM_MESSAGE = 'Ok';


Expand All @@ -27,6 +28,7 @@ class Game {
this.pointsOnTheLine = opts.pointsOnTheLine || 0;
this.deck = this.initDeck(opts.deck);
this.players = this.initPlayers(opts.players);
this.$body = $('body');
this.bindEventHandlers();
}

Expand All @@ -43,22 +45,23 @@ class Game {
this.save();
});
this.vent.sub('render', () => this.render());
this.vent.sub('drawCard', () => this.onDrawCard());
this.vent.sub('drawCardComplete', () => this.onDrawCardComplete());
this.vent.sub('error', (error) => this.error(error));

var self = this;
var $body = $('body');
this.vent.sub('startTurn', () => this.startTurn());
this.vent.sub('endTurn', () => this.endTurn());

$body.on('keydown', (event) => {
var self = this;
this.$body.on('keydown', (event) => {
this.processKeydownEvent(event);
return;
});

$('.deck__card--draw-pile').on('click', function(event) {
event.preventDefault();
var $this = $(this);
//prevent rapid fire clicks from triggering multiple draws, and ignore if game is over.
if (!$this.hasClass('clicked') && !$body.hasClass(GAME_OVER_CLASS)) {
//prevent rapid fire clicks from triggering multiple draws, and ignore if game is over or turn in progress.
if (!$this.hasClass('clicked') && !self.$body.hasClass(GAME_OVER_CLASS) && !self.$body.hasClass(TURN_IN_PROGRESS_CLASS)) {
self.onDrawPileClick();
}
$this.addClass('clicked');
Expand Down Expand Up @@ -92,15 +95,20 @@ class Game {
*/
processKeydownEvent(event) {
let listenForKeycodes = [13, 38, 40, 39];
if (listenForKeycodes.indexOf(event.which) === -1 || $('.vex').is(':visible') || $('body').hasClass(GAME_OVER_CLASS)) {
if (listenForKeycodes.indexOf(event.which) === -1 || $('.vex').is(':visible') || this.$body.hasClass(GAME_OVER_CLASS)) {
return;
}

//prevent rapid clicks from triggering multiple turns.
if (this.turnInProgress()) {
return false;
}


let activePlayer = this.getActivePlayer();
if (activePlayer.role === roles.ROLE_DEALER) {
if (event.which === 13) { //enter
this.deck.draw();
this.drawCard();
}
} else if (event.which === 38) { //up arrow
this.submitGuess(GUESS_HI);
Expand All @@ -116,19 +124,52 @@ class Game {
* @param {string} guess GUESS_LO|GUESS_HI
*/
submitGuess(guess) {
let activePlayer = this.getActivePlayer();
activePlayer
.setGuess(guess);
this.startTurn();
this.getActivePlayer().setGuess(guess);
this.switchPlayers();
this.endTurn();
}

/**
* When the currently active player chooses to pass.
*/
pass() {
this.startTurn();
this.getActivePlayer().clearGuess();
this.switchRoles();
this.switchPlayers();
this.endTurn();
}

/**
* Draw a card.
*/
drawCard() {
this.startTurn();
this.deck.draw();
}

/**
* Handle race conditions triggered by use of keyboard by setting flag for turn in progress.
*/
startTurn() {
this.$body.addClass(TURN_IN_PROGRESS_CLASS);
}

/**
* Triggered when we're "done" with a turn and will begin accepting inputs
* for another turn.
*/
endTurn() {
this.$body.removeClass(TURN_IN_PROGRESS_CLASS);
}

/**
* Check if a turn is currently in progress. Used to bypass handling events
* for starting another play if the previous one isn't finished.
*/
turnInProgress() {
return this.$body.hasClass(TURN_IN_PROGRESS_CLASS);
}

/**
Expand All @@ -137,18 +178,19 @@ class Game {
onDrawPileClick() {
var activePlayer = this.getActivePlayer();
if (activePlayer.role === roles.ROLE_DEALER) {
this.deck.draw();
this.drawCard();
} else {
vex.dialog.alert(activePlayer.name + ", it's not your turn to draw yet. Take a guess instead.");
}
}


/**
* Triggered when we've drawn a new card: we're either just going to switch
* turns if there's no previous guess, or we need to validate prev guess
* against new card.
*/
onDrawCard() {
onDrawCardComplete() {
let inactivePlayer = this.getInactivePlayer();

if (this.deck.remaining === 0) {
Expand All @@ -158,6 +200,7 @@ class Game {
} else {
this.pointsOnTheLine += 1;
this.switchPlayers();
this.endTurn();
}
}

Expand All @@ -168,12 +211,11 @@ class Game {
handleGuess(inactivePlayer) {
if (this.isGuessCorrect(inactivePlayer)) {
this.onCorrectGuess(inactivePlayer);
//give the flash a moment to show and start clearing before
//we swap turns.
setTimeout(() => {
this.pointsOnTheLine += 1;
this.switchPlayers();
}, flash.DISPLAY_DURATION + 100);
this.endTurn();
}, flash.DISPLAY_DURATION);
} else {
this.onIncorrectGuess(inactivePlayer);
}
Expand Down Expand Up @@ -207,7 +249,7 @@ class Game {
store.clearGame();

let winner = this.getWinner();
$('body').addClass(GAME_OVER_CLASS);
this.$body.addClass(GAME_OVER_CLASS);
$('.player').removeClass('player--active');

let $headline = $('.headline');
Expand Down Expand Up @@ -276,19 +318,32 @@ class Game {
.clearGuess()
.render();

//clear this slightly before we clear the pile. We've
//already added the score to the player hand so it needs
//to be cleared in the UI.
this.clearPointsOnTheLine();

setTimeout(() => {
this.clearDiscardPile();
this.endTurn();
}, flash.DISPLAY_DURATION);
}

/**
* Clear the points on the line, resetting to 0.
*/
clearPointsOnTheLine() {
this.pointsOnTheLine = 0;
this.deck.renderPointsOnTheLine(this.pointsOnTheLine);
}

/**
* When a guess is incorrect, we clear the pile.
*/
clearDiscardPile() {
this.pointsOnTheLine = 0;
this.deck.clearActiveCard();
this.save();
this.render();
this.save();
}

/**
Expand Down Expand Up @@ -317,8 +372,8 @@ class Game {
*
* @return {object} game
*/
export() {
let game = exporter.exportObj(this, ['deck', 'players', 'vent']);
export () {
let game = exporter.exportObj(this, ['deck', 'players', 'vent', '$body']);
game.deck = this.deck.export();
game.players = this.exportPlayers();
return game;
Expand Down
3 changes: 3 additions & 0 deletions assets/js/classes/game/tests/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ suite('Game', function() {
test('should return an object without key for $el', function() {
assert.isUndefined(exported['$el']);
});
test('should return an object without key for $body', function() {
assert.isUndefined(exported['$body']);
});
test('should return an object without key for vent', function() {
assert.isUndefined(exported['vent']);
});
Expand Down
2 changes: 1 addition & 1 deletion assets/js/classes/player/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class Player {
* Show modal to change name
*/
showChangeNamePrompt() {
let input = "<input name='vex' type='text' class='vex-dialog-prompt-input' placeholder='Enter new name' maxlength='" + MAX_LENGTH_NAME +"' />"
let input = "<input name='vex' type='text' class='vex-dialog-prompt-input' placeholder='Enter new name' maxlength='" + MAX_LENGTH_NAME +"' />";
vex.dialog.prompt({
message: 'Change your name, ' + this.name + ':',
input: input,
Expand Down
5 changes: 0 additions & 5 deletions assets/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,6 @@ var initGame = () => {
game.render();
}
vent.sub('appReady', () => game.render().showIntro());

//debug info:
if (window.location.href.indexOf('debug') !== -1) {
window.DEBUG_HILO = game;
}
};

initGame();
5 changes: 3 additions & 2 deletions assets/js/modules/exporter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
*/
var exporter = {
/**
* Shallow copy a class object and ignore keys. Used
* for exporting objects without specific keys.
* Shallow copy an object and ignore keys. Used
* for exporting objects without specific keys, such as
* cached DOM references, etc.
*
* @param {object} sourceObj
* @param {array=} ignoreKeys
Expand Down
6 changes: 4 additions & 2 deletions assets/scss/_vars.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ $fa-font-path: '/public/fonts/font-awesome';

$font-family: 'Raleway', 'Helvetica', 'Helvetica Neue', 'Arial', sans-serif;

$color-light-grey: #CCC;
$color-grey: #858484;
$color-grey-0: #F3F3F3;
$color-grey-2: #CCC;
$color-grey-6: #858484;

$color-near-white: #F8F8F8;
$color-near-black: #161515;

Expand Down
Loading

0 comments on commit 53d9395

Please sign in to comment.