use crate::core::{Card, Hand, Suit, Value};
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Clone, Copy)]
pub enum Suitedness {
Suited,
OffSuit,
Any,
}
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Clone)]
pub struct Default {
value_one: Value,
value_two: Value,
suited: Suitedness,
}
impl Default {
fn is_pair(&self) -> bool {
self.value_one == self.value_two
}
fn create_suited(&self) -> Vec<Hand> {
if self.is_pair() {
return vec![];
}
Suit::suits()
.iter()
.map(|s| {
Hand::new_with_cards(vec![
Card {
value: self.value_one,
suit: *s,
},
Card {
value: self.value_two,
suit: *s,
},
])
})
.collect()
}
fn create_offsuit(&self) -> Vec<Hand> {
let expected_hands = if self.is_pair() { 6 } else { 12 };
self.append_offsuit(Vec::with_capacity(expected_hands))
}
fn append_offsuit(&self, mut hands: Vec<Hand>) -> Vec<Hand> {
let suits = Suit::suits();
for (i, suit_one) in suits.iter().enumerate() {
for suit_two in &suits[i + 1..] {
hands.push(Hand::new_with_cards(vec![
Card {
value: self.value_one,
suit: *suit_one,
},
Card {
value: self.value_two,
suit: *suit_two,
},
]));
if self.value_one != self.value_two {
hands.push(Hand::new_with_cards(vec![
Card {
value: self.value_one,
suit: *suit_two,
},
Card {
value: self.value_two,
suit: *suit_one,
},
]));
}
}
}
hands
}
fn possible_hands(&self) -> Vec<Hand> {
match self.suited {
Suitedness::Suited => self.create_suited(),
Suitedness::OffSuit => self.create_offsuit(),
Suitedness::Any => self.append_offsuit(self.create_suited()),
}
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd)]
pub struct SingleCardRange {
value_one: Value,
start: Value,
end: Value,
suited: Suitedness,
}
impl SingleCardRange {
fn possible_hands(&self) -> Vec<Hand> {
let mut cur_value = self.start;
let mut hands = vec![];
while cur_value <= self.end {
let mut new_hands = Default {
value_one: self.value_one,
value_two: cur_value,
suited: self.suited,
}.possible_hands();
hands.append(&mut new_hands);
cur_value = Value::from_u8(cur_value as u8 + 1);
}
hands
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd)]
pub enum StartingHand {
Def(Default),
SingleCardRange(SingleCardRange),
}
impl StartingHand {
pub fn default(value_one: Value, value_two: Value, suited: Suitedness) -> StartingHand {
StartingHand::Def(Default {
value_one: value_one,
value_two: value_two,
suited: suited,
})
}
pub fn single_range(
value_one: Value,
start: Value,
end: Value,
suited: Suitedness,
) -> StartingHand {
StartingHand::SingleCardRange(SingleCardRange {
value_one: value_one,
start: start,
end: end,
suited: suited,
})
}
pub fn all() -> Vec<StartingHand> {
let mut hands = Vec::with_capacity(169);
let values = Value::values();
for (i, value_one) in values.iter().enumerate() {
for value_two in &values[i..] {
hands.push(StartingHand::Def(Default {
value_one: *value_one,
value_two: *value_two,
suited: Suitedness::OffSuit,
}));
if value_one != value_two {
hands.push(StartingHand::Def(Default {
value_one: *value_one,
value_two: *value_two,
suited: Suitedness::Suited,
}));
}
}
}
hands
}
pub fn possible_hands(&self) -> Vec<Hand> {
match *self {
StartingHand::Def(ref h) => h.possible_hands(),
StartingHand::SingleCardRange(ref h) => h.possible_hands(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::Value;
#[test]
fn test_aces() {
let sh = Default {
value_one: Value::Ace,
value_two: Value::Ace,
suited: Suitedness::OffSuit,
};
assert!(6 == sh.possible_hands().len());
}
#[test]
fn test_suited_connector() {
let sh = Default {
value_one: Value::Ace,
value_two: Value::King,
suited: Suitedness::Suited,
};
assert!(4 == sh.possible_hands().len());
}
#[test]
fn test_unsuited_connector() {
let sh = Default {
value_one: Value::Ace,
value_two: Value::King,
suited: Suitedness::OffSuit,
};
assert!(12 == sh.possible_hands().len());
}
#[test]
fn test_starting_hand_count() {
let num_to_test: usize = StartingHand::all()
.iter()
.map(|h| h.possible_hands().len())
.sum();
assert!(1326 == num_to_test);
}
}