From 6a7491483a5fac8e5b6163218c71669764996393 Mon Sep 17 00:00:00 2001 From: MatteoPellegrino05 Date: Fri, 15 May 2026 16:20:23 +0200 Subject: [PATCH] Add: GameTest coverage for totem choice and disconnected players --- .../java/it/polimi/ingsw/gc14/Model/Game.java | 4 - .../it/polimi/ingsw/gc14/Model/GameTest.java | 257 +++++++++++++++--- 2 files changed, 221 insertions(+), 40 deletions(-) diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java index 1b59d3d..af2c162 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java @@ -19,13 +19,9 @@ import it.polimi.ingsw.gc14.Model.GamePackage.GameStages; import java.io.Serializable; import java.util.*; -import java.util.random.RandomGenerator; import java.util.stream.Collectors; import java.util.stream.Stream; -import it.polimi.ingsw.gc14.View.TUI.AsciiTable; -import it.polimi.ingsw.gc14.View.TUI.BorderStyle; - /** * Represents the main game model. * A Game object stores the players, the current state of the match, diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/GameTest.java b/src/test/java/it/polimi/ingsw/gc14/Model/GameTest.java index 8aaa3a8..f7c1007 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/GameTest.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/GameTest.java @@ -11,6 +11,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; import java.util.*; +import java.util.stream.Stream; import java.util.concurrent.TimeUnit; import static org.junit.jupiter.api.Assertions.*; @@ -18,8 +19,33 @@ import static org.junit.jupiter.api.Assertions.*; @Timeout(value = 10, unit = TimeUnit.SECONDS) class GameTest { + private void completeTotemChoice(Game game) { + assertEquals(GameStages.TOTEM_CHOICE, game.getCurrentState().getGameStage()); + + while (game.getCurrentState().getGameStage() == GameStages.TOTEM_CHOICE) { + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + List availableTotems = game.getAvailableTotems(); + assertFalse(availableTotems.isEmpty()); + + Totems selectedTotem = availableTotems.get(0); + + assertTrue(game.TotemChoice(current, selectedTotem)); + assertEquals(selectedTotem, current.totem); + } + + assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + assertNotNull(game.getCurrentState().getCurrentPlayer()); + } private Queue completeSlotChoice(Game game) { + if (game.getCurrentState().getGameStage() == GameStages.TOTEM_CHOICE) { + completeTotemChoice(game); + } + + assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + Queue order = new LinkedList<>(); for (int i = 0; i < game.getNPlayers(); i++) { @@ -252,7 +278,7 @@ class GameTest { } @Test - void addPlayerShouldRejectDuplicatesAndStartSlotChoiceWhenFull() { + void addPlayerShouldRejectDuplicatesAndStartTotemChoiceWhenFull() { Game game = new Game(3); Player p1 = new Player("p1"); Player p2 = new Player("p2"); @@ -264,11 +290,118 @@ class GameTest { assertFalse(game.addPlayer(p2)); assertTrue(game.addPlayer(p3)); - assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + assertEquals(GameStages.TOTEM_CHOICE, game.getCurrentState().getGameStage()); + assertNotNull(game.getCurrentState().getCurrentPlayer()); assertFalse(game.addPlayer(p4)); } + @Test + void gameShouldEnterTotemChoiceWhenAllPlayersAreAdded() { + Game game = new Game(3); + + assertTrue(game.addPlayer(new Player("p1"))); + assertTrue(game.addPlayer(new Player("p2"))); + assertTrue(game.addPlayer(new Player("p3"))); + + assertEquals(GameStages.TOTEM_CHOICE, game.getCurrentState().getGameStage()); + assertNotNull(game.getCurrentState().getCurrentPlayer()); + } + + @Test + void totemChoiceShouldAssignDistinctTotemsAndStartSlotChoice() { + Game game = new Game(3); + + Player p1 = new Player("p1"); + Player p2 = new Player("p2"); + Player p3 = new Player("p3"); + + assertTrue(game.addPlayer(p1)); + assertTrue(game.addPlayer(p2)); + assertTrue(game.addPlayer(p3)); + + completeTotemChoice(game); + + assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + + assertNotNull(p1.totem); + assertNotNull(p2.totem); + assertNotNull(p3.totem); + + assertEquals( + 3, + Stream.of(p1.totem, p2.totem, p3.totem).distinct().count() + ); + } + + @Test + void totemChoiceShouldRejectAlreadyChosenTotem() { + Game game = new Game(3); + + Player p1 = new Player("p1"); + Player p2 = new Player("p2"); + Player p3 = new Player("p3"); + + assertTrue(game.addPlayer(p1)); + assertTrue(game.addPlayer(p2)); + assertTrue(game.addPlayer(p3)); + + Player firstPlayer = game.getCurrentState().getCurrentPlayer(); + Totems chosenTotem = game.getAvailableTotems().get(0); + + assertTrue(game.TotemChoice(firstPlayer, chosenTotem)); + + Player secondPlayer = game.getCurrentState().getCurrentPlayer(); + assertNotNull(secondPlayer); + + assertFalse(game.TotemChoice(secondPlayer, chosenTotem)); + } + + @Test + void totemChoiceShouldRejectWrongPlayer() { + Game game = new Game(3); + + Player p1 = new Player("p1"); + Player p2 = new Player("p2"); + Player p3 = new Player("p3"); + + assertTrue(game.addPlayer(p1)); + assertTrue(game.addPlayer(p2)); + assertTrue(game.addPlayer(p3)); + + Player current = game.getCurrentState().getCurrentPlayer(); + Player wrongPlayer = current.equals(p1) ? p2 : p1; + + Totems availableTotem = game.getAvailableTotems().get(0); + + assertFalse(game.TotemChoice(wrongPlayer, availableTotem)); + } + + @Test + void getAvailableTotemsShouldExcludeChosenTotems() { + Game game = new Game(3); + + Player p1 = new Player("p1"); + Player p2 = new Player("p2"); + Player p3 = new Player("p3"); + + assertTrue(game.addPlayer(p1)); + assertTrue(game.addPlayer(p2)); + assertTrue(game.addPlayer(p3)); + + int initialAvailableTotems = game.getAvailableTotems().size(); + + Player current = game.getCurrentState().getCurrentPlayer(); + Totems chosenTotem = game.getAvailableTotems().get(0); + + assertTrue(game.TotemChoice(current, chosenTotem)); + + assertEquals(initialAvailableTotems - 1, game.getAvailableTotems().size()); + assertFalse(game.getAvailableTotems().contains(chosenTotem)); + } + + + @Test void shouldRejectInvalidSlotChoices() { Game game = new Game(3); @@ -281,6 +414,8 @@ class GameTest { assertTrue(game.addPlayer(p2)); assertTrue(game.addPlayer(p3)); + completeTotemChoice(game); + Player current = game.getCurrentState().getCurrentPlayer(); assertFalse(game.SlotChoiceByIndex(current, -1)); @@ -307,6 +442,8 @@ class GameTest { assertFalse(game.addPlayer(p2)); assertTrue(game.addPlayer(p3)); + completeTotemChoice(game); + Queue players = new LinkedList<>(); for (int i = 0; i < game.getNPlayers(); i++) { players.add(game.getCurrentState().getCurrentPlayer()); @@ -523,6 +660,10 @@ class GameTest { assertTrue(game.addPlayer(player)); } + if (game.getCurrentState().getGameStage() == GameStages.TOTEM_CHOICE) { + completeTotemChoice(game); + } + return players; } @@ -579,6 +720,10 @@ class GameTest { assertTrue(game.addPlayer(p2)); assertTrue(game.addPlayer(p3)); + /* + * The game is currently in TOTEM_CHOICE: + * draw requests must be rejected because the game is not in RES_ACTIONS. + */ Player current = game.getCurrentState().getCurrentPlayer(); assertNotNull(current); @@ -587,6 +732,10 @@ class GameTest { assertFalse(game.DrawUpperBuildingCardByIndex(current, 0)); assertFalse(game.DrawLowerBuildingCardByIndex(current, 0)); + /* + * The totem choice phase and the slot choice phase are completed, + * so the game enters RES_ACTIONS. + */ completeSlotChoice(game); current = game.getCurrentState().getCurrentPlayer(); @@ -621,7 +770,6 @@ class GameTest { } } - @Test void optionalMethodsShouldReturnFalseOutsideOptionalState() { Game game = new Game(3); @@ -694,6 +842,10 @@ class GameTest { assertTrue(game.addPlayer(new Player("p2"))); assertTrue(game.addPlayer(new Player("p3"))); + assertEquals(GameStages.TOTEM_CHOICE, game.getCurrentState().getGameStage()); + + completeTotemChoice(game); + assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); Player current = game.getCurrentState().getCurrentPlayer(); @@ -712,6 +864,8 @@ class GameTest { assertTrue(game.addPlayer(new Player("p" + nPlayers + "_" + i))); } + completeTotemChoice(game); + assertEquals(nPlayers, game.getCurrentPlayerNumber()); assertEquals(nPlayers, game.getPlayers().size()); assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); @@ -852,34 +1006,6 @@ class GameTest { assertFalse(game.PickOptionalBuildingCard(current, 0)); } - @Test - void toStringModel() { - Game game=new Game(5); - Player p1=new Player("p1"); - Player p2=new Player("p2"); - Player p3=new Player("p3"); - Player p4=new Player("p4"); - Player p5=new Player("p5"); - - assertTrue(game.addPlayer(p1)); - assertTrue(game.addPlayer(p2)); - assertTrue(game.addPlayer(p3)); - assertTrue(game.addPlayer(p4)); - assertTrue(game.addPlayer(p5)); - - Queueplayers=new LinkedList<>(); - for (int i = 0; i < game.getNPlayers(); i++) { - players.add(game.getCurrentState().getCurrentPlayer()); - assertTrue(game.SlotChoiceByIndex(game.getCurrentState().getCurrentPlayer(), i)); - } - - String result = game.toString(); - - assertNotNull(result); - assertFalse(result.isBlank()); - assertTrue(result.contains("CURRENT STATE")); - } - @Test @Timeout(value = 5, unit = TimeUnit.SECONDS) void shouldDrawLowerBuildingWhenAvailableAndPlayerCanPay() { @@ -1076,8 +1202,8 @@ class GameTest { } /* - * Mantiene l'effetto opzionale, ma con prestigio finale nullo. - * Così la fase OPT_CARD_E rimane coerente e il confronto resta controllato. + * Keeps the optional effect, but with zero final prestige. + * This preserves the OPT_CARD_E phase while keeping the comparison controlled. */ player.buildingCards.add(new BuildingCard(12, 1, 1, 0)); } @@ -1223,6 +1349,65 @@ class GameTest { assertFalse(game.SkipNoDrawable(current)); } + @Test + void disconnectedCurrentPlayerDuringSlotChoiceShouldAdvanceTurn() { + Game game = new Game(3); + + addPlayers(game, 3, "disconnect_slot_"); + + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + assertTrue(game.DisconnectedPlayer(current)); + + assertTrue(game.disconnetedPlayers.containsKey(current)); + assertTrue(game.disconnetedPlayers.get(current)); + assertNotEquals(current, game.getCurrentState().getCurrentPlayer()); + } + + @Test + void disconnectedPlayerShouldReturnFalseIfAlreadyDisconnected() { + Game game = new Game(3); + + addPlayers(game, 3, "disconnect_twice_"); + + Player current = game.getCurrentState().getCurrentPlayer(); + + assertTrue(game.DisconnectedPlayer(current)); + assertFalse(game.DisconnectedPlayer(current)); + } + + @Test + void reconnectPlayerShouldRemovePlayerFromDisconnectedMapDuringSlotChoice() { + Game game = new Game(3); + + addPlayers(game, 3, "reconnect_"); + + Player current = game.getCurrentState().getCurrentPlayer(); + + assertTrue(game.DisconnectedPlayer(current)); + assertTrue(game.disconnetedPlayers.containsKey(current)); + + assertTrue(game.ReconnectPlayer(current)); + assertFalse(game.disconnetedPlayers.containsKey(current)); + } + + @Test + void clearDisconnectedShouldEmptyDisconnectedPlayersMap() { + Game game = new Game(3); + + addPlayers(game, 3, "clear_disconnect_"); + + Player current = game.getCurrentState().getCurrentPlayer(); + + assertTrue(game.DisconnectedPlayer(current)); + assertFalse(game.disconnetedPlayers.isEmpty()); + + game.ClearDisconnected(); + + assertTrue(game.disconnetedPlayers.isEmpty()); + } + @Test @Timeout(value = 5, unit = TimeUnit.SECONDS) void drawLowerBuildingShouldReturnFalseIfPlayerCannotPay() { @@ -1376,7 +1561,7 @@ class GameTest { assertTrue(game.addPlayer(p4)); assertTrue(game.addPlayer(p5)); - assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + assertEquals(GameStages.TOTEM_CHOICE, game.getCurrentState().getGameStage()); List foodValues = game.getPlayers().stream() .map(Player::getFoodValue) @@ -1446,8 +1631,8 @@ class GameTest { assertNotNull(testedPlayer); /* - * I due player vengono resi identici rispetto a Eventi e final scoring. - * La partita è comunque arrivata realmente al round 10. + * The two players are made equivalent with respect to events and final scoring. + * The game has still reached round 10 through the real flow. */ preparePlayerForComparableFinalScoring(controlPlayer); preparePlayerForComparableFinalScoring(testedPlayer);