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

Class Method, % Branch, % Line, %
DecksCreator 87.5% (7/8) 100% (57/57) 87.5% (70/80)
DecksCreator$1 100% (1/1) 100% (1/1)
DecksCreator$2 100% (1/1) 100% (1/1)
DecksCreator$BuildingCardDefinition
DecksCreator$TribeCardDefinition
Total 90% (9/10) 100% (57/57) 87.8% (72/82)


 package it.polimi.ingsw.gc14.Model;
 
 import com.google.gson.*;
 import it.polimi.ingsw.gc14.Model.Cards.Building.Effects.*;
 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.Model.Cards.TribeCard;
 import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Events.CavePaintings;
 import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Events.Hunt;
 import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Events.ShamanicRitual;
 import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Events.Sustenance;
 
 import java.io.*;
 import java.lang.reflect.Type;
 import java.util.*;
 
 /**
  * Utility class responsible for loading and creating decks of cards and slots for the game.
  * Cards are loaded from JSON resource files and instantiated according to their type and parameters.
  */
 public class DecksCreator {
 
 
     /**
      * Loads the tribe card deck for the specified era from the corresponding JSON resource file.
      *
      * @param era the era number (1, 2, or 3).
      * @return a list of {@link TribeCard} objects for the specified era.
      * @throws IllegalArgumentException if {@code era} is not 1, 2, or 3.
      */
     public static List<TribeCard> loadTribeDeckByEra(int era) throws IllegalArgumentException
     {
         return switch (era) {
             case 1 -> loadTribeDeck("/Cards/tribe_era1.json");
             case 2 -> loadTribeDeck("/Cards/tribe_era2.json");
             case 3 -> loadTribeDeck("/Cards/tribe_era3.json");
             default -> throw new IllegalArgumentException();
         };
     }
 
     /**
      * Loads a tribe card deck from the specified JSON resource file path.
      *
      * @param resourcePath the path to the JSON resource file.
      * @return a list of {@link TribeCard} objects defined in the resource file.
      * @throws RuntimeException if the resource file is not found or an error occurs while reading it.
      */
     public static List<TribeCard> loadTribeDeck(String resourcePath) {
         Gson gson = new Gson();
         Type listType = new com.google.gson.reflect.TypeToken<List<TribeCardDefinition>>(){}.getType();
 
         InputStream is = DecksCreator.class.getResourceAsStream(resourcePath);
         if (is == null) {
             throw new RuntimeException("Resource file not found: " + resourcePath);
         }
 
         try (Reader reader = new InputStreamReader(is)) {
             List<TribeCardDefinition> definitions = gson.fromJson(reader, listType);
             List<TribeCard> cards = new ArrayList<>();
             for (TribeCardDefinition def : definitions) {
                 cards.add(createCard(def));
             }
             return cards;
         } catch (IOException e) {
             throw new RuntimeException("Error loading deck: " + resourcePath, e);
         }
     }
 
     /**
      * Loads the building card deck for the specified era, filtering cards from the global building deck.
      *
      * @param era the era number (1, 2, or 3).
      * @return a list of {@link BuildingCard} objects belonging to the specified era.
      * @throws IllegalArgumentException if {@code era} is not 1, 2, or 3.
      */
     public static List<BuildingCard> loadBuildingDeckByEra(int era) throws IllegalArgumentException
     {
         if(era<=0 || era>3) throw new IllegalArgumentException();
         return loadBuildingDeck("/Cards/buildingCards.json").stream().filter(x->x.getEra()==era).toList();
     }
 
     /**
      * Loads the full building card deck from the specified JSON resource file path.
      *
      * @param resourcePath the path to the JSON resource file.
      * @return a list of {@link BuildingCard} objects defined in the resource file.
      * @throws RuntimeException if the resource file is not found or an error occurs while reading it.
      */
     public static List<BuildingCard> loadBuildingDeck(String resourcePath) {
         Gson gson = new Gson();
         Type listType = new com.google.gson.reflect.TypeToken<List<BuildingCardDefinition>>(){}.getType();
 
         InputStream is = DecksCreator.class.getResourceAsStream(resourcePath);
         if (is == null) {
             throw new RuntimeException("Resource file not found: " + resourcePath);
         }
 
         try (Reader reader = new InputStreamReader(is)) {
             List<BuildingCardDefinition> definitions = gson.fromJson(reader, listType);
             List<BuildingCard> cards = new ArrayList<>();
             for (BuildingCardDefinition def : definitions) {
                 cards.add(createCard(def));
             }
             return cards;
         } catch (IOException e) {
             throw new RuntimeException("Error loading deck: " + resourcePath, e);
         }
     }
 
     /**
      * Creates and returns the list of slots used as the game board.
      * Slots are labeled with the letters A through G.
      *
      * @return a list of {@link Slot} objects representing the game board.
      */
     public static List<Slot> loadSlotDeck()
     {
         List<Slot> slots = new ArrayList<>();
         char[]chars={'A','B','C','D','E','F','G'};
         for(char c : chars)
             slots.add(new Slot(c));
         return slots;
     }
 
     /**
      * Instantiates a {@link TribeCard} from the given definition.
      * Depending on whether the card is an event or a character, the appropriate subclass is created
      * using the type and parameters specified in the definition.
      *
      * @param def the {@link TribeCardDefinition} containing the card's type, era, and parameters.
      * @return the instantiated {@link TribeCard}.
      * @throws IllegalArgumentException if the card type is unknown or the parameters are invalid.
      */
     private static TribeCard createCard(TribeCardDefinition def) {
         int era = def.era;
         int[] p = def.params.stream().mapToInt(d -> ((Double) d).intValue()).toArray();
         if(def.isEvent)
         {
             return switch (def.type) {
                 case "Sustenance" -> new Sustenance(def.id,era,p[0]);
                 case "Hunt" -> new Hunt(def.id,era,p[0]);
                 case "CavePaintings" -> new CavePaintings(def.id,era,p[0],p[1],p[2]);
                 case "ShamanicRitual" -> new ShamanicRitual(def.id,era,p[0],p[1]);
                 default -> throw new IllegalArgumentException("Unknown event type: " + def.type);
             };
         }
         return switch (def.type) {
             case "Hunter" -> p.length == 0
                     ? new Hunter(def.id,era, def.armed)
                     : new Hunter(def.id,era, def.armed, p[0]);
             case "Builder" -> switch (p.length) {
                 case 2 -> new Builder(def.id,era, p[0], p[1]);
                 case 3 -> new Builder(def.id,era, p[0], p[1], p[2]);
                 default -> throw new IllegalArgumentException("Builder: invalid parameters");
             };
             case "Gatherer" -> switch (p.length) {
                 case 0 -> new Gatherer(def.id,era);
                 case 1 -> new Gatherer(def.id,era, p[0]);
                 default -> throw new IllegalArgumentException("Gatherer: invalid parameters");
             };
             case "Artist" -> switch (p.length) {
                 case 0 -> new Artist(def.id,era);
                 case 1 -> new Artist(def.id,era, p[0]);
                 default -> throw new IllegalArgumentException("Artist: invalid parameters");
             };
             case "Inventor" -> switch (p.length) {
                 case 1 -> new Inventor(def.id,era, p[0]);
                 case 2 -> new Inventor(def.id,era, p[0], p[1]);
                 default -> throw new IllegalArgumentException("Inventor: invalid parameters");
             };
             case "Shaman" -> switch (p.length) {
                 case 1 -> new Shaman(def.id,era, p[0]);
                 case 2 -> new Shaman(def.id,era, p[0], p[1]);
                 default -> throw new IllegalArgumentException("Shaman: invalid parameters");
             };
             default -> throw new IllegalArgumentException("Unknown card type: " + def.type);
         };
     }
 
     /**
      * Instantiates a {@link BuildingCard} from the given definition.
      * The appropriate subclass is selected based on the effect ID specified in the definition.
      * If no specific subclass matches the effect ID, a base {@link BuildingCard} is created.
      *
      * @param def the {@link BuildingCardDefinition} containing the card's effect ID, era, price, prestige value, and parameters.
      * @return the instantiated {@link BuildingCard}.
      */
     private static BuildingCard createCard(BuildingCardDefinition def) {
         return switch (def.effectId) {
             case 0 -> new Building0(def.id,def.era, def.price, def.prestigeValue);
             case 1 -> new Building1(def.id,def.era, def.price, def.prestigeValue, CharacterType.valueOf(((String) def.params.get(0)).toUpperCase()));
             case 4 -> new Building4(def.id,def.era, def.price, def.prestigeValue);
             case 8 -> new Building8(def.id,def.era, def.price, def.prestigeValue);
             case 10 -> new Building10(def.id,def.era, def.price, def.prestigeValue);
             case 11 -> new Building11(def.id,def.era, def.price, def.prestigeValue, CharacterType.valueOf(((String) def.params.get(0)).toUpperCase()), ((Double) def.params.get(1)).intValue());
             case 13 -> new Building13(def.id,def.era, def.price, def.prestigeValue);
             default -> new BuildingCard(def.id,def.effectId, def.era, def.price, def.prestigeValue);
         };
 
     }
 
     /**
      * Internal data class representing the raw definition of a tribe card as loaded from a JSON file.
      * Contains the card identifier, type, era, whether it is armed, whether it is an event card,
      * and a list of additional parameters.
      */
     private static class TribeCardDefinition {
         String id;
         String type;
         int era;
         boolean armed;
         boolean isEvent;
         List<Object> params;
     }
 
     /**
      * Internal data class representing the raw definition of a building card as loaded from a JSON file.
      * Contains the card identifier, effect ID, era, price, prestige value, and a list of additional parameters.
      */
     private static class BuildingCardDefinition {
         String id;
         int effectId;
         int era;
         int price;
         int prestigeValue;
         List<Object> params;
     }
 }