--- /dev/null
+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<Card> cards;
+
+ Depot(List<Card> 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<Card> 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<Card> 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<List<Card>> remove(int size) {
+ if (size < 1)
+ throw new IllegalArgumentException("Size must be a positive integer");
+
+ if (cards.size() < size)
+ return Optional.empty();
+
+ List<Card> slice = cards.subList(cards.size() - size, cards.size());
+
+ if (!isValidRun(slice))
+ return Optional.empty();
+
+ List<Card> 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"));
+ }
+}
return cards.size() == Rank.RANKS.size();
}
- private boolean isValidNextCard(Card card) {
- Rank cardRank, lastRank;
-
- if (card.getSuit() != this.suit)
+ private boolean isValidNextCard(Card nextCard) {
+ if (nextCard.getSuit() != this.suit)
return false;
- cardRank = card.getRank();
-
if (cards.isEmpty())
- return cardRank == Rank.ACE;
+ return nextCard.getRank() == Rank.ACE;
- lastRank = cards.getLast().getRank();
+ Card lastCard = cards.getLast();
- return cardRank.isSuccessorOf(lastRank);
+ return nextCard.getRank().isSuccessorOf(lastCard.getRank());
}
boolean add(Card card) {