cube-state-engine 1.4.0 → 1.6.0
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/.claude/settings.local.json +9 -0
- package/.idea/AICommit.xml +6 -0
- package/.idea/awsToolkit.xml +11 -0
- package/.idea/cube-state-engine.iml +8 -0
- package/.idea/inspectionProfiles/Project_Default.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/dist/index.d.mts +1388 -656
- package/dist/index.d.ts +1388 -656
- package/dist/index.js +961 -462
- package/dist/index.mjs +954 -461
- package/package.json +2 -2
- package/.idea/workspace.xml +0 -304
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
2
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
6
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
@@ -17,20 +19,855 @@ var __spreadValues = (a, b) => {
|
|
|
17
19
|
}
|
|
18
20
|
return a;
|
|
19
21
|
};
|
|
22
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
23
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
21
24
|
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
25
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
22
26
|
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
27
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
23
28
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
24
29
|
|
|
30
|
+
// src/simplify.js
|
|
31
|
+
function canMerge(a, b) {
|
|
32
|
+
return typeof a === "string" && a === b && !a.includes("2");
|
|
33
|
+
}
|
|
34
|
+
function doubled(tok) {
|
|
35
|
+
return tok.replace("'", "") + "2";
|
|
36
|
+
}
|
|
37
|
+
function simplifyTokens(tokens) {
|
|
38
|
+
const out = [];
|
|
39
|
+
for (let i = 0; i < tokens.length; ) {
|
|
40
|
+
const a = tokens[i];
|
|
41
|
+
const b = tokens[i + 1];
|
|
42
|
+
if (i + 1 < tokens.length && canMerge(a, b)) {
|
|
43
|
+
out.push(doubled(a));
|
|
44
|
+
i += 2;
|
|
45
|
+
} else {
|
|
46
|
+
out.push(a);
|
|
47
|
+
i += 1;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
function simplifyTimed(moves) {
|
|
53
|
+
const out = [];
|
|
54
|
+
for (let i = 0; i < moves.length; ) {
|
|
55
|
+
const a = moves[i];
|
|
56
|
+
const b = moves[i + 1];
|
|
57
|
+
if (i + 1 < moves.length && canMerge(a == null ? void 0 : a.m, b == null ? void 0 : b.m)) {
|
|
58
|
+
out.push({ m: doubled(a.m), t: b.t });
|
|
59
|
+
i += 2;
|
|
60
|
+
} else {
|
|
61
|
+
out.push(a);
|
|
62
|
+
i += 1;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
function simplifyMoves(moves) {
|
|
68
|
+
if (typeof moves === "string") {
|
|
69
|
+
const tokens = moves.split(/\s+/).filter((t) => t.length > 0);
|
|
70
|
+
return simplifyTokens(tokens).join(" ");
|
|
71
|
+
}
|
|
72
|
+
if (Array.isArray(moves)) {
|
|
73
|
+
if (moves.length === 0) return [];
|
|
74
|
+
if (typeof moves[0] === "string") return simplifyTokens(moves);
|
|
75
|
+
return simplifyTimed(moves);
|
|
76
|
+
}
|
|
77
|
+
return moves;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/analyzer.js
|
|
81
|
+
var FACE_NAMES = ["UPPER", "LEFT", "FRONT", "RIGHT", "BACK", "DOWN"];
|
|
82
|
+
var FACE_MOVE_TO_INDEX = { U: 0, L: 1, F: 2, R: 3, B: 4, D: 5 };
|
|
83
|
+
var SUPPORTED_BASES = /* @__PURE__ */ new Set([
|
|
84
|
+
"U",
|
|
85
|
+
"D",
|
|
86
|
+
"L",
|
|
87
|
+
"R",
|
|
88
|
+
"F",
|
|
89
|
+
"B",
|
|
90
|
+
"x",
|
|
91
|
+
"y",
|
|
92
|
+
"z",
|
|
93
|
+
"M",
|
|
94
|
+
"E",
|
|
95
|
+
"S",
|
|
96
|
+
"Uw",
|
|
97
|
+
"Dw",
|
|
98
|
+
"Rw",
|
|
99
|
+
"Lw",
|
|
100
|
+
"Fw"
|
|
101
|
+
]);
|
|
102
|
+
var WIDE_LOWER = { r: "Rw", u: "Uw", f: "Fw", l: "Lw", d: "Dw", b: "Bw" };
|
|
103
|
+
function normalizeToken(raw) {
|
|
104
|
+
const m = String(raw).trim().match(/^([A-Za-z]w?)('?2?|2?'?)$/);
|
|
105
|
+
if (!m) return { token: raw, base: null };
|
|
106
|
+
let base = m[1];
|
|
107
|
+
if (base.length === 1 && WIDE_LOWER[base]) base = WIDE_LOWER[base];
|
|
108
|
+
return { token: base + m[2], base };
|
|
109
|
+
}
|
|
110
|
+
var GEOMETRY_CACHE = /* @__PURE__ */ new Map();
|
|
111
|
+
function buildGeometry(size) {
|
|
112
|
+
if (GEOMETRY_CACHE.has(size)) return GEOMETRY_CACHE.get(size);
|
|
113
|
+
const perms = getMovePermutations(size);
|
|
114
|
+
const per = size * size;
|
|
115
|
+
const total = per * 6;
|
|
116
|
+
const faceMoves = Object.keys(FACE_MOVE_TO_INDEX);
|
|
117
|
+
const edgeMap = /* @__PURE__ */ new Map();
|
|
118
|
+
const cornerMap = /* @__PURE__ */ new Map();
|
|
119
|
+
for (let i = 0; i < total; i++) {
|
|
120
|
+
const faces = [];
|
|
121
|
+
for (const mv of faceMoves) {
|
|
122
|
+
if (perms[mv].cw[i] !== i) faces.push(FACE_MOVE_TO_INDEX[mv]);
|
|
123
|
+
}
|
|
124
|
+
faces.sort((a, b) => a - b);
|
|
125
|
+
const key = faces.join(",");
|
|
126
|
+
if (faces.length === 2) {
|
|
127
|
+
if (!edgeMap.has(key)) edgeMap.set(key, []);
|
|
128
|
+
edgeMap.get(key).push(i);
|
|
129
|
+
} else if (faces.length === 3) {
|
|
130
|
+
if (!cornerMap.has(key)) cornerMap.set(key, []);
|
|
131
|
+
cornerMap.get(key).push(i);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const edges = [...edgeMap.entries()].map(([key, indices]) => ({
|
|
135
|
+
faces: key.split(",").map(Number),
|
|
136
|
+
indices
|
|
137
|
+
}));
|
|
138
|
+
const corners = [...cornerMap.entries()].map(([key, indices]) => ({
|
|
139
|
+
faces: key.split(",").map(Number),
|
|
140
|
+
indices
|
|
141
|
+
}));
|
|
142
|
+
const neighbors = Array.from({ length: 6 }, () => /* @__PURE__ */ new Set());
|
|
143
|
+
for (const e of edges) {
|
|
144
|
+
const [a, b] = e.faces;
|
|
145
|
+
neighbors[a].add(b);
|
|
146
|
+
neighbors[b].add(a);
|
|
147
|
+
}
|
|
148
|
+
const opposite = new Array(6).fill(-1);
|
|
149
|
+
for (let f = 0; f < 6; f++) {
|
|
150
|
+
for (let g = 0; g < 6; g++) {
|
|
151
|
+
if (g !== f && !neighbors[f].has(g)) {
|
|
152
|
+
opposite[f] = g;
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const geo = {
|
|
158
|
+
size,
|
|
159
|
+
per,
|
|
160
|
+
centerIndex: (f) => f * per + Math.floor(per / 2),
|
|
161
|
+
edges,
|
|
162
|
+
corners,
|
|
163
|
+
neighbors,
|
|
164
|
+
opposite,
|
|
165
|
+
edgesByFace: (f) => edges.filter((e) => e.faces.includes(f)),
|
|
166
|
+
cornersByFace: (f) => corners.filter((c) => c.faces.includes(f)),
|
|
167
|
+
edgeByPair: (a, b) => edges.find(
|
|
168
|
+
(e) => e.faces[0] === a && e.faces[1] === b || e.faces[0] === b && e.faces[1] === a
|
|
169
|
+
)
|
|
170
|
+
};
|
|
171
|
+
GEOMETRY_CACHE.set(size, geo);
|
|
172
|
+
return geo;
|
|
173
|
+
}
|
|
174
|
+
function invertToken(tok) {
|
|
175
|
+
if (tok.endsWith("2")) return tok;
|
|
176
|
+
if (tok.endsWith("'")) return tok.slice(0, -1);
|
|
177
|
+
return tok + "'";
|
|
178
|
+
}
|
|
179
|
+
function invertSequence(tokens) {
|
|
180
|
+
return tokens.slice().reverse().map(invertToken);
|
|
181
|
+
}
|
|
182
|
+
function flattenState(state) {
|
|
183
|
+
const out = [];
|
|
184
|
+
for (const name of FACE_NAMES) {
|
|
185
|
+
const matrix = state[name];
|
|
186
|
+
for (const row of matrix) {
|
|
187
|
+
for (const v of row) out.push(v);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return out;
|
|
191
|
+
}
|
|
192
|
+
function centersOf(st, geo) {
|
|
193
|
+
const centers = new Array(6);
|
|
194
|
+
for (let f = 0; f < 6; f++) centers[f] = st[geo.centerIndex(f)];
|
|
195
|
+
return centers;
|
|
196
|
+
}
|
|
197
|
+
function slotCorrect(st, centers, indices, per) {
|
|
198
|
+
for (const x of indices) {
|
|
199
|
+
if (st[x] !== centers[Math.floor(x / per)]) return false;
|
|
200
|
+
}
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
function isSolvedFlat(st, per) {
|
|
204
|
+
for (let f = 0; f < 6; f++) {
|
|
205
|
+
const base = f * per;
|
|
206
|
+
const c = st[base];
|
|
207
|
+
for (let i = 1; i < per; i++) if (st[base + i] !== c) return false;
|
|
208
|
+
}
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
function crossDone(st, geo, color) {
|
|
212
|
+
const centers = centersOf(st, geo);
|
|
213
|
+
const C = centers.indexOf(color);
|
|
214
|
+
if (C < 0) return false;
|
|
215
|
+
return geo.edgesByFace(C).every((e) => slotCorrect(st, centers, e.indices, geo.per));
|
|
216
|
+
}
|
|
217
|
+
function f2lSlotStates(st, geo, color) {
|
|
218
|
+
const centers = centersOf(st, geo);
|
|
219
|
+
const C = centers.indexOf(color);
|
|
220
|
+
const result = {};
|
|
221
|
+
if (C < 0) return result;
|
|
222
|
+
for (const corner of geo.cornersByFace(C)) {
|
|
223
|
+
const sides = corner.faces.filter((f) => f !== C);
|
|
224
|
+
if (sides.length !== 2) continue;
|
|
225
|
+
const [a, b] = sides;
|
|
226
|
+
const edge = geo.edgeByPair(a, b);
|
|
227
|
+
const cornerOk = slotCorrect(st, centers, corner.indices, geo.per);
|
|
228
|
+
const edgeOk = edge ? slotCorrect(st, centers, edge.indices, geo.per) : false;
|
|
229
|
+
const key = [centers[a], centers[b]].sort().join("-");
|
|
230
|
+
result[key] = cornerOk && edgeOk;
|
|
231
|
+
}
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
234
|
+
function ollDone(st, geo, color) {
|
|
235
|
+
const centers = centersOf(st, geo);
|
|
236
|
+
const C = centers.indexOf(color);
|
|
237
|
+
if (C < 0) return false;
|
|
238
|
+
const O = geo.opposite[C];
|
|
239
|
+
const base = O * geo.per;
|
|
240
|
+
for (let i = 0; i < geo.per; i++) {
|
|
241
|
+
if (st[base + i] !== centers[O]) return false;
|
|
242
|
+
}
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
function rouxBlockPieces(geo, sideFace, upFace) {
|
|
246
|
+
const downFace = geo.opposite[upFace];
|
|
247
|
+
const edges = geo.edgesByFace(sideFace).filter((e) => !e.faces.includes(upFace));
|
|
248
|
+
const corners = geo.cornersByFace(sideFace).filter((c) => c.faces.includes(downFace));
|
|
249
|
+
return { edges, corners };
|
|
250
|
+
}
|
|
251
|
+
function rouxBlockDone(st, centers, geo, sideFace, upFace) {
|
|
252
|
+
const { edges, corners } = rouxBlockPieces(geo, sideFace, upFace);
|
|
253
|
+
if (edges.length !== 3 || corners.length !== 2) return false;
|
|
254
|
+
for (const e of edges)
|
|
255
|
+
if (!slotCorrect(st, centers, e.indices, geo.per)) return false;
|
|
256
|
+
for (const c of corners)
|
|
257
|
+
if (!slotCorrect(st, centers, c.indices, geo.per)) return false;
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
function applyPerm(st, perm) {
|
|
261
|
+
const out = new Array(st.length);
|
|
262
|
+
for (let i = 0; i < st.length; i++) out[i] = st[perm[i]];
|
|
263
|
+
return out;
|
|
264
|
+
}
|
|
265
|
+
function cmllDone(st, geo, upFace, mPerm) {
|
|
266
|
+
let cur = st;
|
|
267
|
+
const corners = geo.cornersByFace(upFace);
|
|
268
|
+
for (let m = 0; m < 4; m++) {
|
|
269
|
+
if (m > 0) cur = applyPerm(cur, mPerm);
|
|
270
|
+
const centers = centersOf(cur, geo);
|
|
271
|
+
if (corners.every((c) => slotCorrect(cur, centers, c.indices, geo.per)))
|
|
272
|
+
return true;
|
|
273
|
+
}
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
function completionIndex(bools) {
|
|
277
|
+
const n = bools.length;
|
|
278
|
+
if (n === 0 || !bools[n - 1]) return null;
|
|
279
|
+
for (let i = 0; i < n; i++) if (bools[i]) return i;
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
function buildForCross(snapshots, geo, color) {
|
|
283
|
+
const n = snapshots.length;
|
|
284
|
+
const crossBools = snapshots.map((st) => crossDone(st, geo, color));
|
|
285
|
+
const crossIdx = completionIndex(crossBools);
|
|
286
|
+
const slotSeries = /* @__PURE__ */ new Map();
|
|
287
|
+
for (let i = 0; i < n; i++) {
|
|
288
|
+
const states = f2lSlotStates(snapshots[i], geo, color);
|
|
289
|
+
for (const [key, val] of Object.entries(states)) {
|
|
290
|
+
if (!slotSeries.has(key)) slotSeries.set(key, new Array(n).fill(false));
|
|
291
|
+
slotSeries.get(key)[i] = crossBools[i] && val;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const f2lSlots = [...slotSeries.entries()].map(([slot, bools]) => ({ slot, idx: completionIndex(bools) })).filter((s) => s.idx != null).sort((a, b) => a.idx - b.idx);
|
|
295
|
+
const f2lComplete = new Array(n).fill(false);
|
|
296
|
+
for (let i = 0; i < n; i++) {
|
|
297
|
+
if (!crossBools[i] || slotSeries.size < 4) continue;
|
|
298
|
+
let all = true;
|
|
299
|
+
for (const bools of slotSeries.values()) {
|
|
300
|
+
if (!bools[i]) {
|
|
301
|
+
all = false;
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
f2lComplete[i] = all;
|
|
306
|
+
}
|
|
307
|
+
const ollIdx = completionIndex(
|
|
308
|
+
snapshots.map((st, i) => f2lComplete[i] && ollDone(st, geo, color))
|
|
309
|
+
);
|
|
310
|
+
const pllIdx = completionIndex(snapshots.map((st) => isSolvedFlat(st, geo.per)));
|
|
311
|
+
return { crossIdx, f2lSlots, ollIdx, pllIdx };
|
|
312
|
+
}
|
|
313
|
+
function isCFOP(build) {
|
|
314
|
+
const { crossIdx, f2lSlots, ollIdx, pllIdx } = build;
|
|
315
|
+
if (crossIdx == null || pllIdx == null || ollIdx == null) return false;
|
|
316
|
+
if (f2lSlots.length !== 4) return false;
|
|
317
|
+
if (!f2lSlots.every((s) => s.idx >= crossIdx)) return false;
|
|
318
|
+
const lastF2L = f2lSlots[3].idx;
|
|
319
|
+
return ollIdx >= lastF2L && pllIdx >= ollIdx;
|
|
320
|
+
}
|
|
321
|
+
function buildForRoux(snapshots, geo, sideA, upFace, mPerm) {
|
|
322
|
+
const n = snapshots.length;
|
|
323
|
+
const sideB = geo.opposite[sideA];
|
|
324
|
+
const centersAt = snapshots.map((st) => centersOf(st, geo));
|
|
325
|
+
const aDone = snapshots.map(
|
|
326
|
+
(st, i) => rouxBlockDone(st, centersAt[i], geo, sideA, upFace)
|
|
327
|
+
);
|
|
328
|
+
const bDone = snapshots.map(
|
|
329
|
+
(st, i) => rouxBlockDone(st, centersAt[i], geo, sideB, upFace)
|
|
330
|
+
);
|
|
331
|
+
const aIdx = completionIndex(aDone);
|
|
332
|
+
const bIdx = completionIndex(bDone);
|
|
333
|
+
let firstSide = sideA;
|
|
334
|
+
let secondSide = sideB;
|
|
335
|
+
let fbBools = aDone;
|
|
336
|
+
let sbBools = bDone;
|
|
337
|
+
if ((bIdx != null ? bIdx : Infinity) < (aIdx != null ? aIdx : Infinity)) {
|
|
338
|
+
firstSide = sideB;
|
|
339
|
+
secondSide = sideA;
|
|
340
|
+
fbBools = bDone;
|
|
341
|
+
sbBools = aDone;
|
|
342
|
+
}
|
|
343
|
+
const fbIdx = completionIndex(fbBools);
|
|
344
|
+
const secondBlockBools = snapshots.map((_, i) => fbBools[i] && sbBools[i]);
|
|
345
|
+
const sbIdx = completionIndex(secondBlockBools);
|
|
346
|
+
const cmllIdx = completionIndex(
|
|
347
|
+
snapshots.map(
|
|
348
|
+
(st, i) => secondBlockBools[i] && cmllDone(st, geo, upFace, mPerm)
|
|
349
|
+
)
|
|
350
|
+
);
|
|
351
|
+
const lseIdx = completionIndex(snapshots.map((st) => isSolvedFlat(st, geo.per)));
|
|
352
|
+
return { firstSide, secondSide, upFace, fbIdx, sbIdx, cmllIdx, lseIdx };
|
|
353
|
+
}
|
|
354
|
+
function isRoux(build) {
|
|
355
|
+
const { fbIdx, sbIdx, cmllIdx, lseIdx } = build;
|
|
356
|
+
if (fbIdx == null || sbIdx == null || cmllIdx == null || lseIdx == null)
|
|
357
|
+
return false;
|
|
358
|
+
return fbIdx <= sbIdx && sbIdx <= cmllIdx && cmllIdx <= lseIdx;
|
|
359
|
+
}
|
|
360
|
+
function analyzeSolution(moves, options = {}) {
|
|
361
|
+
var _a, _b;
|
|
362
|
+
const size = options.size === 2 ? 2 : 3;
|
|
363
|
+
const unsupported = [];
|
|
364
|
+
const seq = (Array.isArray(moves) ? moves : []).map((x) => {
|
|
365
|
+
var _a2;
|
|
366
|
+
const m = String((_a2 = x == null ? void 0 : x.m) != null ? _a2 : "").trim();
|
|
367
|
+
const { token, base: base2 } = normalizeToken(m);
|
|
368
|
+
const supported = base2 != null && SUPPORTED_BASES.has(base2);
|
|
369
|
+
if (m.length > 0 && !supported) unsupported.push(m);
|
|
370
|
+
return { m, mm: supported ? token : "", t: Number(x == null ? void 0 : x.t) };
|
|
371
|
+
}).filter((x) => x.m.length > 0);
|
|
372
|
+
const n = seq.length;
|
|
373
|
+
const simplifiedMoves = simplifyMoves(
|
|
374
|
+
(Array.isArray(moves) ? moves : []).filter((x) => x == null ? void 0 : x.m)
|
|
375
|
+
);
|
|
376
|
+
const simplifiedCount = simplifiedMoves.length;
|
|
377
|
+
const empty = {
|
|
378
|
+
size,
|
|
379
|
+
method: "unknown",
|
|
380
|
+
solved: false,
|
|
381
|
+
total: n > 0 ? seq[n - 1].t : 0,
|
|
382
|
+
tps: 0,
|
|
383
|
+
moves: simplifiedMoves,
|
|
384
|
+
cross: null,
|
|
385
|
+
f2l: [],
|
|
386
|
+
oll: null,
|
|
387
|
+
pll: null,
|
|
388
|
+
firstBlock: null,
|
|
389
|
+
secondBlock: null,
|
|
390
|
+
cmll: null,
|
|
391
|
+
lse: null,
|
|
392
|
+
allCrosses: {},
|
|
393
|
+
unsupported
|
|
394
|
+
};
|
|
395
|
+
if (n === 0) return empty;
|
|
396
|
+
const engine = new CubeEngine("", { size });
|
|
397
|
+
const scramble = invertSequence(seq.map((x) => x.mm).filter(Boolean)).join(" ");
|
|
398
|
+
engine.applyMoves(scramble, { record: false });
|
|
399
|
+
const geo = buildGeometry(size);
|
|
400
|
+
const snapshots = new Array(n);
|
|
401
|
+
for (let i = 0; i < n; i++) {
|
|
402
|
+
if (seq[i].mm) engine.applyMoves(seq[i].mm, { record: false });
|
|
403
|
+
snapshots[i] = flattenState(engine.state());
|
|
404
|
+
}
|
|
405
|
+
const solved = isSolvedFlat(snapshots[n - 1], geo.per);
|
|
406
|
+
const pllIdxOnly = completionIndex(
|
|
407
|
+
snapshots.map((st) => isSolvedFlat(st, geo.per))
|
|
408
|
+
);
|
|
409
|
+
const milestone = (idx, prevAt2) => {
|
|
410
|
+
if (idx == null) return { record: null, at: prevAt2 };
|
|
411
|
+
const at = seq[idx].t;
|
|
412
|
+
return {
|
|
413
|
+
record: { at, duration: at - prevAt2, moveIndex: idx, move: seq[idx].m },
|
|
414
|
+
at
|
|
415
|
+
};
|
|
416
|
+
};
|
|
417
|
+
if (size !== 3) {
|
|
418
|
+
const pll = milestone(pllIdxOnly, 0);
|
|
419
|
+
const total2 = seq[n - 1].t;
|
|
420
|
+
return __spreadProps(__spreadValues({}, empty), {
|
|
421
|
+
solved,
|
|
422
|
+
total: total2,
|
|
423
|
+
tps: total2 > 0 ? simplifiedCount / (total2 / 1e3) : 0,
|
|
424
|
+
pll: pll.record
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
const finalCenters = centersOf(snapshots[n - 1], geo);
|
|
428
|
+
const colors = [...new Set(finalCenters)];
|
|
429
|
+
const allCrosses = {};
|
|
430
|
+
for (const color of colors) {
|
|
431
|
+
const idx = completionIndex(
|
|
432
|
+
snapshots.map((st) => crossDone(st, geo, color))
|
|
433
|
+
);
|
|
434
|
+
allCrosses[color] = idx == null ? null : { at: seq[idx].t, moveIndex: idx, move: seq[idx].m };
|
|
435
|
+
}
|
|
436
|
+
const ordered = colors.map((color) => ({ color, build: buildForCross(snapshots, geo, color) })).sort((a, b) => {
|
|
437
|
+
var _a2, _b2;
|
|
438
|
+
const ai = (_a2 = a.build.crossIdx) != null ? _a2 : Infinity;
|
|
439
|
+
const bi = (_b2 = b.build.crossIdx) != null ? _b2 : Infinity;
|
|
440
|
+
return ai - bi;
|
|
441
|
+
});
|
|
442
|
+
const cfopChosen = (_a = ordered.find((c) => isCFOP(c.build))) != null ? _a : ordered[0];
|
|
443
|
+
const cfopValid = !!cfopChosen && isCFOP(cfopChosen.build);
|
|
444
|
+
const mPerm = getMovePermutations(size)["M"].cw;
|
|
445
|
+
const rouxCandidates = [];
|
|
446
|
+
for (let s = 0; s < 6; s++) {
|
|
447
|
+
for (const u of geo.neighbors[s]) {
|
|
448
|
+
rouxCandidates.push(buildForRoux(snapshots, geo, s, u, mPerm));
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
const rouxBuild = (_b = rouxCandidates.filter((b) => isRoux(b)).sort((a, b) => a.fbIdx - b.fbIdx)[0]) != null ? _b : null;
|
|
452
|
+
let method = "unknown";
|
|
453
|
+
if (cfopValid && rouxBuild) {
|
|
454
|
+
method = cfopChosen.build.crossIdx <= rouxBuild.fbIdx ? "CFOP" : "Roux";
|
|
455
|
+
} else if (cfopValid) {
|
|
456
|
+
method = "CFOP";
|
|
457
|
+
} else if (rouxBuild) {
|
|
458
|
+
method = "Roux";
|
|
459
|
+
}
|
|
460
|
+
const total = seq[n - 1].t;
|
|
461
|
+
const base = {
|
|
462
|
+
size,
|
|
463
|
+
method,
|
|
464
|
+
solved,
|
|
465
|
+
total,
|
|
466
|
+
tps: total > 0 ? simplifiedCount / (total / 1e3) : 0,
|
|
467
|
+
moves: simplifiedMoves,
|
|
468
|
+
cross: null,
|
|
469
|
+
f2l: [],
|
|
470
|
+
oll: null,
|
|
471
|
+
pll: null,
|
|
472
|
+
firstBlock: null,
|
|
473
|
+
secondBlock: null,
|
|
474
|
+
cmll: null,
|
|
475
|
+
lse: null,
|
|
476
|
+
allCrosses,
|
|
477
|
+
unsupported
|
|
478
|
+
};
|
|
479
|
+
if (method === "Roux") {
|
|
480
|
+
const fbM = milestone(rouxBuild.fbIdx, 0);
|
|
481
|
+
const sbM = milestone(rouxBuild.sbIdx, fbM.at);
|
|
482
|
+
const cmllM = milestone(rouxBuild.cmllIdx, sbM.at);
|
|
483
|
+
const lseM = milestone(rouxBuild.lseIdx, cmllM.at);
|
|
484
|
+
return __spreadProps(__spreadValues({}, base), {
|
|
485
|
+
firstBlock: fbM.record ? __spreadValues({ side: finalCenters[rouxBuild.firstSide] }, fbM.record) : null,
|
|
486
|
+
secondBlock: sbM.record ? __spreadValues({ side: finalCenters[rouxBuild.secondSide] }, sbM.record) : null,
|
|
487
|
+
cmll: cmllM.record,
|
|
488
|
+
lse: lseM.record
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
const { color: crossColor, build } = cfopChosen;
|
|
492
|
+
const crossM = milestone(build.crossIdx, 0);
|
|
493
|
+
const cross = crossM.record ? __spreadValues({ color: crossColor }, crossM.record) : null;
|
|
494
|
+
let prevAt = crossM.at;
|
|
495
|
+
const f2l = [];
|
|
496
|
+
for (const slot of build.f2lSlots) {
|
|
497
|
+
const m = milestone(slot.idx, prevAt);
|
|
498
|
+
if (m.record) {
|
|
499
|
+
f2l.push(__spreadValues({ slot: slot.slot }, m.record));
|
|
500
|
+
prevAt = m.at;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
const ollM = milestone(build.ollIdx, prevAt);
|
|
504
|
+
prevAt = ollM.at;
|
|
505
|
+
const pllM = milestone(build.pllIdx, prevAt);
|
|
506
|
+
return __spreadProps(__spreadValues({}, base), {
|
|
507
|
+
cross,
|
|
508
|
+
f2l,
|
|
509
|
+
oll: ollM.record,
|
|
510
|
+
pll: pllM.record
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
|
|
25
514
|
// src/index.js
|
|
26
|
-
var
|
|
515
|
+
var FACE_NAMES2 = ["UPPER", "LEFT", "FRONT", "RIGHT", "BACK", "DOWN"];
|
|
516
|
+
var FACE_COLORS = ["W", "O", "G", "R", "B", "Y"];
|
|
517
|
+
var NOOP_SIZE2 = /* @__PURE__ */ new Set(["Uw", "Dw", "Rw", "Lw", "Fw", "M", "E", "S"]);
|
|
518
|
+
var MOVE_FNS = {
|
|
519
|
+
U: "rotateU",
|
|
520
|
+
D: "rotateD",
|
|
521
|
+
L: "rotateL",
|
|
522
|
+
R: "rotateR",
|
|
523
|
+
F: "rotateF",
|
|
524
|
+
B: "rotateB",
|
|
525
|
+
x: "rotateX",
|
|
526
|
+
y: "rotateY",
|
|
527
|
+
z: "rotateZ",
|
|
528
|
+
M: "rotateM",
|
|
529
|
+
E: "rotateE",
|
|
530
|
+
S: "rotateS",
|
|
531
|
+
Uw: "rotateUw",
|
|
532
|
+
Dw: "rotateDw",
|
|
533
|
+
Rw: "rotateRw",
|
|
534
|
+
Lw: "rotateLw",
|
|
535
|
+
Fw: "rotateFw"
|
|
536
|
+
};
|
|
537
|
+
var PERM_CACHE = /* @__PURE__ */ new Map();
|
|
538
|
+
var _OracleCube = class {
|
|
539
|
+
constructor(size) {
|
|
540
|
+
this.size = size;
|
|
541
|
+
this.STATES = {};
|
|
542
|
+
for (let f = 0; f < FACE_NAMES2.length; f++) {
|
|
543
|
+
const face = [];
|
|
544
|
+
for (let r = 0; r < size; r++) {
|
|
545
|
+
const row = [];
|
|
546
|
+
for (let c = 0; c < size; c++) {
|
|
547
|
+
row.push(f * size * size + r * size + c);
|
|
548
|
+
}
|
|
549
|
+
face.push(row);
|
|
550
|
+
}
|
|
551
|
+
this.STATES[FACE_NAMES2[f]] = face;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
// Concatenate every face row-major into a single flat array of tags.
|
|
555
|
+
flatten() {
|
|
556
|
+
const out = [];
|
|
557
|
+
for (const name of FACE_NAMES2) {
|
|
558
|
+
const face = this.STATES[name];
|
|
559
|
+
for (let r = 0; r < this.size; r++) {
|
|
560
|
+
for (let c = 0; c < this.size; c++) {
|
|
561
|
+
out.push(face[r][c]);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return out;
|
|
566
|
+
}
|
|
567
|
+
switchMatrix(matrix, clockwise = true) {
|
|
568
|
+
const clone = structuredClone(matrix);
|
|
569
|
+
const size = this.size;
|
|
570
|
+
let tempMatrix = [];
|
|
571
|
+
for (let i = 0; i < size; i++) {
|
|
572
|
+
tempMatrix = [...tempMatrix, ...clone[i]];
|
|
573
|
+
}
|
|
574
|
+
if (size === 2) {
|
|
575
|
+
if (clockwise) {
|
|
576
|
+
return [
|
|
577
|
+
[tempMatrix[2], tempMatrix[0]],
|
|
578
|
+
[tempMatrix[3], tempMatrix[1]]
|
|
579
|
+
];
|
|
580
|
+
} else {
|
|
581
|
+
return [
|
|
582
|
+
[tempMatrix[1], tempMatrix[3]],
|
|
583
|
+
[tempMatrix[0], tempMatrix[2]]
|
|
584
|
+
];
|
|
585
|
+
}
|
|
586
|
+
} else {
|
|
587
|
+
if (clockwise) {
|
|
588
|
+
return [
|
|
589
|
+
[tempMatrix[6], tempMatrix[3], tempMatrix[0]],
|
|
590
|
+
[tempMatrix[7], tempMatrix[4], tempMatrix[1]],
|
|
591
|
+
[tempMatrix[8], tempMatrix[5], tempMatrix[2]]
|
|
592
|
+
];
|
|
593
|
+
} else {
|
|
594
|
+
return [
|
|
595
|
+
[tempMatrix[2], tempMatrix[5], tempMatrix[8]],
|
|
596
|
+
[tempMatrix[1], tempMatrix[4], tempMatrix[7]],
|
|
597
|
+
[tempMatrix[0], tempMatrix[3], tempMatrix[6]]
|
|
598
|
+
];
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
specialFlip(matrix) {
|
|
603
|
+
return structuredClone(matrix).reverse().map((row) => [...row].reverse());
|
|
604
|
+
}
|
|
605
|
+
rotateU(clockwise = true) {
|
|
606
|
+
if (clockwise) {
|
|
607
|
+
this.STATES.UPPER = this.switchMatrix(this.STATES.UPPER, true);
|
|
608
|
+
const tempFront = [...this.STATES.FRONT[0]];
|
|
609
|
+
const tempRight = [...this.STATES.RIGHT[0]];
|
|
610
|
+
const tempLeft = [...this.STATES.LEFT[0]];
|
|
611
|
+
const tempBack = [...this.STATES.BACK[0]];
|
|
612
|
+
this.STATES.FRONT[0] = [...tempRight];
|
|
613
|
+
this.STATES.LEFT[0] = [...tempFront];
|
|
614
|
+
this.STATES.BACK[0] = [...tempLeft];
|
|
615
|
+
this.STATES.RIGHT[0] = [...tempBack];
|
|
616
|
+
} else {
|
|
617
|
+
this.STATES.UPPER = this.switchMatrix(this.STATES.UPPER, false);
|
|
618
|
+
const tempFront = [...this.STATES.FRONT[0]];
|
|
619
|
+
const tempRight = [...this.STATES.RIGHT[0]];
|
|
620
|
+
const tempLeft = [...this.STATES.LEFT[0]];
|
|
621
|
+
const tempBack = [...this.STATES.BACK[0]];
|
|
622
|
+
this.STATES.FRONT[0] = [...tempLeft];
|
|
623
|
+
this.STATES.LEFT[0] = [...tempBack];
|
|
624
|
+
this.STATES.BACK[0] = [...tempRight];
|
|
625
|
+
this.STATES.RIGHT[0] = [...tempFront];
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
rotateF(clockwise = true) {
|
|
629
|
+
if (clockwise) {
|
|
630
|
+
this.rotateX(true);
|
|
631
|
+
this.rotateU(true);
|
|
632
|
+
this.rotateX(false);
|
|
633
|
+
} else {
|
|
634
|
+
this.rotateX(true);
|
|
635
|
+
this.rotateU(false);
|
|
636
|
+
this.rotateX(false);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
rotateB(clockwise = true) {
|
|
640
|
+
this.rotateY(true);
|
|
641
|
+
this.rotateY(true);
|
|
642
|
+
if (clockwise) {
|
|
643
|
+
this.rotateF(true);
|
|
644
|
+
} else {
|
|
645
|
+
this.rotateF(false);
|
|
646
|
+
}
|
|
647
|
+
this.rotateY(false);
|
|
648
|
+
this.rotateY(false);
|
|
649
|
+
}
|
|
650
|
+
rotateR(clockwise = true) {
|
|
651
|
+
if (clockwise) {
|
|
652
|
+
this.rotateY(true);
|
|
653
|
+
this.rotateX(true);
|
|
654
|
+
this.rotateU(true);
|
|
655
|
+
this.rotateX(false);
|
|
656
|
+
this.rotateY(false);
|
|
657
|
+
} else {
|
|
658
|
+
this.rotateY(true);
|
|
659
|
+
this.rotateX(true);
|
|
660
|
+
this.rotateU(false);
|
|
661
|
+
this.rotateX(false);
|
|
662
|
+
this.rotateY(false);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
rotateL(clockwise = true) {
|
|
666
|
+
if (clockwise) {
|
|
667
|
+
this.rotateY(false);
|
|
668
|
+
this.rotateX(true);
|
|
669
|
+
this.rotateU(true);
|
|
670
|
+
this.rotateX(false);
|
|
671
|
+
this.rotateY(true);
|
|
672
|
+
} else {
|
|
673
|
+
this.rotateY(false);
|
|
674
|
+
this.rotateX(true);
|
|
675
|
+
this.rotateU(false);
|
|
676
|
+
this.rotateX(false);
|
|
677
|
+
this.rotateY(true);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
rotateD(clockwise = true) {
|
|
681
|
+
if (clockwise) {
|
|
682
|
+
this.rotateX(true);
|
|
683
|
+
this.rotateF(true);
|
|
684
|
+
this.rotateX(false);
|
|
685
|
+
} else {
|
|
686
|
+
this.rotateX(true);
|
|
687
|
+
this.rotateF(false);
|
|
688
|
+
this.rotateX(false);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
rotateDw(clockwise = true) {
|
|
692
|
+
if (this.size === 2) return;
|
|
693
|
+
if (clockwise) {
|
|
694
|
+
this.rotateY(false);
|
|
695
|
+
this.rotateU(true);
|
|
696
|
+
} else {
|
|
697
|
+
this.rotateY(true);
|
|
698
|
+
this.rotateU(false);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
rotateUw(clockwise = true) {
|
|
702
|
+
if (this.size === 2) return;
|
|
703
|
+
if (clockwise) {
|
|
704
|
+
this.rotateY(true);
|
|
705
|
+
this.rotateD(true);
|
|
706
|
+
} else {
|
|
707
|
+
this.rotateY(false);
|
|
708
|
+
this.rotateD(false);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
rotateRw(clockwise = true) {
|
|
712
|
+
if (this.size === 2) return;
|
|
713
|
+
if (clockwise) {
|
|
714
|
+
this.rotateX(true);
|
|
715
|
+
this.rotateL(true);
|
|
716
|
+
} else {
|
|
717
|
+
this.rotateX(false);
|
|
718
|
+
this.rotateL(false);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
rotateLw(clockwise = true) {
|
|
722
|
+
if (this.size === 2) return;
|
|
723
|
+
if (clockwise) {
|
|
724
|
+
this.rotateX(false);
|
|
725
|
+
this.rotateR(true);
|
|
726
|
+
} else {
|
|
727
|
+
this.rotateX(true);
|
|
728
|
+
this.rotateR(false);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
rotateM(clockwise = true) {
|
|
732
|
+
if (this.size === 2) return;
|
|
733
|
+
if (clockwise) {
|
|
734
|
+
this.rotateLw(true);
|
|
735
|
+
this.rotateL(false);
|
|
736
|
+
} else {
|
|
737
|
+
this.rotateLw(false);
|
|
738
|
+
this.rotateL(true);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
rotateE(clockwise = true) {
|
|
742
|
+
if (this.size === 2) return;
|
|
743
|
+
if (clockwise) {
|
|
744
|
+
this.rotateDw(true);
|
|
745
|
+
this.rotateD(false);
|
|
746
|
+
} else {
|
|
747
|
+
this.rotateDw(false);
|
|
748
|
+
this.rotateD(true);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
rotateFw(clockwise = true) {
|
|
752
|
+
if (this.size === 2) return;
|
|
753
|
+
if (clockwise) {
|
|
754
|
+
this.rotateZ(true);
|
|
755
|
+
this.rotateB(true);
|
|
756
|
+
} else {
|
|
757
|
+
this.rotateZ(false);
|
|
758
|
+
this.rotateB(false);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
rotateS(clockwise = true) {
|
|
762
|
+
if (this.size === 2) return;
|
|
763
|
+
if (clockwise) {
|
|
764
|
+
this.rotateFw(true);
|
|
765
|
+
this.rotateF(false);
|
|
766
|
+
} else {
|
|
767
|
+
this.rotateFw(false);
|
|
768
|
+
this.rotateF(true);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
rotateX(clockwise = true) {
|
|
772
|
+
const tempFront = structuredClone(this.STATES.FRONT);
|
|
773
|
+
const tempDown = structuredClone(this.STATES.DOWN);
|
|
774
|
+
const tempUpper = structuredClone(this.STATES.UPPER);
|
|
775
|
+
const tempBack = structuredClone(this.STATES.BACK);
|
|
776
|
+
const tempLeft = structuredClone(this.STATES.LEFT);
|
|
777
|
+
const tempRight = structuredClone(this.STATES.RIGHT);
|
|
778
|
+
if (clockwise) {
|
|
779
|
+
this.STATES.LEFT = this.switchMatrix(tempLeft, false);
|
|
780
|
+
this.STATES.RIGHT = this.switchMatrix(tempRight, true);
|
|
781
|
+
this.STATES.FRONT = [...tempDown];
|
|
782
|
+
this.STATES.UPPER = [...tempFront];
|
|
783
|
+
this.STATES.BACK = this.specialFlip(tempUpper);
|
|
784
|
+
this.STATES.DOWN = this.specialFlip(tempBack);
|
|
785
|
+
} else {
|
|
786
|
+
this.STATES.LEFT = this.switchMatrix(tempLeft, true);
|
|
787
|
+
this.STATES.RIGHT = this.switchMatrix(tempRight, false);
|
|
788
|
+
this.STATES.FRONT = [...tempUpper];
|
|
789
|
+
this.STATES.DOWN = [...tempFront];
|
|
790
|
+
this.STATES.BACK = this.specialFlip(tempDown);
|
|
791
|
+
this.STATES.UPPER = this.specialFlip(tempBack);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
rotateZ(clockwise = true) {
|
|
795
|
+
const tempUpper = structuredClone(this.STATES.UPPER);
|
|
796
|
+
const tempRight = structuredClone(this.STATES.RIGHT);
|
|
797
|
+
const tempDown = structuredClone(this.STATES.DOWN);
|
|
798
|
+
const tempLeft = structuredClone(this.STATES.LEFT);
|
|
799
|
+
const tempFront = structuredClone(this.STATES.FRONT);
|
|
800
|
+
const tempBack = structuredClone(this.STATES.BACK);
|
|
801
|
+
if (clockwise) {
|
|
802
|
+
this.STATES.FRONT = this.switchMatrix(tempFront, true);
|
|
803
|
+
this.STATES.BACK = this.switchMatrix(tempBack, false);
|
|
804
|
+
this.STATES.RIGHT = this.switchMatrix(tempUpper, true);
|
|
805
|
+
this.STATES.DOWN = this.switchMatrix(tempRight, true);
|
|
806
|
+
this.STATES.LEFT = this.switchMatrix(tempDown, true);
|
|
807
|
+
this.STATES.UPPER = this.switchMatrix(tempLeft, true);
|
|
808
|
+
} else {
|
|
809
|
+
this.STATES.FRONT = this.switchMatrix(tempFront, false);
|
|
810
|
+
this.STATES.BACK = this.switchMatrix(tempBack, true);
|
|
811
|
+
this.STATES.RIGHT = this.switchMatrix(tempDown, false);
|
|
812
|
+
this.STATES.DOWN = this.switchMatrix(tempLeft, false);
|
|
813
|
+
this.STATES.LEFT = this.switchMatrix(tempUpper, false);
|
|
814
|
+
this.STATES.UPPER = this.switchMatrix(tempRight, false);
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
rotateY(clockwise = true) {
|
|
818
|
+
const tempFront = structuredClone(this.STATES.FRONT);
|
|
819
|
+
const tempRight = structuredClone(this.STATES.RIGHT);
|
|
820
|
+
const tempBack = structuredClone(this.STATES.BACK);
|
|
821
|
+
const tempLeft = structuredClone(this.STATES.LEFT);
|
|
822
|
+
if (clockwise) {
|
|
823
|
+
this.STATES.UPPER = this.switchMatrix(this.STATES.UPPER, true);
|
|
824
|
+
this.STATES.DOWN = this.switchMatrix(this.STATES.DOWN, false);
|
|
825
|
+
this.STATES.FRONT = [...tempRight];
|
|
826
|
+
this.STATES.RIGHT = [...tempBack];
|
|
827
|
+
this.STATES.LEFT = [...tempFront];
|
|
828
|
+
this.STATES.BACK = [...tempLeft];
|
|
829
|
+
} else {
|
|
830
|
+
this.STATES.UPPER = this.switchMatrix(this.STATES.UPPER, false);
|
|
831
|
+
this.STATES.DOWN = this.switchMatrix(this.STATES.DOWN, true);
|
|
832
|
+
this.STATES.FRONT = [...tempLeft];
|
|
833
|
+
this.STATES.RIGHT = [...tempFront];
|
|
834
|
+
this.STATES.LEFT = [...tempBack];
|
|
835
|
+
this.STATES.BACK = [...tempRight];
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
};
|
|
839
|
+
function buildPerm(size, fnName, clockwise) {
|
|
840
|
+
const oracle = new _OracleCube(size);
|
|
841
|
+
oracle[fnName](clockwise);
|
|
842
|
+
return oracle.flatten();
|
|
843
|
+
}
|
|
844
|
+
function getPerms(size) {
|
|
845
|
+
if (PERM_CACHE.has(size)) return PERM_CACHE.get(size);
|
|
846
|
+
const perms = {};
|
|
847
|
+
for (const key of Object.keys(MOVE_FNS)) {
|
|
848
|
+
perms[key] = {
|
|
849
|
+
cw: buildPerm(size, MOVE_FNS[key], true),
|
|
850
|
+
ccw: buildPerm(size, MOVE_FNS[key], false)
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
PERM_CACHE.set(size, perms);
|
|
854
|
+
return perms;
|
|
855
|
+
}
|
|
856
|
+
function getMovePermutations(size = 3) {
|
|
857
|
+
const allowedSizes = [2, 3];
|
|
858
|
+
return getPerms(allowedSizes.includes(size) ? size : 3);
|
|
859
|
+
}
|
|
860
|
+
var _stickers, _perms, _CubeEngine_instances, initializeState_fn, applyPerm_fn, apply_fn, faceMatrix_fn, applyMovesFromString_fn;
|
|
27
861
|
var CubeEngine = class {
|
|
28
862
|
constructor(initialScramble = "", options = { size: 3 }) {
|
|
29
863
|
__privateAdd(this, _CubeEngine_instances);
|
|
30
864
|
__publicField(this, "MOVES", []);
|
|
31
865
|
__publicField(this, "size", 3);
|
|
866
|
+
__privateAdd(this, _stickers, []);
|
|
867
|
+
__privateAdd(this, _perms, null);
|
|
32
868
|
const allowedSizes = [2, 3];
|
|
33
869
|
this.size = allowedSizes.includes(options.size) ? options.size : 3;
|
|
870
|
+
__privateSet(this, _perms, getPerms(this.size));
|
|
34
871
|
__privateMethod(this, _CubeEngine_instances, initializeState_fn).call(this);
|
|
35
872
|
if (typeof initialScramble === "string" && initialScramble.trim().length > 0) {
|
|
36
873
|
__privateMethod(this, _CubeEngine_instances, applyMovesFromString_fn).call(this, initialScramble, false);
|
|
@@ -41,195 +878,131 @@ var CubeEngine = class {
|
|
|
41
878
|
* Rotates the (UPPER) layer clockwise or counterclockwise.
|
|
42
879
|
*/
|
|
43
880
|
rotateU(clockwise = true) {
|
|
44
|
-
|
|
45
|
-
__privateMethod(this, _CubeEngine_instances, rotateU_fn).call(this, true);
|
|
46
|
-
this.MOVES.push("U");
|
|
47
|
-
} else {
|
|
48
|
-
__privateMethod(this, _CubeEngine_instances, rotateU_fn).call(this, false);
|
|
49
|
-
this.MOVES.push("U'");
|
|
50
|
-
}
|
|
881
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "U", clockwise ? "cw" : "ccw", true);
|
|
51
882
|
}
|
|
52
883
|
/**
|
|
53
884
|
* Rotates the (FRONT) layer clockwise or counterclockwise.
|
|
54
885
|
*/
|
|
55
886
|
rotateF(clockwise = true) {
|
|
56
|
-
|
|
57
|
-
__privateMethod(this, _CubeEngine_instances, rotateF_fn).call(this, true);
|
|
58
|
-
this.MOVES.push("F");
|
|
59
|
-
} else {
|
|
60
|
-
__privateMethod(this, _CubeEngine_instances, rotateF_fn).call(this, false);
|
|
61
|
-
this.MOVES.push("F'");
|
|
62
|
-
}
|
|
887
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "F", clockwise ? "cw" : "ccw", true);
|
|
63
888
|
}
|
|
64
889
|
/**
|
|
65
890
|
* Rotates the (BACK) layer clockwise or counterclockwise.
|
|
66
891
|
*/
|
|
67
892
|
rotateB(clockwise = true) {
|
|
68
|
-
|
|
69
|
-
__privateMethod(this, _CubeEngine_instances, rotateB_fn).call(this, true);
|
|
70
|
-
this.MOVES.push("B");
|
|
71
|
-
} else {
|
|
72
|
-
__privateMethod(this, _CubeEngine_instances, rotateB_fn).call(this, false);
|
|
73
|
-
this.MOVES.push("B'");
|
|
74
|
-
}
|
|
893
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "B", clockwise ? "cw" : "ccw", true);
|
|
75
894
|
}
|
|
76
895
|
/**
|
|
77
896
|
* Rotates the (RIGHT) layer clockwise or counterclockwise.
|
|
78
897
|
*/
|
|
79
898
|
rotateR(clockwise = true) {
|
|
80
|
-
|
|
81
|
-
__privateMethod(this, _CubeEngine_instances, rotateR_fn).call(this, true);
|
|
82
|
-
this.MOVES.push("R");
|
|
83
|
-
} else {
|
|
84
|
-
__privateMethod(this, _CubeEngine_instances, rotateR_fn).call(this, false);
|
|
85
|
-
this.MOVES.push("R'");
|
|
86
|
-
}
|
|
899
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "R", clockwise ? "cw" : "ccw", true);
|
|
87
900
|
}
|
|
88
901
|
/**
|
|
89
902
|
* Rotates the (LEFT) layer clockwise or counterclockwise.
|
|
90
903
|
*/
|
|
91
904
|
rotateL(clockwise = true) {
|
|
92
|
-
|
|
93
|
-
__privateMethod(this, _CubeEngine_instances, rotateL_fn).call(this, true);
|
|
94
|
-
this.MOVES.push("L");
|
|
95
|
-
} else {
|
|
96
|
-
__privateMethod(this, _CubeEngine_instances, rotateL_fn).call(this, false);
|
|
97
|
-
this.MOVES.push("L'");
|
|
98
|
-
}
|
|
905
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "L", clockwise ? "cw" : "ccw", true);
|
|
99
906
|
}
|
|
100
907
|
/**
|
|
101
908
|
* Rotates the (DOWN) layer clockwise or counterclockwise.
|
|
102
909
|
*/
|
|
103
910
|
rotateD(clockwise = true) {
|
|
104
|
-
|
|
105
|
-
__privateMethod(this, _CubeEngine_instances, rotateD_fn).call(this, true);
|
|
106
|
-
this.MOVES.push("D");
|
|
107
|
-
} else {
|
|
108
|
-
__privateMethod(this, _CubeEngine_instances, rotateD_fn).call(this, false);
|
|
109
|
-
this.MOVES.push("D'");
|
|
110
|
-
}
|
|
911
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "D", clockwise ? "cw" : "ccw", true);
|
|
111
912
|
}
|
|
112
913
|
/**
|
|
113
914
|
* Rotates the wide (DOWN two layers) clockwise or counterclockwise.
|
|
114
915
|
*/
|
|
115
916
|
rotateDw(clockwise = true) {
|
|
116
|
-
|
|
117
|
-
if (clockwise) {
|
|
118
|
-
__privateMethod(this, _CubeEngine_instances, rotateDw_fn).call(this, true);
|
|
119
|
-
this.MOVES.push("Dw");
|
|
120
|
-
} else {
|
|
121
|
-
__privateMethod(this, _CubeEngine_instances, rotateDw_fn).call(this, false);
|
|
122
|
-
this.MOVES.push("Dw'");
|
|
123
|
-
}
|
|
917
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "Dw", clockwise ? "cw" : "ccw", true);
|
|
124
918
|
}
|
|
125
919
|
/**
|
|
126
920
|
* Rotates the wide (UPPER two layers) clockwise or counterclockwise.
|
|
127
921
|
*/
|
|
128
922
|
rotateUw(clockwise = true) {
|
|
129
|
-
|
|
130
|
-
if (clockwise) {
|
|
131
|
-
__privateMethod(this, _CubeEngine_instances, rotateUw_fn).call(this, true);
|
|
132
|
-
this.MOVES.push("Uw");
|
|
133
|
-
} else {
|
|
134
|
-
__privateMethod(this, _CubeEngine_instances, rotateUw_fn).call(this, false);
|
|
135
|
-
this.MOVES.push("Uw'");
|
|
136
|
-
}
|
|
923
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "Uw", clockwise ? "cw" : "ccw", true);
|
|
137
924
|
}
|
|
138
925
|
/**
|
|
139
926
|
* Rotates the wide (RIGHT two layers) clockwise or counterclockwise.
|
|
140
927
|
*/
|
|
141
928
|
rotateRw(clockwise = true) {
|
|
142
|
-
|
|
143
|
-
if (clockwise) {
|
|
144
|
-
__privateMethod(this, _CubeEngine_instances, rotateRw_fn).call(this, true);
|
|
145
|
-
this.MOVES.push("Rw");
|
|
146
|
-
} else {
|
|
147
|
-
__privateMethod(this, _CubeEngine_instances, rotateRw_fn).call(this, false);
|
|
148
|
-
this.MOVES.push("Rw'");
|
|
149
|
-
}
|
|
929
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "Rw", clockwise ? "cw" : "ccw", true);
|
|
150
930
|
}
|
|
151
931
|
/**
|
|
152
932
|
* Rotates the wide (LEFT two layers) clockwise or counterclockwise.
|
|
153
933
|
*/
|
|
154
934
|
rotateLw(clockwise = true) {
|
|
155
|
-
|
|
156
|
-
if (clockwise) {
|
|
157
|
-
__privateMethod(this, _CubeEngine_instances, rotateLw_fn).call(this, true);
|
|
158
|
-
this.MOVES.push("Lw");
|
|
159
|
-
} else {
|
|
160
|
-
__privateMethod(this, _CubeEngine_instances, rotateLw_fn).call(this, false);
|
|
161
|
-
this.MOVES.push("Lw'");
|
|
162
|
-
}
|
|
935
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "Lw", clockwise ? "cw" : "ccw", true);
|
|
163
936
|
}
|
|
164
937
|
/**
|
|
165
938
|
* Rotates the middle slice (M) parallel to L/R. Clockwise corresponds to Lw followed by L'.
|
|
166
939
|
*/
|
|
167
940
|
rotateM(clockwise = true) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
941
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "M", clockwise ? "cw" : "ccw", true);
|
|
942
|
+
}
|
|
943
|
+
/**
|
|
944
|
+
* Rotates the equatorial slice (E) parallel to U/D. Clockwise follows the D direction (E = Dw D').
|
|
945
|
+
*/
|
|
946
|
+
rotateE(clockwise = true) {
|
|
947
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "E", clockwise ? "cw" : "ccw", true);
|
|
948
|
+
}
|
|
949
|
+
/**
|
|
950
|
+
* Rotates the wide (FRONT two layers) clockwise or counterclockwise. Equivalent to z B.
|
|
951
|
+
*/
|
|
952
|
+
rotateFw(clockwise = true) {
|
|
953
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "Fw", clockwise ? "cw" : "ccw", true);
|
|
954
|
+
}
|
|
955
|
+
/**
|
|
956
|
+
* Rotates the standing slice (S) parallel to F/B. Clockwise follows the F direction (S = Fw F').
|
|
957
|
+
*/
|
|
958
|
+
rotateS(clockwise = true) {
|
|
959
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "S", clockwise ? "cw" : "ccw", true);
|
|
176
960
|
}
|
|
177
961
|
/**
|
|
178
962
|
* Rotates the (x) axis clockwise or counterclockwise.
|
|
179
963
|
*/
|
|
180
964
|
rotateX(clockwise = true) {
|
|
181
|
-
|
|
182
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, true);
|
|
183
|
-
this.MOVES.push("x");
|
|
184
|
-
} else {
|
|
185
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, false);
|
|
186
|
-
this.MOVES.push("x'");
|
|
187
|
-
}
|
|
965
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "x", clockwise ? "cw" : "ccw", true);
|
|
188
966
|
}
|
|
189
967
|
/**
|
|
190
968
|
* Rotates the (z) axis clockwise or counterclockwise.
|
|
191
969
|
*/
|
|
192
970
|
rotateZ(clockwise = true) {
|
|
193
|
-
|
|
194
|
-
__privateMethod(this, _CubeEngine_instances, rotateZ_fn).call(this, true);
|
|
195
|
-
this.MOVES.push("z");
|
|
196
|
-
} else {
|
|
197
|
-
__privateMethod(this, _CubeEngine_instances, rotateZ_fn).call(this, false);
|
|
198
|
-
this.MOVES.push("z'");
|
|
199
|
-
}
|
|
971
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "z", clockwise ? "cw" : "ccw", true);
|
|
200
972
|
}
|
|
201
973
|
/**
|
|
202
974
|
* Rotates the (y) axis clockwise or counterclockwise.
|
|
203
975
|
*/
|
|
204
976
|
rotateY(clockwise = true) {
|
|
205
|
-
|
|
206
|
-
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, true);
|
|
207
|
-
this.MOVES.push("y");
|
|
208
|
-
} else {
|
|
209
|
-
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, false);
|
|
210
|
-
this.MOVES.push("y'");
|
|
211
|
-
}
|
|
977
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, "y", clockwise ? "cw" : "ccw", true);
|
|
212
978
|
}
|
|
213
979
|
/**
|
|
214
980
|
* Logs the current state of the cube.
|
|
215
981
|
*/
|
|
216
982
|
state() {
|
|
217
|
-
return
|
|
983
|
+
return {
|
|
984
|
+
UPPER: __privateMethod(this, _CubeEngine_instances, faceMatrix_fn).call(this, 0),
|
|
985
|
+
LEFT: __privateMethod(this, _CubeEngine_instances, faceMatrix_fn).call(this, 1),
|
|
986
|
+
FRONT: __privateMethod(this, _CubeEngine_instances, faceMatrix_fn).call(this, 2),
|
|
987
|
+
RIGHT: __privateMethod(this, _CubeEngine_instances, faceMatrix_fn).call(this, 3),
|
|
988
|
+
BACK: __privateMethod(this, _CubeEngine_instances, faceMatrix_fn).call(this, 4),
|
|
989
|
+
DOWN: __privateMethod(this, _CubeEngine_instances, faceMatrix_fn).call(this, 5)
|
|
990
|
+
};
|
|
218
991
|
}
|
|
219
992
|
/**
|
|
220
993
|
* Indicates if the cube is solve or not in all layers.
|
|
221
994
|
*/
|
|
222
995
|
isSolved() {
|
|
223
|
-
const
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
996
|
+
const per = this.size * this.size;
|
|
997
|
+
const centerOffset = this.size === 2 ? 0 : 4;
|
|
998
|
+
for (let f = 0; f < FACE_COLORS.length; f++) {
|
|
999
|
+
const base = f * per;
|
|
1000
|
+
const centerColor = __privateGet(this, _stickers)[base + centerOffset];
|
|
1001
|
+
for (let i = 0; i < per; i++) {
|
|
1002
|
+
if (__privateGet(this, _stickers)[base + i] !== centerColor) return false;
|
|
228
1003
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
});
|
|
232
|
-
return layersSolved.every((isLayerSolved) => isLayerSolved);
|
|
1004
|
+
}
|
|
1005
|
+
return true;
|
|
233
1006
|
}
|
|
234
1007
|
/**
|
|
235
1008
|
* Returns the history of all movements made.
|
|
@@ -249,8 +1022,8 @@ var CubeEngine = class {
|
|
|
249
1022
|
}
|
|
250
1023
|
/**
|
|
251
1024
|
* Applies a sequence of moves provided as a string.
|
|
252
|
-
* Supports: U, D, L, R, F, x, y, z; slice moves: M; and wide moves: Dw, Uw, Rw, Lw with optional ' for counterclockwise and 2 for double turns.
|
|
253
|
-
* @param {string} sequence - e.g. "R U' F R2 D Dw Uw Rw Rw' Lw Lw2 M M' M2"
|
|
1025
|
+
* Supports: U, D, L, R, F, B, x, y, z; slice moves: M, E, S; and wide moves: Dw, Uw, Rw, Lw, Fw with optional ' for counterclockwise and 2 for double turns.
|
|
1026
|
+
* @param {string} sequence - e.g. "R U' F R2 D Dw Uw Rw Rw' Lw Lw2 M M' M2 E E' S S2 Fw"
|
|
254
1027
|
* @param {object} options - { record: boolean } whether to record moves in history (default true)
|
|
255
1028
|
*/
|
|
256
1029
|
applyMoves(sequence, options = { record: false }) {
|
|
@@ -258,269 +1031,51 @@ var CubeEngine = class {
|
|
|
258
1031
|
__privateMethod(this, _CubeEngine_instances, applyMovesFromString_fn).call(this, sequence, record);
|
|
259
1032
|
}
|
|
260
1033
|
};
|
|
1034
|
+
_stickers = new WeakMap();
|
|
1035
|
+
_perms = new WeakMap();
|
|
261
1036
|
_CubeEngine_instances = new WeakSet();
|
|
262
1037
|
initializeState_fn = function() {
|
|
263
|
-
this.
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
};
|
|
271
|
-
};
|
|
272
|
-
// Create a face matrix based on cube size
|
|
273
|
-
createFace_fn = function(color) {
|
|
274
|
-
const face = [];
|
|
275
|
-
for (let i = 0; i < this.size; i++) {
|
|
276
|
-
const row = [];
|
|
277
|
-
for (let j = 0; j < this.size; j++) {
|
|
278
|
-
row.push(color);
|
|
1038
|
+
const per = this.size * this.size;
|
|
1039
|
+
const stickers = new Array(FACE_COLORS.length * per);
|
|
1040
|
+
for (let f = 0; f < FACE_COLORS.length; f++) {
|
|
1041
|
+
const color = FACE_COLORS[f];
|
|
1042
|
+
const base = f * per;
|
|
1043
|
+
for (let i = 0; i < per; i++) {
|
|
1044
|
+
stickers[base + i] = color;
|
|
279
1045
|
}
|
|
280
|
-
face.push(row);
|
|
281
|
-
}
|
|
282
|
-
return face;
|
|
283
|
-
};
|
|
284
|
-
rotateU_fn = function(clockwise = true) {
|
|
285
|
-
if (clockwise) {
|
|
286
|
-
this.STATES.UPPER = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, this.STATES.UPPER, true);
|
|
287
|
-
const tempFront = [...this.STATES.FRONT[0]];
|
|
288
|
-
const tempRight = [...this.STATES.RIGHT[0]];
|
|
289
|
-
const tempLeft = [...this.STATES.LEFT[0]];
|
|
290
|
-
const tempBack = [...this.STATES.BACK[0]];
|
|
291
|
-
this.STATES.FRONT[0] = [...tempRight];
|
|
292
|
-
this.STATES.LEFT[0] = [...tempFront];
|
|
293
|
-
this.STATES.BACK[0] = [...tempLeft];
|
|
294
|
-
this.STATES.RIGHT[0] = [...tempBack];
|
|
295
|
-
} else {
|
|
296
|
-
this.STATES.UPPER = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, this.STATES.UPPER, false);
|
|
297
|
-
const tempFront = [...this.STATES.FRONT[0]];
|
|
298
|
-
const tempRight = [...this.STATES.RIGHT[0]];
|
|
299
|
-
const tempLeft = [...this.STATES.LEFT[0]];
|
|
300
|
-
const tempBack = [...this.STATES.BACK[0]];
|
|
301
|
-
this.STATES.FRONT[0] = [...tempLeft];
|
|
302
|
-
this.STATES.LEFT[0] = [...tempBack];
|
|
303
|
-
this.STATES.BACK[0] = [...tempRight];
|
|
304
|
-
this.STATES.RIGHT[0] = [...tempFront];
|
|
305
|
-
}
|
|
306
|
-
};
|
|
307
|
-
rotateF_fn = function(clockwise = true) {
|
|
308
|
-
if (clockwise) {
|
|
309
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, true);
|
|
310
|
-
__privateMethod(this, _CubeEngine_instances, rotateU_fn).call(this, true);
|
|
311
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, false);
|
|
312
|
-
} else {
|
|
313
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, true);
|
|
314
|
-
__privateMethod(this, _CubeEngine_instances, rotateU_fn).call(this, false);
|
|
315
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, false);
|
|
316
|
-
}
|
|
317
|
-
};
|
|
318
|
-
rotateB_fn = function(clockwise = true) {
|
|
319
|
-
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, true);
|
|
320
|
-
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, true);
|
|
321
|
-
if (clockwise) {
|
|
322
|
-
__privateMethod(this, _CubeEngine_instances, rotateF_fn).call(this, true);
|
|
323
|
-
} else {
|
|
324
|
-
__privateMethod(this, _CubeEngine_instances, rotateF_fn).call(this, false);
|
|
325
|
-
}
|
|
326
|
-
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, false);
|
|
327
|
-
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, false);
|
|
328
|
-
};
|
|
329
|
-
rotateR_fn = function(clockwise = true) {
|
|
330
|
-
if (clockwise) {
|
|
331
|
-
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, true);
|
|
332
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, true);
|
|
333
|
-
__privateMethod(this, _CubeEngine_instances, rotateU_fn).call(this, true);
|
|
334
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, false);
|
|
335
|
-
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, false);
|
|
336
|
-
} else {
|
|
337
|
-
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, true);
|
|
338
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, true);
|
|
339
|
-
__privateMethod(this, _CubeEngine_instances, rotateU_fn).call(this, false);
|
|
340
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, false);
|
|
341
|
-
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, false);
|
|
342
|
-
}
|
|
343
|
-
};
|
|
344
|
-
rotateL_fn = function(clockwise = true) {
|
|
345
|
-
if (clockwise) {
|
|
346
|
-
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, false);
|
|
347
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, true);
|
|
348
|
-
__privateMethod(this, _CubeEngine_instances, rotateU_fn).call(this, true);
|
|
349
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, false);
|
|
350
|
-
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, true);
|
|
351
|
-
} else {
|
|
352
|
-
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, false);
|
|
353
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, true);
|
|
354
|
-
__privateMethod(this, _CubeEngine_instances, rotateU_fn).call(this, false);
|
|
355
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, false);
|
|
356
|
-
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, true);
|
|
357
|
-
}
|
|
358
|
-
};
|
|
359
|
-
rotateD_fn = function(clockwise = true) {
|
|
360
|
-
if (clockwise) {
|
|
361
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, true);
|
|
362
|
-
__privateMethod(this, _CubeEngine_instances, rotateF_fn).call(this, true);
|
|
363
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, false);
|
|
364
|
-
} else {
|
|
365
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, true);
|
|
366
|
-
__privateMethod(this, _CubeEngine_instances, rotateF_fn).call(this, false);
|
|
367
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, false);
|
|
368
|
-
}
|
|
369
|
-
};
|
|
370
|
-
rotateDw_fn = function(clockwise = true) {
|
|
371
|
-
if (clockwise) {
|
|
372
|
-
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, false);
|
|
373
|
-
__privateMethod(this, _CubeEngine_instances, rotateU_fn).call(this, true);
|
|
374
|
-
} else {
|
|
375
|
-
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, true);
|
|
376
|
-
__privateMethod(this, _CubeEngine_instances, rotateU_fn).call(this, false);
|
|
377
1046
|
}
|
|
1047
|
+
__privateSet(this, _stickers, stickers);
|
|
378
1048
|
};
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
__privateMethod(this, _CubeEngine_instances, rotateD_fn).call(this, false);
|
|
1049
|
+
// Apply a precomputed permutation: newState[i] = oldState[perm[i]].
|
|
1050
|
+
applyPerm_fn = function(perm) {
|
|
1051
|
+
const current = __privateGet(this, _stickers);
|
|
1052
|
+
const next = new Array(current.length);
|
|
1053
|
+
for (let i = 0; i < current.length; i++) {
|
|
1054
|
+
next[i] = current[perm[i]];
|
|
386
1055
|
}
|
|
1056
|
+
__privateSet(this, _stickers, next);
|
|
387
1057
|
};
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, false);
|
|
394
|
-
__privateMethod(this, _CubeEngine_instances, rotateL_fn).call(this, false);
|
|
395
|
-
}
|
|
1058
|
+
// Core move dispatch. dir is "cw" or "ccw"; record controls history logging.
|
|
1059
|
+
apply_fn = function(key, dir, record) {
|
|
1060
|
+
if (this.size === 2 && NOOP_SIZE2.has(key)) return;
|
|
1061
|
+
__privateMethod(this, _CubeEngine_instances, applyPerm_fn).call(this, __privateGet(this, _perms)[key][dir]);
|
|
1062
|
+
if (record) this.MOVES.push(dir === "ccw" ? key + "'" : key);
|
|
396
1063
|
};
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, false);
|
|
400
|
-
__privateMethod(this, _CubeEngine_instances, rotateR_fn).call(this, true);
|
|
401
|
-
} else {
|
|
402
|
-
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, true);
|
|
403
|
-
__privateMethod(this, _CubeEngine_instances, rotateR_fn).call(this, false);
|
|
404
|
-
}
|
|
405
|
-
};
|
|
406
|
-
rotateM_fn = function(clockwise = true) {
|
|
407
|
-
if (clockwise) {
|
|
408
|
-
__privateMethod(this, _CubeEngine_instances, rotateLw_fn).call(this, true);
|
|
409
|
-
__privateMethod(this, _CubeEngine_instances, rotateL_fn).call(this, false);
|
|
410
|
-
} else {
|
|
411
|
-
__privateMethod(this, _CubeEngine_instances, rotateLw_fn).call(this, false);
|
|
412
|
-
__privateMethod(this, _CubeEngine_instances, rotateL_fn).call(this, true);
|
|
413
|
-
}
|
|
414
|
-
};
|
|
415
|
-
rotateX_fn = function(clockwise = true) {
|
|
416
|
-
const tempFront = structuredClone(this.STATES.FRONT);
|
|
417
|
-
const tempDown = structuredClone(this.STATES.DOWN);
|
|
418
|
-
const tempUpper = structuredClone(this.STATES.UPPER);
|
|
419
|
-
const tempBack = structuredClone(this.STATES.BACK);
|
|
420
|
-
const tempLeft = structuredClone(this.STATES.LEFT);
|
|
421
|
-
const tempRight = structuredClone(this.STATES.RIGHT);
|
|
422
|
-
if (clockwise) {
|
|
423
|
-
this.STATES.LEFT = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempLeft, false);
|
|
424
|
-
this.STATES.RIGHT = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempRight, true);
|
|
425
|
-
this.STATES.FRONT = [...tempDown];
|
|
426
|
-
this.STATES.UPPER = [...tempFront];
|
|
427
|
-
this.STATES.BACK = __privateMethod(this, _CubeEngine_instances, specialFlip_fn).call(this, tempUpper);
|
|
428
|
-
this.STATES.DOWN = __privateMethod(this, _CubeEngine_instances, specialFlip_fn).call(this, tempBack);
|
|
429
|
-
} else {
|
|
430
|
-
this.STATES.LEFT = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempLeft, true);
|
|
431
|
-
this.STATES.RIGHT = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempRight, false);
|
|
432
|
-
this.STATES.FRONT = [...tempUpper];
|
|
433
|
-
this.STATES.DOWN = [...tempFront];
|
|
434
|
-
this.STATES.BACK = __privateMethod(this, _CubeEngine_instances, specialFlip_fn).call(this, tempDown);
|
|
435
|
-
this.STATES.UPPER = __privateMethod(this, _CubeEngine_instances, specialFlip_fn).call(this, tempBack);
|
|
436
|
-
}
|
|
437
|
-
};
|
|
438
|
-
rotateZ_fn = function(clockwise = true) {
|
|
439
|
-
const tempUpper = structuredClone(this.STATES.UPPER);
|
|
440
|
-
const tempRight = structuredClone(this.STATES.RIGHT);
|
|
441
|
-
const tempDown = structuredClone(this.STATES.DOWN);
|
|
442
|
-
const tempLeft = structuredClone(this.STATES.LEFT);
|
|
443
|
-
const tempFront = structuredClone(this.STATES.FRONT);
|
|
444
|
-
const tempBack = structuredClone(this.STATES.BACK);
|
|
445
|
-
if (clockwise) {
|
|
446
|
-
this.STATES.FRONT = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempFront, true);
|
|
447
|
-
this.STATES.BACK = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempBack, false);
|
|
448
|
-
this.STATES.RIGHT = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempUpper, true);
|
|
449
|
-
this.STATES.DOWN = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempRight, true);
|
|
450
|
-
this.STATES.LEFT = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempDown, true);
|
|
451
|
-
this.STATES.UPPER = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempLeft, true);
|
|
452
|
-
} else {
|
|
453
|
-
this.STATES.FRONT = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempFront, false);
|
|
454
|
-
this.STATES.BACK = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempBack, true);
|
|
455
|
-
this.STATES.RIGHT = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempDown, false);
|
|
456
|
-
this.STATES.DOWN = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempLeft, false);
|
|
457
|
-
this.STATES.LEFT = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempUpper, false);
|
|
458
|
-
this.STATES.UPPER = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempRight, false);
|
|
459
|
-
}
|
|
460
|
-
};
|
|
461
|
-
rotateY_fn = function(clockwise = true) {
|
|
462
|
-
const tempFront = structuredClone(this.STATES.FRONT);
|
|
463
|
-
const tempRight = structuredClone(this.STATES.RIGHT);
|
|
464
|
-
const tempBack = structuredClone(this.STATES.BACK);
|
|
465
|
-
const tempLeft = structuredClone(this.STATES.LEFT);
|
|
466
|
-
if (clockwise) {
|
|
467
|
-
this.STATES.UPPER = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, this.STATES.UPPER, true);
|
|
468
|
-
this.STATES.DOWN = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, this.STATES.DOWN, false);
|
|
469
|
-
this.STATES.FRONT = [...tempRight];
|
|
470
|
-
this.STATES.RIGHT = [...tempBack];
|
|
471
|
-
this.STATES.LEFT = [...tempFront];
|
|
472
|
-
this.STATES.BACK = [...tempLeft];
|
|
473
|
-
} else {
|
|
474
|
-
this.STATES.UPPER = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, this.STATES.UPPER, false);
|
|
475
|
-
this.STATES.DOWN = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, this.STATES.DOWN, true);
|
|
476
|
-
this.STATES.FRONT = [...tempLeft];
|
|
477
|
-
this.STATES.RIGHT = [...tempFront];
|
|
478
|
-
this.STATES.LEFT = [...tempBack];
|
|
479
|
-
this.STATES.BACK = [...tempRight];
|
|
480
|
-
}
|
|
481
|
-
};
|
|
482
|
-
/**
|
|
483
|
-
* Rotate the entire face in the direction set
|
|
484
|
-
*/
|
|
485
|
-
switchMatrix_fn = function(matrix, clockwise = true) {
|
|
486
|
-
const clone = structuredClone(matrix);
|
|
1064
|
+
// Build a single face matrix from the flat sticker array.
|
|
1065
|
+
faceMatrix_fn = function(faceIndex) {
|
|
487
1066
|
const size = this.size;
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
return [
|
|
495
|
-
[tempMatrix[2], tempMatrix[0]],
|
|
496
|
-
[tempMatrix[3], tempMatrix[1]]
|
|
497
|
-
];
|
|
498
|
-
} else {
|
|
499
|
-
return [
|
|
500
|
-
[tempMatrix[1], tempMatrix[3]],
|
|
501
|
-
[tempMatrix[0], tempMatrix[2]]
|
|
502
|
-
];
|
|
503
|
-
}
|
|
504
|
-
} else {
|
|
505
|
-
if (clockwise) {
|
|
506
|
-
return [
|
|
507
|
-
[tempMatrix[6], tempMatrix[3], tempMatrix[0]],
|
|
508
|
-
[tempMatrix[7], tempMatrix[4], tempMatrix[1]],
|
|
509
|
-
[tempMatrix[8], tempMatrix[5], tempMatrix[2]]
|
|
510
|
-
];
|
|
511
|
-
} else {
|
|
512
|
-
return [
|
|
513
|
-
[tempMatrix[2], tempMatrix[5], tempMatrix[8]],
|
|
514
|
-
[tempMatrix[1], tempMatrix[4], tempMatrix[7]],
|
|
515
|
-
[tempMatrix[0], tempMatrix[3], tempMatrix[6]]
|
|
516
|
-
];
|
|
1067
|
+
const base = faceIndex * size * size;
|
|
1068
|
+
const matrix = [];
|
|
1069
|
+
for (let r = 0; r < size; r++) {
|
|
1070
|
+
const row = [];
|
|
1071
|
+
for (let c = 0; c < size; c++) {
|
|
1072
|
+
row.push(__privateGet(this, _stickers)[base + r * size + c]);
|
|
517
1073
|
}
|
|
1074
|
+
matrix.push(row);
|
|
518
1075
|
}
|
|
1076
|
+
return matrix;
|
|
519
1077
|
};
|
|
520
|
-
|
|
521
|
-
return structuredClone(matrix).reverse().map((row) => [...row].reverse());
|
|
522
|
-
};
|
|
523
|
-
// Internal: parses and applies moves. If record=false, uses private methods to avoid logging.
|
|
1078
|
+
// Internal: parses and applies moves, optionally recording them in history.
|
|
524
1079
|
applyMovesFromString_fn = function(sequence, record = true) {
|
|
525
1080
|
if (typeof sequence !== "string") return;
|
|
526
1081
|
const tokens = sequence.split(/\s+/).map((t) => t.trim()).filter((t) => t.length > 0);
|
|
@@ -529,121 +1084,55 @@ applyMovesFromString_fn = function(sequence, record = true) {
|
|
|
529
1084
|
const rest = token.slice(1);
|
|
530
1085
|
const isDouble = rest.includes("2");
|
|
531
1086
|
const isPrime = rest.includes("'");
|
|
532
|
-
const
|
|
533
|
-
|
|
534
|
-
fnClockwise();
|
|
535
|
-
fnClockwise();
|
|
536
|
-
} else {
|
|
537
|
-
if (isPrime) {
|
|
538
|
-
fnCounter();
|
|
539
|
-
} else {
|
|
540
|
-
fnClockwise();
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
};
|
|
1087
|
+
const isWide = /w/i.test(rest);
|
|
1088
|
+
let key;
|
|
544
1089
|
switch (base) {
|
|
545
1090
|
case "U":
|
|
546
|
-
|
|
547
|
-
const isWide = /w/i.test(rest);
|
|
548
|
-
if (isWide) {
|
|
549
|
-
exec(
|
|
550
|
-
() => record ? this.rotateUw(true) : __privateMethod(this, _CubeEngine_instances, rotateUw_fn).call(this, true),
|
|
551
|
-
() => record ? this.rotateUw(false) : __privateMethod(this, _CubeEngine_instances, rotateUw_fn).call(this, false)
|
|
552
|
-
);
|
|
553
|
-
} else {
|
|
554
|
-
exec(
|
|
555
|
-
() => record ? this.rotateU(true) : __privateMethod(this, _CubeEngine_instances, rotateU_fn).call(this, true),
|
|
556
|
-
() => record ? this.rotateU(false) : __privateMethod(this, _CubeEngine_instances, rotateU_fn).call(this, false)
|
|
557
|
-
);
|
|
558
|
-
}
|
|
559
|
-
}
|
|
1091
|
+
key = isWide ? "Uw" : "U";
|
|
560
1092
|
break;
|
|
561
1093
|
case "D":
|
|
562
|
-
|
|
563
|
-
const isWide = /w/i.test(rest);
|
|
564
|
-
if (isWide) {
|
|
565
|
-
exec(
|
|
566
|
-
() => record ? this.rotateDw(true) : __privateMethod(this, _CubeEngine_instances, rotateDw_fn).call(this, true),
|
|
567
|
-
() => record ? this.rotateDw(false) : __privateMethod(this, _CubeEngine_instances, rotateDw_fn).call(this, false)
|
|
568
|
-
);
|
|
569
|
-
} else {
|
|
570
|
-
exec(
|
|
571
|
-
() => record ? this.rotateD(true) : __privateMethod(this, _CubeEngine_instances, rotateD_fn).call(this, true),
|
|
572
|
-
() => record ? this.rotateD(false) : __privateMethod(this, _CubeEngine_instances, rotateD_fn).call(this, false)
|
|
573
|
-
);
|
|
574
|
-
}
|
|
575
|
-
}
|
|
1094
|
+
key = isWide ? "Dw" : "D";
|
|
576
1095
|
break;
|
|
577
1096
|
case "L":
|
|
578
|
-
|
|
579
|
-
const isWide = /w/i.test(rest);
|
|
580
|
-
if (isWide) {
|
|
581
|
-
exec(
|
|
582
|
-
() => record ? this.rotateLw(true) : __privateMethod(this, _CubeEngine_instances, rotateLw_fn).call(this, true),
|
|
583
|
-
() => record ? this.rotateLw(false) : __privateMethod(this, _CubeEngine_instances, rotateLw_fn).call(this, false)
|
|
584
|
-
);
|
|
585
|
-
} else {
|
|
586
|
-
exec(
|
|
587
|
-
() => record ? this.rotateL(true) : __privateMethod(this, _CubeEngine_instances, rotateL_fn).call(this, true),
|
|
588
|
-
() => record ? this.rotateL(false) : __privateMethod(this, _CubeEngine_instances, rotateL_fn).call(this, false)
|
|
589
|
-
);
|
|
590
|
-
}
|
|
591
|
-
}
|
|
1097
|
+
key = isWide ? "Lw" : "L";
|
|
592
1098
|
break;
|
|
593
1099
|
case "R":
|
|
594
|
-
|
|
595
|
-
const isWide = /w/i.test(rest);
|
|
596
|
-
if (isWide) {
|
|
597
|
-
exec(
|
|
598
|
-
() => record ? this.rotateRw(true) : __privateMethod(this, _CubeEngine_instances, rotateRw_fn).call(this, true),
|
|
599
|
-
() => record ? this.rotateRw(false) : __privateMethod(this, _CubeEngine_instances, rotateRw_fn).call(this, false)
|
|
600
|
-
);
|
|
601
|
-
} else {
|
|
602
|
-
exec(
|
|
603
|
-
() => record ? this.rotateR(true) : __privateMethod(this, _CubeEngine_instances, rotateR_fn).call(this, true),
|
|
604
|
-
() => record ? this.rotateR(false) : __privateMethod(this, _CubeEngine_instances, rotateR_fn).call(this, false)
|
|
605
|
-
);
|
|
606
|
-
}
|
|
607
|
-
}
|
|
1100
|
+
key = isWide ? "Rw" : "R";
|
|
608
1101
|
break;
|
|
609
1102
|
case "F":
|
|
610
|
-
|
|
611
|
-
() => record ? this.rotateF(true) : __privateMethod(this, _CubeEngine_instances, rotateF_fn).call(this, true),
|
|
612
|
-
() => record ? this.rotateF(false) : __privateMethod(this, _CubeEngine_instances, rotateF_fn).call(this, false)
|
|
613
|
-
);
|
|
1103
|
+
key = isWide ? "Fw" : "F";
|
|
614
1104
|
break;
|
|
615
1105
|
case "B":
|
|
616
|
-
|
|
617
|
-
() => record ? this.rotateB(true) : __privateMethod(this, _CubeEngine_instances, rotateB_fn).call(this, true),
|
|
618
|
-
() => record ? this.rotateB(false) : __privateMethod(this, _CubeEngine_instances, rotateB_fn).call(this, false)
|
|
619
|
-
);
|
|
1106
|
+
key = "B";
|
|
620
1107
|
break;
|
|
621
1108
|
case "x":
|
|
622
|
-
|
|
623
|
-
() => record ? this.rotateX(true) : __privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, true),
|
|
624
|
-
() => record ? this.rotateX(false) : __privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, false)
|
|
625
|
-
);
|
|
1109
|
+
key = "x";
|
|
626
1110
|
break;
|
|
627
1111
|
case "y":
|
|
628
|
-
|
|
629
|
-
() => record ? this.rotateY(true) : __privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, true),
|
|
630
|
-
() => record ? this.rotateY(false) : __privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, false)
|
|
631
|
-
);
|
|
1112
|
+
key = "y";
|
|
632
1113
|
break;
|
|
633
1114
|
case "z":
|
|
634
|
-
|
|
635
|
-
() => record ? this.rotateZ(true) : __privateMethod(this, _CubeEngine_instances, rotateZ_fn).call(this, true),
|
|
636
|
-
() => record ? this.rotateZ(false) : __privateMethod(this, _CubeEngine_instances, rotateZ_fn).call(this, false)
|
|
637
|
-
);
|
|
1115
|
+
key = "z";
|
|
638
1116
|
break;
|
|
639
1117
|
case "M":
|
|
640
|
-
|
|
641
|
-
() => record ? this.rotateM(true) : __privateMethod(this, _CubeEngine_instances, rotateM_fn).call(this, true),
|
|
642
|
-
() => record ? this.rotateM(false) : __privateMethod(this, _CubeEngine_instances, rotateM_fn).call(this, false)
|
|
643
|
-
);
|
|
1118
|
+
key = "M";
|
|
644
1119
|
break;
|
|
645
|
-
|
|
1120
|
+
case "E":
|
|
1121
|
+
key = "E";
|
|
646
1122
|
break;
|
|
1123
|
+
case "S":
|
|
1124
|
+
key = "S";
|
|
1125
|
+
break;
|
|
1126
|
+
default:
|
|
1127
|
+
continue;
|
|
1128
|
+
}
|
|
1129
|
+
if (isDouble) {
|
|
1130
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, key, "cw", record);
|
|
1131
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, key, "cw", record);
|
|
1132
|
+
} else if (isPrime) {
|
|
1133
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, key, "ccw", record);
|
|
1134
|
+
} else {
|
|
1135
|
+
__privateMethod(this, _CubeEngine_instances, apply_fn).call(this, key, "cw", record);
|
|
647
1136
|
}
|
|
648
1137
|
}
|
|
649
1138
|
};
|
|
@@ -657,5 +1146,9 @@ var COLOR = {
|
|
|
657
1146
|
};
|
|
658
1147
|
export {
|
|
659
1148
|
COLOR,
|
|
660
|
-
CubeEngine
|
|
1149
|
+
CubeEngine,
|
|
1150
|
+
analyzeSolution,
|
|
1151
|
+
getMovePermutations,
|
|
1152
|
+
invertSequence,
|
|
1153
|
+
simplifyMoves
|
|
661
1154
|
};
|