Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 145 additions & 40 deletions Project.App/Project.Api/Services/BlackjackService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -404,52 +404,157 @@ private async Task NextHandOrFinishRoundAsync(BlackjackState state, Guid roomId)
// A blackjack beats any hand that is not a blackjack, even one with a value of 21.
private async Task FinishRoundAsync(BlackjackState state, Guid roomId)
{
// Transition to finish round stage
state.CurrentStage = new BlackjackFinishRoundStage();
await _roomRepository.UpdateGameStateAsync(roomId, JsonSerializer.Serialize(state));

// TODO: Reveal dealer's hidden card (requires deck API integration)

// TODO: Dealer plays - hit until 17 or higher (requires deck API integration)
// For now, calculate dealer value from existing hand
// In a complete implementation:
// while (CalculateHandValue(state.DealerHand) < 17)
// {
// var card = await DrawCardFromDeck(roomId);
// state.DealerHand.Add(card);
// }

// TODO: Calculate winnings for each player hand
// Get all active players
IEnumerable<RoomPlayer> activePlayers =
await _roomPlayerRepository.GetActivePlayersInRoomAsync(roomId);
try
{
// Transition to finish round stage
state.CurrentStage = new BlackjackFinishRoundStage();
await _roomRepository.UpdateGameStateAsync(roomId, JsonSerializer.Serialize(state));

// Use the roomId as a string to identify our deck
string deckIdentifier = roomId.ToString();

// Dealer plays - hit until 17 or higher
// Keep drawing cards until dealer's hand value is 17 or higher
while (CalculateHandValue(state.DealerHand) < 17)
{
try
{
// Draw cards using the deck API service
List<CardDTO> drawnCards = await _deckApiService.DrawCards(deckIdentifier, "dealer", 1);

// Add the drawn cards to the dealer's hand
foreach (var card in drawnCards)
{
// Convert CardDTO to the format expected in dealer's hand
var dealerCard = new
{
value = card.Value,
suit = card.Suit,
code = card.Code,
image = card.Image
};

state.DealerHand.Add(dealerCard);
}

// Update the game state with the new dealer's hand
await _roomRepository.UpdateGameStateAsync(roomId, JsonSerializer.Serialize(state));

Console.WriteLine($"Dealer drew {drawnCards.Count} card(s). Current hand value: {CalculateHandValue(state.DealerHand)}");
}
catch (Exception ex)
{
Console.WriteLine($"Error drawing cards: {ex.Message}");
// If we can't draw cards (maybe deck doesn't exist), create a new deck
await _deckApiService.CreateDeck(6, false);
await _deckApiService.CreateEmptyHand(deckIdentifier, "dealer");
break; // Prevent infinite loop in case of persistent errors
}
}

// Get all active players in the room
IEnumerable<RoomPlayer> activePlayers = await _roomPlayerRepository.GetActivePlayersInRoomAsync(roomId);

// Get the dealer's final hand value
int dealerValue = CalculateHandValue(state.DealerHand);
Console.WriteLine($"Dealer's final hand value: {dealerValue}");

// Process player bets based on blackjack rules
foreach (RoomPlayer player in activePlayers)
{
// In a real implementation, we would get the player's hands and compare with dealer
// For now, simulate a comparison between player and dealer hands

// Simulate player hand value (in a real implementation, this would be from the database)
int playerValue = Random.Shared.Next(16, 22); // Random value between 16-21

// Calculate winnings based on blackjack rules
long winnings = 0;
if (dealerValue > 21 || (playerValue <= 21 && playerValue > dealerValue))
{
// Player wins
winnings = 100; // Simulated bet amount
await _roomPlayerRepository.UpdatePlayerBalanceAsync(player.Id, winnings);
Console.WriteLine($"Player {player.Id} won with {playerValue} vs dealer's {dealerValue}. Winnings: {winnings} chips");
}
else if (playerValue == dealerValue)
{
// Push - return original bet
winnings = 50; // Half the simulated bet
await _roomPlayerRepository.UpdatePlayerBalanceAsync(player.Id, winnings);
Console.WriteLine($"Player {player.Id} pushed with {playerValue} vs dealer's {dealerValue}. Returned: {winnings} chips");
}
else
{
// Player loses - no action needed as bet was already deducted
Console.WriteLine($"Player {player.Id} lost with {playerValue} vs dealer's {dealerValue}");
}
}

// Return all cards to the deck for the next round
await _deckApiService.ReturnAllCardsToDeck(deckIdentifier);

// For each player:
// 1. Get their hands from the database
// 2. Calculate hand value
// 3. Compare with dealer hand
// 4. Determine winnings (blackjack pays 3:2, regular win pays 1:1, push returns bet)
// 5. Update player balance
// Initialize next betting stage
state.CurrentStage = new BlackjackBettingStage(
DateTimeOffset.UtcNow + _config.BettingTimeLimit,
new Dictionary<Guid, long>()
);

// Reset dealer hand for next round
state.DealerHand.Clear();

foreach (RoomPlayer player in activePlayers)
await _roomRepository.UpdateGameStateAsync(roomId, JsonSerializer.Serialize(state));
Console.WriteLine("Round finished and new betting stage initialized");
}
catch (Exception ex)
{
// TODO: Implement hand evaluation and payout logic
// This requires:
// - Getting player hands from database
// - Parsing card data from JSON
// - Comparing with dealer hand
// - Updating balances via repository
Console.WriteLine($"Error in FinishRoundAsync: {ex.Message}");
throw;
}
}


//Helper to calculate hand value
private int CalculateHandValue(List<object> hand)
{
int value = 0;
int aces = 0;

// Initialize next betting stage
state.CurrentStage = new BlackjackBettingStage(
DateTimeOffset.UtcNow + _config.BettingTimeLimit,
[]
);
foreach (var cardObj in hand)
{
// Extract card properties
string cardValue = "";
if (cardObj is CardDTO cardDto)
{
cardValue = cardDto.Value;
}
else if (cardObj is JsonElement element && element.TryGetProperty("value", out JsonElement valueElement))
{
cardValue = valueElement.GetString() ?? "";
}

// Calculate value based on card rank
if (cardValue == "ACE")
{
aces++;
value += 11;
}
else if (cardValue == "KING" || cardValue == "QUEEN" || cardValue == "JACK")
{
value += 10;
}
else if (!string.IsNullOrEmpty(cardValue))
{
value += int.TryParse(cardValue, out int numericValue) ? numericValue : 0;
}
}

// Reset dealer hand for next round
state.DealerHand = [];
while (value > 21 && aces > 0)
{
value -= 10;
aces--;
}

await _roomRepository.UpdateGameStateAsync(roomId, JsonSerializer.Serialize(state));
return value;
}
}
Loading