use std::{
fs::{self, write},
path::Path,
};
use crate::{baccarat::BaccaratBet, money::Money};
use anyhow::Result;
use serde::{Deserialize, Serialize};
use tabled::Tabled;
#[derive(Copy, Clone, Default, Deserialize, Serialize, Tabled)]
pub struct Statistics {
#[serde(default)]
pub biggest_bankroll: Money,
#[serde(default)]
pub times_bankrupted: u32,
#[serde(default)]
#[tabled(skip)]
pub blackjack: BlackjackStatistics,
#[serde(default)]
#[tabled(skip)]
pub roulette: RouletteStatistics,
#[serde(default)]
#[tabled(skip)]
pub slots: SlotMachineStatistics,
#[serde(default)]
#[tabled(skip)]
pub baccarat: BaccaratStatistics,
}
impl Statistics {
pub fn init(stats_path: &Path) -> Result<()> {
if !stats_path.try_exists()? {
let stats = Self::default();
stats.save(stats_path)?;
}
Ok(())
}
pub fn load(stats_path: &Path) -> Result<Self> {
let stats_string = fs::read_to_string(stats_path)?;
let stats = toml::from_str(&stats_string)?;
Ok(stats)
}
pub fn save(&self, stats_path: &Path) -> Result<()> {
fs::create_dir_all(stats_path.parent().unwrap()).expect("Couldn't create stats directory!");
write(stats_path, toml::to_string(&self)?)?;
Ok(())
}
pub fn update_bankroll(&mut self, amount: Money) {
if amount > self.biggest_bankroll {
self.biggest_bankroll = amount;
} else if amount.is_zero() {
self.times_bankrupted += 1;
}
}
}
#[derive(Copy, Clone, Default, Deserialize, Serialize, Tabled)]
#[tabled(rename_all = "Upper Title Case")]
pub struct SlotMachineStatistics {
pub total_pulls: u32,
pub money_won: Money,
pub money_spent: Money,
pub biggest_jackpot: Money,
}
impl SlotMachineStatistics {
pub fn record_pull(&mut self, amount: Money) {
self.total_pulls += 1;
self.money_spent += amount;
}
pub fn record_win(&mut self, amount: Money) {
self.money_won += amount;
if self.biggest_jackpot < amount {
self.biggest_jackpot = amount;
}
}
}
#[derive(Copy, Clone, Default, Deserialize, Serialize, Tabled)]
#[tabled(rename_all = "Upper Title Case")]
pub struct RouletteStatistics {
pub spins_won: u32,
pub spins_lost: u32,
pub money_won: Money,
pub money_lost: Money,
pub biggest_win: Money,
pub biggest_loss: Money,
}
impl RouletteStatistics {
pub fn record_win(&mut self, amount: Money) {
self.spins_won += 1;
self.money_won += amount;
if amount > self.biggest_win {
self.biggest_win = amount;
}
}
pub fn record_loss(&mut self, amount: Money) {
self.spins_lost += 1;
self.money_lost += amount;
if amount > self.biggest_loss {
self.biggest_loss = amount;
}
}
}
#[derive(Copy, Clone, Default, Deserialize, Serialize, Tabled)]
#[tabled(rename_all = "Upper Title Case")]
pub struct BlackjackStatistics {
pub hands_won: u32,
pub hands_lost: u32,
pub hands_push: u32,
pub money_won: Money,
pub money_lost: Money,
pub biggest_win: Money,
pub biggest_loss: Money,
}
impl BlackjackStatistics {
pub fn record_win(&mut self, amount: Money) {
self.hands_won += 1;
self.money_won += amount;
if amount > self.biggest_win {
self.biggest_win = amount;
}
}
pub fn record_loss(&mut self, amount: Money) {
self.hands_lost += 1;
self.money_lost += amount;
if amount > self.biggest_loss {
self.biggest_loss = amount;
}
}
pub fn record_push(&mut self) {
self.hands_push += 1;
}
}
#[derive(Copy, Clone, Default, Deserialize, Serialize, Tabled)]
#[tabled(rename_all = "Upper Title Case")]
pub struct BaccaratStatistics {
pub hands_won: u32,
pub hands_lost: u32,
pub hands_tied: u32,
pub player_bets: u32,
pub banker_bets: u32,
pub tie_bets: u32,
pub money_won: Money,
pub money_lost: Money,
pub biggest_win: Money,
pub biggest_loss: Money,
}
impl BaccaratStatistics {
pub fn record_win(&mut self, bet_type: &BaccaratBet, bet_amount: Money) {
self.hands_won += 1;
match bet_type {
BaccaratBet::Player => self.player_bets += 1,
BaccaratBet::Banker => self.banker_bets += 1,
BaccaratBet::Tie => self.tie_bets += 1,
}
self.money_won += bet_amount;
if bet_amount > self.biggest_win {
self.biggest_win = bet_amount;
}
}
pub fn record_tie(&mut self, bet_type: &BaccaratBet) {
self.hands_tied += 1;
match bet_type {
BaccaratBet::Player => self.player_bets += 1,
BaccaratBet::Banker => self.banker_bets += 1,
BaccaratBet::Tie => self.tie_bets += 1,
}
}
pub fn record_loss(&mut self, bet_type: &BaccaratBet, bet_amount: Money) {
self.hands_lost += 1;
match bet_type {
BaccaratBet::Player => self.player_bets += 1,
BaccaratBet::Banker => self.banker_bets += 1,
BaccaratBet::Tie => self.tie_bets += 1,
}
self.money_lost += bet_amount;
if bet_amount > self.biggest_loss {
self.biggest_loss = bet_amount;
}
}
}