diff --git a/documents/docs/networking/commands/protocol-document.md b/documents/docs/networking/commands/protocol-document.md index 8ac0631..d22cbb2 100644 --- a/documents/docs/networking/commands/protocol-document.md +++ b/documents/docs/networking/commands/protocol-document.md @@ -62,6 +62,7 @@ This document describes the protocol for client-server communication in our appl - [Success Response](#success-response) - [Example Request](#example-request) - [Example Response](#example-response) + - [BET command](#bet-command) - [SEND_MESSAGE command](#send_message-command) - [Required pre-execution checks](#required-pre-execution-checks) - [Request Parameters](#request-parameters) @@ -663,6 +664,63 @@ GET_GAME_STATE GAME_ID=1 END ``` +## BET command + +The `BET` command lets the currently logged-in player place a bet in the ongoing game for their lobby. + +### Required pre-execution checks + +- [`UserLoggedInCheck`](#userloggedincheck) + +### Request Parameters + +| Parameter Name | Type | Optional | Description | +| :------------- | :--- | :------: | :---------- | +| `GAME_ID` | `int` | yes | Numeric id of the lobby/game to target. If omitted the server resolves the lobby by the requesting session's user. | +| `AMOUNT` | `int` | no | Amount the player wants to bet | + +### Implementation notes + +- Parser: `PlayerBetParser` — reads `AMOUNT` and optionally `GAME_ID`. +- Handler: `PlayerBetHandler` — validates the session, lobby (by id when provided or else by session), player's turn and balance and forwards to `GameController`. + +### Success Response + +No additional response fields. Server replies with `+OK` on success. + +### Error Response + +| Code | Description | +| :--- | :---------- | +| `NOT_YOUR_TURN` | The player attempted to bet when not their turn | +| `INSUFFICIENT_FUNDS` | Player does not have enough chips | +| `INVALID_AMOUNT` | Amount parameter is invalid | +| `GAME_NOT_STARTED` | No game is running in the lobby | +| `NOT_IN_LOBBY` | Requesting user is not a member of the lobby | +| `LOBBY_NOT_FOUND` | The specified `GAME_ID` does not exist | + +### Example Request + +``` +BET GAME_ID=1 AMOUNT=50 +``` + +### Example Response (success) + +``` ++OK +END +``` + +### Example Response (error) + +``` +-ERR + CODE=INSUFFICIENT_FUNDS + MSG=Not enough chips +END +``` + ## GET_LOBBY_STATUS command The `GET_LOBBY_STATUS` command requests the server to return the current state of a lobby, including the list of players and their ready state. diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/ServerApp.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/ServerApp.java index f9007eb..7ca3406 100644 --- a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/ServerApp.java +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/ServerApp.java @@ -169,6 +169,18 @@ public class ServerApp { .GetGameStateHandler( responseDispatcher, lobbyManager, userRegistry)); + // BET registration + parserDispatcher.register( + "BET", + new ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.bet.PlayerBetParser()); + commandRouter.register( + ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.bet.PlayerBetRequest.class, + (ch.unibas.dmi.dbis.cs108.casono.server.network.command.execution.CommandHandler< + ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.bet + .PlayerBetRequest>) + new ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.bet + .PlayerBetHandler(responseDispatcher, userRegistry, lobbyManager)); + // GET_LOBBY_STATUS registration parserDispatcher.register( "GET_LOBBY_STATUS", diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/app/commands/game/bet/PlayerBetHandler.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/app/commands/game/bet/PlayerBetHandler.java new file mode 100644 index 0000000..ea39326 --- /dev/null +++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/app/commands/game/bet/PlayerBetHandler.java @@ -0,0 +1,108 @@ +package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.bet; + +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 `BET` command. + * + *
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}. + * + *
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 PlayerBetHandler extends CommandHandler Parses the request parameters and builds a {@link PlayerBetRequest}. Expected parameters:
+ *
+ * Contains the optional target `gameId` and the `amount` the player wants to bet.
+ */
+public class PlayerBetRequest extends Request {
+ private final Integer gameId;
+ private final int amount;
+
+ /**
+ * Creates a new {@code PlayerBetRequest}.
+ *
+ * @param context the request context
+ * @param gameId optional game id of the targeted lobby (may be {@code null})
+ * @param amount the bet amount (non-negative)
+ */
+ public PlayerBetRequest(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 bet amount.
+ *
+ * @return the bet amount
+ */
+ public int getAmount() {
+ return amount;
+ }
+}
diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/GameController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/GameController.java
index aa5585a..02254ba 100644
--- a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/GameController.java
+++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/server/domain/game/GameController.java
@@ -1,5 +1,6 @@
package ch.unibas.dmi.dbis.cs108.casono.server.domain.game;
+import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.action.BetAction;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.action.BlindAction;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.action.CallAction;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.game.action.FoldAction;
@@ -180,6 +181,16 @@ public class GameController {
engine.processAction(new RaiseAction(playerId, amount));
}
+ /**
+ * Processes a player's bet action by sending a BetAction to the GameEngine.
+ *
+ * @param playerId The ID of the player who is betting.
+ * @param amount The amount the player is betting.
+ */
+ public void playerBet(PlayerId playerId, int amount) {
+ engine.processAction(new BetAction(playerId, amount));
+ }
+
/**
* Retrieves the current game state from the GameEngine.
*
+ *
+ */
+public class PlayerBetParser implements CommandParser