package solitaire; import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; final class Depot { private final List cards; Depot(List cards) { if (cards.isEmpty()) throw new IllegalArgumentException("Depot should be initialized with at least one card"); this.cards = new LinkedList<>(cards); this.cards.getLast().reveal(); } private static boolean isValidNextCard(Card lastCard, Card nextCard) { if (nextCard.getSuit().isRed() == lastCard.getSuit().isRed()) return false; return lastCard.getRank().isSuccessorOf(nextCard.getRank()); } private boolean isValidPlacement(Card card) { if (cards.isEmpty()) return card.getRank() == Rank.KING; return isValidNextCard(cards.getLast(), card); } private static boolean isValidRun(List run) { Card prev = null; for (Card next : run) { if (next.isHidden() || (prev != null && !isValidNextCard(prev, next))) return false; prev = next; } return true; } boolean add(List run) { /* * no invalid run can be generated by the game, so we only need to check * placement. */ if (!isValidPlacement(run.getFirst())) return false; cards.addAll(run); return true; } boolean add(Card card) { return add(List.of(card)); } Optional> remove(int size) { if (size < 1) throw new IllegalArgumentException("Size must be a positive integer"); if (cards.size() < size) return Optional.empty(); List slice = cards.subList(cards.size() - size, cards.size()); if (!isValidRun(slice)) return Optional.empty(); List run = List.copyOf(slice); slice.clear(); if (!cards.isEmpty()) cards.getLast().reveal(); return Optional.of(run); } @Override public String toString() { if (cards.isEmpty()) return "< >"; return cards.stream().map(String::valueOf).collect(Collectors.joining("\n")); } }