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
2 changed files with 116 additions and 10 deletions
Showing only changes of commit d855f2d568 - Show all commits
@@ -26,6 +26,7 @@ public class ClientService {
private final Socket socket;
private final ExecutorService executor;
private final boolean offlineMode;
public static ArrayList<String> response;
private final AtomicInteger idGenerator;
@@ -42,6 +43,7 @@ public class ClientService {
this.idGenerator = new AtomicInteger(0);
this.offlineMode = false;
try {
socket = new Socket(ip, port);
clienttcptransport = new TcpTransport(socket);
@@ -52,6 +54,27 @@ public class ClientService {
executor = Executors.newSingleThreadExecutor();
}
/**
* Constructs a ClientService in offline mode. No network connection will be
* attempted and calls to processCommand will throw a RuntimeException.
*
* @param offline true to create an offline (no-network) client service
*/
public ClientService(boolean offline) {
this.idGenerator = new AtomicInteger(0);
this.offlineMode = offline;
this.socket = null;
this.clienttcptransport = null;
this.executor = Executors.newSingleThreadExecutor();
}
/**
* Returns true if this ClientService is running in offline mode (no network).
*/
public boolean isOffline() {
return offlineMode;
}
/**
* 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
@@ -62,6 +85,9 @@ public class ClientService {
* @return The response from the server as a string.
*/
protected String processCommand(String message) {
if (offlineMode) {
throw new RuntimeException("ClientService is offline: cannot process command");
}
AtomicReference<String> response = new AtomicReference<>();
sendRequest(() -> {
try {
@@ -135,8 +161,12 @@ public class ClientService {
public void closeSocket() {
try {
executor.shutdown();
if (clienttcptransport != null) {
clienttcptransport.close();
}
if (socket != null) {
socket.close();
}
} catch (IOException j) {
System.out.println(j);
}
@@ -3,6 +3,9 @@ package ch.unibas.dmi.dbis.cs108.casono.client.ui.lobbyui;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
@@ -12,6 +15,7 @@ import javafx.scene.shape.Rectangle;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService;
import ch.unibas.dmi.dbis.cs108.casono.client.network.LobbyClient;
/**
* Controller for the Casono main UI lobby. Handles UI initialization and user
@@ -20,17 +24,29 @@ import ch.unibas.dmi.dbis.cs108.casono.client.network.ClientService;
public class CasinomainuiController {
private static final Logger LOGGER = LogManager.getLogger(CasinomainuiController.class);
@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;
@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;
@FXML
private TextField usernameField;
@FXML
private Button loginButton;
private LobbyButtonTranslationManager translationManager;
private LobbyButtonGridManager gridManager;
private int nextButtonId = 1;
private LobbyClient lobbyClient;
/** Default constructor for dependency injection by FXMLLoader. */
public CasinomainuiController() {
@@ -47,8 +63,60 @@ public class CasinomainuiController {
translationManager = LobbyButtonTranslationManager.getInstance();
String host = System.getProperty("casono.server.host");
int port = Integer.parseInt(System.getProperty("casono.server.port"));
ClientService clientService = new ClientService(host, port);
ClientService clientService;
try {
clientService = new ClientService(host, port);
} catch (RuntimeException e) {
LOGGER.warn("Could not connect to server {}:{} — starting in offline mode: {}", host, port, e.getMessage());
clientService = new ClientService(true); // offline mode
}
gridManager = new LobbyButtonGridManager(new javafx.scene.layout.GridPane(), translationManager, clientService);
// LobbyClient will use the provided ClientService; in offline mode calls will
// fail with RuntimeException
lobbyClient = new LobbyClient(clientService);
casinoTable.getChildren().clear();
casinoTable.getChildren().add(gridManager.getGridPane());
gridManager.renderLobbyButtons();
}
/**
* Handles the login button action. Validates input and calls
* LobbyClient.login().
*/
@FXML
public void handleLoginButton() {
String username = usernameField.getText();
if (username == null || username.isBlank()) {
showAlert("Please enter a username.");
return;
}
// Only allow alphanumeric, _ and -
if (!username.matches("[a-zA-Z0-9_-]+")) {
showAlert("Only letters, numbers, '_' and '-' are allowed!");
return;
}
if (lobbyClient.getClientService().isOffline()) {
showAlert("Offline mode: cannot send login to server.");
return;
}
try {
lobbyClient.login(username);
showAlert("Login sent: " + username);
} catch (RuntimeException e) {
LOGGER.error("Login failed: {}", e.getMessage());
showAlert("Login failed: " + e.getMessage());
}
}
/**
* Shows an alert dialog with the given message.
*/
private void showAlert(String message) {
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("Info");
alert.setHeaderText(null);
alert.setContentText(message);
alert.showAndWait();
casinoTable.getChildren().clear();
casinoTable.getChildren().add(gridManager.getGridPane());
gridManager.renderLobbyButtons();
@@ -69,6 +137,14 @@ public class CasinomainuiController {
}
int buttonId = nextButtonId++;
try {
String username = usernameField != null ? usernameField.getText() : "<unknown>";
LOGGER.info("Creating lobby for user: {}", username);
// avoid attempting to create a lobby when offline
if (lobbyClient.getClientService().isOffline()) {
LOGGER.warn("Cannot create lobby while offline");
showAlert("Offline mode: cannot create lobby.");
return;
}
int lobbyId = gridManager.createLobby();
translationManager.addLobbyButton(buttonId, lobbyId);
LOGGER.info("ButtonID: {}, LobbyID: {}", buttonId, lobbyId);