@omnitronix/happy-panda-game-engine 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/README.md +732 -0
  2. package/dist/__tests__/bonus-sequence.test.d.ts +7 -0
  3. package/dist/__tests__/bonus-sequence.test.d.ts.map +1 -0
  4. package/dist/__tests__/bonus-sequence.test.js +381 -0
  5. package/dist/__tests__/bonus-sequence.test.js.map +1 -0
  6. package/dist/__tests__/cherry-frequency.test.d.ts +8 -0
  7. package/dist/__tests__/cherry-frequency.test.d.ts.map +1 -0
  8. package/dist/__tests__/cherry-frequency.test.js +128 -0
  9. package/dist/__tests__/cherry-frequency.test.js.map +1 -0
  10. package/dist/__tests__/comprehensive.test.d.ts +16 -0
  11. package/dist/__tests__/comprehensive.test.d.ts.map +1 -0
  12. package/dist/__tests__/comprehensive.test.js +491 -0
  13. package/dist/__tests__/comprehensive.test.js.map +1 -0
  14. package/dist/__tests__/counter-manager.test.d.ts +7 -0
  15. package/dist/__tests__/counter-manager.test.d.ts.map +1 -0
  16. package/dist/__tests__/counter-manager.test.js +317 -0
  17. package/dist/__tests__/counter-manager.test.js.map +1 -0
  18. package/dist/__tests__/coverage-boost.test.d.ts +13 -0
  19. package/dist/__tests__/coverage-boost.test.d.ts.map +1 -0
  20. package/dist/__tests__/coverage-boost.test.js +606 -0
  21. package/dist/__tests__/coverage-boost.test.js.map +1 -0
  22. package/dist/__tests__/cpp-parity.test.d.ts +39 -0
  23. package/dist/__tests__/cpp-parity.test.d.ts.map +1 -0
  24. package/dist/__tests__/cpp-parity.test.js +392 -0
  25. package/dist/__tests__/cpp-parity.test.js.map +1 -0
  26. package/dist/__tests__/debug-trigger-bonus.test.d.ts +8 -0
  27. package/dist/__tests__/debug-trigger-bonus.test.d.ts.map +1 -0
  28. package/dist/__tests__/debug-trigger-bonus.test.js +359 -0
  29. package/dist/__tests__/debug-trigger-bonus.test.js.map +1 -0
  30. package/dist/__tests__/fixtures/cpp-parity-vectors.json +457 -0
  31. package/dist/__tests__/gdd-validation-1000.test.d.ts +14 -0
  32. package/dist/__tests__/gdd-validation-1000.test.d.ts.map +1 -0
  33. package/dist/__tests__/gdd-validation-1000.test.js +418 -0
  34. package/dist/__tests__/gdd-validation-1000.test.js.map +1 -0
  35. package/dist/__tests__/happy-panda-engine.test.d.ts +7 -0
  36. package/dist/__tests__/happy-panda-engine.test.d.ts.map +1 -0
  37. package/dist/__tests__/happy-panda-engine.test.js +414 -0
  38. package/dist/__tests__/happy-panda-engine.test.js.map +1 -0
  39. package/dist/__tests__/jackpot-manager.test.d.ts +8 -0
  40. package/dist/__tests__/jackpot-manager.test.d.ts.map +1 -0
  41. package/dist/__tests__/jackpot-manager.test.js +313 -0
  42. package/dist/__tests__/jackpot-manager.test.js.map +1 -0
  43. package/dist/__tests__/jackpot-trigger-trace.test.d.ts +6 -0
  44. package/dist/__tests__/jackpot-trigger-trace.test.d.ts.map +1 -0
  45. package/dist/__tests__/jackpot-trigger-trace.test.js +146 -0
  46. package/dist/__tests__/jackpot-trigger-trace.test.js.map +1 -0
  47. package/dist/__tests__/rng-gli19-compliance.test.d.ts +21 -0
  48. package/dist/__tests__/rng-gli19-compliance.test.d.ts.map +1 -0
  49. package/dist/__tests__/rng-gli19-compliance.test.js +480 -0
  50. package/dist/__tests__/rng-gli19-compliance.test.js.map +1 -0
  51. package/dist/__tests__/rng-seed-security.test.d.ts +19 -0
  52. package/dist/__tests__/rng-seed-security.test.d.ts.map +1 -0
  53. package/dist/__tests__/rng-seed-security.test.js +518 -0
  54. package/dist/__tests__/rng-seed-security.test.js.map +1 -0
  55. package/dist/__tests__/rng-seed-type.test.d.ts +16 -0
  56. package/dist/__tests__/rng-seed-type.test.d.ts.map +1 -0
  57. package/dist/__tests__/rng-seed-type.test.js +285 -0
  58. package/dist/__tests__/rng-seed-type.test.js.map +1 -0
  59. package/dist/__tests__/rng-stress-boundary.test.d.ts +15 -0
  60. package/dist/__tests__/rng-stress-boundary.test.d.ts.map +1 -0
  61. package/dist/__tests__/rng-stress-boundary.test.js +590 -0
  62. package/dist/__tests__/rng-stress-boundary.test.js.map +1 -0
  63. package/dist/__tests__/rtp-1million.test.d.ts +8 -0
  64. package/dist/__tests__/rtp-1million.test.d.ts.map +1 -0
  65. package/dist/__tests__/rtp-1million.test.js +156 -0
  66. package/dist/__tests__/rtp-1million.test.js.map +1 -0
  67. package/dist/__tests__/rtp-analysis.test.d.ts +8 -0
  68. package/dist/__tests__/rtp-analysis.test.d.ts.map +1 -0
  69. package/dist/__tests__/rtp-analysis.test.js +138 -0
  70. package/dist/__tests__/rtp-analysis.test.js.map +1 -0
  71. package/dist/__tests__/rtp-diagnostic.test.d.ts +6 -0
  72. package/dist/__tests__/rtp-diagnostic.test.d.ts.map +1 -0
  73. package/dist/__tests__/rtp-diagnostic.test.js +141 -0
  74. package/dist/__tests__/rtp-diagnostic.test.js.map +1 -0
  75. package/dist/__tests__/rtp-simulation.test.d.ts +8 -0
  76. package/dist/__tests__/rtp-simulation.test.d.ts.map +1 -0
  77. package/dist/__tests__/rtp-simulation.test.js +411 -0
  78. package/dist/__tests__/rtp-simulation.test.js.map +1 -0
  79. package/dist/__tests__/special-wins.test.d.ts +7 -0
  80. package/dist/__tests__/special-wins.test.d.ts.map +1 -0
  81. package/dist/__tests__/special-wins.test.js +179 -0
  82. package/dist/__tests__/special-wins.test.js.map +1 -0
  83. package/dist/__tests__/spin-generator.test.d.ts +7 -0
  84. package/dist/__tests__/spin-generator.test.d.ts.map +1 -0
  85. package/dist/__tests__/spin-generator.test.js +297 -0
  86. package/dist/__tests__/spin-generator.test.js.map +1 -0
  87. package/dist/__tests__/spin-handler.test.d.ts +7 -0
  88. package/dist/__tests__/spin-handler.test.d.ts.map +1 -0
  89. package/dist/__tests__/spin-handler.test.js +210 -0
  90. package/dist/__tests__/spin-handler.test.js.map +1 -0
  91. package/dist/__tests__/symbol-distribution.test.d.ts +6 -0
  92. package/dist/__tests__/symbol-distribution.test.d.ts.map +1 -0
  93. package/dist/__tests__/symbol-distribution.test.js +119 -0
  94. package/dist/__tests__/symbol-distribution.test.js.map +1 -0
  95. package/dist/__tests__/test-protocol-10000-spin.test.d.ts +14 -0
  96. package/dist/__tests__/test-protocol-10000-spin.test.d.ts.map +1 -0
  97. package/dist/__tests__/test-protocol-10000-spin.test.js +359 -0
  98. package/dist/__tests__/test-protocol-10000-spin.test.js.map +1 -0
  99. package/dist/__tests__/weighted-random.test.d.ts +7 -0
  100. package/dist/__tests__/weighted-random.test.d.ts.map +1 -0
  101. package/dist/__tests__/weighted-random.test.js +165 -0
  102. package/dist/__tests__/weighted-random.test.js.map +1 -0
  103. package/dist/__tests__/win-evaluator.test.d.ts +7 -0
  104. package/dist/__tests__/win-evaluator.test.d.ts.map +1 -0
  105. package/dist/__tests__/win-evaluator.test.js +264 -0
  106. package/dist/__tests__/win-evaluator.test.js.map +1 -0
  107. package/dist/config/happy-panda.config.d.ts +217 -0
  108. package/dist/config/happy-panda.config.d.ts.map +1 -0
  109. package/dist/config/happy-panda.config.js +721 -0
  110. package/dist/config/happy-panda.config.js.map +1 -0
  111. package/dist/config/index.d.ts +5 -0
  112. package/dist/config/index.d.ts.map +1 -0
  113. package/dist/config/index.js +21 -0
  114. package/dist/config/index.js.map +1 -0
  115. package/dist/debug/debug-command-definitions.d.ts +38 -0
  116. package/dist/debug/debug-command-definitions.d.ts.map +1 -0
  117. package/dist/debug/debug-command-definitions.js +80 -0
  118. package/dist/debug/debug-command-definitions.js.map +1 -0
  119. package/dist/domain/debug-trigger-bonus-command.d.ts +17 -0
  120. package/dist/domain/debug-trigger-bonus-command.d.ts.map +1 -0
  121. package/dist/domain/debug-trigger-bonus-command.js +3 -0
  122. package/dist/domain/debug-trigger-bonus-command.js.map +1 -0
  123. package/dist/domain/index.d.ts +5 -0
  124. package/dist/domain/index.d.ts.map +1 -0
  125. package/dist/domain/index.js +21 -0
  126. package/dist/domain/index.js.map +1 -0
  127. package/dist/domain/types.d.ts +228 -0
  128. package/dist/domain/types.d.ts.map +1 -0
  129. package/dist/domain/types.js +30 -0
  130. package/dist/domain/types.js.map +1 -0
  131. package/dist/engine/happy-panda-engine.d.ts +64 -0
  132. package/dist/engine/happy-panda-engine.d.ts.map +1 -0
  133. package/dist/engine/happy-panda-engine.js +324 -0
  134. package/dist/engine/happy-panda-engine.js.map +1 -0
  135. package/dist/engine/index.d.ts +5 -0
  136. package/dist/engine/index.d.ts.map +1 -0
  137. package/dist/engine/index.js +21 -0
  138. package/dist/engine/index.js.map +1 -0
  139. package/dist/game-engine.interface.d.ts +19 -0
  140. package/dist/game-engine.interface.d.ts.map +1 -0
  141. package/dist/game-engine.interface.js +9 -0
  142. package/dist/game-engine.interface.js.map +1 -0
  143. package/dist/happy-panda-v1.game-engine.d.ts +60 -0
  144. package/dist/happy-panda-v1.game-engine.d.ts.map +1 -0
  145. package/dist/happy-panda-v1.game-engine.js +524 -0
  146. package/dist/happy-panda-v1.game-engine.js.map +1 -0
  147. package/dist/index.d.ts +22 -0
  148. package/dist/index.d.ts.map +1 -0
  149. package/dist/index.js +59 -0
  150. package/dist/index.js.map +1 -0
  151. package/dist/logic/handlers/index.d.ts +5 -0
  152. package/dist/logic/handlers/index.d.ts.map +1 -0
  153. package/dist/logic/handlers/index.js +21 -0
  154. package/dist/logic/handlers/index.js.map +1 -0
  155. package/dist/logic/handlers/spin-handler.d.ts +58 -0
  156. package/dist/logic/handlers/spin-handler.d.ts.map +1 -0
  157. package/dist/logic/handlers/spin-handler.js +265 -0
  158. package/dist/logic/handlers/spin-handler.js.map +1 -0
  159. package/dist/logic/index.d.ts +6 -0
  160. package/dist/logic/index.d.ts.map +1 -0
  161. package/dist/logic/index.js +22 -0
  162. package/dist/logic/index.js.map +1 -0
  163. package/dist/logic/services/counter-manager.d.ts +60 -0
  164. package/dist/logic/services/counter-manager.d.ts.map +1 -0
  165. package/dist/logic/services/counter-manager.js +268 -0
  166. package/dist/logic/services/counter-manager.js.map +1 -0
  167. package/dist/logic/services/index.d.ts +7 -0
  168. package/dist/logic/services/index.d.ts.map +1 -0
  169. package/dist/logic/services/index.js +23 -0
  170. package/dist/logic/services/index.js.map +1 -0
  171. package/dist/logic/services/jackpot-manager.d.ts +59 -0
  172. package/dist/logic/services/jackpot-manager.d.ts.map +1 -0
  173. package/dist/logic/services/jackpot-manager.js +142 -0
  174. package/dist/logic/services/jackpot-manager.js.map +1 -0
  175. package/dist/logic/services/win-evaluator.d.ts +51 -0
  176. package/dist/logic/services/win-evaluator.d.ts.map +1 -0
  177. package/dist/logic/services/win-evaluator.js +463 -0
  178. package/dist/logic/services/win-evaluator.js.map +1 -0
  179. package/dist/rng/dummy-rng-client.d.ts +39 -0
  180. package/dist/rng/dummy-rng-client.d.ts.map +1 -0
  181. package/dist/rng/dummy-rng-client.js +77 -0
  182. package/dist/rng/dummy-rng-client.js.map +1 -0
  183. package/dist/rng/index.d.ts +10 -0
  184. package/dist/rng/index.d.ts.map +1 -0
  185. package/dist/rng/index.js +27 -0
  186. package/dist/rng/index.js.map +1 -0
  187. package/dist/rng/rng-client.factory.d.ts +33 -0
  188. package/dist/rng/rng-client.factory.d.ts.map +1 -0
  189. package/dist/rng/rng-client.factory.js +57 -0
  190. package/dist/rng/rng-client.factory.js.map +1 -0
  191. package/dist/rng/rng-client.interface.d.ts +51 -0
  192. package/dist/rng/rng-client.interface.d.ts.map +1 -0
  193. package/dist/rng/rng-client.interface.js +9 -0
  194. package/dist/rng/rng-client.interface.js.map +1 -0
  195. package/dist/rng/rng-service.d.ts +93 -0
  196. package/dist/rng/rng-service.d.ts.map +1 -0
  197. package/dist/rng/rng-service.js +124 -0
  198. package/dist/rng/rng-service.js.map +1 -0
  199. package/dist/rng/spin-generator.d.ts +32 -0
  200. package/dist/rng/spin-generator.d.ts.map +1 -0
  201. package/dist/rng/spin-generator.js +338 -0
  202. package/dist/rng/spin-generator.js.map +1 -0
  203. package/dist/rng/weighted-random.d.ts +30 -0
  204. package/dist/rng/weighted-random.d.ts.map +1 -0
  205. package/dist/rng/weighted-random.js +58 -0
  206. package/dist/rng/weighted-random.js.map +1 -0
  207. package/package.json +59 -0
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ /**
3
+ * Symbol Distribution Diagnostic
4
+ * Checks if our screen generation matches C++ probability expectations.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const spin_generator_1 = require("../rng/spin-generator");
8
+ const happy_panda_config_1 = require("../config/happy-panda.config");
9
+ const types_1 = require("../domain/types");
10
+ function createTestRng(seed = 12345) {
11
+ let state = seed;
12
+ function nextInt() {
13
+ state = (state * 1664525 + 1013904223) >>> 0;
14
+ return state;
15
+ }
16
+ return {
17
+ async random(max) {
18
+ return nextInt() % max;
19
+ },
20
+ async randomBatch(count, max) {
21
+ const results = [];
22
+ for (let i = 0; i < count; i++) {
23
+ results.push(nextInt() % max);
24
+ }
25
+ return results;
26
+ },
27
+ };
28
+ }
29
+ describe('Symbol Distribution Diagnostic', () => {
30
+ it('should check scatter rates across spin types', async () => {
31
+ const rng = createTestRng(99);
32
+ const spinsPerType = 5000;
33
+ const results = {};
34
+ for (const spinType of [happy_panda_config_1.SpinType.BASE_GAME_SPIN, happy_panda_config_1.SpinType.BONUS_BAMBOO_TRIPLETS, happy_panda_config_1.SpinType.BONUS_BAMBOO_TWINS, happy_panda_config_1.SpinType.BONUS_CAMERA, happy_panda_config_1.SpinType.BONUS_FIREWORKS]) {
35
+ const typeName = happy_panda_config_1.SpinType[spinType];
36
+ results[typeName] = { total: spinsPerType, scatter2plus: 0, wall: 0 };
37
+ for (let i = 0; i < spinsPerType; i++) {
38
+ const grid = await (0, spin_generator_1.generateGrid)(spinType, types_1.GameDirection.SINGLE, rng);
39
+ let sevenCount = 0;
40
+ let superSevenCount = 0;
41
+ let allSame = true;
42
+ const firstSymbol = grid[0][0];
43
+ for (let reel = 0; reel < 3; reel++) {
44
+ for (let row = 0; row < 3; row++) {
45
+ if (grid[reel][row] === happy_panda_config_1.Symbol.RED_PANDA)
46
+ sevenCount++;
47
+ if (grid[reel][row] === happy_panda_config_1.Symbol.GOLDEN_PANDA)
48
+ superSevenCount++;
49
+ if (grid[reel][row] !== firstSymbol)
50
+ allSame = false;
51
+ }
52
+ }
53
+ if (sevenCount >= 2 || superSevenCount >= 2)
54
+ results[typeName].scatter2plus++;
55
+ if (allSame)
56
+ results[typeName].wall++;
57
+ }
58
+ }
59
+ console.log('=== SCATTER & WALL RATES BY SPIN TYPE ===\n');
60
+ for (const [typeName, data] of Object.entries(results)) {
61
+ console.log(`${typeName}:`);
62
+ console.log(` Scatter (2+ Seven): ${(data.scatter2plus / data.total * 100).toFixed(2)}%`);
63
+ console.log(` Wall (9 same): ${(data.wall / data.total * 100).toFixed(2)}%`);
64
+ }
65
+ expect(true).toBe(true);
66
+ }, 120000);
67
+ it('should match expected limitation tier distribution', async () => {
68
+ const rng = createTestRng(42);
69
+ const spins = 10000;
70
+ const sevenCounts = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
71
+ const superSevenCounts = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
72
+ for (let i = 0; i < spins; i++) {
73
+ const grid = await (0, spin_generator_1.generateGrid)(happy_panda_config_1.SpinType.BASE_GAME_SPIN, types_1.GameDirection.SINGLE, rng);
74
+ let sevenCount = 0;
75
+ let superSevenCount = 0;
76
+ for (let reel = 0; reel < 3; reel++) {
77
+ for (let row = 0; row < 3; row++) {
78
+ if (grid[reel][row] === happy_panda_config_1.Symbol.RED_PANDA)
79
+ sevenCount++;
80
+ if (grid[reel][row] === happy_panda_config_1.Symbol.GOLDEN_PANDA)
81
+ superSevenCount++;
82
+ }
83
+ }
84
+ sevenCounts[sevenCount]++;
85
+ superSevenCounts[superSevenCount]++;
86
+ }
87
+ console.log('=== SYMBOL DISTRIBUTION ANALYSIS (10k spins) ===\n');
88
+ console.log('Super Seven count distribution:');
89
+ for (let i = 0; i <= 9; i++) {
90
+ if (superSevenCounts[i] > 0) {
91
+ const pct = (superSevenCounts[i] / spins * 100).toFixed(2);
92
+ console.log(` ${i} copies: ${superSevenCounts[i]} (${pct}%)`);
93
+ }
94
+ }
95
+ console.log('\nSeven count distribution:');
96
+ for (let i = 0; i <= 9; i++) {
97
+ if (sevenCounts[i] > 0) {
98
+ const pct = (sevenCounts[i] / spins * 100).toFixed(2);
99
+ console.log(` ${i} copies: ${sevenCounts[i]} (${pct}%)`);
100
+ }
101
+ }
102
+ console.log('\nExpected from C++ limitation weights:');
103
+ console.log(' SEV_S: [9,2,1,1] = 69% max2, 15% max4, 7.7% max7, 7.7% max9');
104
+ console.log(' SEV: [8,3,1,1] = 62% max2, 23% max4, 7.7% max7, 7.7% max9');
105
+ const superSeven2OrLess = superSevenCounts[0] + superSevenCounts[1] + superSevenCounts[2];
106
+ const seven2OrLess = sevenCounts[0] + sevenCounts[1] + sevenCounts[2];
107
+ console.log('\nActual 0-2 copies (should match max2 tier):');
108
+ console.log(` Super Seven: ${(superSeven2OrLess / spins * 100).toFixed(1)}%`);
109
+ console.log(` Seven: ${(seven2OrLess / spins * 100).toFixed(1)}%`);
110
+ const scatter2Plus = sevenCounts.slice(2).reduce((a, b) => a + b, 0);
111
+ const superScatter2Plus = superSevenCounts.slice(2).reduce((a, b) => a + b, 0);
112
+ console.log('\nScatter potential (2+ symbols):');
113
+ console.log(` Super Seven 2+: ${(superScatter2Plus / spins * 100).toFixed(1)}%`);
114
+ console.log(` Seven 2+: ${(scatter2Plus / spins * 100).toFixed(1)}%`);
115
+ console.log(` Either 2+: ${((scatter2Plus + superScatter2Plus - (sevenCounts.slice(2).reduce((a, b, i) => a + Math.min(b, superSevenCounts[i + 2] || 0), 0))) / spins * 100).toFixed(1)}%`);
116
+ expect(true).toBe(true);
117
+ }, 60000);
118
+ });
119
+ //# sourceMappingURL=symbol-distribution.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbol-distribution.test.js","sourceRoot":"","sources":["../../src/__tests__/symbol-distribution.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * 10,000-Spin Test Protocol
3
+ *
4
+ * Comprehensive test protocol for validating Happy Panda game engine
5
+ * over 10,000 spins. Covers:
6
+ * - Base game spin reliability with full state tracking
7
+ * - RTP validation with statistical bounds
8
+ * - State consistency verification
9
+ * - DOUBLE direction high-volume validation
10
+ *
11
+ * Results are written to NDJSON files in the results/ directory.
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=test-protocol-10000-spin.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-protocol-10000-spin.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/test-protocol-10000-spin.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
@@ -0,0 +1,359 @@
1
+ "use strict";
2
+ /**
3
+ * 10,000-Spin Test Protocol
4
+ *
5
+ * Comprehensive test protocol for validating Happy Panda game engine
6
+ * over 10,000 spins. Covers:
7
+ * - Base game spin reliability with full state tracking
8
+ * - RTP validation with statistical bounds
9
+ * - State consistency verification
10
+ * - DOUBLE direction high-volume validation
11
+ *
12
+ * Results are written to NDJSON files in the results/ directory.
13
+ */
14
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ var desc = Object.getOwnPropertyDescriptor(m, k);
17
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
18
+ desc = { enumerable: true, get: function() { return m[k]; } };
19
+ }
20
+ Object.defineProperty(o, k2, desc);
21
+ }) : (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ o[k2] = m[k];
24
+ }));
25
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
26
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
27
+ }) : function(o, v) {
28
+ o["default"] = v;
29
+ });
30
+ var __importStar = (this && this.__importStar) || (function () {
31
+ var ownKeys = function(o) {
32
+ ownKeys = Object.getOwnPropertyNames || function (o) {
33
+ var ar = [];
34
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
35
+ return ar;
36
+ };
37
+ return ownKeys(o);
38
+ };
39
+ return function (mod) {
40
+ if (mod && mod.__esModule) return mod;
41
+ var result = {};
42
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
43
+ __setModuleDefault(result, mod);
44
+ return result;
45
+ };
46
+ })();
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ const fs = __importStar(require("fs"));
49
+ const path = __importStar(require("path"));
50
+ const happy_panda_v1_game_engine_1 = require("../happy-panda-v1.game-engine");
51
+ const types_1 = require("../domain/types");
52
+ // Results output directory
53
+ const RESULTS_DIR = path.join(__dirname, '../../results');
54
+ // Bet calculation constants - must match spin-handler.ts
55
+ // betGame = baseBet * betStake, where baseBet = 8 for SINGLE, 16 for DOUBLE
56
+ const SINGLE_BASE_BET = 8;
57
+ const DOUBLE_BASE_BET = 16;
58
+ const TOTAL_SPINS = 10000;
59
+ const PROGRESS_INTERVAL = 1000;
60
+ function ensureResultsDir() {
61
+ if (!fs.existsSync(RESULTS_DIR)) {
62
+ fs.mkdirSync(RESULTS_DIR, { recursive: true });
63
+ }
64
+ }
65
+ function getResultsFileName(testName, spinCount) {
66
+ const date = new Date().toISOString().split('T')[0];
67
+ const time = new Date()
68
+ .toISOString()
69
+ .split('T')[1]
70
+ .split('.')[0]
71
+ .replace(/:/g, '-');
72
+ return path.join(RESULTS_DIR, `protocol-${testName}-${spinCount}-${date}-${time}.ndjson`);
73
+ }
74
+ function createTracker() {
75
+ return {
76
+ totalWagered: 0,
77
+ totalWon: 0,
78
+ spinCount: 0,
79
+ bonusTriggers: 0,
80
+ failures: 0,
81
+ };
82
+ }
83
+ async function initSession(engine, gameDirection, betStake) {
84
+ const result = await engine.processCommand(null, null, {
85
+ id: `init-protocol-${Math.random().toString(36).slice(2)}`,
86
+ type: 'INIT_SESSION_STATE',
87
+ payload: {
88
+ gameDirection,
89
+ betStake,
90
+ },
91
+ });
92
+ return {
93
+ publicState: result.publicState,
94
+ privateState: result.privateState,
95
+ };
96
+ }
97
+ async function executeSpin(engine, publicState, privateState) {
98
+ const result = await engine.processCommand(publicState, privateState, {
99
+ id: `spin-protocol-${Math.random().toString(36).slice(2)}`,
100
+ type: 'SPIN',
101
+ payload: { sessionId: 'protocol-test-session' },
102
+ });
103
+ return {
104
+ success: result.success,
105
+ publicState: result.publicState,
106
+ privateState: result.privateState,
107
+ outcome: result.outcome,
108
+ };
109
+ }
110
+ function extractWinAmounts(outcome) {
111
+ if (!outcome) {
112
+ return { totalPayout: 0, jackpotWon: 0, poolJackpotWon: 0, isRespin: false };
113
+ }
114
+ // outcome wraps the SpinResponse in a 'result' key for RGS compatibility
115
+ const spinResponse = (outcome.result ?? outcome);
116
+ const wins = spinResponse.wins;
117
+ const totalPayout = wins?.totalPayout ?? 0;
118
+ const jackpotWon = spinResponse.jackpotWon ?? 0;
119
+ const poolJackpotWon = spinResponse.poolJackpotWon ?? 0;
120
+ const triggeredBonus = spinResponse.triggeredBonus;
121
+ const isRespin = triggeredBonus !== undefined && triggeredBonus !== null;
122
+ return { totalPayout, jackpotWon, poolJackpotWon, isRespin };
123
+ }
124
+ // =============================================================================
125
+ // TEST PROTOCOL
126
+ // =============================================================================
127
+ describe('10,000-Spin Test Protocol', () => {
128
+ // ============================================================
129
+ // TEST 1: Base Game Spins with Full State Tracking
130
+ // ============================================================
131
+ describe('Test 1: 10,000 Base Game Spins with Full State Tracking', () => {
132
+ it('should complete 10,000 SINGLE spins with full tracking and NDJSON output', async () => {
133
+ ensureResultsDir();
134
+ const resultsFile = getResultsFileName('base-game-single', TOTAL_SPINS);
135
+ const writeStream = fs.createWriteStream(resultsFile);
136
+ const engine = new happy_panda_v1_game_engine_1.HappyPandaV1GameEngine();
137
+ const betStake = 1;
138
+ const betGame = SINGLE_BASE_BET * betStake; // = 8
139
+ const { publicState: initPublic, privateState: initPrivate } = await initSession(engine, types_1.GameDirection.SINGLE, betStake);
140
+ let currentPublic = initPublic;
141
+ let currentPrivate = initPrivate;
142
+ const tracker = createTracker();
143
+ console.log(`\n=== Test 1: 10,000 Base Game Spins (SINGLE) ===`);
144
+ console.log(`Writing results to: ${resultsFile}\n`);
145
+ for (let i = 0; i < TOTAL_SPINS; i++) {
146
+ const spin = await executeSpin(engine, currentPublic, currentPrivate);
147
+ tracker.spinCount++;
148
+ tracker.totalWagered += betGame;
149
+ if (!spin.success) {
150
+ tracker.failures++;
151
+ }
152
+ else {
153
+ const { totalPayout, jackpotWon, poolJackpotWon, isRespin } = extractWinAmounts(spin.outcome);
154
+ const won = totalPayout + jackpotWon + poolJackpotWon;
155
+ tracker.totalWon += won;
156
+ if (isRespin) {
157
+ tracker.bonusTriggers++;
158
+ }
159
+ const record = {
160
+ spin: tracker.spinCount,
161
+ wagered: betGame,
162
+ won,
163
+ baseWin: totalPayout,
164
+ jackpotWon,
165
+ poolJackpotWon,
166
+ bonusTriggered: isRespin,
167
+ success: spin.success,
168
+ };
169
+ writeStream.write(JSON.stringify(record) + '\n');
170
+ }
171
+ currentPublic = spin.publicState;
172
+ currentPrivate = spin.privateState;
173
+ if (tracker.spinCount % PROGRESS_INTERVAL === 0) {
174
+ const runningRtp = tracker.totalWagered > 0
175
+ ? ((tracker.totalWon / tracker.totalWagered) * 100).toFixed(2)
176
+ : '0.00';
177
+ console.log(`Progress: ${tracker.spinCount}/${TOTAL_SPINS} spins | ` +
178
+ `Wagered: ${tracker.totalWagered} | Won: ${tracker.totalWon.toFixed(2)} | ` +
179
+ `RTP: ${runningRtp}% | Failures: ${tracker.failures}`);
180
+ }
181
+ }
182
+ writeStream.end();
183
+ console.log(`\n--- Test 1 Summary ---`);
184
+ console.log(`Total spins: ${tracker.spinCount}`);
185
+ console.log(`Total wagered: ${tracker.totalWagered}`);
186
+ console.log(`Total won: ${tracker.totalWon.toFixed(2)}`);
187
+ console.log(`Bonus triggers (respins): ${tracker.bonusTriggers}`);
188
+ console.log(`Failures: ${tracker.failures}`);
189
+ console.log(`Results file: ${resultsFile}`);
190
+ expect(tracker.failures).toBe(0);
191
+ expect(tracker.spinCount).toBe(TOTAL_SPINS);
192
+ }, 600000);
193
+ });
194
+ // ============================================================
195
+ // TEST 2: RTP Validation Over 10,000 Spins
196
+ // ============================================================
197
+ describe('Test 2: RTP Validation Over 10,000 Spins', () => {
198
+ it('should produce RTP within 85% - 110% over 10,000 spins', async () => {
199
+ const engine = new happy_panda_v1_game_engine_1.HappyPandaV1GameEngine();
200
+ const betStake = 1;
201
+ const betGame = SINGLE_BASE_BET * betStake; // = 8
202
+ const { publicState: initPublic, privateState: initPrivate } = await initSession(engine, types_1.GameDirection.SINGLE, betStake);
203
+ let currentPublic = initPublic;
204
+ let currentPrivate = initPrivate;
205
+ let totalWagered = 0;
206
+ let totalWon = 0;
207
+ let spinCount = 0;
208
+ console.log(`\n=== Test 2: RTP Validation (SINGLE, betGame=${betGame}) ===\n`);
209
+ for (let i = 0; i < TOTAL_SPINS; i++) {
210
+ const spin = await executeSpin(engine, currentPublic, currentPrivate);
211
+ if (!spin.success) {
212
+ throw new Error(`Spin ${i + 1} failed unexpectedly`);
213
+ }
214
+ spinCount++;
215
+ totalWagered += betGame;
216
+ const { totalPayout, jackpotWon, poolJackpotWon } = extractWinAmounts(spin.outcome);
217
+ totalWon += totalPayout + jackpotWon + poolJackpotWon;
218
+ currentPublic = spin.publicState;
219
+ currentPrivate = spin.privateState;
220
+ if (spinCount % PROGRESS_INTERVAL === 0) {
221
+ const rtp = (totalWon / totalWagered) * 100;
222
+ console.log(`Progress: ${spinCount}/${TOTAL_SPINS} | RTP: ${rtp.toFixed(2)}%`);
223
+ }
224
+ }
225
+ const rtp = totalWagered > 0 ? (totalWon / totalWagered) * 100 : 0;
226
+ console.log(`\n--- Test 2 Summary ---`);
227
+ console.log(`Spins: ${spinCount}`);
228
+ console.log(`Total wagered: ${totalWagered}`);
229
+ console.log(`Total won: ${totalWon.toFixed(2)}`);
230
+ console.log(`Calculated RTP: ${rtp.toFixed(4)}%`);
231
+ console.log(`Expected RTP: ~96% (bounds: 85% - 110%)`);
232
+ // 6-sigma bounds for 10k spins: RTP should be within 85% - 110%
233
+ expect(rtp).toBeGreaterThanOrEqual(85);
234
+ expect(rtp).toBeLessThanOrEqual(110);
235
+ }, 600000);
236
+ });
237
+ // ============================================================
238
+ // TEST 3: State Consistency Over 10,000 Spins
239
+ // ============================================================
240
+ describe('Test 3: State Consistency Over 10,000 Spins', () => {
241
+ it('should maintain valid state on every spin across 10,000 iterations', async () => {
242
+ const engine = new happy_panda_v1_game_engine_1.HappyPandaV1GameEngine();
243
+ const betStake = 1;
244
+ const { publicState: initPublic, privateState: initPrivate } = await initSession(engine, types_1.GameDirection.SINGLE, betStake);
245
+ let currentPublic = initPublic;
246
+ let currentPrivate = initPrivate;
247
+ let spinCount = 0;
248
+ let stateValidationFailures = 0;
249
+ console.log(`\n=== Test 3: State Consistency Validation ===\n`);
250
+ for (let i = 0; i < TOTAL_SPINS; i++) {
251
+ const spin = await executeSpin(engine, currentPublic, currentPrivate);
252
+ spinCount++;
253
+ // Validate state on every spin
254
+ let valid = true;
255
+ if (!spin.success) {
256
+ valid = false;
257
+ console.error(`Spin ${spinCount}: success was false`);
258
+ }
259
+ if (spin.publicState === undefined || spin.publicState === null) {
260
+ valid = false;
261
+ console.error(`Spin ${spinCount}: publicState is ${spin.publicState}`);
262
+ }
263
+ if (spin.privateState === undefined || spin.privateState === null) {
264
+ valid = false;
265
+ console.error(`Spin ${spinCount}: privateState is ${spin.privateState}`);
266
+ }
267
+ if (spin.outcome === undefined || spin.outcome === null) {
268
+ valid = false;
269
+ console.error(`Spin ${spinCount}: outcome is ${spin.outcome}`);
270
+ }
271
+ if (!valid) {
272
+ stateValidationFailures++;
273
+ }
274
+ currentPublic = spin.publicState;
275
+ currentPrivate = spin.privateState;
276
+ if (spinCount % PROGRESS_INTERVAL === 0) {
277
+ console.log(`Progress: ${spinCount}/${TOTAL_SPINS} | ` +
278
+ `State failures: ${stateValidationFailures}`);
279
+ }
280
+ }
281
+ console.log(`\n--- Test 3 Summary ---`);
282
+ console.log(`Total spins: ${spinCount}`);
283
+ console.log(`State validation failures: ${stateValidationFailures}`);
284
+ expect(stateValidationFailures).toBe(0);
285
+ }, 600000);
286
+ });
287
+ // ============================================================
288
+ // TEST 4: DOUBLE Direction 10,000 Spins
289
+ // ============================================================
290
+ describe('Test 4: DOUBLE Direction 10,000 Spins', () => {
291
+ it('should complete 10,000 DOUBLE (BOTH) spins with full tracking and NDJSON output', async () => {
292
+ ensureResultsDir();
293
+ const resultsFile = getResultsFileName('base-game-double', TOTAL_SPINS);
294
+ const writeStream = fs.createWriteStream(resultsFile);
295
+ const engine = new happy_panda_v1_game_engine_1.HappyPandaV1GameEngine();
296
+ const betStake = 1;
297
+ const betGame = DOUBLE_BASE_BET * betStake; // = 16
298
+ const { publicState: initPublic, privateState: initPrivate } = await initSession(engine, types_1.GameDirection.BOTH, betStake);
299
+ let currentPublic = initPublic;
300
+ let currentPrivate = initPrivate;
301
+ const tracker = createTracker();
302
+ console.log(`\n=== Test 4: 10,000 DOUBLE Direction Spins ===`);
303
+ console.log(`betGame: ${betGame} (DOUBLE_BASE_BET=${DOUBLE_BASE_BET} * betStake=${betStake})`);
304
+ console.log(`Writing results to: ${resultsFile}\n`);
305
+ for (let i = 0; i < TOTAL_SPINS; i++) {
306
+ const spin = await executeSpin(engine, currentPublic, currentPrivate);
307
+ tracker.spinCount++;
308
+ tracker.totalWagered += betGame;
309
+ if (!spin.success) {
310
+ tracker.failures++;
311
+ }
312
+ else {
313
+ const { totalPayout, jackpotWon, poolJackpotWon, isRespin } = extractWinAmounts(spin.outcome);
314
+ const won = totalPayout + jackpotWon + poolJackpotWon;
315
+ tracker.totalWon += won;
316
+ if (isRespin) {
317
+ tracker.bonusTriggers++;
318
+ }
319
+ const record = {
320
+ spin: tracker.spinCount,
321
+ wagered: betGame,
322
+ won,
323
+ baseWin: totalPayout,
324
+ jackpotWon,
325
+ poolJackpotWon,
326
+ bonusTriggered: isRespin,
327
+ success: spin.success,
328
+ };
329
+ writeStream.write(JSON.stringify(record) + '\n');
330
+ }
331
+ currentPublic = spin.publicState;
332
+ currentPrivate = spin.privateState;
333
+ if (tracker.spinCount % PROGRESS_INTERVAL === 0) {
334
+ const runningRtp = tracker.totalWagered > 0
335
+ ? ((tracker.totalWon / tracker.totalWagered) * 100).toFixed(2)
336
+ : '0.00';
337
+ console.log(`Progress: ${tracker.spinCount}/${TOTAL_SPINS} spins | ` +
338
+ `Wagered: ${tracker.totalWagered} | Won: ${tracker.totalWon.toFixed(2)} | ` +
339
+ `RTP: ${runningRtp}% | Failures: ${tracker.failures}`);
340
+ }
341
+ }
342
+ writeStream.end();
343
+ const finalRtp = tracker.totalWagered > 0
344
+ ? ((tracker.totalWon / tracker.totalWagered) * 100).toFixed(4)
345
+ : '0.0000';
346
+ console.log(`\n--- Test 4 Summary ---`);
347
+ console.log(`Total spins: ${tracker.spinCount}`);
348
+ console.log(`Total wagered: ${tracker.totalWagered}`);
349
+ console.log(`Total won: ${tracker.totalWon.toFixed(2)}`);
350
+ console.log(`RTP: ${finalRtp}%`);
351
+ console.log(`Bonus triggers (respins): ${tracker.bonusTriggers}`);
352
+ console.log(`Failures: ${tracker.failures}`);
353
+ console.log(`Results file: ${resultsFile}`);
354
+ expect(tracker.failures).toBe(0);
355
+ expect(tracker.spinCount).toBe(TOTAL_SPINS);
356
+ }, 600000);
357
+ });
358
+ });
359
+ //# sourceMappingURL=test-protocol-10000-spin.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-protocol-10000-spin.test.js","sourceRoot":"","sources":["../../src/__tests__/test-protocol-10000-spin.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Weighted Random Tests
3
+ *
4
+ * Tests for weighted random selection utilities.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=weighted-random.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weighted-random.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/weighted-random.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}