namespace KfChatDotNetBot.Models; public class BlackjackGameMetaModel { /// /// The wager ID associated with this game /// public required int WagerId { get; set; } /// /// Player's hand /// public required List PlayerHand { get; set; } /// /// Dealer's hand /// public required List DealerHand { get; set; } /// /// Remaining cards in the deck /// public required List Deck { get; set; } /// /// When the game was started /// public required DateTimeOffset GameStarted { get; set; } /// /// Whether player has doubled down (can only hit once more) /// public bool HasDoubledDown { get; set; } = false; } public class Card { /// /// Card rank (2-10, J, Q, K, A) /// public required string Rank { get; set; } /// /// Card suit (♠, ♥, ♦, ♣) /// public required string Suit { get; set; } /// /// Get the blackjack value of this card /// public int GetValue() { return Rank switch { "A" => 11, // Aces are handled specially in hand calculation "K" or "Q" or "J" => 10, _ => int.Parse(Rank) }; } /// /// Display card as string /// public override string ToString() { return $"{Rank}{Suit}"; } } public static class BlackjackHelper { private static readonly string[] Ranks = { "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A" }; private static readonly string[] Suits = { "♠", "♥", "♦", "♣" }; /// /// Create a new shuffled deck /// public static List CreateDeck(Random random) { var deck = new List(); foreach (var suit in Suits) { foreach (var rank in Ranks) { deck.Add(new Card { Rank = rank, Suit = suit }); } } // Shuffle using Fisher-Yates for (int i = deck.Count - 1; i > 0; i--) { int j = random.Next(0, i + 1); (deck[i], deck[j]) = (deck[j], deck[i]); } return deck; } /// /// Calculate hand value with proper Ace handling /// public static int CalculateHandValue(List hand) { int value = 0; int aces = 0; foreach (var card in hand) { if (card.Rank == "A") { aces++; value += 11; } else { value += card.GetValue(); } } // Convert Aces from 11 to 1 if needed to avoid bust while (value > 21 && aces > 0) { value -= 10; aces--; } return value; } /// /// Check if hand is blackjack (21 with 2 cards) /// public static bool IsBlackjack(List hand) { return hand.Count == 2 && CalculateHandValue(hand) == 21; } /// /// Format hand for display /// public static string FormatHand(List hand, bool hideFirstCard = false) { if (hideFirstCard && hand.Count > 0) { return $"[HIDDEN] {string.Join(" ", hand.Skip(1).Select(c => c.ToString()))}"; } return string.Join(" ", hand.Select(c => c.ToString())); } }