use crate::playing_cards::card::{Card, CardIdx, DECK_SIZE};
use rand::{rng, seq::SliceRandom};
pub struct CardGenerator {
deck: Vec<CardIdx>,
cur_idx: usize,
}
impl CardGenerator {
pub fn new() -> Self {
CardGenerator {
deck: (0..DECK_SIZE as CardIdx).collect(),
cur_idx: DECK_SIZE,
}
}
#[inline]
pub fn draw_a_card(&mut self) -> Card {
if self.cur_idx >= DECK_SIZE {
self.deck.shuffle(&mut rng());
self.cur_idx = 0;
}
let card_idx = self.deck[self.cur_idx];
self.cur_idx += 1;
Card::from_index(card_idx)
}
pub fn draw(&mut self, count: usize) -> Vec<Card> {
let mut cards = Vec::with_capacity(count);
for _ in 0..count {
cards.push(self.draw_a_card());
}
cards
}
#[inline]
pub fn reshuffle(&mut self) {
self.deck.shuffle(&mut rng());
self.cur_idx = 0;
}
}
impl Default for CardGenerator {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashSet;
#[test]
fn test_card_generate() {
let mut generator = CardGenerator::new();
let cards = generator.draw(52);
assert_eq!(cards.len(), 52);
let mut set = HashSet::new();
assert!(cards.iter().all(|c| set.insert(c)));
}
#[test]
fn test_generate_exhausted() {
let mut generator = CardGenerator::new();
let mut cards = generator.draw(10);
assert_eq!(cards.len(), 10);
let mut set = HashSet::new();
assert!(cards.iter().all(|c| set.insert(c)));
cards.append(&mut generator.draw(10));
assert_eq!(cards.len(), 20);
let mut set = HashSet::new();
assert!(cards.iter().all(|c| set.insert(c)));
cards.append(&mut generator.draw(10));
assert_eq!(cards.len(), 30);
let mut set = HashSet::new();
assert!(cards.iter().all(|c| set.insert(c)));
}
#[test]
fn test_shuffle() {
let mut generator = CardGenerator::new();
let mut cards = generator.draw(1);
generator.reshuffle();
cards.append(&mut generator.draw(51));
assert_eq!(cards.len(), 52);
let mut set = HashSet::new();
assert!(!cards.iter().all(|c| set.insert(c)));
}
}