@vscubing/cubing
Version:
A collection of JavaScript cubing libraries.
364 lines (357 loc) • 11.7 kB
JavaScript
import {
exposeAPI
} from "./chunk-7GUL3OBQ.js";
import {
getBuiltinModule,
node_adapter_default
} from "./chunk-GOT3GVLG.js";
import {
Alg
} from "./chunk-2PLBXHXN.js";
// src/cubing/search/inside/solve/puzzles/clock.ts
import { randomUIntBelow } from "random-uint-below";
var backMoves = ["U", "R", "D", "L", "ALL"];
var frontMoves = ["UR", "DR", "DL", "UL"].concat(backMoves);
function randomClockScrambleString() {
let filteringMoveCount = 0;
function randomSuffix() {
const amount = randomUIntBelow(12);
if (amount !== 0) {
filteringMoveCount++;
}
if (amount <= 6) {
return `${amount}+`;
} else {
return `${12 - amount}-`;
}
}
const moves = [];
function side(families) {
for (const family of families) {
moves.push(`${family}${randomSuffix()}`);
}
}
side(frontMoves);
moves.push("y2");
side(backMoves);
if (filteringMoveCount < 2) {
return randomClockScrambleString();
}
return moves.join(" ");
}
// src/cubing/vendor/apache/comlink-everywhere/outside/index.ts
import { wrap } from "comlink";
var useNodeWorkarounds = typeof globalThis.Worker === "undefined" && typeof globalThis.WorkerNavigator === "undefined";
async function nodeWorker(source, options) {
const { Worker: NodeWorker } = await getBuiltinModule("node:worker_threads");
const worker = new NodeWorker(source, options);
worker.unref();
return node_adapter_default(worker);
}
async function constructWorker(source, options) {
let worker;
if (useNodeWorkarounds) {
return nodeWorker(source);
} else {
worker = new globalThis.Worker(source, {
type: options ? options.type : void 0
// TODO: Is it safe to use `options?.type`?
});
}
return worker;
}
// src/cubing/search/worker-workarounds/index.ts
async function searchWorkerURLImportMetaResolve() {
return import.meta.resolve("./search-worker-entry.js");
}
function searchWorkerURLNewURLImportMetaURL() {
return new URL("./search-worker-entry.js", import.meta.url);
}
async function searchWorkerURLEsbuildWorkaround() {
exposeAPI.expose = false;
return (await import("./search-worker-entry.js")).WORKER_ENTRY_FILE_URL;
}
function instantiateSearchWorkerURLNewURLImportMetaURL() {
return new Worker(new URL("./search-worker-entry.js", import.meta.url), {
type: "module"
});
}
// src/cubing/search/instantiator.ts
function probablyCrossOrigin(workerEntryFileURL) {
try {
const scriptOrigin = globalThis.location?.origin;
const workerOrigin = workerEntryFileURL.origin;
return !!scriptOrigin && !!workerOrigin && scriptOrigin !== workerOrigin;
} catch {
return false;
}
}
async function instantiateModuleWorker(workerEntryFileURL) {
const url = new URL(workerEntryFileURL, import.meta.url);
const tryTrampolineFirst = probablyCrossOrigin(url);
try {
return instantiateModuleWorkerAttempt(url, tryTrampolineFirst);
} catch {
return instantiateModuleWorkerAttempt(url, !tryTrampolineFirst);
}
}
async function instantiateModuleWorkerAttempt(workerEntryFileURL, crossOriginTrampoline) {
return new Promise(async (resolve, reject) => {
try {
if (!workerEntryFileURL) {
reject(new Error("Could not get worker entry file URL."));
}
let url = workerEntryFileURL;
if (crossOriginTrampoline) {
const importSrc = `import ${JSON.stringify(
workerEntryFileURL.toString()
)};`;
const blob = new Blob([importSrc], {
type: "text/javascript"
});
url = new URL(URL.createObjectURL(blob));
}
const worker = await constructWorker(url, {
type: "module"
});
worker.unref?.();
const onError = (e) => {
reject(e);
};
const onFirstMessage = (messageData) => {
if (messageData === "comlink-exposed") {
resolve(wrapWithTerminate(worker));
} else {
reject(
new Error(`wrong module instantiation message ${messageData}`)
);
}
};
if (worker.nodeWorker) {
worker.nodeWorker.once("message", onFirstMessage);
} else {
worker.addEventListener("error", onError, {
once: true
});
worker.addEventListener("message", (e) => onFirstMessage(e.data), {
once: true
});
}
} catch (e) {
reject(e);
}
});
}
async function instantiateModuleWorkerDirectlyForBrowser() {
return new Promise(async (resolve, reject) => {
try {
const worker = instantiateSearchWorkerURLNewURLImportMetaURL();
const onError = (e) => {
reject(e);
};
const onFirstMessage = (messageData) => {
if (messageData === "comlink-exposed") {
resolve(wrapWithTerminate(worker));
} else {
reject(
new Error(`wrong module instantiation message ${messageData}`)
);
}
};
worker.addEventListener("error", onError, {
once: true
});
worker.addEventListener("message", (e) => onFirstMessage(e.data), {
once: true
});
} catch (e) {
reject(e);
}
});
}
function wrapWithTerminate(worker) {
const insideAPI = wrap(worker);
const terminate = worker.terminate.bind(worker);
return { insideAPI, outsideAPI: { terminate } };
}
var allInsideOutsideAPIPromises = [];
async function instantiateWorker() {
const insideOutsideAPIPromise = instantiateWorkerImplementation();
allInsideOutsideAPIPromises.push(insideOutsideAPIPromise);
const { insideAPI } = await insideOutsideAPIPromise;
insideAPI.setDebugMeasurePerf(searchOutsideDebugGlobals.logPerf);
insideAPI.setScramblePrefetchLevel(
searchOutsideDebugGlobals.scramblePrefetchLevel
);
return insideOutsideAPIPromise;
}
async function mapToAllWorkers(f) {
await Promise.all(
allInsideOutsideAPIPromises.map((worker) => worker.then(f))
);
}
async function instantiateWorkerImplementation() {
if (globalThis.location?.protocol === "file:") {
console.warn(
"This current web page is loaded from the local filesystem (a URL that starts with `file://`). In this situation, `cubing.js` may be unable to generate scrambles or perform searches in some browsers. See: https://js.cubing.net/cubing/scramble/#file-server-required"
);
}
function failed(methodDescription) {
return `Module worker instantiation${methodDescription ? ` ${methodDescription}` : ""} failed`;
}
const fallbackOrder = [
[
async () => instantiateModuleWorker(await searchWorkerURLImportMetaResolve()),
"using `import.meta.resolve(\u2026)",
null
],
// TODO: This fallback should be lower (because it's less portable), but we need to try it earlier to work around https://github.com/parcel-bundler/parcel/issues/9051
[
instantiateModuleWorkerDirectlyForBrowser,
"using inline `new URL(\u2026, import.meta.url)`",
"may"
],
[
async () => instantiateModuleWorker(searchWorkerURLNewURLImportMetaURL()),
"using `new URL(\u2026, import.meta.url)`",
"will"
],
[
async () => instantiateModuleWorker(await searchWorkerURLEsbuildWorkaround()),
"using the `esbuild` workaround",
"will"
]
];
for (const [fn, description, warnOnSuccess] of fallbackOrder) {
try {
const worker = await fn();
if (warnOnSuccess) {
if (searchOutsideDebugGlobals.showWorkerInstantiationWarnings) {
console.warn(
`Module worker instantiation required ${description}. \`cubing.js\` ${warnOnSuccess} not support this fallback in the future.`
);
}
}
return worker;
} catch {
if (searchOutsideDebugGlobals.showWorkerInstantiationWarnings) {
console.warn(`${failed(description)}, falling back.`);
}
}
}
throw new Error(`${failed()}. There are no more fallbacks available.`);
}
// src/cubing/search/outside.ts
var cachedWorkerInstance;
function getCachedWorkerInstance() {
return cachedWorkerInstance ??= instantiateWorker();
}
async function randomScrambleForEvent(eventID) {
switch (eventID) {
case "clock":
return Alg.fromString(await randomClockScrambleString());
}
const prom = _randomScrambleStringForEvent(eventID);
const wat = await prom;
return Alg.fromString(wat);
}
async function _randomScrambleStringForEvent(eventID) {
if (searchOutsideDebugGlobals.forceNewWorkerForEveryScramble) {
}
const worker = searchOutsideDebugGlobals.forceNewWorkerForEveryScramble ? await instantiateWorker() : await getCachedWorkerInstance();
return worker.insideAPI.randomScrambleStringForEvent(eventID);
}
async function experimentalSolve3x3x3IgnoringCenters(pattern) {
const cwi = await getCachedWorkerInstance();
return Alg.fromString(
await cwi.insideAPI.solve333ToString(pattern.patternData)
);
}
async function experimentalSolve2x2x2(pattern) {
const cwi = await getCachedWorkerInstance();
return Alg.fromString(
await cwi.insideAPI.solve222ToString(pattern.patternData)
);
}
async function solveSkewb(pattern) {
const cwi = await getCachedWorkerInstance();
return Alg.fromString(
await cwi.insideAPI.solveSkewbToString(pattern.patternData)
);
}
async function solvePyraminx(pattern) {
const cwi = await getCachedWorkerInstance();
return Alg.fromString(
await cwi.insideAPI.solvePyraminxToString(pattern.patternData)
);
}
async function solveMegaminx(pattern) {
const cwi = await getCachedWorkerInstance();
return Alg.fromString(
await cwi.insideAPI.solveMegaminxToString(pattern.patternData)
);
}
async function solveTwsearch(kpuzzle, pattern, options) {
const { targetPattern, ...otherOptions } = options ?? {};
const apiOptions = otherOptions;
if (targetPattern) {
apiOptions.targetPattern = targetPattern.patternData;
}
const { ...def } = kpuzzle.definition;
delete def.experimentalIsPatternSolved;
const dedicatedWorker = await instantiateWorker();
try {
return Alg.fromString(
await dedicatedWorker.insideAPI.solveTwsearchToString(
def,
pattern.patternData,
apiOptions
)
);
} finally {
console.log("Search ended, terminating dedicated `twsearch` worker.");
await dedicatedWorker.outsideAPI.terminate();
}
}
var searchOutsideDebugGlobals = {
logPerf: true,
scramblePrefetchLevel: "auto",
disableStringWorker: false,
forceNewWorkerForEveryScramble: false,
showWorkerInstantiationWarnings: true
};
function setSearchDebug(options) {
const { logPerf, scramblePrefetchLevel } = options;
if (typeof logPerf !== "undefined") {
searchOutsideDebugGlobals.logPerf = logPerf;
mapToAllWorkers((worker) => worker.insideAPI.setDebugMeasurePerf(logPerf));
}
if (typeof scramblePrefetchLevel !== "undefined") {
searchOutsideDebugGlobals.scramblePrefetchLevel = scramblePrefetchLevel;
mapToAllWorkers(
(worker) => worker.insideAPI.setScramblePrefetchLevel(
scramblePrefetchLevel
)
);
}
if ("disableStringWorker" in options) {
searchOutsideDebugGlobals.disableStringWorker = !!options.disableStringWorker;
}
if ("forceNewWorkerForEveryScramble" in options) {
searchOutsideDebugGlobals.forceNewWorkerForEveryScramble = !!options.forceNewWorkerForEveryScramble;
}
if ("showWorkerInstantiationWarnings" in options) {
searchOutsideDebugGlobals.showWorkerInstantiationWarnings = !!options.showWorkerInstantiationWarnings;
}
}
export {
randomScrambleForEvent,
experimentalSolve3x3x3IgnoringCenters,
experimentalSolve2x2x2,
solveSkewb,
solvePyraminx,
solveMegaminx,
solveTwsearch,
setSearchDebug
};
//# sourceMappingURL=chunk-FMUJKX6Z.js.map