Feat/103 add raise command on server side #267
@@ -181,6 +181,21 @@ public class ServerApp {
|
|||||||
new ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.bet
|
new ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.bet
|
||||||
.PlayerBetHandler(responseDispatcher, userRegistry, lobbyManager));
|
.PlayerBetHandler(responseDispatcher, userRegistry, lobbyManager));
|
||||||
|
|
||||||
|
// RAISE registration
|
||||||
|
parserDispatcher.register(
|
||||||
|
"RAISE",
|
||||||
|
new ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.raise
|
||||||
|
.PlayerRaiseParser());
|
||||||
|
commandRouter.register(
|
||||||
|
ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.raise.PlayerRaiseRequest
|
||||||
|
.class,
|
||||||
|
(ch.unibas.dmi.dbis.cs108.casono.server.network.command.execution.CommandHandler<
|
||||||
|
ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.raise
|
||||||
|
.PlayerRaiseRequest>)
|
||||||
|
new ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.raise
|
||||||
|
.PlayerRaiseHandler(
|
||||||
|
responseDispatcher, userRegistry, lobbyManager));
|
||||||
|
|
||||||
// GET_LOBBY_STATUS registration
|
// GET_LOBBY_STATUS registration
|
||||||
parserDispatcher.register(
|
parserDispatcher.register(
|
||||||
"GET_LOBBY_STATUS",
|
"GET_LOBBY_STATUS",
|
||||||
|
|||||||
+120
@@ -0,0 +1,120 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.raise;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.GameController;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.player.PlayerId;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.LobbyId;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.LobbyManager;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserRegistry;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.execution.CommandHandler;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.ErrorResponse;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.OkResponse;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for the `RAISE` command.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This handler validates the request (amount >= 0), resolves the user and
|
||||||
|
* target lobby (by
|
||||||
|
* `GAME_ID` when provided or by session username otherwise), checks that a game
|
||||||
|
* is running and then
|
||||||
|
* forwards the action to the {@code GameController}.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* On failure the handler dispatches an {@link ErrorResponse} with an
|
||||||
|
* appropriate error code
|
||||||
|
* (e.g. {@code INVALID_AMOUNT}, {@code NOT_IN_LOBBY}, {@code LOBBY_NOT_FOUND},
|
||||||
|
* {@code
|
||||||
|
* GAME_NOT_STARTED}, {@code GAME_ACTION_FAILED}). On success it dispatches an
|
||||||
|
* {@link OkResponse}.
|
||||||
|
*/
|
||||||
|
public class PlayerRaiseHandler extends CommandHandler<PlayerRaiseRequest> {
|
||||||
|
private final UserRegistry userRegistry;
|
||||||
|
private final LobbyManager lobbyManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@code PlayerRaiseHandler}.
|
||||||
|
*
|
||||||
|
* @param responseDispatcher dispatcher used to send responses back to the
|
||||||
|
* client
|
||||||
|
* @param userRegistry registry to resolve users from session ids
|
||||||
|
* @param lobbyManager manager used to lookup lobbies and their game
|
||||||
|
* controllers
|
||||||
|
*/
|
||||||
|
public PlayerRaiseHandler(
|
||||||
|
ResponseDispatcher responseDispatcher,
|
||||||
|
UserRegistry userRegistry,
|
||||||
|
LobbyManager lobbyManager) {
|
||||||
|
super(responseDispatcher);
|
||||||
|
this.userRegistry = userRegistry;
|
||||||
|
this.lobbyManager = lobbyManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the raise request: validate parameters, resolve lobby and game, and
|
||||||
|
* forward the raise
|
||||||
|
* action to the game controller. Sends an {@link ErrorResponse} on failure or
|
||||||
|
* an {@link
|
||||||
|
* OkResponse} on success.
|
||||||
|
*
|
||||||
|
* @param request the parsed {@link PlayerRaiseRequest}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void execute(PlayerRaiseRequest request) {
|
||||||
|
int amount = request.getAmount();
|
||||||
|
|
||||||
|
if (amount < 0) {
|
||||||
|
responseDispatcher.dispatch(
|
||||||
|
new ErrorResponse(
|
||||||
|
request.getContext(), "INVALID_AMOUNT", "Amount must be non-negative"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<ch.unibas.dmi.dbis.cs108.casono.server.domain.user.User> opt = userRegistry
|
||||||
|
.getBySessionId(request.getSessionId());
|
||||||
|
if (opt.isEmpty()) {
|
||||||
|
responseDispatcher.dispatch(
|
||||||
|
new ErrorResponse(request.getContext(), "NOT_LOGGED_IN", "User not logged in"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String username = opt.get().getName();
|
||||||
|
|
||||||
|
Integer gameId = request.getGameId();
|
||||||
|
var lobby = (gameId != null)
|
||||||
|
? lobbyManager.getLobby(LobbyId.of(gameId))
|
||||||
|
: lobbyManager.getLobbyByUsername(username);
|
||||||
|
|
||||||
|
if (lobby == null) {
|
||||||
|
if (gameId != null) {
|
||||||
|
responseDispatcher.dispatch(
|
||||||
|
new ErrorResponse(
|
||||||
|
request.getContext(), "LOBBY_NOT_FOUND", "Lobby not found"));
|
||||||
|
} else {
|
||||||
|
responseDispatcher.dispatch(
|
||||||
|
new ErrorResponse(
|
||||||
|
request.getContext(), "NOT_IN_LOBBY", "User not in a lobby"));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameController game = lobby.getGameController();
|
||||||
|
if (game == null) {
|
||||||
|
responseDispatcher.dispatch(
|
||||||
|
new ErrorResponse(
|
||||||
|
request.getContext(), "GAME_NOT_STARTED", "Game not started"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
game.playerRaise(PlayerId.of(username), amount);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
responseDispatcher.dispatch(
|
||||||
|
new ErrorResponse(request.getContext(), "GAME_ACTION_FAILED", e.getMessage()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
responseDispatcher.dispatch(new OkResponse(request.getContext()));
|
||||||
|
}
|
||||||
|
}
|
||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.raise;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.CommandParser;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.PrimitiveRequest;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.accessor.RequestParameterAccessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser for the `RAISE` command.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Parses the request parameters and builds a {@link PlayerRaiseRequest}.
|
||||||
|
* Expected parameters:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>`GAME_ID` (optional) - numeric id of the lobby/game to target
|
||||||
|
* <li>`AMOUNT` (required) - amount to raise
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public class PlayerRaiseParser implements CommandParser<PlayerRaiseRequest> {
|
||||||
|
@Override
|
||||||
|
public PlayerRaiseRequest parse(PrimitiveRequest primitiveRequest) {
|
||||||
|
RequestParameterAccessor accessor = new RequestParameterAccessor(primitiveRequest.parameters());
|
||||||
|
|
||||||
|
Integer gameId = null;
|
||||||
|
try {
|
||||||
|
gameId = accessor.optional("GAME_ID", null, Integer::parseInt);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// parse handled by framework
|
||||||
|
}
|
||||||
|
|
||||||
|
int amount = accessor.require("AMOUNT", Integer::parseInt);
|
||||||
|
|
||||||
|
return new PlayerRaiseRequest(primitiveRequest.context(), gameId, amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.raise;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.Request;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request for the `RAISE` command.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Contains the optional target `gameId` and the `amount` the player wants to
|
||||||
|
* raise.
|
||||||
|
*/
|
||||||
|
public class PlayerRaiseRequest extends Request {
|
||||||
|
private final Integer gameId;
|
||||||
|
private final int amount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@code PlayerRaiseRequest}.
|
||||||
|
*
|
||||||
|
* @param context the request context
|
||||||
|
* @param gameId optional game id of the targeted lobby (may be {@code null})
|
||||||
|
* @param amount the raise amount (non-negative)
|
||||||
|
*/
|
||||||
|
public PlayerRaiseRequest(RequestContext context, Integer gameId, int amount) {
|
||||||
|
super(context);
|
||||||
|
this.gameId = gameId;
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the optional target game id.
|
||||||
|
*
|
||||||
|
* @return the game id or {@code null} if not provided
|
||||||
|
*/
|
||||||
|
public Integer getGameId() {
|
||||||
|
return gameId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the requested raise amount.
|
||||||
|
*
|
||||||
|
* @return the raise amount
|
||||||
|
*/
|
||||||
|
public int getAmount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user