use itertools::Itertools;
use crate::{Card, Rank, Suit};
pub fn generate() -> impl Iterator<Item = Card> {
Rank::ALL_VARIANTS
.iter()
.cartesian_product(Suit::ALL_VARIANTS.iter())
.map(|(&rank, &suit)| Card::new(rank, suit))
}
#[cfg(feature = "rand")]
pub fn shuffled() -> Vec<Card> { shuffled_with(&mut rand::thread_rng()) }
#[cfg(feature = "rand")]
pub fn shuffled_with<R>(rng: &mut R) -> Vec<Card>
where
R: rand::Rng + ?Sized,
{
use rand::prelude::*;
let mut deck = generate().collect::<Vec<_>>();
deck.shuffle(rng);
deck
}
#[cfg(test)]
mod tests {
use std::collections::{HashMap, HashSet};
use super::*;
#[test]
fn card_integers_unique() {
let deck = generate();
let mut ints = HashSet::with_capacity(52);
deck.into_iter().for_each(|card| {
assert!(ints.insert(card.unique_integer()));
});
assert_eq!(ints.len(), 52);
}
#[test]
fn card_suit_and_rank_calculations() {
let deck = generate();
let mut suits = HashMap::with_capacity(4);
let mut ranks = HashMap::with_capacity(13);
for card in deck {
let suit_count = suits.entry(card.suit()).or_insert(0);
let rank_count = ranks.entry(card.rank()).or_insert(0);
*suit_count += 1;
*rank_count += 1;
}
assert!(suits.into_iter().all(|(_, count)| count == 13));
assert!(ranks.into_iter().all(|(_, count)| count == 4));
}
#[test]
fn generate_deck_is_52_cards() {
assert_eq!(generate().count(), 52);
}
#[test]
#[cfg(feature = "rand")]
fn generate_shuffled_deck_is_52_cards() {
assert_eq!(shuffled().len(), 52);
}
}