Merge branch 'main' into feat/change-username-at-start-or-in-game

This commit is contained in:
Jona Walpert
2026-04-12 09:12:46 +02:00
187 changed files with 22261 additions and 361 deletions
@@ -0,0 +1,9 @@
package ch.unibas.dmi.dbis.cs108.casono.client.chat;
import javafx.application.Application;
public class Chat {
public static void main(String[] args) {
Application.launch(ChatApplication.class);
}
}
@@ -0,0 +1,38 @@
package ch.unibas.dmi.dbis.cs108.casono.client.chat;
import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService;
import ch.unibas.dmi.dbis.cs108.casono.client.network.CoreClient;
import ch.unibas.dmi.dbis.cs108.casono.client.ui.chatui.ChatBoxController;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class ChatApplication extends Application {
private static final int SCENE_WIDTH = 1200;
private static final int SCENE_HEIGHT = 800;
String ip = "localhost";
String username = "mathis";
final int port = 5000;
public ChatApplication() {}
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader =
new FXMLLoader(
getClass().getResource("/ui-structure/components/chatui/chatbox.fxml"));
ClientService clientService = new ClientService(ip, port);
CoreClient coreClient = new CoreClient(clientService);
coreClient.login(username);
ChatController chatController = new ChatController(username, clientService);
ChatBoxController chatBoxController = new ChatBoxController(username, chatController);
fxmlLoader.setController(chatBoxController);
Scene scene = new Scene(fxmlLoader.load(), SCENE_WIDTH, SCENE_HEIGHT);
stage.setTitle("Chat");
stage.setScene(scene);
stage.show();
}
}
@@ -0,0 +1,21 @@
package ch.unibas.dmi.dbis.cs108.casono.client.chat;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
public class ChatControllerTest {
@BeforeEach
public void setup() {}
@AfterEach
public void teardown() {}
/*
* @Test
* public void testChatController() {
* Client client = new Client("user1");
* client.startApplication();
* }
*/
}
@@ -0,0 +1,39 @@
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.server.network.command.parsing.RequestParameter;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
public class ChatTest {
@Test
public void chatTest() {
List<String> list = new ArrayList<String>();
list.add("COUNT=19199");
list.add("TEXT='test \\' test'");
list.add("TEXT='%/§§%&&/%=%$/%))==/?``*\\'\\'**\\'\\'§?'");
list.add("TEXT='Hello World'");
list.add("NUMBER=-56887387394898392849");
List<RequestParameter> newList = ClientService.convertToRequestParameters(list);
RequestParameter par0 = newList.get(0);
assertEquals("COUNT", par0.key());
assertEquals("19199", par0.value());
RequestParameter par1 = newList.get(1);
assertEquals("TEXT", par1.key());
assertEquals("test ' test", par1.value());
RequestParameter par2 = newList.get(2);
assertEquals("TEXT", par2.key());
assertEquals("%/§§%&&/%=%$/%))==/?``*''**''§?", par2.value());
RequestParameter par4 = newList.get(4);
assertEquals("NUMBER", par4.key());
assertEquals("-56887387394898392849", par4.value());
}
}
@@ -0,0 +1,88 @@
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.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Minimal test server that speaks the RawPacket/TcpTransport protocol used by ClientService.
* Provides deterministic responses for CREATE_LOBBY and GET_LOBBY_STATUS so unit tests can run
* without a real backend.
*/
public class TestServer implements AutoCloseable {
private final ServerSocket serverSocket;
private final ExecutorService exec = Executors.newSingleThreadExecutor();
private final AtomicInteger nextLobbyId = new AtomicInteger(1);
private final Map<Integer, String> lobbyStatus = new ConcurrentHashMap<>();
private volatile boolean running = true;
public TestServer() throws IOException {
this.serverSocket = new ServerSocket(0);
exec.submit(this::acceptLoop);
}
public int getPort() {
return serverSocket.getLocalPort();
}
private void acceptLoop() {
try (Socket client = serverSocket.accept()) {
TcpTransport transport = new TcpTransport(client);
while (running) {
RawPacket request = transport.read();
String payload = request.payload();
String response = handleRequest(payload);
// send the response payload followed by +OK
transport.write(new RawPacket(request.requestId(), response));
transport.write(new RawPacket(request.requestId(), "+OK"));
}
} catch (IOException e) {
if (running) {
throw new RuntimeException(e);
}
}
}
private String handleRequest(String payload) {
if (payload == null) {
return "";
}
if (payload.startsWith("CREATE_LOBBY")) {
int id = nextLobbyId.getAndIncrement();
lobbyStatus.put(id, "created");
return Integer.toString(id);
}
if (payload.startsWith("GET_LOBBY_STATUS")) {
// payload format: GET_LOBBY_STATUS ID=<id>
String[] parts = payload.split("ID=");
if (parts.length == 2) {
try {
int id = Integer.parseInt(parts[1].trim());
return lobbyStatus.getOrDefault(id, "created");
} catch (NumberFormatException e) {
return "created";
}
}
return "created";
}
if (payload.startsWith("JOIN_LOBBY")) {
// no-op
return "";
}
return "";
}
@Override
public void close() throws Exception {
running = false;
serverSocket.close();
exec.shutdownNow();
}
}
@@ -2,6 +2,7 @@ package ch.unibas.dmi.dbis.cs108.casono.client.ui.lobbyui;
import static org.junit.jupiter.api.Assertions.*;
import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService;
import javafx.scene.layout.GridPane;
import org.junit.jupiter.api.*;
@@ -9,18 +10,31 @@ class LobbyButtonGridManagerTest {
LobbyButtonGridManager gridManager;
LobbyButtonTranslationManager translationManager;
GridPane gridPane;
ch.unibas.dmi.dbis.cs108.casono.client.network.TestServer testServer;
@BeforeEach
void setUp() {
void setUp() throws Exception {
gridPane = new GridPane();
translationManager = LobbyButtonTranslationManager.getInstance();
translationManager.getButtonIdToLobbyId().clear();
gridManager = new LobbyButtonGridManager(gridPane, translationManager);
// Start an in-process test server and connect a real ClientService to it.
testServer = new ch.unibas.dmi.dbis.cs108.casono.client.network.TestServer();
String host = "127.0.0.1";
int port = testServer.getPort();
ClientService clientService = new ClientService(host, port);
gridManager = new LobbyButtonGridManager(gridPane, translationManager, clientService);
}
@Test
void testCreateLobbyReturnsId() {
int lobbyId = gridManager.createLobby();
assertTrue(lobbyId > 0);
@AfterEach
void tearDown() throws Exception {
if (testServer != null) {
testServer.close();
}
}
// @Test
// void testCreateLobbyReturnsId() {
// int lobbyId = gridManager.createLobby();
// assertTrue(lobbyId > 0);
// }
}