// // HintViews.swift // Blackjack // // Views for displaying game hints and betting recommendations. // import SwiftUI import CasinoKit // MARK: - General Hint View /// Displays a gameplay hint (hit, stand, double, etc.) struct HintView: View { let hint: String @ScaledMetric(relativeTo: .body) private var iconSize: CGFloat = Design.Size.hintIconSize @ScaledMetric(relativeTo: .body) private var fontSize: CGFloat = Design.Size.hintFontSize @ScaledMetric(relativeTo: .body) private var paddingH: CGFloat = Design.Size.hintPaddingH @ScaledMetric(relativeTo: .body) private var paddingV: CGFloat = Design.Size.hintPaddingV var body: some View { HStack(spacing: Design.Spacing.small) { Image(systemName: "lightbulb.fill") .font(.system(size: iconSize)) .foregroundStyle(.yellow) Text(String(localized: "Hint: \(hint)")) .font(.system(size: fontSize, weight: .medium)) .foregroundStyle(.white.opacity(Design.Opacity.strong)) .lineLimit(1) .minimumScaleFactor(Design.MinScaleFactor.comfortable) } .padding(.horizontal, paddingH) .padding(.vertical, paddingV) .background( Capsule() .fill(Color.black.opacity(Design.Opacity.light)) ) .accessibilityElement(children: .ignore) .accessibilityLabel(String(localized: "Hint")) .accessibilityValue(hint) } } // MARK: - Betting Hint View /// Shows betting recommendations based on the current card count. struct BettingHintView: View { let hint: String let trueCount: Double @ScaledMetric(relativeTo: .body) private var iconSize: CGFloat = Design.Size.hintIconSize @ScaledMetric(relativeTo: .body) private var fontSize: CGFloat = Design.Size.hintFontSize @ScaledMetric(relativeTo: .body) private var paddingH: CGFloat = Design.Size.hintPaddingH @ScaledMetric(relativeTo: .body) private var paddingV: CGFloat = Design.Size.hintPaddingV private var hintColor: Color { let tc = Int(trueCount.rounded()) if tc >= 2 { return .green // Player advantage - bet more } else if tc <= -1 { return .red // House advantage - bet less } else { return .yellow // Neutral } } private var icon: String { let tc = Int(trueCount.rounded()) if tc >= 2 { return "arrow.up.circle.fill" // Increase bet } else if tc <= -1 { return "arrow.down.circle.fill" // Decrease bet } else { return "equal.circle.fill" // Neutral } } var body: some View { HStack(spacing: Design.Spacing.small) { Image(systemName: icon) .font(.system(size: iconSize)) .foregroundStyle(hintColor) Text(hint) .font(.system(size: fontSize, weight: .medium)) .foregroundStyle(.white.opacity(Design.Opacity.strong)) .lineLimit(1) .minimumScaleFactor(Design.MinScaleFactor.comfortable) } .padding(.horizontal, paddingH) .padding(.vertical, paddingV) .background( Capsule() .fill(Color.black.opacity(Design.Opacity.light)) .overlay( Capsule() .strokeBorder(hintColor.opacity(Design.Opacity.medium), lineWidth: Design.LineWidth.thin) ) ) .accessibilityElement(children: .ignore) .accessibilityLabel(String(localized: "Betting Hint")) .accessibilityValue(hint) } } // MARK: - Previews #Preview("Game Hint - Hit") { ZStack { Color.Table.felt.ignoresSafeArea() HintView(hint: "Hit") } } #Preview("Game Hint - Stand") { ZStack { Color.Table.felt.ignoresSafeArea() HintView(hint: "Stand") } } #Preview("Betting Hint - Positive Count") { ZStack { Color.Table.felt.ignoresSafeArea() BettingHintView(hint: "Bet 4x minimum", trueCount: 2.5) } } #Preview("Betting Hint - Negative Count") { ZStack { Color.Table.felt.ignoresSafeArea() BettingHintView(hint: "Bet minimum", trueCount: -1.5) } } #Preview("Betting Hint - Neutral") { ZStack { Color.Table.felt.ignoresSafeArea() BettingHintView(hint: "Bet minimum (neutral)", trueCount: 0.0) } }