feat: implement slots api route
This commit is contained in:
		
					parent
					
						
							
								934e60e80d
							
						
					
				
			
			
				commit
				
					
						7a0dd0593b
					
				
			
		
					 10 changed files with 326 additions and 42 deletions
				
			
		| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
package de.szut.casino.blackjack;
 | 
					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.UserEntity;
 | 
				
			||||||
import de.szut.casino.user.UserService;
 | 
					import de.szut.casino.user.UserService;
 | 
				
			||||||
import jakarta.validation.Valid;
 | 
					import jakarta.validation.Valid;
 | 
				
			||||||
| 
						 | 
					@ -9,19 +10,18 @@ import org.springframework.http.ResponseEntity;
 | 
				
			||||||
import org.springframework.web.bind.annotation.*;
 | 
					import org.springframework.web.bind.annotation.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.math.BigDecimal;
 | 
					import java.math.BigDecimal;
 | 
				
			||||||
import java.util.HashMap;
 | 
					import java.util.*;
 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
import java.util.Objects;
 | 
					 | 
				
			||||||
import java.util.Optional;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Slf4j
 | 
					@Slf4j
 | 
				
			||||||
@RestController
 | 
					@RestController
 | 
				
			||||||
public class BlackJackGameController {
 | 
					public class BlackJackGameController {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final BalanceService balanceService;
 | 
				
			||||||
    private final UserService userService;
 | 
					    private final UserService userService;
 | 
				
			||||||
    private final BlackJackService blackJackService;
 | 
					    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.blackJackService = blackJackService;
 | 
				
			||||||
        this.userService = userService;
 | 
					        this.userService = userService;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -112,7 +112,7 @@ public class BlackJackGameController {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @PostMapping("/blackjack/start")
 | 
					    @PostMapping("/blackjack/start")
 | 
				
			||||||
    public ResponseEntity<Object> createBlackJackGame(@RequestBody @Valid CreateBlackJackGameDto createBlackJackGameDto, @RequestHeader("Authorization") String token) {
 | 
					    public ResponseEntity<Object> createBlackJackGame(@RequestBody @Valid BetDto betDto, @RequestHeader("Authorization") String token) {
 | 
				
			||||||
        Optional<UserEntity> optionalUser = userService.getCurrentUser(token);
 | 
					        Optional<UserEntity> optionalUser = userService.getCurrentUser(token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (optionalUser.isEmpty()) {
 | 
					        if (optionalUser.isEmpty()) {
 | 
				
			||||||
| 
						 | 
					@ -120,21 +120,11 @@ public class BlackJackGameController {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        UserEntity user = optionalUser.get();
 | 
					        UserEntity user = optionalUser.get();
 | 
				
			||||||
        BigDecimal balance = user.getBalance();
 | 
					 | 
				
			||||||
        BigDecimal betAmount = createBlackJackGameDto.getBetAmount();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (betAmount.compareTo(BigDecimal.ZERO) <= 0) {
 | 
					        if (!this.balanceService.hasFunds(user, betDto)) {
 | 
				
			||||||
            Map<String, String> errorResponse = new HashMap<>();
 | 
					            return ResponseEntity.badRequest().body(Collections.singletonMap("error", "Insufficient funds"));
 | 
				
			||||||
            errorResponse.put("error", "Invalid bet amount");
 | 
					 | 
				
			||||||
            return ResponseEntity.badRequest().body(errorResponse);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (betAmount.compareTo(balance) > 0) {
 | 
					        return ResponseEntity.ok(blackJackService.createBlackJackGame(user, betDto.getBetAmount()));
 | 
				
			||||||
            Map<String, String> errorResponse = new HashMap<>();
 | 
					 | 
				
			||||||
            errorResponse.put("error", "Insufficient funds");
 | 
					 | 
				
			||||||
            return ResponseEntity.badRequest().body(errorResponse);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return ResponseEntity.ok(blackJackService.createBlackJackGame(user, betAmount));
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,8 @@ import de.szut.casino.user.UserEntity;
 | 
				
			||||||
import de.szut.casino.user.UserRepository;
 | 
					import de.szut.casino.user.UserRepository;
 | 
				
			||||||
import org.springframework.stereotype.Service;
 | 
					import org.springframework.stereotype.Service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.math.BigDecimal;
 | 
				
			||||||
 | 
					import java.util.Objects;
 | 
				
			||||||
import java.util.Optional;
 | 
					import java.util.Optional;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Service
 | 
					@Service
 | 
				
			||||||
| 
						 | 
					@ -54,7 +56,7 @@ public class TransactionService {
 | 
				
			||||||
        UserEntity user = transaction.getUser();
 | 
					        UserEntity user = transaction.getUser();
 | 
				
			||||||
        Long amountTotal = checkoutSession.getAmountTotal();
 | 
					        Long amountTotal = checkoutSession.getAmountTotal();
 | 
				
			||||||
        if (amountTotal != null) {
 | 
					        if (amountTotal != null) {
 | 
				
			||||||
            user.addBalance(amountTotal);
 | 
					            user.addBalance(BigDecimal.valueOf(amountTotal).movePointLeft(2));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        userRepository.save(user);
 | 
					        userRepository.save(user);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										18
									
								
								backend/src/main/java/de/szut/casino/shared/dto/BetDto.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								backend/src/main/java/de/szut/casino/shared/dto/BetDto.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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<Object> spinSlots(@RequestBody @Valid BetDto betDto, @RequestHeader("Authorization") String token) {
 | 
				
			||||||
 | 
					        Optional<UserEntity> 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);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										127
									
								
								backend/src/main/java/de/szut/casino/slots/SlotService.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								backend/src/main/java/de/szut/casino/slots/SlotService.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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<Symbol> FIRST_REEL = new ArrayList<>(REEL_LENGTH);
 | 
				
			||||||
 | 
					    private final List<Symbol> SECOND_REEL = new ArrayList<>(REEL_LENGTH);
 | 
				
			||||||
 | 
					    private final List<Symbol> 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<List<Symbol>> 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<Symbol> 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<Symbol> reel, int index) {
 | 
				
			||||||
 | 
					        int effectiveIndex = index % REEL_LENGTH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (effectiveIndex < 0) {
 | 
				
			||||||
 | 
					            effectiveIndex += REEL_LENGTH;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return reel.get(effectiveIndex);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										24
									
								
								backend/src/main/java/de/szut/casino/slots/SpinResult.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								backend/src/main/java/de/szut/casino/slots/SpinResult.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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<List<Symbol>> resultMatrix;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										35
									
								
								backend/src/main/java/de/szut/casino/slots/Symbol.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								backend/src/main/java/de/szut/casino/slots/Symbol.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -31,13 +31,31 @@ public class UserEntity {
 | 
				
			||||||
        this.balance = balance;
 | 
					        this.balance = balance;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void addBalance(long amountInCents) {
 | 
					    public void addBalance(BigDecimal amountToAdd) {
 | 
				
			||||||
        BigDecimal amountToAdd = BigDecimal.valueOf(amountInCents).movePointLeft(2);
 | 
					        if (amountToAdd == null || amountToAdd.compareTo(BigDecimal.ZERO) <= 0) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.balance == null) {
 | 
					        if (this.balance == null) {
 | 
				
			||||||
            this.balance = amountToAdd;
 | 
					            this.balance = BigDecimal.ZERO;
 | 
				
			||||||
        } 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);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Reference in a new issue