@duyquangnvx/spindle 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,721 @@
1
+ import { t as createSymbolId } from "../types-B1TeoRrL.mjs";
2
+
3
+ //#region src/testing/index.ts
4
+ /**
5
+ * Creates a test grid filled with a given symbol (or cycling through provided symbols).
6
+ * Useful for quickly constructing grids in test scenarios.
7
+ */
8
+ function createTestGrid(reels, rows, fill) {
9
+ const defaultSymbol = createSymbolId("T");
10
+ const symbols = fill ? Array.isArray(fill) ? fill : [fill] : [defaultSymbol];
11
+ const grid = [];
12
+ let idx = 0;
13
+ for (let r = 0; r < reels; r++) {
14
+ const column = [];
15
+ for (let row = 0; row < rows; row++) {
16
+ column.push(symbols[idx % symbols.length]);
17
+ idx++;
18
+ }
19
+ grid.push(column);
20
+ }
21
+ return grid;
22
+ }
23
+ /**
24
+ * Convenience re-export of createSymbolId for test files.
25
+ */
26
+ const createTestSymbolId = createSymbolId;
27
+ function coreFragment(calls) {
28
+ return {
29
+ async onSpinStart() {
30
+ calls.push({
31
+ method: "onSpinStart",
32
+ data: {}
33
+ });
34
+ },
35
+ async presentReelStop({ reelIndex, symbols, mode, metadata }) {
36
+ calls.push({
37
+ method: "presentReelStop",
38
+ data: {
39
+ reelIndex,
40
+ symbols,
41
+ mode,
42
+ metadata
43
+ }
44
+ });
45
+ },
46
+ async onSpinEnd({ spinWin, featureWin, totalWin }) {
47
+ calls.push({
48
+ method: "onSpinEnd",
49
+ data: {
50
+ spinWin,
51
+ featureWin,
52
+ totalWin
53
+ }
54
+ });
55
+ }
56
+ };
57
+ }
58
+ function fixedDataFragment(calls, spinResult) {
59
+ return { async requestSpinResult(context) {
60
+ calls.push({
61
+ method: "requestSpinResult",
62
+ data: { context }
63
+ });
64
+ return spinResult;
65
+ } };
66
+ }
67
+ function routingDataFragment(calls, base, modeResults) {
68
+ let freeSpinIndex = 0;
69
+ let holdAndSpinIndex = 0;
70
+ return { async requestSpinResult(context) {
71
+ calls.push({
72
+ method: "requestSpinResult",
73
+ data: { context }
74
+ });
75
+ if (context.mode === "freeSpin" && modeResults.freeSpin) return modeResults.freeSpin[freeSpinIndex++];
76
+ if (context.mode === "holdAndSpin" && modeResults.holdAndSpin) return modeResults.holdAndSpin[holdAndSpinIndex++];
77
+ return base;
78
+ } };
79
+ }
80
+ function waysWinFragment(calls) {
81
+ return { async presentWaysWin(data) {
82
+ const { mode, metadata, ...win } = data;
83
+ calls.push({
84
+ method: "presentWaysWin",
85
+ data: {
86
+ win,
87
+ mode,
88
+ metadata
89
+ }
90
+ });
91
+ } };
92
+ }
93
+ function paylineWinFragment(calls) {
94
+ return { async presentPaylineWin(data) {
95
+ const { mode, metadata, ...win } = data;
96
+ calls.push({
97
+ method: "presentPaylineWin",
98
+ data: {
99
+ win,
100
+ mode,
101
+ metadata
102
+ }
103
+ });
104
+ } };
105
+ }
106
+ function clusterWinFragment(calls) {
107
+ return { async presentClusterWin(data) {
108
+ const { mode, metadata, ...win } = data;
109
+ calls.push({
110
+ method: "presentClusterWin",
111
+ data: {
112
+ win,
113
+ mode,
114
+ metadata
115
+ }
116
+ });
117
+ } };
118
+ }
119
+ function scatterWinFragment(calls) {
120
+ return { async presentScatterWin(data) {
121
+ const { mode, metadata, ...win } = data;
122
+ calls.push({
123
+ method: "presentScatterWin",
124
+ data: {
125
+ win,
126
+ mode,
127
+ metadata
128
+ }
129
+ });
130
+ } };
131
+ }
132
+ function bigWinFragment(calls) {
133
+ return { async presentBigWin({ tier, amount, mode, metadata }) {
134
+ calls.push({
135
+ method: "presentBigWin",
136
+ data: {
137
+ tier,
138
+ amount,
139
+ mode,
140
+ metadata
141
+ }
142
+ });
143
+ } };
144
+ }
145
+ function anticipationFragment(calls) {
146
+ return { async presentAnticipation({ reelIndex, mode, metadata }) {
147
+ calls.push({
148
+ method: "presentAnticipation",
149
+ data: {
150
+ reelIndex,
151
+ mode,
152
+ metadata
153
+ }
154
+ });
155
+ } };
156
+ }
157
+ function symbolTransformFragment(calls) {
158
+ return { async presentSymbolTransform({ transforms, mode, metadata }) {
159
+ calls.push({
160
+ method: "presentSymbolTransform",
161
+ data: {
162
+ transforms,
163
+ mode,
164
+ metadata
165
+ }
166
+ });
167
+ } };
168
+ }
169
+ function cascadeFragment(calls) {
170
+ return {
171
+ async presentCascadeDestroy({ step, positions, mode, metadata }) {
172
+ calls.push({
173
+ method: "presentCascadeDestroy",
174
+ data: {
175
+ step,
176
+ positions,
177
+ mode,
178
+ metadata
179
+ }
180
+ });
181
+ },
182
+ async presentCascadeDrop({ step, mode, metadata }) {
183
+ calls.push({
184
+ method: "presentCascadeDrop",
185
+ data: {
186
+ step,
187
+ mode,
188
+ metadata
189
+ }
190
+ });
191
+ },
192
+ async presentCascadeFill({ step, grid, multiplier, mode, metadata }) {
193
+ calls.push({
194
+ method: "presentCascadeFill",
195
+ data: {
196
+ step,
197
+ grid,
198
+ multiplier,
199
+ mode,
200
+ metadata
201
+ }
202
+ });
203
+ }
204
+ };
205
+ }
206
+ function jackpotFragment(calls) {
207
+ return {
208
+ async presentJackpotTrigger({ tier, amount, mode, metadata }) {
209
+ calls.push({
210
+ method: "presentJackpotTrigger",
211
+ data: {
212
+ tier,
213
+ amount,
214
+ mode,
215
+ metadata
216
+ }
217
+ });
218
+ },
219
+ async onJackpotAwarded({ tier, amount, mode, metadata }) {
220
+ calls.push({
221
+ method: "onJackpotAwarded",
222
+ data: {
223
+ tier,
224
+ amount,
225
+ mode,
226
+ metadata
227
+ }
228
+ });
229
+ }
230
+ };
231
+ }
232
+ function freeSpinsFragment(calls) {
233
+ return {
234
+ async onFreeSpinsEnter({ totalSpins }) {
235
+ calls.push({
236
+ method: "onFreeSpinsEnter",
237
+ data: { totalSpins }
238
+ });
239
+ },
240
+ async onFreeSpinStart({ currentSpin, totalSpins, remaining, accumulated }) {
241
+ calls.push({
242
+ method: "onFreeSpinStart",
243
+ data: {
244
+ currentSpin,
245
+ totalSpins,
246
+ remaining,
247
+ accumulated
248
+ }
249
+ });
250
+ },
251
+ async onFreeSpinsRetrigger({ added, totalSpins }) {
252
+ calls.push({
253
+ method: "onFreeSpinsRetrigger",
254
+ data: {
255
+ added,
256
+ totalSpins
257
+ }
258
+ });
259
+ },
260
+ async onFreeSpinsExit({ totalSpins, totalWin }) {
261
+ calls.push({
262
+ method: "onFreeSpinsExit",
263
+ data: {
264
+ totalSpins,
265
+ totalWin
266
+ }
267
+ });
268
+ }
269
+ };
270
+ }
271
+ function holdAndSpinFragment(calls) {
272
+ return {
273
+ async onHoldAndSpinEnter({ totalRounds, lockedSymbols }) {
274
+ calls.push({
275
+ method: "onHoldAndSpinEnter",
276
+ data: {
277
+ totalRounds,
278
+ lockedSymbols
279
+ }
280
+ });
281
+ },
282
+ async onHoldAndSpinRound({ round, remaining, grid, newLocked, allLocked }) {
283
+ calls.push({
284
+ method: "onHoldAndSpinRound",
285
+ data: {
286
+ round,
287
+ remaining,
288
+ grid,
289
+ newLocked,
290
+ allLocked
291
+ }
292
+ });
293
+ },
294
+ async onHoldAndSpinExit({ totalRounds, totalWin, fullGrid }) {
295
+ calls.push({
296
+ method: "onHoldAndSpinExit",
297
+ data: {
298
+ totalRounds,
299
+ totalWin,
300
+ fullGrid
301
+ }
302
+ });
303
+ }
304
+ };
305
+ }
306
+ function pickBonusFragment(calls) {
307
+ return {
308
+ async onPickBonusEnter(data) {
309
+ calls.push({
310
+ method: "onPickBonusEnter",
311
+ data
312
+ });
313
+ },
314
+ async requestPickChoice(data) {
315
+ calls.push({
316
+ method: "requestPickChoice",
317
+ data
318
+ });
319
+ return { choiceIndex: 0 };
320
+ },
321
+ async requestPickReveal(data) {
322
+ calls.push({
323
+ method: "requestPickReveal",
324
+ data
325
+ });
326
+ return {
327
+ choiceIndex: 0,
328
+ prize: 0,
329
+ done: true
330
+ };
331
+ },
332
+ async presentPickReveal(data) {
333
+ calls.push({
334
+ method: "presentPickReveal",
335
+ data
336
+ });
337
+ },
338
+ async onPickBonusExit(data) {
339
+ calls.push({
340
+ method: "onPickBonusExit",
341
+ data
342
+ });
343
+ }
344
+ };
345
+ }
346
+ function wheelBonusFragment(calls) {
347
+ return {
348
+ async onWheelBonusEnter(data) {
349
+ calls.push({
350
+ method: "onWheelBonusEnter",
351
+ data
352
+ });
353
+ },
354
+ async requestWheelSpinResult(data) {
355
+ calls.push({
356
+ method: "requestWheelSpinResult",
357
+ data
358
+ });
359
+ return {
360
+ segmentIndex: 0,
361
+ prize: 0
362
+ };
363
+ },
364
+ async presentWheelResult(data) {
365
+ calls.push({
366
+ method: "presentWheelResult",
367
+ data
368
+ });
369
+ },
370
+ async onWheelBonusExit(data) {
371
+ calls.push({
372
+ method: "onWheelBonusExit",
373
+ data
374
+ });
375
+ }
376
+ };
377
+ }
378
+ function gambleFragment(calls, choices, results) {
379
+ let choiceIndex = 0;
380
+ let resultIndex = 0;
381
+ return {
382
+ async onGambleStart({ currentWin }) {
383
+ calls.push({
384
+ method: "onGambleStart",
385
+ data: { currentWin }
386
+ });
387
+ },
388
+ async requestGambleChoice({ currentWin }) {
389
+ const choice = choices[choiceIndex++];
390
+ calls.push({
391
+ method: "requestGambleChoice",
392
+ data: { currentWin }
393
+ });
394
+ return choice;
395
+ },
396
+ async requestGambleResult({ currentWin }) {
397
+ const result = results[resultIndex++];
398
+ calls.push({
399
+ method: "requestGambleResult",
400
+ data: { currentWin }
401
+ });
402
+ return result;
403
+ },
404
+ async presentGambleResult({ won, amount }) {
405
+ calls.push({
406
+ method: "presentGambleResult",
407
+ data: {
408
+ won,
409
+ amount
410
+ }
411
+ });
412
+ },
413
+ async onGambleEnd({ finalWin }) {
414
+ calls.push({
415
+ method: "onGambleEnd",
416
+ data: { finalWin }
417
+ });
418
+ }
419
+ };
420
+ }
421
+ function expandingWildFragment(calls) {
422
+ return { async presentExpandingWild({ position, expandedPositions, mode, metadata }) {
423
+ calls.push({
424
+ method: "presentExpandingWild",
425
+ data: {
426
+ position,
427
+ expandedPositions,
428
+ mode,
429
+ metadata
430
+ }
431
+ });
432
+ } };
433
+ }
434
+ function stickyWildFragment(calls) {
435
+ return { async presentStickyWild({ position, mode, metadata }) {
436
+ calls.push({
437
+ method: "presentStickyWild",
438
+ data: {
439
+ position,
440
+ mode,
441
+ metadata
442
+ }
443
+ });
444
+ } };
445
+ }
446
+ function walkingWildFragment(calls) {
447
+ return { async presentWalkingWild({ from, to, mode, metadata }) {
448
+ calls.push({
449
+ method: "presentWalkingWild",
450
+ data: {
451
+ from,
452
+ to,
453
+ mode,
454
+ metadata
455
+ }
456
+ });
457
+ } };
458
+ }
459
+ function stackedWildFragment(calls) {
460
+ return { async presentStackedWild({ positions, mode, metadata }) {
461
+ calls.push({
462
+ method: "presentStackedWild",
463
+ data: {
464
+ positions,
465
+ mode,
466
+ metadata
467
+ }
468
+ });
469
+ } };
470
+ }
471
+ function multiplierWildFragment(calls) {
472
+ return { async presentMultiplierWild({ position, multiplier, mode, metadata }) {
473
+ calls.push({
474
+ method: "presentMultiplierWild",
475
+ data: {
476
+ position,
477
+ multiplier,
478
+ mode,
479
+ metadata
480
+ }
481
+ });
482
+ } };
483
+ }
484
+ function randomWildFragment(calls) {
485
+ return { async presentRandomWild({ positions, mode, metadata }) {
486
+ calls.push({
487
+ method: "presentRandomWild",
488
+ data: {
489
+ positions,
490
+ mode,
491
+ metadata
492
+ }
493
+ });
494
+ } };
495
+ }
496
+ function buyFeatureFragment(calls, buyTrigger) {
497
+ return {
498
+ async requestBuyFeatureResult(data) {
499
+ calls.push({
500
+ method: "requestBuyFeatureResult",
501
+ data
502
+ });
503
+ return buyTrigger;
504
+ },
505
+ async onBuyFeatureStart(data) {
506
+ calls.push({
507
+ method: "onBuyFeatureStart",
508
+ data
509
+ });
510
+ },
511
+ async onBuyFeatureEnd(data) {
512
+ calls.push({
513
+ method: "onBuyFeatureEnd",
514
+ data
515
+ });
516
+ }
517
+ };
518
+ }
519
+ var RecordingDelegateBuilder = class {
520
+ calls;
521
+ delegate;
522
+ constructor(calls, delegate) {
523
+ this.calls = calls;
524
+ this.delegate = delegate;
525
+ }
526
+ withWaysWin() {
527
+ Object.assign(this.delegate, waysWinFragment(this.calls));
528
+ return this;
529
+ }
530
+ withPaylineWin() {
531
+ Object.assign(this.delegate, paylineWinFragment(this.calls));
532
+ return this;
533
+ }
534
+ withClusterWin() {
535
+ Object.assign(this.delegate, clusterWinFragment(this.calls));
536
+ return this;
537
+ }
538
+ withCascade() {
539
+ Object.assign(this.delegate, cascadeFragment(this.calls));
540
+ return this;
541
+ }
542
+ withScatter() {
543
+ Object.assign(this.delegate, scatterWinFragment(this.calls));
544
+ return this;
545
+ }
546
+ withBigWin() {
547
+ Object.assign(this.delegate, bigWinFragment(this.calls));
548
+ return this;
549
+ }
550
+ withAnticipation() {
551
+ Object.assign(this.delegate, anticipationFragment(this.calls));
552
+ return this;
553
+ }
554
+ withSymbolTransform() {
555
+ Object.assign(this.delegate, symbolTransformFragment(this.calls));
556
+ return this;
557
+ }
558
+ withJackpot() {
559
+ Object.assign(this.delegate, jackpotFragment(this.calls));
560
+ return this;
561
+ }
562
+ withFreeSpins() {
563
+ Object.assign(this.delegate, freeSpinsFragment(this.calls));
564
+ return this;
565
+ }
566
+ withHoldAndSpin() {
567
+ Object.assign(this.delegate, holdAndSpinFragment(this.calls));
568
+ return this;
569
+ }
570
+ withPickBonus() {
571
+ Object.assign(this.delegate, pickBonusFragment(this.calls));
572
+ return this;
573
+ }
574
+ withWheelBonus() {
575
+ Object.assign(this.delegate, wheelBonusFragment(this.calls));
576
+ return this;
577
+ }
578
+ withWheelBonusResults(wheelResults) {
579
+ let idx = 0;
580
+ const calls = this.calls;
581
+ Object.assign(this.delegate, {
582
+ ...wheelBonusFragment(calls),
583
+ async requestWheelSpinResult(data) {
584
+ calls.push({
585
+ method: "requestWheelSpinResult",
586
+ data
587
+ });
588
+ return wheelResults[idx++];
589
+ }
590
+ });
591
+ return this;
592
+ }
593
+ withGamble(choices, results) {
594
+ Object.assign(this.delegate, gambleFragment(this.calls, choices, results));
595
+ return this;
596
+ }
597
+ withExpandingWild() {
598
+ Object.assign(this.delegate, expandingWildFragment(this.calls));
599
+ return this;
600
+ }
601
+ withStickyWild() {
602
+ Object.assign(this.delegate, stickyWildFragment(this.calls));
603
+ return this;
604
+ }
605
+ withWalkingWild() {
606
+ Object.assign(this.delegate, walkingWildFragment(this.calls));
607
+ return this;
608
+ }
609
+ withStackedWild() {
610
+ Object.assign(this.delegate, stackedWildFragment(this.calls));
611
+ return this;
612
+ }
613
+ withMultiplierWild() {
614
+ Object.assign(this.delegate, multiplierWildFragment(this.calls));
615
+ return this;
616
+ }
617
+ withRandomWild() {
618
+ Object.assign(this.delegate, randomWildFragment(this.calls));
619
+ return this;
620
+ }
621
+ withAllWilds() {
622
+ Object.assign(this.delegate, expandingWildFragment(this.calls), stickyWildFragment(this.calls), walkingWildFragment(this.calls), stackedWildFragment(this.calls), multiplierWildFragment(this.calls), randomWildFragment(this.calls));
623
+ return this;
624
+ }
625
+ withBuyFeature(buyTrigger) {
626
+ Object.assign(this.delegate, buyFeatureFragment(this.calls, buyTrigger));
627
+ return this;
628
+ }
629
+ withPickBonusChoices(choices, reveals) {
630
+ let choiceIdx = 0;
631
+ let revealIdx = 0;
632
+ const calls = this.calls;
633
+ Object.assign(this.delegate, {
634
+ async onPickBonusEnter(data) {
635
+ calls.push({
636
+ method: "onPickBonusEnter",
637
+ data
638
+ });
639
+ },
640
+ async requestPickChoice(data) {
641
+ calls.push({
642
+ method: "requestPickChoice",
643
+ data
644
+ });
645
+ return choices[choiceIdx++];
646
+ },
647
+ async requestPickReveal(data) {
648
+ calls.push({
649
+ method: "requestPickReveal",
650
+ data
651
+ });
652
+ return reveals[revealIdx++];
653
+ },
654
+ async presentPickReveal(data) {
655
+ calls.push({
656
+ method: "presentPickReveal",
657
+ data
658
+ });
659
+ },
660
+ async onPickBonusExit(data) {
661
+ calls.push({
662
+ method: "onPickBonusExit",
663
+ data
664
+ });
665
+ }
666
+ });
667
+ return this;
668
+ }
669
+ build() {
670
+ return {
671
+ delegate: this.delegate,
672
+ calls: this.calls
673
+ };
674
+ }
675
+ };
676
+ /** Minimal recording delegate — CoreDelegate & DataDelegate only. Use .with*() to add capabilities. */
677
+ function recording(spinResult) {
678
+ const calls = [];
679
+ return new RecordingDelegateBuilder(calls, {
680
+ ...coreFragment(calls),
681
+ ...fixedDataFragment(calls, spinResult)
682
+ });
683
+ }
684
+ /** Recording delegate with ways win type — covers 80% of test scenarios. */
685
+ function recordingWays(spinResult) {
686
+ return recording(spinResult).withWaysWin();
687
+ }
688
+ /** Recording delegate with payline win type. */
689
+ function recordingPayline(spinResult) {
690
+ const calls = [];
691
+ return new RecordingDelegateBuilder(calls, {
692
+ ...coreFragment(calls),
693
+ ...fixedDataFragment(calls, spinResult),
694
+ ...paylineWinFragment(calls)
695
+ });
696
+ }
697
+ /** Recording delegate with cluster win type. */
698
+ function recordingCluster(spinResult) {
699
+ const calls = [];
700
+ return new RecordingDelegateBuilder(calls, {
701
+ ...coreFragment(calls),
702
+ ...fixedDataFragment(calls, spinResult),
703
+ ...clusterWinFragment(calls)
704
+ });
705
+ }
706
+ /** Recording delegate with mode-based routing for feature spins. */
707
+ function recordingWithRouting(base, modeResults) {
708
+ const calls = [];
709
+ return new RecordingDelegateBuilder(calls, {
710
+ ...coreFragment(calls),
711
+ ...routingDataFragment(calls, base, modeResults)
712
+ });
713
+ }
714
+ /** Recording delegate with mode-based routing + ways win. */
715
+ function recordingWaysWithRouting(base, modeResults) {
716
+ return recordingWithRouting(base, modeResults).withWaysWin();
717
+ }
718
+
719
+ //#endregion
720
+ export { createTestGrid, createTestSymbolId, recording, recordingCluster, recordingPayline, recordingWays, recordingWaysWithRouting, recordingWithRouting };
721
+ //# sourceMappingURL=index.mjs.map