diff --git a/WebContent/js/cah.ajax.handlers.js b/WebContent/js/cah.ajax.handlers.js index db06804..325f55c 100644 --- a/WebContent/js/cah.ajax.handlers.js +++ b/WebContent/js/cah.ajax.handlers.js @@ -235,3 +235,14 @@ cah.ajax.SuccessHandlers[cah.$.AjaxOperation.KICK] = function(data) { cah.ajax.SuccessHandlers[cah.$.AjaxOperation.BAN] = function(data) { // pass }; + +cah.ajax.SuccessHandlers[cah.$.AjaxOperation.SCORE] = function(data, req) { + var gameId = req[cah.$.AjaxRequest.GAME_ID]; + var info = data[cah.$.AjaxResponse.PLAYER_INFO]; + var msg = info[cah.$.GamePlayerInfo.NAME] + " has " + info[cah.$.GamePlayerInfo.SCORE] + " Awesome Points."; + if (gameId) { + cah.log.status_with_game(gameId, msg); + } else { + cah.log.status(msg); + } +}; diff --git a/WebContent/js/cah.app.js b/WebContent/js/cah.app.js index 11801b9..9573d4e 100644 --- a/WebContent/js/cah.app.js +++ b/WebContent/js/cah.app.js @@ -163,6 +163,12 @@ function chatsubmit_click(game_id, parent_element) { // this could also be an IP address ajax = cah.Ajax.build(cah.$.AjaxOperation.BAN).withNickname(text.split(' ')[0]); break; + case 'score': + ajax = cah.Ajax.build(cah.$.AjaxOperation.SCORE).withMessage(text); + if (game_id != null) { + ajax = ajax.withGameId(game_id); + } + break; case 'names': ajax = cah.Ajax.build(cah.$.AjaxOperation.NAMES); break; diff --git a/WebContent/js/cah.constants.js b/WebContent/js/cah.constants.js index 01e8c1c..a01399c 100644 --- a/WebContent/js/cah.constants.js +++ b/WebContent/js/cah.constants.js @@ -11,6 +11,7 @@ cah.$.AjaxOperation.FIRST_LOAD = "fl"; cah.$.AjaxOperation.LOG_OUT = "lo"; cah.$.AjaxOperation.BAN = "b"; cah.$.AjaxOperation.JUDGE_SELECT = "js"; +cah.$.AjaxOperation.SCORE = "SC"; cah.$.AjaxOperation.GAME_LIST = "ggl"; cah.$.AjaxOperation.CHANGE_GAME_OPTIONS = "cgo"; cah.$.AjaxOperation.GET_GAME_INFO = "ggi"; diff --git a/src/net/socialgamer/cah/Constants.java b/src/net/socialgamer/cah/Constants.java index 12253de..72afc9b 100644 --- a/src/net/socialgamer/cah/Constants.java +++ b/src/net/socialgamer/cah/Constants.java @@ -182,6 +182,7 @@ public class Constants { NAMES("gn"), PLAY_CARD("pc"), REGISTER("r"), + SCORE("SC"), START_GAME("sg"); private final String op; diff --git a/src/net/socialgamer/cah/data/Game.java b/src/net/socialgamer/cah/data/Game.java index b291b92..b180f3c 100644 --- a/src/net/socialgamer/cah/data/Game.java +++ b/src/net/socialgamer/cah/data/Game.java @@ -462,7 +462,7 @@ public class Game { * The player for whom to get status. * @return Information for {@code player}: Name, score, status. */ - private Map getPlayerInfo(final Player player) { + public Map getPlayerInfo(final Player player) { final Map playerInfo = new HashMap(); // TODO make sure this can't happen in the first place if (player == null) { @@ -803,10 +803,7 @@ public class Game { // have to do this after we move to judging state for (final Player player : playersToUpdateStatus) { - final HashMap data = getEventMap(); - data.put(LongPollResponse.EVENT, LongPollEvent.GAME_PLAYER_INFO_CHANGE.toString()); - data.put(LongPollResponse.PLAYER_INFO, getPlayerInfo(player)); - broadcastToPlayers(MessageType.GAME_PLAYER_EVENT, data); + notifyPlayerInfoChange(player); } } @@ -830,17 +827,14 @@ public class Game { final int judgeTimer = useTimer ? JUDGE_TIMEOUT_BASE + (JUDGE_TIMEOUT_PER_CARD * playedCards.size() * blackCard.getPick()) : Integer.MAX_VALUE; - HashMap data = getEventMap(); + final HashMap data = getEventMap(); data.put(LongPollResponse.EVENT, LongPollEvent.GAME_STATE_CHANGE.toString()); data.put(LongPollResponse.GAME_STATE, GameState.JUDGING.toString()); data.put(LongPollResponse.WHITE_CARDS, getWhiteCards()); data.put(LongPollResponse.PLAY_TIMER, judgeTimer); broadcastToPlayers(MessageType.GAME_EVENT, data); - data = getEventMap(); - data.put(LongPollResponse.EVENT, LongPollEvent.GAME_PLAYER_INFO_CHANGE.toString()); - data.put(LongPollResponse.PLAYER_INFO, getPlayerInfo(getJudge())); - broadcastToPlayers(MessageType.GAME_PLAYER_EVENT, data); + notifyPlayerInfoChange(getJudge()); synchronized (nextRoundTimerLock) { killRoundTimer(); @@ -892,23 +886,17 @@ public class Game { final Player judge = getJudge(); judgeIndex = 0; - HashMap data = getEventMap(); + final HashMap data = getEventMap(); data.put(LongPollResponse.EVENT, LongPollEvent.GAME_STATE_CHANGE.toString()); data.put(LongPollResponse.GAME_STATE, GameState.LOBBY.toString()); broadcastToPlayers(MessageType.GAME_EVENT, data); if (host != null) { - data = getEventMap(); - data.put(LongPollResponse.EVENT, LongPollEvent.GAME_PLAYER_INFO_CHANGE.toString()); - data.put(LongPollResponse.PLAYER_INFO, getPlayerInfo(host)); - broadcastToPlayers(MessageType.GAME_PLAYER_EVENT, data); + notifyPlayerInfoChange(host); } if (judge != null) { - data = getEventMap(); - data.put(LongPollResponse.EVENT, LongPollEvent.GAME_PLAYER_INFO_CHANGE.toString()); - data.put(LongPollResponse.PLAYER_INFO, getPlayerInfo(judge)); - broadcastToPlayers(MessageType.GAME_PLAYER_EVENT, data); + notifyPlayerInfoChange(judge); } gameManager.broadcastGameListRefresh(); @@ -1019,7 +1007,7 @@ public class Game { * {@code user} is not in this game. */ @Nullable - private Player getPlayerForUser(final User user) { + public Player getPlayerForUser(final User user) { final Player[] playersCopy = players.toArray(new Player[players.size()]); for (final Player player : playersCopy) { if (player.getUser() == user) { @@ -1210,11 +1198,7 @@ public class Game { } if (playCard != null) { playedCards.addCard(player, playCard); - - final HashMap data = getEventMap(); - data.put(LongPollResponse.EVENT, LongPollEvent.GAME_PLAYER_INFO_CHANGE.toString()); - data.put(LongPollResponse.PLAYER_INFO, getPlayerInfo(player)); - broadcastToPlayers(MessageType.GAME_PLAYER_EVENT, data); + notifyPlayerInfoChange(player); if (startJudging()) { judgingState(); @@ -1228,6 +1212,19 @@ public class Game { } } + /** + * Sends updated player information about a specific player to all players in the game. + * + * @param player + * The player whose information has been changed. + */ + public void notifyPlayerInfoChange(final Player player) { + final HashMap data = getEventMap(); + data.put(LongPollResponse.EVENT, LongPollEvent.GAME_PLAYER_INFO_CHANGE.toString()); + data.put(LongPollResponse.PLAYER_INFO, getPlayerInfo(player)); + broadcastToPlayers(MessageType.GAME_PLAYER_EVENT, data); + } + /** * The judge has selected a card. The {@code cardId} passed in may be any white cards's ID for * black cards that have multiple selection, however only the first card in the set's ID will be @@ -1264,22 +1261,15 @@ public class Game { } final int clientCardId = playedCards.getCards(cardPlayer).get(0).getId(); - HashMap data = getEventMap(); + final HashMap data = getEventMap(); data.put(LongPollResponse.EVENT, LongPollEvent.GAME_ROUND_COMPLETE.toString()); data.put(LongPollResponse.ROUND_WINNER, cardPlayer.getUser().getNickname()); data.put(LongPollResponse.WINNING_CARD, clientCardId); data.put(LongPollResponse.INTERMISSION, ROUND_INTERMISSION); broadcastToPlayers(MessageType.GAME_EVENT, data); - data = getEventMap(); - data.put(LongPollResponse.EVENT, LongPollEvent.GAME_PLAYER_INFO_CHANGE.toString()); - data.put(LongPollResponse.PLAYER_INFO, getPlayerInfo(getJudge())); - broadcastToPlayers(MessageType.GAME_PLAYER_EVENT, data); - - data = getEventMap(); - data.put(LongPollResponse.EVENT, LongPollEvent.GAME_PLAYER_INFO_CHANGE.toString()); - data.put(LongPollResponse.PLAYER_INFO, getPlayerInfo(cardPlayer)); - broadcastToPlayers(MessageType.GAME_PLAYER_EVENT, data); + notifyPlayerInfoChange(getJudge()); + notifyPlayerInfoChange(cardPlayer); synchronized (nextRoundTimerLock) { killRoundTimer(); diff --git a/src/net/socialgamer/cah/data/Player.java b/src/net/socialgamer/cah/data/Player.java index 78e63b0..7fd6146 100644 --- a/src/net/socialgamer/cah/data/Player.java +++ b/src/net/socialgamer/cah/data/Player.java @@ -72,6 +72,13 @@ public class Player { score++; } + /** + * Increase the player's score by the specified amount. + */ + public void increaseScore(final int offset) { + score += offset; + } + /** * Reset the player's score to 0. */ diff --git a/src/net/socialgamer/cah/handlers/Handlers.java b/src/net/socialgamer/cah/handlers/Handlers.java index dfbbb5f..8e9efd9 100644 --- a/src/net/socialgamer/cah/handlers/Handlers.java +++ b/src/net/socialgamer/cah/handlers/Handlers.java @@ -28,6 +28,7 @@ public class Handlers { LIST.put(NamesHandler.OP, NamesHandler.class); LIST.put(PlayCardHandler.OP, PlayCardHandler.class); LIST.put(RegisterHandler.OP, RegisterHandler.class); + LIST.put(ScoreHandler.OP, ScoreHandler.class); LIST.put(StartGameHandler.OP, StartGameHandler.class); } } diff --git a/src/net/socialgamer/cah/handlers/ScoreHandler.java b/src/net/socialgamer/cah/handlers/ScoreHandler.java new file mode 100644 index 0000000..fccb516 --- /dev/null +++ b/src/net/socialgamer/cah/handlers/ScoreHandler.java @@ -0,0 +1,72 @@ +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.AjaxRequest; +import net.socialgamer.cah.Constants.AjaxResponse; +import net.socialgamer.cah.Constants.ErrorCode; +import net.socialgamer.cah.Constants.ReturnableData; +import net.socialgamer.cah.Constants.SessionAttribute; +import net.socialgamer.cah.RequestWrapper; +import net.socialgamer.cah.data.ConnectedUsers; +import net.socialgamer.cah.data.Game; +import net.socialgamer.cah.data.Player; +import net.socialgamer.cah.data.User; + +import com.google.inject.Inject; + + +public class ScoreHandler extends Handler { + + public static final String OP = AjaxOperation.SCORE.toString(); + + private final ConnectedUsers connectedUsers; + + @Inject + public ScoreHandler(final ConnectedUsers connectedUsers) { + this.connectedUsers = connectedUsers; + } + + @Override + public Map handle(final RequestWrapper request, final HttpSession session) { + final User user = (User) session.getAttribute(SessionAttribute.USER); + assert (user != null); + final String params = request.getParameter(AjaxRequest.MESSAGE); + final String[] args = (params == null || params.isEmpty()) ? new String[0] : params.trim() + .split(" "); + + final User target = (args.length > 0) ? connectedUsers.getUser(args[0]) : user; + if (null == target) { + return error(ErrorCode.NO_SUCH_USER); + } + final Game game = target.getGame(); + if (null == game) { + return error(ErrorCode.INVALID_GAME); + } + final Player player = game.getPlayerForUser(target); + if (null == player) { + return error(ErrorCode.INVALID_GAME); + } + + final Map data = new HashMap(); + + if (user.isAdmin() && args.length == 2) { + // for now only admins can change scores. could possibly extend this to let the host do it, + // provided it's for a player in the same game and it does a gamewide announcement. + try { + final int offset = Integer.parseInt(args[1]); + player.increaseScore(offset); + game.notifyPlayerInfoChange(player); + } catch (final NumberFormatException e) { + return error(ErrorCode.BAD_REQUEST); + } + } + data.put(AjaxResponse.PLAYER_INFO, game.getPlayerInfo(player)); + + return data; + } +}