// // BaccaratGameData.swift // Baccarat // // Baccarat-specific game data that persists to iCloud. // import Foundation import CasinoKit /// Persisted data for Baccarat game. public struct BaccaratGameData: PersistableGameData { // MARK: - PersistableGameData public static let gameIdentifier = "baccarat" public var roundsPlayed: Int { roundHistory.count } public static var empty: BaccaratGameData { BaccaratGameData( balance: 10_000, roundHistory: [], totalWinnings: 0, biggestWin: 0, biggestLoss: 0, lastModified: Date() ) } // MARK: - Game Data /// Current chip balance. public var balance: Int /// History of all rounds played. public var roundHistory: [SavedRoundResult] // MARK: - Lifetime Statistics /// Total net winnings (can be negative). public var totalWinnings: Int /// Biggest single-round win. public var biggestWin: Int /// Biggest single-round loss (stored as positive number). public var biggestLoss: Int /// Last time data was modified (required by PersistableGameData). public var lastModified: Date // MARK: - Computed Stats /// Number of Player wins. public var playerWins: Int { roundHistory.filter { $0.result == "player" }.count } /// Number of Banker wins. public var bankerWins: Int { roundHistory.filter { $0.result == "banker" }.count } /// Number of Tie games. public var tieGames: Int { roundHistory.filter { $0.result == "tie" }.count } /// Win rate percentage. public var winRate: Double { guard roundsPlayed > 0 else { return 0 } let wins = roundHistory.filter { $0.netWinnings > 0 }.count return Double(wins) / Double(roundsPlayed) * 100 } } /// Codable round result for persistence. public struct SavedRoundResult: Codable, Identifiable, Sendable { public let id: UUID public let result: String // "player", "banker", "tie" public let playerValue: Int public let bankerValue: Int public let playerPair: Bool public let bankerPair: Bool public let isNatural: Bool public let timestamp: Date public let netWinnings: Int public init( id: UUID = UUID(), result: String, playerValue: Int, bankerValue: Int, playerPair: Bool, bankerPair: Bool, isNatural: Bool, timestamp: Date = Date(), netWinnings: Int ) { self.id = id self.result = result self.playerValue = playerValue self.bankerValue = bankerValue self.playerPair = playerPair self.bankerPair = bankerPair self.isNatural = isNatural self.timestamp = timestamp self.netWinnings = netWinnings } } // MARK: - Conversion from RoundResult extension SavedRoundResult { /// Creates a SavedRoundResult from a RoundResult and net winnings. init(from roundResult: RoundResult, netWinnings: Int) { self.id = roundResult.id self.result = roundResult.result.persistenceKey self.playerValue = roundResult.playerValue self.bankerValue = roundResult.bankerValue self.playerPair = roundResult.playerPair self.bankerPair = roundResult.bankerPair self.isNatural = roundResult.isNatural self.timestamp = roundResult.timestamp self.netWinnings = netWinnings } } // MARK: - GameResult Extension extension GameResult { /// String key for persistence. var persistenceKey: String { switch self { case .playerWins: return "player" case .bankerWins: return "banker" case .tie: return "tie" } } /// Creates GameResult from persistence key. init?(persistenceKey: String) { switch persistenceKey { case "player": self = .playerWins case "banker": self = .bankerWins case "tie": self = .tie default: return nil } } }