Compare commits

...

6 Commits

Author SHA1 Message Date
Jona Walpert cfd13b43fc Feat: register "Call", "Fold","Bet","Raise","AddPlayer" command and change import locatio nto match new folder structure 2026-04-10 13:52:57 +02:00
Jona Walpert 5916c26b86 Feat: add "Call" command 2026-04-10 13:51:48 +02:00
Jona Walpert d734f815e8 Feat: add "Fold" command 2026-04-10 13:51:16 +02:00
Jona Walpert c5518d64a3 Feat: add "Raise" command 2026-04-10 13:50:57 +02:00
Jona Walpert f1e09cb328 Feat: add "Bet" command 2026-04-10 13:50:36 +02:00
Jona Walpert b06cd571b0 Feat: add "AddPlayer" command 2026-04-10 13:50:09 +02:00
16 changed files with 391 additions and 67 deletions
@@ -1,5 +1,14 @@
package ch.unibas.dmi.dbis.cs108.casono.server;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.add_player.AddPlayerHandler;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.add_player.AddPlayerParser;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.add_player.AddPlayerRequest;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.bet.PlayerBetHandler;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.bet.PlayerBetParser;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.bet.PlayerBetRequest;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.call.PlayerCallHandler;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.call.PlayerCallParser;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.call.PlayerCallRequest;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameHandler;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameParser;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameRequest;
@@ -15,6 +24,9 @@ import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.logout.LogoutRequest;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.ping.PingHandler;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.ping.PingParser;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.ping.PingRequest;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.raise.PlayerRaiseHandler;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.raise.PlayerRaiseParser;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.raise.PlayerRaiseRequest;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserCleanupJob;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserRegistry;
import ch.unibas.dmi.dbis.cs108.casono.server.network.NetworkManager;
@@ -85,9 +97,12 @@ public class ServerApp {
/**
* Registers command parsers and handlers.
*
* @param parserDispatcher the dispatcher responsible for parsing incoming commands
* @param commandRouter the router that dispatches parsed commands to appropriate handlers
* @param responseDispatcher the dispatcher responsible for sending responses back to clients
* @param parserDispatcher the dispatcher responsible for parsing incoming
* commands
* @param commandRouter the router that dispatches parsed commands to
* appropriate handlers
* @param responseDispatcher the dispatcher responsible for sending responses
* back to clients
*/
private static void registerCommands(
CommandParserDispatcher parserDispatcher,
@@ -113,5 +128,25 @@ public class ServerApp {
parserDispatcher.register("LIST_USERS", new ListUsersParser());
commandRouter.register(
ListUsersRequest.class, new ListUsersHandler(responseDispatcher, userRegistry));
// ADD_PLAYER
parserDispatcher.register("ADD_PLAYER", new AddPlayerParser());
commandRouter.register(AddPlayerRequest.class,
new AddPlayerHandler(userRegistry, responseDispatcher));
// BET
parserDispatcher.register("BET", new PlayerBetParser());
commandRouter.register(PlayerBetRequest.class,
new PlayerBetHandler(responseDispatcher));
// CALL
parserDispatcher.register("CALL", new PlayerCallParser());
commandRouter.register(PlayerCallRequest.class,
new PlayerCallHandler(responseDispatcher));
// RAISE
parserDispatcher.register("RAISE", new PlayerRaiseParser());
commandRouter.register(PlayerRaiseRequest.class,
new PlayerRaiseHandler(responseDispatcher));
}
}
@@ -0,0 +1,33 @@
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.add_player;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserRegistry;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.User;
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.execution.CommandHandler;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.OkResponse;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.ErrorResponse;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher;
import java.util.Optional;
/**
* Handler for the ADD_PLAYER command.
*/
public class AddPlayerHandler extends CommandHandler<AddPlayerRequest> {
private final UserRegistry userRegistry;
public AddPlayerHandler(UserRegistry userRegistry, ResponseDispatcher responseDispatcher) {
super(responseDispatcher);
this.userRegistry = userRegistry;
}
@Override
public void execute(AddPlayerRequest request) {
Optional<User> created = userRegistry.registerIfAvailable(request.getName(), request.getContext().sessionId());
if (created.isEmpty()) {
responseDispatcher.dispatch(new ErrorResponse(request.getContext(), "NAME_TAKEN", "Name already taken"));
return;
}
responseDispatcher.dispatch(new OkResponse(request.getContext()));
}
}
@@ -0,0 +1,20 @@
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.add_player;
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;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.accessor.ParameterParseException;
/** Parser for the ADD_PLAYER command. */
public class AddPlayerParser implements CommandParser<AddPlayerRequest> {
@Override
public AddPlayerRequest parse(PrimitiveRequest primitiveRequest) {
RequestParameterAccessor accessor = new RequestParameterAccessor(primitiveRequest.parameters());
String name = accessor.require("NAME");
int chips = accessor.require("CHIPS", Integer::parseInt);
return new AddPlayerRequest(primitiveRequest.context(), name, chips);
}
}
@@ -0,0 +1,24 @@
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.add_player;
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 data for the ADD_PLAYER command. */
public class AddPlayerRequest extends Request {
private final String name;
private final int chips;
public AddPlayerRequest(RequestContext context, String name, int chips) {
super(context);
this.name = name;
this.chips = chips;
}
public String getName() {
return name;
}
public int getChips() {
return chips;
}
}
@@ -0,0 +1,27 @@
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.bet;
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.execution.CommandHandler;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.OkResponse;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.ErrorResponse;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher;
/**
* Handler for the BET command.
*/
public class PlayerBetHandler extends CommandHandler<PlayerBetRequest> {
public PlayerBetHandler(ResponseDispatcher responseDispatcher) {
super(responseDispatcher);
}
@Override
public void execute(PlayerBetRequest request) {
if (request.getAmount() < 0) {
responseDispatcher
.dispatch(new ErrorResponse(request.getContext(), "INVALID_AMOUNT", "Amount must be non-negative"));
return;
}
responseDispatcher.dispatch(new OkResponse(request.getContext()));
}
}
@@ -0,0 +1,17 @@
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.bet;
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 BET command. */
public class PlayerBetParser implements CommandParser<PlayerBetRequest> {
@Override
public PlayerBetRequest parse(PrimitiveRequest primitiveRequest) {
RequestParameterAccessor accessor = new RequestParameterAccessor(primitiveRequest.parameters());
int amount = accessor.require("AMOUNT", Integer::parseInt);
return new PlayerBetRequest(primitiveRequest.context(), amount);
}
}
@@ -0,0 +1,18 @@
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.bet;
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 BET command. */
public class PlayerBetRequest extends Request {
private final int amount;
public PlayerBetRequest(RequestContext context, int amount) {
super(context);
this.amount = amount;
}
public int getAmount() {
return amount;
}
}
@@ -0,0 +1,21 @@
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.call;
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.execution.CommandHandler;
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;
/**
* Minimal handler for CALL: acknowledges the command.
*/
public class PlayerCallHandler extends CommandHandler<PlayerCallRequest> {
public PlayerCallHandler(ResponseDispatcher responseDispatcher) {
super(responseDispatcher);
}
@Override
public void execute(PlayerCallRequest request) {
// TODO: integrate with game engine to process call.
responseDispatcher.dispatch(new OkResponse(request.getContext()));
}
}
@@ -0,0 +1,12 @@
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.call;
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.CommandParser;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.PrimitiveRequest;
/** Parser for the CALL command (no parameters). */
public class PlayerCallParser implements CommandParser<PlayerCallRequest> {
@Override
public PlayerCallRequest parse(PrimitiveRequest primitiveRequest) {
return new PlayerCallRequest(primitiveRequest.context());
}
}
@@ -0,0 +1,11 @@
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.call;
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 CALL command. */
public class PlayerCallRequest extends Request {
public PlayerCallRequest(RequestContext context) {
super(context);
}
}
@@ -0,0 +1,19 @@
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.fold;
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.execution.CommandHandler;
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;
/** Minimal handler for FOLD: acknowledges the command. */
public class PlayerFoldHandler extends CommandHandler<PlayerFoldRequest> {
public PlayerFoldHandler(ResponseDispatcher responseDispatcher) {
super(responseDispatcher);
}
@Override
public void execute(PlayerFoldRequest request) {
// TODO: integrate with game engine to process call.
responseDispatcher.dispatch(new OkResponse(request.getContext()));
}
}
@@ -0,0 +1,12 @@
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.fold;
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.CommandParser;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.PrimitiveRequest;
/** Parser for the FOLD command (no parameters). */
public class PlayerFoldParser implements CommandParser<PlayerFoldRequest> {
@Override
public PlayerFoldRequest parse(PrimitiveRequest primitiveRequest) {
return new PlayerFoldRequest(primitiveRequest.context());
}
}
@@ -0,0 +1,11 @@
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.fold;
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 FOLD command. */
public class PlayerFoldRequest extends Request {
public PlayerFoldRequest(RequestContext context) {
super(context);
}
}
@@ -0,0 +1,29 @@
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.game.raise;
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.execution.CommandHandler;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.OkResponse;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.ErrorResponse;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher;
/**
* Minimal handler for RAISE: validates and acknowledges the command.
*/
public class PlayerRaiseHandler extends CommandHandler<PlayerRaiseRequest> {
public PlayerRaiseHandler(ResponseDispatcher responseDispatcher) {
super(responseDispatcher);
}
@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;
}
responseDispatcher.dispatch(new OkResponse(request.getContext()));
}
}
@@ -0,0 +1,17 @@
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. */
public class PlayerRaiseParser implements CommandParser<PlayerRaiseRequest> {
@Override
public PlayerRaiseRequest parse(PrimitiveRequest primitiveRequest) {
RequestParameterAccessor accessor = new RequestParameterAccessor(primitiveRequest.parameters());
int amount = accessor.require("AMOUNT", Integer::parseInt);
return new PlayerRaiseRequest(primitiveRequest.context(), amount);
}
}
@@ -0,0 +1,18 @@
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 RAISE command. */
public class PlayerRaiseRequest extends Request {
private final int amount;
public PlayerRaiseRequest(RequestContext context, int amount) {
super(context);
this.amount = amount;
}
public int getAmount() {
return amount;
}
}