1#![allow(clippy::new_without_default)]
2
3pub mod card;
4pub mod cho_dai_di;
5pub mod collections;
6pub mod player;
7pub mod rank;
8pub mod suit;
9
10use card::{Card, STANDARD_DECK};
11use once_cell::sync::Lazy;
12use rand::{prelude::*, rngs::SmallRng, SeedableRng};
13use std::{marker::PhantomData, sync::Mutex};
14
15static RNG: Lazy<Mutex<SmallRng>> = Lazy::new(|| Mutex::new(SmallRng::from_entropy()));
16
17pub fn shuffled_deck() -> Vec<Card> {
18 let mut deck = STANDARD_DECK;
19 let mut rng = RNG.lock().unwrap();
20 deck.shuffle(&mut *rng);
21 deck.into()
22}
23
24pub struct Deck<G> {
25 cards: Vec<Card>,
26 _game: PhantomData<G>,
27}
28
29impl<G> Deck<G> {
30 pub fn len(&self) -> usize {
31 self.cards.len()
32 }
33
34 pub fn is_empty(&self) -> bool {
35 self.cards.is_empty()
36 }
37}
38
39#[cfg(test)]
40mod tests {
41 use super::shuffled_deck;
42 use crate::{
43 cho_dai_di::{ChoDaiDi, FOUR_PLAYERS},
44 Deck,
45 };
46
47 #[test]
48 fn test_shuffled_deck() {
49 let deck = shuffled_deck();
50 assert_eq!(deck.len(), 52);
51 }
52
53 #[test]
54 fn test_cho_dai_di_draw_starting_hands() {
55 let mut deck = Deck::<ChoDaiDi<FOUR_PLAYERS>>::new();
56 let hands = deck.draw_starting_hands();
57
58 for hand in hands {
59 assert_eq!(hand.len(), 13);
60 }
61 }
62}