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 c9d5c26..c89f3ef 100644 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java +++ b/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java @@ -1,7 +1,6 @@ package de.szut.casino.blackjack; -import de.szut.casino.shared.dto.BetDto; -import de.szut.casino.shared.service.BalanceService; +import de.szut.casino.blackjack.dto.CreateBlackJackGameDto; import de.szut.casino.user.UserEntity; import de.szut.casino.user.UserService; import jakarta.validation.Valid; @@ -10,18 +9,19 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.math.BigDecimal; -import java.util.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; @Slf4j @RestController public class BlackJackGameController { - private final BalanceService balanceService; private final UserService userService; private final BlackJackService blackJackService; - public BlackJackGameController(BalanceService balanceService, UserService userService, BlackJackService blackJackService) { - this.balanceService = balanceService; + public BlackJackGameController(UserService userService, BlackJackService blackJackService) { this.blackJackService = blackJackService; this.userService = userService; } @@ -112,7 +112,7 @@ public class BlackJackGameController { } @PostMapping("/blackjack/start") - public ResponseEntity createBlackJackGame(@RequestBody @Valid BetDto betDto, @RequestHeader("Authorization") String token) { + public ResponseEntity createBlackJackGame(@RequestBody @Valid CreateBlackJackGameDto createBlackJackGameDto, @RequestHeader("Authorization") String token) { Optional optionalUser = userService.getCurrentUser(token); if (optionalUser.isEmpty()) { @@ -120,11 +120,21 @@ public class BlackJackGameController { } UserEntity user = optionalUser.get(); + BigDecimal balance = user.getBalance(); + BigDecimal betAmount = createBlackJackGameDto.getBetAmount(); - if (!this.balanceService.hasFunds(user, betDto)) { - return ResponseEntity.badRequest().body(Collections.singletonMap("error", "Insufficient funds")); + if (betAmount.compareTo(BigDecimal.ZERO) <= 0) { + Map errorResponse = new HashMap<>(); + errorResponse.put("error", "Invalid bet amount"); + return ResponseEntity.badRequest().body(errorResponse); } - return ResponseEntity.ok(blackJackService.createBlackJackGame(user, betDto.getBetAmount())); + if (betAmount.compareTo(balance) > 0) { + Map errorResponse = new HashMap<>(); + errorResponse.put("error", "Insufficient funds"); + return ResponseEntity.badRequest().body(errorResponse); + } + + return ResponseEntity.ok(blackJackService.createBlackJackGame(user, betAmount)); } } diff --git a/backend/src/main/java/de/szut/casino/blackjack/dto/CreateBlackJackGameDto.java b/backend/src/main/java/de/szut/casino/blackjack/dto/CreateBlackJackGameDto.java new file mode 100644 index 0000000..e5b0c97 --- /dev/null +++ b/backend/src/main/java/de/szut/casino/blackjack/dto/CreateBlackJackGameDto.java @@ -0,0 +1,16 @@ +package de.szut.casino.blackjack.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.math.BigDecimal; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class CreateBlackJackGameDto { + private BigDecimal betAmount; +} diff --git a/backend/src/main/java/de/szut/casino/deposit/TransactionService.java b/backend/src/main/java/de/szut/casino/deposit/TransactionService.java index fceb27b..2cfc19e 100644 --- a/backend/src/main/java/de/szut/casino/deposit/TransactionService.java +++ b/backend/src/main/java/de/szut/casino/deposit/TransactionService.java @@ -7,7 +7,6 @@ import de.szut.casino.user.UserEntity; import de.szut.casino.user.UserRepository; import org.springframework.stereotype.Service; -import java.math.BigDecimal; import java.util.Optional; @Service @@ -55,7 +54,7 @@ public class TransactionService { UserEntity user = transaction.getUser(); Long amountTotal = checkoutSession.getAmountTotal(); if (amountTotal != null) { - user.addBalance(BigDecimal.valueOf(amountTotal).movePointLeft(2)); + user.addBalance(amountTotal); } userRepository.save(user); diff --git a/backend/src/main/java/de/szut/casino/shared/dto/BetDto.java b/backend/src/main/java/de/szut/casino/shared/dto/BetDto.java deleted file mode 100644 index a910a03..0000000 --- a/backend/src/main/java/de/szut/casino/shared/dto/BetDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package de.szut.casino.shared.dto; - -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Positive; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; - -import java.math.BigDecimal; - -@Getter -@Setter -@AllArgsConstructor -public class BetDto { - @NotNull(message = "Bet amount cannot be null") - @Positive(message = "Bet amount must be positive") - private BigDecimal betAmount; -} diff --git a/backend/src/main/java/de/szut/casino/shared/service/BalanceService.java b/backend/src/main/java/de/szut/casino/shared/service/BalanceService.java deleted file mode 100644 index 40e6caa..0000000 --- a/backend/src/main/java/de/szut/casino/shared/service/BalanceService.java +++ /dev/null @@ -1,36 +0,0 @@ -package de.szut.casino.shared.service; - -import de.szut.casino.shared.dto.BetDto; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserRepository; -import org.springframework.stereotype.Service; - -import java.math.BigDecimal; - -@Service -public class BalanceService { - private UserRepository userRepository; - - public BalanceService(UserRepository userRepository) { - this.userRepository = userRepository; - } - - public boolean hasFunds(UserEntity user, BetDto betDto) { - BigDecimal balance = user.getBalance(); - BigDecimal betAmount = betDto.getBetAmount(); - - return betAmount.compareTo(balance) <= 0; - } - - public void addFunds(UserEntity user, BigDecimal amount) { - user.addBalance(amount); - - this.userRepository.save(user); - } - - public void subtractFunds(UserEntity user, BigDecimal amount) { - user.subtractBalance(amount); - - this.userRepository.save(user); - } -} diff --git a/backend/src/main/java/de/szut/casino/slots/SlotController.java b/backend/src/main/java/de/szut/casino/slots/SlotController.java deleted file mode 100644 index 8f98b1d..0000000 --- a/backend/src/main/java/de/szut/casino/slots/SlotController.java +++ /dev/null @@ -1,50 +0,0 @@ -package de.szut.casino.slots; - -import de.szut.casino.shared.dto.BetDto; -import de.szut.casino.shared.service.BalanceService; -import de.szut.casino.user.UserEntity; -import de.szut.casino.user.UserService; -import jakarta.validation.Valid; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RestController; - -import java.util.Collections; -import java.util.Optional; - -@RestController -public class SlotController { - private final UserService userService; - private final BalanceService balanceService; - private final SlotService slotService; - - public SlotController(UserService userService, BalanceService balanceService, SlotService slotService) { - this.userService = userService; - this.balanceService = balanceService; - this.slotService = slotService; - } - - @PostMapping("/slots/spin") - public ResponseEntity spinSlots(@RequestBody @Valid BetDto betDto, @RequestHeader("Authorization") String token) { - Optional optionalUser = userService.getCurrentUser(token); - - if (optionalUser.isEmpty()) { - return ResponseEntity.notFound().build(); - } - - UserEntity user = optionalUser.get(); - - if (!this.balanceService.hasFunds(user, betDto)) { - return ResponseEntity.badRequest().body(Collections.singletonMap("error", "Insufficient funds")); - } - - SpinResult spinResult = this.slotService.spin( - betDto.getBetAmount(), - user - ); - - return ResponseEntity.ok(spinResult); - } -} diff --git a/backend/src/main/java/de/szut/casino/slots/SlotService.java b/backend/src/main/java/de/szut/casino/slots/SlotService.java deleted file mode 100644 index 39ebeab..0000000 --- a/backend/src/main/java/de/szut/casino/slots/SlotService.java +++ /dev/null @@ -1,139 +0,0 @@ -package de.szut.casino.slots; - -import de.szut.casino.shared.service.BalanceService; -import de.szut.casino.user.UserEntity; -import org.springframework.stereotype.Service; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Random; - -@Service -public class SlotService { - private final int REEL_LENGTH = 32; - - // 98% RTP - private final int SEVEN_COUNT = 1; - private final int BAR_COUNT = 4; - private final int BELL_COUNT = 7; - private final int CHERRY_COUNT = 10; - private final int BLANK_COUNT = 10; - - private final Symbol SEVEN = new Symbol("seven", new BigDecimal("1000")); - private final Symbol BAR = new Symbol("bar", new BigDecimal("85")); - private final Symbol BELL = new Symbol("bell", new BigDecimal("40")); - private final Symbol CHERRY = new Symbol("cherry", new BigDecimal("10")); - private final Symbol BLANK = new Symbol("blank", new BigDecimal("0")); - - private final List firstReel; - private final List secondReel; - private final List thirdReel; - - private final Random random; - private final BalanceService balanceService; - - public SlotService(BalanceService balanceService) { - this.random = new Random(); - this.balanceService = balanceService; - - List reelStrip = createReelStrip(); - this.firstReel = shuffleReel(reelStrip); - this.secondReel = shuffleReel(reelStrip); - this.thirdReel = shuffleReel(reelStrip); - } - - public SpinResult spin(BigDecimal betAmount, UserEntity user) { - int index1 = this.random.nextInt(REEL_LENGTH); - int index2 = this.random.nextInt(REEL_LENGTH); - int index3 = this.random.nextInt(REEL_LENGTH); - - Symbol symbol1 = getSymbolAt(this.firstReel, index1); - Symbol symbol2 = getSymbolAt(this.secondReel, index2); - Symbol symbol3 = getSymbolAt(this.thirdReel, index3); - - boolean isWin = symbol1.equals(symbol2) && symbol1.equals(symbol3); - - SpinResult spinResult = processResult(betAmount, user, isWin, symbol1); - buildResultMatrix(spinResult, index1, index2, index3); - - return spinResult; - } - - private SpinResult processResult(BigDecimal betAmount, UserEntity user, boolean isWin, Symbol winSymbol) { - BigDecimal resultAmount; - String status; - - if (isWin) { - resultAmount = betAmount.multiply(winSymbol.getPayoutMultiplier()); - status = "win"; - this.balanceService.addFunds(user, resultAmount); - } else { - resultAmount = betAmount; - status = "lose"; - this.balanceService.subtractFunds(user, betAmount); - } - - SpinResult spinResult = new SpinResult(); - spinResult.setStatus(status); - spinResult.setAmount(resultAmount); - spinResult.setWin(isWin); - - return spinResult; - } - - private void buildResultMatrix(SpinResult spinResult, int index1, int index2, int index3) { - List> resultMatrix = new ArrayList<>(3); - - for (int i = 0; i < 3; i++) { - resultMatrix.add(new ArrayList<>(3)); - } - - resultMatrix.getFirst().add(getSymbolAt(this.firstReel, index1 - 1)); - resultMatrix.getFirst().add(getSymbolAt(this.secondReel, index2 - 1)); - resultMatrix.getFirst().add(getSymbolAt(this.thirdReel, index3 - 1)); - - resultMatrix.get(1).add(getSymbolAt(this.firstReel, index1)); - resultMatrix.get(1).add(getSymbolAt(this.secondReel, index2)); - resultMatrix.get(1).add(getSymbolAt(this.thirdReel, index3)); - - resultMatrix.getLast().add(getSymbolAt(this.firstReel, index1 + 1)); - resultMatrix.getLast().add(getSymbolAt(this.secondReel, index2 + 1)); - resultMatrix.getLast().add(getSymbolAt(this.thirdReel, index3 + 1)); - - spinResult.setResultMatrix(resultMatrix); - } - - private List shuffleReel(List reelStrip) { - Collections.shuffle(reelStrip, this.random); - - return reelStrip; - } - - private List createReelStrip() { - List reelStrip = new ArrayList<>(REEL_LENGTH); - addSymbolsToStrip(reelStrip, CHERRY, CHERRY_COUNT); - addSymbolsToStrip(reelStrip, BELL, BELL_COUNT); - addSymbolsToStrip(reelStrip, BAR, BAR_COUNT); - addSymbolsToStrip(reelStrip, SEVEN, SEVEN_COUNT); - addSymbolsToStrip(reelStrip, BLANK, BLANK_COUNT); - return reelStrip; - } - - private void addSymbolsToStrip(List strip, Symbol symbol, int count) { - for (int i = 0; i < count; i++) { - strip.add(symbol); - } - } - - private Symbol getSymbolAt(List reel, int index) { - int effectiveIndex = index % REEL_LENGTH; - - if (effectiveIndex < 0) { - effectiveIndex += REEL_LENGTH; - } - - return reel.get(effectiveIndex); - } -} diff --git a/backend/src/main/java/de/szut/casino/slots/SpinResult.java b/backend/src/main/java/de/szut/casino/slots/SpinResult.java deleted file mode 100644 index 6263e9b..0000000 --- a/backend/src/main/java/de/szut/casino/slots/SpinResult.java +++ /dev/null @@ -1,24 +0,0 @@ -package de.szut.casino.slots; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.math.BigDecimal; -import java.util.List; - -@Getter -@Setter -@NoArgsConstructor -public class SpinResult { - public SpinResult(String status, BigDecimal amount, boolean isWin) { - this.status = status; - this.amount = amount; - this.isWin = isWin; - } - - private String status; - private BigDecimal amount; - private boolean isWin; - private List> resultMatrix; -} diff --git a/backend/src/main/java/de/szut/casino/slots/Symbol.java b/backend/src/main/java/de/szut/casino/slots/Symbol.java deleted file mode 100644 index 806d14b..0000000 --- a/backend/src/main/java/de/szut/casino/slots/Symbol.java +++ /dev/null @@ -1,35 +0,0 @@ -package de.szut.casino.slots; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.math.BigDecimal; - -@Getter -@Setter -@AllArgsConstructor -public class Symbol { - private String name; - private BigDecimal payoutMultiplier; - - @Override - public boolean equals(Object other) { - if (!(other instanceof Symbol that)) { - return false; - } - - return this.name.equals(that.name) && this.payoutMultiplier.equals(that.payoutMultiplier); - } - - @Override - public int hashCode() { - int hashCode = 1; - - hashCode = hashCode * 37 + this.name.hashCode(); - hashCode = hashCode * 37 + this.payoutMultiplier.hashCode(); - - return hashCode; - } -} diff --git a/backend/src/main/java/de/szut/casino/user/UserEntity.java b/backend/src/main/java/de/szut/casino/user/UserEntity.java index 03f4a34..67fc1ae 100644 --- a/backend/src/main/java/de/szut/casino/user/UserEntity.java +++ b/backend/src/main/java/de/szut/casino/user/UserEntity.java @@ -31,31 +31,13 @@ public class UserEntity { this.balance = balance; } - public void addBalance(BigDecimal amountToAdd) { - if (amountToAdd == null || amountToAdd.compareTo(BigDecimal.ZERO) <= 0) { - return; - } + public void addBalance(long amountInCents) { + BigDecimal amountToAdd = BigDecimal.valueOf(amountInCents).movePointLeft(2); if (this.balance == null) { - this.balance = BigDecimal.ZERO; + this.balance = amountToAdd; + } else { + this.balance = this.balance.add(amountToAdd); } - - this.balance = this.balance.add(amountToAdd); - } - - public void subtractBalance(BigDecimal amountToSubtract) { - if (amountToSubtract == null || amountToSubtract.compareTo(BigDecimal.ZERO) <= 0) { - throw new IllegalArgumentException("Amount to subtract must be positive."); - } - - if (this.balance == null) { - this.balance = BigDecimal.ZERO; - } - - if (this.balance.compareTo(amountToSubtract) < 0) { - throw new IllegalStateException("Insufficient funds to subtract " + amountToSubtract); - } - - this.balance = this.balance.subtract(amountToSubtract); } }