@omnitronix/bonnys-fortune-game-engine 1.7.2 → 1.8.0

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 (79) hide show
  1. package/dist/__tests__/base-game.test.js +17 -10
  2. package/dist/__tests__/base-game.test.js.map +1 -1
  3. package/dist/__tests__/bonus-handlers.test.js +15 -21
  4. package/dist/__tests__/bonus-handlers.test.js.map +1 -1
  5. package/dist/__tests__/bonus-meters.test.js.map +1 -1
  6. package/dist/__tests__/collect-feature-handler.test.js +30 -24
  7. package/dist/__tests__/collect-feature-handler.test.js.map +1 -1
  8. package/dist/__tests__/comprehensive.test.js.map +1 -1
  9. package/dist/__tests__/error-paths.test.js +11 -7
  10. package/dist/__tests__/error-paths.test.js.map +1 -1
  11. package/dist/__tests__/helpers/test-engine-factory.d.ts +72 -18
  12. package/dist/__tests__/helpers/test-engine-factory.js +32 -7
  13. package/dist/__tests__/helpers/test-engine-factory.js.map +1 -1
  14. package/dist/__tests__/integration-1000-spin.test.js +33 -37
  15. package/dist/__tests__/integration-1000-spin.test.js.map +1 -1
  16. package/dist/__tests__/rng-gli19-compliance.test.js.map +1 -1
  17. package/dist/__tests__/rng-security.test.js +0 -1
  18. package/dist/__tests__/rng-security.test.js.map +1 -1
  19. package/dist/__tests__/rtp-simulation.test.js +11 -10
  20. package/dist/__tests__/rtp-simulation.test.js.map +1 -1
  21. package/dist/__tests__/state-transitions.test.js +0 -1
  22. package/dist/__tests__/state-transitions.test.js.map +1 -1
  23. package/dist/__tests__/steering-fortune-handler.test.js +18 -14
  24. package/dist/__tests__/steering-fortune-handler.test.js.map +1 -1
  25. package/dist/__tests__/symbol-distribution.test.js +13 -16
  26. package/dist/__tests__/symbol-distribution.test.js.map +1 -1
  27. package/dist/__tests__/treasure-hunt-handler.test.js +23 -16
  28. package/dist/__tests__/treasure-hunt-handler.test.js.map +1 -1
  29. package/dist/__tests__/win-calculator.test.js +10 -7
  30. package/dist/__tests__/win-calculator.test.js.map +1 -1
  31. package/dist/bonnys-fortune-v1.game-engine.d.ts +3 -3
  32. package/dist/bonnys-fortune-v1.game-engine.js +8 -5
  33. package/dist/bonnys-fortune-v1.game-engine.js.map +1 -1
  34. package/dist/game-engine.interface.d.ts +1 -1
  35. package/dist/helpers/optional-boolean-mapper.d.ts +1 -1
  36. package/dist/helpers/validation-helper.d.ts +1 -1
  37. package/dist/logic/bonnys-fortune.game-logic.js +2 -0
  38. package/dist/logic/bonnys-fortune.game-logic.js.map +1 -1
  39. package/dist/logic/bonnys-fortune.types.d.ts +7 -1
  40. package/dist/logic/handlers/collect-feature-bonus.handler.js.map +1 -1
  41. package/dist/logic/handlers/steering-to-the-fortune-bonus.handler.js +6 -5
  42. package/dist/logic/handlers/steering-to-the-fortune-bonus.handler.js.map +1 -1
  43. package/dist/logic/handlers/treasure-hunt-bonus.handler.js.map +1 -1
  44. package/dist/rng/rng-client.factory.js +3 -3
  45. package/dist/rng/rng-client.factory.js.map +1 -1
  46. package/dist/validation/bonnys-fortune/bonnys-fortune-config.dto.js.map +1 -1
  47. package/dist/validation/custom-decorators/IsNestedIntArray.js.map +1 -1
  48. package/dist/validation/game-logic-config-validation.service.d.ts +1 -1
  49. package/dist/validation/game-logic-config-validation.service.js.map +1 -1
  50. package/package.json +3 -3
  51. package/src/__tests__/base-game.test.ts +26 -17
  52. package/src/__tests__/bonus-handlers.test.ts +16 -21
  53. package/src/__tests__/bonus-meters.test.ts +13 -8
  54. package/src/__tests__/collect-feature-handler.test.ts +39 -26
  55. package/src/__tests__/comprehensive.test.ts +40 -36
  56. package/src/__tests__/error-paths.test.ts +29 -18
  57. package/src/__tests__/helpers/test-engine-factory.ts +127 -40
  58. package/src/__tests__/integration-1000-spin.test.ts +53 -48
  59. package/src/__tests__/rng-gli19-compliance.test.ts +17 -17
  60. package/src/__tests__/rng-security.test.ts +11 -8
  61. package/src/__tests__/rtp-simulation.test.ts +17 -10
  62. package/src/__tests__/state-transitions.test.ts +8 -4
  63. package/src/__tests__/steering-fortune-handler.test.ts +30 -18
  64. package/src/__tests__/symbol-distribution.test.ts +19 -16
  65. package/src/__tests__/treasure-hunt-handler.test.ts +36 -22
  66. package/src/__tests__/win-calculator.test.ts +14 -10
  67. package/src/bonnys-fortune-v1.game-engine.ts +18 -8
  68. package/src/domain/types/game-symbols.response.dto.ts +1 -1
  69. package/src/game-engine.interface.ts +1 -1
  70. package/src/helpers/validation-helper.ts +1 -1
  71. package/src/logic/bonnys-fortune.game-logic.ts +3 -0
  72. package/src/logic/bonnys-fortune.types.ts +10 -1
  73. package/src/logic/handlers/collect-feature-bonus.handler.ts +5 -2
  74. package/src/logic/handlers/steering-to-the-fortune-bonus.handler.ts +7 -6
  75. package/src/logic/handlers/treasure-hunt-bonus.handler.ts +2 -2
  76. package/src/rng/rng-client.factory.ts +3 -3
  77. package/src/validation/bonnys-fortune/bonnys-fortune-config.dto.ts +72 -72
  78. package/src/validation/custom-decorators/IsNestedIntArray.ts +1 -1
  79. package/src/validation/game-logic-config-validation.service.ts +2 -2
@@ -20,6 +20,7 @@ import {
20
20
  executeSpin,
21
21
  resetCommandIdCounter,
22
22
  MockRngClient,
23
+ getOutcome,
23
24
  } from './helpers/test-engine-factory';
24
25
 
25
26
  describe('Win Calculator - Bonnys Fortune', () => {
@@ -766,11 +767,12 @@ describe('Win Calculator - Bonnys Fortune', () => {
766
767
 
767
768
  expect(result.success).toBe(true);
768
769
 
770
+ const outcomeW = getOutcome(result);
769
771
  const winResult =
770
- result.outcome?.result?.winResult ?? result.outcome?.winResult;
772
+ outcomeW.result?.winResult ?? outcomeW.winResult;
771
773
  if (winResult) {
772
- expect(winResult.totalWin).toBeGreaterThanOrEqual(0);
773
- expect(Array.isArray(winResult.winningLines)).toBe(true);
774
+ expect((winResult as { totalWin: number }).totalWin).toBeGreaterThanOrEqual(0);
775
+ expect(Array.isArray((winResult as { winningLines: unknown[] }).winningLines)).toBe(true);
774
776
  }
775
777
  });
776
778
 
@@ -789,14 +791,16 @@ describe('Win Calculator - Bonnys Fortune', () => {
789
791
 
790
792
  expect(result.success).toBe(true);
791
793
 
794
+ const outcomeM = getOutcome(result);
792
795
  const screen =
793
- result.outcome?.result?.screen ??
794
- result.outcome?.screen ??
796
+ outcomeM.result?.screen ??
797
+ outcomeM.screen ??
795
798
  result.privateState.screen;
796
- const winResult =
797
- result.outcome?.result?.winResult ?? result.outcome?.winResult;
799
+ const winResult2 =
800
+ outcomeM.result?.winResult ?? outcomeM.winResult;
798
801
 
799
- if (screen && winResult) {
802
+ if (screen && winResult2) {
803
+ const wr = winResult2 as { totalWin: number; winningLines: unknown[] };
800
804
  // Recalculate using the win calculator directly
801
805
  const directResult = BonnysFortuneWinCalculator.calculateWins(
802
806
  screen,
@@ -806,9 +810,9 @@ describe('Win Calculator - Bonnys Fortune', () => {
806
810
  SpinType.BASE_GAME_SPIN,
807
811
  );
808
812
 
809
- expect(directResult.totalWin).toBe(winResult.totalWin);
813
+ expect(directResult.totalWin).toBe(wr.totalWin);
810
814
  expect(directResult.winningLines.length).toBe(
811
- winResult.winningLines.length,
815
+ wr.winningLines.length,
812
816
  );
813
817
  }
814
818
  });
@@ -1,6 +1,8 @@
1
1
  import {
2
2
  BonnysFortunePrivateState,
3
3
  BonnysFortunePublicState,
4
+ BonnysFortuneOutcome,
5
+ StartBonusRoundResult,
4
6
  SpinResult as LocalSpinResult,
5
7
  } from './logic/bonnys-fortune.types';
6
8
  import {
@@ -50,6 +52,7 @@ import { ReelStripsConfig } from './domain/reel-strips-config';
50
52
  import { ReelStripsConfigLoader } from './config/reel-strips-config/reel-strips-config-loader';
51
53
  import { ReelStripsConfigMapper } from './domain/mappers/reel-strips-config.mapper';
52
54
  import { ReelStripsConfigValidationService } from './validation/reel-strips-config-validation.service';
55
+ import { RngClientConfig } from '@omnitronix/rng-client-core';
53
56
  import { RngClientFactory } from './rng/rng-client.factory';
54
57
  import { RngService } from './rng/rng-service';
55
58
  import { StartBonusRoundCommand } from './domain/types/start-bonus-round-command';
@@ -65,7 +68,7 @@ export interface BonnysFortuneV1GameEngineConfig {
65
68
  export class BonnysFortuneV1GameEngine
66
69
  extends SlotGameHandler
67
70
  implements
68
- GameEngine<BonnysFortunePublicState, BonnysFortunePrivateState, any>,
71
+ GameEngine<BonnysFortunePublicState, BonnysFortunePrivateState, BonnysFortuneOutcome>,
69
72
  DebugIntrospectable
70
73
  {
71
74
  /**
@@ -111,7 +114,7 @@ export class BonnysFortuneV1GameEngine
111
114
  this.configOutPort = new FileSystemGameLogicConfigLoader();
112
115
  this.reelsOutPort = new FileSystemReelStripsConfigLoader();
113
116
 
114
- const rngClient = RngClientFactory.create({ metrics: config.metrics });
117
+ const rngClient = RngClientFactory.create({ metrics: config.metrics as RngClientConfig['metrics'] });
115
118
  this.rngService = new RngService(rngClient);
116
119
 
117
120
  this.configValidator = new GameLogicConfigValidationService();
@@ -334,7 +337,7 @@ export class BonnysFortuneV1GameEngine
334
337
  CommandProcessingResult<
335
338
  BonnysFortunePublicState,
336
339
  BonnysFortunePrivateState,
337
- any
340
+ BonnysFortuneOutcome
338
341
  >
339
342
  > {
340
343
  this.logger.log(`Processing command ${command.type}`);
@@ -424,15 +427,22 @@ export class BonnysFortuneV1GameEngine
424
427
  getResultsArray: () => outcome.results ?? [],
425
428
  };
426
429
 
430
+ // The SDK platform expects deliveryStrategy and nextSpinType on the outcome
431
+ // These are SDK-level extensions not part of the game engine's BonnysFortuneOutcome type
432
+ const bonusOutcome: StartBonusRoundResult & {
433
+ nextSpinType: typeof nextSpinType;
434
+ deliveryStrategy: BonusResultDeliveryStrategy;
435
+ } = {
436
+ ...outcome,
437
+ nextSpinType, // Required by platform-connect SDK to set CurrentSpinType
438
+ deliveryStrategy,
439
+ };
440
+
427
441
  return {
428
442
  success: true,
429
443
  publicState: outcome.publicState,
430
444
  privateState: outcome.privateState,
431
- outcome: {
432
- ...outcome,
433
- nextSpinType, // Required by platform-connect SDK to set CurrentSpinType
434
- deliveryStrategy,
435
- },
445
+ outcome: bonusOutcome as BonnysFortuneOutcome,
436
446
  message: 'Bonus round started',
437
447
  rngOutcome,
438
448
  };
@@ -7,5 +7,5 @@ export interface GameSymbol {
7
7
  }
8
8
 
9
9
  export class GameSymbolsResponseDto {
10
- public symbols: GameSymbol[];
10
+ public symbols!: GameSymbol[];
11
11
  }
@@ -11,7 +11,7 @@ export {
11
11
  } from '@omnitronix/game-engine-contract';
12
12
 
13
13
  // Local types specific to this game engine
14
- export type GameEngineMetricsHandlers = RngClientConfig['metrics']['handlers'];
14
+ export type GameEngineMetricsHandlers = NonNullable<RngClientConfig['metrics']>['handlers'];
15
15
  export interface GameEngineConfig {
16
16
  metrics?: {
17
17
  handlers: GameEngineMetricsHandlers;
@@ -21,7 +21,7 @@ export class ValidationHelper {
21
21
  return validate(dto, ValidationHelper.validationOptionsWithoutForbidden);
22
22
  }
23
23
 
24
- public static isPlainObject(value: unknown): value is Record<string, any> {
24
+ public static isPlainObject(value: unknown): value is Record<string, unknown> {
25
25
  return typeof value === 'object' && value !== null && !Array.isArray(value);
26
26
  }
27
27
  }
@@ -228,6 +228,9 @@ export class BonnysFortuneGameLogic {
228
228
  activeBonus,
229
229
  };
230
230
  }
231
+
232
+ default:
233
+ throw new Error(`Unknown bonus type: ${normalizedBonusType}`);
231
234
  }
232
235
  }
233
236
 
@@ -218,11 +218,20 @@ export interface GetSymbolsResult {
218
218
  symbols: GetSymbolsOutcome[];
219
219
  }
220
220
 
221
+ /** Outcome returned by the INIT_SESSION_STATE command. */
222
+ export interface InitSessionOutcome {
223
+ publicState: BonnysFortunePublicState;
224
+ privateState: BonnysFortunePrivateState;
225
+ }
226
+
227
+ /** Union of all possible outcome types returned by processCommand. */
221
228
  export type BonnysFortuneOutcome =
222
229
  | BonnysFortuneGameLogicSpinResult
223
230
  | BonnysFortuneBonusGameLogicSpinResult
231
+ | StartBonusRoundResult
232
+ | InitSessionOutcome
224
233
  | SymbolsCountMatrix
225
234
  | DebugTriggerBonusOutcome
226
235
  | DebugUpdateBonusMeterProgressOutcome
227
- | GetSymbolsOutcome
236
+ | GetSymbolsResult
228
237
  | null;
@@ -6,7 +6,10 @@ import {
6
6
  SpinType,
7
7
  } from '../bonnys-fortune.types';
8
8
 
9
- import { BonnysFortuneGameLogicConfigInterface } from '../game-logic-config.interface';
9
+ import {
10
+ BonnysFortuneGameLogicConfigInterface,
11
+ ScatterGameConfig,
12
+ } from '../game-logic-config.interface';
10
13
  import { GameSpinInputDto } from '../../domain/types/game-spin-input.dto';
11
14
  import { NumberHelper } from '../../helpers/number-helper';
12
15
  import { RngService } from '../../rng/rng-service';
@@ -102,7 +105,7 @@ export class CollectFeatureBonusHandler {
102
105
  totalMultipliers: number,
103
106
  totalWin: number,
104
107
  betGame: number,
105
- scatterConfig: any,
108
+ scatterConfig: ScatterGameConfig,
106
109
  checkpoints: number[],
107
110
  publicState: BonnysFortunePublicState,
108
111
  privateState: BonnysFortunePrivateState,
@@ -41,17 +41,18 @@ export class SteeringToTheFortuneBonusHandler {
41
41
  let triggeredBonus: BonusTrigger | undefined;
42
42
 
43
43
  if (prize.type === PrizeType.MULTIPLIER) {
44
- playerWinning = NumberHelper.safeMultiply(betStake, prize.value, 2);
44
+ playerWinning = NumberHelper.safeMultiply(betStake, prize.value ?? 0, 2);
45
45
  } else if (prize.type === PrizeType.BONUS) {
46
+ const bonusType = prize.bonusType ?? 'bonusGame1';
46
47
  triggeredBonus = {
47
48
  bonusId: UuidHelper.generateUuid(),
48
- bonusType: prize.bonusType,
49
+ bonusType,
49
50
  betAmount: NumberHelper.toFixedNumber(params.betAmount, 2),
50
51
  };
51
- nextSpinType = getSpinTypeForBonus(prize.bonusType);
52
+ nextSpinType = getSpinTypeForBonus(bonusType);
52
53
  }
53
54
 
54
- const results = [
55
+ const results: SpinResultResponse<SteeringToTheFortuneResult>[] = [
55
56
  {
56
57
  result: {
57
58
  spinType: SpinType.BONUS_GAME_3_SPIN,
@@ -59,9 +60,9 @@ export class SteeringToTheFortuneBonusHandler {
59
60
  nextSpinType,
60
61
  prizeType: prize.type,
61
62
  prizeValue:
62
- prize.type === PrizeType.MULTIPLIER ? prize.value : prize.bonusType,
63
+ prize.type === PrizeType.MULTIPLIER ? (prize.value ?? 0) : (prize.bonusType ?? ''),
63
64
  totalMultiplier:
64
- prize.type === PrizeType.MULTIPLIER ? prize.value : 0,
65
+ prize.type === PrizeType.MULTIPLIER ? (prize.value ?? 0) : 0,
65
66
  triggeredBonus,
66
67
  // BaseOutcome standardized fields
67
68
  actionType: SpinType.BONUS_GAME_3_SPIN,
@@ -64,14 +64,14 @@ export class TreasureHuntBonusHandler {
64
64
  // Player only sees the first stepsCount (6) positions
65
65
  const playerSelections = selectionsVector.slice(0, stepsCount);
66
66
  const selections = playerSelections.map((idx) => jackpotKeys[idx]);
67
- const multipliers = selections.map((name) => jackpotMultipliers[name]);
67
+ const multipliers = selections.map((name) => (jackpotMultipliers as Record<string, number>)[name]);
68
68
 
69
69
  const results = selections.map((symbol, index) => {
70
70
  const isFinalStep = index === stepsCount - 1;
71
71
 
72
72
  const winningMultiplier =
73
73
  isFinalStep && winSymbolIndex >= 0
74
- ? jackpotMultipliers[jackpotKeys[winSymbolIndex]]
74
+ ? (jackpotMultipliers as Record<string, number>)[jackpotKeys[winSymbolIndex]]
75
75
  : 0;
76
76
  const playerWinning =
77
77
  isFinalStep && winSymbolIndex >= 0
@@ -15,9 +15,9 @@ export class RngClientFactory {
15
15
  }
16
16
 
17
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',
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') ?? 'rest',
21
21
  poolingSize: parseInt(process.env.RNG_CLIENT_POOL_SIZE || '2000'),
22
22
  metrics: config.metrics,
23
23
  };
@@ -15,109 +15,109 @@ import {
15
15
 
16
16
  export class SymbolMultipliersDto {
17
17
  @IsInt()
18
- public symbolId: number;
18
+ public symbolId!: number;
19
19
 
20
20
  @IsString()
21
- public name: string;
21
+ public name!: string;
22
22
 
23
23
  @IsObject()
24
- public multipliers: Record<'x3' | 'x4' | 'x5', number>;
24
+ public multipliers!: Record<'x3' | 'x4' | 'x5', number>;
25
25
 
26
26
  @IsBoolean()
27
- public isWild: boolean;
27
+ public isWild!: boolean;
28
28
 
29
29
  @IsBoolean()
30
- public isScatter: boolean;
30
+ public isScatter!: boolean;
31
31
  }
32
32
 
33
33
  // --- SymbolDefinitions ---
34
34
 
35
35
  export class CollectFeatureSymbolsDto {
36
36
  @IsObject()
37
- public multipliers: Record<string, number>;
37
+ public multipliers!: Record<string, number>;
38
38
 
39
39
  @IsObject()
40
- public values: Record<string, number>;
40
+ public values!: Record<string, number>;
41
41
  }
42
42
 
43
43
  export class SymbolRangeDto {
44
44
  @IsInt()
45
- public minIndex: number;
45
+ public minIndex!: number;
46
46
 
47
47
  @IsInt()
48
- public maxIndex: number;
48
+ public maxIndex!: number;
49
49
  }
50
50
 
51
51
  export class SymbolDefinitionsDto {
52
52
  @ValidateNested()
53
53
  @Type(() => SymbolRangeDto)
54
- public baseSymbols: SymbolRangeDto;
54
+ public baseSymbols!: SymbolRangeDto;
55
55
 
56
56
  @IsObject()
57
- public specialSymbols: Record<string, number>;
57
+ public specialSymbols!: Record<string, number>;
58
58
 
59
59
  @ValidateNested()
60
60
  @Type(() => CollectFeatureSymbolsDto)
61
- public collectFeatureSymbols: CollectFeatureSymbolsDto;
61
+ public collectFeatureSymbols!: CollectFeatureSymbolsDto;
62
62
  }
63
63
 
64
64
  // --- BaseGameConfig ---
65
65
 
66
66
  export class LayoutDto {
67
67
  @IsInt()
68
- public rows: number;
68
+ public rows!: number;
69
69
 
70
70
  @IsInt()
71
- public reels: number;
71
+ public reels!: number;
72
72
  }
73
73
 
74
74
  export class WinConfigDto {
75
75
  @IsInt()
76
- public minLength: number;
76
+ public minLength!: number;
77
77
 
78
78
  @IsInt()
79
- public maxLength: number;
79
+ public maxLength!: number;
80
80
  }
81
81
 
82
82
  // --- ReelsOptions ---
83
83
 
84
84
  export class ReelsOptionsDto {
85
85
  @IsInt()
86
- public numberOfOptions: number;
86
+ public numberOfOptions!: number;
87
87
 
88
88
  @IsArray()
89
89
  @IsInt({ each: true })
90
- public optionWeights: number[];
90
+ public optionWeights!: number[];
91
91
  }
92
92
 
93
93
  export class BaseGameConfigDto {
94
94
  @ValidateNested()
95
95
  @Type(() => LayoutDto)
96
- public layout: LayoutDto;
96
+ public layout!: LayoutDto;
97
97
 
98
98
  @ValidateNested()
99
99
  @Type(() => WinConfigDto)
100
- public winConfig: WinConfigDto;
100
+ public winConfig!: WinConfigDto;
101
101
 
102
102
  @IsInt()
103
- public baseBet: number;
103
+ public baseBet!: number;
104
104
 
105
105
  @ValidateNested()
106
106
  @Type(() => ReelsOptionsDto)
107
- public reelsOptions: ReelsOptionsDto;
107
+ public reelsOptions!: ReelsOptionsDto;
108
108
  }
109
109
 
110
110
  // --- BonusGameMeter ---
111
111
 
112
112
  export class BonusGameMeterDto {
113
113
  @IsString()
114
- public symbol: string;
114
+ public symbol!: string;
115
115
 
116
116
  @IsInt()
117
- public min: number;
117
+ public min!: number;
118
118
 
119
119
  @IsInt()
120
- public max: number;
120
+ public max!: number;
121
121
  }
122
122
 
123
123
  // --- BaseGame ---
@@ -126,58 +126,58 @@ export class BaseGameDto {
126
126
  @IsArray()
127
127
  @ValidateNested({ each: true })
128
128
  @Type(() => SymbolMultipliersDto)
129
- public symbolMultipliers: SymbolMultipliersDto[];
129
+ public symbolMultipliers!: SymbolMultipliersDto[];
130
130
 
131
131
  @ValidateNested()
132
132
  @Type(() => SymbolDefinitionsDto)
133
- public symbolDefinitions: SymbolDefinitionsDto;
133
+ public symbolDefinitions!: SymbolDefinitionsDto;
134
134
 
135
135
  @ValidateNested()
136
136
  @Type(() => BaseGameConfigDto)
137
- public baseGameConfig: BaseGameConfigDto;
137
+ public baseGameConfig!: BaseGameConfigDto;
138
138
 
139
139
  @IsObject()
140
- public paidHSymbolWeights: Record<string, number>;
140
+ public paidHSymbolWeights!: Record<string, number>;
141
141
 
142
142
  @IsObject()
143
- public paidHSymbolReelWeights: Record<string, [number, number]>;
143
+ public paidHSymbolReelWeights!: Record<string, [number, number]>;
144
144
 
145
145
  @IsObject()
146
- public paidScatterReelWeights: Record<string, [number, number]>;
146
+ public paidScatterReelWeights!: Record<string, [number, number]>;
147
147
 
148
148
  @IsObject()
149
- public bonusGameMeters: Record<string, BonusGameMeterDto>;
149
+ public bonusGameMeters!: Record<string, BonusGameMeterDto>;
150
150
  }
151
151
 
152
152
  // --- BonusGame Specific Config DTOs ---
153
153
 
154
154
  export class TreasureHuntBonusConfigDto {
155
155
  @IsInt()
156
- public symbolsCount: number;
156
+ public symbolsCount!: number;
157
157
 
158
158
  @IsInt()
159
- public stepsCount: number;
159
+ public stepsCount!: number;
160
160
 
161
161
  @IsObject()
162
- public jackpotMultipliers: Record<
162
+ public jackpotMultipliers!: Record<
163
163
  'mini' | 'minor' | 'major' | 'grand',
164
164
  number
165
165
  >;
166
166
 
167
167
  @IsObject()
168
- public jackpotStartCounts: Record<
168
+ public jackpotStartCounts!: Record<
169
169
  'mini' | 'minor' | 'major' | 'grand',
170
170
  number
171
171
  >;
172
172
 
173
173
  @IsObject()
174
- public jackpotScreenCounts: Record<
174
+ public jackpotScreenCounts!: Record<
175
175
  'mini' | 'minor' | 'major' | 'grand',
176
176
  number
177
177
  >;
178
178
 
179
179
  @IsObject()
180
- public winningWeights: Record<
180
+ public winningWeights!: Record<
181
181
  'none' | 'mini' | 'minor' | 'major' | 'grand',
182
182
  number
183
183
  >;
@@ -187,7 +187,7 @@ export class TreasureHuntBonusConfigDto {
187
187
 
188
188
  export class BonusGameEvaluationConfigDto {
189
189
  @IsString()
190
- public defaultConfig: string;
190
+ public defaultConfig!: string;
191
191
 
192
192
  @IsArray()
193
193
  @IsString({ each: true })
@@ -203,57 +203,57 @@ export class BonusGameEvaluationConfigDto {
203
203
 
204
204
  export class BaseBonusGameDto {
205
205
  @IsString()
206
- public type: string;
206
+ public type!: string;
207
207
 
208
208
  @IsString()
209
- public potMeter: string;
209
+ public potMeter!: string;
210
210
 
211
211
  @ValidateNested()
212
212
  @Type(() => BonusGameEvaluationConfigDto)
213
- public evaluationConfig: BonusGameEvaluationConfigDto;
213
+ public evaluationConfig!: BonusGameEvaluationConfigDto;
214
214
  }
215
215
 
216
216
  export class TreasureHuntBonusGameDto extends BaseBonusGameDto {
217
217
  @ValidateNested()
218
218
  @Type(() => TreasureHuntBonusConfigDto)
219
- public config: TreasureHuntBonusConfigDto;
219
+ public config!: TreasureHuntBonusConfigDto;
220
220
  }
221
221
 
222
222
  export class FreeSpinTypeDto {
223
223
  @ValidateNested()
224
224
  @Type(() => LayoutDto)
225
- public layout: LayoutDto;
225
+ public layout!: LayoutDto;
226
226
 
227
227
  @IsInt()
228
- public spins: number;
228
+ public spins!: number;
229
229
 
230
230
  @IsInt()
231
- public multiplier: number;
231
+ public multiplier!: number;
232
232
 
233
233
  @IsInt()
234
- public weight: number;
234
+ public weight!: number;
235
235
 
236
236
  @IsArray()
237
237
  @IsInt({ each: true })
238
- public reelsOptionsWeights: number[];
238
+ public reelsOptionsWeights!: number[];
239
239
  }
240
240
 
241
241
  export class FreeSpinBonusConfigDto {
242
242
  @IsArray()
243
243
  @ValidateNested({ each: true })
244
244
  @Type(() => FreeSpinTypeDto)
245
- public spinTypes: FreeSpinTypeDto[];
245
+ public spinTypes!: FreeSpinTypeDto[];
246
246
  }
247
247
 
248
248
  export class FreeSpinBonusGameDto extends BaseBonusGameDto {
249
249
  @ValidateNested()
250
250
  @Type(() => FreeSpinBonusConfigDto)
251
- public config: FreeSpinBonusConfigDto;
251
+ public config!: FreeSpinBonusConfigDto;
252
252
  }
253
253
 
254
254
  export class SteeringToTheFortuneWheelResultDto {
255
255
  @IsString()
256
- public type: 'MULTIPLIER' | 'BONUS';
256
+ public type!: 'MULTIPLIER' | 'BONUS';
257
257
 
258
258
  @IsOptional()
259
259
  @IsInt()
@@ -264,20 +264,20 @@ export class SteeringToTheFortuneWheelResultDto {
264
264
  public bonusType?: string;
265
265
 
266
266
  @IsInt()
267
- public weight: number;
267
+ public weight!: number;
268
268
  }
269
269
 
270
270
  export class SteeringToTheFortuneBonusConfigDto {
271
271
  @IsArray()
272
272
  @ValidateNested({ each: true })
273
273
  @Type(() => SteeringToTheFortuneWheelResultDto)
274
- public wheelResults: SteeringToTheFortuneWheelResultDto[];
274
+ public wheelResults!: SteeringToTheFortuneWheelResultDto[];
275
275
  }
276
276
 
277
277
  export class SteeringToTheFortuneBonusGameDto extends BaseBonusGameDto {
278
278
  @ValidateNested()
279
279
  @Type(() => SteeringToTheFortuneBonusConfigDto)
280
- public config: SteeringToTheFortuneBonusConfigDto;
280
+ public config!: SteeringToTheFortuneBonusConfigDto;
281
281
  }
282
282
 
283
283
  export class BonusGamesDto {
@@ -301,58 +301,58 @@ export class BonusGamesDto {
301
301
 
302
302
  export class ScatterSymbolDto {
303
303
  @IsString()
304
- public symbolId: string;
304
+ public symbolId!: string;
305
305
 
306
306
  @IsInt()
307
- public value: number;
307
+ public value!: number;
308
308
 
309
309
  @IsInt()
310
- public weight: number;
310
+ public weight!: number;
311
311
  }
312
312
 
313
313
  // --- ScatterGameConfigDto ---
314
314
 
315
315
  export class ScatterCheckpointDto {
316
316
  @IsInt()
317
- public spin: number;
317
+ public spin!: number;
318
318
 
319
319
  @IsInt()
320
- public multiMinValue: number;
320
+ public multiMinValue!: number;
321
321
 
322
322
  @IsInt()
323
- public valueMinValue: number;
323
+ public valueMinValue!: number;
324
324
  }
325
325
 
326
326
  export class ScatterGameConfigDto {
327
327
  @IsInt()
328
- public scatterMinNumber: number;
328
+ public scatterMinNumber!: number;
329
329
 
330
330
  @IsInt()
331
- public scatterSpins: number;
331
+ public scatterSpins!: number;
332
332
 
333
333
  @IsArray()
334
334
  @ValidateNested({ each: true })
335
335
  @Type(() => ScatterCheckpointDto)
336
- public scatterCheckpoints: ScatterCheckpointDto[];
336
+ public scatterCheckpoints!: ScatterCheckpointDto[];
337
337
 
338
338
  @IsArray()
339
339
  @ValidateNested({ each: true })
340
340
  @Type(() => ScatterSymbolDto)
341
- public scatterSymbols: ScatterSymbolDto[];
341
+ public scatterSymbols!: ScatterSymbolDto[];
342
342
 
343
343
  @IsArray()
344
344
  @IsObject({ each: true })
345
- public scatterSymbolSpins: Record<string, number>[];
345
+ public scatterSymbolSpins!: Record<string, number>[];
346
346
 
347
347
  @IsArray()
348
348
  @IsObject({ each: true })
349
- public scatterSymbolSlash: Record<string, number>[];
349
+ public scatterSymbolSlash!: Record<string, number>[];
350
350
  }
351
351
 
352
352
  export class ScatterGameConfigWrapperDto {
353
353
  @ValidateNested()
354
354
  @Type(() => ScatterGameConfigDto)
355
- public config: ScatterGameConfigDto;
355
+ public config!: ScatterGameConfigDto;
356
356
  }
357
357
 
358
358
  // --- Root Config DTO ---
@@ -360,20 +360,20 @@ export class ScatterGameConfigWrapperDto {
360
360
  export class BonnysFortuneGameLogicConfigDto {
361
361
  @ValidateNested()
362
362
  @Type(() => BaseGameDto)
363
- public baseGame: BaseGameDto;
363
+ public baseGame!: BaseGameDto;
364
364
 
365
365
  @ValidateNested()
366
366
  @Type(() => BonusGamesDto)
367
- public bonusGames: BonusGamesDto;
367
+ public bonusGames!: BonusGamesDto;
368
368
 
369
369
  @ValidateNested()
370
370
  @Type(() => ScatterGameConfigWrapperDto)
371
- public scatterGame: ScatterGameConfigWrapperDto;
371
+ public scatterGame!: ScatterGameConfigWrapperDto;
372
372
 
373
373
  @IsArray()
374
374
  @IsNumber({}, { each: true })
375
- public defaultBetAmountThresholds: number[];
375
+ public defaultBetAmountThresholds!: number[];
376
376
 
377
377
  @IsNumber()
378
- public defaultBetAmount: number;
378
+ public defaultBetAmount!: number;
379
379
  }