From 7a0dd0593b3f0629c82171ab8a09ebab9c30c713 Mon Sep 17 00:00:00 2001 From: Phan Huy Tran Date: Thu, 24 Apr 2025 11:00:32 +0200 Subject: [PATCH 1/5] feat: implement slots api route --- .../blackjack/BlackJackGameController.java | 30 ++--- .../blackjack/dto/CreateBlackJackGameDto.java | 16 --- .../casino/deposit/TransactionService.java | 4 +- .../de/szut/casino/shared/dto/BetDto.java | 18 +++ .../casino/shared/service/BalanceService.java | 36 +++++ .../de/szut/casino/slots/SlotController.java | 50 +++++++ .../de/szut/casino/slots/SlotService.java | 127 ++++++++++++++++++ .../java/de/szut/casino/slots/SpinResult.java | 24 ++++ .../java/de/szut/casino/slots/Symbol.java | 35 +++++ .../java/de/szut/casino/user/UserEntity.java | 28 +++- 10 files changed, 326 insertions(+), 42 deletions(-) delete mode 100644 backend/src/main/java/de/szut/casino/blackjack/dto/CreateBlackJackGameDto.java create mode 100644 backend/src/main/java/de/szut/casino/shared/dto/BetDto.java create mode 100644 backend/src/main/java/de/szut/casino/shared/service/BalanceService.java create mode 100644 backend/src/main/java/de/szut/casino/slots/SlotController.java create mode 100644 backend/src/main/java/de/szut/casino/slots/SlotService.java create mode 100644 backend/src/main/java/de/szut/casino/slots/SpinResult.java create mode 100644 backend/src/main/java/de/szut/casino/slots/Symbol.java 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 c89f3ef..c9d5c26 100644 --- a/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java +++ b/backend/src/main/java/de/szut/casino/blackjack/BlackJackGameController.java @@ -1,6 +1,7 @@ package de.szut.casino.blackjack; -import de.szut.casino.blackjack.dto.CreateBlackJackGameDto; +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; @@ -9,19 +10,18 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.math.BigDecimal; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; +import java.util.*; @Slf4j @RestController public class BlackJackGameController { + private final BalanceService balanceService; private final UserService userService; private final BlackJackService blackJackService; - public BlackJackGameController(UserService userService, BlackJackService blackJackService) { + public BlackJackGameController(BalanceService balanceService, UserService userService, BlackJackService blackJackService) { + this.balanceService = balanceService; this.blackJackService = blackJackService; this.userService = userService; } @@ -112,7 +112,7 @@ public class BlackJackGameController { } @PostMapping("/blackjack/start") - public ResponseEntity createBlackJackGame(@RequestBody @Valid CreateBlackJackGameDto createBlackJackGameDto, @RequestHeader("Authorization") String token) { + public ResponseEntity createBlackJackGame(@RequestBody @Valid BetDto betDto, @RequestHeader("Authorization") String token) { Optional optionalUser = userService.getCurrentUser(token); if (optionalUser.isEmpty()) { @@ -120,21 +120,11 @@ public class BlackJackGameController { } UserEntity user = optionalUser.get(); - BigDecimal balance = user.getBalance(); - BigDecimal betAmount = createBlackJackGameDto.getBetAmount(); - if (betAmount.compareTo(BigDecimal.ZERO) <= 0) { - Map errorResponse = new HashMap<>(); - errorResponse.put("error", "Invalid bet amount"); - return ResponseEntity.badRequest().body(errorResponse); + if (!this.balanceService.hasFunds(user, betDto)) { + return ResponseEntity.badRequest().body(Collections.singletonMap("error", "Insufficient funds")); } - 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)); + return ResponseEntity.ok(blackJackService.createBlackJackGame(user, betDto.getBetAmount())); } } 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 deleted file mode 100644 index e5b0c97..0000000 --- a/backend/src/main/java/de/szut/casino/blackjack/dto/CreateBlackJackGameDto.java +++ /dev/null @@ -1,16 +0,0 @@ -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 2cfc19e..7a7c48e 100644 --- a/backend/src/main/java/de/szut/casino/deposit/TransactionService.java +++ b/backend/src/main/java/de/szut/casino/deposit/TransactionService.java @@ -7,6 +7,8 @@ import de.szut.casino.user.UserEntity; import de.szut.casino.user.UserRepository; import org.springframework.stereotype.Service; +import java.math.BigDecimal; +import java.util.Objects; import java.util.Optional; @Service @@ -54,7 +56,7 @@ public class TransactionService { UserEntity user = transaction.getUser(); Long amountTotal = checkoutSession.getAmountTotal(); if (amountTotal != null) { - user.addBalance(amountTotal); + user.addBalance(BigDecimal.valueOf(amountTotal).movePointLeft(2)); } 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 new file mode 100644 index 0000000..a910a03 --- /dev/null +++ b/backend/src/main/java/de/szut/casino/shared/dto/BetDto.java @@ -0,0 +1,18 @@ +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 new file mode 100644 index 0000000..40e6caa --- /dev/null +++ b/backend/src/main/java/de/szut/casino/shared/service/BalanceService.java @@ -0,0 +1,36 @@ +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 new file mode 100644 index 0000000..5d11430 --- /dev/null +++ b/backend/src/main/java/de/szut/casino/slots/SlotController.java @@ -0,0 +1,50 @@ +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.handleSpinResult( + betDto.getBetAmount(), + user + ); + + return ResponseEntity.ok(spinResult); + } +} \ No newline at end of file diff --git a/backend/src/main/java/de/szut/casino/slots/SlotService.java b/backend/src/main/java/de/szut/casino/slots/SlotService.java new file mode 100644 index 0000000..cd5a814 --- /dev/null +++ b/backend/src/main/java/de/szut/casino/slots/SlotService.java @@ -0,0 +1,127 @@ +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 = 60; + private static final int SEVEN_COUNT = 4; + private static final int BAR_COUNT = 20; + private static final int CHERRY_COUNT = 36; + + private final List FIRST_REEL = new ArrayList<>(REEL_LENGTH); + private final List SECOND_REEL = new ArrayList<>(REEL_LENGTH); + private final List THIRD_REEL = new ArrayList<>(REEL_LENGTH); + + private final BalanceService balanceService; + + public SlotService(BalanceService balanceService) { + this.balanceService = balanceService; + + initReels(); + } + + public SpinResult handleSpinResult( + BigDecimal betAmount, + UserEntity user + ) { + Random random = new Random(); + + int index1 = random.nextInt(REEL_LENGTH); + int index2 = random.nextInt(REEL_LENGTH); + int index3 = random.nextInt(REEL_LENGTH); + + Symbol symbol1 = FIRST_REEL.get(index1); + Symbol symbol2 = SECOND_REEL.get(index2); + Symbol symbol3 = THIRD_REEL.get(index3); + + boolean isWin = symbol1.equals(symbol2) && symbol1.equals(symbol3); + + SpinResult spinResult = new SpinResult(); + + if (isWin) { + BigDecimal winAmount = betAmount.multiply(symbol1.getPayoutMultiplier()); + this.balanceService.addFunds(user, winAmount); + + spinResult.setStatus("win"); + spinResult.setAmount(winAmount); + spinResult.setWin(true); + } else { + this.balanceService.subtractFunds(user, betAmount); + + spinResult.setStatus("lose"); + spinResult.setAmount(betAmount); + spinResult.setWin(false); + } + + buildResultMatrix(spinResult, index1, index2, index3); + + return spinResult; + } + + public 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.get(0).add(getSymbolAt(FIRST_REEL, index1 - 1)); + resultMatrix.get(1).add(getSymbolAt(FIRST_REEL, index1)); + resultMatrix.get(2).add(getSymbolAt(FIRST_REEL, index1 + 1)); + + resultMatrix.get(0).add(getSymbolAt(SECOND_REEL, index2 - 1)); + resultMatrix.get(1).add(getSymbolAt(SECOND_REEL, index2)); + resultMatrix.get(2).add(getSymbolAt(SECOND_REEL, index2 + 1)); + + resultMatrix.get(0).add(getSymbolAt(THIRD_REEL, index3 - 1)); + resultMatrix.get(1).add(getSymbolAt(THIRD_REEL, index3)); + resultMatrix.get(2).add(getSymbolAt(THIRD_REEL, index3 + 1)); + + spinResult.setResultMatrix(resultMatrix); + } + + private void initReels() { + List reelStrip = new ArrayList<>(REEL_LENGTH); + + for (int i = 0; i < CHERRY_COUNT; i++) { + Symbol CHERRY = new Symbol("cherry", new BigDecimal(5)); + reelStrip.add(CHERRY); + } + + for (int i = 0; i < BAR_COUNT; i++) { + Symbol BAR = new Symbol("bar", new BigDecimal(10)); + reelStrip.add(BAR); + } + + for (int i = 0; i < SEVEN_COUNT; i++) { + Symbol SEVEN = new Symbol("seven", new BigDecimal(85)); + reelStrip.add(SEVEN); + } + + FIRST_REEL.addAll(reelStrip); + SECOND_REEL.addAll(reelStrip); + THIRD_REEL.addAll(reelStrip); + + Collections.shuffle(FIRST_REEL); + Collections.shuffle(SECOND_REEL); + Collections.shuffle(THIRD_REEL); + } + + 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 new file mode 100644 index 0000000..6263e9b --- /dev/null +++ b/backend/src/main/java/de/szut/casino/slots/SpinResult.java @@ -0,0 +1,24 @@ +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 new file mode 100644 index 0000000..806d14b --- /dev/null +++ b/backend/src/main/java/de/szut/casino/slots/Symbol.java @@ -0,0 +1,35 @@ +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 67fc1ae..03f4a34 100644 --- a/backend/src/main/java/de/szut/casino/user/UserEntity.java +++ b/backend/src/main/java/de/szut/casino/user/UserEntity.java @@ -31,13 +31,31 @@ public class UserEntity { this.balance = balance; } - public void addBalance(long amountInCents) { - BigDecimal amountToAdd = BigDecimal.valueOf(amountInCents).movePointLeft(2); + public void addBalance(BigDecimal amountToAdd) { + if (amountToAdd == null || amountToAdd.compareTo(BigDecimal.ZERO) <= 0) { + return; + } if (this.balance == null) { - this.balance = amountToAdd; - } else { - this.balance = this.balance.add(amountToAdd); + this.balance = BigDecimal.ZERO; } + + 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); } } -- 2.47.2 From a26aeab86ab417f002699a8195f19daac7809bcf Mon Sep 17 00:00:00 2001 From: Phan Huy Tran Date: Thu, 24 Apr 2025 12:04:26 +0200 Subject: [PATCH 2/5] feat: refactor and balance winnings --- .../de/szut/casino/slots/SlotController.java | 2 +- .../de/szut/casino/slots/SlotService.java | 149 ++++++++++-------- 2 files changed, 81 insertions(+), 70 deletions(-) diff --git a/backend/src/main/java/de/szut/casino/slots/SlotController.java b/backend/src/main/java/de/szut/casino/slots/SlotController.java index 5d11430..59f3135 100644 --- a/backend/src/main/java/de/szut/casino/slots/SlotController.java +++ b/backend/src/main/java/de/szut/casino/slots/SlotController.java @@ -40,7 +40,7 @@ public class SlotController { return ResponseEntity.badRequest().body(Collections.singletonMap("error", "Insufficient funds")); } - SpinResult spinResult = this.slotService.handleSpinResult( + SpinResult spinResult = this.slotService.spin( betDto.getBetAmount(), user ); diff --git a/backend/src/main/java/de/szut/casino/slots/SlotService.java b/backend/src/main/java/de/szut/casino/slots/SlotService.java index cd5a814..0bc543f 100644 --- a/backend/src/main/java/de/szut/casino/slots/SlotService.java +++ b/backend/src/main/java/de/szut/casino/slots/SlotService.java @@ -12,107 +12,118 @@ import java.util.Random; @Service public class SlotService { - private final int REEL_LENGTH = 60; - private static final int SEVEN_COUNT = 4; - private static final int BAR_COUNT = 20; - private static final int CHERRY_COUNT = 36; + private final int REEL_LENGTH = 32; - private final List FIRST_REEL = new ArrayList<>(REEL_LENGTH); - private final List SECOND_REEL = new ArrayList<>(REEL_LENGTH); - private final List THIRD_REEL = new ArrayList<>(REEL_LENGTH); + private final int SEVEN_COUNT = 1; + private final int BAR_COUNT = 4; + private final int BELL_COUNT = 7; + private final int CHERRY_COUNT = 11; + private final int BLANK_COUNT = 9; + 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; - initReels(); + List reelStrip = createReelStrip(); + this.firstReel = shuffleReel(reelStrip); + this.secondReel = shuffleReel(reelStrip); + this.thirdReel = shuffleReel(reelStrip); } - public SpinResult handleSpinResult( - BigDecimal betAmount, - UserEntity user - ) { - Random random = new Random(); + 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); - int index1 = random.nextInt(REEL_LENGTH); - int index2 = random.nextInt(REEL_LENGTH); - int index3 = random.nextInt(REEL_LENGTH); - - Symbol symbol1 = FIRST_REEL.get(index1); - Symbol symbol2 = SECOND_REEL.get(index2); - Symbol symbol3 = THIRD_REEL.get(index3); + 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 = new SpinResult(); - - if (isWin) { - BigDecimal winAmount = betAmount.multiply(symbol1.getPayoutMultiplier()); - this.balanceService.addFunds(user, winAmount); - - spinResult.setStatus("win"); - spinResult.setAmount(winAmount); - spinResult.setWin(true); - } else { - this.balanceService.subtractFunds(user, betAmount); - - spinResult.setStatus("lose"); - spinResult.setAmount(betAmount); - spinResult.setWin(false); - } - + SpinResult spinResult = processResult(betAmount, user, isWin, symbol1); buildResultMatrix(spinResult, index1, index2, index3); return spinResult; } - public void buildResultMatrix(SpinResult spinResult, int index1, int index2, int index3) { + 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.get(0).add(getSymbolAt(FIRST_REEL, index1 - 1)); - resultMatrix.get(1).add(getSymbolAt(FIRST_REEL, index1)); - resultMatrix.get(2).add(getSymbolAt(FIRST_REEL, index1 + 1)); + 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(0).add(getSymbolAt(SECOND_REEL, index2 - 1)); - resultMatrix.get(1).add(getSymbolAt(SECOND_REEL, index2)); - resultMatrix.get(2).add(getSymbolAt(SECOND_REEL, index2 + 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.get(0).add(getSymbolAt(THIRD_REEL, index3 - 1)); - resultMatrix.get(1).add(getSymbolAt(THIRD_REEL, index3)); - resultMatrix.get(2).add(getSymbolAt(THIRD_REEL, index3 + 1)); + 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 void initReels() { + 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; + } - for (int i = 0; i < CHERRY_COUNT; i++) { - Symbol CHERRY = new Symbol("cherry", new BigDecimal(5)); - reelStrip.add(CHERRY); + private void addSymbolsToStrip(List strip, Symbol symbol, int count) { + for (int i = 0; i < count; i++) { + strip.add(symbol); } - - for (int i = 0; i < BAR_COUNT; i++) { - Symbol BAR = new Symbol("bar", new BigDecimal(10)); - reelStrip.add(BAR); - } - - for (int i = 0; i < SEVEN_COUNT; i++) { - Symbol SEVEN = new Symbol("seven", new BigDecimal(85)); - reelStrip.add(SEVEN); - } - - FIRST_REEL.addAll(reelStrip); - SECOND_REEL.addAll(reelStrip); - THIRD_REEL.addAll(reelStrip); - - Collections.shuffle(FIRST_REEL); - Collections.shuffle(SECOND_REEL); - Collections.shuffle(THIRD_REEL); } private Symbol getSymbolAt(List reel, int index) { -- 2.47.2 From 29732e63b95063fcfea5e5a36e13bb9010736bab Mon Sep 17 00:00:00 2001 From: Phan Huy Tran Date: Thu, 24 Apr 2025 12:06:55 +0200 Subject: [PATCH 3/5] refactor: balance in favor of the house --- backend/src/main/java/de/szut/casino/slots/SlotService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/de/szut/casino/slots/SlotService.java b/backend/src/main/java/de/szut/casino/slots/SlotService.java index 0bc543f..39ebeab 100644 --- a/backend/src/main/java/de/szut/casino/slots/SlotService.java +++ b/backend/src/main/java/de/szut/casino/slots/SlotService.java @@ -14,11 +14,12 @@ import java.util.Random; 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 = 11; - private final int BLANK_COUNT = 9; + 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")); -- 2.47.2 From c93c386469b80465b6aacd92a3a59811a63f2902 Mon Sep 17 00:00:00 2001 From: Phan Huy Tran Date: Thu, 24 Apr 2025 12:09:52 +0200 Subject: [PATCH 4/5] style: bruh --- backend/src/main/java/de/szut/casino/slots/SlotController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/de/szut/casino/slots/SlotController.java b/backend/src/main/java/de/szut/casino/slots/SlotController.java index 59f3135..8f98b1d 100644 --- a/backend/src/main/java/de/szut/casino/slots/SlotController.java +++ b/backend/src/main/java/de/szut/casino/slots/SlotController.java @@ -47,4 +47,4 @@ public class SlotController { return ResponseEntity.ok(spinResult); } -} \ No newline at end of file +} -- 2.47.2 From f01f6f6477c456fb77350dfbf30191850d9e1618 Mon Sep 17 00:00:00 2001 From: Phan Huy Tran Date: Thu, 24 Apr 2025 12:14:02 +0200 Subject: [PATCH 5/5] chore: rebase --- .../src/main/java/de/szut/casino/deposit/TransactionService.java | 1 - 1 file changed, 1 deletion(-) 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 7a7c48e..fceb27b 100644 --- a/backend/src/main/java/de/szut/casino/deposit/TransactionService.java +++ b/backend/src/main/java/de/szut/casino/deposit/TransactionService.java @@ -8,7 +8,6 @@ import de.szut.casino.user.UserRepository; import org.springframework.stereotype.Service; import java.math.BigDecimal; -import java.util.Objects; import java.util.Optional; @Service -- 2.47.2