package server.cards; import javafx.scene.image.Image; import server.Era; import server.utils.LoadingCardsException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; import java.util.stream.Collectors; public class CardDeck { private List tribeDeck; private Map> buildingDeck; private static final Logger logger = LogManager.getLogger(CardDeck.class); private Map imageCardsMap = new HashMap<>(); public Map getImageCardsMap() { return imageCardsMap; } public List getTribeDeck() { return tribeDeck; } public List getBuildingDeck(Era era) { return buildingDeck.get(era); } public Map> getBuildingDeckMap() { return buildingDeck; } public void setForNPlayerPathTest(String path, int n) throws LoadingCardsException { List tribe = new ArrayList<>(); List building = new ArrayList<>(); try { List rows = Files.readAllLines(Path.of(path)); int p=0; for (String row : rows) { String cleanRow = row.trim(); String[] fields = cleanRow.split(";"); logger.info((p++) + " ROW " +row); switch (fields[0]) { case "C": tribe.add(CharacterCard.parsRow(row)); break; case "E": tribe.add(EventCard.parsRow(row)); break; case "B": building.add(BuildingCard.parsRow(row)); break; default: throw new LoadingCardsException("Content not supported"); } } } catch (IOException e) { logger.error(e); throw new LoadingCardsException("file not found"); } building = CardDeck.shuffle(building); this.tribeDeck = new ArrayList<>(); for(Card card : tribe) { if (card.getForMinPlayer() <= n) this.tribeDeck.add(card); } this.tribeDeck = CardDeck.shuffle(this.tribeDeck); // groups the building cards by era this.buildingDeck = building.stream().collect(Collectors.groupingBy(Card::getEra)); } public void setForNPlayer(InputStream csvStream, int n, boolean shuffle) throws LoadingCardsException { List tribe = new ArrayList<>(); List building = new ArrayList<>(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(csvStream))) { String row; int p = 0; while ((row = reader.readLine()) != null) { String cleanRow = row.trim(); String[] fields = cleanRow.split(";"); logger.info((p++) + " ROW " + row); switch (fields[0]) { case "C": tribe.add(CharacterCard.parsRow(row)); break; case "E": tribe.add(EventCard.parsRow(row)); break; case "B": building.add(BuildingCard.parsRow(row)); break; default: throw new LoadingCardsException("Content not supported"); } } } catch (IOException e) { logger.error(e); throw new LoadingCardsException("file not found"); } // Avoid loading FX Image during Junit Tests if (!shuffle)loadCardImage(tribe); if (!shuffle)loadCardImage(building); if (shuffle) building = CardDeck.shuffle(building); this.tribeDeck = tribe.stream() .filter(card -> card.getForMinPlayer() <= n) .collect(Collectors.toCollection(ArrayList::new)); if (shuffle) this.tribeDeck = CardDeck.shuffle(this.tribeDeck); this.buildingDeck = building.stream().collect(Collectors.groupingBy(Card::getEra)); } private void loadCardImage(List cards){ for (Card c : cards) { String path = "/files/allcards/" + c.getCardId() + ".png"; URL resource = getClass().getResource(path); if (resource != null) { Image image = new Image(resource.toExternalForm()); imageCardsMap.put(c.getCardId(), image); } else { logger.error("Immagine non trovata per cardId: " + c.getCardId()); } } } public List loadForNPlayerTest(InputStream csvStream, int n, boolean shuffle) throws LoadingCardsException { List tribe = new ArrayList<>(); List building = new ArrayList<>(); List allCards = new ArrayList<>(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(csvStream))) { String row; int p = 0; while ((row = reader.readLine()) != null) { String cleanRow = row.trim(); String[] fields = cleanRow.split(";"); logger.info((p++) + " ROW " + row); switch (fields[0]) { case "C": tribe.add(CharacterCard.parsRow(row)); allCards.add(CharacterCard.parsRow(row)); break; case "E": tribe.add(EventCard.parsRow(row)); allCards.add(EventCard.parsRow(row)); break; case "B": building.add(BuildingCard.parsRow(row)); allCards.add(BuildingCard.parsRow(row)); break; default: throw new LoadingCardsException("Content not supported"); } } } catch (IOException e) { logger.error(e); throw new LoadingCardsException("file not found"); } if (shuffle) building = CardDeck.shuffle(building); this.tribeDeck = tribe.stream() .filter(card -> card.getForMinPlayer() <= n) .collect(Collectors.toCollection(ArrayList::new)); if (shuffle) this.tribeDeck = CardDeck.shuffle(this.tribeDeck); this.buildingDeck = building.stream().collect(Collectors.groupingBy(Card::getEra)); return allCards; } public List drawTribe(int n) { List cards = new ArrayList<>(); for (int i = 0; i < n; i++) { if(tribeDeck.isEmpty()) break; cards.add(tribeDeck.getFirst()); tribeDeck.remove(tribeDeck.getFirst()); } return cards; } public List drawBuilding(int n, Era era) { List cards = new ArrayList<>(); for (int i = 0; i < n; i++) { if(buildingDeck.isEmpty()) break; Card card = buildingDeck.get(era).getFirst(); cards.add(card); buildingDeck.remove(card); } return cards; } public static List shuffle(List cards) { List shuffled = new ArrayList<>(); for(Era e: Era.values()) { List cardsToShuffle = new ArrayList<>(); for(Card card : cards) { if(card.getEra() == e){ cardsToShuffle.add(card); } } Collections.shuffle(cardsToShuffle); shuffled.addAll(cardsToShuffle); } return shuffled; } public Card getFirstCardForCover() { if(tribeDeck.isEmpty()) return null; Card card = tribeDeck.getFirst(); return card; } public Card drawTribeOne() { if(tribeDeck.isEmpty()) return null; Card card = tribeDeck.getFirst(); tribeDeck.remove(card); return card; } public Card drawBuildingOne(Era era) { if(buildingDeck.isEmpty()) return null; Card card = buildingDeck.get(era).getFirst(); buildingDeck.get(era).remove(card); return card; } // for testing only public Card drawTestTribe(int cardId) { Card card = tribeDeck.stream().filter(c->c.getCardId()==cardId).findFirst().orElse(null); if (card!=null) { System.out.println("CARTA FOUND " + cardId + " --> " + card); tribeDeck.remove(card); } return card; } // for testing only public Card drawTestBuilding(int cardId, Era era) { Card card = buildingDeck.get(era).stream().filter(c->c.getCardId()==cardId).map(Card.class::cast).findFirst().orElse(null); if (card!=null) { buildingDeck.get(era).remove(card); } return card; } }