CasinoGames/Baccarat/Storage/BaccaratGameData.swift

155 lines
4.0 KiB
Swift

//
// 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
}
}
}