Coverage Summary for Class: Controller (it.polimi.ingsw.Controller)
| Class | Class, % | Method, % | Branch, % | Line, % | 
|---|---|---|---|---|
| Controller | 100% (1/1) | 100% (5/5) | 90% (9/10) | 92,3% (24/26) | 
1 package it.polimi.ingsw.Controller; 2 3 import it.polimi.ingsw.Controller.Actions.EndTurnOfActionPhase; 4 import it.polimi.ingsw.Controller.Actions.PlayAssistantCard; 5 import it.polimi.ingsw.Controller.Actions.PlayerAction; 6 import it.polimi.ingsw.Exceptions.Input.GenericInputValidationException; 7 import it.polimi.ingsw.Exceptions.Input.InputValidationException; 8 import it.polimi.ingsw.Misc.OptionalValue; 9 import it.polimi.ingsw.Model.Enums.GameMode; 10 import it.polimi.ingsw.Model.Model; 11 import it.polimi.ingsw.Model.ModelWrapper; 12 import it.polimi.ingsw.Server.Lobby; 13 import it.polimi.ingsw.Server.Messages.Events.Internal.GameOverEvent; 14 import it.polimi.ingsw.Server.Messages.Events.Internal.ModelUpdateEvent; 15 16 import java.util.ArrayList; 17 import java.util.List; 18 import java.util.Objects; 19 20 /** 21 * This is the Controller of the whole game. <br> 22 * The Controller should be the only entity able to modify the model. 23 */ 24 public class Controller { 25 private final List<PlayerAction> history; 26 private final ModelWrapper modelWrapper; 27 private boolean unsafeReferences = false; 28 29 /** 30 * Subscribes a new {@link Controller} object to a {@link ModelWrapper} instance, allowing the creation of a 31 * Controller to Model connection. 32 * 33 * @param modelWrapper an instance of {@link ModelWrapper} 34 */ 35 private Controller(ModelWrapper modelWrapper) { 36 Objects.requireNonNull(modelWrapper); 37 38 this.history = new ArrayList<>(6); 39 this.modelWrapper = modelWrapper; 40 } 41 42 /** 43 * Generates a new instance of the {@link Controller}. This is the debug method to call to create a game, since the internal attributes 44 * are set to the parameters.<br> 45 * 46 * <b>Note:</b> this method will not protect model references after editing actions to the model. 47 * <b>Note:</b> this method should be called <b>ONLY</b> by test code. 48 * 49 * @param modelWrapper an instance of {@link ModelWrapper} 50 * @param history an instance to a list of {@link PlayerAction}, used by the controller to check the flow of the game 51 */ 52 Controller(ModelWrapper modelWrapper, List<PlayerAction> history) { 53 this.history = history; 54 this.modelWrapper = modelWrapper; 55 this.unsafeReferences = true; 56 } 57 58 /** 59 * Generates a new instance. This is the static method to call for general purpose creation of a game. 60 * 61 * @param gameMode the game mode the players are going to use 62 * @param lobby in case a server is used, insert the {@linkplain Lobby} object wrapped in an {@link OptionalValue} to let it 63 * receive {@link ModelUpdateEvent} and {@link GameOverEvent} 64 * @param players a list of minimum 2 and maximum 4 strings containing the nicknames of the players. 65 * In the case of 4 players: players at index 0 and 2 go together against players at index 1 and 3 66 * @return the generated controller 67 * @throws InputValidationException if the supplied players are less than 2 or more than 4 68 */ 69 public static Controller createGame(GameMode gameMode, OptionalValue<Lobby> lobby, String... players) throws InputValidationException { 70 Objects.requireNonNull(gameMode); 71 Objects.requireNonNull(lobby); 72 Objects.requireNonNull(players); 73 74 if (players.length > 1 && players.length <= 4) { 75 return new Controller(new ModelWrapper(new Model(gameMode, players), lobby)); 76 } else { 77 throw new GenericInputValidationException("Players", "The number of players must be 2, 3 or 4.\n" + 78 "Players received: " + players.length); 79 } 80 } 81 82 /** 83 * An execution request handler. Actions are passed in, validated and (if possible) executed. <br> 84 * Warning: this request is not thread safe, that job is delegated to the caller to handle. 85 * <p> 86 * Note: if this Controller was generated using the debug constructor, then references to the model, once modified, are 87 * going to be kept unsafe, generally decreasing the security of the editing mechanism. 88 * 89 * @param action the action to be validated and executed. 90 * @throws InputValidationException thrown when validation fails, carries information about the error. If thrown, 91 * the model is guaranteed to not have been modified. 92 */ 93 public void executeAction(PlayerAction action) throws InputValidationException { 94 Model model = this.modelWrapper.modelCopy(false); 95 OptionalValue<InputValidationException> validation = action.validate(this.getHistory(), model); 96 if (validation.isPresent()) throw validation.get(); 97 // as right now we are abusing the hell out of exception throwing 98 try { 99 this.modelWrapper.editModel(action::unsafeExecute, unsafeReferences); 100 } catch (Exception e) { 101 e.printStackTrace(); 102 } 103 104 history.add(action); 105 if (action.getClass() == EndTurnOfActionPhase.class || action.getClass() == PlayAssistantCard.class) { 106 this.history.clear(); 107 } 108 } 109 110 /** 111 * @return an immutable copy of the list of player actions.<br> 112 * <b>Note:</b> the single actions are immutable by default, so do not get cloned 113 */ 114 private List<PlayerAction> getHistory() { 115 return List.copyOf(history); 116 } 117 }