ionic_deckhandler/
lib.rs

1use rand::{seq::SliceRandom, thread_rng};
2use std::cmp::Ordering;
3
4/// Provides a rank (value)
5///
6/// Examples:
7///
8/// ```
9/// use ionic_deckhandler::{Card, Suit, Rank};
10///
11/// let card = Card::new(Rank::Five, Suit::Hearts);
12/// let ucard_rank = Card::get_rank(&card) as usize;
13/// ```
14///
15/// ```
16/// use ionic_deckhandler::{Card, Suit, Rank};
17///
18/// let mut hand_arr = [
19///     Card::new(Rank::Five, Suit::Hearts),
20///     Card::new(Rank::Three, Suit::Hearts),
21///     Card::new(Rank::Two, Suit::Hearts),
22///     Card::new(Rank::Ace, Suit::Hearts),
23///     Card::new(Rank::Four, Suit::Hearts),
24///     ];
25/// ```
26#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
27pub enum Rank {
28    Ace,
29    Two,
30    Three,
31    Four,
32    Five,
33    Six,
34    Seven,
35    Eight,
36    Nine,
37    Ten,
38    Jack,
39    Queen,
40    King,
41}
42
43/// The total number of ranks within the deck of cards
44pub const CARD_RANK_COUNT: usize = 13;
45
46pub const ALL_RANKS: [Rank; CARD_RANK_COUNT] = [
47    Rank::Ace,
48    Rank::Two,
49    Rank::Three,
50    Rank::Four,
51    Rank::Five,
52    Rank::Six,
53    Rank::Seven,
54    Rank::Eight,
55    Rank::Nine,
56    Rank::Ten,
57    Rank::Jack,
58    Rank::Queen,
59    Rank::King,
60];
61
62/// Provides a card suit
63///
64/// Examples:
65///
66/// ```
67/// use ionic_deckhandler::{Card, Suit, Rank};
68///
69/// let card = Card::new(Rank::Five, Suit::Hearts);
70/// let ucard_suit = Card::get_suit(&card) as usize;
71/// ```
72///
73/// ```
74/// use ionic_deckhandler::{Card, Suit, Rank};
75///
76/// let mut hand_arr = [
77///     Card::new(Rank::Five, Suit::Hearts),
78///     Card::new(Rank::Three, Suit::Hearts),
79///     Card::new(Rank::Two, Suit::Hearts),
80///     Card::new(Rank::Ace, Suit::Hearts),
81///     Card::new(Rank::Four, Suit::Hearts),
82///     ];
83/// ```
84#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
85pub enum Suit {
86    Clubs,
87    Diamonds,
88    Hearts,
89    Spades,
90}
91
92pub const ALL_SUITS: [Suit; 4] = [Suit::Clubs, Suit::Diamonds, Suit::Hearts, Suit::Spades];
93
94/// A card containing a rank (card value) and a suit. A card may be compared
95/// by value against other cards.
96///
97/// Examples:
98///
99/// ```
100/// use ionic_deckhandler::{Card, Suit, Rank};
101///
102/// let mut hand_arr = [
103///     Card::new(Rank::Five, Suit::Hearts),
104///     Card::new(Rank::Three, Suit::Hearts),
105///     Card::new(Rank::Two, Suit::Hearts),
106///     Card::new(Rank::Ace, Suit::Hearts),
107///     Card::new(Rank::Four, Suit::Hearts),
108///     ];
109///
110/// hand_arr.sort();
111/// ```
112///
113#[derive(Debug, Copy, Clone)]
114pub struct Card {
115    pub rank: Rank,
116    pub suit: Suit,
117}
118
119impl Card {
120    pub fn new(rank: Rank, suit: Suit) -> Self {
121        Card { rank, suit }
122    }
123
124    pub fn get_deck() -> Vec<Self> {
125        let mut deck = Vec::new();
126        for suit in ALL_SUITS.iter() {
127            for rank in ALL_RANKS.iter() {
128                deck.push(Card::new(*rank, *suit));
129            }
130        }
131        deck
132    }
133
134    pub fn get_suit(&self) -> Suit {
135        self.suit
136    }
137
138    pub fn get_rank(&self) -> Rank {
139        self.rank
140    }
141}
142
143impl Ord for Card {
144    fn cmp(&self, other: &Self) -> Ordering {
145        self.rank.cmp(&other.rank)
146    }
147}
148
149impl PartialOrd for Card {
150    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
151        Some(self.cmp(other))
152    }
153}
154
155impl Eq for Card {}
156
157impl PartialEq for Card {
158    fn eq(&self, other: &Self) -> bool {
159        self.rank == other.rank
160    }
161}
162
163/// A deck may be shuffled and sorted
164///
165/// Example:
166///
167/// ```
168/// use ionic_deckhandler::{Card, Deck};
169///
170/// let mut deck = Card::get_deck();
171/// {
172///     let first_card = &deck[0];
173///     assert_eq!(
174///         format!("{:?}", first_card.get_suit()),
175///         String::from("Clubs")
176///     );
177/// }
178/// deck.shuffle_deck();
179///
180/// for card in deck.iter() {
181///     println!("{:?}", card);
182/// }
183/// deck.sort();
184/// for card in deck.iter() {
185///     println!("{:?}", card);
186/// }
187/// ```
188pub trait Deck {
189    fn shuffle_deck(&mut self);
190
191    fn take_from_top(&mut self) -> Option<Card>;
192
193    fn push_to_bottom(&mut self, card: Card);
194}
195
196impl Deck for Vec<Card> {
197    fn shuffle_deck(&mut self) {
198        self.shuffle(&mut thread_rng())
199    }
200
201    fn take_from_top(&mut self) -> Option<Card> {
202        self.pop()
203    }
204
205    fn push_to_bottom(&mut self, card: Card) {
206        let len = self.len();
207        self.insert(len, card);
208    }
209}