Coverage Summary for Class: MoveStudent (it.polimi.ingsw.Controller.Actions)
| Class | Method, % | Branch, % | Line, % |
|---|---|---|---|
| MoveStudent | 100% (3/3) | 78,1% (25/32) | 93,9% (31/33) |
| MoveStudent$1 | 100% (1/1) | 100% (1/1) | |
| Total | 100% (4/4) | 78,1% (25/32) | 94,1% (32/34) |
1 package it.polimi.ingsw.Controller.Actions; 2 3 import it.polimi.ingsw.Controller.DestinationType; 4 import it.polimi.ingsw.Controller.MoveDestination; 5 import it.polimi.ingsw.Exceptions.Input.GenericInputValidationException; 6 import it.polimi.ingsw.Exceptions.Input.InputValidationException; 7 import it.polimi.ingsw.Exceptions.Input.InvalidElementException; 8 import it.polimi.ingsw.Misc.OptionalValue; 9 import it.polimi.ingsw.Model.Enums.GamePhase; 10 import it.polimi.ingsw.Model.Enums.PawnColour; 11 import it.polimi.ingsw.Model.Model; 12 import it.polimi.ingsw.Model.PlayerBoard; 13 14 import java.io.Serial; 15 import java.util.List; 16 17 import static it.polimi.ingsw.Misc.Utils.countSimilarClassOccurrences; 18 19 /** 20 * This {@link PlayerAction} allows the caller to move a single student from the entrance to the school to an island or a dining room table. This action 21 * is linked to the Action Phase. 22 */ 23 public class MoveStudent extends PlayerAction { 24 @Serial 25 private static final long serialVersionUID = 205L; // convention: 2 for controller, (01 -> 99) for objects 26 27 private final int selectedEntrancePosition; 28 private final MoveDestination destination; 29 30 /** 31 * Create a new instance of this class with the following inputs: 32 * 33 * @param playerBoardId the ID of the current {@link PlayerBoard} 34 * @param destination a {@link MoveDestination} value specifying where the selected student will be moved 35 * @param selectedEntrancePosition id of the slot in the list returned by {@link PlayerBoard#getEntranceStudents()}, selects a student to be moved 36 */ 37 public MoveStudent(int playerBoardId, int selectedEntrancePosition, MoveDestination destination) { 38 super(playerBoardId, false); 39 this.selectedEntrancePosition = selectedEntrancePosition; 40 this.destination = destination; 41 } 42 43 /** 44 * {@inheritDoc} 45 * <ul> 46 * <li>The {@link GamePhase} must be {@link GamePhase#ACTION}</li> 47 * <li>The previous {@link PlayerAction}s must be either {@link MoveStudent} or {@link PlayCharacterCard} or the history must be empty</li> 48 * <li>Only a limited number of actions like this one can be played (3 or 4 depending on the players)</li> 49 * <li>The student decleared to move must be part of the entrance on the {@link PlayerBoard}</li> 50 * <li>If the destination is {@link DestinationType#ISLAND} then the island ID must be within bounds (0 to 12 excluded)</li> 51 * <li>If the destination is {@link DestinationType#DININGROOM} then the dining room must be able to contain the pawn</li> 52 * </ul> 53 * 54 * @param history the controller stores a {@link List} of previous {@link PlayerAction}s related to the player taking 55 * the current turn (at every new turn, the history is cleared). 56 * Some actions may use this {@link List} to check for duplicates. 57 * @param ctx a reference to {@link Model}. Some actions may use this reference to check for consistency between what 58 * the actions declares and what the Model offers. 59 * @return An empty {@link OptionalValue} in case of a successful validation. Otherwise the returned {@link OptionalValue} 60 * contains the related {@link InputValidationException} 61 */ 62 @Override 63 protected OptionalValue<InputValidationException> customValidation(List<PlayerAction> history, Model ctx) { 64 int maxCount = ctx.getMutablePlayerBoards().size() == 3 ? 4 : 3; 65 int entranceSize = ctx.getMutablePlayerBoards().size() == 3 ? 9 : 7; 66 PlayerBoard caller = ctx.getMutableTurnOrder().getMutableCurrentPlayer(); 67 if (ctx.getMutableTurnOrder().getGamePhase() != GamePhase.ACTION) { 68 return OptionalValue.of(new GenericInputValidationException("GamePhase", "the game is not in the correct phase")); 69 } 70 if (history.size() > 0) { 71 if (!(history.get(history.size() - 1).getClass() == MoveStudent.class || history.get(history.size() - 1).getClass() == PlayCharacterCard.class)) { 72 return OptionalValue.of(new GenericInputValidationException("History", "MoveStudent can only be preceded by a PlayCharacterCard action or MoveStudent action")); 73 } 74 } 75 if (countSimilarClassOccurrences(MoveStudent.class, history) >= maxCount) { 76 return OptionalValue.of(new GenericInputValidationException("History", "only " + maxCount + " pawns can be moved from entrance")); 77 } 78 79 if (!(this.selectedEntrancePosition >= 0 && this.selectedEntrancePosition < entranceSize)) { 80 return OptionalValue.of(new InvalidElementException("Index Target Entrance Position")); 81 } 82 if (caller.getEntranceStudents().get(this.selectedEntrancePosition).isEmpty()) { 83 return OptionalValue.of(new InvalidElementException("Target Entrance Position")); 84 } 85 86 if (this.destination.getDestinationType() == DestinationType.ISLAND) { 87 int islandId = this.destination.getIslandID(); 88 if (islandId < 0 || islandId > 12) { 89 return OptionalValue.of(new InvalidElementException("Target Island")); // target ti out of bounds for id 90 } 91 } else if (this.destination.getDestinationType() == DestinationType.DININGROOM) { 92 if (caller.isDiningRoomFull(caller.getEntranceStudents().get(this.selectedEntrancePosition).get())) { 93 return OptionalValue.of(new GenericInputValidationException("DiningRoom", 94 "can't contain the pawn without overflowing.")); 95 } 96 } 97 return OptionalValue.empty(); 98 } 99 100 101 @Override 102 public void unsafeExecute(Model ctx) throws Exception { 103 PlayerBoard pb = ctx.getMutablePlayerBoard(this.getPlayerBoardID()); 104 // set entrance position to null 105 PawnColour toMove = pb.removeStudentFromEntrance(selectedEntrancePosition); 106 switch (this.destination.getDestinationType()) { 107 case ISLAND -> { 108 int id = this.destination.getIslandID(); 109 ctx.getMutableIslandField().getMutableIslandById(id) 110 .addStudent(toMove); 111 } 112 case DININGROOM -> ctx.addStudentToDiningRoom(toMove, pb); 113 } 114 } 115 }