Style: Apply Spotless

This commit is contained in:
Mathis Ginkel
2026-04-09 20:36:18 +02:00
parent 84e68d8b20
commit 566c9375ab
26 changed files with 275 additions and 307 deletions
@@ -3,7 +3,6 @@ package ch.unibas.dmi.dbis.cs108.casono.client;
/** /**
* Entry point for the Casono client application. Handles client startup and connection parameters. * Entry point for the Casono client application. Handles client startup and connection parameters.
*/ */
import ch.unibas.dmi.dbis.cs108.casono.client.ui.Launcher; import ch.unibas.dmi.dbis.cs108.casono.client.ui.Launcher;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@@ -3,15 +3,13 @@ package ch.unibas.dmi.dbis.cs108.casono.client.chat;
import ch.unibas.dmi.dbis.cs108.casono.client.network.ChatClient; import ch.unibas.dmi.dbis.cs108.casono.client.network.ChatClient;
import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService; import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService;
import ch.unibas.dmi.dbis.cs108.casono.client.ui.chatui.ChatBoxController; import ch.unibas.dmi.dbis.cs108.casono.client.ui.chatui.ChatBoxController;
import javafx.application.Platform; import java.util.LinkedHashMap;
import org.jspecify.annotations.Nullable; import java.util.List;
import java.util.Map;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.Map; import javafx.application.Platform;
import java.util.List; import org.jspecify.annotations.Nullable;
import java.util.LinkedHashMap;
/** /**
* responsible for the transferring of messages from the server to the ChatModel or from the * responsible for the transferring of messages from the server to the ChatModel or from the
@@ -31,7 +29,6 @@ public class ChatController {
private int lobbyId = -1; private int lobbyId = -1;
private final Timer timer; private final Timer timer;
public record ChatKey(ChatType type, @Nullable String targetUser) { public record ChatKey(ChatType type, @Nullable String targetUser) {
public ChatKey(ChatType type) { public ChatKey(ChatType type) {
this(type, null); this(type, null);
@@ -56,7 +53,8 @@ public class ChatController {
new TimerTask() { new TimerTask() {
@Override @Override
public void run() { public void run() {
Platform.runLater(() -> { Platform.runLater(
() -> {
clientService.ping(); clientService.ping();
receiveMessage(); receiveMessage();
}); });
@@ -84,21 +82,30 @@ public class ChatController {
break; break;
case ChatType.LOBBY: case ChatType.LOBBY:
if (msg.lobbyId == lobbyId) { if (msg.lobbyId == lobbyId) {
chatModelMap.computeIfAbsent(new ChatKey(ChatType.LOBBY), chatModelMap
(_key) -> new ChatModel(ChatType.LOBBY, username, msg.lobbyId, null)).addMessage(msg); .computeIfAbsent(
new ChatKey(ChatType.LOBBY),
(_key) ->
new ChatModel(
ChatType.LOBBY,
username,
msg.lobbyId,
null))
.addMessage(msg);
} }
break; break;
case ChatType.WHISPER: case ChatType.WHISPER:
if (msg.target.equals(username)) { if (msg.target.equals(username)) {
if (chatModelMap.containsKey(new ChatKey(ChatType.WHISPER, msg.sender))) { if (chatModelMap.containsKey(
chatModelMap.get(new ChatKey(ChatType.WHISPER, msg.sender)).addMessage(msg); new ChatKey(ChatType.WHISPER, msg.sender))) {
chatModelMap
.get(new ChatKey(ChatType.WHISPER, msg.sender))
.addMessage(msg);
} else { } else {
chatBoxController.addWhisperChat(msg.sender); chatBoxController.addWhisperChat(msg.sender);
} }
} }
break; break;
} }
} }
} }
@@ -106,6 +113,7 @@ public class ChatController {
/** /**
* method to send a message to the server * method to send a message to the server
*
* @param message * @param message
*/ */
public void onSendToNetwork(Message message) { public void onSendToNetwork(Message message) {
@@ -1,10 +1,9 @@
package ch.unibas.dmi.dbis.cs108.casono.client.chat; package ch.unibas.dmi.dbis.cs108.casono.client.chat;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.function.Consumer; import java.util.function.Consumer;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
/** /**
* ChatModel, stores the data for a specific chat * ChatModel, stores the data for a specific chat
@@ -19,15 +18,10 @@ public class ChatModel {
private final ChatType chattype; private final ChatType chattype;
/** /** The person currently using this client */
* The person currently using this client
*/
public final String username; public final String username;
/** /** The person to send the message to If the chat is a whisper chat */
* The person to send the message to
* If the chat is a whisper chat
*/
private final String target; private final String target;
private final IntegerProperty count; private final IntegerProperty count;
@@ -67,7 +61,6 @@ public class ChatModel {
listeners.stream().forEach((l) -> l.accept(messages.getLast())); listeners.stream().forEach((l) -> l.accept(messages.getLast()));
} }
public void addListener(Consumer<Message> listener) { public void addListener(Consumer<Message> listener) {
this.listeners.add(listener); this.listeners.add(listener);
} }
@@ -3,13 +3,12 @@ package ch.unibas.dmi.dbis.cs108.casono.client.chat;
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.RequestParameter; import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.RequestParameter;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBody; import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBody;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBodyBuilder; import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBodyBuilder;
import org.jspecify.annotations.NonNull;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.jspecify.annotations.NonNull;
/** /**
* Message Object for internal handling of Chat-Messages TODO: Should be used on both sides of the * Message Object for internal handling of Chat-Messages TODO: Should be used on both sides of the
@@ -101,10 +100,12 @@ public class Message {
/** Pattern, to analyze the response String with the given parameters */ /** Pattern, to analyze the response String with the given parameters */
public static Pattern msgRex = public static Pattern msgRex =
Pattern.compile( Pattern.compile(
"TYPE=(?<type>\\w+) " + "(GAME=(?<game>\\w+) )?" + "TYPE=(?<type>\\w+) "
"USER=(?<user>\\w+) " + "(TARGET=(?<target>\\w+) )?" + + "(GAME=(?<game>\\w+) )?"
"TIME=(?<time>[0-9:.]+) " + "TEXT='(?<text>([^']|\\')+)'"); + "USER=(?<user>\\w+) "
+ "(TARGET=(?<target>\\w+) )?"
+ "TIME=(?<time>[0-9:.]+) "
+ "TEXT='(?<text>([^']|\\')+)'");
/** /**
* Method to create a Message Object, from the information given by the String * Method to create a Message Object, from the information given by the String
@@ -167,35 +168,43 @@ public class Message {
String typeString = getParString(parameters, "TYPE"); String typeString = getParString(parameters, "TYPE");
ChatType type = ChatType.valueOf(typeString); ChatType type = ChatType.valueOf(typeString);
return switch (type) { return switch (type) {
case GLOBAL -> new Message(ChatType.GLOBAL, case GLOBAL ->
new Message(
ChatType.GLOBAL,
-1, -1,
getParString(parameters, "USER"), getParString(parameters, "USER"),
null, null,
getParString(parameters, "TIME"), getParString(parameters, "TIME"),
getParString(parameters, "TEXT") getParString(parameters, "TEXT"));
); case LOBBY ->
case LOBBY -> new Message(ChatType.LOBBY, new Message(
ChatType.LOBBY,
Integer.parseInt(getParString(parameters, "GAME")), Integer.parseInt(getParString(parameters, "GAME")),
getParString(parameters, "USER"), getParString(parameters, "USER"),
null, null,
getParString(parameters, "TIME"), getParString(parameters, "TIME"),
getParString(parameters, "TEXT") getParString(parameters, "TEXT"));
); case WHISPER ->
case WHISPER -> new Message(ChatType.WHISPER, new Message(
ChatType.WHISPER,
Integer.parseInt(getParString(parameters, "GAME", "-1")), Integer.parseInt(getParString(parameters, "GAME", "-1")),
getParString(parameters, "USER"), getParString(parameters, "USER"),
getParString(parameters, "TARGET"), getParString(parameters, "TARGET"),
getParString(parameters, "TIME"), getParString(parameters, "TIME"),
getParString(parameters, "TEXT") getParString(parameters, "TEXT"));
);
}; };
} }
private static @NonNull String getParString(List<RequestParameter> parameters, String keyString) {
private static @NonNull String getParString(
List<RequestParameter> parameters, String keyString) {
return getParString(parameters, keyString, null); return getParString(parameters, keyString, null);
} }
private static @NonNull String getParString(List<RequestParameter> parameters, String keyString, String defaultVal) {
Optional<String> parOption = parameters.stream().filter((p) -> keyString.equals(p.key())) private static @NonNull String getParString(
List<RequestParameter> parameters, String keyString, String defaultVal) {
Optional<String> parOption =
parameters.stream()
.filter((p) -> keyString.equals(p.key()))
.findFirst() .findFirst()
.map(RequestParameter::value); .map(RequestParameter::value);
if (parOption.isEmpty()) { if (parOption.isEmpty()) {
@@ -2,16 +2,15 @@ package ch.unibas.dmi.dbis.cs108.casono.client.network;
import ch.unibas.dmi.dbis.cs108.casono.client.chat.Message; import ch.unibas.dmi.dbis.cs108.casono.client.chat.Message;
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.RequestParameter; import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.RequestParameter;
import java.util.ArrayList;
import java.util.List;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
/** /**
* The ChatClient class is responsible for sending messages to the server and * The ChatClient class is responsible for sending messages to the server and retrieving messages
* retrieving messages from the server. It uses the ClientService to send * from the server. It uses the ClientService to send commands and receive responses from the
* commands and receive responses from the server. * server.
*/ */
public class ChatClient { public class ChatClient {
@@ -21,8 +20,8 @@ public class ChatClient {
/** /**
* Constructs a ChatClient with the given ClientService for communication. * Constructs a ChatClient with the given ClientService for communication.
* *
* @param clientService The ClientService instance used to send commands and * @param clientService The ClientService instance used to send commands and receive responses
* receive responses from the server. * from the server.
*/ */
public ChatClient(ClientService clientService) { public ChatClient(ClientService clientService) {
this.clientService = clientService; this.clientService = clientService;
@@ -30,8 +29,8 @@ public class ChatClient {
} }
/** /**
* Send a Message to the server by converting it to a string format and * Send a Message to the server by converting it to a string format and sending a "SEND_MESSAGE"
* sending a "SEND_MESSAGE" command with the message content as arguments. * command with the message content as arguments.
* *
* @param message The Message object to be sent to the server. * @param message The Message object to be sent to the server.
*/ */
@@ -42,17 +41,18 @@ public class ChatClient {
} }
/** /**
* Retrieve messages from the server by first sending a "GET_MESSAGE_COUNT" * Retrieve messages from the server by first sending a "GET_MESSAGE_COUNT" command to determine
* command to determine how many messages are available and then sending * how many messages are available and then sending "GET_NEXT_MESSAGE" commands in a loop to
* "GET_NEXT_MESSAGE" commands in a loop to retrieve each message. The * retrieve each message. The retrieved messages are parsed into Message objects and returned as
* retrieved messages are parsed into Message objects and returned as a list. * a list.
* *
* @return A list of Message objects representing the messages retrieved from * @return A list of Message objects representing the messages retrieved from the server.
* the server.
*/ */
public List<Message> getMessages() { public List<Message> getMessages() {
logger.info("Asking server for new messages"); logger.info("Asking server for new messages");
List<RequestParameter> countStr = ClientService.convertToRequestParameters(clientService.processCommand("GET_MESSAGE_COUNT")); List<RequestParameter> countStr =
ClientService.convertToRequestParameters(
clientService.processCommand("GET_MESSAGE_COUNT"));
RequestParameter countRes = countStr.getFirst(); RequestParameter countRes = countStr.getFirst();
if (!countRes.key().equals("COUNT")) { if (!countRes.key().equals("COUNT")) {
logger.error("Not the right response from server"); logger.error("Not the right response from server");
@@ -61,7 +61,9 @@ public class ChatClient {
logger.info("Got " + count + " messages"); logger.info("Got " + count + " messages");
ArrayList<Message> messages = new ArrayList<>(); ArrayList<Message> messages = new ArrayList<>();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
List<RequestParameter> msgRes = ClientService.convertToRequestParameters(clientService.processCommand("GET_NEXT_MESSAGE")); List<RequestParameter> msgRes =
ClientService.convertToRequestParameters(
clientService.processCommand("GET_NEXT_MESSAGE"));
Message msg = Message.toMessageReqPars(msgRes); Message msg = Message.toMessageReqPars(msgRes);
messages.add(msg); messages.add(msg);
} }
@@ -3,9 +3,6 @@ package ch.unibas.dmi.dbis.cs108.casono.client.network;
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.RequestParameter; import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.RequestParameter;
import ch.unibas.dmi.dbis.cs108.casono.server.network.transport.RawPacket; import ch.unibas.dmi.dbis.cs108.casono.server.network.transport.RawPacket;
import ch.unibas.dmi.dbis.cs108.casono.server.network.transport.TcpTransport; import ch.unibas.dmi.dbis.cs108.casono.server.network.transport.TcpTransport;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException; import java.io.IOException;
import java.net.Socket; import java.net.Socket;
import java.util.ArrayList; import java.util.ArrayList;
@@ -17,13 +14,13 @@ import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/** /**
* The ClientService class is responsible for managing the connection to the * The ClientService class is responsible for managing the connection to the server, sending
* server, * commands, and receiving responses. It uses a TcpTransport to communicate with the server and an
* sending commands, and receiving responses. It uses a TcpTransport to * ExecutorService to handle asynchronous requests.
* communicate
* with the server and an ExecutorService to handle asynchronous requests.
*/ */
public class ClientService { public class ClientService {
@@ -35,6 +32,7 @@ public class ClientService {
public static ArrayList<String> response; public static ArrayList<String> response;
private final AtomicInteger idGenerator; private final AtomicInteger idGenerator;
private final Logger logger; private final Logger logger;
/* /*
* Constructs a ClientService with the given server IP and port. It establishes * Constructs a ClientService with the given server IP and port. It establishes
* a socket connection to the server and initializes the TcpTransport and * a socket connection to the server and initializes the TcpTransport and
@@ -58,10 +56,11 @@ public class ClientService {
} }
executor = Executors.newSingleThreadExecutor(); executor = Executors.newSingleThreadExecutor();
} }
static Pattern responseRex = Pattern.compile("(?<key>\\w+)=(('(?<string>([^']|\\')+)')|(?<primVal>[+-]?[\\d\\w:]+))"); static Pattern responseRex =
Pattern.compile(
"(?<key>\\w+)=(('(?<string>([^']|\\')+)')|(?<primVal>[+-]?[\\d\\w:]+))");
/** /**
* Sends the Requests to the server and waits for the response If the response is "+OK" it * Sends the Requests to the server and waits for the response If the response is "+OK" it
@@ -73,19 +72,25 @@ public class ClientService {
private static String unescape(String input) { private static String unescape(String input) {
return input.replaceAll("\\\\'", "'"); return input.replaceAll("\\\\'", "'");
} }
public static List<RequestParameter> convertToRequestParameters(List<String> input) { public static List<RequestParameter> convertToRequestParameters(List<String> input) {
return input.stream().map((String parString)-> responseRex.matcher(parString)) return input.stream()
.map((String parString) -> responseRex.matcher(parString))
.filter(Matcher::matches) .filter(Matcher::matches)
.map((m)->{ .map(
(m) -> {
if (!(m.group("string") == null)) { if (!(m.group("string") == null)) {
return new RequestParameter(m.group("key"), unescape(m.group("string"))); return new RequestParameter(
m.group("key"), unescape(m.group("string")));
} else if (!(m.group("primVal") == null)) { } else if (!(m.group("primVal") == null)) {
return new RequestParameter(m.group("key"), m.group("primVal")); return new RequestParameter(m.group("key"), m.group("primVal"));
} else { } else {
throw new RuntimeException(); throw new RuntimeException();
} }
}).toList(); })
.toList();
} }
protected List<String> processCommand(String message) { protected List<String> processCommand(String message) {
List<String> response = new ArrayList<>(); List<String> response = new ArrayList<>();
sendRequest( sendRequest(
@@ -113,7 +118,6 @@ public class ClientService {
} }
line = line.replaceFirst("^\t", ""); line = line.replaceFirst("^\t", "");
response.add(line); response.add(line);
} }
if (success != null && success) { if (success != null && success) {
return; return;
@@ -128,13 +132,11 @@ public class ClientService {
} }
/** /**
* Helper method to send a request to the server using the ExecutorService. It * Helper method to send a request to the server using the ExecutorService. It submits the
* submits the request as a Runnable task and waits for its completion. If * request as a Runnable task and waits for its completion. If the task is interrupted or
* the task is interrupted or encounters an execution exception, it throws a * encounters an execution exception, it throws a RuntimeException with the appropriate cause.
* RuntimeException with the appropriate cause.
* *
* @param request The Runnable task representing the request to be sent to the * @param request The Runnable task representing the request to be sent to the server.
* server.
*/ */
private void sendRequest(Runnable request) { private void sendRequest(Runnable request) {
Future<?> future = executor.submit(request); Future<?> future = executor.submit(request);
@@ -148,11 +150,10 @@ public class ClientService {
} }
/** /**
* Helper method to extract the cause of an exception and return it as a * Helper method to extract the cause of an exception and return it as a RuntimeException. If
* RuntimeException. If the cause is null, it returns the original exception as * the cause is null, it returns the original exception as a RuntimeException. If the cause is
* a RuntimeException. If the cause is already a RuntimeException, it returns * already a RuntimeException, it returns it directly. Otherwise, it wraps the cause in a new
* it directly. Otherwise, it wraps the cause in a new RuntimeException and * RuntimeException and returns it.
* returns it.
* *
* @param e The exception from which to extract the cause. * @param e The exception from which to extract the cause.
* @return A RuntimeException representing the cause of the original exception. * @return A RuntimeException representing the cause of the original exception.
@@ -170,10 +171,9 @@ public class ClientService {
} }
/** /**
* Closes the socket connection to the server and shuts down the * Closes the socket connection to the server and shuts down the ExecutorService. It also closes
* ExecutorService. * the TcpTransport used for communication. If any IOException occurs during this process, it
* It also closes the TcpTransport used for communication. If any IOException * prints the exception to the console.
* occurs during this process, it prints the exception to the console.
*/ */
public void closeSocket() { public void closeSocket() {
try { try {
@@ -200,6 +200,4 @@ public class ClientService {
public void ping() { public void ping() {
processCommand("PING"); processCommand("PING");
} }
} }
@@ -1,27 +1,26 @@
package ch.unibas.dmi.dbis.cs108.casono.client.network; package ch.unibas.dmi.dbis.cs108.casono.client.network;
/** /**
* The CoreClient class provides basic functionalities for communicating with * The CoreClient class provides basic functionalities for communicating with the server, such as
* the * sending a ping command to check connectivity and logging in with a username. It uses the
* server, such as sending a ping command to check connectivity and logging in * ClientService to send commands and receive responses from the server.
* with a username. It uses the ClientService to send commands and receive
* responses from the server.
*/ */
public class CoreClient { public class CoreClient {
private final ClientService clientService; private final ClientService clientService;
/** /**
* Constructs a CoreClient with the given ClientService for communication. * Constructs a CoreClient with the given ClientService for communication.
* *
* @param clientservice The ClientService instance used to send commands and * @param clientservice The ClientService instance used to send commands and receive responses
* receive responses from the server. * from the server.
*/ */
public CoreClient(ClientService clientservice) { public CoreClient(ClientService clientservice) {
this.clientService = clientservice; this.clientService = clientservice;
} }
/** /**
* Sends a "PING" command to the server to check connectivity. The server * Sends a "PING" command to the server to check connectivity. The server should respond with a
* should respond with a "PONG" message if the connection is successful. * "PONG" message if the connection is successful.
*/ */
public void ping() { public void ping() {
clientService.processCommand("PING"); clientService.processCommand("PING");
@@ -3,14 +3,12 @@ package ch.unibas.dmi.dbis.cs108.casono.client.network;
import ch.unibas.dmi.dbis.cs108.casono.client.game.Card; import ch.unibas.dmi.dbis.cs108.casono.client.game.Card;
import ch.unibas.dmi.dbis.cs108.casono.client.game.GameState; import ch.unibas.dmi.dbis.cs108.casono.client.game.GameState;
import ch.unibas.dmi.dbis.cs108.casono.client.game.Player; import ch.unibas.dmi.dbis.cs108.casono.client.game.Player;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* The GameClient class is responsible for communicating with the server to * The GameClient class is responsible for communicating with the server to retrieve the current
* retrieve the current game state. It sends a command to the server and * game state. It sends a command to the server and parses the response into a structured GameState
* parses the response into a structured GameState object. * object.
*/ */
public class GameClient { public class GameClient {
@@ -19,16 +17,16 @@ public class GameClient {
/** /**
* Constructs a GameClient with the given ClientService for communication. * Constructs a GameClient with the given ClientService for communication.
* *
* @param client The ClientService instance used to send commands and receive * @param client The ClientService instance used to send commands and receive responses from the
* responses from the server. * server.
*/ */
public GameClient(ClientService client) { public GameClient(ClientService client) {
this.client = client; this.client = client;
} }
/** /**
* Retrieves the current game state from the server by sending a command and * Retrieves the current game state from the server by sending a command and parsing the
* parsing the response. * response.
* *
* @return A GameState object representing the current state of the game. * @return A GameState object representing the current state of the game.
*/ */
@@ -43,13 +41,10 @@ public class GameClient {
* @param input The raw response string from the server. * @param input The raw response string from the server.
* @return A GameState object representing the current state of the game. * @return A GameState object representing the current state of the game.
*/ */
private GameState parseGameState(String input) {
private GameState parseGameState(List<String> input) { private GameState parseGameState(List<String> input) {
GameState state = new GameState(); GameState state = new GameState();
String[] lines = input.split("\n");
Player currentPlayer = null; Player currentPlayer = null;
Card currentCard = null; Card currentCard = null;
@@ -63,46 +58,26 @@ public class GameClient {
if (line.startsWith("PHASE=")) { if (line.startsWith("PHASE=")) {
state.phase = line.split("=")[1]; state.phase = line.split("=")[1];
} } else if (line.startsWith("POT=")) {
else if (line.startsWith("POT=")) {
state.pot = Integer.parseInt(line.split("=")[1]); state.pot = Integer.parseInt(line.split("=")[1]);
} } else if (line.startsWith("CURRENT_BET=")) {
else if (line.startsWith("CURRENT_BET=")) {
state.currentBet = Integer.parseInt(line.split("=")[1]); state.currentBet = Integer.parseInt(line.split("=")[1]);
} } else if (line.startsWith("DEALER=")) {
else if (line.startsWith("DEALER=")) {
state.dealer = Integer.parseInt(line.split("=")[1]); state.dealer = Integer.parseInt(line.split("=")[1]);
} } else if (line.startsWith("ACTIVE_PLAYER=")) {
else if (line.startsWith("ACTIVE_PLAYER=")) {
state.activePlayer = Integer.parseInt(line.split("=")[1]); state.activePlayer = Integer.parseInt(line.split("=")[1]);
} } else if (line.startsWith("PLAYER")) {
else if (line.startsWith("PLAYER")) {
currentPlayer = new Player(); currentPlayer = new Player();
state.players.add(currentPlayer); state.players.add(currentPlayer);
} } else if (line.startsWith("NAME=") && currentPlayer != null) {
else if (line.startsWith("NAME=") && currentPlayer != null) {
currentPlayer.name = line.split("=")[1]; currentPlayer.name = line.split("=")[1];
} } else if (line.startsWith("CHIPS=") && currentPlayer != null) {
else if (line.startsWith("CHIPS=") && currentPlayer != null) {
currentPlayer.chips = Integer.parseInt(line.split("=")[1]); currentPlayer.chips = Integer.parseInt(line.split("=")[1]);
} } else if (line.startsWith("BET=") && currentPlayer != null) {
else if (line.startsWith("BET=") && currentPlayer != null) {
currentPlayer.bet = Integer.parseInt(line.split("=")[1]); currentPlayer.bet = Integer.parseInt(line.split("=")[1]);
} } else if (line.startsWith("STATE=") && currentPlayer != null) {
else if (line.startsWith("STATE=") && currentPlayer != null) {
currentPlayer.state = line.split("=")[1]; currentPlayer.state = line.split("=")[1];
} } else if (line.startsWith("CARD")) {
else if (line.startsWith("CARD")) {
currentCard = new Card(); currentCard = new Card();
if (currentPlayer != null) { if (currentPlayer != null) {
@@ -110,13 +85,9 @@ public class GameClient {
} else { } else {
state.communityCards.add(currentCard); state.communityCards.add(currentCard);
} }
} } else if (line.startsWith("VALUE=") && currentCard != null) {
else if (line.startsWith("VALUE=") && currentCard != null) {
currentCard.value = line.split("=")[1]; currentCard.value = line.split("=")[1];
} } else if (line.startsWith("SUIT=") && currentCard != null) {
else if (line.startsWith("SUIT=") && currentCard != null) {
currentCard.suit = line.split("=")[1]; currentCard.suit = line.split("=")[1];
} }
} }
@@ -1,10 +1,9 @@
package ch.unibas.dmi.dbis.cs108.casono.client.network; package ch.unibas.dmi.dbis.cs108.casono.client.network;
/** /**
* The LobbyClient class is responsible for communicating with the server to * The LobbyClient class is responsible for communicating with the server to manage game lobbies. It
* manage game lobbies. It provides methods to create a lobby, join a lobby, * provides methods to create a lobby, join a lobby, and fetch the current status of a lobby by
* and fetch the current status of a lobby by sending appropriate commands to * sending appropriate commands to the server and processing the responses.
* the server and processing the responses.
*/ */
public class LobbyClient { public class LobbyClient {
private final ClientService client; private final ClientService client;
@@ -12,8 +11,8 @@ public class LobbyClient {
/** /**
* Constructs a LobbyClient with the given ClientService for communication. * Constructs a LobbyClient with the given ClientService for communication.
* *
* @param client The ClientService instance used to send commands and receive * @param client The ClientService instance used to send commands and receive responses from the
* responses from the server. * server.
*/ */
public LobbyClient(ClientService client) { public LobbyClient(ClientService client) {
this.client = client; this.client = client;
@@ -23,16 +22,14 @@ public class LobbyClient {
* Fetch the current status of the lobby with the given id from the server. * Fetch the current status of the lobby with the given id from the server.
* *
* @param lobbyId The id of the lobby to fetch the status for. * @param lobbyId The id of the lobby to fetch the status for.
* @return A string representing the current status of the lobby, as returned * @return A string representing the current status of the lobby, as returned by the server.
* by the server.
*/ */
public String fetchLobbyStatusString(int lobbyId) { public String fetchLobbyStatusString(int lobbyId) {
return client.processCommand("GET_LOBBY_STATUS ID=" + lobbyId).getFirst(); return client.processCommand("GET_LOBBY_STATUS ID=" + lobbyId).getFirst();
} }
/** /**
* Request the server to create a new lobby and return the id of the newly * Request the server to create a new lobby and return the id of the newly created lobby.
* created lobby.
* *
* @return The id of the newly created lobby, as returned by the server. * @return The id of the newly created lobby, as returned by the server.
*/ */
@@ -42,11 +39,9 @@ public class LobbyClient {
} }
/** /**
* Request the server to return the id of the lobby that the client is * Request the server to return the id of the lobby that the client is currently in.
* currently in.
* *
* @return The id of the lobby that the client is currently in, as returned by * @return The id of the lobby that the client is currently in, as returned by the server.
* the server.
*/ */
public int getLobbyId() { public int getLobbyId() {
String response = client.processCommand("GET_LOBBY_ID").getFirst(); String response = client.processCommand("GET_LOBBY_ID").getFirst();
@@ -3,6 +3,9 @@ package ch.unibas.dmi.dbis.cs108.casono.client.ui.chatui;
import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatController; import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatController;
import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatModel; import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatModel;
import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatType; import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatType;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.scene.Node; import javafx.scene.Node;
@@ -10,12 +13,9 @@ import javafx.scene.control.MenuButton;
import javafx.scene.control.MenuItem; import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.scene.control.TabPane; import javafx.scene.control.TabPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import java.io.IOException;
import java.net.URL;
import java.util.List;
public class ChatBoxController { public class ChatBoxController {
private String username; private String username;
@@ -24,7 +24,7 @@ public class ChatBoxController {
@FXML private VBox chatBox; @FXML private VBox chatBox;
@FXML private TabPane ChatTabPane; @FXML private TabPane chatTabPane;
@FXML private MenuButton addWhisperChatButton; @FXML private MenuButton addWhisperChatButton;
@@ -34,7 +34,6 @@ public class ChatBoxController {
private String ressource = "/ui-structure/components/chatui/chattab.fxml"; private String ressource = "/ui-structure/components/chatui/chattab.fxml";
public ChatBoxController(String username, ChatController chatController) { public ChatBoxController(String username, ChatController chatController) {
this.username = username; this.username = username;
this.chatController = chatController; this.chatController = chatController;
@@ -43,37 +42,43 @@ public class ChatBoxController {
@FXML @FXML
public void initialize() { public void initialize() {
ChatModel globalChatModel = new ChatModel(ChatType.GLOBAL, username, -1, null); ChatModel globalChatModel = new ChatModel(ChatType.GLOBAL, username, -1, null);
chatController.getChatModelMap().put(new ChatController.ChatKey(ChatType.GLOBAL), globalChatModel); chatController
.getChatModelMap()
.put(new ChatController.ChatKey(ChatType.GLOBAL), globalChatModel);
addChatTab("GLOBAL", globalChatModel); addChatTab("GLOBAL", globalChatModel);
// TODO: Button to add new Whisper Chat // TODO: Button to add new Whisper Chat
} }
public void addWhisperUser(String targetUserName) { public void addWhisperUser(String targetUserName) {
MenuItem menuItem = new MenuItem(targetUserName); MenuItem menuItem = new MenuItem(targetUserName);
whisperUsers.add(menuItem); whisperUsers.add(menuItem);
addWhisperChatButton.getItems().add(menuItem); addWhisperChatButton.getItems().add(menuItem);
menuItem.setOnAction(event -> addWhisperChat(targetUserName)); menuItem.setOnAction(event -> addWhisperChat(targetUserName));
} }
public void addWhisperChat(String target) { public void addWhisperChat(String target) {
ChatModel chatModel = new ChatModel(ChatType.WHISPER, username, -1, target); ChatModel chatModel = new ChatModel(ChatType.WHISPER, username, -1, target);
chatController.getChatModelMap().put(new ChatController.ChatKey(ChatType.WHISPER, target), chatModel); chatController
.getChatModelMap()
.put(new ChatController.ChatKey(ChatType.WHISPER, target), chatModel);
addChatTab(target, chatModel); addChatTab(target, chatModel);
} }
public void addChatTab(String title, ChatModel chatModel) { public void addChatTab(String title, ChatModel chatModel) {
URL resource = getClass().getResource(ressource); URL resource = getClass().getResource(ressource);
FXMLLoader fxmlLoader = new FXMLLoader(resource); FXMLLoader fxmlLoader = new FXMLLoader(resource);
try { try {
ChatViewController chatViewController = new ChatViewController(this.chatController, chatModel, this.username); ChatViewController chatViewController =
new ChatViewController(this.chatController, chatModel, this.username);
fxmlLoader.setController(chatViewController); fxmlLoader.setController(chatViewController);
Node load = fxmlLoader.load(); Node load = fxmlLoader.load();
VBox.setVgrow(load, Priority.ALWAYS);
VBox vbox = new VBox();
VBox.setVgrow(vbox, Priority.ALWAYS);
vbox.getChildren().add(load);
chatModel.addListener((msg) -> chatViewController.showMessage(msg)); chatModel.addListener((msg) -> chatViewController.showMessage(msg));
Tab newChat = new Tab(title, load); Tab newChat = new Tab(title, vbox);
this.ChatTabPane.getTabs().add(newChat); this.chatTabPane.getTabs().add(newChat);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -55,7 +55,13 @@ public class ChatViewController implements Initializable {
String message = inputField.getText().trim(); String message = inputField.getText().trim();
if (!message.isEmpty()) { if (!message.isEmpty()) {
inputField.clear(); inputField.clear();
Message msg = new Message(chatModel.getChattype(), chatModel.lobbyId, username, chatModel.getTarget(), message); Message msg =
new Message(
chatModel.getChattype(),
chatModel.lobbyId,
username,
chatModel.getTarget(),
message);
controller.onSendToNetwork(msg); controller.onSendToNetwork(msg);
} }
} }
@@ -69,6 +75,7 @@ public class ChatViewController implements Initializable {
chat.getChildren().add(label); chat.getChildren().add(label);
} }
public VBox getChatInterfaceVBox() {
return chatInterfaceVBox;
}
} }
@@ -1,14 +1,12 @@
package ch.unibas.dmi.dbis.cs108.casono.client.ui.lobbyui; package ch.unibas.dmi.dbis.cs108.casono.client.ui.lobbyui;
/** Main UI application for Casono. Loads the main FXML layout and sets up the stage. */ /** Main UI application for Casono. Loads the main FXML layout and sets up the stage. */
import java.io.IOException;
import javafx.application.Application; import javafx.application.Application;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.stage.Stage; import javafx.stage.Stage;
import java.io.IOException;
/** /**
* JavaFX Application class for the Casono main UI. * JavaFX Application class for the Casono main UI.
* *
@@ -3,18 +3,18 @@ package ch.unibas.dmi.dbis.cs108.casono.server;
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.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.CheckUsernameParser;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameRequest; import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.check_nick.CheckUsernameRequest;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login.LoginHandler;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login.LoginParser;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login.LoginRequest;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.logout.LogoutHandler;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.logout.LogoutParser;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.logout.LogoutRequest;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.get_message_count.GetMessageCountHandler; import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.get_message_count.GetMessageCountHandler;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.get_message_count.GetMessageCountParser; import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.get_message_count.GetMessageCountParser;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.get_message_count.GetMessageCountRequest; import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.get_message_count.GetMessageCountRequest;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.get_next_message.GetNextMessageHandler; import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.get_next_message.GetNextMessageHandler;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.get_next_message.GetNextMessageParser; import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.get_next_message.GetNextMessageParser;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.get_next_message.GetNextMessageRequest; import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.get_next_message.GetNextMessageRequest;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login.LoginHandler;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login.LoginParser;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.login.LoginRequest;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.logout.LogoutHandler;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.logout.LogoutParser;
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.PingHandler;
import ch.unibas.dmi.dbis.cs108.casono.server.app.commands.ping.PingParser; 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.ping.PingRequest;
@@ -32,13 +32,12 @@ import ch.unibas.dmi.dbis.cs108.casono.server.network.events.EventBus;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher; import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher;
import ch.unibas.dmi.dbis.cs108.casono.server.network.sessions.SessionDisconnectJob; import ch.unibas.dmi.dbis.cs108.casono.server.network.sessions.SessionDisconnectJob;
import ch.unibas.dmi.dbis.cs108.casono.server.network.sessions.SessionManager; import ch.unibas.dmi.dbis.cs108.casono.server.network.sessions.SessionManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.time.Duration; import java.time.Duration;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/** Application class for starting the server. */ /** Application class for starting the server. */
public class ServerApp { public class ServerApp {
@@ -118,22 +117,16 @@ public class ServerApp {
LogoutRequest.class, new LogoutHandler(responseDispatcher, userRegistry)); LogoutRequest.class, new LogoutHandler(responseDispatcher, userRegistry));
parserDispatcher.register("SEND_MESSAGE", new SendMessageParser()); parserDispatcher.register("SEND_MESSAGE", new SendMessageParser());
commandRouter.register( commandRouter.register(
SendMessageRequest.class, SendMessageRequest.class, new SendMessageHandler(responseDispatcher, userRegistry));
new SendMessageHandler(responseDispatcher, userRegistry)
);
parserDispatcher.register("GET_MESSAGE_COUNT", new GetMessageCountParser()); parserDispatcher.register("GET_MESSAGE_COUNT", new GetMessageCountParser());
commandRouter.register( commandRouter.register(
GetMessageCountRequest.class, GetMessageCountRequest.class,
new GetMessageCountHandler(responseDispatcher, userRegistry) new GetMessageCountHandler(responseDispatcher, userRegistry));
);
parserDispatcher.register("GET_NEXT_MESSAGE", new GetNextMessageParser()); parserDispatcher.register("GET_NEXT_MESSAGE", new GetNextMessageParser());
commandRouter.register( commandRouter.register(
GetNextMessageRequest.class, GetNextMessageRequest.class,
new GetNextMessageHandler(responseDispatcher, userRegistry) new GetNextMessageHandler(responseDispatcher, userRegistry));
);
} }
} }
@@ -5,15 +5,14 @@ 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.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.ErrorResponse;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher; import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher;
import java.util.Optional; import java.util.Optional;
public class GetMessageCountHandler implements CommandHandler<GetMessageCountRequest> { public class GetMessageCountHandler extends CommandHandler<GetMessageCountRequest> {
public final ResponseDispatcher responseDispatcher;
private final UserRegistry userRegistry; private final UserRegistry userRegistry;
public GetMessageCountHandler(ResponseDispatcher responseDispatcher, UserRegistry userRegistry) { public GetMessageCountHandler(
this.responseDispatcher = responseDispatcher; ResponseDispatcher responseDispatcher, UserRegistry userRegistry) {
super(responseDispatcher);
this.userRegistry = userRegistry; this.userRegistry = userRegistry;
} }
@@ -22,18 +21,14 @@ public class GetMessageCountHandler implements CommandHandler<GetMessageCountReq
Optional<User> user = userRegistry.getBySessionId(request.getSessionId()); Optional<User> user = userRegistry.getBySessionId(request.getSessionId());
if (user.isPresent()) { if (user.isPresent()) {
int count = user.get().getMessageCount(); int count = user.get().getMessageCount();
GetMessageCountResponse response = new GetMessageCountResponse( GetMessageCountResponse response =
request.getContext(), new GetMessageCountResponse(request.getContext(), count);
count
);
responseDispatcher.dispatch(response); responseDispatcher.dispatch(response);
} else { } else {
ErrorResponse response = new ErrorResponse( ErrorResponse response =
request.getContext(), new ErrorResponse(
"", request.getContext(), "", "user could not be identified by SessionId");
"user could not be identified by SessionId"
);
responseDispatcher.dispatch(response); responseDispatcher.dispatch(response);
} }
} }
@@ -7,7 +7,8 @@ import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.accessor.
public class GetMessageCountParser implements CommandParser<GetMessageCountRequest> { public class GetMessageCountParser implements CommandParser<GetMessageCountRequest> {
@Override @Override
public GetMessageCountRequest parse(PrimitiveRequest primitiveRequest) { public GetMessageCountRequest parse(PrimitiveRequest primitiveRequest) {
RequestParameterAccessor accessor = new RequestParameterAccessor(primitiveRequest.parameters()); RequestParameterAccessor accessor =
new RequestParameterAccessor(primitiveRequest.parameters());
return new GetMessageCountRequest(primitiveRequest.context()); return new GetMessageCountRequest(primitiveRequest.context());
} }
} }
@@ -6,8 +6,6 @@ import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.
public class GetMessageCountResponse extends SuccessResponse { public class GetMessageCountResponse extends SuccessResponse {
public GetMessageCountResponse(RequestContext context, int count) { public GetMessageCountResponse(RequestContext context, int count) {
super(context, new ResponseBodyBuilder() super(context, new ResponseBodyBuilder().param("COUNT", count).build());
.param("COUNT", count)
.build());
} }
} }
@@ -6,15 +6,13 @@ 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.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.ErrorResponse;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher; import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher;
import java.util.Optional; import java.util.Optional;
public class GetNextMessageHandler implements CommandHandler<GetNextMessageRequest> { public class GetNextMessageHandler extends CommandHandler<GetNextMessageRequest> {
public final ResponseDispatcher responseDispatcher;
private final UserRegistry userRegistry; private final UserRegistry userRegistry;
public GetNextMessageHandler(ResponseDispatcher responseDispatcher, UserRegistry userRegistry) { public GetNextMessageHandler(ResponseDispatcher responseDispatcher, UserRegistry userRegistry) {
this.responseDispatcher = responseDispatcher; super(responseDispatcher);
this.userRegistry = userRegistry; this.userRegistry = userRegistry;
} }
@@ -23,18 +21,14 @@ public class GetNextMessageHandler implements CommandHandler<GetNextMessageReque
Optional<User> user = userRegistry.getBySessionId(request.getSessionId()); Optional<User> user = userRegistry.getBySessionId(request.getSessionId());
if (user.isPresent()) { if (user.isPresent()) {
Message msg = user.get().dequeMessage(); Message msg = user.get().dequeMessage();
GetNextMessageResponse response = new GetNextMessageResponse( GetNextMessageResponse response = new GetNextMessageResponse(request.getContext(), msg);
request.getContext(),
msg
);
responseDispatcher.dispatch(response); responseDispatcher.dispatch(response);
} else { } else {
ErrorResponse response = new ErrorResponse( ErrorResponse response =
new ErrorResponse(
request.getContext(), request.getContext(),
"NO_USER_ASSOCIATED", "NO_USER_ASSOCIATED",
"user could not be identified by SessionId" "user could not be identified by SessionId");
);
responseDispatcher.dispatch(response); responseDispatcher.dispatch(response);
} }
} }
@@ -7,7 +7,8 @@ import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.accessor.
public class GetNextMessageParser implements CommandParser<GetNextMessageRequest> { public class GetNextMessageParser implements CommandParser<GetNextMessageRequest> {
@Override @Override
public GetNextMessageRequest parse(PrimitiveRequest primitiveRequest) { public GetNextMessageRequest parse(PrimitiveRequest primitiveRequest) {
RequestParameterAccessor accessor = new RequestParameterAccessor(primitiveRequest.parameters()); RequestParameterAccessor accessor =
new RequestParameterAccessor(primitiveRequest.parameters());
return new GetNextMessageRequest(primitiveRequest.context()); return new GetNextMessageRequest(primitiveRequest.context());
} }
} }
@@ -7,7 +7,6 @@ import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.
public class GetNextMessageResponse extends SuccessResponse { public class GetNextMessageResponse extends SuccessResponse {
public GetNextMessageResponse(RequestContext context, Message msg) { public GetNextMessageResponse(RequestContext context, Message msg) {
super(context, msg.toResponse(ResponseBody.builder()) super(context, msg.toResponse(ResponseBody.builder()));
);
} }
} }
@@ -1,18 +1,16 @@
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.send_message; package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.send_message;
import ch.unibas.dmi.dbis.cs108.casono.client.chat.Message; import ch.unibas.dmi.dbis.cs108.casono.client.chat.Message;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserRegistry; 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.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.OkResponse;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher; import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher;
public class SendMessageHandler implements CommandHandler<SendMessageRequest> { public class SendMessageHandler extends CommandHandler<SendMessageRequest> {
public final ResponseDispatcher responseDispatcher;
private final UserRegistry userRegistry; private final UserRegistry userRegistry;
public SendMessageHandler(ResponseDispatcher responseDispatcher, UserRegistry userRegistry) { public SendMessageHandler(ResponseDispatcher responseDispatcher, UserRegistry userRegistry) {
this.responseDispatcher = responseDispatcher; super(responseDispatcher);
this.userRegistry = userRegistry; this.userRegistry = userRegistry;
} }
@@ -23,8 +21,8 @@ public class SendMessageHandler implements CommandHandler<SendMessageRequest> {
OkResponse response = new OkResponse(request.getContext()); OkResponse response = new OkResponse(request.getContext());
responseDispatcher.dispatch(response); responseDispatcher.dispatch(response);
} }
public void broadcast(Message message) { public void broadcast(Message message) {
userRegistry.getAllUsers().forEach(user -> user.enqueueMessage(message)); userRegistry.getAllUsers().forEach(user -> user.enqueueMessage(message));
} }
} }
@@ -1,4 +1,5 @@
package ch.unibas.dmi.dbis.cs108.casono.server.domain.message; package ch.unibas.dmi.dbis.cs108.casono.server.domain.message;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserRegistry; import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserRegistry;
/** NOT USED * */ /** NOT USED * */
@@ -1,9 +1,13 @@
package ch.unibas.dmi.dbis.cs108.casono.server.domain.user; package ch.unibas.dmi.dbis.cs108.casono.server.domain.user;
import ch.unibas.dmi.dbis.cs108.casono.client.chat.Message;
import ch.unibas.dmi.dbis.cs108.casono.client.chat.Message;
import ch.unibas.dmi.dbis.cs108.casono.server.network.sessions.SessionId; import ch.unibas.dmi.dbis.cs108.casono.server.network.sessions.SessionId;
import java.time.Instant; import java.time.Instant;
import java.util.*; import java.util.ArrayDeque;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
/** Represents an authenticated user on the server. */ /** Represents an authenticated user on the server. */
@@ -85,9 +89,13 @@ public class User {
messages.add(message); messages.add(message);
} }
public synchronized int getMessageCount() { return messages.size(); } public synchronized int getMessageCount() {
return messages.size();
}
public synchronized Message dequeMessage() throws NoSuchElementException { return messages.remove(); } public synchronized Message dequeMessage() throws NoSuchElementException {
return messages.remove();
}
public synchronized List<Message> dequeueAllMessages(Message message) { public synchronized List<Message> dequeueAllMessages(Message message) {
List<Message> allMessages = new ArrayDeque<>(messages).stream().toList(); List<Message> allMessages = new ArrayDeque<>(messages).stream().toList();
@@ -17,17 +17,19 @@
maxWidth="Infinity"> maxWidth="Infinity">
<children> <children>
<HBox> <HBox spacing="10"
styleClass="">
<children> <children>
<Label text="== CHAT ==" styleClass="chat-header" alignment="CENTER" maxWidth="Infinity"/> <Label text="== CHAT ==" styleClass="chat-header" alignment="CENTER" maxWidth="Infinity"/>
<Region minHeight="4" styleClass="chat-separator"/> <Region HBox.hgrow="ALWAYS" />
<MenuButton fx:id="addWhisperChatButton" styleClass="gray-button" text="+" alignment="CENTER_RIGHT"> <MenuButton fx:id="addWhisperChatButton" styleClass="yellow-button" text="WHISPER CHAT" alignment="CENTER_RIGHT">
</MenuButton> </MenuButton>
</children> </children>
</HBox> </HBox>
<TabPane fx:id="ChatTabPane"> <TabPane fx:id="ChatTabPane"
VBox.vgrow="ALWAYS">
</TabPane> </TabPane>
@@ -7,14 +7,12 @@
<VBox fx:id="chatInterfaceVBox" <VBox fx:id="chatInterfaceVBox"
maxWidth="Infinity" maxWidth="Infinity"
minHeight="500"
spacing="10" spacing="10"
styleClass="chat-box" styleClass="chat-box"
stylesheets="@chatui.css" stylesheets="@chatui.css"
VBox.vgrow="ALWAYS" VBox.vgrow="ALWAYS"
xmlns="http://javafx.com/javafx/17.0.12" xmlns="http://javafx.com/javafx/17.0.12"
xmlns:fx="http://javafx.com/fxml/1" xmlns:fx="http://javafx.com/fxml/1">
>
<children> <children>
<!-- Chatnachrichten werden hier hinzugefügt --> <!-- Chatnachrichten werden hier hinzugefügt -->
@@ -83,7 +83,7 @@
.gray-button { .gray-button {
-fx-background-color: #333333; -fx-background-color: #333333;
-fx-border-color: #666666; -fx-border-color: #666666;
-fx-text-fill: #cccccc; -fx-text-fill: #ffffff;
} }
.gray-button, .yellow-button, .red-button { .gray-button, .yellow-button, .red-button {
@@ -1,13 +1,12 @@
package ch.unibas.dmi.dbis.cs108.casono.client.chat; package ch.unibas.dmi.dbis.cs108.casono.client.chat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService; import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService;
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.RequestParameter; import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.RequestParameter;
import org.junit.jupiter.api.Test;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class ChatTest { public class ChatTest {
@@ -20,8 +19,6 @@ public class ChatTest {
list.add("TEXT='Hello World'"); list.add("TEXT='Hello World'");
list.add("NUMBER=-56887387394898392849"); list.add("NUMBER=-56887387394898392849");
List<RequestParameter> newList = ClientService.convertToRequestParameters(list); List<RequestParameter> newList = ClientService.convertToRequestParameters(list);
RequestParameter par0 = newList.get(0); RequestParameter par0 = newList.get(0);
assertEquals("COUNT", par0.key()); assertEquals("COUNT", par0.key());
@@ -39,5 +36,4 @@ public class ChatTest {
assertEquals("NUMBER", par4.key()); assertEquals("NUMBER", par4.key());
assertEquals("-56887387394898392849", par4.value()); assertEquals("-56887387394898392849", par4.value());
} }
} }