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 }