diff --git a/build.gradle b/build.gradle
index b9a94a7..077897d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -36,6 +36,7 @@ dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.10.0")
+ implementation 'org.json:json:20240303'
}
test {
diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/Main.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/Main.java
index d1890db..f7d2273 100644
--- a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/Main.java
+++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/Main.java
@@ -3,8 +3,25 @@ package ch.unibas.dmi.dbis.cs108.casono;
import ch.unibas.dmi.dbis.cs108.casono.client.ClientApp;
import ch.unibas.dmi.dbis.cs108.casono.server.ServerApp;
+/**
+ * Main entry point for Casono application.
+ * Handles client and server startup.
+ *
+ * Standardkonstruktor für die Anwendung.
+ */
public final class Main {
+ /**
+ * Standardkonstruktor.
+ */
+ public Main() {
+ // Standardkonstruktor
+ }
+
+ /**
+ * Main entry point for Casono.
+ * @param args Command line arguments
+ */
public static void main(String[] args) {
if (!isValid(args)) {
printUsage();
diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ClientApp.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ClientApp.java
index 2c17a37..76dc06d 100644
--- a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ClientApp.java
+++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ClientApp.java
@@ -1,6 +1,29 @@
package ch.unibas.dmi.dbis.cs108.casono.client;
+/**
+ * Entry point for the Casono client application.
+ * Handles client startup and connection parameters.
+ */
+import ch.unibas.dmi.dbis.cs108.casono.client.ui.Launcher;
+/**
+ * Entry point for the Casono client application.
+ * Handles client startup and connection parameters.
+ *
+ * Standardkonstruktor für die Anwendung.
+ */
public class ClientApp {
+
+ /**
+ * Standardkonstruktor.
+ */
+ public ClientApp() {
+ // Standardkonstruktor
+ }
+ /**
+ * Starts the client application with the given address.
+ * @param arg Address in the format "ip:port".
+ * @throws IllegalArgumentException if the address format is invalid.
+ */
public static void start(String arg) {
String[] parts = arg.split(":", 2);
if (parts.length != 2) {
@@ -10,5 +33,6 @@ public class ClientApp {
int port = Integer.parseInt(parts[1]);
System.out.println("You've selected the client. It will connect port " + port + " at host " + host);
+ Launcher.main(new String[]{});
}
}
diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/Launcher.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/Launcher.java
new file mode 100644
index 0000000..c687abf
--- /dev/null
+++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/Launcher.java
@@ -0,0 +1,26 @@
+package ch.unibas.dmi.dbis.cs108.casono.client.ui;
+
+import javafx.application.Application;
+
+/**
+ * Launcher for the Casono main UI.
+ *
+ * Standardkonstruktor für die Anwendung.
+ */
+public class Launcher {
+
+ /**
+ * Standardkonstruktor.
+ */
+ public Launcher() {
+ // Standardkonstruktor
+ }
+ /**
+ * Main entry point for launching the UI.
+ * @param args Command line arguments
+ */
+ public static void main(String[] args) {
+ Application.launch(ch.unibas.dmi.dbis.cs108.casono.client.ui.lobbyui.Casinomainui.class, args);
+ }
+}
+
\ No newline at end of file
diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/Casinomainui.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/Casinomainui.java
new file mode 100644
index 0000000..169da1d
--- /dev/null
+++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/Casinomainui.java
@@ -0,0 +1,51 @@
+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.
+ */
+import javafx.application.Application;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+
+import java.io.IOException;
+
+/**
+ * JavaFX Application class for the Casono main UI.
+ *
+ * Standardkonstruktor für die Anwendung.
+ */
+public class Casinomainui extends Application {
+
+ /**
+ * Standardkonstruktor.
+ */
+ public Casinomainui() {
+ // Standardkonstruktor
+ }
+ @Override
+ /**
+ * Starts the JavaFX application and loads the main UI.
+ * @param stage The primary stage for this application.
+ * @throws IOException If loading the FXML fails.
+ */
+ public void start(Stage stage) throws IOException {
+ FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/ui-structure/Casinomainui.fxml"));
+ Scene scene = new Scene(fxmlLoader.load(), 1200, 800);
+ stage.setTitle("Casono");
+
+ stage.getIcons().add(new javafx.scene.image.Image(getClass().getResource("/images/logoinverted.png").toExternalForm()));
+ stage.setScene(scene);
+ stage.setFullScreen(true);
+ stage.show();
+ }
+
+ /**
+ * Main entry point for launching the application.
+ * @param args Command line arguments
+ */
+ public static void main(String[] args) {
+ launch();
+ }
+}
diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/CasinomainuiController.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/CasinomainuiController.java
new file mode 100644
index 0000000..5c235cf
--- /dev/null
+++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/CasinomainuiController.java
@@ -0,0 +1,85 @@
+package ch.unibas.dmi.dbis.cs108.casono.client.ui.lobbyui;
+
+import javafx.application.Platform;
+import javafx.fxml.FXML;
+import javafx.scene.control.Label;
+import javafx.scene.control.Button;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.AnchorPane;
+import javafx.scene.layout.VBox;
+import javafx.scene.shape.Rectangle;
+
+/**
+ * Controller for the Casono main UI lobby.
+ * Handles UI initialization and user actions.
+ */
+public class CasinomainuiController {
+
+ @FXML
+ private AnchorPane rootPane;
+ @FXML
+ private Label titleLabel;
+ @FXML
+ private Label subtitleLabel;
+ @FXML
+ private ImageView logoView;
+ @FXML
+ private Rectangle greenBox;
+ @FXML
+ private Button exitbutton;
+ @FXML
+ private VBox casinoTable;
+
+ private LobbyButtonTranslationManager translationManager;
+ private LobbyButtonGridManager gridManager;
+ private int nextButtonId = 1;
+
+ public CasinomainuiController() {
+ // Default constructor
+ }
+
+ /**
+ * Initializes the UI components and sets default values.
+ */
+ @FXML
+ public void initialize() {
+ titleLabel.setText("Casono");
+ subtitleLabel.setText("Texas Hold'em Poker");
+ logoView.setImage(new Image(getClass().getResource("/images/logo.png").toExternalForm()));
+
+ translationManager = new LobbyButtonTranslationManager();
+ gridManager = new LobbyButtonGridManager(new javafx.scene.layout.GridPane(), translationManager);
+ casinoTable.getChildren().clear();
+ casinoTable.getChildren().add(gridManager.getGridPane());
+ gridManager.renderLobbyButtons();
+ }
+
+ /**
+ * Handles the exit button action to close the application.
+ */
+ @FXML
+ public void handleexitbutton() {
+ Platform.exit();
+ }
+
+ /**
+ * Handles creation of a new lobby button.
+ */
+ @FXML
+ public void handleCreateLobbyButton() {
+ if (translationManager.isFull()) {
+ System.out.println("Grid voll! Keine weiteren Lobbys moeglich.");
+ return;
+ }
+ int buttonId = nextButtonId++;
+ int lobbyId = gridManager.createLobby();
+ try {
+ translationManager.addLobbyButton(buttonId, lobbyId);
+ System.out.println("ButtonID: " + buttonId + ", LobbyID: " + lobbyId);
+ gridManager.renderLobbyButtons();
+ } catch (Exception e) {
+ System.out.println("Fehler beim Hinzufügen: " + e.getMessage());
+ }
+ }
+}
diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/LobbyButtonGridManager.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/LobbyButtonGridManager.java
new file mode 100644
index 0000000..6add82d
--- /dev/null
+++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/LobbyButtonGridManager.java
@@ -0,0 +1,101 @@
+package ch.unibas.dmi.dbis.cs108.casono.client.ui.lobbyui;
+
+/**
+ * Manages the grid for lobby buttons and rendering.
+ * Uses LobbyButtonTranslationManager for mapping ButtonID to LobbyID.
+ */
+
+import javafx.scene.control.Button;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.GridPane;
+import java.util.Map;
+
+/**
+ * Manages the grid for lobby buttons and rendering.
+ * Uses LobbyButtonTranslationManager for mapping ButtonID to LobbyID.
+ */
+public class LobbyButtonGridManager {
+
+ /** GridPane for the button grid. */
+ private final GridPane gridPane;
+ /** Manager for mapping ButtonID to LobbyID. */
+ private final LobbyButtonTranslationManager translationManager;
+ /** Number of rows in the grid. */
+ private final int rows = 2;
+ /** Number of columns in the grid. */
+ private final int cols = 4;
+ /** Path to the button image. */
+ private final String buttonImagePath = "/images/logo.png";
+
+ /**
+ * Constructor for the GridManager.
+ *
+ * @param gridPane the GridPane for rendering
+ * @param translationManager the manager for mapping ButtonID to LobbyID
+ */
+ public LobbyButtonGridManager(GridPane gridPane, LobbyButtonTranslationManager translationManager) {
+ this.gridPane = gridPane;
+ this.translationManager = translationManager;
+ }
+
+ /**
+ * Renders all lobby buttons in the grid.
+ * Creates a button for each mapping with image and event handler.
+ */
+ public void renderLobbyButtons() {
+ gridPane.getChildren().clear();
+ int index = 0;
+ Map mapping = translationManager.getButtonIdToLobbyId();
+ if (mapping.isEmpty()) {
+ // No buttons to render
+ return;
+ }
+ for (Map.Entry entry : mapping.entrySet()) {
+ int buttonId = entry.getKey();
+ Button btn = new Button();
+ btn.setId("lobbyBtn-" + buttonId);
+ btn.setGraphic(new ImageView(new Image(getClass().getResourceAsStream(buttonImagePath))));
+ btn.setOnAction(e -> {
+ Integer lobbyId = translationManager.getLobbyIdForButton(buttonId);
+ if (lobbyId != null)
+ joinLobby(lobbyId);
+ });
+ int row = index / cols;
+ int col = index % cols;
+ gridPane.add(btn, col, row);
+ index++;
+ }
+ }
+
+ /**
+ * Placeholder for lobby creation logic. Returns a generated lobbyId.
+ *
+ * @return The generated lobbyId
+ */
+ public int createLobby() {
+ // TODO: Replace with actual lobby creation logic
+ int lobbyId = (int) (Math.random() * 10000 + 1);
+ System.out.println("Lobby created: " + lobbyId);
+ return lobbyId;
+ }
+
+ /**
+ * Placeholder for joining a lobby.
+ *
+ * @param lobbyId The lobbyId to join
+ */
+ public void joinLobby(int lobbyId) {
+ // TODO: Replace with actual join logic
+ System.out.println("Joining lobby: " + lobbyId);
+ }
+
+ /**
+ * Getter for the GridPane.
+ *
+ * @return The GridPane for the button grid
+ */
+ public javafx.scene.layout.GridPane getGridPane() {
+ return gridPane;
+ }
+}
diff --git a/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/LobbyButtonTranslationManager.java b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/LobbyButtonTranslationManager.java
new file mode 100644
index 0000000..e3dd72e
--- /dev/null
+++ b/src/main/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/LobbyButtonTranslationManager.java
@@ -0,0 +1,66 @@
+package ch.unibas.dmi.dbis.cs108.casono.client.ui.lobbyui;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Verwaltet das Mapping zwischen Button-IDs und Lobby-IDs rein im Speicher.
+ * Keine Dateioperationen, nur Laufzeitdatenstruktur.
+ */
+public class LobbyButtonTranslationManager {
+ /** Maximale Anzahl an Buttons/Lobbys */
+ private static final int MAX_BUTTONS = 8;
+ /** Zuordnung ButtonID → LobbyID */
+ private final Map buttonIdToLobbyId = new HashMap<>();
+
+ /**
+ * Konstruktor: initialisiert die Zuordnung leer.
+ */
+ public LobbyButtonTranslationManager() {
+ // Zuordnung bleibt leer beim Start
+ }
+
+ /**
+ * Prüft, ob das Grid voll ist (MAX_BUTTONS erreicht).
+ * @return true, wenn Grid voll; sonst false
+ */
+ public boolean isFull() {
+ return buttonIdToLobbyId.size() >= MAX_BUTTONS;
+ }
+
+ /**
+ * Fügt eine Zuordnung ButtonID → LobbyID hinzu.
+ * @param buttonId Die ID des Buttons
+ * @param lobbyId Die ID der Lobby
+ * @throws Exception wenn das Grid voll ist
+ */
+ public void addLobbyButton(int buttonId, int lobbyId) throws Exception {
+ if (isFull()) throw new Exception("Grid is full!");
+ buttonIdToLobbyId.put(buttonId, lobbyId);
+ }
+
+ /**
+ * Entfernt eine Zuordnung für die gegebene ButtonID.
+ * @param buttonId Die ID des zu entfernenden Buttons
+ */
+ public void removeLobbyButton(int buttonId) {
+ buttonIdToLobbyId.remove(buttonId);
+ }
+
+ /**
+ * Gibt die LobbyID für eine gegebene ButtonID zurück.
+ * @param buttonId Die ButtonID
+ * @return Die zugehoerige LobbyID oder null, falls nicht vorhanden
+ */
+ public Integer getLobbyIdForButton(int buttonId) {
+ return buttonIdToLobbyId.get(buttonId);
+ }
+
+ /**
+ * Gibt die gesamte Zuordnung ButtonID → LobbyID zurück.
+ * @return Map aller Zuordnungen
+ */
+ public Map getButtonIdToLobbyId() {
+ return buttonIdToLobbyId;
+ }
+}
diff --git a/src/main/resources/images/background.png b/src/main/resources/images/background.png
new file mode 100644
index 0000000..2b84fa7
Binary files /dev/null and b/src/main/resources/images/background.png differ
diff --git a/src/main/resources/ui-structure/Casinomainui.css b/src/main/resources/ui-structure/Casinomainui.css
new file mode 100644
index 0000000..8a9dc97
--- /dev/null
+++ b/src/main/resources/ui-structure/Casinomainui.css
@@ -0,0 +1,160 @@
+/* Pixel-Art Font (WICHTIG: Nutze eine Monospace-Schrift für Pixel-Look) */
+.root {
+ -fx-background-color: #000000;
+ -fx-font-family: "Monospaced", "Courier New";
+}
+
+.anchor-pane-bg {
+ -fx-background-color: #ffffff;
+ /* Optional: Bild entfernen oder als Overlay nutzen */
+ -fx-background-image: url("/images/background.png");
+ -fx-background-size: cover;
+ -fx-background-position: center center;
+ -fx-background-repeat: no-repeat;
+}
+
+/* DIE SCHWEBENDE INFO-BOX (PIXEL-STYLE) */
+.floating-chat-box {
+ -fx-background-color: #0d9e3b;
+ /* Pixel-Ränder: Keine Rundung (0px) oder nur sehr kleine Stufen */
+ -fx-background-radius: 58;
+ -fx-border-radius: 50;
+ -fx-border-color: #5c3d10 #3d260a #3d260a #5c3d10;
+ -fx-border-width: 12;
+ -fx-padding: 20;
+ /* Harter Schatten statt weicher Glow */
+ -fx-effect: dropshadow(one-pass-box, rgba(0,0,0,1), 0, 0, 15, 15);
+}
+
+.chat-header {
+ -fx-text-fill: #ffffff;
+ -fx-font-size: 22px;
+ -fx-font-weight: bold;
+ -fx-padding: 0 0 10 0;
+}
+
+.info-text {
+ -fx-text-fill: #ffffff;
+ -fx-font-size: 16px;
+}
+
+/* DER OVALE PIXEL-TISCH */
+.casino-table {
+ -fx-background-color: #0d9e3b; /* Feste Farbe statt Gradient für Pixel-Look */
+ /* Oval durch festen Radius - Pixel-Art-Ovale sind stufig */
+ -fx-background-radius: 2000;
+ -fx-border-radius: 2000;
+
+ /* Dicker, eckiger Holzrand */
+ -fx-border-color: #5c3d10 #3d260a #3d260a #5c3d10;
+ -fx-border-width: 12;
+
+}
+
+
+.table-title {
+ -fx-text-fill: #ffffff;
+ -fx-font-size: 28px;
+ -fx-font-weight: bold;
+ -fx-effect: dropshadow(one-pass-box, #000, 0, 0, 3, 3);
+}
+
+
+
+
+/* Hauptcontainer der Statusbox */
+.player-status-pane {
+ -fx-background-color: rgb(129, 13, 158);
+ -fx-background-radius: 15;
+ -fx-border-radius: 15;
+
+ /* -fx-border-color: #5c3d10 #3d260a #3d260a #5c3d10;
+ -fx-border-width: 2;
+ -fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.5), 10, 0, 0, 4);*/
+}
+
+.player-status-pane:hover {
+ -fx-translate-y: -3;
+}
+
+/* Die zwei inneren Boxen */
+.status-inner-box-top {
+ -fx-background-color: rgb(13, 93, 158);
+ -fx-background-radius: 19;
+ -fx-border-radius: 15;
+ -fx-padding: 5 10;
+ -fx-border-color: #5c3d10 #3d260a #3d260a #5c3d10;
+ -fx-border-width: 3;
+ -fx-effect: dropshadow(one-pass-box, rgba(0, 0, 0, 0.8), 0, 0, 3, 3);
+}
+
+.status-inner-box-midle {
+ -fx-background-color: rgba(13, 158, 59, 0);
+}
+
+.status-inner-box-bottom {
+ -fx-background-color: rgb(158, 13, 102);
+ -fx-background-radius: 19;
+ -fx-border-radius: 15;
+ -fx-padding: 5 10;
+ -fx-border-color: #5c3d10 #3d260a #3d260a #5c3d10;
+ -fx-border-width: 3;
+ -fx-effect: dropshadow(one-pass-box, rgba(0, 0, 0, 0.8), 0, 0, 3, 3);
+}
+
+.table-title {
+ /* Titel-Text anpassen */
+ -fx-text-fill: #ffffff;
+ -fx-font-size: 32px;
+ -fx-font-weight: bold;
+ -fx-effect: dropshadow(one-pass-box, #000, 0, 0, 3, 3);
+ -fx-padding: 10 0 0 0; /* Abstand nach oben */
+}
+
+.green-box {
+ /* Grüne Box anpassen */
+ -fx-fill: #4CAF50;
+ -fx-stroke: #FFFFFF;
+ -fx-stroke-width: 3;
+ -fx-effect: dropshadow(one-pass-box, #000, 0, 0, 10, 10);
+ -fx-padding: 0 0 40 0;
+}
+
+/* EXIT BUTTON */
+.button-exit {
+ -fx-background-radius: 12;
+ -fx-border-radius: 12;
+ -fx-font-family: "Courier New";
+ -fx-font-weight: bold;
+ -fx-border-width: 2;
+ -fx-padding: 6 15;
+ -fx-cursor: hand;
+ -fx-background-color: #333333;
+ -fx-border-color: #666666;
+ -fx-text-fill: #CCCCCC;
+}
+.button-exit:hover {
+ -fx-translate-y: -3;
+ -fx-effect: dropshadow(one-pass-box, rgba(0, 0, 0, 0.8), 0, 0, 3, 3);
+}
+
+/* LOBBY ERSTELLEN BUTTON */
+.button-create-lobby {
+ -fx-background-radius: 12;
+ -fx-border-radius: 12;
+ -fx-font-family: "Courier New";
+ -fx-font-weight: bold;
+ -fx-border-width: 2;
+ -fx-padding: 6 15;
+ -fx-cursor: hand;
+ -fx-background-color: #1a7f2e;
+ -fx-border-color: #2ecc71;
+ -fx-text-fill: #ffffff;
+}
+.button-create-lobby:hover {
+ -fx-translate-y: -3;
+ -fx-effect: dropshadow(one-pass-box, rgba(0, 0, 0, 0.8), 0, 0, 3, 3);
+ -fx-background-color: #27ae60;
+}
+
+
diff --git a/src/main/resources/ui-structure/Casinomainui.fxml b/src/main/resources/ui-structure/Casinomainui.fxml
new file mode 100644
index 0000000..2d18a48
--- /dev/null
+++ b/src/main/resources/ui-structure/Casinomainui.fxml
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/ui-structure/lobby_button_translation.json b/src/main/resources/ui-structure/lobby_button_translation.json
new file mode 100644
index 0000000..aadb243
--- /dev/null
+++ b/src/main/resources/ui-structure/lobby_button_translation.json
@@ -0,0 +1,10 @@
+{
+ "1": 1240,
+ "2": 3640,
+ "3": 7589,
+ "4": 3982,
+ "5": 5655,
+ "6": 6418,
+ "7": 8586,
+ "8": 7378
+}
\ No newline at end of file
diff --git a/src/test/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/LobbyButtonGridManagerTest.java b/src/test/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/LobbyButtonGridManagerTest.java
new file mode 100644
index 0000000..3f4d574
--- /dev/null
+++ b/src/test/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/LobbyButtonGridManagerTest.java
@@ -0,0 +1,32 @@
+package ch.unibas.dmi.dbis.cs108.casono.client.ui.lobbyui;
+
+import javafx.scene.layout.GridPane;
+import org.junit.jupiter.api.*;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class LobbyButtonGridManagerTest {
+ LobbyButtonGridManager gridManager;
+ LobbyButtonTranslationManager translationManager;
+ GridPane gridPane;
+
+ @BeforeEach
+ void setUp() {
+ gridPane = new GridPane();
+ translationManager = new LobbyButtonTranslationManager();
+ translationManager.getButtonIdToLobbyId().clear();
+ gridManager = new LobbyButtonGridManager(gridPane, translationManager);
+ }
+
+ @Test
+ void testCreateLobbyReturnsId() {
+ int lobbyId = gridManager.createLobby();
+ assertTrue(lobbyId > 0);
+ }
+
+ @Test
+ void testJoinLobbyPlaceholder() {
+ // check if exception is thrown
+ assertDoesNotThrow(() -> gridManager.joinLobby(123));
+ }
+}
diff --git a/src/test/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/LobbyButtonTranslationManagerTest.java b/src/test/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/LobbyButtonTranslationManagerTest.java
new file mode 100644
index 0000000..4c1e526
--- /dev/null
+++ b/src/test/java/ch/unibas/dmi/dbis/cs108/casono/client/ui/lobbyui/LobbyButtonTranslationManagerTest.java
@@ -0,0 +1,47 @@
+package ch.unibas.dmi.dbis.cs108.casono.client.ui.lobbyui;
+
+import org.junit.jupiter.api.*;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class LobbyButtonTranslationManagerTest {
+ LobbyButtonTranslationManager manager;
+
+ @BeforeEach
+ void setUp() {
+ manager = new LobbyButtonTranslationManager();
+ manager.getButtonIdToLobbyId().clear();
+ }
+
+ @Test
+ void testAddLobbyButton() throws Exception {
+ manager.addLobbyButton(1, 100);
+ assertEquals(100, manager.getLobbyIdForButton(1));
+ }
+
+ @Test
+ void testRemoveLobbyButton() throws Exception {
+ manager.addLobbyButton(2, 200);
+ manager.removeLobbyButton(2);
+ assertNull(manager.getLobbyIdForButton(2));
+ }
+
+ @Test
+ void testIsFull() throws Exception {
+ for (int i = 1; i <= 8; i++) {
+ manager.addLobbyButton(i, 100 + i);
+ }
+ assertTrue(manager.isFull());
+ Exception ex = assertThrows(Exception.class, () -> manager.addLobbyButton(9, 109));
+ assertEquals("Grid is full!", ex.getMessage());
+ }
+
+ @Test
+ void testGetButtonIdToLobbyId() throws Exception {
+ manager.addLobbyButton(4, 400);
+ Map map = manager.getButtonIdToLobbyId();
+ assertTrue(map.containsKey(4));
+ assertEquals(400, map.get(4));
+ }
+}