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 }