@omnitronix/bonnys-fortune-game-engine 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/dist/__tests__/comprehensive.test.js +741 -0
  2. package/dist/__tests__/comprehensive.test.js.map +1 -0
  3. package/dist/bonnys-fortune-v1.game-engine.js +12 -7
  4. package/dist/bonnys-fortune-v1.game-engine.js.map +1 -1
  5. package/dist/domain/types/{cheat-trigger-bonus-command.js → debug-trigger-bonus-command.js} +1 -1
  6. package/dist/domain/types/debug-trigger-bonus-command.js.map +1 -0
  7. package/dist/domain/types/{cheat-trigger-bonus-request.dto.js → debug-trigger-bonus-request.dto.js} +1 -1
  8. package/dist/domain/types/debug-trigger-bonus-request.dto.js.map +1 -0
  9. package/dist/domain/types/{cheat-update-bonus-meter-progress-command.js → debug-update-bonus-meter-progress-command.js} +1 -1
  10. package/dist/domain/types/debug-update-bonus-meter-progress-command.js.map +1 -0
  11. package/dist/domain/types/{cheat-update-bonus-meter-progress-request.dto.js → debug-update-bonus-meter-progress-request.dto.js} +1 -1
  12. package/dist/domain/types/debug-update-bonus-meter-progress-request.dto.js.map +1 -0
  13. package/dist/logic/bonnys-fortune.game-logic.js +4 -2
  14. package/dist/logic/bonnys-fortune.game-logic.js.map +1 -1
  15. package/dist/rng/DummyRngClient.js +8 -1
  16. package/dist/rng/DummyRngClient.js.map +1 -1
  17. package/dist/rng/rng-client.factory.js +1 -2
  18. package/dist/rng/rng-client.factory.js.map +1 -1
  19. package/package.json +3 -4
  20. package/dist/__tests__/bonnys-fortune-v1.game-engine.test.d.ts +0 -1
  21. package/dist/bonnys-fortune-v1.game-engine.d.ts +0 -32
  22. package/dist/config/game-logic-config/file-system.game-logic-config-loader.d.ts +0 -4
  23. package/dist/config/game-logic-config/game-logic-config-loader.d.ts +0 -3
  24. package/dist/config/game-logic-config/game-logic-config.d.ts +0 -2
  25. package/dist/config/reel-strips-config/file-system.reel-strips-config-loader.d.ts +0 -4
  26. package/dist/config/reel-strips-config/reel-strip-option.dto.d.ts +0 -4
  27. package/dist/config/reel-strips-config/reel-strips-config-loader.d.ts +0 -3
  28. package/dist/config/reel-strips-config/reel-strips-config.dto.d.ts +0 -5
  29. package/dist/config/reel-strips-config/reel.dto.d.ts +0 -5
  30. package/dist/domain/game-round.types.d.ts +0 -9
  31. package/dist/domain/mappers/reel-strips-config.mapper.d.ts +0 -4
  32. package/dist/domain/reel-strip-option.d.ts +0 -7
  33. package/dist/domain/reel-strips-config.d.ts +0 -9
  34. package/dist/domain/reel.d.ts +0 -8
  35. package/dist/domain/types/cheat-trigger-bonus-command.d.ts +0 -5
  36. package/dist/domain/types/cheat-trigger-bonus-command.js.map +0 -1
  37. package/dist/domain/types/cheat-trigger-bonus-request.dto.d.ts +0 -5
  38. package/dist/domain/types/cheat-trigger-bonus-request.dto.js.map +0 -1
  39. package/dist/domain/types/cheat-update-bonus-meter-progress-command.d.ts +0 -5
  40. package/dist/domain/types/cheat-update-bonus-meter-progress-command.js.map +0 -1
  41. package/dist/domain/types/cheat-update-bonus-meter-progress-request.dto.d.ts +0 -5
  42. package/dist/domain/types/cheat-update-bonus-meter-progress-request.dto.js.map +0 -1
  43. package/dist/domain/types/game-spin-command.d.ts +0 -8
  44. package/dist/domain/types/game-spin-input.dto.d.ts +0 -8
  45. package/dist/domain/types/game-spin-output.dto.d.ts +0 -119
  46. package/dist/domain/types/game-symbols.response.dto.d.ts +0 -10
  47. package/dist/domain/types/reel-strip-option.dto.d.ts +0 -4
  48. package/dist/domain/types/reel-strips-config.dto.d.ts +0 -5
  49. package/dist/domain/types/reel.dto.d.ts +0 -5
  50. package/dist/domain/types/start-bonus-round-command.d.ts +0 -8
  51. package/dist/domain/types/start-bonus-round-input.dto.d.ts +0 -10
  52. package/dist/game-engine.interface.d.ts +0 -41
  53. package/dist/helpers/generate-hash.d.ts +0 -1
  54. package/dist/helpers/number-helper.d.ts +0 -23
  55. package/dist/helpers/optional-boolean-mapper.d.ts +0 -1
  56. package/dist/helpers/uuid-helper.d.ts +0 -3
  57. package/dist/helpers/validation-helper.d.ts +0 -14
  58. package/dist/index.d.ts +0 -2
  59. package/dist/logger/logger.d.ts +0 -22
  60. package/dist/logic/bonnys-fortune.game-logic.d.ts +0 -32
  61. package/dist/logic/bonnys-fortune.spin-generator.d.ts +0 -19
  62. package/dist/logic/bonnys-fortune.types.d.ts +0 -170
  63. package/dist/logic/bonnys-fortune.win-calculator.d.ts +0 -10
  64. package/dist/logic/game-logic-config.interface.d.ts +0 -178
  65. package/dist/logic/handlers/base-game.handler.d.ts +0 -15
  66. package/dist/logic/handlers/collect-feature-bonus.handler.d.ts +0 -13
  67. package/dist/logic/handlers/free-spins-bonus.handler.d.ts +0 -11
  68. package/dist/logic/handlers/steering-to-the-fortune-bonus.handler.d.ts +0 -11
  69. package/dist/logic/handlers/treasure-hunt-bonus.handler.d.ts +0 -15
  70. package/dist/rng/DummyRngClient.d.ts +0 -18
  71. package/dist/rng/rng-client.factory.d.ts +0 -7
  72. package/dist/rng/rng-client.interface.d.ts +0 -16
  73. package/dist/rng/rng-service.d.ts +0 -26
  74. package/dist/validation/abstract-game-logic-config.validator.d.ts +0 -4
  75. package/dist/validation/bonnys-fortune/bonnys-fortune-config.dto.d.ts +0 -129
  76. package/dist/validation/bonnys-fortune/bonnys-fortune-config.validator.d.ts +0 -5
  77. package/dist/validation/custom-decorators/IsNestedIntArray.d.ts +0 -2
  78. package/dist/validation/game-logic-config-validation.service.d.ts +0 -8
  79. package/dist/validation/reel-strips-config-validation.service.d.ts +0 -5
  80. package/src/__tests__/bonnys-fortune-v1.game-engine.test.ts +0 -80
  81. package/src/bonnys-fortune-v1.game-engine.ts +0 -285
  82. package/src/config/game-logic-config/file-system.game-logic-config-loader.ts +0 -27
  83. package/src/config/game-logic-config/game-logic-config-loader.ts +0 -3
  84. package/src/config/game-logic-config/game-logic-config.ts +0 -380
  85. package/src/config/reel-strips-config/file-system.reel-strips-config-loader.ts +0 -43
  86. package/src/config/reel-strips-config/reel-strip-option.dto.ts +0 -13
  87. package/src/config/reel-strips-config/reel-strips-config-loader.ts +0 -9
  88. package/src/config/reel-strips-config/reel-strips-config.dto.ts +0 -16
  89. package/src/config/reel-strips-config/reel.dto.ts +0 -16
  90. package/src/config/reel-strips-config/reels-BASE.csv +0 -52
  91. package/src/config/reel-strips-config/reels-BONUS.csv +0 -52
  92. package/src/domain/game-round.types.ts +0 -10
  93. package/src/domain/mappers/reel-strips-config.mapper.ts +0 -16
  94. package/src/domain/reel-strip-option.ts +0 -15
  95. package/src/domain/reel-strips-config.ts +0 -21
  96. package/src/domain/reel.ts +0 -17
  97. package/src/domain/types/cheat-trigger-bonus-command.ts +0 -5
  98. package/src/domain/types/cheat-trigger-bonus-request.dto.ts +0 -5
  99. package/src/domain/types/cheat-update-bonus-meter-progress-command.ts +0 -6
  100. package/src/domain/types/cheat-update-bonus-meter-progress-request.dto.ts +0 -5
  101. package/src/domain/types/game-spin-command.ts +0 -8
  102. package/src/domain/types/game-spin-input.dto.ts +0 -8
  103. package/src/domain/types/game-spin-output.dto.ts +0 -142
  104. package/src/domain/types/game-symbols.response.dto.ts +0 -11
  105. package/src/domain/types/reel-strip-option.dto.ts +0 -13
  106. package/src/domain/types/reel-strips-config.dto.ts +0 -15
  107. package/src/domain/types/reel.dto.ts +0 -15
  108. package/src/domain/types/start-bonus-round-command.ts +0 -8
  109. package/src/domain/types/start-bonus-round-input.dto.ts +0 -10
  110. package/src/game-engine.interface.ts +0 -59
  111. package/src/helpers/generate-hash.ts +0 -5
  112. package/src/helpers/number-helper.ts +0 -41
  113. package/src/helpers/optional-boolean-mapper.ts +0 -5
  114. package/src/helpers/uuid-helper.ts +0 -7
  115. package/src/helpers/validation-helper.ts +0 -27
  116. package/src/index.ts +0 -3
  117. package/src/logger/logger.ts +0 -178
  118. package/src/logic/bonnys-fortune.game-logic.ts +0 -480
  119. package/src/logic/bonnys-fortune.spin-generator.ts +0 -277
  120. package/src/logic/bonnys-fortune.types.ts +0 -223
  121. package/src/logic/bonnys-fortune.win-calculator.ts +0 -210
  122. package/src/logic/game-logic-config.interface.ts +0 -174
  123. package/src/logic/handlers/base-game.handler.ts +0 -213
  124. package/src/logic/handlers/collect-feature-bonus.handler.ts +0 -301
  125. package/src/logic/handlers/free-spins-bonus.handler.ts +0 -119
  126. package/src/logic/handlers/steering-to-the-fortune-bonus.handler.ts +0 -118
  127. package/src/logic/handlers/treasure-hunt-bonus.handler.ts +0 -232
  128. package/src/rng/DummyRngClient.ts +0 -108
  129. package/src/rng/rng-client.factory.ts +0 -27
  130. package/src/rng/rng-client.interface.ts +0 -38
  131. package/src/rng/rng-service.ts +0 -130
  132. package/src/validation/abstract-game-logic-config.validator.ts +0 -20
  133. package/src/validation/bonnys-fortune/bonnys-fortune-config.dto.ts +0 -371
  134. package/src/validation/bonnys-fortune/bonnys-fortune-config.validator.ts +0 -8
  135. package/src/validation/custom-decorators/IsNestedIntArray.ts +0 -29
  136. package/src/validation/game-logic-config-validation.service.ts +0 -28
  137. package/src/validation/reel-strips-config-validation.service.ts +0 -29
@@ -1,119 +0,0 @@
1
- import {
2
- BonnysFortunePrivateState,
3
- BonnysFortunePublicState,
4
- BonusRoundResult,
5
- FreeSpinResult,
6
- SpinResultResponse,
7
- SpinType,
8
- } from '../bonnys-fortune.types';
9
-
10
- import { BonnysFortuneGameLogicConfigInterface } from '../game-logic-config.interface';
11
- import { BonnysFortuneSpinGenerator } from '../bonnys-fortune.spin-generator';
12
- import { BonnysFortuneWinCalculator } from '../bonnys-fortune.win-calculator';
13
- import { GameSpinInputDto } from '../../domain/types/game-spin-input.dto';
14
- import { NumberHelper } from '../../helpers/number-helper';
15
- import { ReelStripsConfig } from '../../domain/reel-strips-config';
16
- import { RngService } from '../../rng/rng-service';
17
-
18
- export class FreeSpinsBonusHandler {
19
- constructor(private rngService: RngService) {}
20
-
21
- public async generateFullBonusRound(
22
- params: GameSpinInputDto,
23
- publicState: BonnysFortunePublicState,
24
- privateState: BonnysFortunePrivateState,
25
- config: BonnysFortuneGameLogicConfigInterface,
26
- reelStripsConfig: ReelStripsConfig,
27
- commandId: string,
28
- ): Promise<BonusRoundResult<FreeSpinResult>> {
29
- const betStake = this.getBetStake(params, config);
30
- const spinGenerator = new BonnysFortuneSpinGenerator(this.rngService);
31
- const spinTypes = config.bonusGames.bonusGame2.config.spinTypes;
32
- const weights = spinTypes.map((st) => st.weight);
33
- const total = weights.reduce((a, b) => NumberHelper.safeSum(a, b, 2), 0);
34
-
35
- const result = await this.rngService.getSingleNumber(
36
- 0,
37
- total - 1,
38
- commandId,
39
- 'free_spins_type_selection',
40
- );
41
- const rand = result.value;
42
-
43
- let spinTypeIndex = 0;
44
- let cumulative = 0;
45
- for (let i = 0; i < weights.length; i++) {
46
- cumulative += weights[i];
47
- if (rand < cumulative) {
48
- spinTypeIndex = i;
49
- break;
50
- }
51
- }
52
- const spinTypeConfig = spinTypes[spinTypeIndex];
53
-
54
- const results: SpinResultResponse<FreeSpinResult>[] = [];
55
- let spinsLeft = spinTypeConfig.spins;
56
-
57
- while (spinsLeft > 0) {
58
- const screen = await spinGenerator.generateScreenWithLayout(
59
- reelStripsConfig,
60
- spinTypeConfig.layout,
61
- spinTypeConfig.reelsOptionsWeights,
62
- commandId,
63
- `free_spin_${spinsLeft}`,
64
- );
65
-
66
- const winResult = BonnysFortuneWinCalculator.calculateWins(
67
- screen,
68
- config,
69
- NumberHelper.toFixedNumber(betStake, 2),
70
- NumberHelper.toFixedNumber(spinTypeConfig.multiplier, 2),
71
- SpinType.BONUS_GAME_2_SPIN,
72
- spinTypeIndex,
73
- );
74
-
75
- results.push({
76
- result: {
77
- spinType: SpinType.BONUS_GAME_2_SPIN,
78
- screen,
79
- winResult,
80
- playerWinning: NumberHelper.toFixedNumber(winResult.totalWin, 2),
81
- nextSpinType:
82
- spinsLeft === 1
83
- ? SpinType.BASE_GAME_SPIN
84
- : SpinType.BONUS_GAME_2_SPIN,
85
- multiplier: NumberHelper.toFixedNumber(spinTypeConfig.multiplier, 2),
86
- },
87
- publicState: publicState,
88
- privateState: {
89
- ...privateState,
90
- nextSpinType:
91
- spinsLeft === 1
92
- ? SpinType.BASE_GAME_SPIN
93
- : SpinType.BONUS_GAME_2_SPIN,
94
- activeBonus: spinsLeft === 1 ? undefined : privateState.activeBonus,
95
- },
96
- });
97
-
98
- spinsLeft--;
99
- }
100
-
101
- return {
102
- results,
103
- publicState,
104
- privateState,
105
- };
106
- }
107
-
108
- private getBetStake(
109
- params: GameSpinInputDto,
110
- config: BonnysFortuneGameLogicConfigInterface,
111
- ): number {
112
- const baseBet = config.baseGame.baseGameConfig.baseBet;
113
- return NumberHelper.safeDivide(
114
- params.betAmount,
115
- params.creditsPerLine === baseBet ? params.creditsPerLine : baseBet,
116
- 3,
117
- );
118
- }
119
- }
@@ -1,118 +0,0 @@
1
- import {
2
- BonnysFortunePrivateState,
3
- BonnysFortunePublicState,
4
- BonusRoundResult,
5
- BonusTrigger,
6
- PrizeType,
7
- SpinResultResponse,
8
- SpinType,
9
- SteeringToTheFortuneResult,
10
- } from '../bonnys-fortune.types';
11
-
12
- import { BonnysFortuneGameLogicConfigInterface } from '../game-logic-config.interface';
13
- import { GameSpinInputDto } from '../../domain/types/game-spin-input.dto';
14
- import { NumberHelper } from '../../helpers/number-helper';
15
- import { RngService } from '../../rng/rng-service';
16
- import { UuidHelper } from '../../helpers/uuid-helper';
17
- import { getSpinTypeForBonus } from './base-game.handler';
18
-
19
- export class SteeringToTheFortuneBonusHandler {
20
- constructor(private rngService: RngService) {}
21
-
22
- public async generateFullBonusRound(
23
- params: GameSpinInputDto,
24
- publicState: BonnysFortunePublicState,
25
- privateState: BonnysFortunePrivateState,
26
- config: BonnysFortuneGameLogicConfigInterface,
27
- commandId: string,
28
- ): Promise<BonusRoundResult<SteeringToTheFortuneResult>> {
29
- const betStake = this.getBetStake(params, config);
30
- const wheelResults = config.bonusGames.bonusGame3.config.wheelResults;
31
-
32
- const selectedIndex = await this.weightedDraw(
33
- wheelResults.map((w) => w.weight),
34
- commandId,
35
- 'steering_fortune_wheel_selection',
36
- );
37
- const prize = wheelResults[selectedIndex];
38
-
39
- let playerWinning = 0;
40
- let nextSpinType: SpinType = SpinType.BASE_GAME_SPIN;
41
- let triggeredBonus: BonusTrigger | undefined;
42
-
43
- if (prize.type === PrizeType.MULTIPLIER) {
44
- playerWinning = NumberHelper.safeMultiply(betStake, prize.value, 2);
45
- } else if (prize.type === PrizeType.BONUS) {
46
- triggeredBonus = {
47
- bonusId: UuidHelper.generateUuid(),
48
- bonusType: prize.bonusType,
49
- betAmount: NumberHelper.toFixedNumber(params.betAmount, 2),
50
- };
51
- nextSpinType = getSpinTypeForBonus(prize.bonusType);
52
- }
53
-
54
- const results = [
55
- {
56
- result: {
57
- spinType: SpinType.BONUS_GAME_3_SPIN,
58
- playerWinning,
59
- nextSpinType,
60
- prizeType: prize.type,
61
- prizeValue:
62
- prize.type === PrizeType.MULTIPLIER ? prize.value : prize.bonusType,
63
- totalMultiplier:
64
- prize.type === PrizeType.MULTIPLIER ? prize.value : 0,
65
- triggeredBonus,
66
- },
67
- publicState,
68
- privateState: {
69
- ...privateState,
70
- nextSpinType,
71
- pendingBonuses: triggeredBonus ? [triggeredBonus] : [],
72
- activeBonus: undefined,
73
- },
74
- },
75
- ];
76
-
77
- return {
78
- results,
79
- publicState,
80
- privateState,
81
- };
82
- }
83
-
84
- private async weightedDraw(
85
- weights: number[],
86
- commandId: string,
87
- actionId: string,
88
- ): Promise<number> {
89
- const sum = weights.reduce((acc, w) => NumberHelper.safeSum(acc, w, 2), 0);
90
-
91
- const result = await this.rngService.getSingleNumber(
92
- 0,
93
- sum - 1,
94
- commandId,
95
- actionId,
96
- );
97
- const draw = result.value;
98
-
99
- let cumulative = 0;
100
- for (let i = 0; i < weights.length; i++) {
101
- cumulative = NumberHelper.safeSum(cumulative, weights[i], 2);
102
- if (draw < cumulative) return i;
103
- }
104
- return weights.length - 1;
105
- }
106
-
107
- private getBetStake(
108
- params: GameSpinInputDto,
109
- config: BonnysFortuneGameLogicConfigInterface,
110
- ): number {
111
- const baseBet = config.baseGame.baseGameConfig.baseBet;
112
- return NumberHelper.safeDivide(
113
- params.betAmount,
114
- params.creditsPerLine === baseBet ? params.creditsPerLine : baseBet,
115
- 3,
116
- );
117
- }
118
- }
@@ -1,232 +0,0 @@
1
- import {
2
- BonnysFortunePrivateState,
3
- BonnysFortunePublicState,
4
- BonusRoundResult,
5
- SpinType,
6
- TreasureHuntSpinResult,
7
- } from '../bonnys-fortune.types';
8
-
9
- import { BonnysFortuneGameLogicConfigInterface } from '../game-logic-config.interface';
10
- import { GameSpinInputDto } from '../../domain/types/game-spin-input.dto';
11
- import { NumberHelper } from '../../helpers/number-helper';
12
- import { RngService } from '../../rng/rng-service';
13
-
14
- export class TreasureHuntBonusHandler {
15
- constructor(private rngService: RngService) {}
16
-
17
- public async generateFullBonusRound(
18
- params: GameSpinInputDto,
19
- publicState: BonnysFortunePublicState,
20
- privateState: BonnysFortunePrivateState,
21
- config: BonnysFortuneGameLogicConfigInterface,
22
- commandId: string,
23
- ): Promise<BonusRoundResult<TreasureHuntSpinResult>> {
24
- const betStake = this.getBetStake(params, config);
25
- const {
26
- stepsCount,
27
- jackpotScreenCounts,
28
- jackpotMultipliers,
29
- winningWeights,
30
- } = this.extractBonusConfig(config);
31
-
32
- const jackpotKeys = Object.keys(jackpotMultipliers);
33
- const jackpotsNo = Object.values(jackpotScreenCounts);
34
- const weightsArray = Object.values(winningWeights);
35
-
36
- const winSymbolIndex = await this.drawWinningSymbol(
37
- weightsArray,
38
- commandId,
39
- );
40
-
41
- const selectionsVector = Array<number>(stepsCount).fill(-1);
42
-
43
- if (winSymbolIndex >= 0) {
44
- const positions = await this.randomPositions(stepsCount, 3, commandId);
45
- positions.forEach((pos) => (selectionsVector[pos] = winSymbolIndex));
46
- jackpotsNo[winSymbolIndex] = NumberHelper.safeSum(
47
- jackpotsNo[winSymbolIndex],
48
- -3,
49
- 0,
50
- );
51
- }
52
-
53
- await this.fillRemainingSteps(
54
- selectionsVector,
55
- stepsCount,
56
- jackpotsNo,
57
- winSymbolIndex,
58
- commandId,
59
- );
60
-
61
- const selections = selectionsVector.map((idx) => jackpotKeys[idx]);
62
- const multipliers = selections.map((name) => jackpotMultipliers[name]);
63
-
64
- const results = selections.map((symbol, index) => {
65
- const isFinalStep = index === stepsCount - 1;
66
-
67
- const winningMultiplier =
68
- isFinalStep && winSymbolIndex >= 0
69
- ? jackpotMultipliers[jackpotKeys[winSymbolIndex]]
70
- : 0;
71
- const playerWinning =
72
- isFinalStep && winSymbolIndex >= 0
73
- ? NumberHelper.safeMultiply(betStake, winningMultiplier, 2)
74
- : 0;
75
-
76
- return {
77
- result: {
78
- spinType: SpinType.BONUS_GAME_1_SPIN,
79
- playerWinning,
80
- nextSpinType: isFinalStep
81
- ? SpinType.BASE_GAME_SPIN
82
- : SpinType.BONUS_GAME_1_SPIN,
83
- selection: symbol,
84
- multiplier: multipliers[index],
85
- multiplierCounts: selections.slice(0, index + 1).reduce(
86
- (acc, key) => {
87
- acc[key] = (acc[key] || 0) + 1;
88
- return acc;
89
- },
90
- {} as Record<string, number>,
91
- ),
92
- winningMultiplier,
93
- winningCount: isFinalStep && winSymbolIndex >= 0 ? 3 : 0,
94
- totalMultiplier: winningMultiplier,
95
- },
96
- publicState,
97
- privateState: {
98
- ...privateState,
99
- nextSpinType: isFinalStep
100
- ? SpinType.BASE_GAME_SPIN
101
- : SpinType.BONUS_GAME_1_SPIN,
102
- activeBonus: isFinalStep ? undefined : privateState.activeBonus,
103
- },
104
- };
105
- });
106
-
107
- return {
108
- results,
109
- publicState,
110
- privateState,
111
- };
112
- }
113
-
114
- private getBetStake(
115
- params: GameSpinInputDto,
116
- config: BonnysFortuneGameLogicConfigInterface,
117
- ): number {
118
- const baseBet = config.baseGame.baseGameConfig.baseBet;
119
- return NumberHelper.safeDivide(
120
- params.betAmount,
121
- params.creditsPerLine === baseBet ? params.creditsPerLine : baseBet,
122
- 3,
123
- );
124
- }
125
-
126
- private async drawWinningSymbol(
127
- weights: number[],
128
- commandId: string,
129
- ): Promise<number> {
130
- const total = weights.reduce(
131
- (acc, w) => NumberHelper.safeSum(acc, w, 2),
132
- 0,
133
- );
134
- if (total === 0) return -1;
135
-
136
- const result = await this.rngService.getSingleNumber(
137
- 0,
138
- total - 1,
139
- commandId,
140
- 'treasure_hunt_winning_symbol',
141
- );
142
- const draw = result.value;
143
-
144
- let cumulative = 0;
145
- for (let i = 0; i < weights.length; i++) {
146
- cumulative = NumberHelper.safeSum(cumulative, weights[i], 2);
147
- if (draw < cumulative) return i;
148
- }
149
- return -1;
150
- }
151
-
152
- private async fillRemainingSteps(
153
- vector: number[],
154
- stepsCount: number,
155
- jackpotsNo: number[],
156
- excludeSymbol: number | undefined,
157
- commandId: string,
158
- ) {
159
- const weights: number[] = jackpotsNo.map((_, idx) =>
160
- idx === excludeSymbol ? 0 : 4,
161
- );
162
-
163
- for (let i = 0; i < stepsCount; i++) {
164
- if (vector[i] < 0) {
165
- const symbol = await this.weightedDraw(
166
- weights,
167
- commandId,
168
- `fill_step_${i}`,
169
- );
170
- vector[i] = symbol;
171
- jackpotsNo[symbol] = NumberHelper.safeSum(jackpotsNo[symbol], -1, 0);
172
- weights[symbol] = Math.max(0, weights[symbol] - 2);
173
- }
174
- }
175
- }
176
-
177
- private async weightedDraw(
178
- weights: number[],
179
- commandId: string,
180
- actionId: string,
181
- ): Promise<number> {
182
- const sum = weights.reduce((acc, w) => NumberHelper.safeSum(acc, w, 2), 0);
183
- if (sum === 0) return 0;
184
-
185
- const result = await this.rngService.getSingleNumber(
186
- 0,
187
- sum - 1,
188
- commandId,
189
- actionId,
190
- );
191
- const draw = result.value;
192
-
193
- let cumulative = 0;
194
- for (let i = 0; i < weights.length; i++) {
195
- cumulative = NumberHelper.safeSum(cumulative, weights[i], 2);
196
- if (draw < cumulative) return i;
197
- }
198
- return weights.length - 1;
199
- }
200
-
201
- private async randomPositions(
202
- limit: number,
203
- count: number,
204
- commandId: string,
205
- ): Promise<number[]> {
206
- const positions = Array.from({ length: limit }, (_, i) => i);
207
- const selected: number[] = [];
208
- while (selected.length < count) {
209
- const actionId = `random_position_${selected.length}`;
210
- const result = await this.rngService.getSingleNumber(
211
- 0,
212
- positions.length - 1,
213
- commandId,
214
- actionId,
215
- );
216
- const idx = result.value;
217
- selected.push(positions.splice(idx, 1)[0]);
218
- }
219
- return selected;
220
- }
221
-
222
- private extractBonusConfig(config: BonnysFortuneGameLogicConfigInterface) {
223
- return {
224
- stepsCount: config.bonusGames.bonusGame1.config.stepsCount,
225
- jackpotMultipliers:
226
- config.bonusGames.bonusGame1.config.jackpotMultipliers,
227
- winningWeights: config.bonusGames.bonusGame1.config.winningWeights,
228
- jackpotScreenCounts:
229
- config.bonusGames.bonusGame1.config.jackpotScreenCounts,
230
- };
231
- }
232
- }
@@ -1,108 +0,0 @@
1
- import {
2
- RngBatchResponse,
3
- RngSingleResponse,
4
- } from '@omnitronix/rng-client-core/dist/http/http-client.types';
5
-
6
- import { IRngClient } from './rng-client.interface';
7
-
8
- export class DummyRngClient implements IRngClient {
9
- constructor() {}
10
-
11
- getSingleNumber(
12
- min: number,
13
- max: number,
14
- _seed?: number,
15
- ): Promise<{ value: number; seed: number }> {
16
- const randomValue = Math.random();
17
- const result = Math.floor(randomValue * (max - min + 1)) + min;
18
- return Promise.resolve({ value: result, seed: 0 });
19
- }
20
-
21
- getBatchNumbers(
22
- min: number,
23
- max: number,
24
- count: number,
25
- _seed?: number,
26
- ): Promise<number[]> {
27
- const results: number[] = [];
28
- for (let i = 0; i < count; i++) {
29
- const randomValue = Math.random();
30
- const result = Math.floor(randomValue * (max - min + 1)) + min;
31
- results.push(result);
32
- }
33
- return Promise.resolve(results);
34
- }
35
-
36
- getBatchNumbersWithSeeds(
37
- min: number,
38
- max: number,
39
- count: number,
40
- _seed?: number,
41
- ): Promise<{ value: number; seed: number }[]> {
42
- const results: number[] = [];
43
- for (let i = 0; i < count; i++) {
44
- const randomValue = Math.random();
45
- const result = Math.floor(randomValue * (max - min + 1)) + min;
46
- results.push(result);
47
- }
48
- return Promise.resolve(
49
- results.map((result) => ({ value: result, seed: 0 })),
50
- );
51
- }
52
-
53
- getSingleFloat(_seed?: number): Promise<RngSingleResponse> {
54
- const result = Math.random();
55
- return Promise.resolve({
56
- id: '0',
57
- seed: 0,
58
- result,
59
- min: 0,
60
- max: 1,
61
- createdAt: new Date().toISOString(),
62
- });
63
- }
64
-
65
- getBatchFloats(count: number, _seed?: number): Promise<RngBatchResponse> {
66
- const result: number[] = [];
67
- for (let i = 0; i < count; i++) {
68
- result.push(Math.random());
69
- }
70
- return Promise.resolve({
71
- id: '0',
72
- seed: 0,
73
- result,
74
- min: 0,
75
- max: 1,
76
- createdAt: new Date().toISOString(),
77
- });
78
- }
79
-
80
- getRandomNumber(
81
- min: number,
82
- max: number,
83
- _seed?: number,
84
- ): Promise<RngSingleResponse> {
85
- const randomValue = Math.random();
86
- const result = Math.floor(randomValue * (max - min + 1)) + min;
87
- return Promise.resolve({
88
- id: '0',
89
- seed: 0,
90
- result,
91
- min,
92
- max,
93
- createdAt: new Date().toISOString(),
94
- });
95
- }
96
-
97
- getRandomFloat(_seed?: number): Promise<RngSingleResponse> {
98
- const result = Math.random();
99
- return Promise.resolve({
100
- id: '0',
101
- seed: 0,
102
- result,
103
- min: 0,
104
- max: 1,
105
- createdAt: new Date().toISOString(),
106
- });
107
- }
108
- }
@@ -1,27 +0,0 @@
1
- import { RngClient, RngClientConfig } from '@omnitronix/rng-client-core';
2
-
3
- import { DummyRngClient } from './DummyRngClient';
4
- import { IRngClient } from './rng-client.interface';
5
-
6
- export class RngClientFactory {
7
- static create(
8
- config: { metrics?: RngClientConfig['metrics'] } = {},
9
- ): IRngClient {
10
- const mode = process.env.RNG_CLIENT_MODE || 'external';
11
- console.log('RNG_CLIENT_MODE', mode);
12
-
13
- if (mode === 'local') {
14
- return new DummyRngClient();
15
- }
16
-
17
- const rngClientConfig: RngClientConfig = {
18
- serverUrl: process.env.RNG_CLIENT_URL,
19
- grpcUrl: process.env.RNG_CLIENT_GRPC_URL,
20
- clientMethod: process.env.RNG_CLIENT_METHOD as 'grpc' | 'rest',
21
- poolingSize: parseInt(process.env.RNG_CLIENT_POOL_SIZE || '2000'),
22
- metrics: config.metrics,
23
- };
24
-
25
- return new RngClient(rngClientConfig);
26
- }
27
- }
@@ -1,38 +0,0 @@
1
- import {
2
- RngBatchResponse,
3
- RngSingleResponse,
4
- } from '@omnitronix/rng-client-core/dist/http/http-client.types';
5
-
6
- export interface IRngClient {
7
- getSingleNumber(
8
- min: number,
9
- max: number,
10
- seed?: number,
11
- ): Promise<{ value: number; seed: number }>;
12
-
13
- getBatchNumbers(
14
- min: number,
15
- max: number,
16
- count: number,
17
- seed?: number,
18
- ): Promise<number[]>;
19
-
20
- getBatchNumbersWithSeeds(
21
- min: number,
22
- max: number,
23
- count: number,
24
- seed?: number,
25
- ): Promise<{ value: number; seed: number }[]>;
26
-
27
- getSingleFloat(seed?: number): Promise<RngSingleResponse>;
28
-
29
- getBatchFloats(count: number, seed?: number): Promise<RngBatchResponse>;
30
-
31
- getRandomNumber(
32
- min: number,
33
- max: number,
34
- seed?: number,
35
- ): Promise<RngSingleResponse>;
36
-
37
- getRandomFloat(seed?: number): Promise<RngSingleResponse>;
38
- }