Coverage Summary for Class: IslandField (it.polimi.ingsw.Model)
| Class | Class, % | Method, % | Branch, % | Line, % |
|---|---|---|---|---|
| IslandField | 100% (1/1) | 100% (11/11) | 100% (14/14) | 86,8% (46/53) |
1 package it.polimi.ingsw.Model; 2 3 import it.polimi.ingsw.Exceptions.Container.EmptyContainerException; 4 import it.polimi.ingsw.Exceptions.Container.InvalidContainerIndexException; 5 import it.polimi.ingsw.Exceptions.Operation.OperationException; 6 import it.polimi.ingsw.Logger; 7 import it.polimi.ingsw.Misc.Utils; 8 9 import java.io.Serial; 10 import java.io.Serializable; 11 import java.util.ArrayList; 12 import java.util.List; 13 14 /** 15 * All {@link IslandGroup}s in the game need to be contained in a circular structure. This class does just that - along 16 * joining the groups and tracking Mother Nature's position 17 */ 18 public class IslandField implements Serializable { 19 @Serial 20 private static final long serialVersionUID = 122L; // convention: 1 for model, (01 -> 99) for objects 21 22 private static final int FIELD_SIZE = 12; 23 private final ArrayList<IslandGroup> groups; 24 private final ArrayList<Island> islands; 25 private IslandGroup motherNaturePosition; 26 27 /** 28 * Creates the Field, populating it with 12 {@link Island}s and 12 {@link IslandGroup}s. 29 * The generated elements are populated with following the rules of the game. 30 */ 31 public IslandField() { 32 this.groups = new ArrayList<>(FIELD_SIZE); 33 this.islands = new ArrayList<>(FIELD_SIZE); 34 for (int i = 0; i < FIELD_SIZE; i++) { 35 Island island = new Island(i); 36 IslandGroup islandGroup = new IslandGroup(island); 37 this.islands.add(island); 38 this.groups.add(islandGroup); 39 } 40 41 this.motherNaturePosition = Utils.random(this.groups); 42 int motherNatureIslandId = this.motherNaturePosition.getId(); 43 44 StudentBag tempBag = new StudentBag(2); 45 46 for (Island island : this.islands) { 47 if (island.getId() != motherNatureIslandId && island.getId() != (motherNatureIslandId + 6) % FIELD_SIZE) { 48 try { 49 island.addStudent(tempBag.extract()); 50 } catch (EmptyContainerException e) { 51 // should never happen 52 Logger.severe("student bag was found empty while adding a student to an island. Critical, unrecoverable, error"); 53 throw new RuntimeException(e); 54 } 55 } 56 } 57 } 58 59 /** 60 * @return an unmodifiable {@link List} containing all the {@link IslandGroup}s on the field. Each element on the list 61 * CAN be modified, the list itself can't. 62 */ 63 public List<IslandGroup> getMutableGroups() { 64 return List.copyOf(this.groups); 65 } 66 67 /** 68 * @return an unmodifiable {@link List} containing all the {@link Island}s on the field. Each element on the list 69 * CAN be modified, the list itself can't. 70 */ 71 public List<Island> getMutableIslands() { 72 return List.copyOf(this.islands); 73 } 74 75 /** 76 * @param id the ID of the group to search for 77 * @return the {@link IslandGroup} matching the ID on the input 78 * @throws InvalidContainerIndexException if the specified ID is not in the list of currently active groups, this exception 79 * is thrown 80 */ 81 public IslandGroup getMutableIslandGroupById(int id) throws InvalidContainerIndexException { 82 return groups.stream() 83 .filter(g -> g.getId() == id) 84 .findAny() 85 .orElseThrow(() -> new InvalidContainerIndexException("Island Groups")); 86 } 87 88 /** 89 * @param id the ID of the island to search for 90 * @return the {@link Island} matching the ID on the input 91 * @throws InvalidContainerIndexException if the specified ID is not in the list of currently active islands, this exception 92 * is thrown 93 */ 94 public Island getMutableIslandById(int id) throws InvalidContainerIndexException { 95 return islands.stream() 96 .filter(i -> i.getId() == id) 97 .findAny() 98 .orElseThrow(() -> new InvalidContainerIndexException("Islands")); 99 } 100 101 /** 102 * this method is Package-private - moving mother nature through this method does not enact its power. it is therefore unsafe 103 * to call this outside of very specific circumstances. 104 * 105 * @param moves the amount of moves mother nature will move. 106 */ 107 protected void moveMotherNature(int moves) { 108 motherNaturePosition = groups.get((groups.indexOf(motherNaturePosition) + moves) % groups.size()); 109 } 110 111 /** 112 * When called, this method will join the groups adjacent to mother nature following the game's rules. 113 */ 114 public void joinGroups() { 115 IslandGroup motherGroup = this.getMutableMotherNaturePosition(); 116 IslandGroup nextGroup = this.nextGroup(motherGroup); 117 IslandGroup prevGroup = this.prevGroup(motherGroup); 118 // look to the group before mother nature position and join if necessary 119 ifJoinableThenJoin(motherGroup, prevGroup); 120 motherGroup = this.getMutableMotherNaturePosition(); 121 ifJoinableThenJoin(motherGroup, nextGroup); 122 } 123 124 /** 125 * @return the {@link IslandGroup} matching the position of mother nature 126 */ 127 public IslandGroup getMutableMotherNaturePosition() { 128 return motherNaturePosition; 129 } 130 131 /** 132 * searches for the {@link IslandGroup} adjacent to a selected one 133 * 134 * @param curr the {@link IslandGroup} you wish to find the next adjacent one 135 * @return the {@link IslandGroup} that comes after the one in input 136 */ 137 private IslandGroup nextGroup(IslandGroup curr) { 138 int groupSize = this.groups.size(); 139 int currIndex = this.groups.indexOf(curr); 140 return groups.get( 141 (currIndex + groupSize + 1) % groupSize 142 ); 143 } 144 145 /** 146 * searches for the {@link IslandGroup} adjacent to a selected one 147 * 148 * @param curr the {@link IslandGroup} you wish to find the previous adjacent one 149 * @return the {@link IslandGroup} that comes before the one in input 150 */ 151 private IslandGroup prevGroup(IslandGroup curr) { 152 int groupSize = this.groups.size(); 153 int currIndex = this.groups.indexOf(curr); 154 return groups.get( 155 (currIndex + groupSize - 1) % groupSize 156 ); 157 } 158 159 /** 160 * Two groups are considered joinable if they share the same tower colour. 161 * 162 * @param motherGroup the group on which Mother nature is standing 163 * @param otherGroup a group adjacent to motherGroup 164 */ 165 private void ifJoinableThenJoin(IslandGroup motherGroup, IslandGroup otherGroup) { 166 try { 167 if (motherGroup.canJoin(otherGroup)) { 168 IslandGroup joined = new IslandGroup(motherGroup, otherGroup); 169 this.groups.remove(otherGroup); 170 this.groups.set(this.groups.indexOf(motherGroup), joined); 171 this.motherNaturePosition = joined; 172 } 173 } catch (OperationException e) { 174 Logger.severe("Unreachable statement has been reached. Severe, unrecoverable error"); 175 e.printStackTrace(); 176 throw new RuntimeException(); 177 } 178 } 179 180 }