Coverage Summary for Class: IslandGroup (it.polimi.ingsw.Model)
| Class | Class, % | Method, % | Branch, % | Line, % |
|---|---|---|---|---|
| IslandGroup | 100% (1/1) | 100% (14/14) | 79,2% (19/24) | 92,2% (47/51) |
1 package it.polimi.ingsw.Model; 2 3 import it.polimi.ingsw.Exceptions.Operation.FailedOperationException; 4 import it.polimi.ingsw.Exceptions.Operation.ForbiddenOperationException; 5 import it.polimi.ingsw.Exceptions.Operation.OperationException; 6 import it.polimi.ingsw.Misc.OptionalValue; 7 import it.polimi.ingsw.Model.Enums.PawnColour; 8 import it.polimi.ingsw.Model.Enums.TowerColour; 9 10 import java.io.Serial; 11 import java.io.Serializable; 12 import java.util.*; 13 14 /** 15 * Every {@link Island} can be contained in an IslandGroup and multiple Islands can be grouped up. 16 */ 17 public class IslandGroup implements Serializable { 18 @Serial 19 private static final long serialVersionUID = 123L; // convention: 1 for model, (01 -> 99) for objects 20 21 private final int id; 22 private final ArrayList<Island> islands; 23 private final Stack<NoEntryTile> noEntryTiles; 24 25 /** 26 * Construct an IslandGroup starting from a single {@link Island} 27 * 28 * @param i a single {@link Island}, its {@link Island#getId()} becomes the group's ID 29 */ 30 public IslandGroup(Island i) { 31 this.islands = new ArrayList<>(); 32 this.id = i.getId(); 33 this.islands.add(i); 34 this.noEntryTiles = new Stack<>(); 35 } 36 37 /** 38 * Construct a new amalgamation of groups. The new group contains the sum of all the {@link PawnColour} on each group, the sum of the 39 * {@link NoEntryTile}s on each group. Groups can only be joined if their {@link Tower#getColour()} returns the same value.<br> 40 * The ID assigned to the new group will be the lowest between the input groups. 41 * 42 * @param islandGroups an array of groups to be merged into one 43 * @throws OperationException if the groups cannot be joined 44 */ 45 public IslandGroup(IslandGroup... islandGroups) throws OperationException { 46 if (islandGroups.length > 0 && islandGroups[0].canJoin(islandGroups)) { 47 this.islands = new ArrayList<>(); 48 this.noEntryTiles = new Stack<>(); 49 for (IslandGroup i : islandGroups) { 50 this.islands.addAll(i.getMutableIslands()); 51 this.noEntryTiles.addAll(i.getMutableNoEntryTiles()); 52 } 53 this.id = Arrays.stream(islandGroups) 54 .min(Comparator.comparingInt(IslandGroup::getId)) 55 .orElseThrow(() -> new FailedOperationException("Island Groups Constructor", "no minimum ID between groups found")) 56 .getId(); 57 } else { 58 throw new ForbiddenOperationException("Island Groups Constructor", "groups are not join-able"); 59 } 60 } 61 62 /** 63 * returns true if the inputted {@link IslandGroup} all contain the same type of tower 64 * 65 * @param groups the groups you'd like to join 66 */ 67 public boolean canJoin(IslandGroup... groups) { 68 if (groups.length <= 0) { 69 return false; 70 } else { 71 if (this.getTowerColour().isEmpty()) return false; 72 else return 73 Arrays.stream(groups).allMatch(g -> g.getTowerColour().equals(this.getTowerColour())); 74 } 75 } 76 77 /** 78 * @return an unmodifiable {@link List} containing all the {@link Island}s in the group. Each element on the list 79 * CAN be modified, the list itself can't. 80 */ 81 public List<Island> getMutableIslands() { 82 return List.copyOf(islands); 83 } 84 85 /** 86 * @return an unmodifiable {@link List} containing all the {@link NoEntryTile}s in the group. Each element on the list 87 * CAN be modified, the list itself can't. 88 */ 89 public List<NoEntryTile> getMutableNoEntryTiles() { 90 return List.copyOf(noEntryTiles); 91 } 92 93 /** 94 * @return the ID of the group 95 */ 96 public int getId() { 97 return id; 98 } 99 100 /** 101 * Get the colour of the towers stored on the islands. 102 * 103 * @return a non empty {@link OptionalValue} containing the {@link TowerColour}, if present. Note: if at least an island doesn't match the {@link TowerColour} of the others, this method will return an empty 104 * {@link OptionalValue}. 105 */ 106 public OptionalValue<TowerColour> getTowerColour() { 107 List<Island> islands = this.getMutableIslands(); 108 if (islands.stream().allMatch(i -> i.getTowerColour().equals(islands.get(0).getTowerColour()))) { 109 return islands.get(0).getTowerColour(); 110 } else return OptionalValue.empty(); 111 } 112 113 /** 114 * @return the amount of towers in the group (either 0 or equal to the number of islands in the group) 115 */ 116 public int getTowerCount() { 117 if (getTowerColour().isPresent()) return getMutableIslands().size(); 118 else return 0; 119 } 120 121 /** 122 * @return an unmodifiable {@link Map} a {@link PawnColour} to the amount of students of that colour in the group. 123 */ 124 public Map<PawnColour, Integer> getStudentCount() { 125 Map<PawnColour, Integer> studentCount = new EnumMap<>(PawnColour.class); 126 for (PawnColour p : this.getStudents()) { 127 studentCount.merge(p, 1, Integer::sum); 128 } 129 return Map.copyOf(studentCount); 130 } 131 132 /** 133 * @return an unmodifiable {@link List} containing all the {@link PawnColour}s in the group. 134 */ 135 public List<PawnColour> getStudents() { 136 List<PawnColour> islandGroupStudents = new ArrayList<>(); 137 for (Island s : this.getMutableIslands()) { 138 islandGroupStudents.addAll(s.getStudents()); 139 } 140 return List.copyOf(islandGroupStudents); 141 } 142 143 /** 144 * Checks to see if an island is contained in the group 145 * 146 * @param i the {@link Island} you wish to search for in the group 147 * @return true if the island is contained, false otherwise 148 */ 149 public boolean contains(Island i) { 150 for (Island island : islands) { 151 if (island.equals(i)) { 152 return true; 153 } 154 } 155 return false; 156 } 157 158 /** 159 * adds a {@link NoEntryTile} to the group 160 * 161 * @param tile the no entry tile to add 162 */ 163 public void addNoEntry(NoEntryTile tile) { 164 this.noEntryTiles.add(tile); 165 } 166 167 /** 168 * removes a {@link NoEntryTile} from the stack of tiles and puts it back on the character card where it came from 169 */ 170 public void resetNoEntry() { 171 this.noEntryTiles.remove(0).goHome(); 172 } 173 174 /** 175 * multiple {@link Tower}s may need to be swapped or added during the Group's lifespan, this method can be used for that 176 * 177 * @param ts the new {@link TowerStorage} where towers are coming from. the old towers (if any were present) will all be returned to its 178 * rightful storage automatically. If the new tower storage runs out of towers before swapping out all the towers from the group, 179 * then some islands fill be left empty while others will be full. Note that the empty islands will keep staying in 180 * the group, which is going to become un-join able. 181 */ 182 public void swapTower(TowerStorage ts) { 183 for (Island i : this.islands) { 184 i.swapTower(ts.extractTower()); 185 } 186 } 187 }