feat: add double down feature to blackjack game
This commit is contained in:
parent
d90fcdcf1e
commit
d2b22b561d
7 changed files with 190 additions and 61 deletions
|
@ -77,6 +77,23 @@ public class BlackJackGameController {
|
|||
return ResponseEntity.ok(blackJackService.stand(game));
|
||||
}
|
||||
|
||||
@PostMapping("/blackjack/{id}/doubleDown")
|
||||
public ResponseEntity<Object> doubleDown(@PathVariable Long id, @RequestHeader("Authorization") String token) {
|
||||
Optional<UserEntity> optionalUser = userService.getCurrentUser(token);
|
||||
|
||||
if (optionalUser.isEmpty()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
UserEntity user = optionalUser.get();
|
||||
BlackJackGameEntity game = blackJackService.getBlackJackGame(id);
|
||||
if (game == null || !Objects.equals(game.getUserId(), user.getId())) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
return ResponseEntity.ok(blackJackService.doubleDown(game));
|
||||
}
|
||||
|
||||
@PostMapping("/blackjack/start")
|
||||
public ResponseEntity<Object> createBlackJackGame(@RequestBody @Valid CreateBlackJackGameDto createBlackJackGameDto, @RequestHeader("Authorization") String token) {
|
||||
Optional<UserEntity> optionalUser = userService.getCurrentUser(token);
|
||||
|
|
|
@ -14,17 +14,15 @@ import java.util.Random;
|
|||
public class BlackJackService {
|
||||
private final BlackJackGameRepository blackJackGameRepository;
|
||||
private final UserRepository userRepository;
|
||||
private final Random random = new Random();
|
||||
|
||||
public BlackJackService(BlackJackGameRepository blackJackGameRepository, UserRepository userRepository) {
|
||||
this.blackJackGameRepository = blackJackGameRepository;
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
private final Random random = new Random();
|
||||
|
||||
public BlackJackGameEntity getBlackJackGame(Long id) {
|
||||
Optional<BlackJackGameEntity> optionalBlackJackGame = blackJackGameRepository.findById(id);
|
||||
return optionalBlackJackGame.orElse(null);
|
||||
return blackJackGameRepository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
@ -32,88 +30,146 @@ public class BlackJackService {
|
|||
BlackJackGameEntity game = new BlackJackGameEntity();
|
||||
game.setUser(user);
|
||||
game.setBet(betAmount);
|
||||
|
||||
initializeDeck(game);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
CardEntity playerCard = drawCardFromDeck(game);
|
||||
playerCard.setCardType(CardType.PLAYER);
|
||||
game.getPlayerCards().add(playerCard);
|
||||
}
|
||||
|
||||
CardEntity dealerCard = drawCardFromDeck(game);
|
||||
dealerCard.setCardType(CardType.DEALER);
|
||||
game.getDealerCards().add(dealerCard);
|
||||
|
||||
BlackJackState state = handleState(game, user);
|
||||
game.setState(state);
|
||||
|
||||
userRepository.save(user);
|
||||
dealInitialCards(game);
|
||||
|
||||
game.setState(getState(game));
|
||||
deductBetFromBalance(user, betAmount);
|
||||
|
||||
return blackJackGameRepository.save(game);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public BlackJackGameEntity hit(BlackJackGameEntity game) {
|
||||
game = blackJackGameRepository.findById(game.getId()).orElse(game);
|
||||
game = refreshGameState(game);
|
||||
|
||||
if (game.getState() != BlackJackState.IN_PROGRESS) {
|
||||
return game;
|
||||
}
|
||||
|
||||
CardEntity drawnCard = drawCardFromDeck(game);
|
||||
drawnCard.setCardType(CardType.PLAYER);
|
||||
game.getPlayerCards().add(drawnCard);
|
||||
|
||||
game.setState(handleState(game, game.getUser()));
|
||||
|
||||
if (game.getState() == BlackJackState.PLAYER_WON) {
|
||||
updateUserBalance(game, true);
|
||||
} else if (game.getState() == BlackJackState.PLAYER_LOST) {
|
||||
updateUserBalance(game, false);
|
||||
}
|
||||
|
||||
dealCardToPlayer(game);
|
||||
updateGameStateAndBalance(game);
|
||||
|
||||
return blackJackGameRepository.save(game);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public BlackJackGameEntity stand(BlackJackGameEntity game) {
|
||||
game = blackJackGameRepository.findById(game.getId()).orElse(game);
|
||||
game = refreshGameState(game);
|
||||
|
||||
if (game.getState() != BlackJackState.IN_PROGRESS) {
|
||||
return game;
|
||||
}
|
||||
|
||||
while (calculateHandValue(game.getDealerCards()) < 17) {
|
||||
CardEntity dealerCard = drawCardFromDeck(game);
|
||||
dealerCard.setCardType(CardType.DEALER);
|
||||
game.getDealerCards().add(dealerCard);
|
||||
}
|
||||
dealCardsToDealerUntilMinimumScore(game);
|
||||
determineWinnerAndUpdateBalance(game);
|
||||
|
||||
return blackJackGameRepository.save(game);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public BlackJackGameEntity doubleDown(BlackJackGameEntity game) {
|
||||
game = refreshGameState(game);
|
||||
|
||||
if (game.getState() != BlackJackState.IN_PROGRESS || game.getPlayerCards().size() != 2) {
|
||||
return game;
|
||||
}
|
||||
|
||||
UserEntity user = getUserWithFreshData(game.getUser());
|
||||
BigDecimal additionalBet = game.getBet();
|
||||
|
||||
if (user.getBalance().compareTo(additionalBet) < 0) {
|
||||
return game;
|
||||
}
|
||||
|
||||
deductBetFromBalance(user, additionalBet);
|
||||
game.setBet(game.getBet().add(additionalBet));
|
||||
|
||||
dealCardToPlayer(game);
|
||||
updateGameStateAndBalance(game);
|
||||
|
||||
if (game.getState() == BlackJackState.IN_PROGRESS) {
|
||||
return stand(game);
|
||||
}
|
||||
|
||||
return game;
|
||||
}
|
||||
|
||||
private BlackJackGameEntity refreshGameState(BlackJackGameEntity game) {
|
||||
return blackJackGameRepository.findById(game.getId()).orElse(game);
|
||||
}
|
||||
|
||||
private UserEntity getUserWithFreshData(UserEntity user) {
|
||||
return userRepository.findById(user.getId()).orElse(user);
|
||||
}
|
||||
|
||||
private void dealInitialCards(BlackJackGameEntity game) {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
dealCardToPlayer(game);
|
||||
}
|
||||
|
||||
dealCardToDealer(game);
|
||||
}
|
||||
|
||||
private void dealCardToPlayer(BlackJackGameEntity game) {
|
||||
CardEntity card = drawCardFromDeck(game);
|
||||
card.setCardType(CardType.PLAYER);
|
||||
game.getPlayerCards().add(card);
|
||||
}
|
||||
|
||||
private void dealCardToDealer(BlackJackGameEntity game) {
|
||||
CardEntity card = drawCardFromDeck(game);
|
||||
card.setCardType(CardType.DEALER);
|
||||
game.getDealerCards().add(card);
|
||||
}
|
||||
|
||||
private void dealCardsToDealerUntilMinimumScore(BlackJackGameEntity game) {
|
||||
while (calculateHandValue(game.getDealerCards()) < 17) {
|
||||
dealCardToDealer(game);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateGameStateAndBalance(BlackJackGameEntity game) {
|
||||
game.setState(getState(game));
|
||||
|
||||
if (game.getState() == BlackJackState.PLAYER_WON) {
|
||||
updateUserBalance(game, true);
|
||||
} else if (game.getState() == BlackJackState.PLAYER_LOST) {
|
||||
updateUserBalance(game, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void determineWinnerAndUpdateBalance(BlackJackGameEntity game) {
|
||||
int playerValue = calculateHandValue(game.getPlayerCards());
|
||||
int dealerValue = calculateHandValue(game.getDealerCards());
|
||||
|
||||
if (dealerValue > 21 || playerValue > dealerValue) {
|
||||
game.setState(BlackJackState.PLAYER_WON);
|
||||
updateUserBalance(game, true);
|
||||
} else if (playerValue < dealerValue) {
|
||||
game.setState(BlackJackState.PLAYER_LOST);
|
||||
updateUserBalance(game, false);
|
||||
} else {
|
||||
game.setState(BlackJackState.DRAW);
|
||||
updateUserBalance(game, false);
|
||||
updateUserBalance(game, false); // For draw, player gets their bet back
|
||||
}
|
||||
|
||||
return blackJackGameRepository.save(game);
|
||||
}
|
||||
|
||||
private void deductBetFromBalance(UserEntity user, BigDecimal betAmount) {
|
||||
user.setBalance(user.getBalance().subtract(betAmount));
|
||||
userRepository.save(user);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
private void updateUserBalance(BlackJackGameEntity game, boolean isWin) {
|
||||
UserEntity user = game.getUser();
|
||||
user = userRepository.findById(user.getId()).orElse(user);
|
||||
BigDecimal balance = user.getBalance();
|
||||
|
||||
UserEntity user = getUserWithFreshData(game.getUser());
|
||||
BigDecimal betAmount = game.getBet();
|
||||
BigDecimal balance = user.getBalance();
|
||||
|
||||
if (isWin) {
|
||||
balance = balance.add(betAmount.multiply(BigDecimal.valueOf(2)));
|
||||
}
|
||||
else if (game.getState() == BlackJackState.DRAW) {
|
||||
} else if (game.getState() == BlackJackState.DRAW) {
|
||||
balance = balance.add(betAmount);
|
||||
}
|
||||
|
||||
|
@ -144,7 +200,7 @@ public class BlackJackService {
|
|||
return game.getDeck().removeFirst();
|
||||
}
|
||||
|
||||
private BlackJackState handleState(BlackJackGameEntity game, UserEntity user) {
|
||||
private BlackJackState getState(BlackJackGameEntity game) {
|
||||
int playerHandValue = calculateHandValue(game.getPlayerCards());
|
||||
|
||||
if (playerHandValue == 21) {
|
||||
|
@ -155,14 +211,14 @@ public class BlackJackService {
|
|||
int dealerHandValue = calculateHandValue(game.getDealerCards());
|
||||
|
||||
if (dealerHandValue == 21) {
|
||||
return BlackJackState.STANDOFF;
|
||||
return BlackJackState.DRAW;
|
||||
} else {
|
||||
BigDecimal blackjackWinnings = game.getBet().multiply(new BigDecimal("1.5"));
|
||||
UserEntity user = getUserWithFreshData(game.getUser());
|
||||
user.setBalance(user.getBalance().add(blackjackWinnings));
|
||||
return BlackJackState.PLAYER_BLACKJACK;
|
||||
}
|
||||
} else if (playerHandValue > 21) {
|
||||
user.setBalance(user.getBalance().subtract(game.getBet()));
|
||||
return BlackJackState.PLAYER_LOST;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue