Coverage Summary for Class: Card07 (it.polimi.ingsw.Model)
| Class | Class, % | Method, % | Branch, % | Line, % |
|---|---|---|---|---|
| Card07 | 100% (1/1) | 100% (5/5) | 78,1% (25/32) | 94,4% (51/54) |
1 package it.polimi.ingsw.Model; 2 3 import it.polimi.ingsw.Exceptions.Container.EmptyContainerException; 4 import it.polimi.ingsw.Exceptions.Input.GenericInputValidationException; 5 import it.polimi.ingsw.Exceptions.Input.InputValidationException; 6 import it.polimi.ingsw.Exceptions.Input.InvalidElementException; 7 import it.polimi.ingsw.Logger; 8 import it.polimi.ingsw.Misc.OptionalValue; 9 import it.polimi.ingsw.Misc.Pair; 10 import it.polimi.ingsw.Model.Enums.PawnColour; 11 import it.polimi.ingsw.Model.Enums.StateType; 12 13 import java.io.Serial; 14 import java.util.*; 15 16 import static it.polimi.ingsw.Misc.Utils.canMapFit; 17 18 /** 19 * In Setup, draw 6 Students and place them on this card <br> 20 * EFFECT: you may take up to 3 students from this card and replace them with the same number of Students 21 * from your Entrance 22 */ 23 public class Card07 extends StatefulEffect { 24 @Serial 25 private static final long serialVersionUID = 109L; // convention: 1 for model, (01 -> 99) for objects 26 27 private final PawnColour[] students = new PawnColour[6]; 28 29 public Card07(Model ctx) { 30 super(7, 1, StateType.PAWNCOLOUR, ctx); 31 for (int i = 0; i < 6; i++) { 32 try { 33 this.students[i] = ctx.getMutableStudentBag().extract(); 34 } catch (EmptyContainerException e) { 35 // should never happen 36 Logger.severe("student bag was found empty while adding a student to Card07. Critical, unrecoverable, error"); 37 throw new RuntimeException(e); 38 } 39 40 } 41 } 42 43 @Override 44 public ArrayList<Object> getState() { 45 return new ArrayList<>(Arrays.asList(students)); 46 } 47 48 @Override 49 public StateType getStateType() { 50 return stateType; 51 } 52 53 /** 54 * Refer to: {@link CharacterCard#overridableCheckInput(CharacterCardInput)} for further information 55 * 56 * @param input CharacterCardInput should contain: 57 * <ul> 58 * <li>A valid list of pair having following properties: </li> 59 * <ul> 60 * No more than three pairs<br> 61 * No null values inside pairs 62 * </ul> 63 * <li>Every pairs must follow this format:</li> 64 * <ul> 65 * first element from entrance and second from card 66 * </ul> 67 * <li>a valid PawnColour from card</li> 68 * </ul> 69 */ 70 public OptionalValue<InputValidationException> overridableCheckInput(CharacterCardInput input) { 71 //convention of input.targetPawnPairs ---> array of pairs, first element is from entrance, second is from card 72 OptionalValue<List<Pair<PawnColour, PawnColour>>> optionalPawnPair = input.getTargetPawnPairs(); 73 PlayerBoard playerBoard = input.getCaller(); 74 // make sure the pair is formatted properly 75 if ( 76 optionalPawnPair.isEmpty() || // target pawn pairs was set as parameter 77 //optionalPawnPair.get().size() == 0 || /target pawn pairs is not empty (technically allowed) 78 optionalPawnPair.get().size() > 3 || // target pawn pairs are not over the pair limit of 2 swaps 79 optionalPawnPair.get().stream().anyMatch(p -> p.first() == null || p.second() == null) // no null values in pair 80 ) { 81 // in case throw exception for invalid element in input 82 return OptionalValue.of(new InvalidElementException("Target Pawn Pairs")); 83 } 84 85 86 // explode pawnpairs into respective arrays of elements 87 List<Pair<PawnColour, PawnColour>> pawnPairs = optionalPawnPair.get(); 88 // first count how many students of each colour the user picked 89 Map<PawnColour, Integer> firstMap = new EnumMap<>(PawnColour.class); // counts user entrance selected colours 90 Map<PawnColour, Integer> secondMap = new EnumMap<>(PawnColour.class); // counts card state selected colours 91 for (Pair<PawnColour, PawnColour> pair : pawnPairs) { 92 firstMap.merge(pair.first(), 1, Integer::sum); 93 secondMap.merge(pair.second(), 1, Integer::sum); 94 } 95 96 // get user entrance counts per colour 97 PlayerBoard me = input.getCaller(); 98 Map<PawnColour, Integer> entranceMap = new EnumMap<>(PawnColour.class); // counts user entrance total colours 99 for (PawnColour pawn : me.getEntranceStudents().stream() 100 .filter(OptionalValue::isPresent) 101 .map(OptionalValue::get) 102 .toList()) { 103 entranceMap.merge(pawn, 1, Integer::sum); 104 } 105 // make sure the elements coming from user (first) are also mapped to entrance 106 if (!canMapFit(entranceMap, firstMap)) { 107 return OptionalValue.of(new InvalidElementException("Target Pawn Pairs")); 108 } 109 110 // get card storage counts per colour 111 Map<PawnColour, Integer> cardMap = new EnumMap<>(PawnColour.class); // counts user entrance total colours 112 for (PawnColour pawn : this.students) { 113 cardMap.merge(pawn, 1, Integer::sum); 114 } 115 // make sure the elements coming from card (second) are also mapped to the card state 116 if (!canMapFit(cardMap, secondMap)) { 117 return OptionalValue.of(new InvalidElementException("Target Pawn Pairs")); 118 } 119 if (playerBoard.getEntranceSpaceLeft() + pawnPairs.size() >= playerBoard.getEntranceSize()) { 120 return OptionalValue.of(new GenericInputValidationException("Entrance", 121 "does not contain " + pawnPairs.size() 122 + " pawns")); 123 } 124 if (context.getMutableStudentBag().getSize() == 0) { 125 return OptionalValue.of(new GenericInputValidationException("Student Bag", "is empty")); 126 } 127 128 return OptionalValue.empty(); 129 } 130 131 /** 132 * Refer to: {@link CharacterCard#unsafeApplyEffect(CharacterCardInput)} for further information 133 */ 134 @Override 135 protected void unsafeApplyEffect(CharacterCardInput input) throws Exception { 136 PlayerBoard me = input.getCaller(); 137 138 //convention of input.targetPawnPairs ---> array of pairs, first element is from entrance, second is from card 139 for (Pair<PawnColour, PawnColour> pair : input.getTargetPawnPairs().get()) { 140 // match the first element in entrance with first and swap it with second 141 me.removeStudentFromEntrance(pair.first()); 142 me.addStudentToEntrance(pair.second()); 143 144 // match the first element in card with second and swap it with first 145 for (int i = 0; i < students.length; i++) { 146 if (students[i] == pair.second()) { 147 students[i] = pair.first(); 148 break; 149 } 150 } 151 } 152 } 153 154 //test-purpose only 155 }