diff --git a/tichu-common/src/main/java/eu/jonahbauer/tichu/common/model/CombinationType.java b/tichu-common/src/main/java/eu/jonahbauer/tichu/common/model/CombinationType.java index bf25490..feafe02 100644 --- a/tichu-common/src/main/java/eu/jonahbauer/tichu/common/model/CombinationType.java +++ b/tichu-common/src/main/java/eu/jonahbauer/tichu/common/model/CombinationType.java @@ -1,18 +1,23 @@ package eu.jonahbauer.tichu.common.model; +import eu.jonahbauer.tichu.common.model.combinations.*; +import eu.jonahbauer.tichu.common.model.exceptions.InvalidCombinationException; +import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; import java.util.*; +import java.util.function.Function; /** * A type of combination. */ +@RequiredArgsConstructor public enum CombinationType { /** * A single card, {@linkplain Card#isNormal() normal} or {@linkplain Card#isSpecial() special}. This is the * correct {@code CombinationType} for playing the {@link Card#HOUND} or {@link Card#DRAGON}. */ - SINGLE { + SINGLE(Single.class, Single::of) { private static final Set SPECIAL_CARDS = EnumSet.of(Card.PHOENIX, Card.MAHJONG, Card.DRAGON, Card.HOUND); @Override @@ -24,7 +29,7 @@ public enum CombinationType { * A pair, i.e. two {@linkplain Card#isNormal() normal cards} of the same {@linkplain Card#value() value} or the * {@link Card#PHOENIX} and a normal card. */ - PAIR { + PAIR(Pair.class, Pair::of) { private static final Set SPECIAL_CARDS = EnumSet.of(Card.PHOENIX); private static final int[] INDICES = new int[] {0, 1}; @@ -38,7 +43,7 @@ public enum CombinationType { * A triple, i.e. three {@linkplain Card#isNormal() normal cards} of the same {@linkplain Card#value() value} * or the {@linkplain Card#PHOENIX} and two normal cards of the same value. */ - TRIPLE { + TRIPLE(Triple.class, Triple::of) { private static final Set SPECIAL_CARDS = EnumSet.of(Card.PHOENIX); private static final int[] INDICES = new int[] {0, 1, 2}; @@ -53,7 +58,7 @@ public enum CombinationType { * @apiNote A list of cards representing a full house must have the triple at the first three indices and the pair * at the last two. This prevents any ambiguity, e.g. when the full house consists of two pairs and the phoenix. */ - FULL_HOUSE { + FULL_HOUSE(FullHouse.class, FullHouse::of) { private static final Set SPECIAL_CARDS = EnumSet.of(Card.PHOENIX); private static final int[] INDICES_TRIPLE = new int[] {0, 1, 2}; @@ -72,7 +77,7 @@ public enum CombinationType { * @apiNote A list of cards representing a sequence must be sorted by ascending value. This allows to distinguish * between a sequence starting with the phoenix and a sequence ending with the phoenix. */ - SEQUENCE { + SEQUENCE(SingleSequence.class, SingleSequence::of) { private static final Set SPECIAL_CARDS = EnumSet.of(Card.PHOENIX, Card.MAHJONG); private int getStartValue(@NotNull List<@NotNull Card> cards) { @@ -107,7 +112,7 @@ public enum CombinationType { * @apiNote Although not strictly necessary, for consistency with {@link #SEQUENCE} a list of cards representing * a sequence of pairs must be sorted by ascending value. */ - PAIR_SEQUENCE { + PAIR_SEQUENCE(PairSequence.class, PairSequence::of) { private static final Set SPECIAL_CARDS = EnumSet.of(Card.PHOENIX); private int getStartValue(@NotNull List<@NotNull Card> cards) { @@ -137,7 +142,7 @@ public enum CombinationType { /** * A bomb, i.e. four {@linkplain Card#isNormal() normal cards} of the same {@linkplain Card#value() value}. */ - BOMB { + BOMB(BombTuple.class, BombTuple::of) { private static final int[] INDICES = new int[] {0, 1, 2, 3}; private static final Set SPECIAL_CARDS = Collections.emptySet(); @@ -154,7 +159,7 @@ public enum CombinationType { * bomb sequence must be sorted by ascending value. * @apiNote */ - BOMB_SEQUENCE { + BOMB_SEQUENCE(BombSequence.class, BombSequence::of) { private static final Set SPECIAL_CARDS = Collections.emptySet(); private int getStartValue(@NotNull List<@NotNull Card> cards) { @@ -179,14 +184,48 @@ public enum CombinationType { } }; + private final @NotNull Class combinationClass; + private final @NotNull Function<@NotNull List<@NotNull Card>, @NotNull Combination> factory; + /** * Checks whether the given cards form a valid combination of this type. See the documentation of a specific * {@code CombinationType} for more information on what cards form a combination of that particular type. * @param cards a list of cards * @return {@code true} if the cards form a valid combination of this type. + * @throws NullPointerException if the list or any of its elements are {@code null}. */ public abstract boolean check(@NotNull List<@NotNull Card> cards); + /** + * Creates a new combination of this type consisting of the given cards. + * @param cards a list of cards forming a {@linkplain #check(List) valid} combination + * @return a new combination. + * @throws InvalidCombinationException if the given cards do not form a valid combination. + * @throws NullPointerException if the list or any of its elements are {@code null}. + */ + public @NotNull Combination of(@NotNull List<@NotNull Card> cards) { + return factory.apply(cards); + } + + /** + * Creates a new combination of this type consisting of the given cards. + * @param cards a list of cards forming a {@linkplain #check(List) valid} combination + * @return a new combination. + * @throws InvalidCombinationException if the given cards do not form a valid combination. + * @throws NullPointerException if the list or any of its elements are {@code null}. + */ + public @NotNull Combination of(@NotNull Card @NotNull... cards) { + return of(List.of(cards)); + } + + /** + * Returns the class representing a combination of this type. + * @return the class representing a combination of this type. + */ + public @NotNull Class getCombinationClass() { + return combinationClass; + } + // /** * Performs basic checks on a list of cards, i.e. this method checks diff --git a/tichu-common/src/main/java/eu/jonahbauer/tichu/common/model/combinations/Combination.java b/tichu-common/src/main/java/eu/jonahbauer/tichu/common/model/combinations/Combination.java index 3d0a519..0ffa06e 100644 --- a/tichu-common/src/main/java/eu/jonahbauer/tichu/common/model/combinations/Combination.java +++ b/tichu-common/src/main/java/eu/jonahbauer/tichu/common/model/combinations/Combination.java @@ -3,6 +3,7 @@ package eu.jonahbauer.tichu.common.model.combinations; import eu.jonahbauer.tichu.common.model.Card; import eu.jonahbauer.tichu.common.model.CombinationType; import eu.jonahbauer.tichu.common.model.Stack; +import eu.jonahbauer.tichu.common.model.exceptions.InvalidCombinationException; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Range; @@ -79,9 +80,11 @@ public sealed interface Combination extends Serializable permits AbstractCombina /** * Creates a new combination of the given type consisting of the given cards. - * @param type a combination type * @param cards a list of cards forming a {@linkplain CombinationType#check(List) valid} combination - * @return a new combination + * @param type a combination type + * @return a new combination. + * @throws InvalidCombinationException if the given cards do not form a valid combination. + * @throws NullPointerException if the type, the list or any of its elements are {@code null}. */ @Contract("_, _ -> new") static Combination of(@NotNull CombinationType type, @NotNull List<@NotNull Card> cards) {