@slot-engine/core 0.0.2 → 0.0.3
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.d.mts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +61 -85
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +61 -85
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/lib/zstd.exe +0 -0
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/GameConfig.ts
|
|
2
|
+
import assert from "assert";
|
|
2
3
|
var GameConfig = class _GameConfig {
|
|
3
4
|
config;
|
|
4
5
|
constructor(opts) {
|
|
@@ -22,14 +23,12 @@ var GameConfig = class _GameConfig {
|
|
|
22
23
|
userState: opts.userState,
|
|
23
24
|
outputDir: "__build__"
|
|
24
25
|
};
|
|
25
|
-
for (const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
);
|
|
32
|
-
}
|
|
26
|
+
for (const [key, value] of Object.entries(opts.symbols)) {
|
|
27
|
+
assert(
|
|
28
|
+
value.id === key,
|
|
29
|
+
`Symbol key "${key}" does not match symbol id "${value.id}"`
|
|
30
|
+
);
|
|
31
|
+
this.config.symbols.set(key, value);
|
|
33
32
|
}
|
|
34
33
|
function getAnticipationTrigger(spinType) {
|
|
35
34
|
return Math.min(...Object.keys(opts.scatterToFreespins[spinType]).map(Number)) - 1;
|
|
@@ -1773,7 +1772,7 @@ var ManywaysWinType = class extends WinType {
|
|
|
1773
1772
|
};
|
|
1774
1773
|
|
|
1775
1774
|
// src/optimizer/OptimizationConditions.ts
|
|
1776
|
-
import
|
|
1775
|
+
import assert2 from "assert";
|
|
1777
1776
|
var OptimizationConditions = class {
|
|
1778
1777
|
rtp;
|
|
1779
1778
|
avgWin;
|
|
@@ -1784,14 +1783,14 @@ var OptimizationConditions = class {
|
|
|
1784
1783
|
constructor(opts) {
|
|
1785
1784
|
let { rtp, avgWin, hitRate, searchConditions, priority } = opts;
|
|
1786
1785
|
if (rtp == void 0 || rtp === "x") {
|
|
1787
|
-
|
|
1786
|
+
assert2(avgWin !== void 0 && hitRate !== void 0, "If RTP is not specified, hit-rate (hr) and average win amount (av_win) must be given.");
|
|
1788
1787
|
rtp = Math.round(avgWin / Number(hitRate) * 1e5) / 1e5;
|
|
1789
1788
|
}
|
|
1790
1789
|
let noneCount = 0;
|
|
1791
1790
|
for (const val of [rtp, avgWin, hitRate]) {
|
|
1792
1791
|
if (val === void 0) noneCount++;
|
|
1793
1792
|
}
|
|
1794
|
-
|
|
1793
|
+
assert2(noneCount <= 1, "Invalid combination of optimization conditions.");
|
|
1795
1794
|
this.searchRange = [-1, -1];
|
|
1796
1795
|
this.forceSearch = {};
|
|
1797
1796
|
if (typeof searchConditions === "number") {
|
|
@@ -1871,41 +1870,11 @@ var OptimizationParameters = class _OptimizationParameters {
|
|
|
1871
1870
|
|
|
1872
1871
|
// src/Simulation.ts
|
|
1873
1872
|
import fs3 from "fs";
|
|
1874
|
-
import
|
|
1875
|
-
import
|
|
1873
|
+
import path2 from "path";
|
|
1874
|
+
import assert3 from "assert";
|
|
1875
|
+
import zlib from "zlib";
|
|
1876
1876
|
import { buildSync } from "esbuild";
|
|
1877
1877
|
import { Worker, isMainThread as isMainThread2, parentPort, workerData } from "worker_threads";
|
|
1878
|
-
|
|
1879
|
-
// src/utils/zstd.ts
|
|
1880
|
-
import path2 from "path";
|
|
1881
|
-
import { spawn } from "child_process";
|
|
1882
|
-
async function zstd(...args) {
|
|
1883
|
-
return new Promise((resolve, reject) => {
|
|
1884
|
-
const task = spawn(path2.join(__dirname, "./lib/zstd.exe"), args);
|
|
1885
|
-
task.on("error", (error) => {
|
|
1886
|
-
console.error("Error:", error);
|
|
1887
|
-
reject(error);
|
|
1888
|
-
});
|
|
1889
|
-
task.on("exit", () => {
|
|
1890
|
-
resolve(true);
|
|
1891
|
-
});
|
|
1892
|
-
task.on("close", () => {
|
|
1893
|
-
resolve(true);
|
|
1894
|
-
});
|
|
1895
|
-
task.stdout.on("data", (data) => {
|
|
1896
|
-
console.log(data.toString());
|
|
1897
|
-
});
|
|
1898
|
-
task.stderr.on("data", (data) => {
|
|
1899
|
-
console.log(data.toString());
|
|
1900
|
-
});
|
|
1901
|
-
task.stdout.on("error", (data) => {
|
|
1902
|
-
console.log(data.toString());
|
|
1903
|
-
reject(data.toString());
|
|
1904
|
-
});
|
|
1905
|
-
});
|
|
1906
|
-
}
|
|
1907
|
-
|
|
1908
|
-
// src/Simulation.ts
|
|
1909
1878
|
var completedSimulations = 0;
|
|
1910
1879
|
var TEMP_FILENAME = "__temp_compiled_src_IGNORE.js";
|
|
1911
1880
|
var Simulation = class _Simulation {
|
|
@@ -1926,7 +1895,7 @@ var Simulation = class _Simulation {
|
|
|
1926
1895
|
this.library = /* @__PURE__ */ new Map();
|
|
1927
1896
|
this.records = [];
|
|
1928
1897
|
const gameModeKeys = Object.keys(this.gameConfig.config.gameModes);
|
|
1929
|
-
|
|
1898
|
+
assert3(
|
|
1930
1899
|
Object.values(this.gameConfig.config.gameModes).map((m) => gameModeKeys.includes(m.name)).every((v) => v === true),
|
|
1931
1900
|
"Game mode name must match its key in the gameModes object."
|
|
1932
1901
|
);
|
|
@@ -1963,14 +1932,14 @@ Simulating game mode: ${mode}`);
|
|
|
1963
1932
|
const simNumsToCriteria = ResultSet.assignCriteriaToSimulations(this, mode);
|
|
1964
1933
|
await this.spawnWorkersForGameMode({ mode, simNumsToCriteria });
|
|
1965
1934
|
createDirIfNotExists(
|
|
1966
|
-
|
|
1935
|
+
path2.join(
|
|
1967
1936
|
process.cwd(),
|
|
1968
1937
|
this.gameConfig.config.outputDir,
|
|
1969
1938
|
"optimization_files"
|
|
1970
1939
|
)
|
|
1971
1940
|
);
|
|
1972
1941
|
createDirIfNotExists(
|
|
1973
|
-
|
|
1942
|
+
path2.join(process.cwd(), this.gameConfig.config.outputDir, "publish_files")
|
|
1974
1943
|
);
|
|
1975
1944
|
_Simulation.writeLookupTableCSV({
|
|
1976
1945
|
gameMode: mode,
|
|
@@ -2066,7 +2035,7 @@ Simulating game mode: ${mode}`);
|
|
|
2066
2035
|
}
|
|
2067
2036
|
}
|
|
2068
2037
|
return new Promise((resolve, reject) => {
|
|
2069
|
-
const scriptPath =
|
|
2038
|
+
const scriptPath = path2.join(process.cwd(), basePath, TEMP_FILENAME);
|
|
2070
2039
|
const worker = new Worker(scriptPath, {
|
|
2071
2040
|
workerData: {
|
|
2072
2041
|
mode,
|
|
@@ -2114,10 +2083,10 @@ Simulating game mode: ${mode}`);
|
|
|
2114
2083
|
}
|
|
2115
2084
|
rows.sort((a, b) => Number(a.split(",")[0]) - Number(b.split(",")[0]));
|
|
2116
2085
|
let outputFileName = `lookUpTable_${gameMode}.csv`;
|
|
2117
|
-
let outputFilePath =
|
|
2086
|
+
let outputFilePath = path2.join(gameConfig.outputDir, outputFileName);
|
|
2118
2087
|
writeFile(outputFilePath, rows.join("\n"));
|
|
2119
2088
|
outputFileName = `lookUpTable_${gameMode}_0.csv`;
|
|
2120
|
-
outputFilePath =
|
|
2089
|
+
outputFilePath = path2.join(gameConfig.outputDir, outputFileName);
|
|
2121
2090
|
writeFile(outputFilePath, rows.join("\n"));
|
|
2122
2091
|
return outputFilePath;
|
|
2123
2092
|
}
|
|
@@ -2134,21 +2103,21 @@ Simulating game mode: ${mode}`);
|
|
|
2134
2103
|
}
|
|
2135
2104
|
rows.sort((a, b) => Number(a.split(",")[0]) - Number(b.split(",")[0]));
|
|
2136
2105
|
const outputFileName = `lookUpTableSegmented_${gameMode}.csv`;
|
|
2137
|
-
const outputFilePath =
|
|
2106
|
+
const outputFilePath = path2.join(gameConfig.outputDir, outputFileName);
|
|
2138
2107
|
writeFile(outputFilePath, rows.join("\n"));
|
|
2139
2108
|
return outputFilePath;
|
|
2140
2109
|
}
|
|
2141
2110
|
static writeRecords(opts) {
|
|
2142
2111
|
const { gameMode, fileNameWithoutExtension, records, gameConfig, debug } = opts;
|
|
2143
2112
|
const outputFileName = fileNameWithoutExtension ? `${fileNameWithoutExtension}.json` : `force_record_${gameMode}.json`;
|
|
2144
|
-
const outputFilePath =
|
|
2113
|
+
const outputFilePath = path2.join(gameConfig.outputDir, outputFileName);
|
|
2145
2114
|
writeFile(outputFilePath, JSON.stringify(records, null, 2));
|
|
2146
2115
|
if (debug) _Simulation.logSymbolOccurrences(records);
|
|
2147
2116
|
return outputFilePath;
|
|
2148
2117
|
}
|
|
2149
2118
|
static writeIndexJson(opts) {
|
|
2150
2119
|
const { gameConfig } = opts;
|
|
2151
|
-
const outputFilePath =
|
|
2120
|
+
const outputFilePath = path2.join(
|
|
2152
2121
|
process.cwd(),
|
|
2153
2122
|
gameConfig.outputDir,
|
|
2154
2123
|
"publish_files",
|
|
@@ -2165,7 +2134,7 @@ Simulating game mode: ${mode}`);
|
|
|
2165
2134
|
static async writeBooksJson(opts) {
|
|
2166
2135
|
const { gameMode, fileNameWithoutExtension, library, gameConfig } = opts;
|
|
2167
2136
|
const outputFileName = fileNameWithoutExtension ? `${fileNameWithoutExtension}.jsonl` : `books_${gameMode}.jsonl`;
|
|
2168
|
-
const outputFilePath =
|
|
2137
|
+
const outputFilePath = path2.join(gameConfig.outputDir, outputFileName);
|
|
2169
2138
|
const books = Array.from(library.values()).map((b) => b.serialize()).map((b) => ({
|
|
2170
2139
|
id: b.id,
|
|
2171
2140
|
payoutMultiplier: b.payout,
|
|
@@ -2174,14 +2143,15 @@ Simulating game mode: ${mode}`);
|
|
|
2174
2143
|
const contents = JSONL.stringify(books);
|
|
2175
2144
|
writeFile(outputFilePath, contents);
|
|
2176
2145
|
const compressedFileName = fileNameWithoutExtension ? `${fileNameWithoutExtension}.jsonl.zst` : `books_${gameMode}.jsonl.zst`;
|
|
2177
|
-
const compressedFilePath =
|
|
2146
|
+
const compressedFilePath = path2.join(
|
|
2178
2147
|
process.cwd(),
|
|
2179
2148
|
gameConfig.outputDir,
|
|
2180
2149
|
"publish_files",
|
|
2181
2150
|
compressedFileName
|
|
2182
2151
|
);
|
|
2183
2152
|
fs3.rmSync(compressedFilePath, { force: true });
|
|
2184
|
-
|
|
2153
|
+
const compressed = zlib.zstdCompressSync(Buffer.from(contents));
|
|
2154
|
+
fs3.writeFileSync(compressedFilePath, compressed);
|
|
2185
2155
|
}
|
|
2186
2156
|
static logSymbolOccurrences(records) {
|
|
2187
2157
|
const validRecords = records.filter(
|
|
@@ -2212,14 +2182,14 @@ Simulating game mode: ${mode}`);
|
|
|
2212
2182
|
* Compiles user configured game to JS for use in different Node processes
|
|
2213
2183
|
*/
|
|
2214
2184
|
preprocessFiles() {
|
|
2215
|
-
const builtFilePath =
|
|
2185
|
+
const builtFilePath = path2.join(this.gameConfig.config.outputDir, TEMP_FILENAME);
|
|
2216
2186
|
fs3.rmSync(builtFilePath, { force: true });
|
|
2217
2187
|
buildSync({
|
|
2218
2188
|
entryPoints: [process.cwd()],
|
|
2219
2189
|
bundle: true,
|
|
2220
2190
|
platform: "node",
|
|
2221
|
-
outfile:
|
|
2222
|
-
external: ["esbuild"
|
|
2191
|
+
outfile: path2.join(this.gameConfig.config.outputDir, TEMP_FILENAME),
|
|
2192
|
+
external: ["esbuild"]
|
|
2223
2193
|
});
|
|
2224
2194
|
}
|
|
2225
2195
|
getSimRangesForChunks(total, chunks) {
|
|
@@ -2327,8 +2297,8 @@ var SimulationContext = class extends Board {
|
|
|
2327
2297
|
|
|
2328
2298
|
// src/analysis/index.ts
|
|
2329
2299
|
import fs4 from "fs";
|
|
2330
|
-
import
|
|
2331
|
-
import
|
|
2300
|
+
import path3 from "path";
|
|
2301
|
+
import assert4 from "assert";
|
|
2332
2302
|
|
|
2333
2303
|
// src/analysis/utils.ts
|
|
2334
2304
|
function parseLookupTable(content) {
|
|
@@ -2372,8 +2342,11 @@ function getPayoutWeights(lut, opts = {}) {
|
|
|
2372
2342
|
}
|
|
2373
2343
|
function getNonZeroHitrate(payoutWeights) {
|
|
2374
2344
|
const totalWeight = getTotalWeight(payoutWeights);
|
|
2375
|
-
|
|
2376
|
-
|
|
2345
|
+
if (Math.min(...Object.keys(payoutWeights).map(Number)) == 0) {
|
|
2346
|
+
return totalWeight / (totalWeight - (payoutWeights[0] ?? 0) / totalWeight);
|
|
2347
|
+
} else {
|
|
2348
|
+
return 1;
|
|
2349
|
+
}
|
|
2377
2350
|
}
|
|
2378
2351
|
function getNullHitrate(payoutWeights) {
|
|
2379
2352
|
return payoutWeights[0] ?? 0;
|
|
@@ -2434,6 +2407,7 @@ function getLessBetHitrate(payoutWeights, cost) {
|
|
|
2434
2407
|
}
|
|
2435
2408
|
|
|
2436
2409
|
// src/analysis/index.ts
|
|
2410
|
+
import { isMainThread as isMainThread3 } from "worker_threads";
|
|
2437
2411
|
var Analysis = class {
|
|
2438
2412
|
gameConfig;
|
|
2439
2413
|
optimizerConfig;
|
|
@@ -2444,6 +2418,7 @@ var Analysis = class {
|
|
|
2444
2418
|
this.filePaths = {};
|
|
2445
2419
|
}
|
|
2446
2420
|
async runAnalysis(gameModes) {
|
|
2421
|
+
if (!isMainThread3) return;
|
|
2447
2422
|
this.filePaths = this.getPathsForModes(gameModes);
|
|
2448
2423
|
this.getNumberStats(gameModes);
|
|
2449
2424
|
this.getWinRanges(gameModes);
|
|
@@ -2453,28 +2428,28 @@ var Analysis = class {
|
|
|
2453
2428
|
const rootPath = process.cwd();
|
|
2454
2429
|
const paths = {};
|
|
2455
2430
|
for (const modeStr of gameModes) {
|
|
2456
|
-
const lut =
|
|
2431
|
+
const lut = path3.join(
|
|
2457
2432
|
rootPath,
|
|
2458
2433
|
this.gameConfig.outputDir,
|
|
2459
2434
|
`lookUpTable_${modeStr}.csv`
|
|
2460
2435
|
);
|
|
2461
|
-
const lutSegmented =
|
|
2436
|
+
const lutSegmented = path3.join(
|
|
2462
2437
|
rootPath,
|
|
2463
2438
|
this.gameConfig.outputDir,
|
|
2464
2439
|
`lookUpTableSegmented_${modeStr}.csv`
|
|
2465
2440
|
);
|
|
2466
|
-
const lutOptimized =
|
|
2441
|
+
const lutOptimized = path3.join(
|
|
2467
2442
|
rootPath,
|
|
2468
2443
|
this.gameConfig.outputDir,
|
|
2469
2444
|
"publish_files",
|
|
2470
2445
|
`lookUpTable_${modeStr}_0.csv`
|
|
2471
2446
|
);
|
|
2472
|
-
const booksJsonl =
|
|
2447
|
+
const booksJsonl = path3.join(
|
|
2473
2448
|
rootPath,
|
|
2474
2449
|
this.gameConfig.outputDir,
|
|
2475
2450
|
`books_${modeStr}.jsonl`
|
|
2476
2451
|
);
|
|
2477
|
-
const booksJsonlCompressed =
|
|
2452
|
+
const booksJsonlCompressed = path3.join(
|
|
2478
2453
|
rootPath,
|
|
2479
2454
|
this.gameConfig.outputDir,
|
|
2480
2455
|
"publish_files",
|
|
@@ -2488,7 +2463,7 @@ var Analysis = class {
|
|
|
2488
2463
|
booksJsonlCompressed
|
|
2489
2464
|
};
|
|
2490
2465
|
for (const p of Object.values(paths[modeStr])) {
|
|
2491
|
-
|
|
2466
|
+
assert4(
|
|
2492
2467
|
fs4.existsSync(p),
|
|
2493
2468
|
`File "${p}" does not exist. Run optimization to auto-create it.`
|
|
2494
2469
|
);
|
|
@@ -2522,7 +2497,7 @@ var Analysis = class {
|
|
|
2522
2497
|
});
|
|
2523
2498
|
}
|
|
2524
2499
|
writeJsonFile(
|
|
2525
|
-
|
|
2500
|
+
path3.join(process.cwd(), this.gameConfig.outputDir, "stats_summary.json"),
|
|
2526
2501
|
stats
|
|
2527
2502
|
);
|
|
2528
2503
|
}
|
|
@@ -2560,13 +2535,13 @@ var Analysis = class {
|
|
|
2560
2535
|
}
|
|
2561
2536
|
getGameModeConfig(mode) {
|
|
2562
2537
|
const config = this.gameConfig.gameModes[mode];
|
|
2563
|
-
|
|
2538
|
+
assert4(config, `Game mode "${mode}" not found in game config`);
|
|
2564
2539
|
return config;
|
|
2565
2540
|
}
|
|
2566
2541
|
};
|
|
2567
2542
|
|
|
2568
2543
|
// src/utils/math-config.ts
|
|
2569
|
-
import
|
|
2544
|
+
import path4 from "path";
|
|
2570
2545
|
function makeMathConfig(optimizer, opts = {}) {
|
|
2571
2546
|
const game = optimizer.getGameConfig();
|
|
2572
2547
|
const gameModesCfg = optimizer.getOptimizerGameModes();
|
|
@@ -2610,14 +2585,14 @@ function makeMathConfig(optimizer, opts = {}) {
|
|
|
2610
2585
|
}))
|
|
2611
2586
|
};
|
|
2612
2587
|
if (writeToFile) {
|
|
2613
|
-
const outPath =
|
|
2588
|
+
const outPath = path4.join(process.cwd(), game.outputDir, "math_config.json");
|
|
2614
2589
|
writeJsonFile(outPath, config);
|
|
2615
2590
|
}
|
|
2616
2591
|
return config;
|
|
2617
2592
|
}
|
|
2618
2593
|
|
|
2619
2594
|
// src/utils/setup-file.ts
|
|
2620
|
-
import
|
|
2595
|
+
import path5 from "path";
|
|
2621
2596
|
function makeSetupFile(optimizer, gameMode) {
|
|
2622
2597
|
const gameConfig = optimizer.getGameConfig();
|
|
2623
2598
|
const optimizerGameModes = optimizer.getOptimizerGameModes();
|
|
@@ -2653,19 +2628,19 @@ function makeSetupFile(optimizer, gameMode) {
|
|
|
2653
2628
|
`;
|
|
2654
2629
|
content += `simulation_trials;${params.simulationTrials}
|
|
2655
2630
|
`;
|
|
2656
|
-
content += `user_game_build_path;${
|
|
2631
|
+
content += `user_game_build_path;${path5.join(process.cwd(), gameConfig.outputDir)}
|
|
2657
2632
|
`;
|
|
2658
2633
|
content += `pmb_rtp;${params.pmbRtp}
|
|
2659
2634
|
`;
|
|
2660
|
-
const outPath =
|
|
2635
|
+
const outPath = path5.join(__dirname, "./optimizer-rust/src", "setup.txt");
|
|
2661
2636
|
writeFile(outPath, content);
|
|
2662
2637
|
}
|
|
2663
2638
|
|
|
2664
2639
|
// src/optimizer/index.ts
|
|
2665
|
-
import { spawn
|
|
2666
|
-
import
|
|
2667
|
-
import
|
|
2668
|
-
import { isMainThread as
|
|
2640
|
+
import { spawn } from "child_process";
|
|
2641
|
+
import path6 from "path";
|
|
2642
|
+
import assert5 from "assert";
|
|
2643
|
+
import { isMainThread as isMainThread4 } from "worker_threads";
|
|
2669
2644
|
var Optimizer = class {
|
|
2670
2645
|
gameConfig;
|
|
2671
2646
|
gameModes;
|
|
@@ -2678,12 +2653,13 @@ var Optimizer = class {
|
|
|
2678
2653
|
* Runs the optimization process, and runs analysis after.
|
|
2679
2654
|
*/
|
|
2680
2655
|
async runOptimization({ gameModes }) {
|
|
2681
|
-
if (!
|
|
2656
|
+
if (!isMainThread4) return;
|
|
2682
2657
|
const mathConfig = makeMathConfig(this, { writeToFile: true });
|
|
2683
2658
|
for (const mode of gameModes) {
|
|
2684
2659
|
const setupFile = makeSetupFile(this, mode);
|
|
2685
2660
|
await this.runSingleOptimization();
|
|
2686
2661
|
}
|
|
2662
|
+
console.log("Optimization complete. Files written to build directory.");
|
|
2687
2663
|
}
|
|
2688
2664
|
async runSingleOptimization() {
|
|
2689
2665
|
return await rustProgram();
|
|
@@ -2707,7 +2683,7 @@ var Optimizer = class {
|
|
|
2707
2683
|
}
|
|
2708
2684
|
}
|
|
2709
2685
|
const criteria = configMode.resultSets.map((r) => r.criteria);
|
|
2710
|
-
|
|
2686
|
+
assert5(
|
|
2711
2687
|
conditions.every((c) => criteria.includes(c)),
|
|
2712
2688
|
`Not all ResultSet criteria in game mode "${k}" are defined as optimization conditions.`
|
|
2713
2689
|
);
|
|
@@ -2719,7 +2695,7 @@ var Optimizer = class {
|
|
|
2719
2695
|
}
|
|
2720
2696
|
gameModeRtp = Math.round(gameModeRtp * 1e3) / 1e3;
|
|
2721
2697
|
paramRtp = Math.round(paramRtp * 1e3) / 1e3;
|
|
2722
|
-
|
|
2698
|
+
assert5(
|
|
2723
2699
|
gameModeRtp === paramRtp,
|
|
2724
2700
|
`Sum of all RTP conditions (${paramRtp}) does not match the game mode RTP (${gameModeRtp}) in game mode "${k}".`
|
|
2725
2701
|
);
|
|
@@ -2734,9 +2710,9 @@ var Optimizer = class {
|
|
|
2734
2710
|
};
|
|
2735
2711
|
async function rustProgram(...args) {
|
|
2736
2712
|
return new Promise((resolve, reject) => {
|
|
2737
|
-
const task =
|
|
2713
|
+
const task = spawn("cargo", ["run", "--release", ...args], {
|
|
2738
2714
|
shell: true,
|
|
2739
|
-
cwd:
|
|
2715
|
+
cwd: path6.join(__dirname, "./optimizer-rust"),
|
|
2740
2716
|
stdio: "pipe"
|
|
2741
2717
|
});
|
|
2742
2718
|
task.on("error", (error) => {
|