soliterm-model 0.1.0

Shared model types for soliterm
Documentation
use crate::card::Card;
use crate::card_sequence::CardSequence;
use crate::enums::EnumSequence as _;

pub(super) struct FoundationSequence(!);

impl CardSequence for FoundationSequence {
    fn accepts(current_card: Card, next_card: Card) -> bool {
        current_card.suit == next_card.suit && current_card.rank.precedes(next_card.rank)
    }
}

#[cfg(test)]
mod test {
    use super::FoundationSequence;
    use crate::card::{Card, Rank, Suit};
    use crate::card_sequence::CardSequence as _;

    mod foundation_sequence_accepts {
        use assert2::assert;
        use rstest::rstest;

        use super::*;

        #[rstest]
        #[case(Rank::Ace, Rank::Two)]
        #[case(Rank::Five, Rank::Six)]
        #[case(Rank::Ten, Rank::Jack)]
        #[case(Rank::Queen, Rank::King)]
        fn sequential_same_suit(
            #[case] left_rank: Rank,
            #[case] right_rank: Rank,
            #[values(Suit::Spades, Suit::Clubs, Suit::Hearts, Suit::Diamonds)] suit: Suit,
        ) {
            let left_card = Card {
                rank: left_rank,
                suit,
            };
            let right_card = Card {
                rank: right_rank,
                suit,
            };

            assert!(FoundationSequence::accepts(left_card, right_card) == true);
        }

        #[rstest]
        #[case(Rank::Ace, Rank::Two)]
        #[case(Rank::Five, Rank::Six)]
        #[case(Rank::Ten, Rank::Jack)]
        #[case(Rank::Queen, Rank::King)]
        fn sequential_red_black(
            #[case] left_rank: Rank,
            #[case] right_rank: Rank,
            #[values(Suit::Hearts, Suit::Diamonds)] left_suit: Suit,
            #[values(Suit::Spades, Suit::Clubs)] right_suit: Suit,
        ) {
            let left_card = Card {
                rank: left_rank,
                suit: left_suit,
            };
            let right_card = Card {
                rank: right_rank,
                suit: right_suit,
            };

            assert!(FoundationSequence::accepts(left_card, right_card) == false);
        }

        #[rstest]
        #[case(Rank::Ace, Rank::Two)]
        #[case(Rank::Five, Rank::Six)]
        #[case(Rank::Ten, Rank::Jack)]
        #[case(Rank::Queen, Rank::King)]
        fn sequential_black_red(
            #[case] left_rank: Rank,
            #[case] right_rank: Rank,
            #[values(Suit::Spades, Suit::Clubs)] left_suit: Suit,
            #[values(Suit::Hearts, Suit::Diamonds)] right_suit: Suit,
        ) {
            let left_card = Card {
                rank: left_rank,
                suit: left_suit,
            };
            let right_card = Card {
                rank: right_rank,
                suit: right_suit,
            };

            assert!(FoundationSequence::accepts(left_card, right_card) == false);
        }

        #[rstest]
        #[case(Rank::Ace, Rank::Two)]
        #[case(Rank::Five, Rank::Six)]
        #[case(Rank::Ten, Rank::Jack)]
        #[case(Rank::Queen, Rank::King)]
        fn sequential_both_red_or_black(
            #[case] left_rank: Rank,
            #[case] right_rank: Rank,
            #[values(
                (Suit::Spades, Suit::Clubs),
                (Suit::Clubs, Suit::Spades),
                (Suit::Hearts, Suit::Diamonds),
                (Suit::Diamonds, Suit::Hearts),
            )]
            suits: (Suit, Suit),
        ) {
            let (left_suit, right_suit) = suits;
            let left_card = Card {
                rank: left_rank,
                suit: left_suit,
            };
            let right_card = Card {
                rank: right_rank,
                suit: right_suit,
            };

            assert!(FoundationSequence::accepts(left_card, right_card) == false);
        }

        #[rstest]
        #[case(Rank::Ace, Rank::Ace)]
        #[case(Rank::Two, Rank::Ace)]
        #[case(Rank::King, Rank::Ace)]
        #[case(Rank::Ace, Rank::Three)]
        #[case(Rank::Four, Rank::Four)]
        #[case(Rank::Five, Rank::Four)]
        #[case(Rank::Six, Rank::Four)]
        #[case(Rank::Four, Rank::Six)]
        #[case(Rank::King, Rank::King)]
        fn nonsequential_all_suits(
            #[case] left_rank: Rank,
            #[case] right_rank: Rank,
            #[values(Suit::Spades, Suit::Clubs, Suit::Hearts, Suit::Diamonds)] left_suit: Suit,
            #[values(Suit::Spades, Suit::Clubs, Suit::Hearts, Suit::Diamonds)] right_suit: Suit,
        ) {
            let left_card = Card {
                rank: left_rank,
                suit: left_suit,
            };
            let right_card = Card {
                rank: right_rank,
                suit: right_suit,
            };

            assert!(FoundationSequence::accepts(left_card, right_card) == false);
        }
    }
}