stochasta/playing_cards/
playing_card_deck.rs

1use std::fmt::Display;
2
3use enumset::EnumSet;
4use itertools::Itertools;
5
6use crate::CardDeck;
7
8use super::{
9    playing_card_suit::ALL_SUITS, playing_card_value::ALL_VALUES, PlayingCard, PlayingCardSuit,
10    PlayingCardValue,
11};
12
13/// A builder for quickly creating decks of playing cards.
14///
15/// # Example
16///
17/// ```
18/// use stochasta::playing_cards::{PlayingCard, PlayingCardDeck, PlayingCardSuit, PlayingCardValue};
19///
20/// let deck = PlayingCardDeck::new()
21///     .value_range(PlayingCardValue::Seven, PlayingCardValue::Ace)
22///     .all_suits()
23///     .set_count(2)
24///     .to_deck();
25/// println!("{:?}", deck);
26/// assert_eq!(deck.size(), 64);
27/// ```
28///
29#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31pub struct PlayingCardDeck {
32    values: EnumSet<PlayingCardValue>,
33    suits: EnumSet<PlayingCardSuit>,
34    count: u64,
35}
36
37impl PlayingCardDeck {
38    /// Constructs a new empty deck.
39    ///
40    /// # Example
41    ///
42    /// ```
43    /// use stochasta::playing_cards::PlayingCardDeck;
44    ///
45    /// let deck = PlayingCardDeck::new();
46    /// assert!(deck.is_empty())
47    /// ```
48    #[must_use]
49    pub fn new() -> Self {
50        Self {
51            values: EnumSet::new(),
52            suits: EnumSet::new(),
53            count: 1,
54        }
55    }
56
57    /// Sets the values.
58    ///
59    /// # Example
60    ///
61    /// ```
62    /// use stochasta::playing_cards::{PlayingCard, PlayingCardDeck, PlayingCardSuit, PlayingCardValue};
63    ///
64    /// let deck = PlayingCardDeck::new()
65    ///     .set_values([PlayingCardValue::Ten, PlayingCardValue::Ace])
66    ///     .set_suits([PlayingCardSuit::Hearts])
67    ///     .to_deck();
68    ///
69    /// assert_eq!(deck.size(), 2);
70    /// assert!(deck.contains(&PlayingCard::new(PlayingCardValue::Ten, PlayingCardSuit::Hearts)));
71    /// assert!(deck.contains(&PlayingCard::new(PlayingCardValue::Ace, PlayingCardSuit::Hearts)));
72    /// ```
73    #[must_use]
74    pub fn set_values<I>(mut self, values: I) -> Self
75    where
76        I: IntoIterator<Item = PlayingCardValue>,
77    {
78        self.values.clear();
79        self.values.extend(values);
80        self
81    }
82
83    /// Sets the suits.
84    ///
85    /// # Example
86    ///
87    /// ```
88    /// use stochasta::playing_cards::{PlayingCard, PlayingCardDeck, PlayingCardSuit, PlayingCardValue};
89    ///
90    /// let deck = PlayingCardDeck::new()
91    ///     .set_values([PlayingCardValue::Ace])
92    ///     .set_suits([PlayingCardSuit::Hearts, PlayingCardSuit::Clubs])
93    ///     .to_deck();
94    ///
95    /// assert_eq!(deck.size(), 2);
96    /// assert!(deck.contains(&PlayingCard::new(PlayingCardValue::Ace, PlayingCardSuit::Hearts)));
97    /// assert!(deck.contains(&PlayingCard::new(PlayingCardValue::Ace, PlayingCardSuit::Clubs)));
98    /// ```
99    #[must_use]
100    pub fn set_suits<I>(mut self, suits: I) -> Self
101    where
102        I: IntoIterator<Item = PlayingCardSuit>,
103    {
104        self.suits.clear();
105        self.suits.extend(suits);
106        self
107    }
108
109    /// Sets the value range. (both inclusive)
110    ///    
111    /// # Example
112    ///
113    /// ```
114    /// use stochasta::playing_cards::{PlayingCard, PlayingCardDeck, PlayingCardSuit, PlayingCardValue};
115    ///
116    /// let deck = PlayingCardDeck::new()
117    ///     .value_range(PlayingCardValue::Jack, PlayingCardValue::Ace)
118    ///     .set_suits([PlayingCardSuit::Hearts])
119    ///     .to_deck();
120    ///
121    /// assert_eq!(deck.size(), 4);
122    /// assert!(deck.contains(&PlayingCard::new(PlayingCardValue::Jack, PlayingCardSuit::Hearts)));
123    /// assert!(deck.contains(&PlayingCard::new(PlayingCardValue::Queen, PlayingCardSuit::Hearts)));
124    /// assert!(deck.contains(&PlayingCard::new(PlayingCardValue::King, PlayingCardSuit::Hearts)));
125    /// assert!(deck.contains(&PlayingCard::new(PlayingCardValue::Ace, PlayingCardSuit::Hearts)));
126    /// ```
127    #[must_use]
128    pub fn value_range(mut self, from: PlayingCardValue, to: PlayingCardValue) -> Self {
129        self.values.clear();
130        self.values.extend(arr_from_to(&ALL_VALUES, &from, &to));
131        self
132    }
133
134    /// Sets all `PlayingCardValue`s to be included.
135    ///
136    /// # Example
137    ///
138    /// ```
139    /// use stochasta::playing_cards::{PlayingCard, PlayingCardDeck, PlayingCardSuit, PlayingCardValue};
140    ///
141    /// let deck = PlayingCardDeck::new()
142    ///     .all_values()
143    ///     .set_suits([PlayingCardSuit::Hearts])
144    ///     .to_deck();
145    ///
146    /// assert_eq!(deck.size(), 13);
147    /// assert!(deck.contains(&PlayingCard::new(PlayingCardValue::Two, PlayingCardSuit::Hearts)));
148    /// assert!(deck.contains(&PlayingCard::new(PlayingCardValue::Ten, PlayingCardSuit::Hearts)));
149    /// assert!(deck.contains(&PlayingCard::new(PlayingCardValue::Ace, PlayingCardSuit::Hearts)));
150    /// ```
151    #[must_use]
152    pub fn all_values(mut self) -> Self {
153        self.values.extend(ALL_VALUES);
154        self
155    }
156
157    /// Sets all `PlayingCardSuit`s inclusive.
158    ///
159    /// # Example
160    ///
161    /// ```
162    /// use stochasta::playing_cards::{PlayingCard, PlayingCardDeck, PlayingCardSuit, PlayingCardValue};
163    ///
164    /// let deck = PlayingCardDeck::new()
165    ///     .set_values([PlayingCardValue::Two])
166    ///     .all_suits()
167    ///     .to_deck();
168    ///
169    /// assert_eq!(deck.size(), 4);
170    /// assert!(deck.contains(&PlayingCard::new(PlayingCardValue::Two, PlayingCardSuit::Diamonds)));
171    /// assert!(deck.contains(&PlayingCard::new(PlayingCardValue::Two, PlayingCardSuit::Hearts)));
172    /// assert!(deck.contains(&PlayingCard::new(PlayingCardValue::Two, PlayingCardSuit::Clubs)));
173    /// assert!(deck.contains(&PlayingCard::new(PlayingCardValue::Two, PlayingCardSuit::Spades)));
174    /// ```
175    #[must_use]
176    pub fn all_suits(mut self) -> Self {
177        self.suits.extend(ALL_SUITS);
178        self
179    }
180
181    /// Sets the count of each individual card.
182    ///
183    /// # Example
184    ///
185    /// ```
186    /// use stochasta::playing_cards::{PlayingCard, PlayingCardDeck, PlayingCardSuit, PlayingCardValue};
187    ///
188    /// let deck = PlayingCardDeck::new()
189    ///     .set_values([PlayingCardValue::Two])
190    ///     .set_suits([PlayingCardSuit::Hearts])
191    ///     .set_count(4)
192    ///     .to_deck();
193    ///
194    /// assert_eq!(deck.size(), 4);
195    /// assert!(deck.contains(&PlayingCard::new(PlayingCardValue::Two, PlayingCardSuit::Hearts)));
196    /// ```
197    #[must_use]
198    pub fn set_count(mut self, count: u64) -> Self {
199        self.count = count;
200        self
201    }
202
203    /// Converts this to a [`CardDeck`](crate::CardDeck).
204    ///
205    /// # Example
206    ///
207    /// ```
208    /// use stochasta::playing_cards::{PlayingCard, PlayingCardDeck, PlayingCardSuit, PlayingCardValue};
209    ///
210    /// let deck = PlayingCardDeck::new()
211    ///     .all_values()
212    ///     .all_suits()
213    ///     .set_count(2)
214    ///     .to_deck();
215    ///
216    /// assert_eq!(deck.size(), 13 * 4 * 2);
217    /// ```
218    #[must_use]
219    pub fn to_deck(&self) -> CardDeck<PlayingCard> {
220        let mut deck = CardDeck::new();
221        for value in self.values.iter() {
222            for suit in self.suits.iter() {
223                deck.add_times(PlayingCard::new(value, suit), self.count);
224            }
225        }
226        deck
227    }
228
229    /// Returns `true` if deck contains no cards.
230    ///
231    /// # Example
232    ///
233    /// ```
234    /// use stochasta::playing_cards::{PlayingCard, PlayingCardDeck, PlayingCardSuit, PlayingCardValue};
235    ///
236    /// assert!(PlayingCardDeck::new().is_empty());
237    /// ```
238    #[must_use]
239    pub fn is_empty(&self) -> bool {
240        self.count == 0 || self.suits.is_empty() || self.values.is_empty()
241    }
242}
243
244impl Default for PlayingCardDeck {
245    fn default() -> Self {
246        Self::new()
247    }
248}
249
250impl Display for PlayingCardDeck {
251    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
252        write!(
253            f,
254            "[{}] ({}x)",
255            self.suits
256                .iter()
257                .map(|s| self.values.iter().map(|v| format!("{v}{s}")).join(" "))
258                .join(" "),
259            self.count
260        )
261    }
262}
263
264fn arr_from_to<T>(arr: &[T], from: &T, to: &T) -> Vec<T>
265where
266    T: Eq + Clone,
267{
268    let from_idx = arr.iter().position(|x| x == from).unwrap();
269    let to_idx = arr.iter().position(|x| x == to).unwrap();
270    arr[from_idx..=to_idx].to_vec()
271}
272
273#[cfg(test)]
274mod tests {
275    use super::*;
276
277    #[test]
278    fn display_check() {
279        let deck = PlayingCardDeck::new()
280            .set_suits([PlayingCardSuit::Clubs, PlayingCardSuit::Hearts])
281            .set_values([
282                PlayingCardValue::Jack,
283                PlayingCardValue::Queen,
284                PlayingCardValue::King,
285            ])
286            .set_count(2);
287
288        assert_eq!("[J♣ Q♣ K♣ J♥ Q♥ K♥] (2x)", deck.to_string());
289    }
290}