diff --git a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java b/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java index 03d4a46..c780ca9 100644 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java +++ b/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java @@ -57,6 +57,13 @@ public class BlackJackGameController { return ResponseEntity.ok(blackJackService.doubleDown(game)); } + @PostMapping("/blackjack/{id}/split") + public ResponseEntity split(@PathVariable Long id) { + BlackJackGameEntity game = getBlackJackGame(id); + + return ResponseEntity.ok(blackJackService.split(game)); + } + @PostMapping("/blackjack/start") public ResponseEntity createBlackJackGame(@RequestBody @Valid BetDto betDto) { Optional optionalUser = userService.getCurrentUser(); diff --git a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameEntity.java b/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameEntity.java index 4f22c9d..4b03b21 100644 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameEntity.java +++ b/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameEntity.java @@ -51,4 +51,15 @@ public class BlackJackGameEntity { @JsonManagedReference @SQLRestriction("card_type = 'DEALER'") private List dealerCards = new ArrayList<>(); + + @OneToMany(mappedBy = "game", cascade = CascadeType.ALL, orphanRemoval = true) + @JsonManagedReference + @SQLRestriction("card_type = 'PLAYER_SPLIT'") + private List playerSplitCards = new ArrayList<>(); + + @Column(name = "split_bet") + private BigDecimal splitBet; + + @Column(name = "is_split") + private boolean isSplit; } diff --git a/backend/src/main/java/de/szut/casino/blackjack/BlackJackService.java b/backend/src/main/java/de/szut/casino/blackjack/BlackJackService.java index 2d1c08b..5e54efe 100644 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackService.java +++ b/backend/src/main/java/de/szut/casino/blackjack/BlackJackService.java @@ -2,8 +2,8 @@ package de.szut.casino.blackjack; import de.szut.casino.user.UserEntity; import de.szut.casino.user.UserRepository; -import jakarta.transaction.Transactional; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.List; @@ -85,6 +85,36 @@ public class BlackJackService { return game; } + @Transactional + public BlackJackGameEntity split(BlackJackGameEntity game) { + if (game.getState() != BlackJackState.IN_PROGRESS || + game.getPlayerCards().size() != 2 || + game.isSplit() || + !game.getPlayerCards().get(0).getRank().equals(game.getPlayerCards().get(1).getRank())) { + return game; + } + + UserEntity user = getUserWithFreshData(game.getUser()); + BigDecimal splitBet = game.getBet(); + + if (user.getBalance().compareTo(splitBet) < 0) { + return game; + } + + deductBetFromBalance(user, splitBet); + game.setSplitBet(splitBet); + game.setSplit(true); + + CardEntity card = game.getPlayerCards().remove(1); + card.setCardType(CardType.PLAYER_SPLIT); + game.getPlayerSplitCards().add(card); + + dealCardToPlayer(game); + dealCardToSplitHand(game); + + return processGameBasedOnState(game); + } + private BlackJackGameEntity processGameBasedOnState(BlackJackGameEntity game) { if (game.getState() != BlackJackState.IN_PROGRESS) { this.blackJackGameRepository.delete(game); @@ -124,13 +154,33 @@ public class BlackJackService { } } - private void updateGameStateAndBalance(BlackJackGameEntity game) { - game.setState(getState(game)); + private void dealCardToSplitHand(BlackJackGameEntity game) { + CardEntity card = drawCardFromDeck(game); + card.setCardType(CardType.PLAYER_SPLIT); + game.getPlayerSplitCards().add(card); + } - if (game.getState() == BlackJackState.PLAYER_WON) { - updateUserBalance(game, true); - } else if (game.getState() == BlackJackState.PLAYER_LOST) { - updateUserBalance(game, false); + private void updateGameStateAndBalance(BlackJackGameEntity game) { + if (game.isSplit()) { + int mainHandValue = calculateHandValue(game.getPlayerCards()); + int splitHandValue = calculateHandValue(game.getPlayerSplitCards()); + + if (mainHandValue > 21 && splitHandValue > 21) { + game.setState(BlackJackState.PLAYER_LOST); + updateUserBalance(game, false); + } else if (mainHandValue <= 21 && splitHandValue <= 21) { + game.setState(BlackJackState.IN_PROGRESS); + } else { + game.setState(BlackJackState.IN_PROGRESS); + } + } else { + game.setState(getState(game)); + + if (game.getState() == BlackJackState.PLAYER_WON) { + updateUserBalance(game, true); + } else if (game.getState() == BlackJackState.PLAYER_LOST) { + updateUserBalance(game, false); + } } } @@ -155,15 +205,40 @@ public class BlackJackService { userRepository.save(user); } + @Transactional protected void updateUserBalance(BlackJackGameEntity game, boolean isWin) { UserEntity user = getUserWithFreshData(game.getUser()); BigDecimal totalBet = game.getBet(); BigDecimal balance = user.getBalance(); - if (isWin) { - balance = balance.add(totalBet.multiply(BigDecimal.valueOf(2))); - } else if (game.getState() == BlackJackState.DRAW) { - balance = balance.add(totalBet); + if (game.isSplit()) { + totalBet = totalBet.add(game.getSplitBet()); + + if (isWin) { + int mainHandValue = calculateHandValue(game.getPlayerCards()); + int splitHandValue = calculateHandValue(game.getPlayerSplitCards()); + int dealerValue = calculateHandValue(game.getDealerCards()); + + if (mainHandValue <= 21 && (dealerValue > 21 || mainHandValue > dealerValue)) { + balance = balance.add(game.getBet().multiply(BigDecimal.valueOf(2))); + } else if (mainHandValue == dealerValue) { + balance = balance.add(game.getBet()); + } + + if (splitHandValue <= 21 && (dealerValue > 21 || splitHandValue > dealerValue)) { + balance = balance.add(game.getSplitBet().multiply(BigDecimal.valueOf(2))); + } else if (splitHandValue == dealerValue) { + balance = balance.add(game.getSplitBet()); + } + } else if (game.getState() == BlackJackState.DRAW) { + balance = balance.add(totalBet); + } + } else { + if (isWin) { + balance = balance.add(totalBet.multiply(BigDecimal.valueOf(2))); + } else if (game.getState() == BlackJackState.DRAW) { + balance = balance.add(totalBet); + } } user.setBalance(balance); diff --git a/backend/src/main/java/de/szut/casino/blackjack/CardEntity.java b/backend/src/main/java/de/szut/casino/blackjack/CardEntity.java index 3b6903a..e2c1f0e 100644 --- a/backend/src/main/java/de/szut/casino/blackjack/CardEntity.java +++ b/backend/src/main/java/de/szut/casino/blackjack/CardEntity.java @@ -36,5 +36,5 @@ public class CardEntity { } enum CardType { - DECK, PLAYER, DEALER + DECK, PLAYER, DEALER, PLAYER_SPLIT }