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 }