Merge pull request #80 from uecasm/stop-games

Add a button to Stop an in-progress game.
This commit is contained in:
Andy Janata 2014-01-25 07:56:28 -08:00
commit e50a19f19d
8 changed files with 100 additions and 2 deletions

View File

@ -134,6 +134,7 @@ HttpSession hSession = request.getSession(true);
<input type="button" id="create_game" class="hide" value="Create Game" />
<input type="button" id="leave_game" class="hide" value="Leave Game" />
<input type="button" id="start_game" class="hide" value="Start Game" />
<input type="button" id="stop_game" class="hide" value="Stop Game" />
</div>
<div id="menubar_right">
Current timer duration: <span id="current_timer">0</span> seconds

View File

@ -200,6 +200,10 @@ cah.ajax.SuccessHandlers[cah.$.AjaxOperation.START_GAME] = function(data, req) {
}
};
cah.ajax.SuccessHandlers[cah.$.AjaxOperation.STOP_GAME] = function(data, req) {
// pass
};
cah.ajax.SuccessHandlers[cah.$.AjaxOperation.GET_CARDS] = function(data, req) {
var gameId = req[cah.$.AjaxRequest.GAME_ID];
var game = cah.currentGames[gameId];

View File

@ -24,6 +24,7 @@ cah.$.AjaxOperation.ADMIN_SET_VERBOSE_LOG = "svl";
cah.$.AjaxOperation.GET_CARDS = "gc";
cah.$.AjaxOperation.JOIN_GAME = "jg";
cah.$.AjaxOperation.REGISTER = "r";
cah.$.AjaxOperation.STOP_GAME = "Sg";
cah.$.AjaxOperation.CHAT = "c";
cah.$.AjaxOperation.NAMES = "gn";
cah.$.AjaxOperation.LEAVE_GAME = "lg";
@ -137,6 +138,7 @@ cah.$.ErrorCode.BAD_REQUEST = "br";
cah.$.ErrorCode.NO_SUCH_USER = "nsu";
cah.$.ErrorCode.DO_NOT_HAVE_CARD = "dnhc";
cah.$.ErrorCode.MESSAGE_TOO_LONG = "mtl";
cah.$.ErrorCode.ALREADY_STOPPED = "aS";
cah.$.ErrorCode.NOT_ENOUGH_PLAYERS = "nep";
cah.$.ErrorCode.INVALID_GAME = "ig";
cah.$.ErrorCode.NO_MSG_SPECIFIED = "nms";
@ -151,6 +153,7 @@ cah.$.ErrorCode_msg['nitg'] = "You are not in that game.";
cah.$.ErrorCode_msg['nep'] = "There are not enough players to start the game.";
cah.$.ErrorCode_msg['tf'] = "You are chatting too fast. Wait a few seconds and try again.";
cah.$.ErrorCode_msg['nyt'] = "It is not your turn to play a card.";
cah.$.ErrorCode_msg['aS'] = "The game has already stopped.";
cah.$.ErrorCode_msg['mtl'] = "Messages cannot be longer than 200 characters.";
cah.$.ErrorCode_msg['gf'] = "That game is full. Join another.";
cah.$.ErrorCode_msg['br'] = "Bad request.";

View File

@ -301,6 +301,7 @@ cah.Game = function(id) {
$("#leave_game").click(cah.bind(this, this.leaveGameClick_));
$("#start_game").click(cah.bind(this, this.startGameClick_));
$("#stop_game").click(cah.bind(this, this.stopGameClick_));
$(".confirm_card", this.element_).click(cah.bind(this, this.confirmClick_));
$(".game_show_last_round", this.element_).click(cah.bind(this, this.showLastRoundClick_));
$(".game_show_options", this.element_).click(cah.bind(this, this.showOptionsClick_));
@ -778,6 +779,12 @@ cah.Game.prototype.updateGameStatus = function(data) {
$("#start_game").hide();
}
if (this.host_ == cah.nickname && gameInfo[cah.$.GameInfo.STATE] != cah.$.GameState.LOBBY) {
$("#stop_game").show();
} else {
$("#stop_game").hide();
}
if (gameInfo[cah.$.GameInfo.STATE] == cah.$.GameState.LOBBY) {
this.showOptions_();
} else {
@ -1166,6 +1173,15 @@ cah.Game.prototype.startGameComplete = function() {
$("#start_game").hide();
};
/**
* Event handler for stop game button.
*
* @private
*/
cah.Game.prototype.stopGameClick_ = function() {
cah.Ajax.build(cah.$.AjaxOperation.STOP_GAME).withGameId(this.id_).run();
};
/**
* Called when the call to the server to play a card has completed successfully.
*/
@ -1214,6 +1230,7 @@ cah.Game.prototype.dispose = function() {
$(this.scoreboardElement_).remove();
$("#leave_game").unbind().hide();
$("#start_game").unbind().hide();
$("#stop_game").unbind().hide();
$(window).off("resize.game_" + this.id_);
cah.updateHash('');
@ -1316,6 +1333,7 @@ cah.Game.prototype.stateChange = function(data) {
this.removeAllCards();
this.judge_ = null;
$(".game_hand_filter", this.element_).addClass("hide"); // in case they were the judge last
$("#stop_game").hide();
// round
this.showOptions_();

View File

@ -188,7 +188,8 @@ public class Constants {
PLAY_CARD("pc"),
REGISTER("r"),
SCORE("SC"),
START_GAME("sg");
START_GAME("sg"),
STOP_GAME("Sg");
private final String op;
@ -289,6 +290,7 @@ public class Constants {
public enum ErrorCode implements Localizable {
ACCESS_DENIED("ad", "Access denied."),
ALREADY_STARTED("as", "The game has already started."),
ALREADY_STOPPED("aS", "The game has already stopped."),
BAD_OP("bo", "Invalid operation."),
BAD_REQUEST("br", "Bad request."),
@DuplicationAllowed

View File

@ -966,7 +966,7 @@ public class Game {
* True if because there are no long enough people to play a game, false if because the
* previous game finished.
*/
private void resetState(final boolean lostPlayer) {
public void resetState(final boolean lostPlayer) {
logger.info(String.format("Resetting game %d to lobby (lostPlayer=%b)", id, lostPlayer));
killRoundTimer();
synchronized (players) {

View File

@ -31,5 +31,6 @@ public class Handlers {
LIST.put(ScoreHandler.OP, ScoreHandler.class);
LIST.put(SpectateGameHandler.OP, SpectateGameHandler.class);
LIST.put(StartGameHandler.OP, StartGameHandler.class);
LIST.put(StopGameHandler.OP, StopGameHandler.class);
}
}

View File

@ -0,0 +1,69 @@
/**
* Copyright (c) 2012, Andy Janata
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions
* and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.socialgamer.cah.handlers;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
import net.socialgamer.cah.Constants.AjaxOperation;
import net.socialgamer.cah.Constants.ErrorCode;
import net.socialgamer.cah.Constants.GameState;
import net.socialgamer.cah.Constants.ReturnableData;
import net.socialgamer.cah.RequestWrapper;
import net.socialgamer.cah.data.Game;
import net.socialgamer.cah.data.GameManager;
import net.socialgamer.cah.data.User;
import com.google.inject.Inject;
/**
* Handler to stop a game.
*/
public class StopGameHandler extends GameWithPlayerHandler {
public static final String OP = AjaxOperation.STOP_GAME.toString();
@Inject
public StopGameHandler(final GameManager gameManager) {
super(gameManager);
}
@Override
public Map<ReturnableData, Object> handleWithUserInGame(final RequestWrapper request,
final HttpSession session, final User user, final Game game) {
final Map<ReturnableData, Object> data = new HashMap<ReturnableData, Object>();
if (game.getHost() != user) {
return error(ErrorCode.NOT_GAME_HOST);
} else if (game.getState() == GameState.LOBBY) {
return error(ErrorCode.ALREADY_STOPPED);
} else {
game.resetState(false);
return data;
}
}
}