@omnitronix/bonnys-fortune-game-engine 1.3.2 → 1.5.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.
- package/README.md +25 -15
- package/dist/__tests__/base-game.test.js +255 -0
- package/dist/__tests__/base-game.test.js.map +1 -0
- package/dist/__tests__/bonnys-fortune-v1.game-engine.test.js +1 -1
- package/dist/__tests__/bonus-handlers.test.js +303 -0
- package/dist/__tests__/bonus-handlers.test.js.map +1 -0
- package/dist/__tests__/bonus-meters.test.js +508 -0
- package/dist/__tests__/bonus-meters.test.js.map +1 -0
- package/dist/__tests__/collect-feature-handler.test.js +386 -0
- package/dist/__tests__/collect-feature-handler.test.js.map +1 -0
- package/dist/__tests__/comprehensive.test.js +747 -0
- package/dist/__tests__/comprehensive.test.js.map +1 -0
- package/dist/__tests__/error-paths.test.js +373 -0
- package/dist/__tests__/error-paths.test.js.map +1 -0
- package/dist/__tests__/helpers/test-engine-factory.js +268 -0
- package/dist/__tests__/helpers/test-engine-factory.js.map +1 -0
- package/dist/__tests__/rng-gli19-compliance.test.js +292 -0
- package/dist/__tests__/rng-gli19-compliance.test.js.map +1 -0
- package/dist/__tests__/rng-security.test.js +383 -0
- package/dist/__tests__/rng-security.test.js.map +1 -0
- package/dist/__tests__/rtp-simulation.test.js +242 -0
- package/dist/__tests__/rtp-simulation.test.js.map +1 -0
- package/dist/__tests__/state-transitions.test.js +307 -0
- package/dist/__tests__/state-transitions.test.js.map +1 -0
- package/dist/__tests__/steering-fortune-handler.test.js +286 -0
- package/dist/__tests__/steering-fortune-handler.test.js.map +1 -0
- package/dist/__tests__/symbol-distribution.test.js +195 -0
- package/dist/__tests__/symbol-distribution.test.js.map +1 -0
- package/dist/__tests__/treasure-hunt-handler.test.js +295 -0
- package/dist/__tests__/treasure-hunt-handler.test.js.map +1 -0
- package/dist/__tests__/win-calculator.test.js +515 -0
- package/dist/__tests__/win-calculator.test.js.map +1 -0
- package/dist/bonnys-fortune-v1.game-engine.js +14 -25
- package/dist/bonnys-fortune-v1.game-engine.js.map +1 -1
- package/dist/config/game-logic-config/game-logic-config.js +0 -2
- package/dist/config/game-logic-config/game-logic-config.js.map +1 -1
- package/dist/domain/types/{cheat-trigger-bonus-command.js → debug-trigger-bonus-command.js} +1 -1
- package/dist/domain/types/debug-trigger-bonus-command.js.map +1 -0
- package/dist/domain/types/{cheat-trigger-bonus-request.dto.js → debug-trigger-bonus-request.dto.js} +1 -1
- package/dist/domain/types/debug-trigger-bonus-request.dto.js.map +1 -0
- package/dist/domain/types/{cheat-update-bonus-meter-progress-command.js → debug-update-bonus-meter-progress-command.js} +1 -1
- package/dist/domain/types/debug-update-bonus-meter-progress-command.js.map +1 -0
- package/dist/domain/types/{cheat-update-bonus-meter-progress-request.dto.js → debug-update-bonus-meter-progress-request.dto.js} +1 -1
- package/dist/domain/types/debug-update-bonus-meter-progress-request.dto.js.map +1 -0
- package/dist/index.js.map +1 -1
- package/dist/logic/bonnys-fortune.game-logic.js +37 -17
- package/dist/logic/bonnys-fortune.game-logic.js.map +1 -1
- package/dist/logic/handlers/base-game.handler.js +1 -5
- package/dist/logic/handlers/base-game.handler.js.map +1 -1
- package/dist/rng/DummyRngClient.js +8 -1
- package/dist/rng/DummyRngClient.js.map +1 -1
- package/dist/rng/rng-client.factory.js.map +1 -1
- package/dist/validation/bonnys-fortune/bonnys-fortune-config.dto.js +0 -9
- package/dist/validation/bonnys-fortune/bonnys-fortune-config.dto.js.map +1 -1
- package/package.json +6 -6
- package/dist/__tests__/bonnys-fortune-v1.game-engine.test.d.ts +0 -1
- package/dist/bonnys-fortune-v1.game-engine.d.ts +0 -36
- package/dist/config/game-logic-config/file-system.game-logic-config-loader.d.ts +0 -4
- package/dist/config/game-logic-config/game-logic-config-loader.d.ts +0 -3
- package/dist/config/game-logic-config/game-logic-config.d.ts +0 -2
- package/dist/config/reel-strips-config/file-system.reel-strips-config-loader.d.ts +0 -4
- package/dist/config/reel-strips-config/reel-strip-option.dto.d.ts +0 -4
- package/dist/config/reel-strips-config/reel-strips-config-loader.d.ts +0 -3
- package/dist/config/reel-strips-config/reel-strips-config.dto.d.ts +0 -5
- package/dist/config/reel-strips-config/reel.dto.d.ts +0 -5
- package/dist/domain/game-round.types.d.ts +0 -9
- package/dist/domain/mappers/reel-strips-config.mapper.d.ts +0 -4
- package/dist/domain/reel-strip-option.d.ts +0 -7
- package/dist/domain/reel-strips-config.d.ts +0 -9
- package/dist/domain/reel.d.ts +0 -8
- package/dist/domain/types/cheat-trigger-bonus-command.d.ts +0 -5
- package/dist/domain/types/cheat-trigger-bonus-command.js.map +0 -1
- package/dist/domain/types/cheat-trigger-bonus-request.dto.d.ts +0 -5
- package/dist/domain/types/cheat-trigger-bonus-request.dto.js.map +0 -1
- package/dist/domain/types/cheat-update-bonus-meter-progress-command.d.ts +0 -5
- package/dist/domain/types/cheat-update-bonus-meter-progress-command.js.map +0 -1
- package/dist/domain/types/cheat-update-bonus-meter-progress-request.dto.d.ts +0 -5
- package/dist/domain/types/cheat-update-bonus-meter-progress-request.dto.js.map +0 -1
- package/dist/domain/types/game-spin-command.d.ts +0 -8
- package/dist/domain/types/game-spin-input.dto.d.ts +0 -8
- package/dist/domain/types/game-spin-output.dto.d.ts +0 -119
- package/dist/domain/types/game-symbols.response.dto.d.ts +0 -10
- package/dist/domain/types/reel-strip-option.dto.d.ts +0 -4
- package/dist/domain/types/reel-strips-config.dto.d.ts +0 -5
- package/dist/domain/types/reel.dto.d.ts +0 -5
- package/dist/domain/types/start-bonus-round-command.d.ts +0 -8
- package/dist/domain/types/start-bonus-round-input.dto.d.ts +0 -10
- package/dist/game-engine.interface.d.ts +0 -41
- package/dist/helpers/generate-hash.d.ts +0 -1
- package/dist/helpers/number-helper.d.ts +0 -23
- package/dist/helpers/optional-boolean-mapper.d.ts +0 -1
- package/dist/helpers/uuid-helper.d.ts +0 -3
- package/dist/helpers/validation-helper.d.ts +0 -14
- package/dist/index.d.ts +0 -2
- package/dist/logger/logger.d.ts +0 -22
- package/dist/logger/logger.js +0 -140
- package/dist/logger/logger.js.map +0 -1
- package/dist/logic/bonnys-fortune.game-logic.d.ts +0 -32
- package/dist/logic/bonnys-fortune.spin-generator.d.ts +0 -19
- package/dist/logic/bonnys-fortune.types.d.ts +0 -170
- package/dist/logic/bonnys-fortune.win-calculator.d.ts +0 -10
- package/dist/logic/game-logic-config.interface.d.ts +0 -180
- package/dist/logic/handlers/base-game.handler.d.ts +0 -15
- package/dist/logic/handlers/collect-feature-bonus.handler.d.ts +0 -13
- package/dist/logic/handlers/free-spins-bonus.handler.d.ts +0 -11
- package/dist/logic/handlers/steering-to-the-fortune-bonus.handler.d.ts +0 -11
- package/dist/logic/handlers/treasure-hunt-bonus.handler.d.ts +0 -15
- package/dist/rng/DummyRngClient.d.ts +0 -18
- package/dist/rng/rng-client.factory.d.ts +0 -7
- package/dist/rng/rng-client.interface.d.ts +0 -16
- package/dist/rng/rng-service.d.ts +0 -26
- package/dist/validation/abstract-game-logic-config.validator.d.ts +0 -4
- package/dist/validation/bonnys-fortune/bonnys-fortune-config.dto.d.ts +0 -131
- package/dist/validation/bonnys-fortune/bonnys-fortune-config.validator.d.ts +0 -5
- package/dist/validation/custom-decorators/IsNestedIntArray.d.ts +0 -2
- package/dist/validation/game-logic-config-validation.service.d.ts +0 -8
- package/dist/validation/reel-strips-config-validation.service.d.ts +0 -5
- package/src/__tests__/bonnys-fortune-v1.game-engine.test.ts +0 -80
- package/src/bonnys-fortune-v1.game-engine.ts +0 -314
- package/src/config/game-logic-config/file-system.game-logic-config-loader.ts +0 -27
- package/src/config/game-logic-config/game-logic-config-loader.ts +0 -3
- package/src/config/game-logic-config/game-logic-config.ts +0 -382
- package/src/config/reel-strips-config/file-system.reel-strips-config-loader.ts +0 -43
- package/src/config/reel-strips-config/reel-strip-option.dto.ts +0 -13
- package/src/config/reel-strips-config/reel-strips-config-loader.ts +0 -9
- package/src/config/reel-strips-config/reel-strips-config.dto.ts +0 -16
- package/src/config/reel-strips-config/reel.dto.ts +0 -16
- package/src/config/reel-strips-config/reels-BASE.csv +0 -52
- package/src/config/reel-strips-config/reels-BONUS.csv +0 -52
- package/src/domain/game-round.types.ts +0 -10
- package/src/domain/mappers/reel-strips-config.mapper.ts +0 -16
- package/src/domain/reel-strip-option.ts +0 -15
- package/src/domain/reel-strips-config.ts +0 -21
- package/src/domain/reel.ts +0 -17
- package/src/domain/types/cheat-trigger-bonus-command.ts +0 -5
- package/src/domain/types/cheat-trigger-bonus-request.dto.ts +0 -5
- package/src/domain/types/cheat-update-bonus-meter-progress-command.ts +0 -6
- package/src/domain/types/cheat-update-bonus-meter-progress-request.dto.ts +0 -5
- package/src/domain/types/game-spin-command.ts +0 -8
- package/src/domain/types/game-spin-input.dto.ts +0 -8
- package/src/domain/types/game-spin-output.dto.ts +0 -142
- package/src/domain/types/game-symbols.response.dto.ts +0 -11
- package/src/domain/types/reel-strip-option.dto.ts +0 -13
- package/src/domain/types/reel-strips-config.dto.ts +0 -15
- package/src/domain/types/reel.dto.ts +0 -15
- package/src/domain/types/start-bonus-round-command.ts +0 -8
- package/src/domain/types/start-bonus-round-input.dto.ts +0 -10
- package/src/game-engine.interface.ts +0 -59
- package/src/helpers/generate-hash.ts +0 -5
- package/src/helpers/number-helper.ts +0 -41
- package/src/helpers/optional-boolean-mapper.ts +0 -5
- package/src/helpers/uuid-helper.ts +0 -7
- package/src/helpers/validation-helper.ts +0 -27
- package/src/index.ts +0 -3
- package/src/logger/logger.ts +0 -178
- package/src/logic/bonnys-fortune.game-logic.ts +0 -490
- package/src/logic/bonnys-fortune.spin-generator.ts +0 -277
- package/src/logic/bonnys-fortune.types.ts +0 -223
- package/src/logic/bonnys-fortune.win-calculator.ts +0 -210
- package/src/logic/game-logic-config.interface.ts +0 -176
- package/src/logic/handlers/base-game.handler.ts +0 -221
- package/src/logic/handlers/collect-feature-bonus.handler.ts +0 -301
- package/src/logic/handlers/free-spins-bonus.handler.ts +0 -119
- package/src/logic/handlers/steering-to-the-fortune-bonus.handler.ts +0 -118
- package/src/logic/handlers/treasure-hunt-bonus.handler.ts +0 -232
- package/src/rng/DummyRngClient.ts +0 -108
- package/src/rng/rng-client.factory.ts +0 -27
- package/src/rng/rng-client.interface.ts +0 -38
- package/src/rng/rng-service.ts +0 -130
- package/src/validation/abstract-game-logic-config.validator.ts +0 -20
- package/src/validation/bonnys-fortune/bonnys-fortune-config.dto.ts +0 -379
- package/src/validation/bonnys-fortune/bonnys-fortune-config.validator.ts +0 -8
- package/src/validation/custom-decorators/IsNestedIntArray.ts +0 -29
- package/src/validation/game-logic-config-validation.service.ts +0 -28
- package/src/validation/reel-strips-config-validation.service.ts +0 -29
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* Bonus Meters Tests - Bonnys Fortune
|
|
5
|
+
*
|
|
6
|
+
* Tests the bonus meter system:
|
|
7
|
+
* - 3 bonus meter types (Treasure Hunt, Steering Fortune, Free Spins)
|
|
8
|
+
* - Threshold randomization per session
|
|
9
|
+
* - Level progression mechanics
|
|
10
|
+
* - Bet-specific meter tracking
|
|
11
|
+
* - Meter reset on trigger
|
|
12
|
+
* - Meter persistence across spins
|
|
13
|
+
*/
|
|
14
|
+
const test_engine_factory_1 = require("./helpers/test-engine-factory");
|
|
15
|
+
const game_logic_config_1 = require("../config/game-logic-config/game-logic-config");
|
|
16
|
+
/**
|
|
17
|
+
* Custom helper to update bonus meter progress using correct API payload.
|
|
18
|
+
* The test-engine-factory helper has a bug (uses meterId instead of bonusType).
|
|
19
|
+
*/
|
|
20
|
+
async function updateBonusMeterProgress(engine, publicState, privateState, bonusType, progress) {
|
|
21
|
+
return engine.processCommand(publicState, privateState, {
|
|
22
|
+
id: (0, test_engine_factory_1.nextCommandId)('debug-meter'),
|
|
23
|
+
type: 'DEBUG_UPDATE_BONUS_METER_PROGRESS',
|
|
24
|
+
payload: {
|
|
25
|
+
sessionId: 'test-session',
|
|
26
|
+
bonusType,
|
|
27
|
+
progress,
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
describe('Bonus Meters - Bonnys Fortune', () => {
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
(0, test_engine_factory_1.resetCommandIdCounter)();
|
|
34
|
+
});
|
|
35
|
+
describe('3 Bonus Meter Types', () => {
|
|
36
|
+
it('should initialize with 3 bonus meters (bonusGame1, bonusGame2, bonusGame3)', async () => {
|
|
37
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
38
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
39
|
+
const meters = session.publicState.bonusMeters;
|
|
40
|
+
expect(Object.keys(meters)).toContain('bonusGame1');
|
|
41
|
+
expect(Object.keys(meters)).toContain('bonusGame2');
|
|
42
|
+
expect(Object.keys(meters)).toContain('bonusGame3');
|
|
43
|
+
expect(Object.keys(meters).length).toBe(3);
|
|
44
|
+
});
|
|
45
|
+
it('should have bonusGame1 (Treasure Hunt) meter linked to H1 symbol', async () => {
|
|
46
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
47
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
48
|
+
const meter = session.publicState.bonusMeters.bonusGame1;
|
|
49
|
+
expect(meter.symbolName).toBe('H1');
|
|
50
|
+
expect(meter.symbolId).toBe(0); // H1 is symbol ID 0
|
|
51
|
+
});
|
|
52
|
+
it('should have bonusGame2 (Free Spins) meter linked to H2 symbol', async () => {
|
|
53
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
54
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
55
|
+
const meter = session.publicState.bonusMeters.bonusGame2;
|
|
56
|
+
expect(meter.symbolName).toBe('H2');
|
|
57
|
+
expect(meter.symbolId).toBe(1); // H2 is symbol ID 1
|
|
58
|
+
});
|
|
59
|
+
it('should have bonusGame3 (Steering Fortune) meter linked to H3 symbol', async () => {
|
|
60
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
61
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
62
|
+
const meter = session.publicState.bonusMeters.bonusGame3;
|
|
63
|
+
expect(meter.symbolName).toBe('H3');
|
|
64
|
+
expect(meter.symbolId).toBe(2); // H3 is symbol ID 2
|
|
65
|
+
});
|
|
66
|
+
it('should have valid structure for each meter (symbolName, symbolId, threshold, progress, level)', async () => {
|
|
67
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
68
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
69
|
+
for (const [, meter] of Object.entries(session.publicState.bonusMeters)) {
|
|
70
|
+
expect(meter).toHaveProperty('symbolName');
|
|
71
|
+
expect(meter).toHaveProperty('symbolId');
|
|
72
|
+
expect(meter).toHaveProperty('threshold');
|
|
73
|
+
expect(meter).toHaveProperty('progress');
|
|
74
|
+
expect(meter).toHaveProperty('level');
|
|
75
|
+
expect(typeof meter.symbolName).toBe('string');
|
|
76
|
+
expect(typeof meter.symbolId).toBe('number');
|
|
77
|
+
expect(typeof meter.threshold).toBe('number');
|
|
78
|
+
expect(typeof meter.progress).toBe('number');
|
|
79
|
+
expect(typeof meter.level).toBe('number');
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
describe('Threshold Randomization Per Session', () => {
|
|
84
|
+
it('should have threshold within configured min/max range for bonusGame1', async () => {
|
|
85
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
86
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
87
|
+
const meter = session.publicState.bonusMeters.bonusGame1;
|
|
88
|
+
const config = game_logic_config_1.gameLogicConfig.baseGame.bonusGameMeters.bonusGame1;
|
|
89
|
+
expect(meter.threshold).toBeGreaterThanOrEqual(config.min);
|
|
90
|
+
expect(meter.threshold).toBeLessThanOrEqual(config.max);
|
|
91
|
+
});
|
|
92
|
+
it('should have threshold within configured min/max range for bonusGame2', async () => {
|
|
93
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
94
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
95
|
+
const meter = session.publicState.bonusMeters.bonusGame2;
|
|
96
|
+
const config = game_logic_config_1.gameLogicConfig.baseGame.bonusGameMeters.bonusGame2;
|
|
97
|
+
expect(meter.threshold).toBeGreaterThanOrEqual(config.min);
|
|
98
|
+
expect(meter.threshold).toBeLessThanOrEqual(config.max);
|
|
99
|
+
});
|
|
100
|
+
it('should have threshold within configured min/max range for bonusGame3', async () => {
|
|
101
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
102
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
103
|
+
const meter = session.publicState.bonusMeters.bonusGame3;
|
|
104
|
+
const config = game_logic_config_1.gameLogicConfig.baseGame.bonusGameMeters.bonusGame3;
|
|
105
|
+
expect(meter.threshold).toBeGreaterThanOrEqual(config.min);
|
|
106
|
+
expect(meter.threshold).toBeLessThanOrEqual(config.max);
|
|
107
|
+
});
|
|
108
|
+
it('should produce different thresholds with different RNG seeds', async () => {
|
|
109
|
+
const { engine: engine1 } = (0, test_engine_factory_1.createEngineWithLcgRng)(11111);
|
|
110
|
+
const { engine: engine2 } = (0, test_engine_factory_1.createEngineWithLcgRng)(99999);
|
|
111
|
+
const session1 = await (0, test_engine_factory_1.initSession)(engine1);
|
|
112
|
+
const session2 = await (0, test_engine_factory_1.initSession)(engine2);
|
|
113
|
+
// At least one meter should have different threshold
|
|
114
|
+
const thresholds1 = Object.values(session1.publicState.bonusMeters).map((m) => m.threshold);
|
|
115
|
+
const thresholds2 = Object.values(session2.publicState.bonusMeters).map((m) => m.threshold);
|
|
116
|
+
const allSame = thresholds1.every((t, i) => t === thresholds2[i]);
|
|
117
|
+
// Very unlikely all 3 thresholds are same with different seeds
|
|
118
|
+
expect(allSame).toBe(false);
|
|
119
|
+
});
|
|
120
|
+
it('should produce deterministic thresholds with same RNG seed', async () => {
|
|
121
|
+
const { engine: engine1 } = (0, test_engine_factory_1.createEngineWithMockRng)([50, 50, 50]);
|
|
122
|
+
const { engine: engine2 } = (0, test_engine_factory_1.createEngineWithMockRng)([50, 50, 50]);
|
|
123
|
+
const session1 = await (0, test_engine_factory_1.initSession)(engine1);
|
|
124
|
+
const session2 = await (0, test_engine_factory_1.initSession)(engine2);
|
|
125
|
+
// All meters should have same threshold
|
|
126
|
+
for (const key of Object.keys(session1.publicState.bonusMeters)) {
|
|
127
|
+
expect(session1.publicState.bonusMeters[key].threshold).toBe(session2.publicState.bonusMeters[key].threshold);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
describe('Level Progression Mechanics', () => {
|
|
132
|
+
it('should start at level 1 with 0 progress', async () => {
|
|
133
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
134
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
135
|
+
for (const [, meter] of Object.entries(session.publicState.bonusMeters)) {
|
|
136
|
+
expect(meter.progress).toBe(0);
|
|
137
|
+
expect(meter.level).toBe(1);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
it('should progress to level 2 at 25% threshold', async () => {
|
|
141
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
142
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
143
|
+
// Use debug to set progress to 25% of threshold
|
|
144
|
+
const threshold = session.publicState.bonusMeters.bonusGame1.threshold;
|
|
145
|
+
const progress = Math.ceil(threshold * 0.25);
|
|
146
|
+
const result = await updateBonusMeterProgress(engine, session.publicState, session.privateState, 'bonusGame1', progress);
|
|
147
|
+
expect(result.success).toBe(true);
|
|
148
|
+
expect(result.publicState.bonusMeters.bonusGame1.progress).toBe(progress);
|
|
149
|
+
expect(result.publicState.bonusMeters.bonusGame1.level).toBe(2);
|
|
150
|
+
});
|
|
151
|
+
it('should progress to level 3 at 65% threshold', async () => {
|
|
152
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
153
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
154
|
+
const threshold = session.publicState.bonusMeters.bonusGame2.threshold;
|
|
155
|
+
const progress = Math.ceil(threshold * 0.65);
|
|
156
|
+
const result = await updateBonusMeterProgress(engine, session.publicState, session.privateState, 'bonusGame2', progress);
|
|
157
|
+
expect(result.success).toBe(true);
|
|
158
|
+
expect(result.publicState.bonusMeters.bonusGame2.level).toBe(3);
|
|
159
|
+
});
|
|
160
|
+
it('should progress to level 4 at 80% threshold', async () => {
|
|
161
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
162
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
163
|
+
const threshold = session.publicState.bonusMeters.bonusGame3.threshold;
|
|
164
|
+
const progress = Math.ceil(threshold * 0.80);
|
|
165
|
+
const result = await updateBonusMeterProgress(engine, session.publicState, session.privateState, 'bonusGame3', progress);
|
|
166
|
+
expect(result.success).toBe(true);
|
|
167
|
+
expect(result.publicState.bonusMeters.bonusGame3.level).toBe(4);
|
|
168
|
+
});
|
|
169
|
+
it('should reach level 5 at 100% threshold', async () => {
|
|
170
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
171
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
172
|
+
const threshold = session.publicState.bonusMeters.bonusGame1.threshold;
|
|
173
|
+
const result = await updateBonusMeterProgress(engine, session.publicState, session.privateState, 'bonusGame1', threshold);
|
|
174
|
+
expect(result.success).toBe(true);
|
|
175
|
+
expect(result.publicState.bonusMeters.bonusGame1.level).toBe(5);
|
|
176
|
+
});
|
|
177
|
+
it('should calculate level based on percentage ranges correctly', async () => {
|
|
178
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
179
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
180
|
+
// Test boundary conditions
|
|
181
|
+
const threshold = session.publicState.bonusMeters.bonusGame1.threshold;
|
|
182
|
+
// Just below 25% = level 1
|
|
183
|
+
const result1 = await updateBonusMeterProgress(engine, session.publicState, session.privateState, 'bonusGame1', Math.floor(threshold * 0.24));
|
|
184
|
+
expect(result1.publicState.bonusMeters.bonusGame1.level).toBe(1);
|
|
185
|
+
// At 25% = level 2
|
|
186
|
+
const result2 = await updateBonusMeterProgress(engine, result1.publicState, result1.privateState, 'bonusGame1', Math.ceil(threshold * 0.25));
|
|
187
|
+
expect(result2.publicState.bonusMeters.bonusGame1.level).toBe(2);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
describe('Bet-Specific Meter Tracking', () => {
|
|
191
|
+
it('should maintain separate meter states for each bet amount', async () => {
|
|
192
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
193
|
+
const betAmounts = [0.1, 0.2, 0.5, 1, 2, 5];
|
|
194
|
+
const session = await (0, test_engine_factory_1.initSession)(engine, 1.0, betAmounts);
|
|
195
|
+
// Private state should have meters for each bet amount
|
|
196
|
+
const privateMetersByAmount = session.privateState.bonusMetersByAmount;
|
|
197
|
+
expect(Object.keys(privateMetersByAmount).length).toBeGreaterThan(1);
|
|
198
|
+
for (const amount of betAmounts) {
|
|
199
|
+
expect(privateMetersByAmount[amount]).toBeDefined();
|
|
200
|
+
expect(Object.keys(privateMetersByAmount[amount] || {}).length).toBe(3);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
it('should update only the current bet amount meters on spin', async () => {
|
|
204
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
205
|
+
const betAmounts = [1.0, 2.0];
|
|
206
|
+
const session = await (0, test_engine_factory_1.initSession)(engine, 1.0, betAmounts);
|
|
207
|
+
// Get initial state for bet amount 2.0
|
|
208
|
+
const initialMeters2 = JSON.stringify(session.privateState.bonusMetersByAmount[2.0]);
|
|
209
|
+
// Spin at bet amount 1.0
|
|
210
|
+
if (session.privateState.nextSpinType === 'BASE_GAME_SPIN') {
|
|
211
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, session.publicState, session.privateState, 1.0);
|
|
212
|
+
expect(result.success).toBe(true);
|
|
213
|
+
// Meters for bet amount 2.0 should be unchanged (thresholds same)
|
|
214
|
+
const afterMeters2Thresholds = Object.values(result.privateState.bonusMetersByAmount[2.0] || {}).map((m) => m.threshold);
|
|
215
|
+
const initialMeters2Thresholds = Object.values(JSON.parse(initialMeters2) || {}).map((m) => m.threshold);
|
|
216
|
+
expect(afterMeters2Thresholds).toEqual(initialMeters2Thresholds);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
it('should switch to correct meters when bet amount changes', async () => {
|
|
220
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
221
|
+
const betAmounts = [1.0, 5.0];
|
|
222
|
+
const session = await (0, test_engine_factory_1.initSession)(engine, 1.0, betAmounts);
|
|
223
|
+
// Initial meters are for bet 1.0
|
|
224
|
+
expect(session.publicState.currentBetAmount).toBe(1.0);
|
|
225
|
+
// Change bet and spin
|
|
226
|
+
if (session.privateState.nextSpinType === 'BASE_GAME_SPIN') {
|
|
227
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, session.publicState, session.privateState, 5.0);
|
|
228
|
+
expect(result.success).toBe(true);
|
|
229
|
+
expect(result.publicState.currentBetAmount).toBe(5.0);
|
|
230
|
+
// Public meters should match private meters for bet 5.0
|
|
231
|
+
expect(result.publicState.bonusMeters).toEqual(result.privateState.bonusMetersByAmount[5.0]);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
it('should have independent progress for different bet amounts', async () => {
|
|
235
|
+
const { engine } = (0, test_engine_factory_1.createEngineWithLcgRng)(12345);
|
|
236
|
+
const betAmounts = [1.0, 2.0];
|
|
237
|
+
const session = await (0, test_engine_factory_1.initSession)(engine, 1.0, betAmounts);
|
|
238
|
+
let pub = session.publicState;
|
|
239
|
+
let priv = session.privateState;
|
|
240
|
+
// Spin a few times at bet 1.0
|
|
241
|
+
for (let i = 0; i < 3; i++) {
|
|
242
|
+
if (priv.nextSpinType !== 'BASE_GAME_SPIN')
|
|
243
|
+
break;
|
|
244
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, pub, priv, 1.0);
|
|
245
|
+
if (!result.success)
|
|
246
|
+
break;
|
|
247
|
+
pub = result.publicState;
|
|
248
|
+
priv = result.privateState;
|
|
249
|
+
}
|
|
250
|
+
// Progress at bet 1.0 may have changed
|
|
251
|
+
const progress1 = priv.bonusMetersByAmount[1.0]?.bonusGame1?.progress ?? 0;
|
|
252
|
+
// Progress at bet 2.0 should still be 0 (no spins at that bet)
|
|
253
|
+
const progress2 = priv.bonusMetersByAmount[2.0]?.bonusGame1?.progress ?? 0;
|
|
254
|
+
// They should be independent (unless both are 0)
|
|
255
|
+
expect(progress2).toBe(0);
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
describe('Meter Reset on Trigger', () => {
|
|
259
|
+
it('should reset meter progress to 0 after bonusGame1 triggers and completes', async () => {
|
|
260
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
261
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
262
|
+
// Debug trigger bonusGame1
|
|
263
|
+
const debugResult = await (0, test_engine_factory_1.debugTriggerBonus)(engine, session.publicState, session.privateState, 'bonusGame1');
|
|
264
|
+
expect(debugResult.success).toBe(true);
|
|
265
|
+
// Start the bonus round
|
|
266
|
+
const bonus = debugResult.privateState.pendingBonuses[0];
|
|
267
|
+
const bonusResult = await (0, test_engine_factory_1.startBonusRound)(engine, debugResult.publicState, debugResult.privateState, bonus.bonusType);
|
|
268
|
+
expect(bonusResult.success).toBe(true);
|
|
269
|
+
// After bonus completion, meter should be reset
|
|
270
|
+
const finalMeters = bonusResult.publicState.bonusMeters;
|
|
271
|
+
expect(finalMeters.bonusGame1.progress).toBe(0);
|
|
272
|
+
expect(finalMeters.bonusGame1.level).toBe(1);
|
|
273
|
+
});
|
|
274
|
+
it('should reset meter progress to 0 after bonusGame2 triggers and completes', async () => {
|
|
275
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
276
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
277
|
+
const debugResult = await (0, test_engine_factory_1.debugTriggerBonus)(engine, session.publicState, session.privateState, 'bonusGame2');
|
|
278
|
+
expect(debugResult.success).toBe(true);
|
|
279
|
+
const bonus = debugResult.privateState.pendingBonuses[0];
|
|
280
|
+
const bonusResult = await (0, test_engine_factory_1.startBonusRound)(engine, debugResult.publicState, debugResult.privateState, bonus.bonusType);
|
|
281
|
+
expect(bonusResult.success).toBe(true);
|
|
282
|
+
const finalMeters = bonusResult.publicState.bonusMeters;
|
|
283
|
+
expect(finalMeters.bonusGame2.progress).toBe(0);
|
|
284
|
+
expect(finalMeters.bonusGame2.level).toBe(1);
|
|
285
|
+
});
|
|
286
|
+
it('should reset meter progress to 0 after bonusGame3 triggers and completes', async () => {
|
|
287
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
288
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
289
|
+
const debugResult = await (0, test_engine_factory_1.debugTriggerBonus)(engine, session.publicState, session.privateState, 'bonusGame3');
|
|
290
|
+
expect(debugResult.success).toBe(true);
|
|
291
|
+
let pub = debugResult.publicState;
|
|
292
|
+
let priv = debugResult.privateState;
|
|
293
|
+
// Start bonusGame3
|
|
294
|
+
const bonus = priv.pendingBonuses[0];
|
|
295
|
+
const bonusResult = await (0, test_engine_factory_1.startBonusRound)(engine, pub, priv, bonus.bonusType);
|
|
296
|
+
expect(bonusResult.success).toBe(true);
|
|
297
|
+
// bonusGame3 may chain to another bonus, handle that
|
|
298
|
+
const finalState = (0, test_engine_factory_1.extractFinalBonusState)(bonusResult);
|
|
299
|
+
pub = finalState.publicState;
|
|
300
|
+
priv = finalState.privateState;
|
|
301
|
+
while (priv.pendingBonuses?.length > 0) {
|
|
302
|
+
const nextBonus = priv.pendingBonuses[0];
|
|
303
|
+
const chainResult = await (0, test_engine_factory_1.startBonusRound)(engine, pub, priv, nextBonus.bonusType);
|
|
304
|
+
const chainFinal = (0, test_engine_factory_1.extractFinalBonusState)(chainResult);
|
|
305
|
+
pub = chainFinal.publicState;
|
|
306
|
+
priv = chainFinal.privateState;
|
|
307
|
+
}
|
|
308
|
+
// bonusGame3 meter should be reset
|
|
309
|
+
expect(pub.bonusMeters.bonusGame3.progress).toBe(0);
|
|
310
|
+
expect(pub.bonusMeters.bonusGame3.level).toBe(1);
|
|
311
|
+
});
|
|
312
|
+
it('should assign new random threshold after meter reset', async () => {
|
|
313
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
314
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
315
|
+
// Record original threshold
|
|
316
|
+
const originalThreshold = session.publicState.bonusMeters.bonusGame1.threshold;
|
|
317
|
+
// Trigger and complete bonusGame1
|
|
318
|
+
const debugResult = await (0, test_engine_factory_1.debugTriggerBonus)(engine, session.publicState, session.privateState, 'bonusGame1');
|
|
319
|
+
const bonus = debugResult.privateState.pendingBonuses[0];
|
|
320
|
+
const bonusResult = await (0, test_engine_factory_1.startBonusRound)(engine, debugResult.publicState, debugResult.privateState, bonus.bonusType);
|
|
321
|
+
expect(bonusResult.success).toBe(true);
|
|
322
|
+
// New threshold should be within valid range
|
|
323
|
+
const newThreshold = bonusResult.publicState.bonusMeters.bonusGame1.threshold;
|
|
324
|
+
const config = game_logic_config_1.gameLogicConfig.baseGame.bonusGameMeters.bonusGame1;
|
|
325
|
+
expect(newThreshold).toBeGreaterThanOrEqual(config.min);
|
|
326
|
+
expect(newThreshold).toBeLessThanOrEqual(config.max);
|
|
327
|
+
// Note: threshold might be same by chance, but should be valid
|
|
328
|
+
});
|
|
329
|
+
it('should NOT reset meters for collectFeature bonus', async () => {
|
|
330
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
331
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
332
|
+
// Set some progress first
|
|
333
|
+
const updateResult = await updateBonusMeterProgress(engine, session.publicState, session.privateState, 'bonusGame1', 10);
|
|
334
|
+
// Trigger collectFeature
|
|
335
|
+
const debugResult = await (0, test_engine_factory_1.debugTriggerBonus)(engine, updateResult.publicState, updateResult.privateState, 'collectFeature');
|
|
336
|
+
expect(debugResult.success).toBe(true);
|
|
337
|
+
const bonus = debugResult.privateState.pendingBonuses[0];
|
|
338
|
+
const bonusResult = await (0, test_engine_factory_1.startBonusRound)(engine, debugResult.publicState, debugResult.privateState, bonus.bonusType);
|
|
339
|
+
expect(bonusResult.success).toBe(true);
|
|
340
|
+
// collectFeature should NOT reset the bonusGame meters
|
|
341
|
+
// (collectFeature is scatter-triggered, not meter-triggered)
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
describe('Meter Persistence Across Spins', () => {
|
|
345
|
+
it('should maintain meter state across multiple spins', async () => {
|
|
346
|
+
const { engine } = (0, test_engine_factory_1.createEngineWithLcgRng)(54321);
|
|
347
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
348
|
+
let pub = session.publicState;
|
|
349
|
+
let priv = session.privateState;
|
|
350
|
+
// Track meters across spins
|
|
351
|
+
const meterHistory = [];
|
|
352
|
+
meterHistory.push({
|
|
353
|
+
bonusGame1: pub.bonusMeters.bonusGame1.progress,
|
|
354
|
+
bonusGame2: pub.bonusMeters.bonusGame2.progress,
|
|
355
|
+
bonusGame3: pub.bonusMeters.bonusGame3.progress,
|
|
356
|
+
});
|
|
357
|
+
// Do several spins
|
|
358
|
+
for (let i = 0; i < 10; i++) {
|
|
359
|
+
if (priv.nextSpinType !== 'BASE_GAME_SPIN') {
|
|
360
|
+
// If bonus triggered, complete it
|
|
361
|
+
if (priv.pendingBonuses?.length > 0) {
|
|
362
|
+
const bonus = priv.pendingBonuses[0];
|
|
363
|
+
const bonusResult = await (0, test_engine_factory_1.startBonusRound)(engine, pub, priv, bonus.bonusType);
|
|
364
|
+
const finalState = (0, test_engine_factory_1.extractFinalBonusState)(bonusResult);
|
|
365
|
+
pub = finalState.publicState;
|
|
366
|
+
priv = finalState.privateState;
|
|
367
|
+
// Handle chained bonuses
|
|
368
|
+
while (priv.pendingBonuses?.length > 0) {
|
|
369
|
+
const nextBonus = priv.pendingBonuses[0];
|
|
370
|
+
const chainResult = await (0, test_engine_factory_1.startBonusRound)(engine, pub, priv, nextBonus.bonusType);
|
|
371
|
+
const chainFinal = (0, test_engine_factory_1.extractFinalBonusState)(chainResult);
|
|
372
|
+
pub = chainFinal.publicState;
|
|
373
|
+
priv = chainFinal.privateState;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
if (priv.nextSpinType !== 'BASE_GAME_SPIN')
|
|
377
|
+
break;
|
|
378
|
+
}
|
|
379
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, pub, priv);
|
|
380
|
+
if (!result.success)
|
|
381
|
+
break;
|
|
382
|
+
pub = result.publicState;
|
|
383
|
+
priv = result.privateState;
|
|
384
|
+
meterHistory.push({
|
|
385
|
+
bonusGame1: pub.bonusMeters.bonusGame1.progress,
|
|
386
|
+
bonusGame2: pub.bonusMeters.bonusGame2.progress,
|
|
387
|
+
bonusGame3: pub.bonusMeters.bonusGame3.progress,
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
// Verify meters generally increase or stay same (unless reset)
|
|
391
|
+
// Progress should be non-negative throughout
|
|
392
|
+
for (const state of meterHistory) {
|
|
393
|
+
expect(state.bonusGame1).toBeGreaterThanOrEqual(0);
|
|
394
|
+
expect(state.bonusGame2).toBeGreaterThanOrEqual(0);
|
|
395
|
+
expect(state.bonusGame3).toBeGreaterThanOrEqual(0);
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
it('should accumulate progress based on symbol count on screen', async () => {
|
|
399
|
+
// This test verifies the meter increases by the count of matching symbols
|
|
400
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
401
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
402
|
+
const initialProgress = session.publicState.bonusMeters.bonusGame1.progress;
|
|
403
|
+
expect(initialProgress).toBe(0);
|
|
404
|
+
// We can't easily control the screen, but verify progress changes
|
|
405
|
+
if (session.privateState.nextSpinType === 'BASE_GAME_SPIN') {
|
|
406
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, session.publicState, session.privateState);
|
|
407
|
+
expect(result.success).toBe(true);
|
|
408
|
+
// Progress should be >= 0 (may or may not have H1 symbols on screen)
|
|
409
|
+
expect(result.publicState.bonusMeters.bonusGame1.progress).toBeGreaterThanOrEqual(0);
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
it('should preserve thresholds across spins', async () => {
|
|
413
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
414
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
415
|
+
const originalThresholds = {
|
|
416
|
+
bonusGame1: session.publicState.bonusMeters.bonusGame1.threshold,
|
|
417
|
+
bonusGame2: session.publicState.bonusMeters.bonusGame2.threshold,
|
|
418
|
+
bonusGame3: session.publicState.bonusMeters.bonusGame3.threshold,
|
|
419
|
+
};
|
|
420
|
+
// Do a few spins
|
|
421
|
+
let pub = session.publicState;
|
|
422
|
+
let priv = session.privateState;
|
|
423
|
+
for (let i = 0; i < 5; i++) {
|
|
424
|
+
if (priv.nextSpinType !== 'BASE_GAME_SPIN')
|
|
425
|
+
break;
|
|
426
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, pub, priv);
|
|
427
|
+
if (!result.success)
|
|
428
|
+
break;
|
|
429
|
+
pub = result.publicState;
|
|
430
|
+
priv = result.privateState;
|
|
431
|
+
}
|
|
432
|
+
// Thresholds should remain unchanged (unless a bonus was triggered)
|
|
433
|
+
// Check against original or verify within valid range
|
|
434
|
+
for (const [key, threshold] of Object.entries(originalThresholds)) {
|
|
435
|
+
const config = game_logic_config_1.gameLogicConfig.baseGame.bonusGameMeters[key];
|
|
436
|
+
const currentThreshold = pub.bonusMeters[key].threshold;
|
|
437
|
+
expect(currentThreshold).toBeGreaterThanOrEqual(config.min);
|
|
438
|
+
expect(currentThreshold).toBeLessThanOrEqual(config.max);
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
it('should update level as progress changes', async () => {
|
|
442
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
443
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
444
|
+
const threshold = session.publicState.bonusMeters.bonusGame1.threshold;
|
|
445
|
+
// Set progress at different percentages and verify levels
|
|
446
|
+
const testCases = [
|
|
447
|
+
{ progress: 0, expectedLevel: 1 },
|
|
448
|
+
{ progress: Math.floor(threshold * 0.24), expectedLevel: 1 },
|
|
449
|
+
{ progress: Math.ceil(threshold * 0.25), expectedLevel: 2 },
|
|
450
|
+
{ progress: Math.floor(threshold * 0.64), expectedLevel: 2 },
|
|
451
|
+
{ progress: Math.ceil(threshold * 0.65), expectedLevel: 3 },
|
|
452
|
+
{ progress: Math.floor(threshold * 0.79), expectedLevel: 3 },
|
|
453
|
+
{ progress: Math.ceil(threshold * 0.8), expectedLevel: 4 },
|
|
454
|
+
{ progress: Math.floor(threshold * 0.99), expectedLevel: 4 },
|
|
455
|
+
{ progress: threshold, expectedLevel: 5 },
|
|
456
|
+
];
|
|
457
|
+
let pub = session.publicState;
|
|
458
|
+
let priv = session.privateState;
|
|
459
|
+
for (const { progress, expectedLevel } of testCases) {
|
|
460
|
+
const result = await updateBonusMeterProgress(engine, pub, priv, 'bonusGame1', progress);
|
|
461
|
+
expect(result.success).toBe(true);
|
|
462
|
+
expect(result.publicState.bonusMeters.bonusGame1.level).toBe(expectedLevel);
|
|
463
|
+
pub = result.publicState;
|
|
464
|
+
priv = result.privateState;
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
});
|
|
468
|
+
describe('Meter Trigger Behavior', () => {
|
|
469
|
+
it('should trigger bonus when progress >= threshold', async () => {
|
|
470
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
471
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
472
|
+
const threshold = session.publicState.bonusMeters.bonusGame1.threshold;
|
|
473
|
+
// Set progress just below threshold
|
|
474
|
+
const belowResult = await updateBonusMeterProgress(engine, session.publicState, session.privateState, 'bonusGame1', threshold - 1);
|
|
475
|
+
expect(belowResult.success).toBe(true);
|
|
476
|
+
// Progress is below threshold, no bonus should be pending yet
|
|
477
|
+
// (bonus triggers on spin, not on debug update)
|
|
478
|
+
expect(belowResult.privateState.pendingBonuses.length).toBe(0);
|
|
479
|
+
// Now set to exactly threshold
|
|
480
|
+
const atThresholdResult = await updateBonusMeterProgress(engine, belowResult.publicState, belowResult.privateState, 'bonusGame1', threshold);
|
|
481
|
+
expect(atThresholdResult.success).toBe(true);
|
|
482
|
+
// Still no pending bonus until a spin occurs
|
|
483
|
+
expect(atThresholdResult.privateState.pendingBonuses.length).toBe(0);
|
|
484
|
+
});
|
|
485
|
+
it('should only trigger one bonus at a time even if multiple meters are full', async () => {
|
|
486
|
+
const engine = (0, test_engine_factory_1.createEngine)();
|
|
487
|
+
const session = await (0, test_engine_factory_1.initSession)(engine);
|
|
488
|
+
// Set all meters to threshold
|
|
489
|
+
let pub = session.publicState;
|
|
490
|
+
let priv = session.privateState;
|
|
491
|
+
for (const key of ['bonusGame1', 'bonusGame2', 'bonusGame3']) {
|
|
492
|
+
const threshold = pub.bonusMeters[key].threshold;
|
|
493
|
+
const result = await updateBonusMeterProgress(engine, pub, priv, key, threshold);
|
|
494
|
+
pub = result.publicState;
|
|
495
|
+
priv = result.privateState;
|
|
496
|
+
}
|
|
497
|
+
// Spin should trigger only one bonus (the first one found)
|
|
498
|
+
if (priv.nextSpinType === 'BASE_GAME_SPIN') {
|
|
499
|
+
const result = await (0, test_engine_factory_1.executeSpin)(engine, pub, priv);
|
|
500
|
+
if (result.success && result.privateState.pendingBonuses?.length > 0) {
|
|
501
|
+
// Should have exactly 1 pending bonus
|
|
502
|
+
expect(result.privateState.pendingBonuses.length).toBe(1);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
});
|
|
506
|
+
});
|
|
507
|
+
});
|
|
508
|
+
//# sourceMappingURL=bonus-meters.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bonus-meters.test.js","sourceRoot":"","sources":["../../src/__tests__/bonus-meters.test.ts"],"names":[],"mappings":";;AAAA;;;;;;;;;;GAUG;AACH,uEAauC;AACvC,qFAAgF;AAIhF;;;GAGG;AACH,KAAK,UAAU,wBAAwB,CACrC,MAAiC,EACjC,WAAgB,EAChB,YAAiB,EACjB,SAAiB,EACjB,QAAgB;IAEhB,OAAO,MAAM,CAAC,cAAc,CAAC,WAAW,EAAE,YAAY,EAAE;QACtD,EAAE,EAAE,IAAA,mCAAa,EAAC,aAAa,CAAC;QAChC,IAAI,EAAE,mCAAmC;QACzC,OAAO,EAAE;YACP,SAAS,EAAE,cAAc;YACzB,SAAS;YACT,QAAQ;SACT;KACF,CAAC,CAAC;AACL,CAAC;AAED,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,UAAU,CAAC,GAAG,EAAE;QACd,IAAA,2CAAqB,GAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;QACnC,EAAE,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;YAC1F,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC;YAC/C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YACpD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YACpD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YACpD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;YAChF,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC;YACzD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB;QACtD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;YAC7E,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC;YACzD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB;QACtD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;YACnF,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC;YACzD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB;QACtD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+FAA+F,EAAE,KAAK,IAAI,EAAE;YAC7G,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,WAAW,CAA2B,EAAE,CAAC;gBAClG,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;gBAC3C,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;gBACzC,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;gBAC1C,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;gBACzC,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;gBACtC,MAAM,CAAC,OAAO,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC/C,MAAM,CAAC,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC7C,MAAM,CAAC,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC9C,MAAM,CAAC,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC7C,MAAM,CAAC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,qCAAqC,EAAE,GAAG,EAAE;QACnD,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;YACpF,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC;YACzD,MAAM,MAAM,GAAG,mCAAe,CAAC,QAAQ,CAAC,eAAe,CAAC,UAAU,CAAC;YACnE,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC3D,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;YACpF,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC;YACzD,MAAM,MAAM,GAAG,mCAAe,CAAC,QAAQ,CAAC,eAAe,CAAC,UAAU,CAAC;YACnE,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC3D,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;YACpF,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC;YACzD,MAAM,MAAM,GAAG,mCAAe,CAAC,QAAQ,CAAC,eAAe,CAAC,UAAU,CAAC;YACnE,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC3D,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;YAC5E,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAA,4CAAsB,EAAC,KAAK,CAAC,CAAC;YAC1D,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAA,4CAAsB,EAAC,KAAK,CAAC,CAAC;YAE1D,MAAM,QAAQ,GAAG,MAAM,IAAA,iCAAW,EAAC,OAAO,CAAC,CAAC;YAC5C,MAAM,QAAQ,GAAG,MAAM,IAAA,iCAAW,EAAC,OAAO,CAAC,CAAC;YAE5C,qDAAqD;YACrD,MAAM,WAAW,GAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,WAAW,CAAkB,CAAC,GAAG,CACvF,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CACnB,CAAC;YACF,MAAM,WAAW,GAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,WAAW,CAAkB,CAAC,GAAG,CACvF,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CACnB,CAAC;YAEF,MAAM,OAAO,GACX,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;YACpD,+DAA+D;YAC/D,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;YAC1E,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAA,6CAAuB,EAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YAClE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAA,6CAAuB,EAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YAElE,MAAM,QAAQ,GAAG,MAAM,IAAA,iCAAW,EAAC,OAAO,CAAC,CAAC;YAC5C,MAAM,QAAQ,GAAG,MAAM,IAAA,iCAAW,EAAC,OAAO,CAAC,CAAC;YAE5C,wCAAwC;YACxC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC;gBAChE,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAC1D,QAAQ,CAAC,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,SAAS,CAChD,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;QAC3C,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,WAAW,CAA2B,EAAE,CAAC;gBAClG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAC/B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;YAC3D,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,gDAAgD;YAChD,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC;YACvE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;YAE7C,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAC3C,MAAM,EACN,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,YAAY,EACpB,YAAY,EACZ,QAAQ,CACT,CAAC;YAEF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC1E,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;YAC3D,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC;YACvE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;YAE7C,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAC3C,MAAM,EACN,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,YAAY,EACpB,YAAY,EACZ,QAAQ,CACT,CAAC;YAEF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;YAC3D,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC;YACvE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;YAE7C,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAC3C,MAAM,EACN,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,YAAY,EACpB,YAAY,EACZ,QAAQ,CACT,CAAC;YAEF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;YACtD,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC;YAEvE,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAC3C,MAAM,EACN,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,YAAY,EACpB,YAAY,EACZ,SAAS,CACV,CAAC;YAEF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;YAC3E,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,2BAA2B;YAC3B,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC;YAEvE,2BAA2B;YAC3B,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAC5C,MAAM,EACN,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,YAAY,EACpB,YAAY,EACZ,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,CAC7B,CAAC;YACF,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAEjE,mBAAmB;YACnB,MAAM,OAAO,GAAG,MAAM,wBAAwB,CAC5C,MAAM,EACN,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,YAAY,EACpB,YAAY,EACZ,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAC5B,CAAC;YACF,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;QAC3C,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;YACzE,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC5C,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;YAE3D,uDAAuD;YACvD,MAAM,qBAAqB,GAAG,OAAO,CAAC,YAAY,CAAC,mBAAmB,CAAC;YACvE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;YAErE,KAAK,MAAM,MAAM,IAAI,UAAU,EAAE,CAAC;gBAChC,MAAM,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;gBACpD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;YACxE,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;YAE3D,uCAAuC;YACvC,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CACnC,OAAO,CAAC,YAAY,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAC9C,CAAC;YAEF,yBAAyB;YACzB,IAAI,OAAO,CAAC,YAAY,CAAC,YAAY,KAAK,gBAAgB,EAAE,CAAC;gBAC3D,MAAM,MAAM,GAAG,MAAM,IAAA,iCAAW,EAC9B,MAAM,EACN,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,YAAY,EACpB,GAAG,CACJ,CAAC;gBAEF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAElC,kEAAkE;gBAClE,MAAM,sBAAsB,GAAG,MAAM,CAAC,MAAM,CAC1C,MAAM,CAAC,YAAY,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,EAAE,CACnD,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;gBAC/B,MAAM,wBAAwB,GAAG,MAAM,CAAC,MAAM,CAC5C,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,EAAE,CACjC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;gBAE/B,MAAM,CAAC,sBAAsB,CAAC,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;YACnE,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;YACvE,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;YAE3D,iCAAiC;YACjC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAEvD,sBAAsB;YACtB,IAAI,OAAO,CAAC,YAAY,CAAC,YAAY,KAAK,gBAAgB,EAAE,CAAC;gBAC3D,MAAM,MAAM,GAAG,MAAM,IAAA,iCAAW,EAC9B,MAAM,EACN,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,YAAY,EACpB,GAAG,CACJ,CAAC;gBAEF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACtD,wDAAwD;gBACxD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,OAAO,CAC5C,MAAM,CAAC,YAAY,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAC7C,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;YAC1E,MAAM,EAAE,MAAM,EAAE,GAAG,IAAA,4CAAsB,EAAC,KAAK,CAAC,CAAC;YACjD,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;YAE3D,IAAI,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC;YAC9B,IAAI,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC;YAEhC,8BAA8B;YAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,IAAI,IAAI,CAAC,YAAY,KAAK,gBAAgB;oBAAE,MAAM;gBAClD,MAAM,MAAM,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;gBACzD,IAAI,CAAC,MAAM,CAAC,OAAO;oBAAE,MAAM;gBAC3B,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC;gBACzB,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC;YAC7B,CAAC;YAED,uCAAuC;YACvC,MAAM,SAAS,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,QAAQ,IAAI,CAAC,CAAC;YAC3E,+DAA+D;YAC/D,MAAM,SAAS,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,QAAQ,IAAI,CAAC,CAAC;YAE3E,iDAAiD;YACjD,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACtC,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;YACxF,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,2BAA2B;YAC3B,MAAM,WAAW,GAAG,MAAM,IAAA,uCAAiB,EACzC,MAAM,EACN,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,YAAY,EACpB,YAAY,CACb,CAAC;YAEF,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEvC,wBAAwB;YACxB,MAAM,KAAK,GAAG,WAAW,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;YACzD,MAAM,WAAW,GAAG,MAAM,IAAA,qCAAe,EACvC,MAAM,EACN,WAAW,CAAC,WAAW,EACvB,WAAW,CAAC,YAAY,EACxB,KAAK,CAAC,SAAS,CAChB,CAAC;YAEF,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEvC,gDAAgD;YAChD,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC;YACxD,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;YACxF,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,WAAW,GAAG,MAAM,IAAA,uCAAiB,EACzC,MAAM,EACN,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,YAAY,EACpB,YAAY,CACb,CAAC;YAEF,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEvC,MAAM,KAAK,GAAG,WAAW,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;YACzD,MAAM,WAAW,GAAG,MAAM,IAAA,qCAAe,EACvC,MAAM,EACN,WAAW,CAAC,WAAW,EACvB,WAAW,CAAC,YAAY,EACxB,KAAK,CAAC,SAAS,CAChB,CAAC;YAEF,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEvC,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC;YACxD,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;YACxF,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,WAAW,GAAG,MAAM,IAAA,uCAAiB,EACzC,MAAM,EACN,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,YAAY,EACpB,YAAY,CACb,CAAC;YAEF,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEvC,IAAI,GAAG,GAAG,WAAW,CAAC,WAAW,CAAC;YAClC,IAAI,IAAI,GAAG,WAAW,CAAC,YAAY,CAAC;YAEpC,mBAAmB;YACnB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;YACrC,MAAM,WAAW,GAAG,MAAM,IAAA,qCAAe,EAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;YAC9E,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEvC,qDAAqD;YACrD,MAAM,UAAU,GAAG,IAAA,4CAAsB,EAAC,WAAW,CAAC,CAAC;YACvD,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC;YAC7B,IAAI,GAAG,UAAU,CAAC,YAAY,CAAC;YAE/B,OAAO,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvC,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;gBACzC,MAAM,WAAW,GAAG,MAAM,IAAA,qCAAe,EAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;gBAClF,MAAM,UAAU,GAAG,IAAA,4CAAsB,EAAC,WAAW,CAAC,CAAC;gBACvD,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC;gBAC7B,IAAI,GAAG,UAAU,CAAC,YAAY,CAAC;YACjC,CAAC;YAED,mCAAmC;YACnC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACpD,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;YACpE,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,4BAA4B;YAC5B,MAAM,iBAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC;YAE/E,kCAAkC;YAClC,MAAM,WAAW,GAAG,MAAM,IAAA,uCAAiB,EACzC,MAAM,EACN,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,YAAY,EACpB,YAAY,CACb,CAAC;YAEF,MAAM,KAAK,GAAG,WAAW,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;YACzD,MAAM,WAAW,GAAG,MAAM,IAAA,qCAAe,EACvC,MAAM,EACN,WAAW,CAAC,WAAW,EACvB,WAAW,CAAC,YAAY,EACxB,KAAK,CAAC,SAAS,CAChB,CAAC;YAEF,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEvC,6CAA6C;YAC7C,MAAM,YAAY,GAAG,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC;YAC9E,MAAM,MAAM,GAAG,mCAAe,CAAC,QAAQ,CAAC,eAAe,CAAC,UAAU,CAAC;YACnE,MAAM,CAAC,YAAY,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACxD,MAAM,CAAC,YAAY,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAErD,+DAA+D;QACjE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,0BAA0B;YAC1B,MAAM,YAAY,GAAG,MAAM,wBAAwB,CACjD,MAAM,EACN,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,YAAY,EACpB,YAAY,EACZ,EAAE,CACH,CAAC;YAEF,yBAAyB;YACzB,MAAM,WAAW,GAAG,MAAM,IAAA,uCAAiB,EACzC,MAAM,EACN,YAAY,CAAC,WAAW,EACxB,YAAY,CAAC,YAAY,EACzB,gBAAgB,CACjB,CAAC;YAEF,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEvC,MAAM,KAAK,GAAG,WAAW,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;YACzD,MAAM,WAAW,GAAG,MAAM,IAAA,qCAAe,EACvC,MAAM,EACN,WAAW,CAAC,WAAW,EACvB,WAAW,CAAC,YAAY,EACxB,KAAK,CAAC,SAAS,CAChB,CAAC;YAEF,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEvC,uDAAuD;YACvD,6DAA6D;QAC/D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;QAC9C,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;YACjE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAA,4CAAsB,EAAC,KAAK,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,IAAI,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC;YAC9B,IAAI,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC;YAEhC,4BAA4B;YAC5B,MAAM,YAAY,GAAqE,EAAE,CAAC;YAC1F,YAAY,CAAC,IAAI,CAAC;gBAChB,UAAU,EAAE,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ;gBAC/C,UAAU,EAAE,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ;gBAC/C,UAAU,EAAE,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ;aAChD,CAAC,CAAC;YAEH,mBAAmB;YACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5B,IAAI,IAAI,CAAC,YAAY,KAAK,gBAAgB,EAAE,CAAC;oBAC3C,kCAAkC;oBAClC,IAAI,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;wBACpC,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;wBACrC,MAAM,WAAW,GAAG,MAAM,IAAA,qCAAe,EAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;wBAC9E,MAAM,UAAU,GAAG,IAAA,4CAAsB,EAAC,WAAW,CAAC,CAAC;wBACvD,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC;wBAC7B,IAAI,GAAG,UAAU,CAAC,YAAY,CAAC;wBAC/B,yBAAyB;wBACzB,OAAO,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;4BACvC,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;4BACzC,MAAM,WAAW,GAAG,MAAM,IAAA,qCAAe,EAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;4BAClF,MAAM,UAAU,GAAG,IAAA,4CAAsB,EAAC,WAAW,CAAC,CAAC;4BACvD,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC;4BAC7B,IAAI,GAAG,UAAU,CAAC,YAAY,CAAC;wBACjC,CAAC;oBACH,CAAC;oBACD,IAAI,IAAI,CAAC,YAAY,KAAK,gBAAgB;wBAAE,MAAM;gBACpD,CAAC;gBAED,MAAM,MAAM,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;gBACpD,IAAI,CAAC,MAAM,CAAC,OAAO;oBAAE,MAAM;gBAE3B,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC;gBACzB,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC;gBAE3B,YAAY,CAAC,IAAI,CAAC;oBAChB,UAAU,EAAE,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ;oBAC/C,UAAU,EAAE,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ;oBAC/C,UAAU,EAAE,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ;iBAChD,CAAC,CAAC;YACL,CAAC;YAED,+DAA+D;YAC/D,6CAA6C;YAC7C,KAAK,MAAM,KAAK,IAAI,YAAY,EAAE,CAAC;gBACjC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;gBACnD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;gBACnD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;YACrD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;YAC1E,0EAA0E;YAC1E,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,eAAe,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC;YAC5E,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAEhC,kEAAkE;YAClE,IAAI,OAAO,CAAC,YAAY,CAAC,YAAY,KAAK,gBAAgB,EAAE,CAAC;gBAC3D,MAAM,MAAM,GAAG,MAAM,IAAA,iCAAW,EAC9B,MAAM,EACN,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,YAAY,CACrB,CAAC;gBAEF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAElC,qEAAqE;gBACrE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;YACvF,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,kBAAkB,GAAG;gBACzB,UAAU,EAAE,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS;gBAChE,UAAU,EAAE,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS;gBAChE,UAAU,EAAE,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS;aACjE,CAAC;YAEF,iBAAiB;YACjB,IAAI,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC;YAC9B,IAAI,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC;YAEhC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,IAAI,IAAI,CAAC,YAAY,KAAK,gBAAgB;oBAAE,MAAM;gBAClD,MAAM,MAAM,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;gBACpD,IAAI,CAAC,MAAM,CAAC,OAAO;oBAAE,MAAM;gBAC3B,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC;gBACzB,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC;YAC7B,CAAC;YAED,oEAAoE;YACpE,sDAAsD;YACtD,KAAK,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBAClE,MAAM,MAAM,GAAG,mCAAe,CAAC,QAAQ,CAAC,eAAe,CAAC,GAA4D,CAAC,CAAC;gBACtH,MAAM,gBAAgB,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC;gBACxD,MAAM,CAAC,gBAAgB,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC5D,MAAM,CAAC,gBAAgB,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC3D,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC;YAEvE,0DAA0D;YAC1D,MAAM,SAAS,GAAG;gBAChB,EAAE,QAAQ,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;gBACjC,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;gBAC5D,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;gBAC3D,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;gBAC5D,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;gBAC3D,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;gBAC5D,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;gBAC1D,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE;gBAC5D,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,EAAE;aAC1C,CAAC;YAEF,IAAI,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC;YAC9B,IAAI,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC;YAEhC,KAAK,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,SAAS,EAAE,CAAC;gBACpD,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAC3C,MAAM,EACN,GAAG,EACH,IAAI,EACJ,YAAY,EACZ,QAAQ,CACT,CAAC;gBAEF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAClC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBAE5E,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC;gBACzB,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC;YAC7B,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACtC,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;YAC/D,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC;YAEvE,oCAAoC;YACpC,MAAM,WAAW,GAAG,MAAM,wBAAwB,CAChD,MAAM,EACN,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,YAAY,EACpB,YAAY,EACZ,SAAS,GAAG,CAAC,CACd,CAAC;YAEF,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEvC,8DAA8D;YAC9D,gDAAgD;YAChD,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAE/D,+BAA+B;YAC/B,MAAM,iBAAiB,GAAG,MAAM,wBAAwB,CACtD,MAAM,EACN,WAAW,CAAC,WAAW,EACvB,WAAW,CAAC,YAAY,EACxB,YAAY,EACZ,SAAS,CACV,CAAC;YAEF,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7C,6CAA6C;YAC7C,MAAM,CAAC,iBAAiB,CAAC,YAAY,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;YACxF,MAAM,MAAM,GAAG,IAAA,kCAAY,GAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,CAAC,CAAC;YAE1C,8BAA8B;YAC9B,IAAI,GAAG,GAAG,OAAO,CAAC,WAAW,CAAC;YAC9B,IAAI,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC;YAEhC,KAAK,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,YAAY,EAAE,YAAY,CAAC,EAAE,CAAC;gBAC7D,MAAM,SAAS,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC;gBACjD,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;gBACjF,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC;gBACzB,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC;YAC7B,CAAC;YAED,2DAA2D;YAC3D,IAAI,IAAI,CAAC,YAAY,KAAK,gBAAgB,EAAE,CAAC;gBAC3C,MAAM,MAAM,GAAG,MAAM,IAAA,iCAAW,EAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;gBACpD,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,YAAY,CAAC,cAAc,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;oBACrE,sCAAsC;oBACtC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAC5D,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|