fantasy_realms_unofficial_api 0.1.0

An unofficial API for the Fantasy Realms card game.
Documentation
use std::{iter::Sum, ops::{Not, Add, AddAssign, Sub, SubAssign, Deref, DerefMut}};
use rand::Rng;
use crate::deck::{Card, Suit, Name};
use crate::hand::Hand;

/// finds all unkown cards
/// # Arguments
/// * `known_cards`` - A `Vec<CardCollection>` representing a group of known cards.
/// usually a list of all known cards in opponents hands. 
/// # Returns
/// A `CardCollection` all cards that are not in the input.
pub fn unknown_cards(known_cards: Vec<CardCollection>) -> CardCollection {
    !known_cards.into_iter().sum::<CardCollection>()
}

/// Represents a collection of cards.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct CardCollection(u64);
pub trait CardCollectionContains<Rhs> {fn contains(&self, other: Rhs) -> bool;} 
impl Deref for CardCollection {
    type Target = u64;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
} impl DerefMut for CardCollection {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
} impl Add for CardCollection {
    type Output = Self;
    fn add(self, other: Self) -> Self {
        CardCollection(self.0 | other.0)
    }
} impl Add<Name> for CardCollection {
    type Output = Self;
    fn add(self, name: Name) -> Self {
        CardCollection(self.0 | (1 << (name as u64)))
    }
} impl Add<Suit> for CardCollection {
    type Output = Self;
    fn add(self, suit: Suit) -> Self {
        if suit == Suit::Wild {
            CardCollection(self.0 | (0b111 << 50))
        } else {
            CardCollection(self.0 | (0b11111 << (5 * (suit as u64))))
        }
    }
} impl Add<Card> for CardCollection {
    type Output = Self;
    fn add(self, card: Card) -> Self {
        CardCollection(self.0 | (1 << (card.name as u64)))
    }
} impl AddAssign for CardCollection {
    fn add_assign(&mut self, other: Self) {
        self.0 |= other.0;
    }
} impl AddAssign<Name> for CardCollection {
    fn add_assign(&mut self, name: Name) {
        self.0 |= 1 << (name as u64)
    }
} impl AddAssign<Suit> for CardCollection {
    fn add_assign(&mut self, suit: Suit) {
        if suit == Suit::Wild {
            self.0 |= 0b111 << 50
        } else {
            self.0 |= 0b11111 << (5 * (suit as u64))
        }
    }
} impl AddAssign<Card> for CardCollection {
    fn add_assign(&mut self, card: Card) {
        self.0 |= 1 << (card.name as u64)
    }
} impl Sum<CardCollection> for CardCollection {
    fn sum<I: Iterator<Item = CardCollection>>(iter: I) -> Self {
        iter.fold(CardCollection::new(), |acc, item| acc + item)
    }
} impl Sub for CardCollection {
    type Output = Self;
    fn sub(self, other: Self) -> Self {
        CardCollection(self.0 & !other.0)
    }
} impl Sub<Name> for CardCollection {
    type Output = Self;
    fn sub(self, name: Name) -> Self {
        CardCollection(self.0 & !(1 << (name as u64)))
    }
} impl Sub<Suit> for CardCollection {
    type Output = Self;
    fn sub(self, suit: Suit) -> Self {
        if suit == Suit::Wild {
            CardCollection(self.0 & !(0b111 << 50))
        } else {
            CardCollection(self.0 & !(0b11111 << (5 * (suit as u64))))
        }
    }
} impl Sub<Card> for CardCollection {
    type Output = Self;
    fn sub(self, card: Card) -> Self {
        CardCollection(self.0 & !(1 << (card.name as u64)))
    }
} impl SubAssign for CardCollection {
    fn sub_assign(&mut self, other: Self) {
        self.0 &= !other.0;
    }
} impl SubAssign<Name> for CardCollection {
    fn sub_assign(&mut self, name: Name) {
        self.0 &= !(1 << (name as u64))
    }
} impl SubAssign<Suit> for CardCollection {
    fn sub_assign(&mut self, suit: Suit) {
        if suit == Suit::Wild {
            self.0 &= !(0b111 << 50)
        } else {
            self.0 &= !(0b11111 << (5 * (suit as u64)))
        }
    }
} impl SubAssign<Card> for CardCollection {
    fn sub_assign(&mut self, card: Card) {
        self.0 &= !(1 << (card.name as u64))
    }
} impl Not for CardCollection {
    type Output = Self;
    fn not(self) -> Self {
        CardCollection((!self.0) - (0b11111111111 << 53))
    }
} impl CardCollectionContains<CardCollection> for CardCollection {
    fn contains(&self, other: CardCollection) -> bool {
        self.0 & other.0 != 0
    }
} impl CardCollectionContains<Name> for CardCollection {
    fn contains(&self, name: Name) -> bool {
        self.0 & (1 << (name as u64)) != 0
    }
} impl CardCollectionContains<Suit> for CardCollection {
    fn contains(&self, suit: Suit) -> bool {
        if suit == Suit::Wild {
            self.0 & (0b111 << 50) != 0
        } else {
            self.0 & (0b11111 << (5 * (suit as u64))) != 0
        }
    }
} impl CardCollectionContains<Card> for CardCollection {
    fn contains(&self, card: Card) -> bool {
        self.0 & (1 << (card.name as u64)) != 0
    }
} impl IntoIterator for CardCollection {
    type Item = Card;
    type IntoIter = CardCollectionIterator;
    fn into_iter(self) -> Self::IntoIter {
        CardCollectionIterator {
            remaining_bits: self.0,
        }
    }
} impl IntoIterator for &CardCollection {
    type Item = Card;
    type IntoIter = CardCollectionIterator;
    fn into_iter(self) -> Self::IntoIter {
        CardCollectionIterator {
            remaining_bits: self.0,
        }
    }
} impl CardCollection {
    pub fn new() -> Self {
        CardCollection(0)
    }

    pub fn len(&self) -> u32 {
        self.0.count_ones()
    }

    pub fn is_empty(&self) -> bool {
        self.0 == 0
    }

    pub fn iter(&self) -> CardCollectionIterator {
        CardCollectionIterator {
            remaining_bits: self.0,
        }
    }

    /// Gets a random card from the collection.
    /// # Errors 
    /// This function returns an `Err(String)` if:
    /// * The collection is empty.
    pub fn get_random_card(&self) -> Result<Card, String> {
        let set_bits: Vec<u8> = self
            .iter()
            .map(|card| card.name as u8)
            .collect();
        if set_bits.is_empty() {
            Err("No cards in collection.".to_string())
        } else {
            let random_index = rand::thread_rng().gen_range(0..set_bits.len());
            Ok(Card::from(set_bits[random_index]))
        }
    }

    /// Gets a random hand from the collection.
    /// # Errors
    /// This function returns an `Err(String)` if:
    /// * The collection contains less than 7 cards.
    /// # Side Effects
    /// * Removes the cards in the hand generated from the collection.
    pub fn draw_hand(&mut self) -> Hand {
        let hand: Vec<Card> = (0..7)
            .map(|_| {
                let card = self.get_random_card().expect("Not enough cards in deck");
                *self -= card;
                card
            })
            .collect();
        let hand_array: [Card; 7] = hand.try_into()
            .map_err(|_| "Failed to convert to array")
            .expect("Should have exactly 7 cards");
        
        Hand::new(hand_array)
    }
}

pub struct CardCollectionIterator {
    remaining_bits: u64,
} impl Iterator for CardCollectionIterator {
    type Item = Card;
    fn next(&mut self) -> Option<Self::Item> {
        if self.remaining_bits == 0 {
            return None;
        }
        let position = self.remaining_bits.trailing_zeros() as u8;
        self.remaining_bits &= self.remaining_bits - 1;
        Some(Card::from(position))
    }
} impl From<Hand> for CardCollection {
    fn from(hand: Hand) -> Self {
        let mut new_hand = CardCollection::new();
        for card in hand {
            new_hand += card;
        }
        new_hand
    }
} impl From<&Hand> for CardCollection {
    fn from(hand: &Hand) -> Self {
        let mut new_hand = CardCollection::new();
        for card in hand {
            new_hand += *card;
        }
        new_hand
    }
}