From 0d9585f73938c5ae38237eadaf3941ba96247324 Mon Sep 17 00:00:00 2001 From: Martin Stenhagen Date: Wed, 14 Jan 2026 10:23:34 +0100 Subject: [PATCH 1/4] =?UTF-8?q?Ut=C3=B6kad=20exception-hantering=20i=20Tra?= =?UTF-8?q?velGameController=20och=20hj=C3=A4lpmetod=20cancelJourney()=20i?= =?UTF-8?q?=20traveler=20f=C3=B6r=20att=20f=C3=B6rhindra=20att=20programme?= =?UTF-8?q?t=20crashar=20om=20en=20spelare=20inte=20har=20r=C3=A5d=20med?= =?UTF-8?q?=20en=20resa.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/example/TravelGameController.java | 49 +++++++++++++++++++ src/main/java/org/example/Traveler.java | 8 +++ 2 files changed, 57 insertions(+) diff --git a/src/main/java/org/example/TravelGameController.java b/src/main/java/org/example/TravelGameController.java index 0557bdea..b0c891e9 100644 --- a/src/main/java/org/example/TravelGameController.java +++ b/src/main/java/org/example/TravelGameController.java @@ -362,12 +362,23 @@ private void doMove(Long travelerId, PossibleMoves chosen) { } syncHudAndMap(); + } catch (IllegalStateException e) { + // typiskt: "traveler cannot afford this move" + if (tx.isActive()) tx.rollback(); + + logList.getItems().add("💾 " + safeName(em.find(Traveler.class, travelerId)) + + " kan inte genomföra den hĂ€r resan: " + e.getMessage()); + // viktigt: kasta inte vidare -> ui ska inte krascha + // lĂ„t spelaren stanna kvar och vĂ€lja en annan move + return; + } catch (RuntimeException e) { if (tx.isActive()) tx.rollback(); throw e; } finally { rollButton.setDisable(false); } + } @@ -439,12 +450,50 @@ private void doContinueJourney(Long travelerId) { } syncHudAndMap(); + } catch (IllegalStateException e) { + if (tx.isActive()) tx.rollback(); + + Traveler managed = em.find(Traveler.class, travelerId); + String who = safeName(managed); + + // om det Ă€r just pengar som Ă€r problemet: avbryt resan sĂ„ spelaren inte soft-lockas + if (e.getMessage() != null && e.getMessage().toLowerCase().contains("afford")) { + EntityTransaction tx2 = em.getTransaction(); + tx2.begin(); + try { + Traveler managed2 = em.find(Traveler.class, travelerId); + Location targetBefore = managed2.getTargetLocation(); + String targetName = (targetBefore != null) ? targetBefore.getName() : "?"; + + managed2.cancelJourney(); + em.merge(managed2); + + tx2.commit(); + + logList.getItems().add("💾 " + who + " har inte rĂ„d att fortsĂ€tta mot " + targetName + + " – resan avbröts."); + players.set(currentPlayerIndex, managed2); + syncHudAndMap(); + return; + + } catch (RuntimeException ex) { + if (tx2.isActive()) tx2.rollback(); + logList.getItems().add("⚠ kunde inte avbryta resan: " + ex.getMessage()); + return; + } + } + + // övriga illegal states + logList.getItems().add("⚠ " + who + ": " + e.getMessage()); + return; + } catch (RuntimeException e) { if (tx.isActive()) tx.rollback(); throw e; } finally { rollButton.setDisable(false); } + } private String safeName(Traveler t) { diff --git a/src/main/java/org/example/Traveler.java b/src/main/java/org/example/Traveler.java index fda55cb4..8788ffd8 100644 --- a/src/main/java/org/example/Traveler.java +++ b/src/main/java/org/example/Traveler.java @@ -206,4 +206,12 @@ public void deductMoney(BigDecimal amount) { this.money = next.signum() < 0 ? BigDecimal.ZERO : next; } + public void cancelJourney() { + this.targetLocation = null; + this.remainingDistance = 0; + // destinationPos kan du lĂ„ta vara, eller synca till current: + // setDestinationPos(currentLocation.getX(), currentLocation.getY()); + } + + } From 5cb8cf8e3118b3646562385529053ed81549a0fc Mon Sep 17 00:00:00 2001 From: Martin Stenhagen Date: Wed, 14 Jan 2026 10:23:34 +0100 Subject: [PATCH 2/4] =?UTF-8?q?Ut=C3=B6kad=20exception-hantering=20i=20Tra?= =?UTF-8?q?velGameController=20och=20hj=C3=A4lpmetod=20cancelJourney()=20i?= =?UTF-8?q?=20traveler=20f=C3=B6r=20att=20f=C3=B6rhindra=20att=20programme?= =?UTF-8?q?t=20crashar=20om=20en=20spelare=20inte=20har=20r=C3=A5d=20med?= =?UTF-8?q?=20en=20resa.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/example/TravelGameController.java | 49 +++++++++++++++++++ src/main/java/org/example/Traveler.java | 8 +++ .../java/org/example/service/EventResult.java | 21 -------- 3 files changed, 57 insertions(+), 21 deletions(-) delete mode 100644 src/main/java/org/example/service/EventResult.java diff --git a/src/main/java/org/example/TravelGameController.java b/src/main/java/org/example/TravelGameController.java index 0557bdea..b0c891e9 100644 --- a/src/main/java/org/example/TravelGameController.java +++ b/src/main/java/org/example/TravelGameController.java @@ -362,12 +362,23 @@ private void doMove(Long travelerId, PossibleMoves chosen) { } syncHudAndMap(); + } catch (IllegalStateException e) { + // typiskt: "traveler cannot afford this move" + if (tx.isActive()) tx.rollback(); + + logList.getItems().add("💾 " + safeName(em.find(Traveler.class, travelerId)) + + " kan inte genomföra den hĂ€r resan: " + e.getMessage()); + // viktigt: kasta inte vidare -> ui ska inte krascha + // lĂ„t spelaren stanna kvar och vĂ€lja en annan move + return; + } catch (RuntimeException e) { if (tx.isActive()) tx.rollback(); throw e; } finally { rollButton.setDisable(false); } + } @@ -439,12 +450,50 @@ private void doContinueJourney(Long travelerId) { } syncHudAndMap(); + } catch (IllegalStateException e) { + if (tx.isActive()) tx.rollback(); + + Traveler managed = em.find(Traveler.class, travelerId); + String who = safeName(managed); + + // om det Ă€r just pengar som Ă€r problemet: avbryt resan sĂ„ spelaren inte soft-lockas + if (e.getMessage() != null && e.getMessage().toLowerCase().contains("afford")) { + EntityTransaction tx2 = em.getTransaction(); + tx2.begin(); + try { + Traveler managed2 = em.find(Traveler.class, travelerId); + Location targetBefore = managed2.getTargetLocation(); + String targetName = (targetBefore != null) ? targetBefore.getName() : "?"; + + managed2.cancelJourney(); + em.merge(managed2); + + tx2.commit(); + + logList.getItems().add("💾 " + who + " har inte rĂ„d att fortsĂ€tta mot " + targetName + + " – resan avbröts."); + players.set(currentPlayerIndex, managed2); + syncHudAndMap(); + return; + + } catch (RuntimeException ex) { + if (tx2.isActive()) tx2.rollback(); + logList.getItems().add("⚠ kunde inte avbryta resan: " + ex.getMessage()); + return; + } + } + + // övriga illegal states + logList.getItems().add("⚠ " + who + ": " + e.getMessage()); + return; + } catch (RuntimeException e) { if (tx.isActive()) tx.rollback(); throw e; } finally { rollButton.setDisable(false); } + } private String safeName(Traveler t) { diff --git a/src/main/java/org/example/Traveler.java b/src/main/java/org/example/Traveler.java index fda55cb4..8788ffd8 100644 --- a/src/main/java/org/example/Traveler.java +++ b/src/main/java/org/example/Traveler.java @@ -206,4 +206,12 @@ public void deductMoney(BigDecimal amount) { this.money = next.signum() < 0 ? BigDecimal.ZERO : next; } + public void cancelJourney() { + this.targetLocation = null; + this.remainingDistance = 0; + // destinationPos kan du lĂ„ta vara, eller synca till current: + // setDestinationPos(currentLocation.getX(), currentLocation.getY()); + } + + } diff --git a/src/main/java/org/example/service/EventResult.java b/src/main/java/org/example/service/EventResult.java deleted file mode 100644 index 4bce711f..00000000 --- a/src/main/java/org/example/service/EventResult.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.example.service; - -import org.example.EventType; - -import java.math.BigDecimal; - -public record EventResult( - EventType type, - String description, - BigDecimal amount -) { - - public static EventResult penalty(String description, BigDecimal amount) { - return new EventResult(org.example.EventType.PENALTY, description, amount.negate()); - } - - public static EventResult bonus(String description, BigDecimal amount) { - return new EventResult(EventType.BONUS, description, amount); - } -} - From 020e2cbb712dc3146513dc5908f88cdd2e74d919 Mon Sep 17 00:00:00 2001 From: Martin Stenhagen Date: Wed, 14 Jan 2026 11:13:41 +0100 Subject: [PATCH 3/4] =?UTF-8?q?Tagit=20bort=20private=20List=20?= =?UTF-8?q?transports=20=3D=20new=20ArrayList<>();,=20private=20String=20m?= =?UTF-8?q?anagedMoneyAsInt(Traveler=20t),=20private=20List=20di?= =?UTF-8?q?stinctLocationsById(List=20locations)=20som=20inte=20?= =?UTF-8?q?anv=C3=A4nds=20l=C3=A4ngre=20i=20TravelGameController.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/example/TravelGameController.java | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/src/main/java/org/example/TravelGameController.java b/src/main/java/org/example/TravelGameController.java index b0c891e9..adaa40d7 100644 --- a/src/main/java/org/example/TravelGameController.java +++ b/src/main/java/org/example/TravelGameController.java @@ -62,9 +62,6 @@ public class TravelGameController { private int currentPlayerIndex = 0; private boolean wonGame = false; - - private List transports = new ArrayList<>(); - @FXML private void initialize() { visualizer = new MapVisualizer(gridLayer, markerLayer, playerLayer); @@ -381,18 +378,6 @@ private void doMove(Long travelerId, PossibleMoves chosen) { } - - private List distinctLocationsById(List locations) { - java.util.Map byId = new java.util.LinkedHashMap<>(); - for (Location l : locations) { - if (l != null && l.getId() != null) { - byId.putIfAbsent(l.getId(), l); - } - } - return new java.util.ArrayList<>(byId.values()); - } - - private void highlightSelectedMoveButton(Button selected) { for (var node : movesBox.getChildren()) { if (node instanceof Button b) b.setStyle(""); @@ -406,14 +391,6 @@ private Location getLocationByName(String name) { .getSingleResult(); } - private String managedMoneyAsInt(Traveler t) { - try { - return t.getMoney().toBigInteger().toString(); // eller t.getMoney().toPlainString() - } catch (Exception e) { - return "-"; - } - } - private void doContinueJourney(Long travelerId) { if (wonGame) return; From dab7848614a8da6e7af283dda081822d0cd6b9a1 Mon Sep 17 00:00:00 2001 From: Martin Stenhagen Date: Wed, 14 Jan 2026 11:53:02 +0100 Subject: [PATCH 4/4] =?UTF-8?q?Tagit=20bort=20detta=20som=20inte=20anv?= =?UTF-8?q?=C3=A4nds=20l=C3=A4ngre:=20konstruktorn=20public=20LocationLink?= =?UTF-8?q?(Location=20fromLocation,=20Location=20toLocation,=20int=20dist?= =?UTF-8?q?ance)=20i=20LocationLink,=20dialogPane=20i=20TravelGame,=20kons?= =?UTF-8?q?truktorn=20public=20Transport(TransportType=20type,=20String=20?= =?UTF-8?q?costPerMove)=20i=20Transport,=20getTurnNumber()=20i=20Journey,?= =?UTF-8?q?=20setType=20i=20Location,=20getLocationLink()=20i=20TransportL?= =?UTF-8?q?ink.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/org/example/Journey.java | 4 ---- src/main/java/org/example/Location.java | 4 ---- src/main/java/org/example/LocationLink.java | 9 --------- src/main/java/org/example/Transport.java | 20 ------------------- src/main/java/org/example/TransportLink.java | 4 ---- src/main/java/org/example/TravelGame.java | 1 - .../org/example/TravelGameController.java | 1 - 7 files changed, 43 deletions(-) diff --git a/src/main/java/org/example/Journey.java b/src/main/java/org/example/Journey.java index e9bb3a25..f11132bd 100644 --- a/src/main/java/org/example/Journey.java +++ b/src/main/java/org/example/Journey.java @@ -109,8 +109,4 @@ public int getRemainingDistance() { return remainingDistance; } - public int getTurnNumber() { - return turnNumber; - } - } diff --git a/src/main/java/org/example/Location.java b/src/main/java/org/example/Location.java index fefb79d2..ff59a182 100644 --- a/src/main/java/org/example/Location.java +++ b/src/main/java/org/example/Location.java @@ -34,10 +34,6 @@ public void setName(String name) { this.name = name; } - public void setType(LocationType type) { - this.type = type; - } - public int getX() { return x; } diff --git a/src/main/java/org/example/LocationLink.java b/src/main/java/org/example/LocationLink.java index 53c8f316..5c4f3c25 100644 --- a/src/main/java/org/example/LocationLink.java +++ b/src/main/java/org/example/LocationLink.java @@ -26,15 +26,6 @@ public class LocationLink { @OneToMany(mappedBy = "locationLink") private Set transportLinks = new HashSet<>(); - - public LocationLink() {} - - public LocationLink(Location fromLocation, Location toLocation, int distance) { - this.fromLocation = fromLocation; - this.toLocation = toLocation; - this.distance = distance; - } - public Long getId() { return id; } diff --git a/src/main/java/org/example/Transport.java b/src/main/java/org/example/Transport.java index 827446ee..e1131e1e 100644 --- a/src/main/java/org/example/Transport.java +++ b/src/main/java/org/example/Transport.java @@ -25,25 +25,6 @@ public class Transport { public Transport(){} - public Transport(TransportType type, String costPerMove) { - this.type = type; - this.costPerMove = new BigDecimal(costPerMove); - switch (type){ - case BUSS -> { - this.diceCount = 1; - this.diceSides = 6; - } - case TRAIN -> { - this.diceCount = 2; - this.diceSides = 6; - } - case AIRPLANE -> { - this.diceCount = 3; - this.diceSides = 6; - } - } - } - public int rollDistance() { Random r = new Random(); int total = 0; @@ -65,5 +46,4 @@ public String getType() { return type.toString(); } - } diff --git a/src/main/java/org/example/TransportLink.java b/src/main/java/org/example/TransportLink.java index e9f3ca8d..f3a98129 100644 --- a/src/main/java/org/example/TransportLink.java +++ b/src/main/java/org/example/TransportLink.java @@ -40,10 +40,6 @@ public Long getId() { return id; } - public LocationLink getLocationLink() { - return locationLink; - } - public Transport getTransport() { return transport; } diff --git a/src/main/java/org/example/TravelGame.java b/src/main/java/org/example/TravelGame.java index 7c9d8ab4..c398b412 100644 --- a/src/main/java/org/example/TravelGame.java +++ b/src/main/java/org/example/TravelGame.java @@ -24,7 +24,6 @@ public void start(Stage stage) throws Exception { dialog.setContentText("Ange ditt spelarnamn:"); dialog.setGraphic(null); - DialogPane dialogPane = dialog.getDialogPane(); // ok att ha kvar eller ta bort Optional result = dialog.showAndWait(); if (result.isPresent() && !result.get().trim().isEmpty()) { diff --git a/src/main/java/org/example/TravelGameController.java b/src/main/java/org/example/TravelGameController.java index adaa40d7..6c0e928e 100644 --- a/src/main/java/org/example/TravelGameController.java +++ b/src/main/java/org/example/TravelGameController.java @@ -88,7 +88,6 @@ private void initialize() { logList.getItems().add("🌍 spelet startade. tryck roll."); } - public void setupGame(String playerName) { GameConfig.MODE = GameMode.GUI;