//! Play history as sent to the client. use serde::{Deserialize, Serialize}; pub const DEFAULT_HISTORY: u32 = 20; pub const MAX_HISTORY: u32 = 50; /// One settled play. `details` is the game's own audit blob. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct PlayRecord { pub game: String, pub bet: i64, pub winnings: i64, pub balance_after: i64, /// Timestamp as stored in SQLite (`YYYY-MM-DD HH:MM:SS`, UTC). pub at: String, #[serde(default)] pub details: serde_json::Value, } impl PlayRecord { /// Short human summary of the game-specific details. pub fn summary(&self) -> String { let field = |name: &str| -> Option { self.details.get(name).map(|value| match value.as_str() { Some(text) => text.to_string(), None => value.to_string(), }) }; match self.game.as_str() { "slots" => field("win_type").unwrap_or_else(|| "spin".to_string()), "roulette" => match (field("number"), field("color")) { (Some(number), Some(color)) => format!("{number} {color}"), (Some(number), None) => number, _ => String::new(), }, "blackjack" => field("result").unwrap_or_default(), "crash" => { let result = field("result").unwrap_or_default(); match self.details.get("multiplier").and_then(|value| value.as_f64()) { Some(multiplier) => format!("{result} {multiplier:.2}x"), None => result, } } _ => String::new(), } } /// `YYYY-MM-DD HH:MM`, dropping the seconds. pub fn short_time(&self) -> &str { self.at.get(..16).unwrap_or(&self.at) } }