@omnitronix/bonnys-fortune-game-engine 1.2.6 → 1.3.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 +0 -0
- package/dist/bonnys-fortune-v1.game-engine.js +2 -2
- package/dist/bonnys-fortune-v1.game-engine.js.map +1 -1
- package/dist/config/reel-strips-config/reels-BASE.csv +0 -0
- package/dist/config/reel-strips-config/reels-BONUS.csv +0 -0
- package/dist/index.js.map +1 -1
- package/dist/logic/handlers/base-game.handler.js +1 -19
- package/dist/logic/handlers/base-game.handler.js.map +1 -1
- package/dist/logic/handlers/collect-feature-bonus.handler.js +2 -2
- package/dist/logic/handlers/collect-feature-bonus.handler.js.map +1 -1
- package/dist/logic/handlers/free-spins-bonus.handler.js +2 -4
- package/dist/logic/handlers/free-spins-bonus.handler.js.map +1 -1
- package/dist/logic/handlers/steering-to-the-fortune-bonus.handler.js +2 -4
- package/dist/logic/handlers/steering-to-the-fortune-bonus.handler.js.map +1 -1
- package/dist/logic/handlers/treasure-hunt-bonus.handler.js +2 -4
- package/dist/logic/handlers/treasure-hunt-bonus.handler.js.map +1 -1
- package/dist/rng/rng-client.factory.js +3 -46
- package/dist/rng/rng-client.factory.js.map +1 -1
- package/package.json +1 -1
- package/dist/__tests__/rng-gli19-compliance.test.js +0 -222
- package/dist/__tests__/rng-gli19-compliance.test.js.map +0 -1
- package/dist/__tests__/rng-seed-security.test.js +0 -263
- package/dist/__tests__/rng-seed-security.test.js.map +0 -1
- package/dist/__tests__/rng-seed-type.test.js +0 -282
- package/dist/__tests__/rng-seed-type.test.js.map +0 -1
- package/dist/__tests__/rng-stress-boundary.test.js +0 -386
- package/dist/__tests__/rng-stress-boundary.test.js.map +0 -1
|
@@ -1,386 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* RNG Stress and Boundary Tests - Bonny's Fortune
|
|
4
|
-
*/
|
|
5
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
-
}
|
|
11
|
-
Object.defineProperty(o, k2, desc);
|
|
12
|
-
}) : (function(o, m, k, k2) {
|
|
13
|
-
if (k2 === undefined) k2 = k;
|
|
14
|
-
o[k2] = m[k];
|
|
15
|
-
}));
|
|
16
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
-
}) : function(o, v) {
|
|
19
|
-
o["default"] = v;
|
|
20
|
-
});
|
|
21
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
-
var ownKeys = function(o) {
|
|
23
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
-
var ar = [];
|
|
25
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
-
return ar;
|
|
27
|
-
};
|
|
28
|
-
return ownKeys(o);
|
|
29
|
-
};
|
|
30
|
-
return function (mod) {
|
|
31
|
-
if (mod && mod.__esModule) return mod;
|
|
32
|
-
var result = {};
|
|
33
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
-
__setModuleDefault(result, mod);
|
|
35
|
-
return result;
|
|
36
|
-
};
|
|
37
|
-
})();
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
const fs = __importStar(require("fs"));
|
|
40
|
-
const path = __importStar(require("path"));
|
|
41
|
-
const bonnys_fortune_v1_game_engine_1 = require("../bonnys-fortune-v1.game-engine");
|
|
42
|
-
const bonnys_fortune_types_1 = require("../logic/bonnys-fortune.types");
|
|
43
|
-
// Results output directory
|
|
44
|
-
const RESULTS_DIR = path.join(__dirname, '../../results');
|
|
45
|
-
function ensureResultsDir() {
|
|
46
|
-
if (!fs.existsSync(RESULTS_DIR)) {
|
|
47
|
-
fs.mkdirSync(RESULTS_DIR, { recursive: true });
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
function getResultsFileName(gameName, spinCount) {
|
|
51
|
-
const date = new Date().toISOString().split('T')[0];
|
|
52
|
-
const time = new Date().toISOString().split('T')[1].split('.')[0].replace(/:/g, '-');
|
|
53
|
-
return path.join(RESULTS_DIR, `${gameName}-${spinCount}-${date}-${time}.ndjson`);
|
|
54
|
-
}
|
|
55
|
-
describe('RNG Stress and Boundary Tests', () => {
|
|
56
|
-
let engine;
|
|
57
|
-
beforeEach(() => {
|
|
58
|
-
engine = new bonnys_fortune_v1_game_engine_1.BonnysFortuneV1GameEngine();
|
|
59
|
-
});
|
|
60
|
-
async function initSession() {
|
|
61
|
-
return engine.processCommand(null, null, {
|
|
62
|
-
id: `init-${Math.random().toString(36).slice(2)}`,
|
|
63
|
-
type: 'INIT_SESSION_STATE',
|
|
64
|
-
payload: { betAmountThresholds: [1, 2, 5, 10], defaultBetAmount: 1 },
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
async function executeSpin(publicState, privateState) {
|
|
68
|
-
return engine.processCommand(publicState, privateState, {
|
|
69
|
-
id: `spin-${Math.random().toString(36).slice(2)}`,
|
|
70
|
-
type: 'SPIN',
|
|
71
|
-
payload: { sessionId: 'test', betAmount: 1, gameCode: 'bonnys-fortune', gameVersion: '1.0.0', lines: 10, creditsPerLine: 1 },
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
async function executeBonusRound(publicState, privateState) {
|
|
75
|
-
const pendingBonus = privateState.pendingBonuses?.[0];
|
|
76
|
-
if (!pendingBonus) {
|
|
77
|
-
throw new Error('No pending bonus found');
|
|
78
|
-
}
|
|
79
|
-
return engine.processCommand(publicState, privateState, {
|
|
80
|
-
id: `bonus-${Math.random().toString(36).slice(2)}`,
|
|
81
|
-
type: 'START_BONUS_ROUND',
|
|
82
|
-
payload: {
|
|
83
|
-
sessionId: 'test',
|
|
84
|
-
betAmount: pendingBonus.betAmount || 1,
|
|
85
|
-
bonusId: pendingBonus.bonusId,
|
|
86
|
-
bonusType: pendingBonus.bonusType,
|
|
87
|
-
gameCode: 'bonnys-fortune',
|
|
88
|
-
gameVersion: '1.0.0',
|
|
89
|
-
},
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
// Helper to execute spin and handle any bonus that triggers
|
|
93
|
-
async function executeSpinWithBonusHandling(publicState, privateState) {
|
|
94
|
-
const results = [];
|
|
95
|
-
let pub = publicState;
|
|
96
|
-
let priv = privateState;
|
|
97
|
-
const spin = await executeSpin(pub, priv);
|
|
98
|
-
results.push(spin);
|
|
99
|
-
pub = spin.publicState;
|
|
100
|
-
priv = spin.privateState;
|
|
101
|
-
// Handle bonus rounds - any non-BASE_GAME_SPIN with pending bonuses
|
|
102
|
-
while (priv.nextSpinType !== bonnys_fortune_types_1.SpinType.BASE_GAME_SPIN && priv.pendingBonuses?.length > 0) {
|
|
103
|
-
const bonus = await executeBonusRound(pub, priv);
|
|
104
|
-
results.push(bonus);
|
|
105
|
-
pub = bonus.publicState;
|
|
106
|
-
priv = bonus.privateState;
|
|
107
|
-
}
|
|
108
|
-
return { results, publicState: pub, privateState: priv };
|
|
109
|
-
}
|
|
110
|
-
function canonicalizeForHash(outcome) {
|
|
111
|
-
return JSON.stringify(Object.entries(outcome)
|
|
112
|
-
.map(([actionId, record]) => ({
|
|
113
|
-
actionId, result: Number(record.result), seed: String(record.seed),
|
|
114
|
-
min: Number(record.min), max: Number(record.max),
|
|
115
|
-
}))
|
|
116
|
-
.sort((a, b) => a.actionId.localeCompare(b.actionId)));
|
|
117
|
-
}
|
|
118
|
-
// ============================================================
|
|
119
|
-
// BOUNDARY CONDITIONS
|
|
120
|
-
// ============================================================
|
|
121
|
-
describe('Boundary Conditions', () => {
|
|
122
|
-
it('should handle MAX_SAFE_INTEGER', () => {
|
|
123
|
-
const outcome = { test: { result: 5, seed: Number.MAX_SAFE_INTEGER, min: 0, max: 10 } };
|
|
124
|
-
expect(canonicalizeForHash(outcome)).toContain(`"seed":"${Number.MAX_SAFE_INTEGER}"`);
|
|
125
|
-
});
|
|
126
|
-
it('should handle MIN_SAFE_INTEGER', () => {
|
|
127
|
-
const outcome = { test: { result: 5, seed: Number.MIN_SAFE_INTEGER, min: -100, max: 100 } };
|
|
128
|
-
expect(canonicalizeForHash(outcome)).toContain(`"seed":"${Number.MIN_SAFE_INTEGER}"`);
|
|
129
|
-
});
|
|
130
|
-
it('should handle empty outcome', () => {
|
|
131
|
-
expect(canonicalizeForHash({})).toBe('[]');
|
|
132
|
-
});
|
|
133
|
-
it('should handle 100 records', () => {
|
|
134
|
-
const outcome = {};
|
|
135
|
-
for (let i = 0; i < 100; i++) {
|
|
136
|
-
outcome[`action_${i.toString().padStart(3, '0')}`] = { result: i % 10, seed: i * 1000, min: 0, max: 9 };
|
|
137
|
-
}
|
|
138
|
-
expect(JSON.parse(canonicalizeForHash(outcome)).length).toBe(100);
|
|
139
|
-
});
|
|
140
|
-
it('should handle 1000 records', () => {
|
|
141
|
-
const outcome = {};
|
|
142
|
-
for (let i = 0; i < 1000; i++) {
|
|
143
|
-
outcome[`action_${i.toString().padStart(4, '0')}`] = { result: i % 10, seed: i * 1000, min: 0, max: 9 };
|
|
144
|
-
}
|
|
145
|
-
expect(JSON.parse(canonicalizeForHash(outcome)).length).toBe(1000);
|
|
146
|
-
});
|
|
147
|
-
it('should handle long actionId (1000 chars)', () => {
|
|
148
|
-
const longId = 'a'.repeat(1000);
|
|
149
|
-
const outcome = { [longId]: { result: 5, seed: 123, min: 0, max: 10 } };
|
|
150
|
-
expect(JSON.parse(canonicalizeForHash(outcome))[0].actionId.length).toBe(1000);
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
// ============================================================
|
|
154
|
-
// STRESS TESTS
|
|
155
|
-
// ============================================================
|
|
156
|
-
describe('Stress Tests', () => {
|
|
157
|
-
it('should handle 100 consecutive spins with bonus handling', async () => {
|
|
158
|
-
const init = await initSession();
|
|
159
|
-
let pub = init.publicState;
|
|
160
|
-
let priv = init.privateState;
|
|
161
|
-
const allResults = [];
|
|
162
|
-
for (let i = 0; i < 100; i++) {
|
|
163
|
-
const { results, publicState, privateState } = await executeSpinWithBonusHandling(pub, priv);
|
|
164
|
-
// Verify all results (spin + any bonus rounds) succeeded
|
|
165
|
-
results.forEach(r => allResults.push(r.success));
|
|
166
|
-
pub = publicState;
|
|
167
|
-
priv = privateState;
|
|
168
|
-
}
|
|
169
|
-
expect(allResults.every(r => r === true)).toBe(true);
|
|
170
|
-
}, 120000);
|
|
171
|
-
it('should maintain consistent RNG structure across 100 spins with bonus handling', async () => {
|
|
172
|
-
const init = await initSession();
|
|
173
|
-
let pub = init.publicState;
|
|
174
|
-
let priv = init.privateState;
|
|
175
|
-
for (let i = 0; i < 100; i++) {
|
|
176
|
-
const { results, publicState, privateState } = await executeSpinWithBonusHandling(pub, priv);
|
|
177
|
-
// Verify RNG structure for all results (spin + any bonus rounds)
|
|
178
|
-
for (const result of results) {
|
|
179
|
-
if (result.rngOutcome) {
|
|
180
|
-
for (const [, record] of Object.entries(result.rngOutcome)) {
|
|
181
|
-
expect(typeof record.seed).toBe('number');
|
|
182
|
-
expect(typeof record.result).toBe('number');
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
pub = publicState;
|
|
187
|
-
priv = privateState;
|
|
188
|
-
}
|
|
189
|
-
}, 120000);
|
|
190
|
-
it('should handle rapid session initialization', async () => {
|
|
191
|
-
const results = [];
|
|
192
|
-
for (let i = 0; i < 50; i++) {
|
|
193
|
-
const init = await initSession();
|
|
194
|
-
results.push(init.success);
|
|
195
|
-
}
|
|
196
|
-
expect(results.every(r => r === true)).toBe(true);
|
|
197
|
-
}, 30000);
|
|
198
|
-
it('should process 10000 canonicalizations efficiently', () => {
|
|
199
|
-
const outcomes = Array(10000).fill(0).map((_, i) => ({
|
|
200
|
-
[`action_${i}`]: { result: i % 10, seed: i * 1000, min: 0, max: 9 },
|
|
201
|
-
}));
|
|
202
|
-
const start = Date.now();
|
|
203
|
-
outcomes.forEach(o => canonicalizeForHash(o));
|
|
204
|
-
expect(Date.now() - start).toBeLessThan(5000);
|
|
205
|
-
});
|
|
206
|
-
it('should handle consecutive spins with bonus handling (configurable)', async () => {
|
|
207
|
-
const SPIN_COUNT = parseInt(process.env.RTP_TEST_SPINS || '10000');
|
|
208
|
-
ensureResultsDir();
|
|
209
|
-
const resultsFile = getResultsFileName('bonnys-fortune', SPIN_COUNT);
|
|
210
|
-
const writeStream = fs.createWriteStream(resultsFile);
|
|
211
|
-
const init = await initSession();
|
|
212
|
-
let pub = init.publicState;
|
|
213
|
-
let priv = init.privateState;
|
|
214
|
-
let totalSpins = 0;
|
|
215
|
-
let totalBonusRounds = 0;
|
|
216
|
-
let failures = 0;
|
|
217
|
-
const betAmount = 1;
|
|
218
|
-
console.log(`\nRunning ${SPIN_COUNT} spins with real RNG`);
|
|
219
|
-
console.log(`Writing results to: ${resultsFile}\n`);
|
|
220
|
-
for (let i = 0; i < SPIN_COUNT; i++) {
|
|
221
|
-
const { results, publicState, privateState } = await executeSpinWithBonusHandling(pub, priv);
|
|
222
|
-
totalSpins++;
|
|
223
|
-
const bonusRoundsThisSpin = results.length - 1;
|
|
224
|
-
totalBonusRounds += bonusRoundsThisSpin;
|
|
225
|
-
// Sum winnings from all results (spin + any bonus rounds)
|
|
226
|
-
let totalWonThisSpin = 0;
|
|
227
|
-
let bonusWonThisSpin = 0;
|
|
228
|
-
results.forEach((r, idx) => {
|
|
229
|
-
if (!r.success) {
|
|
230
|
-
failures++;
|
|
231
|
-
}
|
|
232
|
-
else {
|
|
233
|
-
const outcome = r.outcome;
|
|
234
|
-
// Base spin: outcome.result.playerWinning
|
|
235
|
-
// Bonus round: outcome.results[] array of results
|
|
236
|
-
let won = 0;
|
|
237
|
-
if (outcome?.result?.playerWinning !== undefined) {
|
|
238
|
-
won = outcome.result.playerWinning;
|
|
239
|
-
}
|
|
240
|
-
else if (Array.isArray(outcome?.results)) {
|
|
241
|
-
// Sum all wins from bonus round results array
|
|
242
|
-
won = outcome.results.reduce((sum, res) => {
|
|
243
|
-
return sum + (res?.result?.playerWinning || 0);
|
|
244
|
-
}, 0);
|
|
245
|
-
}
|
|
246
|
-
totalWonThisSpin += won;
|
|
247
|
-
if (idx > 0)
|
|
248
|
-
bonusWonThisSpin += won;
|
|
249
|
-
}
|
|
250
|
-
});
|
|
251
|
-
// Write result to NDJSON file
|
|
252
|
-
const record = {
|
|
253
|
-
spin: totalSpins,
|
|
254
|
-
wagered: betAmount,
|
|
255
|
-
won: totalWonThisSpin,
|
|
256
|
-
baseWin: totalWonThisSpin - bonusWonThisSpin,
|
|
257
|
-
bonusTriggered: bonusRoundsThisSpin > 0,
|
|
258
|
-
bonusWon: bonusWonThisSpin,
|
|
259
|
-
bonusRounds: bonusRoundsThisSpin,
|
|
260
|
-
success: results.every(r => r.success),
|
|
261
|
-
};
|
|
262
|
-
writeStream.write(JSON.stringify(record) + '\n');
|
|
263
|
-
pub = publicState;
|
|
264
|
-
priv = privateState;
|
|
265
|
-
if (totalSpins % 1000 === 0) {
|
|
266
|
-
console.log(`Progress: ${totalSpins} spins completed...`);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
writeStream.end();
|
|
270
|
-
console.log(`\n=== ${SPIN_COUNT} Spins Test - Bonny's Fortune ===`);
|
|
271
|
-
console.log(`Total base spins: ${totalSpins}`);
|
|
272
|
-
console.log(`Total bonus rounds: ${totalBonusRounds}`);
|
|
273
|
-
console.log(`Total failures: ${failures}`);
|
|
274
|
-
console.log(`Results saved to: ${resultsFile}`);
|
|
275
|
-
console.log(`\nTo calculate RTP, run:`);
|
|
276
|
-
console.log(` node /opt/omnitronix/omnitronix-docs/scripts/calculate-rtp.js ${resultsFile}`);
|
|
277
|
-
expect(failures).toBe(0);
|
|
278
|
-
expect(totalSpins).toBe(SPIN_COUNT);
|
|
279
|
-
}, 1800000); // 30 minute timeout
|
|
280
|
-
it('should handle 100000 consecutive spins with bonus handling', async () => {
|
|
281
|
-
const init = await initSession();
|
|
282
|
-
let pub = init.publicState;
|
|
283
|
-
let priv = init.privateState;
|
|
284
|
-
let totalSpins = 0;
|
|
285
|
-
let totalBonusRounds = 0;
|
|
286
|
-
let failures = 0;
|
|
287
|
-
let totalWagered = 0;
|
|
288
|
-
let totalWon = 0;
|
|
289
|
-
const betAmount = 1; // Default bet from initSession
|
|
290
|
-
while (totalSpins < 100000) {
|
|
291
|
-
const { results, publicState, privateState } = await executeSpinWithBonusHandling(pub, priv);
|
|
292
|
-
totalSpins++;
|
|
293
|
-
totalWagered += betAmount; // Only base spin costs money
|
|
294
|
-
totalBonusRounds += results.length - 1; // Subtract 1 for the base spin
|
|
295
|
-
// Sum winnings from all results (spin + any bonus rounds)
|
|
296
|
-
results.forEach(r => {
|
|
297
|
-
if (!r.success) {
|
|
298
|
-
failures++;
|
|
299
|
-
}
|
|
300
|
-
else {
|
|
301
|
-
// Slot engines return playerWinning in outcome.result
|
|
302
|
-
const outcome = r.outcome;
|
|
303
|
-
totalWon += outcome?.result?.playerWinning || 0;
|
|
304
|
-
}
|
|
305
|
-
});
|
|
306
|
-
pub = publicState;
|
|
307
|
-
priv = privateState;
|
|
308
|
-
}
|
|
309
|
-
const rtp = totalWagered > 0 ? (totalWon / totalWagered) * 100 : 0;
|
|
310
|
-
console.log(`\n=== 100000 Spins Test - Bonny's Fortune ===`);
|
|
311
|
-
console.log(`Total base spins: ${totalSpins}`);
|
|
312
|
-
console.log(`Total bonus rounds triggered: ${totalBonusRounds}`);
|
|
313
|
-
console.log(`Bonus trigger rate: ${(totalBonusRounds / totalSpins * 100).toFixed(2)}%`);
|
|
314
|
-
console.log(`Total failures: ${failures}`);
|
|
315
|
-
console.log(`Total wagered: ${totalWagered.toFixed(2)}`);
|
|
316
|
-
console.log(`Total won: ${totalWon.toFixed(2)}`);
|
|
317
|
-
console.log(`Calculated RTP: ${rtp.toFixed(2)}%`);
|
|
318
|
-
expect(failures).toBe(0);
|
|
319
|
-
expect(totalSpins).toBe(100000);
|
|
320
|
-
}, 1800000); // 30 minute timeout
|
|
321
|
-
});
|
|
322
|
-
// ============================================================
|
|
323
|
-
// SORTING
|
|
324
|
-
// ============================================================
|
|
325
|
-
describe('Sorting Verification', () => {
|
|
326
|
-
it('should sort alphabetically', () => {
|
|
327
|
-
const outcome = {
|
|
328
|
-
zebra: { result: 1, seed: 100, min: 0, max: 10 },
|
|
329
|
-
apple: { result: 2, seed: 200, min: 0, max: 10 },
|
|
330
|
-
mango: { result: 3, seed: 300, min: 0, max: 10 },
|
|
331
|
-
};
|
|
332
|
-
const parsed = JSON.parse(canonicalizeForHash(outcome));
|
|
333
|
-
expect(parsed[0].actionId).toBe('apple');
|
|
334
|
-
expect(parsed[1].actionId).toBe('mango');
|
|
335
|
-
expect(parsed[2].actionId).toBe('zebra');
|
|
336
|
-
});
|
|
337
|
-
it('should sort numeric strings as strings', () => {
|
|
338
|
-
const outcome = {
|
|
339
|
-
'10': { result: 1, seed: 100, min: 0, max: 10 },
|
|
340
|
-
'2': { result: 2, seed: 200, min: 0, max: 10 },
|
|
341
|
-
'1': { result: 3, seed: 300, min: 0, max: 10 },
|
|
342
|
-
};
|
|
343
|
-
const parsed = JSON.parse(canonicalizeForHash(outcome));
|
|
344
|
-
expect(parsed[0].actionId).toBe('1');
|
|
345
|
-
expect(parsed[1].actionId).toBe('10');
|
|
346
|
-
expect(parsed[2].actionId).toBe('2');
|
|
347
|
-
});
|
|
348
|
-
it('should maintain stable sort', () => {
|
|
349
|
-
const outcome = {};
|
|
350
|
-
for (let i = 0; i < 100; i++) {
|
|
351
|
-
outcome[`action_${String.fromCharCode(65 + (i % 26))}_${i}`] = { result: i % 10, seed: i * 1000, min: 0, max: 9 };
|
|
352
|
-
}
|
|
353
|
-
const c1 = canonicalizeForHash(outcome);
|
|
354
|
-
const c2 = canonicalizeForHash(outcome);
|
|
355
|
-
expect(c1).toBe(c2);
|
|
356
|
-
});
|
|
357
|
-
});
|
|
358
|
-
// ============================================================
|
|
359
|
-
// STATE PERSISTENCE
|
|
360
|
-
// ============================================================
|
|
361
|
-
describe('State Persistence', () => {
|
|
362
|
-
it('should handle state serialization round-trip', async () => {
|
|
363
|
-
const init = await initSession();
|
|
364
|
-
const spin = await executeSpin(init.publicState, init.privateState);
|
|
365
|
-
const serializedPublic = JSON.stringify(spin.publicState);
|
|
366
|
-
const serializedPrivate = JSON.stringify(spin.privateState);
|
|
367
|
-
const restoredPublic = JSON.parse(serializedPublic);
|
|
368
|
-
const restoredPrivate = JSON.parse(serializedPrivate);
|
|
369
|
-
// Verify serialization preserved the state structure
|
|
370
|
-
expect(restoredPublic).toBeDefined();
|
|
371
|
-
expect(restoredPrivate).toBeDefined();
|
|
372
|
-
expect(restoredPrivate.nextSpinType).toBeDefined();
|
|
373
|
-
// If bonus triggered, execute bonus round with restored state
|
|
374
|
-
if (restoredPrivate.nextSpinType !== bonnys_fortune_types_1.SpinType.BASE_GAME_SPIN && restoredPrivate.pendingBonuses?.length > 0) {
|
|
375
|
-
const bonus = await executeBonusRound(restoredPublic, restoredPrivate);
|
|
376
|
-
expect(bonus.success).toBe(true);
|
|
377
|
-
}
|
|
378
|
-
else {
|
|
379
|
-
// Continue with regular spin
|
|
380
|
-
const nextSpin = await executeSpin(restoredPublic, restoredPrivate);
|
|
381
|
-
expect(nextSpin.success).toBe(true);
|
|
382
|
-
}
|
|
383
|
-
});
|
|
384
|
-
});
|
|
385
|
-
});
|
|
386
|
-
//# sourceMappingURL=rng-stress-boundary.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rng-stress-boundary.test.js","sourceRoot":"","sources":["../../src/__tests__/rng-stress-boundary.test.ts"],"names":[],"mappings":"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"}
|