CasinoGames/Baccarat/Models/BetType.swift

166 lines
4.8 KiB
Swift

//
// BetType.swift
// Baccarat
//
// Bet types and payout rates for baccarat.
//
import Foundation
import SwiftUI
/// The types of bets available in baccarat.
enum BetType: String, CaseIterable, Identifiable {
// MARK: - Main Bets
case player = "Player"
case banker = "Banker"
case tie = "Tie"
// MARK: - Side Bets
case playerPair = "Player Pair"
case bankerPair = "Banker Pair"
case dragonBonusPlayer = "Dragon Bonus Player"
case dragonBonusBanker = "Dragon Bonus Banker"
var id: String { rawValue }
/// Whether this is a main bet (Player/Banker) that is required to play.
var isMainBet: Bool {
self == .player || self == .banker
}
/// Whether this is a side bet.
var isSideBet: Bool {
!isMainBet && self != .tie
}
/// The base payout multiplier for winning this bet type.
/// Note: Dragon Bonus has variable payouts based on margin - this is the natural win payout.
var payoutMultiplier: Double {
switch self {
case .player: return 1.0
case .banker: return 0.95 // 5% commission
case .tie: return 8.0
case .playerPair, .bankerPair: return 11.0 // 11:1
case .dragonBonusPlayer, .dragonBonusBanker: return 1.0 // Base for natural
}
}
/// Display name with payout info.
var displayWithPayout: String {
switch self {
case .player: return "Player (1:1)"
case .banker: return "Banker (0.95:1)"
case .tie: return "Tie (8:1)"
case .playerPair: return "P Pair (11:1)"
case .bankerPair: return "B Pair (11:1)"
case .dragonBonusPlayer: return "Dragon P"
case .dragonBonusBanker: return "Dragon B"
}
}
/// Short display name for betting zones.
var shortName: String {
switch self {
case .player: return "PLAYER"
case .banker: return "BANKER"
case .tie: return "TIE"
case .playerPair: return "P PAIR"
case .bankerPair: return "B PAIR"
case .dragonBonusPlayer: return "P BONUS"
case .dragonBonusBanker: return "B BONUS"
}
}
/// The payout description shown in betting zones.
var payoutDescription: String {
switch self {
case .player: return "PAYS 1 TO 1"
case .banker: return "PAYS 0.95 TO 1"
case .tie: return "PAYS 8 TO 1"
case .playerPair, .bankerPair: return "PAYS 11 TO 1"
case .dragonBonusPlayer, .dragonBonusBanker: return "UP TO 30 TO 1"
}
}
/// The color associated with this bet type.
var color: Color {
switch self {
case .player: return .blue
case .banker: return .red
case .tie: return .green
case .playerPair: return .blue.opacity(0.7)
case .bankerPair: return .red.opacity(0.7)
case .dragonBonusPlayer: return .purple
case .dragonBonusBanker: return .orange
}
}
/// All main betting options (required to play).
static var mainBets: [BetType] {
[.player, .banker]
}
/// All side bets.
static var sideBets: [BetType] {
[.tie, .playerPair, .bankerPair, .dragonBonusPlayer, .dragonBonusBanker]
}
/// Pair bets.
static var pairBets: [BetType] {
[.playerPair, .bankerPair]
}
/// Dragon bonus bets.
static var dragonBets: [BetType] {
[.dragonBonusPlayer, .dragonBonusBanker]
}
}
/// Represents a bet placed by the user.
struct Bet: Identifiable, Equatable {
let id = UUID()
let type: BetType
let amount: Int
static func == (lhs: Bet, rhs: Bet) -> Bool {
lhs.id == rhs.id
}
}
/// Dragon Bonus payout table based on margin of victory.
enum DragonBonusPayout {
/// Returns the payout multiplier for Dragon Bonus based on the margin of victory.
/// Returns nil if the bet loses.
static func multiplier(for margin: Int, isNatural: Bool) -> Int? {
// Natural win (8 or 9)
if isNatural && margin > 0 {
return 1
}
// Non-natural wins by margin
switch margin {
case 9: return 30
case 8: return 10
case 7: return 6
case 6: return 4
case 5: return 2
case 4: return 1
default: return nil // Loses on margin < 4, tie, or loss
}
}
/// All possible payouts for display in rules.
static var payoutTable: [(margin: String, payout: String)] {
[
("Natural Win (8 or 9)", "1 to 1"),
("Win by 9", "30 to 1"),
("Win by 8", "10 to 1"),
("Win by 7", "6 to 1"),
("Win by 6", "4 to 1"),
("Win by 5", "2 to 1"),
("Win by 4", "1 to 1"),
("Win by 0-3 or Lose", "Lose")
]
}
}