Skip to content

Commit

Permalink
Deserialize (#24)
Browse files Browse the repository at this point in the history
* added exclude block to Cargo.toml

* Card::new_from_string

* added Suit::from_french_suit_symbol

* working on rank from string

* rstest

* refactored Suit::from_french_suit_index

* refactored Suit::from_french_suit_index again

* ran fmt

* Added stardard52

* added Standard52::card_from_index_string

* refactored suit prossessing

* Negative scenarios via Blank

* fixing clippy and fmt issues

* Fixing invalid Standard52::card_from_index_string

* cleanup

* hardened FluentName::new

* added to Standard52

* Added from_index roundtrip test

* Moved to_index_str to Pile

* Added Standard52::display()
  • Loading branch information
folkengine authored Dec 11, 2021
1 parent 61ba77b commit 30c6da4
Show file tree
Hide file tree
Showing 15 changed files with 388 additions and 36 deletions.
7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "cardpack"
description = "Generic Deck of Cards"
version = "0.4.1"
version = "0.4.2"
authors = ["folkengine <gaoler@electronicpanopticon.com>"]
repository = "https://github.com/ContractBridge/cardpack.rs.git"
homepage = "https://github.com/ContractBridge/cardpack.rs"
Expand All @@ -20,4 +20,7 @@ colored = "2"
fluent-templates = "0.6.1"
lazy_static = "1.4.0"
rand = "0.8.4"
unic-langid = { version = "0.9.0", features = ["macros"] }
unic-langid = { version = "0.9.0", features = ["macros"] }

[dev-dependencies]
rstest = "0.11.0"
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,7 @@ internationalization. Current languages supported are

* [Fluent Templates](https://github.com/XAMPPRocky/fluent-templates)
* [Project Fluent](https://www.projectfluent.org/)

## Dev Dependencies

* [rstest](https://github.com/la10736/rstest) - Fixture-based test framework for Rust
10 changes: 5 additions & 5 deletions examples/poker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ fn main() {
let sb = shuffled.draw(2).unwrap();
let bb = shuffled.draw(2).unwrap();

println!("small blind: {}", sb.by_symbol_index());
println!("big blind: {}", bb.by_symbol_index());
println!("small blind: {}", sb.to_symbol_index());
println!("big blind: {}", bb.to_symbol_index());

println!();
println!("flop : {}", shuffled.draw(3).unwrap().by_symbol_index());
println!("turn : {}", shuffled.draw(1).unwrap().by_symbol_index());
println!("river: {}", shuffled.draw(1).unwrap().by_symbol_index());
println!("flop : {}", shuffled.draw(3).unwrap().to_symbol_index());
println!("turn : {}", shuffled.draw(1).unwrap().to_symbol_index());
println!("river: {}", shuffled.draw(1).unwrap().to_symbol_index());
}
16 changes: 16 additions & 0 deletions examples/serialize.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
fn main() {
let pack = cardpack::Pack::french_deck();
let shuffled = pack.cards().shuffle();

let card_str = shuffled.to_symbol_index();

let _rawcards: Vec<&str> = card_str.split(' ').collect();

// for _s in rawcards {
//
// }

println!();

print!("{}", card_str);
}
6 changes: 6 additions & 0 deletions examples/standard52.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fn main() {
println!("Let's shuffle a Standard 52 deck of cards:\n");
let standard52 = cardpack::Standard52::new_shuffled();

println!("{}", standard52);
}
22 changes: 22 additions & 0 deletions src/cards/card.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ impl Card {
}
}

pub fn blank_card() -> Card {
Card::new(BLANK, BLANK)
}

pub fn is_valid(&self) -> bool {
!self.rank.is_blank() && !self.suit.is_blank()
}

// Private methods
fn determine_index(suit: &Suit, rank: &Rank) -> String {
let rank = rank.index_default();
Expand Down Expand Up @@ -176,6 +184,20 @@ mod card_tests {
assert_eq!(card.symbol_colorized(&GERMAN), "D♥".red().to_string());
}

#[test]
fn is_valid() {
assert!(Card::new(QUEEN, CLUBS).is_valid())
}

#[test]
fn is_valid__false() {
assert!(!Card::new("", "").is_valid());
assert!(!Card::new(QUEEN, BLANK_SUIT).is_valid());
assert!(!Card::new(BLANK_RANK, CLUBS).is_valid());
assert!(!Card::new(BLANK_RANK, BLANK_SUIT).is_valid());
assert!(!Card::new(" ", BLANK_SUIT).is_valid());
}

#[test]
fn default() {
let card = Card::default();
Expand Down
18 changes: 9 additions & 9 deletions src/cards/decks/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ impl BridgeBoard {
}

pub fn demo(&self) {
println!("S: {}", self.south.sort().by_symbol_index());
println!("W: {}", self.west.sort().by_symbol_index());
println!("N: {}", self.north.sort().by_symbol_index());
println!("E: {}", self.east.sort().by_symbol_index());
println!("S: {}", self.south.sort().to_symbol_index());
println!("W: {}", self.west.sort().to_symbol_index());
println!("N: {}", self.north.sort().to_symbol_index());
println!("E: {}", self.east.sort().to_symbol_index());
}

pub fn get_pack(&self) -> &Pack {
Expand Down Expand Up @@ -226,10 +226,10 @@ mod bridge_tests {

let deal = BridgeBoard::from_pbn_deal(PBN_TEST_STRING);

assert_eq!(south.unwrap().by_index(), deal.south.by_index());
assert_eq!(west.unwrap().by_index(), deal.west.by_index());
assert_eq!(north.unwrap().by_index(), deal.north.by_index());
assert_eq!(east.unwrap().by_index(), deal.east.by_index());
assert_eq!(south.unwrap().to_index(), deal.south.to_index());
assert_eq!(west.unwrap().to_index(), deal.west.to_index());
assert_eq!(north.unwrap().to_index(), deal.north.to_index());
assert_eq!(east.unwrap().to_index(), deal.east.to_index());
assert!(deal.is_valid())
}

Expand All @@ -252,7 +252,7 @@ mod bridge_tests {

let deal = BridgeBoard::from_pbn_deal(pbn);

assert_eq!(west.unwrap().by_index(), deal.west.by_index());
assert_eq!(west.unwrap().to_index(), deal.west.to_index());
assert!(deal.is_valid())
}

Expand Down
1 change: 1 addition & 0 deletions src/cards/decks/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod bridge;
pub mod standard52;
173 changes: 173 additions & 0 deletions src/cards/decks/standard52.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
use std::fmt;

use crate::cards::rank::*;
use crate::cards::suit::*;
use crate::{Card, Pack, Pile};

#[derive(Clone, Debug, Hash, PartialEq)]
pub struct Standard52 {
pub pack: Pack,
pub deck: Pile,
}

impl Standard52 {
pub fn new(pile: Pile) -> Standard52 {
Standard52 {
pack: Pack::french_deck(),
deck: pile,
}
}

pub fn new_shuffled() -> Standard52 {
Standard52 {
pack: Pack::french_deck(),
deck: Pile::french_deck().shuffle(),
}
}

pub fn from_index(card_str: &'static str) -> Standard52 {
let mut pile = Pile::default();
for index in card_str.split_whitespace() {
pile.add(Standard52::card_from_index(index));
}

Standard52 {
pack: Pack::french_deck(),
deck: pile,
}
}

pub fn to_index(&self) -> String {
self.deck.to_index()
}

pub fn to_index_str(&self) -> &'static str {
self.deck.to_index_str()
}

pub fn is_complete(&self) -> bool {
let pile = self.deck.sort();
&pile == self.pack.cards()
}

pub fn card_from_index(card_str: &'static str) -> Card {
let rank = Rank::from_french_deck_index(Standard52::rank_str_from_index(card_str));
let suit = Suit::from_french_deck_index(Standard52::suit_char_from_index(card_str));

if rank.is_blank() || suit.is_blank() {
Card::blank_card()
} else {
Card::new_from_structs(rank, suit)
}
}

fn rank_str_from_index(card_str: &'static str) -> &'static str {
if card_str.len() < 2 {
return BLANK_RANK;
}
&card_str[..1]
}

fn suit_char_from_index(card_str: &'static str) -> char {
if card_str.len() < 2 {
return '_';
}
card_str.char_indices().nth(1).unwrap().1
}
}

impl Default for Standard52 {
fn default() -> Standard52 {
Standard52 {
pack: Pack::french_deck(),
deck: Pile::french_deck(),
}
}
}

impl fmt::Display for Standard52 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let sig = self.to_index();
write!(f, "{}", sig)
}
}

#[cfg(test)]
#[allow(non_snake_case)]
mod standard52_tests {
use super::*;
use rstest::rstest;

#[test]
fn from_index() {
let index_string = "2S 3D QS KH 3C 3S TC 9H 3H 6H QD 4H 2H 5S 6D 9S AD 5C 7S JS AC 6S 8H 7C JC 7H JD TS AS KS JH 5D 6C 9C QC 8D 4C 5H 4D 8S 2C AH 2D 9D TH KD 7D KC 4S 8C QH TD";
let mut standard52 = Standard52::from_index(index_string);

assert_eq!(
Card::new(TWO, SPADES),
standard52.deck.draw_first().unwrap()
);
assert_eq!(
Card::new(THREE, DIAMONDS),
standard52.deck.draw_first().unwrap()
);
}

#[test]
fn from_index_shuffled() {
let starter = Standard52::new_shuffled();
let standard52 = Standard52::from_index(starter.to_index_str());

assert!(standard52.is_complete());
assert_eq!(starter, standard52);
}

#[test]
fn is_complete() {
assert!(Standard52::default().is_complete());
assert!(Standard52::new_shuffled().is_complete());
assert!(Standard52::new(Pile::french_deck().draw(52).unwrap()).is_complete());
}

#[test]
fn is_complete__false() {
assert!(!Standard52::new(Pile::french_deck().draw(4).unwrap()).is_complete());
assert!(!Standard52::new(Pile::french_deck_with_jokers()).is_complete());
}

#[test]
fn rank_str_from_index() {
assert_eq!("2", Standard52::rank_str_from_index("2S"));
}

#[test]
fn suit_char_from_index() {
assert_eq!('S', Standard52::suit_char_from_index("2S"));
assert_eq!('♠', Standard52::suit_char_from_index("2♠"));
}

#[rstest]
#[case("2S", Card::new(TWO, SPADES))]
#[case("2♠", Card::new(TWO, SPADES))]
#[case("3S", Card::new(THREE, SPADES))]
#[case("3♠", Card::new(THREE, SPADES))]
#[case("4♠", Card::new(FOUR, SPADES))]
#[case("4S", Card::new(FOUR, SPADES))]
#[case("5♠", Card::new(FIVE, SPADES))]
#[case("5S", Card::new(FIVE, SPADES))]
fn card_from_index(#[case] input: &'static str, #[case] expected: Card) {
assert_eq!(expected, Standard52::card_from_index(input));
}

#[rstest]
#[case("XX")]
#[case("2X")]
#[case("2s")]
#[case("XS")]
#[case(" ")]
#[case(" ")]
#[case("")]
fn card_from_index__invalid_index(#[case] input: &'static str) {
assert_eq!(Card::blank_card(), Standard52::card_from_index(input));
}
}
2 changes: 1 addition & 1 deletion src/cards/pack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::cards::pile::Pile;
/// let sb = shuffled.draw(2).unwrap();
/// let bb = shuffled.draw(2).unwrap();
///
/// println!("small blind: {}", sb.by_symbol_index());
/// println!("small blind: {}", sb.to_symbol_index());
/// println!("big blind: {}", bb);
///
/// println!();
Expand Down
Loading

0 comments on commit 30c6da4

Please sign in to comment.