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