@slot-engine/core 0.2.10 → 0.2.12

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/dist/index.mjs CHANGED
@@ -45,7 +45,8 @@ function createPermanentFilePaths(basePath) {
45
45
  simulationSummary: path.join(basePath, "simulation_summary.json"),
46
46
  statsPayouts: path.join(basePath, "stats_payouts.json"),
47
47
  statsSummary: path.join(basePath, "stats_summary.json"),
48
- statsRecords: path.join(basePath, "stats_records.json")
48
+ statsRecords: path.join(basePath, "stats_records.json"),
49
+ frontendConfig: path.join(basePath, "frontend_config.json")
49
50
  };
50
51
  }
51
52
  function createTemporaryFilePaths(basePath, tempFolder) {
@@ -1419,19 +1420,6 @@ var Book = class {
1419
1420
  data: copy(event.data)
1420
1421
  });
1421
1422
  }
1422
- /**
1423
- * Intended for internal use only.
1424
- */
1425
- _serialize() {
1426
- return {
1427
- id: this.id,
1428
- criteria: this.criteria,
1429
- events: this.events,
1430
- payout: this.payout,
1431
- basegameWins: this.basegameWins,
1432
- freespinsWins: this.freespinsWins
1433
- };
1434
- }
1435
1423
  };
1436
1424
 
1437
1425
  // src/wallet/index.ts
@@ -1600,7 +1588,7 @@ var Wallet = class {
1600
1588
  this.currentWin = process2(this.currentWin);
1601
1589
  this.cumulativeWins += this.currentWin;
1602
1590
  let spinTypeWins = 0;
1603
- for (const spinType of Object.keys(this.currentWinPerSpinType)) {
1591
+ for (const spinType in this.currentWinPerSpinType) {
1604
1592
  const st = spinType;
1605
1593
  const spinTypeWin = process2(this.currentWinPerSpinType[st]);
1606
1594
  this.cumulativeWinsPerSpinType[st] += spinTypeWin;
@@ -2405,9 +2393,9 @@ var Simulation = class {
2405
2393
  }
2406
2394
  const chunkIndex = this.bookChunkIndexes.get(index);
2407
2395
  const bookChunkPath = this.PATHS.booksChunk(mode, index, chunkIndex);
2408
- const data = this.bookBuffers.get(index).join("\n") + "\n";
2396
+ const bookLines = this.bookBuffers.get(index);
2409
2397
  await pipeline(
2410
- Readable.from([Buffer.from(data, "utf8")]),
2398
+ Readable.from(bookLines),
2411
2399
  zlib.createZstdCompress(),
2412
2400
  fs3.createWriteStream(bookChunkPath)
2413
2401
  );
@@ -2488,50 +2476,51 @@ var Simulation = class {
2488
2476
  }
2489
2477
  }
2490
2478
  writeChain = writeChain.then(async () => {
2491
- const book = msg.book;
2492
- const bookData = {
2493
- id: book.id,
2494
- payoutMultiplier: book.payout,
2495
- events: book.events
2496
- };
2497
- if (!this.summary[mode]?.criteria[book.criteria]) {
2498
- this.summary[mode].criteria[book.criteria] = {
2479
+ const bookId = msg.bookId;
2480
+ const bookCriteria = msg.bookCriteria;
2481
+ const bookPayout = msg.bookPayout;
2482
+ const bookBasegameWins = msg.bookBasegameWins;
2483
+ const bookFreespinsWins = msg.bookFreespinsWins;
2484
+ const bookLine = msg.bookLine;
2485
+ const bookLineWithNewline = bookLine + "\n";
2486
+ if (!this.summary[mode]?.criteria[bookCriteria]) {
2487
+ this.summary[mode].criteria[bookCriteria] = {
2499
2488
  numSims: 0,
2500
2489
  bsWins: 0,
2501
2490
  fsWins: 0,
2502
2491
  rtp: 0
2503
2492
  };
2504
2493
  }
2505
- const bsWins = round(book.basegameWins, 4);
2506
- const fsWins = round(book.freespinsWins, 4);
2507
- this.summary[mode].criteria[book.criteria].numSims += 1;
2494
+ const bsWins = round(bookBasegameWins, 4);
2495
+ const fsWins = round(bookFreespinsWins, 4);
2496
+ const criteria = this.summary[mode].criteria[bookCriteria];
2497
+ criteria.numSims += 1;
2508
2498
  this.summary[mode].total.bsWins += bsWins;
2509
2499
  this.summary[mode].total.fsWins += fsWins;
2510
- this.summary[mode].criteria[book.criteria].bsWins += bsWins;
2511
- this.summary[mode].criteria[book.criteria].fsWins += fsWins;
2512
- const bookLine = JSON.stringify(bookData);
2513
- const lineSize = Buffer.byteLength(bookLine + "\n", "utf8");
2500
+ criteria.bsWins += bsWins;
2501
+ criteria.fsWins += fsWins;
2502
+ const lineSize = Buffer.byteLength(bookLineWithNewline, "utf8");
2514
2503
  if (this.bookBuffers.has(index)) {
2515
- this.bookBuffers.get(index).push(bookLine);
2504
+ this.bookBuffers.get(index).push(bookLineWithNewline);
2516
2505
  this.bookBufferSizes.set(
2517
2506
  index,
2518
2507
  this.bookBufferSizes.get(index) + lineSize
2519
2508
  );
2520
2509
  } else {
2521
- this.bookBuffers.set(index, [bookLine]);
2510
+ this.bookBuffers.set(index, [bookLineWithNewline]);
2522
2511
  this.bookBufferSizes.set(index, lineSize);
2523
2512
  }
2524
2513
  if (!this.tempBookIndexPaths.includes(booksIndexPath)) {
2525
2514
  this.tempBookIndexPaths.push(booksIndexPath);
2526
2515
  }
2527
2516
  booksIndexBatch.push(
2528
- `${book.id},${index},${this.bookChunkIndexes.get(index) || 0}
2517
+ `${bookId},${index},${this.bookChunkIndexes.get(index) || 0}
2529
2518
  `
2530
2519
  );
2531
- lookupBatch.push(`${book.id},1,${Math.round(book.payout)}
2520
+ lookupBatch.push(`${bookId},1,${Math.round(bookPayout)}
2532
2521
  `);
2533
2522
  lookupSegBatch.push(
2534
- `${book.id},${book.criteria},${book.basegameWins},${book.freespinsWins}
2523
+ `${bookId},${bookCriteria},${bookBasegameWins},${bookFreespinsWins}
2535
2524
  `
2536
2525
  );
2537
2526
  if (booksIndexBatch.length >= WRITE_BATCH_SIZE) {
@@ -2540,15 +2529,10 @@ var Simulation = class {
2540
2529
  if (this.bookBufferSizes.get(index) >= 10 * 1024 * 1024) {
2541
2530
  await flushBookChunk();
2542
2531
  }
2543
- if (this.recordsWriteStream) {
2544
- for (const record of msg.records) {
2545
- const recordPrefix = this.hasWrittenRecord ? "\n" : "";
2546
- await write(
2547
- this.recordsWriteStream,
2548
- recordPrefix + JSON.stringify(record)
2549
- );
2550
- this.hasWrittenRecord = true;
2551
- }
2532
+ if (this.recordsWriteStream && typeof msg.recordsLines === "string" && msg.recordsLines.length) {
2533
+ const recordPrefix = this.hasWrittenRecord ? "\n" : "";
2534
+ await write(this.recordsWriteStream, recordPrefix + msg.recordsLines);
2535
+ this.hasWrittenRecord = true;
2552
2536
  }
2553
2537
  this.wallet.mergeSerialized(msg.wallet);
2554
2538
  worker.postMessage({ type: "credit", amount: 1 });
@@ -2639,9 +2623,11 @@ var Simulation = class {
2639
2623
  });
2640
2624
  }
2641
2625
  }
2642
- ctx.services.wallet._getWallet().writePayoutToBook(ctx);
2643
- ctx.services.wallet._getWallet().confirmWins(ctx);
2644
- if (ctx.services.data._getBook().payout >= ctx.config.maxWinX) {
2626
+ const wallet = ctx.services.wallet._getWallet();
2627
+ wallet.writePayoutToBook(ctx);
2628
+ wallet.confirmWins(ctx);
2629
+ const book = ctx.services.data._getBook();
2630
+ if (book.payout >= ctx.config.maxWinX) {
2645
2631
  ctx.state.triggeredMaxWin = true;
2646
2632
  }
2647
2633
  ctx.services.data.record({
@@ -2649,12 +2635,24 @@ var Simulation = class {
2649
2635
  });
2650
2636
  ctx.config.hooks.onSimulationAccepted?.(ctx);
2651
2637
  this.confirmRecords(ctx);
2638
+ const bookLine = JSON.stringify({
2639
+ id: book.id,
2640
+ payoutMultiplier: book.payout,
2641
+ events: book.events
2642
+ });
2643
+ const records = ctx.services.data._getRecords();
2644
+ const recordsLines = records.length > 0 ? records.map((r) => JSON.stringify(r)).join("\n") : "";
2652
2645
  parentPort2?.postMessage({
2653
2646
  type: "complete",
2654
2647
  simId,
2655
- book: ctx.services.data._getBook()._serialize(),
2656
- wallet: ctx.services.wallet._getWallet().serialize(),
2657
- records: ctx.services.data._getRecords()
2648
+ bookLine,
2649
+ bookId: book.id,
2650
+ bookCriteria: book.criteria,
2651
+ bookPayout: book.payout,
2652
+ bookBasegameWins: book.basegameWins,
2653
+ bookFreespinsWins: book.freespinsWins,
2654
+ wallet: wallet.serialize(),
2655
+ recordsLines
2658
2656
  });
2659
2657
  }
2660
2658
  initCreditListener() {
@@ -3700,6 +3698,43 @@ async function rustProgram(...args) {
3700
3698
 
3701
3699
  // src/slot-game/index.ts
3702
3700
  import { isMainThread as isMainThread5, workerData as workerData2 } from "worker_threads";
3701
+
3702
+ // src/utils/frontend-config.ts
3703
+ function createFrontendConfig(config, meta) {
3704
+ const path9 = meta.paths.frontendConfig;
3705
+ const gameModes = Object.values(config.gameModes).map((gm) => ({
3706
+ name: gm.name,
3707
+ cost: gm.cost,
3708
+ rtp: gm.rtp
3709
+ }));
3710
+ const reelSets = /* @__PURE__ */ new Map();
3711
+ Object.values(config.gameModes).forEach((gm) => {
3712
+ gm.reelSets.forEach((reelSet) => {
3713
+ reelSet.associatedGameModeName = gm.name;
3714
+ reelSet.generateReels(config);
3715
+ if (!reelSets.has(reelSet.id)) {
3716
+ reelSets.set(
3717
+ reelSet.id,
3718
+ reelSet.reels.map((reel) => reel.map((s) => s.id))
3719
+ );
3720
+ }
3721
+ });
3722
+ });
3723
+ const frontendConfig = {
3724
+ name: config.name,
3725
+ maxWin: config.maxWinX,
3726
+ padSymbols: config.padSymbols,
3727
+ symbols: Array.from(config.symbols.values()).map((s) => ({
3728
+ id: s.id,
3729
+ pays: s.pays
3730
+ })),
3731
+ gameModes,
3732
+ reelSets: Object.fromEntries(reelSets)
3733
+ };
3734
+ writeJsonFile(path9, frontendConfig);
3735
+ }
3736
+
3737
+ // src/slot-game/index.ts
3703
3738
  var SlotGame = class _SlotGame {
3704
3739
  configOpts;
3705
3740
  simulation;
@@ -3787,7 +3822,10 @@ var SlotGame = class _SlotGame {
3787
3822
  this.runAnalysis(opts.analysisOpts || { gameModes: [] });
3788
3823
  }
3789
3824
  }
3790
- if (isMainThread5) console.log("Done!");
3825
+ if (isMainThread5) {
3826
+ createFrontendConfig(this.getConfig(), this.getMetadata());
3827
+ console.log("Done!");
3828
+ }
3791
3829
  }
3792
3830
  /**
3793
3831
  * Gets the game configuration.