Skip to main content

server/domain/cards/
deck.rs

1use constants::*;
2
3use crate::domain::{Card, Hand, cards::pile::Pile};
4
5/// Marker type for the main deck (the draw pile).
6#[derive(Clone, Debug, PartialEq, Eq)]
7pub struct DeckType;
8
9/// The deck contains all cards at the start of the game and is drawn from
10/// during dealing and for the starter cut.
11pub type Deck = Pile<DeckType>;
12
13/// The main draw pile / stock.
14pub trait HasDeck {
15    /// Immutable access to the deck.
16    fn deck(&self) -> &Deck;
17
18    /// Mutable access to the deck.
19    fn deck_mut(&mut self) -> &mut Deck;
20}
21
22impl Deck {
23    pub fn shuffled_pack() -> Self {
24        use rand::{rng, seq::SliceRandom};
25
26        let mut cards = Card::all();
27        cards.shuffle(&mut rng());
28        Self::from(cards.as_ref())
29    }
30
31    pub fn cut(&mut self) -> Card {
32        self.pop().expect("available card")
33    }
34
35    pub fn deal(&mut self, count: usize) -> Vec<Hand> {
36        Vec::from_iter((0..count).map(|_| {
37            let cards = self.take(CARDS_DEALT_PER_HAND);
38            Hand::from(cards.as_ref())
39        }))
40    }
41}
42
43#[cfg(test)]
44pub(crate) const STANDARD_DECK_SIZE: usize = 52;
45
46#[cfg(test)]
47mod test {
48    use super::*;
49
50    #[test]
51    fn contains_52_cards() {
52        let deck = Deck::shuffled_pack();
53        assert_eq!(deck.len(), STANDARD_DECK_SIZE);
54    }
55
56    #[test]
57    fn contains_all_cards_for_all_suits_and_faces() {
58        let deck = Deck::shuffled_pack();
59        let cards = Card::all();
60
61        for card in cards {
62            assert!(deck.contains(card))
63        }
64    }
65
66    #[test]
67    fn allow_a_random_card_to_be_cut() {
68        let deck0 = Deck::shuffled_pack();
69        let mut deck1 = deck0.clone();
70        let cut = deck1.cut();
71
72        assert!(deck0.contains(cut));
73        assert!(!deck1.contains(cut));
74        assert_eq!(deck1.len(), 51);
75    }
76
77    #[test]
78    fn allow_deals() {
79        let deck0 = Deck::shuffled_pack();
80        let mut deck1 = deck0.clone();
81        let deals = deck1.deal(2);
82        assert!(deck0.contains_all(deals[0].as_ref()));
83        assert!(deck0.contains_all(deals[1].as_ref()));
84        assert!(deck1.contains_none(deals[0].as_ref()));
85        assert!(deck1.contains_none(deals[1].as_ref()));
86    }
87}