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 }