diff --git a/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java b/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java index cec543c..5e02464 100644 --- a/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java +++ b/src/main/java/it/polimi/ingsw/gc14/ClientLauncherTUI.java @@ -1,53 +1,85 @@ package it.polimi.ingsw.gc14; import it.polimi.ingsw.gc14.Controller.ClientController; +import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.RMI.Client.RMIClient; -import it.polimi.ingsw.gc14.View.IView; +import it.polimi.ingsw.gc14.Network.TCP.Client.TCPClient; +import it.polimi.ingsw.gc14.View.TUI.TUI; + import java.util.Scanner; public class ClientLauncherTUI { //TODO Javadoc public void main() throws InterruptedException { - ClientController controller = new ClientController(); + TUI view=new TUI(null); + ClientController controller = new ClientController(view); Scanner scanner = new Scanner(System.in); - System.out.println("Selezionare nome utente: "); String username = scanner.next(); - System.out.println(username); - System.out.println("Selezionare numero di giocatori desiderato: "); int proposedNumPlayers = scanner.nextInt(); - System.out.println(proposedNumPlayers); - System.out.println("Selezionare RMI[0] o TCP[1]: "); int networkType = scanner.nextInt(); - System.out.println(networkType); - scanner.close(); + + // RMI if (networkType == 0) { - RMIClient client = new RMIClient("localhost", 1099); - if (client.connect(username, proposedNumPlayers, controller)) { + // Connect + RMIClient client = new RMIClient(controller, "localhost", 1099); + if (client.connect(username, proposedNumPlayers)) { System.out.println("Succesfully connected to RMI server\n\n"); } else { System.out.println("RMI connection refused\n\n"); + return; } + controller.setClient(client); + // Play + //while(controller.localController.getModel()==null){ + // scanner.nextInt(); + //} while(true) { - System.out.flush(); - if (controller.localModel!=null) { - break; - } - Thread.sleep(500); + getInput(scanner, controller, username); } - System.out.println("Model set\n\n"); - - - + // TCP } else if (networkType == 1) { - return; + // Connect + TCPClient client = new TCPClient(controller, "localhost", 8080); + if (client.connect(username, proposedNumPlayers)) { + System.out.println("Succesfully connected to TCP server\n\n"); + } else { + System.out.println("TCP connection refused\n\n"); + return; + } + controller.setClient(client); + + // Play + while(true) { + getInput(scanner, controller, username); + } } + + scanner.close(); + } + + + + private void getInput(Scanner scanner, ClientController controller, String username) { + int action = scanner.nextInt(); + int pos = scanner.nextInt(); + + switch(action) { + case 1 -> controller.drawLowerBuildingCard(username, pos); + case 2 -> controller.drawLowerTribeCard(username, pos); + case 3 -> controller.drawUpperBuildingCard(username, pos); + case 4 -> controller.drawUpperTribeCard(username, pos); + case 5 -> controller.pickOptionalBuildingCard(username, pos); + case 6 -> controller.slotChoice(username, pos); + } + + return; } } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java b/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java index e41a0b1..63da09f 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java +++ b/src/main/java/it/polimi/ingsw/gc14/Controller/ClientController.java @@ -1,40 +1,119 @@ package it.polimi.ingsw.gc14.Controller; import it.polimi.ingsw.gc14.Model.Game; +import it.polimi.ingsw.gc14.Model.Player; +import it.polimi.ingsw.gc14.Network.IClient; +import it.polimi.ingsw.gc14.Network.NetworkEvents.*; import it.polimi.ingsw.gc14.Network.Observer; import it.polimi.ingsw.gc14.View.IView; //TODO Javadoc public class ClientController { - //TODO Javadoc - public Game localModel; - //TODO Javadoc public GameController localController; //TODO Javadoc public IView view=null; + private IClient client; - //TODO Javadoc - public ClientController(IView view,Game localModel) { + public ClientController(IView view) { this.view = view; - this.localModel = localModel; - this.localController = new GameController(localModel); + this.localController = new GameController(); } - - //TODO Javadoc - public ClientController() { - this.localController = new GameController(localModel); + public void setClient(IClient client) { + this.client = client; } - public void setModel(Game model) { - this.localModel = model; localController.setModel(model); - // localModel.addObserver((Observer) view); // registra la view come observer + view.update(localController.getModel()); } - //TODO Javadoc public void onError(String message) { view.showError(message); } + + /** + * Attempts to draw an upper tribe card for the specified player from the specified position. + * + * @param playerUsername the username of the player performing the action. + * @param pos the position of the upper tribe card to draw. + * @return {@code true} if the action succeeds, {@code false} if the player does not exist + * or if the draw operation fails. + */ + public void drawUpperTribeCard(String playerUsername,int pos) { + client.doEvent(new DrawUpperTribeCard(playerUsername,pos)); + } + + /** + * Attempts to draw a lower tribe card for the specified player from the specified position. + * + * @param playerUsername the username of the player performing the action. + * @param pos the position of the lower tribe card to draw. + * @return {@code true} if the action succeeds, {@code false} if the player does not exist + * or if the draw operation fails. + */ + public void drawLowerTribeCard(String playerUsername,int pos) { + client.doEvent(new DrawLowerTribeCard(playerUsername,pos)); + } + + /** + * Attempts to draw an upper building card for the specified player from the specified position. + * + * @param playerUsername the username of the player performing the action. + * @param pos the position of the upper building card to draw. + * @return {@code true} if the action succeeds, {@code false} if the player does not exist + * or if the draw operation fails. + */ + public void drawUpperBuildingCard(String playerUsername,int pos) { + client.doEvent(new DrawUpperBuildingCard(playerUsername,pos)); + } + + /** + * Attempts to draw a lower building card for the specified player from the specified position. + * + * @param playerUsername the username of the player performing the action. + * @param pos the position of the lower building card to draw. + * @return {@code true} if the action succeeds, {@code false} if the player does not exist + * or if the draw operation fails. + */ + public void drawLowerBuildingCard(String playerUsername,int pos) { + client.doEvent(new DrawLowerBuildingCard(playerUsername,pos)); + } + + /** + * Attempts to pick an optional tribe card for the specified player from the specified position. + * + * @param playerUsername the username of the player performing the action. + * @param pos the position of the optional tribe card to pick. + * @return {@code true} if the action succeeds, {@code false} if the player does not exist + * or if the pick operation fails. + */ + public void pickOptionalTribeCard(String playerUsername,int pos) { + client.doEvent(new PickOptionalTribeCard(playerUsername,pos)); + } + + /** + * Attempts to pick an optional building card for the specified player from the specified position. + * + * @param playerUsername the username of the player performing the action. + * @param pos the position of the optional building card to pick. + * @return {@code true} if the action succeeds, {@code false} if the player does not exist + * or if the pick operation fails. + */ + public void pickOptionalBuildingCard(String playerUsername,int pos) { + client.doEvent(new PickOptionalBuildingCard(playerUsername,pos)); + } + + /** + * Attempts to perform the slot choice action for the specified player at the specified position. + * + * @param playerUsername the username of the player performing the action. + * @param pos the position of the chosen slot. + * @return {@code true} if the action succeeds, {@code false} if the player does not exist + * or if the slot choice operation fails. + */ + public void slotChoice(String playerUsername,int pos) { + client.doEvent(new SlotChoice(playerUsername,pos)); + } + } 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 054b2f6..2308aa2 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Game.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Game.java @@ -169,8 +169,9 @@ public class Game implements Serializable { * @throws IllegalArgumentException if {@code nPlayers < 0} or {@code nPlayers > 5}. */ public Game(int nPlayers) throws IllegalArgumentException{ - if(nPlayers < 0||nPlayers > 5) + if(nPlayers !=0 && (nPlayers < 2 || nPlayers > 5)) { throw new IllegalArgumentException(); + } this.nPlayers = nPlayers; board=new Board(nPlayers); slotMap = new LinkedHashMap<>(); @@ -312,10 +313,9 @@ public class Game implements Serializable { tempCard.insert(player); board.removeUpperTribeCard(tempCard); currentState.UpperDrawn(); - if(currentState.getNUpper() ==0 && currentState.getNLower() ==0) + if((currentState.getNLower() ==0 ||( getLowerListTribeCards().size()==0 && getLowerListBuilding().size()==0)) && ((currentState.getNUpper() ==0)||( getUpperListTribeCards().size()==0 && getUpperListBuilding().size()==0))) nextPlayerSetup(); return true; - } /** @@ -354,7 +354,7 @@ public class Game implements Serializable { tempCard.insert(player); board.removeLowerTribeCard(tempCard); currentState.LowerDrawn(); - if(currentState.getNLower() ==0 && currentState.getNUpper() ==0) + if((currentState.getNLower() ==0 ||( getLowerListTribeCards().size()==0 && getLowerListBuilding().size()==0)) && ((currentState.getNUpper() ==0)||( getUpperListTribeCards().size()==0 && getUpperListBuilding().size()==0))) nextPlayerSetup(); return true; @@ -393,7 +393,7 @@ public class Game implements Serializable { } else return false; - if(currentState.getNLower() ==0 && currentState.getNUpper() ==0) + if((currentState.getNLower() ==0 ||( getLowerListTribeCards().size()==0 && getLowerListBuilding().size()==0)) && ((currentState.getNUpper() ==0)||( getUpperListTribeCards().size()==0 && getUpperListBuilding().size()==0))) nextPlayerSetup(); return true; @@ -418,7 +418,7 @@ public class Game implements Serializable { { return false; } - + if(!player.equals(currentState.getCurrentPlayer())) { return false; @@ -433,7 +433,7 @@ public class Game implements Serializable { } else return false; - if(currentState.getNLower() ==0 && currentState.getNUpper() ==0) + if((currentState.getNLower() ==0 ||( getLowerListTribeCards().size()==0 && getLowerListBuilding().size()==0)) && ((currentState.getNUpper() ==0)||( getUpperListTribeCards().size()==0 && getUpperListBuilding().size()==0))) nextPlayerSetup(); return true; @@ -509,8 +509,8 @@ public class Game implements Serializable { else { return false; } - nextPlayerSetup(); OptionalCardQueue.removeIf(x->x.equals(player)); + nextPlayerSetup(); return true; } @@ -566,10 +566,16 @@ public class Game implements Serializable { return; } currentState.GameStageUpdate(GameStages.RESOLVING_ACTIONS); - for (Map.Entry s : slotMap.entrySet()) { - if (s.getValue()!=null) { - currentState.PlayerUpdate(s.getValue(), s.getKey()); - return; + for (Slot s : slotMap.keySet()) { + if (slotMap.get(s) != null) { + currentState.PlayerUpdate(slotMap.get(s), s); + if(!((currentState.getNLower() ==0 ||( getLowerListTribeCards().size()==0 && getLowerListBuilding().size()==0)) && ((currentState.getNUpper() ==0)||( getUpperListTribeCards().size()==0 && getUpperListBuilding().size()==0)))) + break; + else + { + orderLogicCard.push(currentState.getCurrentPlayer()); + slotMap.put(currentState.getSlot(), null); + } } } return; @@ -581,7 +587,15 @@ public class Game implements Serializable { for (Slot s : slotMap.keySet()) { if (slotMap.get(s) != null) { currentState.PlayerUpdate(slotMap.get(s), s); - break; + if((currentState.getNLower() ==0 ||( getLowerListTribeCards().size()==0 && getLowerListBuilding().size()==0)) && ((currentState.getNUpper() ==0)||( getUpperListTribeCards().size()==0 && getUpperListBuilding().size()==0))) { + orderLogicCard.push(currentState.getCurrentPlayer()); + + slotMap.put(currentState.getSlot(), null); + } + else + { + break; + } } } if(slotMap.values().stream().allMatch(v -> v == null)) @@ -600,31 +614,51 @@ public class Game implements Serializable { { OptionalCardQueue.add(e.getKey()); } - currentState.PlayerUpdate(OptionalCardQueue.remove(), null); - if(currentState.getCurrentPlayer()==null) - { - currentState.GameStageUpdate(GameStages.RESOLVING_EVENT); - if(currentState.getRound()<10) - { - nextRound(); - } - else - { - EventResolution(); - currentState.GameStageUpdate(GameStages.ENDING); - endGame(); - } + Player optionalPlayer = OptionalCardQueue.poll(); + if (optionalPlayer != null) { + currentState.PlayerUpdate(optionalPlayer, null); return; } - } - } - if(GameStages.OPTIONAL_CARD_EFFECT==currentState.getGameStage()) { - currentState.PlayerUpdate(OptionalCardQueue.remove(), null); - if(currentState.getCurrentPlayer()==null) - { + currentState.GameStageUpdate(GameStages.RESOLVING_EVENT); + + if (currentState.getRound() < 10) { + nextRound(); + currentState.PlayerUpdate(orderLogicCard.pull(), null); + currentState.GameStageUpdate(GameStages.SLOT_CHOICE); + } else { + EventResolution(); + currentState.GameStageUpdate(GameStages.ENDING); + endGame(); + } + + return; + } } + + if (GameStages.OPTIONAL_CARD_EFFECT == currentState.getGameStage()) { + Player optionalPlayer = OptionalCardQueue.poll(); + + if (optionalPlayer != null) { + currentState.PlayerUpdate(optionalPlayer, null); + return; + } + + currentState.GameStageUpdate(GameStages.RESOLVING_EVENT); + + if (currentState.getRound() < 10) { + nextRound(); + currentState.PlayerUpdate(orderLogicCard.pull(), null); + currentState.GameStageUpdate(GameStages.SLOT_CHOICE); + } else { + EventResolution(); + currentState.GameStageUpdate(GameStages.ENDING); + endGame(); + } + + return; + } } @@ -669,9 +703,13 @@ public class Game implements Serializable { { currentState.GameStageUpdate(GameStages.ENDING); endGame(); + return; } - if(currentState.getEra()!= board.nextRound()) + + if(currentState.getEra()!= board.nextRound()) { currentState.EraUpdate(); + } + currentState.RoundUpdate(); } @@ -695,11 +733,28 @@ public class Game implements Serializable { * @param nPlayers the new configured number of players. * @return {@code true} if the number of players is updated, {@code false} otherwise. */ - public boolean setNPlayer(int nPlayers) - { - if(this.nPlayers!=0) + public boolean setNPlayer(int nPlayers) { + if (this.nPlayers != 0) { return false; - this.nPlayers=nPlayers; + } + + if (nPlayers < 2 || nPlayers > 5) { + return false; + } + + this.nPlayers = nPlayers; + + board = new Board(nPlayers); + + slotMap = new LinkedHashMap<>(); + for (Slot s : board.getSlotList()) { + slotMap.put(s, null); + } + + currentState = new CurrentState(); + playersList = new ArrayList<>(); + OptionalCardQueue = new LinkedList<>(); + return true; } @@ -715,88 +770,76 @@ public class Game implements Serializable { */ @Override public String toString() { - var table = new AsciiTable(BorderStyle.UNICODE, slotMap.size()); - List stringUp=new ArrayList<>(); - List stringEmpty=new ArrayList<>(); - List stringDown=new ArrayList<>(); + return PlayersStamp()+"\n"+BoardStamp()+"\n"; + } + public String PlayersStamp() + { + StringBuilder stringBuilder=new StringBuilder(); + for(int i=0;i stringUpOffer=new ArrayList<>(); + List stringDownOffer=new ArrayList<>(); + for(Map.Entry entry:slotMap.entrySet()) { - stringEmpty.add(" "); - stringDown.add(entry.getKey().toStringTUI()); + stringDownOffer.add(entry.getKey().toStringTUI()); if(entry.getValue()!=null) - stringUp.add(entry.getValue().getUserName()); + stringUpOffer.add(entry.getValue().getUserName()); else - stringUp.add(" "); + stringUpOffer.add(" "); } - table.addRow(stringUp); - table.addRow(stringEmpty); - table.addRow(stringDown); - Listlines=List.of(orderLogicCard.toString().split("\n")); - List lines2=new ArrayList<>(); - lines2.add("OFFER TRACK"); - lines2.addAll(List.of(table.build().split("\n"))); + var TribeTableUpper = new AsciiTable(BorderStyle.UNICODE,1); + var TribeTableLower = new AsciiTable(BorderStyle.UNICODE,1); - String boardToString=AsciiTable.sideBySide(lines,lines2,1); - - - - var table2 = new AsciiTable(BorderStyle.UNICODE, Math.max(getUpperListTribeCards().size(),getLowerListTribeCards().size())); - List stringUp2=new ArrayList<>(); - List stringDown2=new ArrayList<>(); + List stringUpperListTribe=new ArrayList<>(); + List stringLowerListTribe=new ArrayList<>(); + stringUpperListTribe.add("Char/Events"); + stringLowerListTribe.add("Char/Events"); for(int i=0;i stringUp3=new ArrayList<>(); - List stringDown3=new ArrayList<>(); for(int i=0;iTribeTableUpper.addRow(x)); + stringLowerListTribe.forEach(x->TribeTableLower.addRow(x)); + offerTrack.addRow(stringUpOffer); + offerTrack.addRow(stringDownOffer); + return "CURRENT STATE\n"+getCurrentState()+"\n"+orderLogicCard.toString()+"\n"+ AsciiTable.sideBySide(Arrays.stream((TribeTableUpper.build().split("\n"))).toList(), Arrays.stream(BuildTableUpper.build().split("\n")).toList(),2)+"\n"+offerTrack.build()+"\n"+AsciiTable.sideBySide(List.of(TribeTableLower.build().split("\n")), Arrays.stream(BuildTableLower.build().split("\n")).toList(),2); } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/GamePackage/CurrentState.java b/src/main/java/it/polimi/ingsw/gc14/Model/GamePackage/CurrentState.java index b2489b8..f464e02 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/GamePackage/CurrentState.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/GamePackage/CurrentState.java @@ -3,7 +3,12 @@ package it.polimi.ingsw.gc14.Model.GamePackage; import it.polimi.ingsw.gc14.Model.Player; import it.polimi.ingsw.gc14.Model.Slot; import it.polimi.ingsw.gc14.Model.GamePackage.GameStages; +import it.polimi.ingsw.gc14.View.TUI.AsciiTable; +import it.polimi.ingsw.gc14.View.TUI.BorderStyle; + import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; /** * Represents the current state of the game. @@ -194,5 +199,27 @@ public class CurrentState implements Serializable { } } + @Override + public String toString(){ + var table= new AsciiTable(BorderStyle.UNICODE,6); + Listheader= new ArrayList<>(); + header.add("Player"); + header.add("NUpper"); + header.add("NLower"); + header.add("Round"); + header.add("Era"); + header.add("GameStage"); + table.addRow(header); + table.addSeparator(); + Listvalues= new ArrayList<>(); + values.add(player.getUserName()); + values.add(Integer.toString(NUpper)); + values.add(Integer.toString(NLower)); + values.add(Integer.toString(round)); + values.add(Integer.toString(Era)); + values.add(GameStage.toString()); + table.addRow(values); + return table.build(); + } // endregion functions } diff --git a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/OrderPlayer.java b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/OrderPlayer.java index 56ac136..cb3034b 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Model/Orders/OrderPlayer.java +++ b/src/main/java/it/polimi/ingsw/gc14/Model/Orders/OrderPlayer.java @@ -2,13 +2,15 @@ package it.polimi.ingsw.gc14.Model.Orders; import it.polimi.ingsw.gc14.Model.Player; +import java.io.Serializable; + /** * Abstract base class for all order {@code logic cards}. * An {@code OrderLogicCard} manages a queue of {@code players} and defines the effects * applied when they are pushed back into the queue. * @see it.polimi.ingsw.gc14.Model.Player Player */ -public class OrderPlayer{ +public class OrderPlayer implements Serializable { public Player player; public boolean played; public OrderPlayer(Player player,boolean played){ diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java b/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java new file mode 100644 index 0000000..86f6435 --- /dev/null +++ b/src/main/java/it/polimi/ingsw/gc14/Network/IClient.java @@ -0,0 +1,8 @@ +package it.polimi.ingsw.gc14.Network; + +import java.rmi.RemoteException; + +public interface IClient { + public boolean connect(String username,int preferredInt); + public void doEvent(NetworkEvent event) ; +} diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java index 5b16b76..beb9c91 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/ClientCallbackImpl.java @@ -39,6 +39,7 @@ public class ClientCallbackImpl extends UnicastRemoteObject implements IClientCa @Override public void onGameInit(Game model) throws RemoteException { clientController.setModel(model); + clientController.view.render(); } @@ -55,7 +56,7 @@ public class ClientCallbackImpl extends UnicastRemoteObject implements IClientCa System.out.println(event.toString()); } else { event.apply(clientController.localController); - //clientController.view.update(); TODO + clientController.view.render(); } } } diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/RMIClient.java b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/RMIClient.java index fda4005..2d4c348 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/RMIClient.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/RMI/Client/RMIClient.java @@ -4,6 +4,7 @@ import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import it.polimi.ingsw.gc14.Controller.ClientController; +import it.polimi.ingsw.gc14.Network.IClient; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.RMI.Common.IClientCallback; import it.polimi.ingsw.gc14.Network.RMI.Common.IGameServer; @@ -11,7 +12,7 @@ import it.polimi.ingsw.gc14.Network.RMI.Common.IGameServer; /** * Client RMI. Uses the methods exposed by the server RMI. */ -public class RMIClient { +public class RMIClient implements IClient { /** The host address of the RMI server */ private final String host; @@ -22,13 +23,18 @@ public class RMIClient { /** The remote stub used to call methods on the server */ private IGameServer stub; + /** Client game's controller */ + ClientController controller; + /** * Class constructor. + * @param controller the client controller used to create the callback * @param host the host address of the RMI server * @param port the port of the RMI server */ - public RMIClient(String host, int port) { + public RMIClient(ClientController controller, String host, int port) { + this.controller=controller; this.host = host; this.port = port; } @@ -40,14 +46,13 @@ public class RMIClient { * Then, creates a {@link ClientCallbackImpl} and calls {@link RMIServer#joinGame(String, int, IClientCallback)}. * @param username the player's username * @param preferredInt the desired number of players - * @param clientController the client controller used to create the callback * @return true if the player successfully joined the game, false otherwise */ - public boolean connect(String username,int preferredInt, ClientController clientController) { + public boolean connect(String username,int preferredInt) { try { Registry registry = LocateRegistry.getRegistry(host, port); this.stub = (IGameServer) registry.lookup("RMIGameServer"); - ClientCallbackImpl callback = new ClientCallbackImpl(clientController); + ClientCallbackImpl callback = new ClientCallbackImpl(controller); return stub.joinGame(username, preferredInt, callback); } @@ -63,8 +68,12 @@ public class RMIClient { * @param event the event to send * @throws RemoteException if any RMI error occurs */ - public void doEvent(NetworkEvent event) throws RemoteException { - stub.doEvent(event); + public void doEvent(NetworkEvent event) { + try { + stub.doEvent(event); + }catch (Exception e) { + + } } } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java index c69734e..3408e99 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Client/TCPClient.java @@ -1,7 +1,8 @@ package it.polimi.ingsw.gc14.Network.TCP.Client; -import it.polimi.ingsw.gc14.Controller.GameController; +import it.polimi.ingsw.gc14.Controller.ClientController; import it.polimi.ingsw.gc14.Model.Game; +import it.polimi.ingsw.gc14.Network.IClient; import it.polimi.ingsw.gc14.Network.NetworkEvent; import it.polimi.ingsw.gc14.Network.NetworkEvents.AddPlayer; @@ -11,7 +12,7 @@ import java.net.*; /** * Client TCP. Sends and receives messages with the TCP server. */ -public class TCPClient { +public class TCPClient implements IClient { /** Socket TCP */ Socket communicationSocket; @@ -23,7 +24,7 @@ public class TCPClient { ObjectOutputStream socketSend; /** Client game's controller */ - GameController controller; + ClientController controller; /** IP address of the server to connect to */ String hostname; @@ -38,7 +39,7 @@ public class TCPClient { * @param hostname The IP address of the server * @param port The TCP port of the server */ - public TCPClient(GameController controller, String hostname, int port) { + public TCPClient(ClientController controller, String hostname, int port) { this.controller = controller; this.hostname = hostname; this.port = port; @@ -53,13 +54,15 @@ public class TCPClient { * @param proposedNPlayers The desired number of players for the game * @return true if the connection is successful, false otherwise. */ - public boolean start(String user, int proposedNPlayers) { + public boolean connect(String user, int proposedNPlayers) { try { + communicationSocket = new Socket(hostname, port); socketSend = new ObjectOutputStream(communicationSocket.getOutputStream()); socketReceive = new ObjectInputStream(communicationSocket.getInputStream()); - sendEvent(new AddPlayer(user, proposedNPlayers)); + + doEvent(new AddPlayer(user, proposedNPlayers)); if (communicationSocket.getInputStream().read() == -1) { System.out.println("Could not connect to server"); return false; @@ -89,11 +92,12 @@ public class TCPClient { if (event.getIsError()) { System.out.println(event); } else { - event.apply(controller); - //clientController.view.update(); TODO + event.apply(controller.localController); + controller.view.render(); } } else if (read instanceof Game model) { controller.setModel(model); + controller.view.render(); } } catch (IOException e) { e.printStackTrace(); @@ -108,7 +112,7 @@ public class TCPClient { * Sends a {@link NetworkEvent} to the server. * @param event The NetworkEvent to send. */ - private void sendEvent(NetworkEvent event) { + public void doEvent(NetworkEvent event) { try { socketSend.writeObject(event); } catch (IOException e) { diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/ClientHandler.java b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/ClientHandler.java index 07864f0..539416e 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/ClientHandler.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/ClientHandler.java @@ -41,8 +41,10 @@ public class ClientHandler implements Runnable { * @param clientHandlers The shared list of all active client handlers * @param actionQueue The queue containing incoming events */ - public ClientHandler(Socket clientSocket, List clientHandlers, BlockingQueue actionQueue) { + public ClientHandler(Socket clientSocket, ObjectOutputStream out, ObjectInputStream in, List clientHandlers, BlockingQueue actionQueue) { this.clientSocket = clientSocket; + this.in = in; + this.out = out; this.clientHandlers = clientHandlers; this.actionQueue = actionQueue; } @@ -55,8 +57,7 @@ public class ClientHandler implements Runnable { @Override public void run() { try { - in = new ObjectInputStream(clientSocket.getInputStream()); - out = new ObjectOutputStream(clientSocket.getOutputStream()); + while (true) { NetworkEvent event = (NetworkEvent) in.readObject(); if (!actionQueue.add(event)) { @@ -76,15 +77,13 @@ public class ClientHandler implements Runnable { * Sends a {@link NetworkEvent} to the client. * @param event The network event to send to the client. */ - public void notifyEvent(NetworkEvent event) { - synchronized (out) { - try { - out = new ObjectOutputStream(clientSocket.getOutputStream()); - out.writeObject(event); - } catch (IOException e) { - e.printStackTrace(); - } + public synchronized void notifyEvent(NetworkEvent event) { + try { + out.writeObject(event); + } catch (IOException e) { + e.printStackTrace(); } + } @@ -92,14 +91,11 @@ public class ClientHandler implements Runnable { * Sends the current game model to this client. * @param game The current state of the game to send to the client. */ - public void notifyModel(Game game) { - synchronized (out) { - try { - out = new ObjectOutputStream(clientSocket.getOutputStream()); - out.writeObject(game); - } catch (IOException e) { - e.printStackTrace(); - } + public synchronized void notifyModel(Game game) { + try { + out.writeObject(game); + } catch (IOException e) { + e.printStackTrace(); } } } \ No newline at end of file diff --git a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java index 16c4cfb..55fd6a6 100644 --- a/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java +++ b/src/main/java/it/polimi/ingsw/gc14/Network/TCP/Server/TCPServer.java @@ -88,8 +88,9 @@ public class TCPServer { try{ clientSocket = socketTCP.accept(); - ObjectInputStream clientSocketObj = new ObjectInputStream(clientSocket.getInputStream()); - NetworkEvent event = (NetworkEvent) clientSocketObj.readObject(); + ObjectOutputStream clientSend = new ObjectOutputStream(clientSocket.getOutputStream()); + ObjectInputStream clientReceive = new ObjectInputStream(clientSocket.getInputStream()); + NetworkEvent event = (NetworkEvent) clientReceive.readObject(); if(!(event.getEventType() == EventType.ADD_PLAYER)){ clientSocket.getOutputStream().write((int)(-1)); @@ -114,7 +115,7 @@ public class TCPServer { clientSocket.getOutputStream().write((int) (1)); System.out.println("Accepted player: " + eventAddPlayer.getUsername()); - ClientHandler clientHandler = new ClientHandler(clientSocket, clientHandlers, actionQueue); + ClientHandler clientHandler = new ClientHandler(clientSocket, clientSend, clientReceive, clientHandlers, actionQueue); clientHandlers.add(clientHandler); ConnectedPlayers++; diff --git a/src/main/java/it/polimi/ingsw/gc14/View/IView.java b/src/main/java/it/polimi/ingsw/gc14/View/IView.java index 80c7616..2169583 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/IView.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/IView.java @@ -4,9 +4,9 @@ import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Network.NetworkEvent; public interface IView { - - void render(Game model); - void showMessage(String message); - void showError(String message); + public void update(Game game); + public void render(); + public void showMessage(String message); + public void showError(String message); } diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java index 26ccb31..74cf535 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/AsciiTable.java @@ -29,6 +29,7 @@ public class AsciiTable { //TODO javadoc public void addHeader(String... cells) { rows.add(0, Arrays.asList(cells)); separators.add(0); } + public void addSeparator() { separators.add(rows.size()-1); } //TODO javadoc public void addSeparator() { separators.add(rows.size()-1); } diff --git a/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java b/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java index 8d25fa3..6170dd5 100644 --- a/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java +++ b/src/main/java/it/polimi/ingsw/gc14/View/TUI/TUI.java @@ -1,93 +1,103 @@ -//package it.polimi.ingsw.gc14.View.TUI; -//import it.polimi.ingsw.gc14.Model.Game; -// -//public class TUI { -// -// // ── dati di stato ─────────────────────────────────────────── -// private BorderStyle style = BorderStyle.UNICODE; -// private Game model; -// // ── punto di ingresso ─────────────────────────────────────── -// public String render() { -// var sb = new StringBuilder(); -// sb.append(renderHeader()); -// sb.append(renderTurnOrder()); -// sb.append(renderOfferTrack()); -// sb.append(renderCardRows()); -// sb.append(renderTableaux()); -// sb.append(renderFooter()); -// return sb.toString(); -// } -// -// // ── sezioni ───────────────────────────────────────────────── -// private String renderTurnOrder() { -// var table = new AsciiTable(style, 4, 10); // 4 colonne, largh 10 -// table.addRow(model.getPlayers().stream() -// .map(p -> + ". " + p.getUserName()) -// .toList()); -// table.addRow(state.getPlayers().stream() -// .map(p -> p.getTotemPosition() != null -// ? "totem: " + p.getTotemPosition() -// : "(da piaz)") -// .toList()); -// return " TURN ORDER\n" + table.build() + "\n"; -// } -// -// private String renderOfferTrack() { -// var table = new AsciiTable(style, 5, 14); -// table.addRow(state.getOfferTiles().stream() -// .map(t -> t.getId() + ": " + t.getLabel()).toList()); -// table.addRow(state.getOfferTiles().stream() -// .map(OfferTile::getRowsLabel).toList()); -// table.addRow(state.getOfferTiles().stream() -// .map(t -> state.getTotemOnTile(t.getId())).toList()); -// return " OFFER TRACK\n" + table.build() + "\n"; -// } -// -// private String renderCardRows() { -// int cols = state.getTopRow().size(); -// var table = new AsciiTable(style, cols, 13); -// table.addRow(state.getTopRow().stream() -// .map(c -> "[" + c.getTypeLabel() + "]").toList()); -// table.addRow(state.getTopRow().stream() -// .map(Card::getName).toList()); -// table.addSeparator(); -// table.addRow(state.getBotRow().stream() -// .map(c -> "[" + c.getTypeLabel() + "]").toList()); -// table.addRow(state.getBotRow().stream() -// .map(Card::getName).toList()); -// return " CARTE IN GIOCO\n" + prefix("TOP ", "BOT ", table.build()) + "\n"; -// } -// -// private String renderTableaux() { -// var sb = new StringBuilder(" TABLEAU GIOCATORI\n\n"); -// for (Player p : state.getPlayers()) { -// String marker = p.isActive() ? ">>>" : " "; -// sb.append(String.format(" %s %s%s Food:%d PP:%d%n", -// marker, p.getName(), -// p.isActive() ? " [TUO TURNO]" : "", -// p.getFood(), p.getPP())); -// sb.append(renderPlayerTableau(p)); -// sb.append("\n"); -// } -// return sb.toString(); -// } -// -// private String renderPlayerTableau(Player p) { -// var table = new AsciiTable(style, 3, 14); -// table.addHeader("PERSONAGGI", "EDIFICI", "RISORSE"); -// int rows = Math.max(p.getChars().size(), -// Math.max(p.getBuildings().size(), 3)); -// for (int i = 0; i < rows; i++) { -// String ch = i < p.getChars().size() ? p.getChars().get(i) : ""; -// String bd = i < p.getBuildings().size() ? p.getBuildings().get(i) : ""; -// String rs = switch (i) { -// case 0 -> "Food: " + "O".repeat(p.getFood()); -// case 1 -> "PP: " + p.getPP(); -// case 2 -> "Chars:" + p.getChars().size() + " Edif:" + p.getBuildings().size(); -// default -> ""; -// }; -// table.addRow(ch, bd, rs); -// } -// return " " + table.build().replace("\n", "\n "); -// } -//} +package it.polimi.ingsw.gc14.View.TUI; +import it.polimi.ingsw.gc14.Model.Game; +import it.polimi.ingsw.gc14.View.IView; + +public class TUI implements IView { + + // ── dati di stato ─────────────────────────────────────────── + private BorderStyle style = BorderStyle.UNICODE; + private Game model; + private String username; + public TUI(Game model) { + this.model = model; + this.username=""; + } + public void setUsername(String username) { + this.username = username; + } + + @Override + public void update(Game model) { + this.model = model; + } + + // ── punto di ingresso ─────────────────────────────────────── + public void render() + { + try{ + String os = System.getProperty("os.name").toLowerCase(); + ProcessBuilder pb; + if (os.contains("win")) { + pb = new ProcessBuilder("cmd", "/c", "cls"); + } else { + pb = new ProcessBuilder("clear"); + } + pb.inheritIO().start().waitFor(); + } + catch(Exception e){ + } + System.out.println(model.toString()); + } + + public void renderBoard() + { + try{ + String os = System.getProperty("os.name").toLowerCase(); + ProcessBuilder pb; + if (os.contains("win")) { + pb = new ProcessBuilder("cmd", "/c", "cls"); + } else { + pb = new ProcessBuilder("clear"); + } + pb.inheritIO().start().waitFor(); + } + catch(Exception e){ + } + System.out.println(model.BoardStamp()); + } + public void renderPlayer() + { + try{ + String os = System.getProperty("os.name").toLowerCase(); + ProcessBuilder pb; + if (os.contains("win")) { + pb = new ProcessBuilder("cmd", "/c", "cls"); + } else { + pb = new ProcessBuilder("clear"); + } + pb.inheritIO().start().waitFor(); + } + catch(Exception e){ + } + System.out.println(model.BoardStamp()); + } + public void renderMyHand() + { + try{ + String os = System.getProperty("os.name").toLowerCase(); + ProcessBuilder pb; + if (os.contains("win")) { + pb = new ProcessBuilder("cmd", "/c", "cls"); + } else { + pb = new ProcessBuilder("clear"); + } + pb.inheritIO().start().waitFor(); + } + catch(Exception e){ + } + System.out.println(model.getPlayerByUsername(username)); + } + + + public void showMessage(String message) + { + System.out.println(message); + } + + + public void showError(String message) + { + System.out.println(message); + } + +} diff --git a/src/test/java/it/polimi/ingsw/gc14/Controller/GameControllerTest.java b/src/test/java/it/polimi/ingsw/gc14/Controller/GameControllerTest.java index 19a845e..aa89a2a 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Controller/GameControllerTest.java +++ b/src/test/java/it/polimi/ingsw/gc14/Controller/GameControllerTest.java @@ -1,5 +1,6 @@ package it.polimi.ingsw.gc14.Controller; +import it.polimi.ingsw.gc14.Model.Cards.BuildingCard; import it.polimi.ingsw.gc14.Model.Cards.TribeCard; import it.polimi.ingsw.gc14.Model.Game; import it.polimi.ingsw.gc14.Model.GamePackage.GameStages; @@ -14,6 +15,114 @@ import static org.junit.jupiter.api.Assertions.*; class GameControllerTest { + private Game createStartedGame() { + Game game = new Game(3); + GameController controller = new GameController(game); + assertEquals( controller.getModel(),game); + controller = new GameController(); + controller.setModel(game); + assertEquals( controller.getModel(),game); + assertTrue(controller.addPlayer("Giorgio")); + assertTrue(controller.addPlayer("Marco")); + assertTrue(controller.addPlayer("Luca")); + + return game; + } + + private Queue completeSlotChoice(Game game, GameController controller) { + Queue order = new LinkedList<>(); + + for (int i = 0; i < 3; i++) { + Player current = game.getCurrentState().getCurrentPlayer(); + order.add(current); + + assertTrue(controller.slotChoice(current.getUserName(), i)); + } + + assertEquals(GameStages.RESOLVING_ACTIONS, game.getCurrentState().getGameStage()); + + return order; + } + + private int firstNonEventIndex(List cards) { + for (int i = 0; i < cards.size(); i++) { + if (!cards.get(i).IsEventCard()) { + return i; + } + } + + fail("No non-event tribe card available."); + return -1; + } + + private int firstEventIndexOrMinusOne(List cards) { + for (int i = 0; i < cards.size(); i++) { + if (cards.get(i).IsEventCard()) { + return i; + } + } + + return -1; + } + + private int firstNonEventIndexOrMinusOne(List cards) { + for (int i = 0; i < cards.size(); i++) { + if (!cards.get(i).IsEventCard()) { + return i; + } + } + + return -1; + } + + private void giveOptionalEffectToAllPlayers(Game game) { + Player first = game.getPlayerByUsername("Giorgio"); + Player second = game.getPlayerByUsername("Marco"); + Player third = game.getPlayerByUsername("Luca"); + + assertNotNull(first); + assertNotNull(second); + assertNotNull(third); + + first.buildingCards.add(new BuildingCard(12, 1, 1, 0)); + second.buildingCards.add(new BuildingCard(12, 1, 1, 0)); + third.buildingCards.add(new BuildingCard(12, 1, 1, 0)); + } + + private void resolveActionsUntilOptionalCardEffect(Game game, GameController controller) { + int guard = 0; + + while (game.getCurrentState().getGameStage() == GameStages.RESOLVING_ACTIONS && guard < 20) { + guard++; + + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + if (game.getCurrentState().getNLower() > 0) { + int index = firstNonEventIndexOrMinusOne(game.getLowerListTribeCards()); + + if (index == -1) { + fail("No non-event lower tribe card available."); + } + + assertTrue(controller.drawLowerTribeCard(current.getUserName(), index)); + } else if (game.getCurrentState().getNUpper() > 0) { + int index = firstNonEventIndexOrMinusOne(game.getUpperListTribeCards()); + + if (index == -1) { + fail("No non-event upper tribe card available."); + } + + assertTrue(controller.drawUpperTribeCard(current.getUserName(), index)); + } else { + fail("Current player has no remaining upper or lower draws."); + } + } + + assertEquals(GameStages.OPTIONAL_CARD_EFFECT, game.getCurrentState().getGameStage()); + } + + @Test void addPlayer() { Game game = new Game(3); @@ -47,23 +156,15 @@ class GameControllerTest { @Test void slotChoice() { - Game game = new Game(3); + Game game = createStartedGame(); GameController controller = new GameController(game); - assertTrue(controller.addPlayer("Giorgio")); - assertTrue(controller.addPlayer("Marco")); - assertTrue(controller.addPlayer("Luca")); - String cur = game.getCurrentState().getCurrentPlayer().getUserName(); String other = cur.equals("Giorgio") ? "Marco" : "Giorgio"; + assertFalse(controller.slotChoice(other, 0)); - Queue order = new LinkedList<>(); - for (int i = 0; i < 3; i++) { - Player p = game.getCurrentState().getCurrentPlayer(); - order.add(p); - assertTrue(controller.slotChoice(p.getUserName(), i)); - } + Queue order = completeSlotChoice(game, controller); assertEquals(GameStages.RESOLVING_ACTIONS, game.getCurrentState().getGameStage()); assertEquals(order.poll(), game.getCurrentState().getCurrentPlayer()); @@ -71,66 +172,43 @@ class GameControllerTest { @Test void drawLowerTribeCard() { - Game game = new Game(3); + Game game = createStartedGame(); GameController controller = new GameController(game); - assertTrue(controller.addPlayer("Giorgio")); - assertTrue(controller.addPlayer("Marco")); - assertTrue(controller.addPlayer("Luca")); - - Queue order = new LinkedList<>(); - for (int i = 0; i < 3; i++) { - Player p = game.getCurrentState().getCurrentPlayer(); - order.add(p); - assertTrue(controller.slotChoice(p.getUserName(), i)); - } + Queue order = completeSlotChoice(game, controller); Player first = order.poll(); assertEquals(first, game.getCurrentState().getCurrentPlayer()); List cards = game.getLowerListTribeCards(); - int idx = cards.indexOf( - cards.stream() - .filter(c -> !c.IsEventCard()) - .findFirst() - .orElseThrow() - ); + int idx = firstNonEventIndex(cards); Player wrongPlayer = order.peek(); assertNotNull(wrongPlayer); + assertFalse(controller.drawLowerTribeCard(wrongPlayer.getUserName(), idx)); + int before = first.getTotCharacters(); + assertTrue(controller.drawLowerTribeCard(first.getUserName(), idx)); + assertEquals(before + 1, first.getTotCharacters()); } @Test void drawUpperTribeCard() { - Game game = new Game(3); + Game game = createStartedGame(); GameController controller = new GameController(game); - assertTrue(controller.addPlayer("Giorgio")); - assertTrue(controller.addPlayer("Marco")); - assertTrue(controller.addPlayer("Luca")); - - for (int i = 0; i < 3; i++) { - Player p = game.getCurrentState().getCurrentPlayer(); - assertTrue(controller.slotChoice(p.getUserName(), i)); - } - - assertEquals(GameStages.RESOLVING_ACTIONS, game.getCurrentState().getGameStage()); + completeSlotChoice(game, controller); while (game.getCurrentState().getNUpper() == 0) { assertTrue(game.getCurrentState().getNLower() > 0); Player current = game.getCurrentState().getCurrentPlayer(); + List lower = game.getLowerListTribeCards(); - int lowerIdx = lower.indexOf( - lower.stream() - .filter(c -> !c.IsEventCard()) - .findFirst() - .orElseThrow() - ); + int lowerIdx = firstNonEventIndex(lower); assertTrue(controller.drawLowerTribeCard(current.getUserName(), lowerIdx)); } @@ -139,12 +217,7 @@ class GameControllerTest { int beforeTot = current.getTotCharacters(); List upper = game.getUpperListTribeCards(); - int upperIdx = upper.indexOf( - upper.stream() - .filter(c -> !c.IsEventCard()) - .findFirst() - .orElseThrow() - ); + int upperIdx = firstNonEventIndex(upper); assertTrue(controller.drawUpperTribeCard(current.getUserName(), upperIdx)); assertEquals(beforeTot + 1, current.getTotCharacters()); @@ -152,31 +225,18 @@ class GameControllerTest { @Test void drawUpperBuildingCard() { - Game game = new Game(3); + Game game = createStartedGame(); GameController controller = new GameController(game); - assertTrue(controller.addPlayer("Giacomo")); - assertTrue(controller.addPlayer("Marco")); - assertTrue(controller.addPlayer("Luca")); - - for (int i = 0; i < 3; i++) { - Player p = game.getCurrentState().getCurrentPlayer(); - assertTrue(controller.slotChoice(p.getUserName(), i)); - } - - assertEquals(GameStages.RESOLVING_ACTIONS, game.getCurrentState().getGameStage()); + completeSlotChoice(game, controller); while (game.getCurrentState().getNUpper() == 0) { assertTrue(game.getCurrentState().getNLower() > 0); Player current = game.getCurrentState().getCurrentPlayer(); + List lower = game.getLowerListTribeCards(); - int lowerIdx = lower.indexOf( - lower.stream() - .filter(c -> !c.IsEventCard()) - .findFirst() - .orElseThrow() - ); + int lowerIdx = firstNonEventIndex(lower); assertTrue(controller.drawLowerTribeCard(current.getUserName(), lowerIdx)); } @@ -186,43 +246,214 @@ class GameControllerTest { assertFalse(controller.drawUpperBuildingCard(current.getUserName(), 0)); current.addFood(100); + int foodBefore = current.getFoodValue(); + int buildingsBefore = current.buildingCards.size(); + assertTrue(controller.drawUpperBuildingCard(current.getUserName(), 0)); + + assertTrue(current.getFoodValue() < foodBefore); + assertEquals(buildingsBefore + 1, current.buildingCards.size()); } - @Test - void drawLowerBuildingCard() { - Game game = new Game(3); - GameController controller = new GameController(game); + @Test + void drawingByIndexThroughController() { + Game game = new Game(3); + GameController controller = new GameController(game); - assertTrue(controller.addPlayer("Giacomo")); - assertTrue(controller.addPlayer("Marco")); - assertTrue(controller.addPlayer("Luca")); + assertTrue(controller.addPlayer("p1")); + assertTrue(controller.addPlayer("p2")); + assertFalse(controller.addPlayer("p2")); + assertTrue(controller.addPlayer("p3")); - for (int i = 0; i < 3; i++) { - Player p = game.getCurrentState().getCurrentPlayer(); - assertTrue(controller.slotChoice(p.getUserName(), i)); + Queue players = new LinkedList<>(); + + for (int i = 0; i < 3; i++) { + Player current = game.getCurrentState().getCurrentPlayer(); + players.add(current); + + assertTrue(controller.slotChoice(current.getUserName(), i)); + } + + assertEquals(GameStages.RESOLVING_ACTIONS, game.getCurrentState().getGameStage()); + + Player tempPlayer = players.poll(); + assertNotNull(tempPlayer); + assertEquals(tempPlayer, game.getCurrentState().getCurrentPlayer()); + + List cards = game.getLowerListTribeCards(); + int index = firstNonEventIndex(cards); + + assertTrue(controller.drawLowerTribeCard(tempPlayer.getUserName(), index)); + + tempPlayer = players.poll(); + assertNotNull(tempPlayer); + assertEquals(tempPlayer, game.getCurrentState().getCurrentPlayer()); + + while (game.getCurrentState().getNUpper() > 1) { + cards = game.getUpperListTribeCards(); + + index = firstNonEventIndexOrMinusOne(cards); + + if (index == -1) { + break; } - String cur = game.getCurrentState().getCurrentPlayer().getUserName(); - assertFalse(controller.drawLowerBuildingCard(cur, 0)); + int before = tempPlayer.getTotCharacters(); + + assertTrue(controller.drawUpperTribeCard(tempPlayer.getUserName(), index)); + + assertEquals(before + 1, tempPlayer.getTotCharacters()); + } + + cards = game.getUpperListTribeCards(); + + int eventIndex = firstEventIndexOrMinusOne(cards); + + if (eventIndex != -1) { + assertFalse(controller.drawUpperTribeCard(tempPlayer.getUserName(), eventIndex)); + } + + tempPlayer.addFood(100); + + assertFalse(controller.drawUpperBuildingCard(tempPlayer.getUserName(), 999)); + + if (!game.getUpperListBuilding().isEmpty() && game.getCurrentState().getNUpper() > 0) { + assertTrue(controller.drawUpperBuildingCard(tempPlayer.getUserName(), 0)); + } + + cards = game.getUpperListTribeCards(); + + int nonEventIndex = firstNonEventIndexOrMinusOne(cards); + + if (nonEventIndex != -1) { + assertFalse(controller.drawUpperTribeCard(tempPlayer.getUserName(), nonEventIndex)); + } } - @Test - void pickOptionalCards() { - Game game = new Game(3); - GameController controller = new GameController(game); + @Test + void drawLowerBuildingCardShouldReturnFalseForUnavailableLowerBuildingCard() { + Game game = createStartedGame(); + GameController controller = new GameController(game); - assertTrue(controller.addPlayer("Giacomo")); - assertTrue(controller.addPlayer("Marco")); - assertTrue(controller.addPlayer("Luca")); + completeSlotChoice(game, controller); - for (int i = 0; i < 3; i++) { - Player p = game.getCurrentState().getCurrentPlayer(); - assertTrue(controller.slotChoice(p.getUserName(), i)); - } + Player current = game.getCurrentState().getCurrentPlayer(); - String cur = game.getCurrentState().getCurrentPlayer().getUserName(); - assertFalse(controller.pickOptionalTribeCard(cur, 0)); - assertFalse(controller.pickOptionalBuildingCard(cur, 0)); + assertFalse(controller.drawLowerBuildingCard(current.getUserName(), 0)); + } + + @Test + void pickOptionalCardsShouldReturnFalseOutsideOptionalCardEffectState() { + Game game = createStartedGame(); + GameController controller = new GameController(game); + + completeSlotChoice(game, controller); + + assertEquals(GameStages.RESOLVING_ACTIONS, game.getCurrentState().getGameStage()); + + String cur = game.getCurrentState().getCurrentPlayer().getUserName(); + + assertFalse(controller.pickOptionalTribeCard(cur, 0)); + assertFalse(controller.pickOptionalBuildingCard(cur, 0)); + } + + @Test + void pickOptionalTribeCardShouldWorkDuringOptionalCardEffectState() { + Game game = createStartedGame(); + GameController controller = new GameController(game); + + giveOptionalEffectToAllPlayers(game); + + completeSlotChoice(game, controller); + resolveActionsUntilOptionalCardEffect(game, controller); + + Player optionalPlayer = game.getCurrentState().getCurrentPlayer(); + assertNotNull(optionalPlayer); + + assertTrue(optionalPlayer.buildingCards.stream() + .anyMatch(building -> building.getEffectId() == 12)); + + List upperCards = game.getUpperListTribeCards(); + int index = firstNonEventIndex(upperCards); + + int charactersBefore = optionalPlayer.getTotCharacters(); + + assertTrue(controller.pickOptionalTribeCard(optionalPlayer.getUserName(), index)); + + assertEquals(charactersBefore + 1, optionalPlayer.getTotCharacters()); + } + + @Test + void pickOptionalBuildingCardShouldWorkDuringOptionalCardEffectState() { + Game game = createStartedGame(); + GameController controller = new GameController(game); + + giveOptionalEffectToAllPlayers(game); + + completeSlotChoice(game, controller); + resolveActionsUntilOptionalCardEffect(game, controller); + + Player optionalPlayer = game.getCurrentState().getCurrentPlayer(); + assertNotNull(optionalPlayer); + + assertTrue(optionalPlayer.buildingCards.stream() + .anyMatch(building -> building.getEffectId() == 12)); + + assertFalse(game.getUpperListBuilding().isEmpty()); + + optionalPlayer.addFood(100); + + int foodBefore = optionalPlayer.getFoodValue(); + int buildingsBefore = optionalPlayer.buildingCards.size(); + + assertTrue(controller.pickOptionalBuildingCard(optionalPlayer.getUserName(), 0)); + + assertTrue(optionalPlayer.getFoodValue() < foodBefore); + assertEquals(buildingsBefore + 1, optionalPlayer.buildingCards.size()); + } + + @Test + void addPlayerShouldRejectDuplicateUsername() { + Game game = new Game(3); + GameController controller = new GameController(game); + + assertTrue(controller.addPlayer("Giorgio")); + assertFalse(controller.addPlayer("Giorgio")); + } + + @Test + void drawingMethodsShouldReturnFalseForInvalidIndexes() { + Game game = createStartedGame(); + GameController controller = new GameController(game); + + completeSlotChoice(game, controller); + + Player current = game.getCurrentState().getCurrentPlayer(); + String username = current.getUserName(); + + assertFalse(controller.drawLowerTribeCard(username, -1)); + assertFalse(controller.drawLowerTribeCard(username, 999)); + + assertFalse(controller.drawUpperTribeCard(username, -1)); + assertFalse(controller.drawUpperTribeCard(username, 999)); + + assertFalse(controller.drawLowerBuildingCard(username, -1)); + assertFalse(controller.drawLowerBuildingCard(username, 999)); + + assertFalse(controller.drawUpperBuildingCard(username, -1)); + assertFalse(controller.drawUpperBuildingCard(username, 999)); + } + + @Test + void slotChoiceShouldReturnFalseForAlreadyOccupiedSlot() { + Game game = createStartedGame(); + GameController controller = new GameController(game); + + Player first = game.getCurrentState().getCurrentPlayer(); + assertTrue(controller.slotChoice(first.getUserName(), 0)); + + Player second = game.getCurrentState().getCurrentPlayer(); + + assertFalse(controller.slotChoice(second.getUserName(), 0)); } } 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 ac50d5a..959dd13 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/GameTest.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/GameTest.java @@ -5,186 +5,381 @@ import it.polimi.ingsw.gc14.Model.Cards.TribeCard; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Character; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.CharacterType; import it.polimi.ingsw.gc14.Model.GamePackage.GameStages; -import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; -import org.junit.platform.commons.annotation.Testable; +import org.junit.jupiter.api.Timeout; +import java.io.IOException; import java.util.*; +import java.util.concurrent.TimeUnit; import static org.junit.jupiter.api.Assertions.*; +@Timeout(value = 10, unit = TimeUnit.SECONDS) class GameTest { - @Test void Game() - { - int nPlayers = 3; - Game game=new Game(nPlayers); - assertEquals(nPlayers,game.getNPlayers()); - assertEquals(GameStages.WAITING,game.getCurrentState().getGameStage()); - assertThrows(IllegalArgumentException.class,()->new Game(6)); - game=new Game(); + + private Queue completeSlotChoice(Game game) { + Queue order = new LinkedList<>(); + + for (int i = 0; i < game.getNPlayers(); i++) { + Player current = game.getCurrentState().getCurrentPlayer(); + order.add(current); + + assertTrue(game.SlotChoiceByIndex(current, i)); + } + + assertEquals(GameStages.RESOLVING_ACTIONS, game.getCurrentState().getGameStage()); + + return order; + } + + private int firstNonEventIndex(List cards) { + for (int i = 0; i < cards.size(); i++) { + if (!cards.get(i).IsEventCard()) { + return i; + } + } + + fail("No non-event tribe card available."); + return -1; + } + + private int firstNonEventIndexOrMinusOne(List cards) { + for (int i = 0; i < cards.size(); i++) { + if (!cards.get(i).IsEventCard()) { + return i; + } + } + + return -1; + } + + private void giveOptionalEffectToAllPlayers(Player... players) { + for (Player player : players) { + player.buildingCards.add(new BuildingCard(12, 1, 1, 1)); + } + } + + private void resolveAllMandatoryActions(Game game) { + while (game.getCurrentState().getGameStage() == GameStages.RESOLVING_ACTIONS) { + resolveOneMandatoryAction(game); + } + } + + private void resolveOneMandatoryAction(Game game) { + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + if (game.getCurrentState().getNLower() > 0 && hasDrawableLower(game)) { + int index = firstNonEventIndexOrMinusOne(game.getLowerListTribeCards()); + + if (index != -1) { + assertTrue(game.DrawLowerTribeCardByIndex(current, index)); + } else { + current.addFood(100); + assertTrue(game.DrawLowerBuildingCardByIndex(current, 0)); + } + + } else if (game.getCurrentState().getNUpper() > 0 && hasDrawableUpper(game)) { + int index = firstNonEventIndexOrMinusOne(game.getUpperListTribeCards()); + + if (index != -1) { + assertTrue(game.DrawUpperTribeCardByIndex(current, index)); + } else { + current.addFood(100); + assertTrue(game.DrawUpperBuildingCardByIndex(current, 0)); + } + + } else { + fail( + "Current player has no drawable cards, although the game is still resolving actions.\n" + + "Current player: " + current + "\n" + + "Round: " + game.getCurrentState().getRound() + "\n" + + "Stage: " + game.getCurrentState().getGameStage() + "\n" + + "Slot: " + (game.getCurrentState().getSlot() == null + ? "null" + : game.getCurrentState().getSlot().getSlotId()) + "\n" + + "NLower: " + game.getCurrentState().getNLower() + "\n" + + "NUpper: " + game.getCurrentState().getNUpper() + "\n" + + "Lower tribe size: " + game.getLowerListTribeCards().size() + "\n" + + "Upper tribe size: " + game.getUpperListTribeCards().size() + "\n" + + "Lower building size: " + game.getLowerListBuilding().size() + "\n" + + "Upper building size: " + game.getUpperListBuilding().size() + "\n" + + "First lower non-event: " + firstNonEventIndexOrMinusOne(game.getLowerListTribeCards()) + "\n" + + "First upper non-event: " + firstNonEventIndexOrMinusOne(game.getUpperListTribeCards()) + ); + } + } + + private void resolveActionsUntilOptionalCardEffect(Game game) { + while (game.getCurrentState().getGameStage() == GameStages.RESOLVING_ACTIONS) { + resolveOneMandatoryAction(game); + } + + assertEquals(GameStages.OPTIONAL_CARD_EFFECT, game.getCurrentState().getGameStage()); + } + + private void resolveOptionalPhaseIfPresent(Game game) { + while (game.getCurrentState().getGameStage() == GameStages.OPTIONAL_CARD_EFFECT) { + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + assertTrue(game.NoOptionalCard(current)); + } + } + + private void playOneFullRound(Game game) { + assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + + completeSlotChoice(game); + + assertEquals(GameStages.RESOLVING_ACTIONS, game.getCurrentState().getGameStage()); + + resolveAllMandatoryActions(game); + + resolveOptionalPhaseIfPresent(game); + } + + private boolean hasDrawableLower(Game game) { + return firstNonEventIndexOrMinusOne(game.getLowerListTribeCards()) != -1 + || !game.getLowerListBuilding().isEmpty(); + } + + private boolean hasDrawableUpper(Game game) { + return firstNonEventIndexOrMinusOne(game.getUpperListTribeCards()) != -1 + || !game.getUpperListBuilding().isEmpty(); + } + + @Test + void constructorShouldInitializeGameCorrectly() { + int nPlayers = 3; + Game game = new Game(nPlayers); + + assertEquals(nPlayers, game.getNPlayers()); + assertEquals(GameStages.WAITING, game.getCurrentState().getGameStage()); + + assertThrows(IllegalArgumentException.class, () -> new Game(6)); + assertThrows(IllegalArgumentException.class, () -> new Game(-1)); + + game = new Game(); + assertFalse(game.addPlayer(new Player("p1"))); - game.setNPlayer(nPlayers); + + + assertTrue(game.setNPlayer(nPlayers)); assertTrue(game.addPlayer(new Player("p1"))); - assertEquals(nPlayers,game.getNPlayers()); - assertEquals(GameStages.WAITING,game.getCurrentState().getGameStage()); + + assertEquals(nPlayers, game.getNPlayers()); + assertEquals(GameStages.WAITING, game.getCurrentState().getGameStage()); } @Test void getUpperListTribeCards() { int nPlayers = 3; - Game game=new Game(nPlayers); - assertEquals(nPlayers+4 ,game.getUpperListTribeCards().size()); + Game game = new Game(nPlayers); + assertEquals(nPlayers + 4, game.getUpperListTribeCards().size()); } + @Test void getUpperListBuildingCards() { int nPlayers = 3; - Game game=new Game(nPlayers); - assertEquals(2 ,game.getUpperListBuilding().size()); + Game game = new Game(nPlayers); + assertEquals(2, game.getUpperListBuilding().size()); } @Test void getLowerListBuildingCards() { int nPlayers = 3; - Game game=new Game(nPlayers); - assertEquals(0 ,game.getLowerListBuilding().size()); + Game game = new Game(nPlayers); + assertEquals(0, game.getLowerListBuilding().size()); } @Test void getLowerListTribeCards() { int nPlayers = 3; - Game game=new Game(nPlayers); - assertEquals(nPlayers+1 ,game.getLowerListTribeCards().size()); + Game game = new Game(nPlayers); + assertEquals(nPlayers + 1, game.getLowerListTribeCards().size()); } @Test - void getPlayerByIndex() { + void getPlayerByUsernameShouldReturnPlayerOrNull() { + Game game = new Game(3); + + Player p1 = new Player("p1"); + + assertTrue(game.addPlayer(p1)); + + assertEquals(p1, game.getPlayerByUsername("p1")); + assertNull(game.getPlayerByUsername("ghost")); } @Test - void getNPlayers() { + void setNPlayerShouldWorkOnlyIfGameWasCreatedWithZeroPlayers() { + Game game = new Game(); + assertTrue(game.setNPlayer(3)); + assertEquals(3, game.getNPlayers()); + + assertFalse(game.setNPlayer(4)); } @Test - void addPlayer() { - Game game=new Game(3); - Player p1=new Player("p1"); - Player p2=new Player("p2"); - Player p3=new Player("p3"); - Player p4=new Player("p3"); + void addPlayerShouldRejectDuplicatesAndStartSlotChoiceWhenFull() { + Game game = new Game(3); + Player p1 = new Player("p1"); + Player p2 = new Player("p2"); + Player p3 = new Player("p3"); + Player p4 = new Player("p4"); assertTrue(game.addPlayer(p1)); assertTrue(game.addPlayer(p2)); assertFalse(game.addPlayer(p2)); assertTrue(game.addPlayer(p3)); - assertEquals(GameStages.SLOT_CHOICE,game.getCurrentState().getGameStage()); + assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + assertFalse(game.addPlayer(p4)); - - } @Test - void init() { + void shouldRejectInvalidSlotChoices() { + Game game = new Game(3); - } + Player p1 = new Player("p1"); + Player p2 = new Player("p2"); + Player p3 = new Player("p3"); - @Test - void slotChoiceByIndex() { + assertTrue(game.addPlayer(p1)); + assertTrue(game.addPlayer(p2)); + assertTrue(game.addPlayer(p3)); + + Player current = game.getCurrentState().getCurrentPlayer(); + + assertFalse(game.SlotChoiceByIndex(current, -1)); + assertFalse(game.SlotChoiceByIndex(current, 999)); + + Player wrongPlayer = current.equals(p1) ? p2 : p1; + assertFalse(game.SlotChoiceByIndex(wrongPlayer, 0)); + + assertTrue(game.SlotChoiceByIndex(current, 0)); + + Player next = game.getCurrentState().getCurrentPlayer(); + assertFalse(game.SlotChoiceByIndex(next, 0)); } @Test void drawingByIndex() { - Game game=new Game(3); - Player p1=new Player("p1"); - Player p2=new Player("p2"); - Player p3=new Player("p3"); - Player p4=new Player("p3"); + 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)); assertFalse(game.addPlayer(p2)); assertTrue(game.addPlayer(p3)); - Queueplayers=new LinkedList<>(); - for(int i=0;i<3;i++) { - players.add( game.getCurrentState().getCurrentPlayer()); + Queue players = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + players.add(game.getCurrentState().getCurrentPlayer()); assertTrue(game.SlotChoiceByIndex(game.getCurrentState().getCurrentPlayer(), i)); } Player temp_player; - System.out.println(game); - temp_player=players.poll(); - assertEquals(temp_player,game.getCurrentState().getCurrentPlayer()); + + temp_player = players.poll(); + assertEquals(temp_player, game.getCurrentState().getCurrentPlayer()); int index; - List cards=game.getLowerListTribeCards(); + List cards = game.getLowerListTribeCards(); - index=cards.indexOf(cards.stream().filter(x->!x.IsEventCard()).findFirst().get()); - assertTrue(game.DrawLowerTribeCardByIndex(temp_player,index)); + index = firstNonEventIndex(cards); + assertTrue(game.DrawLowerTribeCardByIndex(temp_player, index)); - temp_player=players.poll(); - assertEquals(temp_player,game.getCurrentState().getCurrentPlayer()); - int nCards=game.getUpperListTribeCards().size(); - int countCards=0; - HashMapnCardsByType=new HashMap(); - Arrays.stream(CharacterType.values()).forEach(type->nCardsByType.put(type,0)); - while(game.getCurrentState().getNUpper()>1) { - cards=game.getUpperListTribeCards(); - TribeCard temp_card=cards.stream().filter(x->!x.IsEventCard()).findFirst().get(); - index=cards.indexOf(temp_card); - assertEquals(nCards-countCards,game.getUpperListTribeCards().size()-countCards); - drawTribeTest(nCardsByType,nCards,countCards,temp_card,temp_player,game); - assertTrue(game.DrawUpperTribeCardByIndex(temp_player,index)); + temp_player = players.poll(); + assertEquals(temp_player, game.getCurrentState().getCurrentPlayer()); + + int nCards = game.getUpperListTribeCards().size(); + int countCards = 0; + HashMap nCardsByType = new HashMap(); + Arrays.stream(CharacterType.values()).forEach(type -> nCardsByType.put(type, 0)); + while (game.getCurrentState().getNUpper() > 1) { + cards = game.getUpperListTribeCards(); + index = firstNonEventIndexOrMinusOne(cards); + + if (index == -1) { + break; + } + + TribeCard temp_card = cards.get(index); + assertEquals(nCards - countCards, game.getUpperListTribeCards().size()); + assertTrue(game.DrawUpperTribeCardByIndex(temp_player, index)); + drawTribeTest(nCardsByType, temp_card, temp_player); countCards++; } - cards=game.getUpperListTribeCards(); - try { - index = cards.indexOf(cards.stream().filter(TribeCard::IsEventCard).findFirst().get()); - assertFalse(game.DrawUpperTribeCardByIndex(temp_player, index)); - }catch (Exception e) { + cards = game.getUpperListTribeCards(); + int eventIndex = firstEventIndexOrMinusOne(cards); + if (eventIndex != -1) { + assertFalse(game.DrawUpperTribeCardByIndex(temp_player, eventIndex)); } - //index=cards.indexOf(cards.stream().filter(x->!x.IsEventCard()).findFirst().get()); - //assertTrue(game.DrawUpperTribeCardByIndex(temp_player,index)); - List buildings=game.getUpperListBuilding(); - temp_player.addFood(10); - index=0; - assertTrue(game.DrawUpperBuildingCardByIndex(temp_player,index)); - index=cards.indexOf(cards.stream().filter(x->!x.IsEventCard()).findFirst().get()); - assertFalse(game.DrawUpperTribeCardByIndex(temp_player,index)); + + temp_player.addFood(100); + + assertFalse(game.getUpperListBuilding().isEmpty()); + + index = 0; + assertTrue(game.DrawUpperBuildingCardByIndex(temp_player, index)); + + int remainingTribeIndex = firstNonEventIndexOrMinusOne(game.getUpperListTribeCards()); + if (remainingTribeIndex != -1) { + assertFalse(game.DrawUpperTribeCardByIndex(temp_player, remainingTribeIndex)); + } + + Player thirdPlayer = players.poll(); + assertNotNull(thirdPlayer); + assertEquals(thirdPlayer, game.getCurrentState().getCurrentPlayer()); + + while (game.getCurrentState().getGameStage() == GameStages.RESOLVING_ACTIONS + && thirdPlayer.equals(game.getCurrentState().getCurrentPlayer())) { + resolveOneMandatoryAction(game); + } + + assertNotEquals(thirdPlayer, game.getCurrentState().getCurrentPlayer()); System.out.println(game); } - private void drawTribeTest(HashMapnCardsByType,int nCards,int countCards,TribeCard temp_card,Player temp_player,Game game) { - switch (((Character)temp_card).getType()) { - case CharacterType.ARTIST: - assertEquals( nCardsByType.get(((Character)temp_card).getType())+1,temp_player.artists.size()); - nCardsByType.merge(((Character)temp_card).getType(),1,Integer::sum); + private void drawTribeTest(HashMap nCardsByType, + TribeCard temp_card, + Player temp_player) { + + switch (((Character) temp_card).getType()) { + case ARTIST: + assertEquals(nCardsByType.get(((Character) temp_card).getType()) + 1, temp_player.artists.size()); + nCardsByType.merge(((Character) temp_card).getType(), 1, Integer::sum); break; - case CharacterType.INVENTOR: - assertEquals( nCardsByType.get(((Character)temp_card).getType())+1,temp_player.inventors.size()); - nCardsByType.merge(((Character)temp_card).getType(),1,Integer::sum); + case INVENTOR: + assertEquals(nCardsByType.get(((Character) temp_card).getType()) + 1, temp_player.inventors.size()); + nCardsByType.merge(((Character) temp_card).getType(), 1, Integer::sum); break; - case CharacterType.HUNTER: - assertEquals( nCardsByType.get(((Character)temp_card).getType())+1,temp_player.hunters.size()); - nCardsByType.merge(((Character)temp_card).getType(),1,Integer::sum); + case HUNTER: + assertEquals(nCardsByType.get(((Character) temp_card).getType()) + 1, temp_player.hunters.size()); + nCardsByType.merge(((Character) temp_card).getType(), 1, Integer::sum); break; - case CharacterType.SHAMAN: - assertEquals( nCardsByType.get(((Character)temp_card).getType())+1,temp_player.shamans.size()); - nCardsByType.merge(((Character)temp_card).getType(),1,Integer::sum); + case SHAMAN: + assertEquals(nCardsByType.get(((Character) temp_card).getType()) + 1, temp_player.shamans.size()); + nCardsByType.merge(((Character) temp_card).getType(), 1, Integer::sum); break; - case CharacterType.BUILDER: - assertEquals( nCardsByType.get(((Character)temp_card).getType())+1,temp_player.builders.size()); - nCardsByType.merge(((Character)temp_card).getType(),1,Integer::sum); + case BUILDER: + assertEquals(nCardsByType.get(((Character) temp_card).getType()) + 1, temp_player.builders.size()); + nCardsByType.merge(((Character) temp_card).getType(), 1, Integer::sum); break; - case CharacterType.GATHERER: - assertEquals( nCardsByType.get(((Character)temp_card).getType())+1,temp_player.gatherers.size()); - nCardsByType.merge(((Character)temp_card).getType(),1,Integer::sum); + case GATHERER: + assertEquals(nCardsByType.get(((Character) temp_card).getType()) + 1, temp_player.gatherers.size()); + nCardsByType.merge(((Character) temp_card).getType(), 1, Integer::sum); break; } @@ -192,30 +387,447 @@ class GameTest { @Test void pickOptionalTribeCard() { - } - @Test - void pickOptionalBuildingCard() { - } - @Test - void noOptionalCard() { - } - @Test - void toStringModel() - { - Game game=new Game(3); - Player p1=new Player("p1"); - Player p2=new Player("p2"); - Player p3=new Player("p3"); + 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)); + giveOptionalEffectToAllPlayers(p1, p2, p3); + + completeSlotChoice(game); + resolveActionsUntilOptionalCardEffect(game); + + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + int index = firstNonEventIndex(game.getUpperListTribeCards()); + + int charactersBefore = current.getTotCharacters(); + + assertTrue(game.PickOptionalTribeCardByIndex(current, index)); + + assertEquals(charactersBefore + 1, current.getTotCharacters()); + } + + @Test + void pickOptionalBuildingCard() { + 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)); + + giveOptionalEffectToAllPlayers(p1, p2, p3); + + completeSlotChoice(game); + resolveActionsUntilOptionalCardEffect(game); + + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + assertFalse(game.getUpperListBuilding().isEmpty()); + + current.addFood(100); + + int foodBefore = current.getFoodValue(); + int buildingsBefore = current.buildingCards.size(); + + assertTrue(game.PickOptionalBuildingCard(current, 0)); + + assertTrue(current.getFoodValue() < foodBefore); + assertEquals(buildingsBefore + 1, current.buildingCards.size()); + } + + @Test + void noOptionalCard() { + 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)); + + giveOptionalEffectToAllPlayers(p1, p2, p3); + + completeSlotChoice(game); + resolveActionsUntilOptionalCardEffect(game); + + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + assertTrue(game.NoOptionalCard(current)); + + assertEquals(GameStages.OPTIONAL_CARD_EFFECT, game.getCurrentState().getGameStage()); + assertNotEquals(current, game.getCurrentState().getCurrentPlayer()); + } + + private List addPlayers(Game game, int nPlayers, String prefix) { + List players = new ArrayList<>(); + + for (int i = 1; i <= nPlayers; i++) { + Player player = new Player(prefix + i); + players.add(player); + assertTrue(game.addPlayer(player)); + } + + return players; + } + + private int firstEventIndexOrMinusOne(List cards) { + for (int i = 0; i < cards.size(); i++) { + if (cards.get(i).IsEventCard()) { + return i; + } + } + + return -1; + } + + @Test + void getCurrentPlayerNumberShouldTrackAddedPlayers() { + Game game = new Game(3); + + assertEquals(0, game.getCurrentPlayerNumber()); + + assertTrue(game.addPlayer(new Player("a"))); + assertEquals(1, game.getCurrentPlayerNumber()); + + assertTrue(game.addPlayer(new Player("b"))); + assertEquals(2, game.getCurrentPlayerNumber()); + + assertTrue(game.addPlayer(new Player("c"))); + assertEquals(3, game.getCurrentPlayerNumber()); + } + + + @Test + void slotChoiceByIndexShouldReturnFalseOutsideSlotChoiceStage() { + Game game = new Game(3); + + addPlayers(game, 3, "slot_out_"); + + completeSlotChoice(game); + + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + assertFalse(game.SlotChoiceByIndex(current, 0)); + } + + @Test + void shouldRejectInvalidDrawRequests() { + 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(); + assertNotNull(current); + + assertFalse(game.DrawLowerTribeCardByIndex(current, 0)); + assertFalse(game.DrawUpperTribeCardByIndex(current, 0)); + assertFalse(game.DrawUpperBuildingCardByIndex(current, 0)); + assertFalse(game.DrawLowerBuildingCardByIndex(current, 0)); + + completeSlotChoice(game); + + current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + Player wrongPlayer = current.equals(p1) ? p2 : p1; + + assertFalse(game.DrawLowerTribeCardByIndex(current, -1)); + assertFalse(game.DrawLowerTribeCardByIndex(current, 999)); + + assertFalse(game.DrawUpperTribeCardByIndex(current, -1)); + assertFalse(game.DrawUpperTribeCardByIndex(current, 999)); + + assertFalse(game.DrawUpperBuildingCardByIndex(current, -1)); + assertFalse(game.DrawUpperBuildingCardByIndex(current, 999)); + + assertFalse(game.DrawLowerBuildingCardByIndex(current, -1)); + assertFalse(game.DrawLowerBuildingCardByIndex(current, 999)); + + int lowerIndex = firstNonEventIndexOrMinusOne(game.getLowerListTribeCards()); + if (lowerIndex != -1) { + assertFalse(game.DrawLowerTribeCardByIndex(wrongPlayer, lowerIndex)); + } + + int upperIndex = firstNonEventIndexOrMinusOne(game.getUpperListTribeCards()); + if (upperIndex != -1) { + assertFalse(game.DrawUpperTribeCardByIndex(wrongPlayer, upperIndex)); + } + + if (!game.getUpperListBuilding().isEmpty()) { + assertFalse(game.DrawUpperBuildingCardByIndex(wrongPlayer, 0)); + } + } + + + @Test + void optionalMethodsShouldReturnFalseOutsideOptionalState() { + Game game = new Game(3); + + addPlayers(game, 3, "optional_out_"); + + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + assertFalse(game.PickOptionalTribeCardByIndex(current, 0)); + assertFalse(game.PickOptionalBuildingCard(current, 0)); + assertFalse(game.NoOptionalCard(current)); + } + + @Test + void optionalMethodsShouldRejectWrongPlayerAndInvalidIndexes() { + Game game = new Game(3); + + List players = addPlayers(game, 3, "optional_invalid_"); + + giveOptionalEffectToAllPlayers(players.get(0), players.get(1), players.get(2)); + + completeSlotChoice(game); + resolveActionsUntilOptionalCardEffect(game); + + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + Player wrongPlayer = current.equals(players.get(0)) ? players.get(1) : players.get(0); + + assertFalse(game.PickOptionalTribeCardByIndex(wrongPlayer, 0)); + assertFalse(game.PickOptionalBuildingCard(wrongPlayer, 0)); + assertFalse(game.NoOptionalCard(wrongPlayer)); + + assertFalse(game.PickOptionalTribeCardByIndex(current, -1)); + assertFalse(game.PickOptionalTribeCardByIndex(current, 999)); + + assertFalse(game.PickOptionalBuildingCard(current, -1)); + assertFalse(game.PickOptionalBuildingCard(current, 999)); + + } + + @Test + @Timeout(value = 2, unit = TimeUnit.SECONDS) + void shouldNotCrashWhenNoPlayerHasOptionalEffect() { + Game game = new Game(3); + + addPlayers(game, 3, "no_optional_"); + + completeSlotChoice(game); + + assertDoesNotThrow(() -> resolveAllMandatoryActions(game)); + + assertNotEquals(GameStages.OPTIONAL_CARD_EFFECT, game.getCurrentState().getGameStage()); + } + + + @Test + void constructorShouldRejectOnePlayerGame() { + assertThrows(IllegalArgumentException.class, () -> new Game(1)); + } + + @Test + void setNPlayerShouldAllowCompleteGameSetup() { + Game game = new Game(); + + assertTrue(game.setNPlayer(3)); + + assertTrue(game.addPlayer(new Player("p1"))); + assertTrue(game.addPlayer(new Player("p2"))); + assertTrue(game.addPlayer(new Player("p3"))); + + assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + assertTrue(game.SlotChoiceByIndex(current, 0)); + } + + @Test + @Timeout(value = 20, unit = TimeUnit.SECONDS) + void shouldCompleteFullGameThroughRealFlow() { + for (int nPlayers : new int[]{2, 3, 4, 5}) { + Game game = new Game(nPlayers); + + for (int i = 1; i <= nPlayers; i++) { + assertTrue(game.addPlayer(new Player("p" + nPlayers + "_" + i))); + } + + assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + assertEquals(1, game.getCurrentState().getRound()); + assertNotNull(game.getCurrentState().getCurrentPlayer()); + + for (int expectedRound = 1; expectedRound < 10; expectedRound++) { + assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + assertEquals(expectedRound, game.getCurrentState().getRound()); + + playOneFullRound(game); + + assertEquals( + GameStages.SLOT_CHOICE, + game.getCurrentState().getGameStage(), + "After round " + expectedRound + ", the game should return to SLOT_CHOICE." + ); + + assertEquals( + expectedRound + 1, + game.getCurrentState().getRound(), + "The round should increase after completing round " + expectedRound + "." + ); + + assertNotNull(game.getCurrentState().getCurrentPlayer()); + } + + assertEquals(10, game.getCurrentState().getRound()); + assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + + playOneFullRound(game); + + assertEquals( + GameStages.ENDED, + game.getCurrentState().getGameStage(), + "The game should end after completing round 10 with " + nPlayers + " players." + ); + + assertEquals( + 10, + game.getCurrentState().getRound(), + "The game should end at round 10 with " + nPlayers + " players." + ); + } + } + + @Test + void setNPlayerShouldRejectInvalidPlayerCounts() { + assertFalse(new Game().setNPlayer(-1)); + assertFalse(new Game().setNPlayer(1)); + assertFalse(new Game().setNPlayer(6)); + } + + @Test + void addPlayerShouldRejectDifferentPlayerWithSameUsername() { + Game game = new Game(3); + + assertTrue(game.addPlayer(new Player("same_name"))); + assertFalse(game.addPlayer(new Player("same_name"))); + } + + @Test + @Timeout(value = 2, unit = TimeUnit.SECONDS) + void roundShouldAdvanceAfterOnlyOptionalPlayerSkipsOptionalCard() { + Game game = new Game(3); + + List players = addPlayers(game, 3, "single_optional_"); + + players.get(0).buildingCards.add(new BuildingCard(12, 1, 1, 1)); + + int roundBefore = game.getCurrentState().getRound(); + + completeSlotChoice(game); + resolveActionsUntilOptionalCardEffect(game); + + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + assertTrue(game.NoOptionalCard(current)); + + assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + assertEquals(roundBefore + 1, game.getCurrentState().getRound()); + assertNotNull(game.getCurrentState().getCurrentPlayer()); + } + + @Test + @Timeout(value = 2, unit = TimeUnit.SECONDS) + void roundShouldAdvanceAfterAllOptionalPlayersSkipOptionalCard() { + 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)); + + giveOptionalEffectToAllPlayers(p1, p2, p3); + + int roundBefore = game.getCurrentState().getRound(); + + completeSlotChoice(game); + resolveActionsUntilOptionalCardEffect(game); + + resolveOptionalPhaseIfPresent(game); + + assertEquals(GameStages.SLOT_CHOICE, game.getCurrentState().getGameStage()); + assertEquals(roundBefore + 1, game.getCurrentState().getRound()); + assertNotNull(game.getCurrentState().getCurrentPlayer()); + } + + @Test + void pickOptionalBuildingCardShouldReturnFalseIfPlayerCannotPay() { + Game game = new Game(3); + List players = addPlayers(game, 3, "no_food_"); + + giveOptionalEffectToAllPlayers(players.get(0), players.get(1), players.get(2)); + + completeSlotChoice(game); + resolveActionsUntilOptionalCardEffect(game); + + Player current = game.getCurrentState().getCurrentPlayer(); + assertNotNull(current); + + while (current.getFoodValue() > 0) { + assertTrue(current.removeFood(1)); + } + + assertEquals(0, current.getFoodValue()); + + assertFalse( + game.getUpperListBuilding().isEmpty(), + "There must be at least one upper building card to test that the player cannot buy it." + ); + + assertFalse(game.PickOptionalBuildingCard(current, 0)); + } + @Test + void toStringModel() throws IOException, InterruptedException { + 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<3;i++) { players.add( game.getCurrentState().getCurrentPlayer()); assertTrue(game.SlotChoiceByIndex(game.getCurrentState().getCurrentPlayer(), i)); } - System.out.println(game); + + System.out.println(game.toString()); } } \ No newline at end of file diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order3Test.java b/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order3Test.java index 34c2e3e..3e24680 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order3Test.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order3Test.java @@ -69,7 +69,7 @@ class Order3Test { } @Test - void thirdReturnPaysFoodAndLosesPrestige() { + void thirdReturnPaysFoodWithoutLosingPrestige() { Player p1 = new Player("p1"); Player p2 = new Player("p2"); Player p3 = new Player("p3"); @@ -90,33 +90,7 @@ class Order3Test { order.push(thirdToAct); assertEquals(0, thirdToAct.getFoodValue()); - assertEquals(-2, thirdToAct.getPrestigeValue()); - } - - @Test - void thirdReturnWithoutFoodNoEffect() { - Player p1 = new Player("p1"); - Player p2 = new Player("p2"); - Player p3 = new Player("p3"); - ArrayList players = new ArrayList<>(); - players.add(p1); - players.add(p2); - players.add(p3); - Order3 order = new Order3(players); - - Player firstToAct = order.pull(); - Player secondToAct = order.pull(); - Player thirdToAct = order.pull(); - - int initialFood = thirdToAct.getFoodValue(); - int initialPrestige = thirdToAct.getPrestigeValue(); - - order.push(firstToAct); - order.push(secondToAct); - order.push(thirdToAct); - - assertEquals(initialFood, thirdToAct.getFoodValue()); - assertEquals(initialPrestige, thirdToAct.getPrestigeValue()); + assertEquals(0, thirdToAct.getPrestigeValue()); } @Test diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order4Test.java b/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order4Test.java index c562f60..78e731f 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order4Test.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order4Test.java @@ -102,7 +102,7 @@ class Order4Test { } @Test - void fourthReturnPaysFoodAndLosesPrestige() { + void fourthReturnPaysFoodWithoutLosingPrestige() { Player p1 = new Player("p1"); Player p2 = new Player("p2"); Player p3 = new Player("p3"); @@ -127,11 +127,11 @@ class Order4Test { order.push(fourthToAct); assertEquals(0, fourthToAct.getFoodValue()); - assertEquals(-2, fourthToAct.getPrestigeValue()); + assertEquals(0, fourthToAct.getPrestigeValue()); } @Test - void fourthReturnWithoutFoodNoEffect() { + void fourthReturnWithoutFoodLosesPrestige() { Player p1 = new Player("p1"); Player p2 = new Player("p2"); Player p3 = new Player("p3"); @@ -157,7 +157,7 @@ class Order4Test { order.push(fourthToAct); assertEquals(initialFood, fourthToAct.getFoodValue()); - assertEquals(initialPrestige, fourthToAct.getPrestigeValue()); + assertEquals(initialPrestige - 2, fourthToAct.getPrestigeValue()); } @Test diff --git a/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order5Test.java b/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order5Test.java index 0dceb69..9e838fb 100644 --- a/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order5Test.java +++ b/src/test/java/it/polimi/ingsw/gc14/Model/Orders/Order5Test.java @@ -12,7 +12,9 @@ import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.Test; import java.util.ArrayList; +import java.util.Arrays; import java.util.NoSuchElementException; + import static org.junit.jupiter.api.Assertions.*; class Order5Test { @@ -149,7 +151,7 @@ class Order5Test { } @Test - void fifthReturnPaysFoodAndLosesPrestige() { + void fifthReturnPaysFoodWithoutLosingPrestige() { Player p1 = new Player("p1"); Player p2 = new Player("p2"); Player p3 = new Player("p3"); @@ -178,11 +180,11 @@ class Order5Test { order.push(fifthToAct); assertEquals(0, fifthToAct.getFoodValue()); - assertEquals(-2, fifthToAct.getPrestigeValue()); + assertEquals(0, fifthToAct.getPrestigeValue()); } @Test - void fifthReturnWithoutFoodNoEffect() { + void fifthReturnWithoutFoodLosesPrestige() { Player p1 = new Player("p1"); Player p2 = new Player("p2"); Player p3 = new Player("p3"); @@ -212,7 +214,7 @@ class Order5Test { order.push(fifthToAct); assertEquals(initialFood, fifthToAct.getFoodValue()); - assertEquals(initialPrestige, fifthToAct.getPrestigeValue()); + assertEquals(initialPrestige - 2, fifthToAct.getPrestigeValue()); } @Test