Fix: Resolving Git Merge Conflicts #253

Merged
j.kropff merged 69 commits from chore/ui-checkstyle-fixes into main 2026-04-11 15:10:58 +02:00
8 changed files with 330 additions and 40 deletions
Showing only changes of commit 77c7f7c0a5 - Show all commits
@@ -0,0 +1,9 @@
package ch.unibas.dmi.dbis.cs108.casono.client.game;
/**
* Represents a playing card with a value and suit.
*/
public class Card {
public String value;
public String suit;
}
@@ -0,0 +1,23 @@
package ch.unibas.dmi.dbis.cs108.casono.client.game;
import ch.unibas.dmi.dbis.cs108.casono.client.game.Card;
import ch.unibas.dmi.dbis.cs108.casono.client.game.Player;
import java.util.ArrayList;
import java.util.List;
/**
* Represents the current state of the poker game, including the phase, pot
* size, current bet, dealer position,
* active player, community cards, and player information.
*/
public class GameState {
public String phase;
public int pot;
public int currentBet;
public int dealer;
public int activePlayer;
public List<Card> communityCards = new ArrayList<>();
public List<Player> players = new ArrayList<>();
}
@@ -0,0 +1,17 @@
package ch.unibas.dmi.dbis.cs108.casono.client.game;
import java.util.ArrayList;
import java.util.List;
/**
* Represents a player in the poker game, including their name, chip count,
* current bet, state (e.g., "active", "folded"), and their hole cards.
*/
public class Player {
public String name;
public int chips;
public int bet;
public String state;
public List<Card> cards = new ArrayList<>();
}
@@ -5,36 +5,52 @@ import ch.unibas.dmi.dbis.cs108.casono.client.chat.Message;
import java.util.ArrayList;
import java.util.List;
/**
* The ChatClient class is responsible for sending messages to the server and
* retrieving messages from the server. It uses the ClientService to send
* commands and receive responses from the server.
*/
public class ChatClient {
private ClientService clientService;
/**
* Constructs a ChatClient with the given ClientService for communication.
*
* @param clientService The ClientService instance used to send commands and
* receive responses from the server.
*/
public ChatClient(ClientService clientService) {
this.clientService = clientService;
}
/**
* sends a message to the server
* @param message
* Send a Message to the server by converting it to a string format and
* sending a "SEND_MESSAGE" command with the message content as arguments.
*
* @param message The Message object to be sent to the server.
*/
public void sendMessage(Message message) {
String request = "SEND_MESSAGE " + message.toArgsString();
clientService.processCommand(request);
}
/**
* Send a Request to get the number of Messages currently in the Queue for the client.
* Then proceeds, if needed, to get the messages by sending
* Retrieve messages from the server by first sending a "GET_MESSAGE_COUNT"
* command to determine how many messages are available and then sending
* "GET_NEXT_MESSAGE" commands in a loop to retrieve each message. The
* retrieved messages are parsed into Message objects and returned as a list.
*
* @return A list of Message objects representing the messages retrieved from
* the server.
*/
public List<Message> getMessages() {
String countStr = clientService.processCommand("GET_MESSAGE_COUNT");
int count = Integer.parseInt(countStr);
System.out.println("Got " + count + " messages");
List<Message> messages = new ArrayList<>();
for (int i = 0; i < count; i++) {
String message = clientService.processCommand("GET_NEXT_MESSAGE");
String message = clientService.processCommand("GET_NEXT_MESSAGE");
if (message != null) {
Message message1 = Message.toMessage(message);
messages.add(message1);
@@ -1,6 +1,5 @@
package ch.unibas.dmi.dbis.cs108.casono.client.network;
import ch.unibas.dmi.dbis.cs108.casono.server.network.transport.RawPacket;
import ch.unibas.dmi.dbis.cs108.casono.server.network.transport.TcpTransport;
import java.net.Socket;
@@ -14,11 +13,13 @@ import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
/**
* Responsible for the transferring of the data from the Client to the Server and the other way around
* The ClientService class is responsible for managing the connection to the
* server,
* sending commands, and receiving responses. It uses a TcpTransport to
* communicate
* with the server and an ExecutorService to handle asynchronous requests.
*/
public class ClientService {
private final TcpTransport clienttcptransport;
@@ -30,11 +31,13 @@ public class ClientService {
private final AtomicInteger idGenerator;
/**
* Creates a new ClientSession with a Socket, a Reader and Writer of the Input- and the Outputstream and a pool of threads to send requests and receive responses.
* @param ip : ip-adress of the server
* @param port : port of the server
* Constructs a ClientService with the given server IP and port. It establishes
* a socket connection to the server and initializes the TcpTransport and
* ExecutorService for communication.
*
* @param ip The IP address of the server to connect to.
* @param port The port number of the server to connect to.
*/
public ClientService(String ip, int port) {
this.idGenerator = new AtomicInteger(0);
@@ -42,30 +45,28 @@ public class ClientService {
try {
socket = new Socket(ip, port);
clienttcptransport = new TcpTransport(socket);
}
catch (IOException i) {
} catch (IOException i) {
throw new RuntimeException(i);
}
executor = Executors.newSingleThreadExecutor();
}
/**
* Sends the Requests to the server and waits for the response
* If the response is "+OK" it proceeds normal
* If the response "-ERROR" it throws a runtime exception
* @param message
* @return - The response as a string, if it has to be returned
* (+OK will not be returned)
* Sends a command to the server and waits for the response. The command is
* sent using the TcpTransport, and the response is read in a loop until a
* valid response is received. The method handles "+OK" and "-ERROR" responses
* from the server and returns the actual response content.
*
* @param message The command message to be sent to the server.
* @return The response from the server as a string.
*/
protected String processCommand(String message) {
AtomicReference<String> response = new AtomicReference<>();
sendRequest(() -> {
try {
writeToTransport(message);
String responseLine=null;
String responseLine = null;
do {
responseLine = clienttcptransport.read().payload();
System.out.println("Raw message '" + responseLine + "'");
@@ -75,7 +76,7 @@ public class ClientService {
throw new RuntimeException(responseLine);
}
response.set(responseLine);
} while(true);
} while (true);
} catch (Exception e) {
throw getRuntimeException(e);
}
@@ -84,10 +85,14 @@ public class ClientService {
}
/**
* Helper method to send a request to the server using the ExecutorService. It
* submits the request as a Runnable task and waits for its completion. If
* the task is interrupted or encounters an execution exception, it throws a
* RuntimeException with the appropriate cause.
*
* @param request
* @param request The Runnable task representing the request to be sent to the
* server.
*/
private void sendRequest(Runnable request) {
Future<?> future = executor.submit(request);
try {
@@ -100,11 +105,15 @@ public class ClientService {
}
/**
* Returns a Runtime Exceptions thrown by the sendRequest method
* @param e - an Exception
* @return - a Runtime Exception
* Helper method to extract the cause of an exception and return it as a
* RuntimeException. If the cause is null, it returns the original exception as
* a RuntimeException. If the cause is already a RuntimeException, it returns
* it directly. Otherwise, it wraps the cause in a new RuntimeException and
* returns it.
*
* @param e The exception from which to extract the cause.
* @return A RuntimeException representing the cause of the original exception.
*/
private static RuntimeException getRuntimeException(Exception e) {
Throwable reason = e.getCause();
RuntimeException re;
@@ -118,9 +127,11 @@ public class ClientService {
}
/**
* Closes the Socket and shuts down the Threadpool associated with that Socket-Connection.
* Closes the socket connection to the server and shuts down the
* ExecutorService.
* It also closes the TcpTransport used for communication. If any IOException
* occurs during this process, it prints the exception to the console.
*/
public void closeSocket() {
try {
executor.shutdown();
@@ -133,11 +144,14 @@ public class ClientService {
}
/**
* Method to write with the tcp transport to the server
* @param s - Message to be sent
* @throws IOException
* Helper method to write a command string to the TcpTransport. It generates a
* unique ID for the command using the idGenerator and sends a RawPacket
* containing the ID and the command string to the server. If an IOException
* occurs during this process, it throws a RuntimeException with the cause.
*
* @param s The command string to be sent to the server.
* @throws IOException If an I/O error occurs while writing to the transport.
*/
private void writeToTransport(String s) throws IOException {
int id = this.idGenerator.incrementAndGet();
this.clienttcptransport.write(new RawPacket(id, s));
@@ -1,17 +1,39 @@
package ch.unibas.dmi.dbis.cs108.casono.client.network;
/**
* The CoreClient class provides basic functionalities for communicating with
* the
* server, such as sending a ping command to check connectivity and logging in
* with a username. It uses the ClientService to send commands and receive
* responses from the server.
*/
public class CoreClient {
private final ClientService clientService;
/**
* Constructs a CoreClient with the given ClientService for communication.
*
* @param clientservice The ClientService instance used to send commands and
* receive responses from the server.
*/
public CoreClient(ClientService clientservice) {
this.clientService = clientservice;
}
/**
* Sends a "PING" command to the server to check connectivity. The server
* should respond with a "PONG" message if the connection is successful.
*/
public void ping() {
clientService.processCommand("PING");
}
/**
* Logs in to the server with the given username by sending a "LOGIN" command.
*
* @param user The username to log in with.
*/
public void login(String user) {
clientService.processCommand("LOGIN USERNAME=" + user);
}
}
}
@@ -0,0 +1,125 @@
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.GameState;
import ch.unibas.dmi.dbis.cs108.casono.client.game.Player;
import java.util.ArrayList;
import java.util.List;
/**
* The GameClient class is responsible for communicating with the server to
* retrieve the current game state. It sends a command to the server and
* parses the response into a structured GameState object.
*/
public class GameClient {
private final ClientService client;
/**
* Constructs a GameClient with the given ClientService for communication.
*
* @param client The ClientService instance used to send commands and receive
* responses from the server.
*/
public GameClient(ClientService client) {
this.client = client;
}
/**
* Retrieves the current game state from the server by sending a command and
* parsing the response.
*
* @return A GameState object representing the current state of the game.
*/
public GameState getGameState() {
String response = client.processCommand("GET_GAME_STATE");
return parseGameState(response);
}
/**
* Parses the raw response from the server into a structured GameState object.
*
* @param input The raw response string from the server.
* @return A GameState object representing the current state of the game.
*/
private GameState parseGameState(String input) {
GameState state = new GameState();
String[] lines = input.split("\n");
Player currentPlayer = null;
Card currentCard = null;
for (String rawLine : lines) {
String line = rawLine.trim();
if (line.startsWith("+OK") || line.equals("END")) {
continue;
}
if (line.startsWith("PHASE=")) {
state.phase = line.split("=")[1];
}
else if (line.startsWith("POT=")) {
state.pot = Integer.parseInt(line.split("=")[1]);
}
else if (line.startsWith("CURRENT_BET=")) {
state.currentBet = Integer.parseInt(line.split("=")[1]);
}
else if (line.startsWith("DEALER=")) {
state.dealer = Integer.parseInt(line.split("=")[1]);
}
else if (line.startsWith("ACTIVE_PLAYER=")) {
state.activePlayer = Integer.parseInt(line.split("=")[1]);
}
else if (line.startsWith("PLAYER")) {
currentPlayer = new Player();
state.players.add(currentPlayer);
}
else if (line.startsWith("NAME=") && currentPlayer != null) {
currentPlayer.name = line.split("=")[1];
}
else if (line.startsWith("CHIPS=") && currentPlayer != null) {
currentPlayer.chips = Integer.parseInt(line.split("=")[1]);
}
else if (line.startsWith("BET=") && currentPlayer != null) {
currentPlayer.bet = Integer.parseInt(line.split("=")[1]);
}
else if (line.startsWith("STATE=") && currentPlayer != null) {
currentPlayer.state = line.split("=")[1];
}
else if (line.startsWith("CARD")) {
currentCard = new Card();
if (currentPlayer != null) {
currentPlayer.cards.add(currentCard);
} else {
state.communityCards.add(currentCard);
}
}
else if (line.startsWith("VALUE=") && currentCard != null) {
currentCard.value = line.split("=")[1];
}
else if (line.startsWith("SUIT=") && currentCard != null) {
currentCard.suit = line.split("=")[1];
}
}
return state;
}
}
@@ -0,0 +1,64 @@
package ch.unibas.dmi.dbis.cs108.casono.client.network;
/**
* The LobbyClient class is responsible for communicating with the server to
* manage game lobbies. It provides methods to create a lobby, join a lobby,
* and fetch the current status of a lobby by sending appropriate commands to
* the server and processing the responses.
*/
public class LobbyClient {
private final ClientService client;
/**
* Constructs a LobbyClient with the given ClientService for communication.
*
* @param client The ClientService instance used to send commands and receive
* responses from the server.
*/
public LobbyClient(ClientService client) {
this.client = client;
}
/**
* 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.
* @return A string representing the current status of the lobby, as returned
* by the server.
*/
public String fetchLobbyStatusString(int lobbyId) {
return client.processCommand("GET_LOBBY_STATUS ID=" + lobbyId);
}
/**
* Request the server to create a new lobby and return the id of the newly
* created lobby.
*
* @return The id of the newly created lobby, as returned by the server.
*/
public int createLobby() {
String response = client.processCommand("CREATE_LOBBY");
return Integer.parseInt(response);
}
/**
* Request the server to return the id of the lobby that the client is
* currently in.
*
* @return The id of the lobby that the client is currently in, as returned by
* the server.
*/
public int getLobbyId() {
String response = client.processCommand("GET_LOBBY_ID");
return Integer.parseInt(response);
}
/**
* Request the server to join the lobby with the given id.
*
* @param lobbyId The id of the lobby to join.
*/
public void joinLobby(int lobbyId) {
client.processCommand("JOIN_LOBBY ID=" + lobbyId);
}
}