use crate::cards::StandardCard;
use crate::deck_of_cards::STANDARD_DECK_OF_CARDS;
use crate::errors::{BASE_DECK_ERROR_CODE, ErrorCode};
use core::fmt::{self, Debug, Display};
use rand::RngExt;
use std::{collections::VecDeque, collections::vec_deque::IntoIter as DequeIntoIter};
pub trait DefaultCollection: Copy + Clone + Debug + Ord + Display {
fn default_collection() -> VecDeque<Self>;
fn multiple_collections(n: usize) -> VecDeque<Self> {
let c = Self::default_collection();
let set_len = c.len();
c.into_iter().cycle().take(set_len * n).collect()
}
fn create_deck() -> Deck<Self> {
Deck::default()
}
}
impl DefaultCollection for StandardCard {
fn default_collection() -> VecDeque<Self> {
STANDARD_DECK_OF_CARDS.iter().copied().collect()
}
fn multiple_collections(n: usize) -> VecDeque<Self> {
STANDARD_DECK_OF_CARDS
.iter()
.copied()
.cycle()
.take(52usize * n)
.collect()
}
}
#[repr(C)]
#[derive(
Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq, Ord, PartialOrd, Hash,
)]
pub struct Deck<C: Copy + Clone + Debug + Ord + Display>(pub(crate) VecDeque<C>);
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
pub enum DeckError {
NoCard,
}
impl Display for DeckError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
DeckError::NoCard => f.write_str("No Cards are left in the deck"),
}
}
}
impl ErrorCode for DeckError {
fn error_code(&self) -> i32 {
BASE_DECK_ERROR_CODE
+ match *self {
DeckError::NoCard => 1,
}
}
}
impl<C: Copy + Clone + Debug + Ord + Display> Deck<C> {
pub fn draw(&mut self) -> Result<C, DeckError> {
self.0.pop_front().ok_or(DeckError::NoCard)
}
pub fn draw_random(&mut self) -> Result<C, DeckError> {
if self.0.is_empty() {
return Err(DeckError::NoCard);
}
let len = self.0.len();
if len == 1 {
self.0.pop_front().ok_or(DeckError::NoCard)
} else {
let index = crate::get_rng().random_range(0..len);
self.0.remove(index).ok_or(DeckError::NoCard)
}
}
pub fn draw_many_random(&mut self, count: usize) -> Vec<C> {
if self.0.is_empty() || count == 0 {
return Vec::with_capacity(0);
}
let len = self.0.len();
let mut rng = crate::get_rng();
let mid = len.saturating_sub(count);
for i in (len..mid).rev() {
let idx = rng.random_range(0..(i + 1));
self.0.swap(i, idx);
}
self.0.split_off(mid).into()
}
pub fn draw_many(&mut self, count: usize) -> Vec<C> {
if self.0.is_empty() || count == 0 {
return Vec::with_capacity(0);
}
let len = self.0.len();
if count >= len {
self.0.drain(..).collect()
} else {
self.0.split_off(len - count).into()
}
}
pub fn draw_rest(&mut self) -> Vec<C> {
self.0.drain(0..).collect()
}
pub fn draw_rest_random(&mut self) -> Vec<C> {
self.shuffle();
self.0.drain(0..).collect()
}
pub fn insert(&mut self, card: C) {
self.0.push_back(card);
}
pub fn into_vec(self) -> Vec<C> {
self.0.into()
}
pub fn shuffle(&mut self) {
let mut rng = crate::get_rng();
for i in (1..self.len()).rev() {
let idx = rng.random_range(0..(i + 1));
self.0.swap(i, idx);
}
}
pub fn peek(&self) -> Option<&C> {
self.0.front()
}
pub fn from_cards(cards: Vec<C>) -> Self {
Self(cards.into())
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn empty() -> Self {
Self(VecDeque::new())
}
}
impl<C: DefaultCollection> Default for Deck<C> {
fn default() -> Deck<C> {
Self(C::default_collection())
}
}
impl<C: Copy + Clone + Debug + Ord + Display> Extend<C> for Deck<C> {
fn extend<I: IntoIterator<Item = C>>(&mut self, iter: I) {
self.0.extend(iter)
}
}
impl<C: Copy + Clone + Debug + Ord + Display> core::iter::FromIterator<C> for Deck<C> {
fn from_iter<I: IntoIterator<Item = C>>(iter: I) -> Self {
let mut c = Self::empty();
c.extend(iter);
c
}
}
impl<C: Copy + Clone + Debug + Ord + Display> IntoIterator for Deck<C> {
type Item = C;
type IntoIter = DequeIntoIter<C>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub struct DeckBuilder<C: Copy + Clone + Debug + Ord + Display>(Vec<C>);
impl<C: Copy + Clone + Debug + Ord + Display> DeckBuilder<C> {
pub fn sets(mut self, n: usize) -> Self {
let set_len = self.0.len();
self.0 = self.0.into_iter().cycle().take(set_len * n).collect();
self
}
pub fn build(self) -> Deck<C> {
Deck(self.0.into())
}
}
impl<C: DefaultCollection> Default for DeckBuilder<C> {
fn default() -> DeckBuilder<C> {
Self(C::default_collection().into())
}
}
impl<C: Copy + Clone + Debug + Ord + Display> From<Vec<C>> for Deck<C> {
fn from(cards: Vec<C>) -> Self {
Self(cards.into())
}
}
impl<C: Copy + Clone + Debug + Ord + Display> From<VecDeque<C>> for Deck<C> {
fn from(cards: VecDeque<C>) -> Self {
Self(cards)
}
}
impl<C: Copy + Clone + Debug + Ord + Display> From<Vec<C>> for DeckBuilder<C> {
fn from(cards: Vec<C>) -> Self {
Self(cards)
}
}
impl<C: Copy + Clone + Debug + Ord + Display> From<VecDeque<C>> for DeckBuilder<C> {
fn from(cards: VecDeque<C>) -> Self {
Self(cards.into())
}
}