server/domain/cards/
deck.rs1use constants::*;
2
3use crate::domain::{Card, Hand, cards::pile::Pile};
4
5#[derive(Clone, Debug, PartialEq, Eq)]
7pub struct DeckType;
8
9pub type Deck = Pile<DeckType>;
12
13pub trait HasDeck {
15 fn deck(&self) -> &Deck;
17
18 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}