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;
}
}