@omnitronix/bonnys-fortune-game-engine 1.0.0-beta.1
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.
- package/README.md +680 -0
- package/dist/__tests__/bonnys-fortune-v1.game-engine.test.js +71 -0
- package/dist/__tests__/bonnys-fortune-v1.game-engine.test.js.map +1 -0
- package/dist/__tests__/comprehensive.test.js +741 -0
- package/dist/__tests__/comprehensive.test.js.map +1 -0
- package/dist/bonnys-fortune-v1.game-engine.js +184 -0
- package/dist/bonnys-fortune-v1.game-engine.js.map +1 -0
- package/dist/config/game-logic-config/file-system.game-logic-config-loader.js +57 -0
- package/dist/config/game-logic-config/file-system.game-logic-config-loader.js.map +1 -0
- package/dist/config/game-logic-config/game-logic-config-loader.js +3 -0
- package/dist/config/game-logic-config/game-logic-config-loader.js.map +1 -0
- package/dist/config/game-logic-config/game-logic-config.js +382 -0
- package/dist/config/game-logic-config/game-logic-config.js.map +1 -0
- package/dist/config/reel-strips-config/file-system.reel-strips-config-loader.js +34 -0
- package/dist/config/reel-strips-config/file-system.reel-strips-config-loader.js.map +1 -0
- package/dist/config/reel-strips-config/reel-strip-option.dto.js +27 -0
- package/dist/config/reel-strips-config/reel-strip-option.dto.js.map +1 -0
- package/dist/config/reel-strips-config/reel-strips-config-loader.js +3 -0
- package/dist/config/reel-strips-config/reel-strips-config-loader.js.map +1 -0
- package/dist/config/reel-strips-config/reel-strips-config.dto.js +29 -0
- package/dist/config/reel-strips-config/reel-strips-config.dto.js.map +1 -0
- package/dist/config/reel-strips-config/reel.dto.js +29 -0
- package/dist/config/reel-strips-config/reel.dto.js.map +1 -0
- package/dist/config/reel-strips-config/reels-BASE.csv +52 -0
- package/dist/config/reel-strips-config/reels-BONUS.csv +52 -0
- package/dist/domain/game-round.types.js +9 -0
- package/dist/domain/game-round.types.js.map +1 -0
- package/dist/domain/mappers/reel-strips-config.mapper.js +17 -0
- package/dist/domain/mappers/reel-strips-config.mapper.js.map +1 -0
- package/dist/domain/reel-strip-option.js +19 -0
- package/dist/domain/reel-strip-option.js.map +1 -0
- package/dist/domain/reel-strips-config.js +22 -0
- package/dist/domain/reel-strips-config.js.map +1 -0
- package/dist/domain/reel.js +19 -0
- package/dist/domain/reel.js.map +1 -0
- package/dist/domain/types/debug-trigger-bonus-command.js +3 -0
- package/dist/domain/types/debug-trigger-bonus-command.js.map +1 -0
- package/dist/domain/types/debug-trigger-bonus-request.dto.js +3 -0
- package/dist/domain/types/debug-trigger-bonus-request.dto.js.map +1 -0
- package/dist/domain/types/debug-update-bonus-meter-progress-command.js +3 -0
- package/dist/domain/types/debug-update-bonus-meter-progress-command.js.map +1 -0
- package/dist/domain/types/debug-update-bonus-meter-progress-request.dto.js +3 -0
- package/dist/domain/types/debug-update-bonus-meter-progress-request.dto.js.map +1 -0
- package/dist/domain/types/game-spin-command.js +3 -0
- package/dist/domain/types/game-spin-command.js.map +1 -0
- package/dist/domain/types/game-spin-input.dto.js +3 -0
- package/dist/domain/types/game-spin-input.dto.js.map +1 -0
- package/dist/domain/types/game-spin-output.dto.js +17 -0
- package/dist/domain/types/game-spin-output.dto.js.map +1 -0
- package/dist/domain/types/game-symbols.response.dto.js +7 -0
- package/dist/domain/types/game-symbols.response.dto.js.map +1 -0
- package/dist/domain/types/reel-strip-option.dto.js +27 -0
- package/dist/domain/types/reel-strip-option.dto.js.map +1 -0
- package/dist/domain/types/reel-strips-config.dto.js +28 -0
- package/dist/domain/types/reel-strips-config.dto.js.map +1 -0
- package/dist/domain/types/reel.dto.js +28 -0
- package/dist/domain/types/reel.dto.js.map +1 -0
- package/dist/domain/types/start-bonus-round-command.js +3 -0
- package/dist/domain/types/start-bonus-round-command.js.map +1 -0
- package/dist/domain/types/start-bonus-round-input.dto.js +3 -0
- package/dist/domain/types/start-bonus-round-input.dto.js.map +1 -0
- package/dist/game-engine.interface.js +3 -0
- package/dist/game-engine.interface.js.map +1 -0
- package/dist/helpers/generate-hash.js +9 -0
- package/dist/helpers/generate-hash.js.map +1 -0
- package/dist/helpers/number-helper.js +43 -0
- package/dist/helpers/number-helper.js.map +1 -0
- package/dist/helpers/optional-boolean-mapper.js +9 -0
- package/dist/helpers/optional-boolean-mapper.js.map +1 -0
- package/dist/helpers/uuid-helper.js +11 -0
- package/dist/helpers/uuid-helper.js.map +1 -0
- package/dist/helpers/validation-helper.js +25 -0
- package/dist/helpers/validation-helper.js.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/logger/logger.js +140 -0
- package/dist/logger/logger.js.map +1 -0
- package/dist/logic/bonnys-fortune.game-logic.js +252 -0
- package/dist/logic/bonnys-fortune.game-logic.js.map +1 -0
- package/dist/logic/bonnys-fortune.spin-generator.js +101 -0
- package/dist/logic/bonnys-fortune.spin-generator.js.map +1 -0
- package/dist/logic/bonnys-fortune.types.js +17 -0
- package/dist/logic/bonnys-fortune.types.js.map +1 -0
- package/dist/logic/bonnys-fortune.win-calculator.js +130 -0
- package/dist/logic/bonnys-fortune.win-calculator.js.map +1 -0
- package/dist/logic/game-logic-config.interface.js +3 -0
- package/dist/logic/game-logic-config.interface.js.map +1 -0
- package/dist/logic/handlers/base-game.handler.js +113 -0
- package/dist/logic/handlers/base-game.handler.js.map +1 -0
- package/dist/logic/handlers/collect-feature-bonus.handler.js +152 -0
- package/dist/logic/handlers/collect-feature-bonus.handler.js.map +1 -0
- package/dist/logic/handlers/free-spins-bonus.handler.js +69 -0
- package/dist/logic/handlers/free-spins-bonus.handler.js.map +1 -0
- package/dist/logic/handlers/steering-to-the-fortune-bonus.handler.js +75 -0
- package/dist/logic/handlers/steering-to-the-fortune-bonus.handler.js.map +1 -0
- package/dist/logic/handlers/treasure-hunt-bonus.handler.js +131 -0
- package/dist/logic/handlers/treasure-hunt-bonus.handler.js.map +1 -0
- package/dist/rng/DummyRngClient.js +86 -0
- package/dist/rng/DummyRngClient.js.map +1 -0
- package/dist/rng/rng-client.factory.js +23 -0
- package/dist/rng/rng-client.factory.js.map +1 -0
- package/dist/rng/rng-client.interface.js +3 -0
- package/dist/rng/rng-client.interface.js.map +1 -0
- package/dist/rng/rng-service.js +78 -0
- package/dist/rng/rng-service.js.map +1 -0
- package/dist/validation/abstract-game-logic-config.validator.js +18 -0
- package/dist/validation/abstract-game-logic-config.validator.js.map +1 -0
- package/dist/validation/bonnys-fortune/bonnys-fortune-config.dto.js +454 -0
- package/dist/validation/bonnys-fortune/bonnys-fortune-config.dto.js.map +1 -0
- package/dist/validation/bonnys-fortune/bonnys-fortune-config.validator.js +12 -0
- package/dist/validation/bonnys-fortune/bonnys-fortune-config.validator.js.map +1 -0
- package/dist/validation/custom-decorators/IsNestedIntArray.js +26 -0
- package/dist/validation/custom-decorators/IsNestedIntArray.js.map +1 -0
- package/dist/validation/game-logic-config-validation.service.js +20 -0
- package/dist/validation/game-logic-config-validation.service.js.map +1 -0
- package/dist/validation/reel-strips-config-validation.service.js +26 -0
- package/dist/validation/reel-strips-config-validation.service.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseGameHandler = void 0;
|
|
4
|
+
exports.getSpinTypeForBonus = getSpinTypeForBonus;
|
|
5
|
+
const bonnys_fortune_types_1 = require("../bonnys-fortune.types");
|
|
6
|
+
const bonnys_fortune_spin_generator_1 = require("../bonnys-fortune.spin-generator");
|
|
7
|
+
const bonnys_fortune_win_calculator_1 = require("../bonnys-fortune.win-calculator");
|
|
8
|
+
const number_helper_1 = require("../../helpers/number-helper");
|
|
9
|
+
const uuid_helper_1 = require("../../helpers/uuid-helper");
|
|
10
|
+
class BaseGameHandler {
|
|
11
|
+
constructor(rngService) {
|
|
12
|
+
this.rngService = rngService;
|
|
13
|
+
}
|
|
14
|
+
async handleSpin(params, publicState, privateState, config, reelStripsConfig, commandId) {
|
|
15
|
+
if (privateState.nextSpinType !== bonnys_fortune_types_1.SpinType.BASE_GAME_SPIN) {
|
|
16
|
+
throw new Error(`Cannot execute base spin while a bonus spin (${privateState.nextSpinType}) is expected`);
|
|
17
|
+
}
|
|
18
|
+
let screen = await new bonnys_fortune_spin_generator_1.BonnysFortuneSpinGenerator(this.rngService).generateBaseScreen(config, reelStripsConfig, commandId, 'base_spin_screen');
|
|
19
|
+
screen = await new bonnys_fortune_spin_generator_1.BonnysFortuneSpinGenerator(this.rngService).applyBonusSymbols(screen, config, commandId, 'base_spin_bonus_symbols');
|
|
20
|
+
const updatedBonusMeters = this.updateBonusMeters(screen, privateState.bonusMetersByAmount[params.betAmount], config);
|
|
21
|
+
privateState.bonusMetersByAmount[params.betAmount] = updatedBonusMeters;
|
|
22
|
+
const scatterSymbolId = config.baseGame.symbolDefinitions.specialSymbols.SCATTER;
|
|
23
|
+
const betStake = this.getBetStake(params, config);
|
|
24
|
+
const triggeredBonus = this.findTriggeredBonus(updatedBonusMeters, params.betAmount, screen, scatterSymbolId);
|
|
25
|
+
const nextSpinType = triggeredBonus
|
|
26
|
+
? getSpinTypeForBonus(triggeredBonus.bonusType)
|
|
27
|
+
: bonnys_fortune_types_1.SpinType.BASE_GAME_SPIN;
|
|
28
|
+
const winResult = bonnys_fortune_win_calculator_1.BonnysFortuneWinCalculator.calculateWins(screen, config, betStake, 1, bonnys_fortune_types_1.SpinType.BASE_GAME_SPIN);
|
|
29
|
+
return {
|
|
30
|
+
result: {
|
|
31
|
+
spinType: bonnys_fortune_types_1.SpinType.BASE_GAME_SPIN,
|
|
32
|
+
screen,
|
|
33
|
+
winResult,
|
|
34
|
+
playerWinning: number_helper_1.NumberHelper.toFixedNumber(winResult.totalWin, 2),
|
|
35
|
+
nextSpinType,
|
|
36
|
+
triggeredBonus,
|
|
37
|
+
},
|
|
38
|
+
publicState: {
|
|
39
|
+
currentBetAmount: params.betAmount,
|
|
40
|
+
bonusMeters: updatedBonusMeters,
|
|
41
|
+
},
|
|
42
|
+
privateState: {
|
|
43
|
+
...privateState,
|
|
44
|
+
nextSpinType,
|
|
45
|
+
pendingBonuses: triggeredBonus ? [triggeredBonus] : [],
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
updateBonusMeters(screen, bonusMeters, config) {
|
|
50
|
+
const symbolsInScreen = screen.flat();
|
|
51
|
+
return Object.fromEntries(Object.entries(bonusMeters).map(([key, bonusMeter]) => {
|
|
52
|
+
const count = symbolsInScreen.filter((sym) => sym === bonusMeter.symbolId).length;
|
|
53
|
+
const newProgress = number_helper_1.NumberHelper.safeSum(bonusMeter.progress, count, 0);
|
|
54
|
+
const cfg = config?.baseGame.bonusGameMeters[key];
|
|
55
|
+
const percentageLevels = cfg?.percentageLevels ?? {};
|
|
56
|
+
const level = this.getMeterLevel(newProgress, bonusMeter.threshold, percentageLevels);
|
|
57
|
+
return [key, { ...bonusMeter, progress: newProgress, level }];
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
findTriggeredBonus(bonusMeters, betAmount, screen, scatterSymbolId) {
|
|
61
|
+
const triggeredPot = Object.entries(bonusMeters).find(([, bonusMeter]) => bonusMeter.progress >= bonusMeter.threshold);
|
|
62
|
+
if (triggeredPot) {
|
|
63
|
+
const [bonusType] = triggeredPot;
|
|
64
|
+
return {
|
|
65
|
+
bonusId: uuid_helper_1.UuidHelper.generateUuid(),
|
|
66
|
+
bonusType,
|
|
67
|
+
betAmount: number_helper_1.NumberHelper.toFixedNumber(betAmount, 2),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (screen && scatterSymbolId !== undefined) {
|
|
71
|
+
const flatScreen = screen.flat();
|
|
72
|
+
const scatterCount = flatScreen.filter((sym) => sym === scatterSymbolId).length;
|
|
73
|
+
if (scatterCount >= 3) {
|
|
74
|
+
return {
|
|
75
|
+
bonusId: uuid_helper_1.UuidHelper.generateUuid(),
|
|
76
|
+
bonusType: 'collectFeature',
|
|
77
|
+
betAmount: number_helper_1.NumberHelper.toFixedNumber(betAmount, 2),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
getMeterLevel(progress, threshold, percentageLevels) {
|
|
84
|
+
for (const [, range] of Object.entries(percentageLevels)) {
|
|
85
|
+
const minValue = number_helper_1.NumberHelper.safeMultiply(range.min, threshold, 4);
|
|
86
|
+
const maxValue = number_helper_1.NumberHelper.safeMultiply(range.max, threshold, 4);
|
|
87
|
+
if (progress >= minValue && progress < maxValue) {
|
|
88
|
+
return range.value;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return 5;
|
|
92
|
+
}
|
|
93
|
+
getBetStake(params, config) {
|
|
94
|
+
const baseBet = config.baseGame.baseGameConfig.baseBet;
|
|
95
|
+
return number_helper_1.NumberHelper.safeDivide(params.betAmount, params.creditsPerLine === baseBet ? params.creditsPerLine : baseBet, 3);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.BaseGameHandler = BaseGameHandler;
|
|
99
|
+
function getSpinTypeForBonus(bonusType) {
|
|
100
|
+
switch (bonusType) {
|
|
101
|
+
case 'bonusGame1':
|
|
102
|
+
return bonnys_fortune_types_1.SpinType.BONUS_GAME_1_SPIN;
|
|
103
|
+
case 'bonusGame2':
|
|
104
|
+
return bonnys_fortune_types_1.SpinType.BONUS_GAME_2_SPIN;
|
|
105
|
+
case 'bonusGame3':
|
|
106
|
+
return bonnys_fortune_types_1.SpinType.BONUS_GAME_3_SPIN;
|
|
107
|
+
case 'collectFeature':
|
|
108
|
+
return bonnys_fortune_types_1.SpinType.COLLECT_FEATURE_SPIN;
|
|
109
|
+
default:
|
|
110
|
+
return bonnys_fortune_types_1.SpinType.BASE_GAME_SPIN;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=base-game.handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-game.handler.js","sourceRoot":"","sources":["../../../src/logic/handlers/base-game.handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CollectFeatureBonusHandler = void 0;
|
|
4
|
+
const bonnys_fortune_types_1 = require("../bonnys-fortune.types");
|
|
5
|
+
const number_helper_1 = require("../../helpers/number-helper");
|
|
6
|
+
class CollectFeatureBonusHandler {
|
|
7
|
+
constructor(rngService) {
|
|
8
|
+
this.rngService = rngService;
|
|
9
|
+
}
|
|
10
|
+
async generateFullBonusRound(params, publicState, privateState, config, commandId) {
|
|
11
|
+
const betStake = this.getBetStake(params, config);
|
|
12
|
+
const scatterConfig = config.scatterGame.config;
|
|
13
|
+
const results = [];
|
|
14
|
+
const initialPublicState = { ...publicState };
|
|
15
|
+
const initialPrivateState = { ...privateState };
|
|
16
|
+
let spinsLeft = scatterConfig.scatterSpins;
|
|
17
|
+
let totalValues = 0;
|
|
18
|
+
let totalMultipliers = 1;
|
|
19
|
+
let totalWin = 0;
|
|
20
|
+
const checkpoints = await Promise.all(scatterConfig.scatterCheckpoints.map(async (cp, index) => {
|
|
21
|
+
const actionId = `checkpoint_${index}`;
|
|
22
|
+
const result = await this.rngService.getSingleNumber(0, 1, commandId, actionId);
|
|
23
|
+
return cp.spin - 1 + result.value;
|
|
24
|
+
}));
|
|
25
|
+
for (let spinIndex = 0; spinIndex < scatterConfig.scatterSpins; spinIndex++) {
|
|
26
|
+
const { result, updatedState, updatedPublicState, updatedPrivateState } = await this.executeSingleSpin(spinIndex, spinsLeft, totalValues, totalMultipliers, totalWin, betStake, scatterConfig, checkpoints, publicState, privateState, commandId);
|
|
27
|
+
results.push({
|
|
28
|
+
result,
|
|
29
|
+
publicState: updatedPublicState,
|
|
30
|
+
privateState: updatedPrivateState,
|
|
31
|
+
});
|
|
32
|
+
totalValues = updatedState.totalValues;
|
|
33
|
+
totalMultipliers = updatedState.totalMultipliers;
|
|
34
|
+
totalWin = updatedState.totalWin;
|
|
35
|
+
spinsLeft = updatedState.spinsLeft;
|
|
36
|
+
publicState = updatedPublicState;
|
|
37
|
+
privateState = updatedPrivateState;
|
|
38
|
+
if (spinsLeft <= 0)
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
results,
|
|
43
|
+
publicState: initialPublicState,
|
|
44
|
+
privateState: initialPrivateState,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
async executeSingleSpin(spinIndex, spinsLeft, totalValues, totalMultipliers, totalWin, betStake, scatterConfig, checkpoints, publicState, privateState, commandId) {
|
|
48
|
+
const symbolCount = await this.weightedPick(scatterConfig.scatterSymbolSpins, commandId, `spin_${spinIndex}_symbol_count`);
|
|
49
|
+
const symbols = [];
|
|
50
|
+
let multiCount = 0;
|
|
51
|
+
let valueCount = 0;
|
|
52
|
+
for (let i = 0; i < symbolCount; i++) {
|
|
53
|
+
const symbol = await this.weightedPickSymbol(scatterConfig.scatterSymbols, commandId, `spin_${spinIndex}_symbol_${i}`);
|
|
54
|
+
symbols.push(symbol.symbolId);
|
|
55
|
+
if (symbol.symbolId.startsWith('CM'))
|
|
56
|
+
multiCount++;
|
|
57
|
+
else
|
|
58
|
+
valueCount++;
|
|
59
|
+
}
|
|
60
|
+
if (checkpoints.includes(spinsLeft)) {
|
|
61
|
+
const cpIndex = checkpoints.indexOf(spinsLeft);
|
|
62
|
+
const cp = scatterConfig.scatterCheckpoints[cpIndex];
|
|
63
|
+
if ((totalMultipliers < cp.multiMinValue && multiCount === 0) ||
|
|
64
|
+
(totalValues < cp.valueMinValue && valueCount === 0)) {
|
|
65
|
+
symbols[0] = 'CV1';
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const slashedCount = Math.min(await this.weightedPick(scatterConfig.scatterSymbolSlash, commandId, `spin_${spinIndex}_slashed_count`), symbolCount);
|
|
69
|
+
const slashed = Array(symbolCount).fill(false);
|
|
70
|
+
for (let i = 0; i < slashedCount; i++)
|
|
71
|
+
slashed[i] = true;
|
|
72
|
+
let currentValues = 0;
|
|
73
|
+
let currentMultipliers = 0;
|
|
74
|
+
for (let i = 0; i < slashed.length; i++) {
|
|
75
|
+
if (slashed[i]) {
|
|
76
|
+
const symbol = scatterConfig.scatterSymbols.find((s) => s.symbolId === symbols[i]);
|
|
77
|
+
if (!symbol)
|
|
78
|
+
continue;
|
|
79
|
+
if (symbols[i].startsWith('CM'))
|
|
80
|
+
currentMultipliers = number_helper_1.NumberHelper.safeSum(currentMultipliers, symbol.value, 2);
|
|
81
|
+
else
|
|
82
|
+
currentValues = number_helper_1.NumberHelper.safeSum(currentValues, symbol.value, 2);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const newTotalValues = number_helper_1.NumberHelper.safeSum(totalValues, currentValues, 2);
|
|
86
|
+
const newTotalMultipliers = number_helper_1.NumberHelper.safeSum(totalMultipliers, currentMultipliers, 2);
|
|
87
|
+
const newTotalWin = number_helper_1.NumberHelper.safeMultiply(number_helper_1.NumberHelper.safeMultiply(newTotalValues, newTotalMultipliers, 2), betStake, 2);
|
|
88
|
+
const playerWinning = number_helper_1.NumberHelper.safeSum(newTotalWin, -totalWin, 2);
|
|
89
|
+
spinsLeft -= 1;
|
|
90
|
+
const result = {
|
|
91
|
+
spinIndex,
|
|
92
|
+
spinType: bonnys_fortune_types_1.SpinType.COLLECT_FEATURE_SPIN,
|
|
93
|
+
symbols,
|
|
94
|
+
slashed,
|
|
95
|
+
currentValues,
|
|
96
|
+
currentMultipliers,
|
|
97
|
+
totalValues: newTotalValues,
|
|
98
|
+
totalMultipliers: newTotalMultipliers,
|
|
99
|
+
playerWinning,
|
|
100
|
+
totalWin: newTotalWin,
|
|
101
|
+
spinsLeft,
|
|
102
|
+
nextSpinType: spinsLeft > 0 ? bonnys_fortune_types_1.SpinType.COLLECT_FEATURE_SPIN : bonnys_fortune_types_1.SpinType.BASE_GAME_SPIN,
|
|
103
|
+
};
|
|
104
|
+
const updatedPublicState = {
|
|
105
|
+
...publicState,
|
|
106
|
+
};
|
|
107
|
+
const updatedPrivateState = {
|
|
108
|
+
...privateState,
|
|
109
|
+
nextSpinType: spinsLeft > 0 ? bonnys_fortune_types_1.SpinType.COLLECT_FEATURE_SPIN : bonnys_fortune_types_1.SpinType.BASE_GAME_SPIN,
|
|
110
|
+
activeBonus: spinsLeft > 0 ? privateState.activeBonus : undefined,
|
|
111
|
+
};
|
|
112
|
+
return {
|
|
113
|
+
result,
|
|
114
|
+
updatedState: {
|
|
115
|
+
spinsLeft,
|
|
116
|
+
totalValues: newTotalValues,
|
|
117
|
+
totalMultipliers: newTotalMultipliers,
|
|
118
|
+
totalWin: newTotalWin,
|
|
119
|
+
},
|
|
120
|
+
updatedPublicState,
|
|
121
|
+
updatedPrivateState,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
async weightedPick(items, commandId, actionId) {
|
|
125
|
+
const sum = items.reduce((acc, item) => number_helper_1.NumberHelper.safeSum(acc, item.weight, 2), 0);
|
|
126
|
+
let { value: draw } = await this.rngService.getSingleNumber(0, sum - 1, commandId, actionId);
|
|
127
|
+
for (const item of items) {
|
|
128
|
+
if (draw < item.weight) {
|
|
129
|
+
return item.count || items.indexOf(item) + 1;
|
|
130
|
+
}
|
|
131
|
+
draw -= item.weight;
|
|
132
|
+
}
|
|
133
|
+
return 1;
|
|
134
|
+
}
|
|
135
|
+
async weightedPickSymbol(symbols, commandId, actionId) {
|
|
136
|
+
const sum = symbols.reduce((acc, s) => number_helper_1.NumberHelper.safeSum(acc, s.weight, 2), 0);
|
|
137
|
+
const result = await this.rngService.getSingleNumber(0, sum - 1, commandId, actionId);
|
|
138
|
+
let drawValue = result.value;
|
|
139
|
+
for (const s of symbols) {
|
|
140
|
+
if (drawValue < s.weight)
|
|
141
|
+
return s;
|
|
142
|
+
drawValue -= s.weight;
|
|
143
|
+
}
|
|
144
|
+
return symbols[0];
|
|
145
|
+
}
|
|
146
|
+
getBetStake(params, config) {
|
|
147
|
+
const baseBet = config.baseGame.baseGameConfig.baseBet;
|
|
148
|
+
return number_helper_1.NumberHelper.safeDivide(params.betAmount, params.creditsPerLine === baseBet ? params.creditsPerLine : baseBet, 3);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
exports.CollectFeatureBonusHandler = CollectFeatureBonusHandler;
|
|
152
|
+
//# sourceMappingURL=collect-feature-bonus.handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect-feature-bonus.handler.js","sourceRoot":"","sources":["../../../src/logic/handlers/collect-feature-bonus.handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FreeSpinsBonusHandler = void 0;
|
|
4
|
+
const bonnys_fortune_types_1 = require("../bonnys-fortune.types");
|
|
5
|
+
const bonnys_fortune_spin_generator_1 = require("../bonnys-fortune.spin-generator");
|
|
6
|
+
const bonnys_fortune_win_calculator_1 = require("../bonnys-fortune.win-calculator");
|
|
7
|
+
const number_helper_1 = require("../../helpers/number-helper");
|
|
8
|
+
class FreeSpinsBonusHandler {
|
|
9
|
+
constructor(rngService) {
|
|
10
|
+
this.rngService = rngService;
|
|
11
|
+
}
|
|
12
|
+
async generateFullBonusRound(params, publicState, privateState, config, reelStripsConfig, commandId) {
|
|
13
|
+
const betStake = this.getBetStake(params, config);
|
|
14
|
+
const spinGenerator = new bonnys_fortune_spin_generator_1.BonnysFortuneSpinGenerator(this.rngService);
|
|
15
|
+
const spinTypes = config.bonusGames.bonusGame2.config.spinTypes;
|
|
16
|
+
const weights = spinTypes.map((st) => st.weight);
|
|
17
|
+
const total = weights.reduce((a, b) => number_helper_1.NumberHelper.safeSum(a, b, 2), 0);
|
|
18
|
+
const result = await this.rngService.getSingleNumber(0, total - 1, commandId, 'free_spins_type_selection');
|
|
19
|
+
const rand = result.value;
|
|
20
|
+
let spinTypeIndex = 0;
|
|
21
|
+
let cumulative = 0;
|
|
22
|
+
for (let i = 0; i < weights.length; i++) {
|
|
23
|
+
cumulative += weights[i];
|
|
24
|
+
if (rand < cumulative) {
|
|
25
|
+
spinTypeIndex = i;
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const spinTypeConfig = spinTypes[spinTypeIndex];
|
|
30
|
+
const results = [];
|
|
31
|
+
let spinsLeft = spinTypeConfig.spins;
|
|
32
|
+
while (spinsLeft > 0) {
|
|
33
|
+
const screen = await spinGenerator.generateScreenWithLayout(reelStripsConfig, spinTypeConfig.layout, spinTypeConfig.reelsOptionsWeights, commandId, `free_spin_${spinsLeft}`);
|
|
34
|
+
const winResult = bonnys_fortune_win_calculator_1.BonnysFortuneWinCalculator.calculateWins(screen, config, number_helper_1.NumberHelper.toFixedNumber(betStake, 2), number_helper_1.NumberHelper.toFixedNumber(spinTypeConfig.multiplier, 2), bonnys_fortune_types_1.SpinType.BONUS_GAME_2_SPIN, spinTypeIndex);
|
|
35
|
+
results.push({
|
|
36
|
+
result: {
|
|
37
|
+
spinType: bonnys_fortune_types_1.SpinType.BONUS_GAME_2_SPIN,
|
|
38
|
+
screen,
|
|
39
|
+
winResult,
|
|
40
|
+
playerWinning: number_helper_1.NumberHelper.toFixedNumber(winResult.totalWin, 2),
|
|
41
|
+
nextSpinType: spinsLeft === 1
|
|
42
|
+
? bonnys_fortune_types_1.SpinType.BASE_GAME_SPIN
|
|
43
|
+
: bonnys_fortune_types_1.SpinType.BONUS_GAME_2_SPIN,
|
|
44
|
+
multiplier: number_helper_1.NumberHelper.toFixedNumber(spinTypeConfig.multiplier, 2),
|
|
45
|
+
},
|
|
46
|
+
publicState: publicState,
|
|
47
|
+
privateState: {
|
|
48
|
+
...privateState,
|
|
49
|
+
nextSpinType: spinsLeft === 1
|
|
50
|
+
? bonnys_fortune_types_1.SpinType.BASE_GAME_SPIN
|
|
51
|
+
: bonnys_fortune_types_1.SpinType.BONUS_GAME_2_SPIN,
|
|
52
|
+
activeBonus: spinsLeft === 1 ? undefined : privateState.activeBonus,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
spinsLeft--;
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
results,
|
|
59
|
+
publicState,
|
|
60
|
+
privateState,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
getBetStake(params, config) {
|
|
64
|
+
const baseBet = config.baseGame.baseGameConfig.baseBet;
|
|
65
|
+
return number_helper_1.NumberHelper.safeDivide(params.betAmount, params.creditsPerLine === baseBet ? params.creditsPerLine : baseBet, 3);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.FreeSpinsBonusHandler = FreeSpinsBonusHandler;
|
|
69
|
+
//# sourceMappingURL=free-spins-bonus.handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"free-spins-bonus.handler.js","sourceRoot":"","sources":["../../../src/logic/handlers/free-spins-bonus.handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SteeringToTheFortuneBonusHandler = void 0;
|
|
4
|
+
const bonnys_fortune_types_1 = require("../bonnys-fortune.types");
|
|
5
|
+
const number_helper_1 = require("../../helpers/number-helper");
|
|
6
|
+
const uuid_helper_1 = require("../../helpers/uuid-helper");
|
|
7
|
+
const base_game_handler_1 = require("./base-game.handler");
|
|
8
|
+
class SteeringToTheFortuneBonusHandler {
|
|
9
|
+
constructor(rngService) {
|
|
10
|
+
this.rngService = rngService;
|
|
11
|
+
}
|
|
12
|
+
async generateFullBonusRound(params, publicState, privateState, config, commandId) {
|
|
13
|
+
const betStake = this.getBetStake(params, config);
|
|
14
|
+
const wheelResults = config.bonusGames.bonusGame3.config.wheelResults;
|
|
15
|
+
const selectedIndex = await this.weightedDraw(wheelResults.map((w) => w.weight), commandId, 'steering_fortune_wheel_selection');
|
|
16
|
+
const prize = wheelResults[selectedIndex];
|
|
17
|
+
let playerWinning = 0;
|
|
18
|
+
let nextSpinType = bonnys_fortune_types_1.SpinType.BASE_GAME_SPIN;
|
|
19
|
+
let triggeredBonus;
|
|
20
|
+
if (prize.type === bonnys_fortune_types_1.PrizeType.MULTIPLIER) {
|
|
21
|
+
playerWinning = number_helper_1.NumberHelper.safeMultiply(betStake, prize.value, 2);
|
|
22
|
+
}
|
|
23
|
+
else if (prize.type === bonnys_fortune_types_1.PrizeType.BONUS) {
|
|
24
|
+
triggeredBonus = {
|
|
25
|
+
bonusId: uuid_helper_1.UuidHelper.generateUuid(),
|
|
26
|
+
bonusType: prize.bonusType,
|
|
27
|
+
betAmount: number_helper_1.NumberHelper.toFixedNumber(params.betAmount, 2),
|
|
28
|
+
};
|
|
29
|
+
nextSpinType = (0, base_game_handler_1.getSpinTypeForBonus)(prize.bonusType);
|
|
30
|
+
}
|
|
31
|
+
const results = [
|
|
32
|
+
{
|
|
33
|
+
result: {
|
|
34
|
+
spinType: bonnys_fortune_types_1.SpinType.BONUS_GAME_3_SPIN,
|
|
35
|
+
playerWinning,
|
|
36
|
+
nextSpinType,
|
|
37
|
+
prizeType: prize.type,
|
|
38
|
+
prizeValue: prize.type === bonnys_fortune_types_1.PrizeType.MULTIPLIER ? prize.value : prize.bonusType,
|
|
39
|
+
totalMultiplier: prize.type === bonnys_fortune_types_1.PrizeType.MULTIPLIER ? prize.value : 0,
|
|
40
|
+
triggeredBonus,
|
|
41
|
+
},
|
|
42
|
+
publicState,
|
|
43
|
+
privateState: {
|
|
44
|
+
...privateState,
|
|
45
|
+
nextSpinType,
|
|
46
|
+
pendingBonuses: triggeredBonus ? [triggeredBonus] : [],
|
|
47
|
+
activeBonus: undefined,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
return {
|
|
52
|
+
results,
|
|
53
|
+
publicState,
|
|
54
|
+
privateState,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
async weightedDraw(weights, commandId, actionId) {
|
|
58
|
+
const sum = weights.reduce((acc, w) => number_helper_1.NumberHelper.safeSum(acc, w, 2), 0);
|
|
59
|
+
const result = await this.rngService.getSingleNumber(0, sum - 1, commandId, actionId);
|
|
60
|
+
const draw = result.value;
|
|
61
|
+
let cumulative = 0;
|
|
62
|
+
for (let i = 0; i < weights.length; i++) {
|
|
63
|
+
cumulative = number_helper_1.NumberHelper.safeSum(cumulative, weights[i], 2);
|
|
64
|
+
if (draw < cumulative)
|
|
65
|
+
return i;
|
|
66
|
+
}
|
|
67
|
+
return weights.length - 1;
|
|
68
|
+
}
|
|
69
|
+
getBetStake(params, config) {
|
|
70
|
+
const baseBet = config.baseGame.baseGameConfig.baseBet;
|
|
71
|
+
return number_helper_1.NumberHelper.safeDivide(params.betAmount, params.creditsPerLine === baseBet ? params.creditsPerLine : baseBet, 3);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.SteeringToTheFortuneBonusHandler = SteeringToTheFortuneBonusHandler;
|
|
75
|
+
//# sourceMappingURL=steering-to-the-fortune-bonus.handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"steering-to-the-fortune-bonus.handler.js","sourceRoot":"","sources":["../../../src/logic/handlers/steering-to-the-fortune-bonus.handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TreasureHuntBonusHandler = void 0;
|
|
4
|
+
const bonnys_fortune_types_1 = require("../bonnys-fortune.types");
|
|
5
|
+
const number_helper_1 = require("../../helpers/number-helper");
|
|
6
|
+
class TreasureHuntBonusHandler {
|
|
7
|
+
constructor(rngService) {
|
|
8
|
+
this.rngService = rngService;
|
|
9
|
+
}
|
|
10
|
+
async generateFullBonusRound(params, publicState, privateState, config, commandId) {
|
|
11
|
+
const betStake = this.getBetStake(params, config);
|
|
12
|
+
const { stepsCount, jackpotScreenCounts, jackpotMultipliers, winningWeights, } = this.extractBonusConfig(config);
|
|
13
|
+
const jackpotKeys = Object.keys(jackpotMultipliers);
|
|
14
|
+
const jackpotsNo = Object.values(jackpotScreenCounts);
|
|
15
|
+
const weightsArray = Object.values(winningWeights);
|
|
16
|
+
const winSymbolIndex = await this.drawWinningSymbol(weightsArray, commandId);
|
|
17
|
+
const selectionsVector = Array(stepsCount).fill(-1);
|
|
18
|
+
if (winSymbolIndex >= 0) {
|
|
19
|
+
const positions = await this.randomPositions(stepsCount, 3, commandId);
|
|
20
|
+
positions.forEach((pos) => (selectionsVector[pos] = winSymbolIndex));
|
|
21
|
+
jackpotsNo[winSymbolIndex] = number_helper_1.NumberHelper.safeSum(jackpotsNo[winSymbolIndex], -3, 0);
|
|
22
|
+
}
|
|
23
|
+
await this.fillRemainingSteps(selectionsVector, stepsCount, jackpotsNo, winSymbolIndex, commandId);
|
|
24
|
+
const selections = selectionsVector.map((idx) => jackpotKeys[idx]);
|
|
25
|
+
const multipliers = selections.map((name) => jackpotMultipliers[name]);
|
|
26
|
+
const results = selections.map((symbol, index) => {
|
|
27
|
+
const isFinalStep = index === stepsCount - 1;
|
|
28
|
+
const winningMultiplier = isFinalStep && winSymbolIndex >= 0
|
|
29
|
+
? jackpotMultipliers[jackpotKeys[winSymbolIndex]]
|
|
30
|
+
: 0;
|
|
31
|
+
const playerWinning = isFinalStep && winSymbolIndex >= 0
|
|
32
|
+
? number_helper_1.NumberHelper.safeMultiply(betStake, winningMultiplier, 2)
|
|
33
|
+
: 0;
|
|
34
|
+
return {
|
|
35
|
+
result: {
|
|
36
|
+
spinType: bonnys_fortune_types_1.SpinType.BONUS_GAME_1_SPIN,
|
|
37
|
+
playerWinning,
|
|
38
|
+
nextSpinType: isFinalStep
|
|
39
|
+
? bonnys_fortune_types_1.SpinType.BASE_GAME_SPIN
|
|
40
|
+
: bonnys_fortune_types_1.SpinType.BONUS_GAME_1_SPIN,
|
|
41
|
+
selection: symbol,
|
|
42
|
+
multiplier: multipliers[index],
|
|
43
|
+
multiplierCounts: selections.slice(0, index + 1).reduce((acc, key) => {
|
|
44
|
+
acc[key] = (acc[key] || 0) + 1;
|
|
45
|
+
return acc;
|
|
46
|
+
}, {}),
|
|
47
|
+
winningMultiplier,
|
|
48
|
+
winningCount: isFinalStep && winSymbolIndex >= 0 ? 3 : 0,
|
|
49
|
+
totalMultiplier: winningMultiplier,
|
|
50
|
+
},
|
|
51
|
+
publicState,
|
|
52
|
+
privateState: {
|
|
53
|
+
...privateState,
|
|
54
|
+
nextSpinType: isFinalStep
|
|
55
|
+
? bonnys_fortune_types_1.SpinType.BASE_GAME_SPIN
|
|
56
|
+
: bonnys_fortune_types_1.SpinType.BONUS_GAME_1_SPIN,
|
|
57
|
+
activeBonus: isFinalStep ? undefined : privateState.activeBonus,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
results,
|
|
63
|
+
publicState,
|
|
64
|
+
privateState,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
getBetStake(params, config) {
|
|
68
|
+
const baseBet = config.baseGame.baseGameConfig.baseBet;
|
|
69
|
+
return number_helper_1.NumberHelper.safeDivide(params.betAmount, params.creditsPerLine === baseBet ? params.creditsPerLine : baseBet, 3);
|
|
70
|
+
}
|
|
71
|
+
async drawWinningSymbol(weights, commandId) {
|
|
72
|
+
const total = weights.reduce((acc, w) => number_helper_1.NumberHelper.safeSum(acc, w, 2), 0);
|
|
73
|
+
if (total === 0)
|
|
74
|
+
return -1;
|
|
75
|
+
const result = await this.rngService.getSingleNumber(0, total - 1, commandId, 'treasure_hunt_winning_symbol');
|
|
76
|
+
const draw = result.value;
|
|
77
|
+
let cumulative = 0;
|
|
78
|
+
for (let i = 0; i < weights.length; i++) {
|
|
79
|
+
cumulative = number_helper_1.NumberHelper.safeSum(cumulative, weights[i], 2);
|
|
80
|
+
if (draw < cumulative)
|
|
81
|
+
return i;
|
|
82
|
+
}
|
|
83
|
+
return -1;
|
|
84
|
+
}
|
|
85
|
+
async fillRemainingSteps(vector, stepsCount, jackpotsNo, excludeSymbol, commandId) {
|
|
86
|
+
const weights = jackpotsNo.map((_, idx) => idx === excludeSymbol ? 0 : 4);
|
|
87
|
+
for (let i = 0; i < stepsCount; i++) {
|
|
88
|
+
if (vector[i] < 0) {
|
|
89
|
+
const symbol = await this.weightedDraw(weights, commandId, `fill_step_${i}`);
|
|
90
|
+
vector[i] = symbol;
|
|
91
|
+
jackpotsNo[symbol] = number_helper_1.NumberHelper.safeSum(jackpotsNo[symbol], -1, 0);
|
|
92
|
+
weights[symbol] = Math.max(0, weights[symbol] - 2);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async weightedDraw(weights, commandId, actionId) {
|
|
97
|
+
const sum = weights.reduce((acc, w) => number_helper_1.NumberHelper.safeSum(acc, w, 2), 0);
|
|
98
|
+
if (sum === 0)
|
|
99
|
+
return 0;
|
|
100
|
+
const result = await this.rngService.getSingleNumber(0, sum - 1, commandId, actionId);
|
|
101
|
+
const draw = result.value;
|
|
102
|
+
let cumulative = 0;
|
|
103
|
+
for (let i = 0; i < weights.length; i++) {
|
|
104
|
+
cumulative = number_helper_1.NumberHelper.safeSum(cumulative, weights[i], 2);
|
|
105
|
+
if (draw < cumulative)
|
|
106
|
+
return i;
|
|
107
|
+
}
|
|
108
|
+
return weights.length - 1;
|
|
109
|
+
}
|
|
110
|
+
async randomPositions(limit, count, commandId) {
|
|
111
|
+
const positions = Array.from({ length: limit }, (_, i) => i);
|
|
112
|
+
const selected = [];
|
|
113
|
+
while (selected.length < count) {
|
|
114
|
+
const actionId = `random_position_${selected.length}`;
|
|
115
|
+
const result = await this.rngService.getSingleNumber(0, positions.length - 1, commandId, actionId);
|
|
116
|
+
const idx = result.value;
|
|
117
|
+
selected.push(positions.splice(idx, 1)[0]);
|
|
118
|
+
}
|
|
119
|
+
return selected;
|
|
120
|
+
}
|
|
121
|
+
extractBonusConfig(config) {
|
|
122
|
+
return {
|
|
123
|
+
stepsCount: config.bonusGames.bonusGame1.config.stepsCount,
|
|
124
|
+
jackpotMultipliers: config.bonusGames.bonusGame1.config.jackpotMultipliers,
|
|
125
|
+
winningWeights: config.bonusGames.bonusGame1.config.winningWeights,
|
|
126
|
+
jackpotScreenCounts: config.bonusGames.bonusGame1.config.jackpotScreenCounts,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
exports.TreasureHuntBonusHandler = TreasureHuntBonusHandler;
|
|
131
|
+
//# sourceMappingURL=treasure-hunt-bonus.handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"treasure-hunt-bonus.handler.js","sourceRoot":"","sources":["../../../src/logic/handlers/treasure-hunt-bonus.handler.ts"],"names":[],"mappings":"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"}
|