Coverage Summary for Class: Player (it.polimi.ingsw.gc14.Model)

Class Method, % Branch, % Line, %
Player 100% (22/22) 84.5% (49/58) 98.1% (102/104)
Player$1 100% (1/1) 100% (1/1)
Total 100% (23/23) 84.5% (49/58) 98.1% (103/105)


 package it.polimi.ingsw.gc14.Model;
 
 import it.polimi.ingsw.gc14.Model.Cards.BuildingCard;
 import it.polimi.ingsw.gc14.Model.Cards.TribeCards.CharacterType;
 import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Characters.*;
 import it.polimi.ingsw.gc14.View.TUI.AsciiTable;
 
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Map;
 import java.util.stream.Collectors;
 
 import static it.polimi.ingsw.gc14.View.TUI.BorderStyle.*;
 
 /**
  * Default Player class; contains all identifiers and methods needed.
  */
 public class Player implements Serializable {
     /**
      * The maximum length allowed for the username string.
      */
     private static final int MAX_USERNAME_LENGTH = 10;
 
     /**
      * Identifier for the {@code Player} when displaying the game through the GUI.
      * @see Totems
      */
     private Totems totem;
 
     /**
      * Unique string identifier for players; must not be {@code null} and must not
      * exceed {@link #MAX_USERNAME_LENGTH} otherwise an {@link IllegalArgumentException} will be thrown
      * when the {@link #Player(String) constructor} is called.
      */
     private final String userName;
 
     /**
      * Getter for the private attribute {@link #userName}.
      * @return {@code String} - The UserName
      */
     public String getUserName() {
         return userName;
     }
 
     /**
      * Returns the totem assigned to this player.
      *
      * @return this player's totem.
      */
     public Totems getTotem() {
         return totem;
     }
 
     /**
      * Counts the total {@link it.polimi.ingsw.gc14.Model.Cards.TribeCards.Character Character Cards}
      * the player currently possesses.
      * @return {@code int} - Total Character Cards.
      */
     public int getTotCharacters() {
         return Arrays.stream(CharacterType.values())
                 .mapToInt(this::getNType)
                 .sum();
     }
 
     /**
      * Counts the total number of cards of the specified {@link it.polimi.ingsw.gc14.Model.Cards.TribeCards.CharacterType Character Type}.
      * Character Type must not be {@code null}
      * @param type the Character Type to be Counted.
      * @return {@code int} - Total number of cards of given {@code type}.
      */
     public int getNType(CharacterType type) {
         return switch (type) {
             case ARTIST -> artists.size();
             case INVENTOR -> inventors.size();
             case HUNTER -> hunters.size();
             case BUILDER -> builders.size();
             case SHAMAN -> shamans.size();
             case GATHERER -> gatherers.size();
         };
     }
 
     /**
      * The current {@link BuildingCard Building Cards} in the player's deck.
      */
     private final ArrayList<BuildingCard> buildingCards;
 
     /**
      * The current {@link Artist Artist} cards in the player's deck.
      */
     private final ArrayList<Artist> artists;
 
     /**
      * The current {@link Builder Builder} cards in the player's deck.
      */
     private final ArrayList<Builder> builders;
 
     /**
      * The current {@link Inventor Inventor} cards in the player's deck.
      */
     private final ArrayList<Inventor> inventors;
 
     /**
      * The current {@link Gatherer Gatherer} cards in the player's deck.
      */
     private final ArrayList<Gatherer> gatherers;
 
     /**
      * The current {@link Shaman Shaman} cards in the player's deck.
      */
     private final ArrayList<Shaman> shamans;
 
     /**
      * The current {@link Hunter Hunter} cards in the player's deck.
      */
     private final ArrayList<Hunter> hunters;
 
     /** @return this player's building cards. */
     public ArrayList<BuildingCard> getBuildingCards() { return buildingCards; }
     /** @return this player's Artist character cards. */
     public ArrayList<Artist> getArtists() { return artists; }
     /** @return this player's Builder character cards. */
     public ArrayList<Builder> getBuilders() { return builders; }
     /** @return this player's Inventor character cards. */
     public ArrayList<Inventor> getInventors() { return inventors; }
     /** @return this player's Gatherer character cards. */
     public ArrayList<Gatherer> getGatherers() { return gatherers; }
     /** @return this player's Shaman character cards. */
     public ArrayList<Shaman> getShamans() { return shamans; }
     /** @return this player's Hunter character cards. */
     public ArrayList<Hunter> getHunters() { return hunters; }
 
     /**
      * The current amount of {@code Food} the Player possesses.
      * Cannot be negative.
      */
     private int foodValue;
 
     /**
      * Getter for the private attribute {@link #foodValue}.
      * @return {@code int} - The amount of Food the player possesses.
      */
     public int getFoodValue() {
         return foodValue;
     }
 
     /**
      * The current amount of {@code Prestige} the Player possesses.
      */
     private int prestigeValue;
 
     /**
      * Getter for the private attribute {@link #prestigeValue}.
      * @return {@code int} - The amount of Prestige the Player possesses.
      */
     public int getPrestigeValue() {
         return prestigeValue;
     }
 
     /**
      * Adds {@code value} amount of Food to the Player.
      * @param value The amount of Food to be added. Should be non-negative.
      * @see #foodValue
      */
     public void addFood(int value){
         this.foodValue += value;
     }
 
     /**
      * Sets the totem for this player.
      *
      * @param totem the totem to assign.
      */
     public void setTotem(Totems totem) {
         this.totem = totem;
     }
 
     /**
      * Removes {@code value} amount of Food from the Player.
      * {@link #foodValue} cannot go negative: returns {@code false} if
      * {@code value} exceeds the current food and leaves the value unchanged.
      *
      * @param value The amount of Food to be removed. Should be non-negative.
      * @return {@code true} if the Food is successfully removed, {@code false} otherwise.
      * @see #foodValue
      */
     public boolean removeFood(int value){
         if(value > this.foodValue){
             return false;
         }
         this.foodValue -= value;
         return true;
     }
 
     /**
      * Adds {@code value} amount of Prestige to the Player.
      * @param value The amount of Prestige to be added. Should be non-negative.
      * @see #prestigeValue
      */
     public void addPrestige(int value){
         this.prestigeValue += value;
     }
 
     /**
      * Removes {@code value} amount of Prestige from the Player.
      * @param value The amount of Prestige to be removed. Should be non-negative.
      * @see #prestigeValue
      */
     public void removePrestige(int value){
         this.prestigeValue -= value;
     }
 
 
 
     /**
      * Constructor for the class {@code Player}. Each Player is uniquely identified by the {@link #userName}.
      *
      * @param userName Unique String identifier for a Player.
      * @throws IllegalArgumentException when {@code userName} is empty or exceeds {@link #MAX_USERNAME_LENGTH},
      *                                  with message:
      *                                  <pre>{@code UserName is empty or exceeds maximum permitted length.}</pre>
      *
      * @see #userName
      * @see #MAX_USERNAME_LENGTH
      */
     public Player(String userName) throws  IllegalArgumentException {
         if(userName.isEmpty() || userName.length() > MAX_USERNAME_LENGTH) {
             throw new IllegalArgumentException("UserName is empty or exceeds maximum permitted length.");
         }
         this.userName = userName;
 
         this.inventors = new ArrayList <>();
         this.builders = new ArrayList <>();
         this.gatherers = new ArrayList <>();
         this.shamans = new ArrayList <>();
         this.hunters = new ArrayList <>();
         this.artists = new ArrayList<>();
 
         this.buildingCards = new ArrayList<>();
         this.foodValue = 0;
         this.prestigeValue = 0;
         this.totem = null;
     }
 
     /**
      * Checks equality between this {@code Player} and another object.
      * Two players are equal if and only if they share the same {@code userName}.
      *
      * @param obj the object to compare with.
      * @return {@code true} if {@code obj} is a {@code Player} with the same username; {@code false} otherwise.
      */
     @Override
     public boolean equals(Object obj) {
         if (this == obj) return true;
         if (!(obj instanceof Player)) return false;
         return userName.equals(((Player) obj).userName);
     }
 
     @Override
     public int hashCode() {
         return userName.hashCode();
     }
 
     /**
      * Prints the {@code Player}'s attributes for the {@code Board}'s representation.
      * Uses the {@code UNICODE} border style.
      * <p><b>Includes:</b>
      * <li>{@link #foodValue Food}
      * <li>{@link #prestigeValue Prestige}
      * <li>{@link #artists Artists}
      * <li>{@link #builders Builders}
      * <li>{@link #gatherers Gatherers}
      * <li>{@link #shamans Shamans}
      * <li>{@link #inventors Inventors}
      * <li>{@link #hunters Hunters}
      * <li>{@link #buildingCards Buildings}
      * </p>
      * @return {@code String} - A string representation of the {@code Player}'s attributes.
      * @see it.polimi.ingsw.gc14.View.TUI.BorderStyle BorderStyle
      */
     @Override
     public String toString() {
         int last;
 
         var table = new AsciiTable(ROUNDED, 1);
 
         String totemStr = (this.totem != null) ? " (" + this.totem + ")" : "";
         table.addHeader(this.getUserName() + totemStr + "  |  \uD83C\uDF56:" + this.getFoodValue() + "  |  \uD83C\uDFC5:" + this.getPrestigeValue());
         table.addSeparator();
 
         if(!this.hunters.isEmpty()){
             last = 6;
         }
         else if(!this.inventors.isEmpty()){
             last = 5;
         }
         else if(!this.shamans.isEmpty()){
             last = 4;
         }
         else if(!this.gatherers.isEmpty()){
             last = 3;
         }
         else if(!this.builders.isEmpty()){
             last = 2;
         }
         else if(!this.artists.isEmpty()){
             last = 1;
         }
         else{
             last = 0;
         }
 
         if(last == 0){
             table.addSeparator();
         }
         table.addRow("CHARACTERS");
         if(!this.artists.isEmpty()){
             table.addRow(this.artists.size() + " Artists: \uD83C\uDFA8:" + this.artists.size());
             if(last == 1){
                 table.addSeparator();
             }
         }
 
         if(!this.builders.isEmpty()){
             table.addRow(this.builders.size() + " Builders: " + "\uD83D\uDD28:" + this.builders.stream().mapToInt(Builder::getReductionValue).sum() + " \uD83C\uDFC5:" + this.builders.stream().mapToInt(Builder::getPrestigeValue).sum());
             if(last == 2){
                 table.addSeparator();
             }
         }
 
         if(!this.gatherers.isEmpty()){
             table.addRow(this.gatherers.size() + " Gatherers: \uD83C\uDF56:" + 3*this.gatherers.size());
             if(last == 3){
                 table.addSeparator();
             }
         }
 
         if(!this.shamans.isEmpty()){
             table.addRow(this.shamans.size() + " Shamans: " + "\uD83C\uDF1F:" + this.shamans.stream().mapToInt(Shaman::getIcon).sum());
             if(last == 4){
                 table.addSeparator();
             }
         }
 
         if(!this.inventors.isEmpty()){
             table.addRow(this.inventors.size() + " Inventors: " + this.inventors.stream()
                     .collect(Collectors.groupingBy(
                             Inventor::getIcon,
                             Collectors.counting()
                     ))
                     .entrySet().stream()
                     .sorted(Map.Entry.comparingByKey())
                     .map(e -> e.getKey() + ":" + e.getValue())
                     .collect(Collectors.joining(", ")));
             if(last == 5){
                 table.addSeparator();
             }
         }
 
 
         if(!this.hunters.isEmpty()){
             table.addRow(this.hunters.size() + " Hunters: \uD83C\uDF56" + this.hunters.stream().filter(Hunter::getIcon).count());
             table.addSeparator();
         }
         table.addSeparator();
         table.addRow("BUILDING CARDS" +
                 (this.buildingCards.stream().mapToInt(BuildingCard::getPrestigeValue).sum() != 0
                         ? " \uD83C\uDFC5:" + this.buildingCards.stream().mapToInt(BuildingCard::getPrestigeValue).sum()
                         : ""));
         if(!this.buildingCards.isEmpty()){
             table.addRow(this.buildingCards.size() + " Buildings: " + this.buildingCards.stream().map(BuildingCard::toStringPlayer).collect(Collectors.joining(", ")));
         }
 
         return table.build();
     }
 }