cube-state-engine 1.0.4 → 1.1.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/.idea/cube-state-engine.iml +12 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/README.md +36 -14
- package/dist/index.d.mts +308 -1
- package/dist/index.d.ts +308 -1
- package/dist/index.js +279 -3
- package/dist/index.mjs +279 -3
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
class CubeEngine {
|
|
2
2
|
MOVES = [];
|
|
3
3
|
|
|
4
|
+
constructor(initialScramble) {
|
|
5
|
+
// If an initial scramble string is provided, apply it without recording moves
|
|
6
|
+
if (typeof initialScramble === "string" && initialScramble.trim().length > 0) {
|
|
7
|
+
this.#applyMovesFromString(initialScramble, false);
|
|
8
|
+
// Ensure history is empty for initial position
|
|
9
|
+
this.MOVES = [];
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
4
13
|
// States object for the rotation
|
|
5
14
|
STATES = {
|
|
6
15
|
UPPER: [
|
|
@@ -190,6 +199,122 @@ class CubeEngine {
|
|
|
190
199
|
}
|
|
191
200
|
}
|
|
192
201
|
|
|
202
|
+
/**
|
|
203
|
+
* Rotates the wide (DOWN two layers) clockwise or counterclockwise.
|
|
204
|
+
*/
|
|
205
|
+
rotateDw(clockwise = true) {
|
|
206
|
+
if (clockwise) {
|
|
207
|
+
this.#rotateDw(true);
|
|
208
|
+
this.MOVES.push("Dw");
|
|
209
|
+
} else {
|
|
210
|
+
this.#rotateDw(false);
|
|
211
|
+
this.MOVES.push("Dw'");
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
#rotateDw(clockwise = true) {
|
|
216
|
+
if (clockwise) {
|
|
217
|
+
this.#rotateY(false);
|
|
218
|
+
this.#rotateU(true);
|
|
219
|
+
} else {
|
|
220
|
+
this.#rotateY(true);
|
|
221
|
+
this.#rotateU(false);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Rotates the wide (UPPER two layers) clockwise or counterclockwise.
|
|
227
|
+
*/
|
|
228
|
+
rotateUw(clockwise = true) {
|
|
229
|
+
if (clockwise) {
|
|
230
|
+
this.#rotateUw(true);
|
|
231
|
+
this.MOVES.push("Uw");
|
|
232
|
+
} else {
|
|
233
|
+
this.#rotateUw(false);
|
|
234
|
+
this.MOVES.push("Uw'");
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
#rotateUw(clockwise = true) {
|
|
239
|
+
if (clockwise) {
|
|
240
|
+
this.#rotateY(true);
|
|
241
|
+
this.#rotateD(true);
|
|
242
|
+
} else {
|
|
243
|
+
this.#rotateY(false);
|
|
244
|
+
this.#rotateD(false);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Rotates the wide (RIGHT two layers) clockwise or counterclockwise.
|
|
250
|
+
*/
|
|
251
|
+
rotateRw(clockwise = true) {
|
|
252
|
+
if (clockwise) {
|
|
253
|
+
this.#rotateRw(true);
|
|
254
|
+
this.MOVES.push("Rw");
|
|
255
|
+
} else {
|
|
256
|
+
this.#rotateRw(false);
|
|
257
|
+
this.MOVES.push("Rw'");
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
#rotateRw(clockwise = true) {
|
|
262
|
+
if (clockwise) {
|
|
263
|
+
this.#rotateX(true);
|
|
264
|
+
this.#rotateL(true);
|
|
265
|
+
} else {
|
|
266
|
+
this.#rotateX(false);
|
|
267
|
+
this.#rotateL(false);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Rotates the wide (LEFT two layers) clockwise or counterclockwise.
|
|
273
|
+
*/
|
|
274
|
+
rotateLw(clockwise = true) {
|
|
275
|
+
if (clockwise) {
|
|
276
|
+
this.#rotateLw(true);
|
|
277
|
+
this.MOVES.push("Lw");
|
|
278
|
+
} else {
|
|
279
|
+
this.#rotateLw(false);
|
|
280
|
+
this.MOVES.push("Lw'");
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
#rotateLw(clockwise = true) {
|
|
285
|
+
if (clockwise) {
|
|
286
|
+
// Lw equals x' R
|
|
287
|
+
this.#rotateX(false);
|
|
288
|
+
this.#rotateR(true);
|
|
289
|
+
} else {
|
|
290
|
+
this.#rotateX(true);
|
|
291
|
+
this.#rotateR(false);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Rotates the middle slice (M) parallel to L/R. Clockwise corresponds to Lw followed by L'.
|
|
297
|
+
*/
|
|
298
|
+
rotateM(clockwise = true) {
|
|
299
|
+
if (clockwise) {
|
|
300
|
+
this.#rotateM(true);
|
|
301
|
+
this.MOVES.push("M");
|
|
302
|
+
} else {
|
|
303
|
+
this.#rotateM(false);
|
|
304
|
+
this.MOVES.push("M'");
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
#rotateM(clockwise = true) {
|
|
309
|
+
if (clockwise) {
|
|
310
|
+
this.#rotateLw(true);
|
|
311
|
+
this.#rotateL(false);
|
|
312
|
+
} else {
|
|
313
|
+
this.#rotateLw(false);
|
|
314
|
+
this.#rotateL(true);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
193
318
|
/**
|
|
194
319
|
* Rotates the (x) axis clockwise or counterclockwise.
|
|
195
320
|
*/
|
|
@@ -235,6 +360,50 @@ class CubeEngine {
|
|
|
235
360
|
}
|
|
236
361
|
}
|
|
237
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Rotates the (z) axis clockwise or counterclockwise.
|
|
365
|
+
*/
|
|
366
|
+
rotateZ(clockwise = true) {
|
|
367
|
+
if (clockwise) {
|
|
368
|
+
this.#rotateZ(true);
|
|
369
|
+
this.MOVES.push("z");
|
|
370
|
+
} else {
|
|
371
|
+
this.#rotateZ(false);
|
|
372
|
+
this.MOVES.push("z'");
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
#rotateZ(clockwise = true) {
|
|
377
|
+
const tempUpper = structuredClone(this.STATES.UPPER);
|
|
378
|
+
const tempRight = structuredClone(this.STATES.RIGHT);
|
|
379
|
+
const tempDown = structuredClone(this.STATES.DOWN);
|
|
380
|
+
const tempLeft = structuredClone(this.STATES.LEFT);
|
|
381
|
+
const tempFront = structuredClone(this.STATES.FRONT);
|
|
382
|
+
const tempBack = structuredClone(this.STATES.BACK);
|
|
383
|
+
|
|
384
|
+
if (clockwise) {
|
|
385
|
+
// Rotate faces on the rotation axis
|
|
386
|
+
this.STATES.FRONT = this.#switchMatrix(tempFront, true);
|
|
387
|
+
this.STATES.BACK = this.#switchMatrix(tempBack, false);
|
|
388
|
+
|
|
389
|
+
// Cycle U -> R -> D -> L -> U with proper orientation
|
|
390
|
+
this.STATES.RIGHT = this.#switchMatrix(tempUpper, true);
|
|
391
|
+
this.STATES.DOWN = this.#switchMatrix(tempRight, true);
|
|
392
|
+
this.STATES.LEFT = this.#switchMatrix(tempDown, true);
|
|
393
|
+
this.STATES.UPPER = this.#switchMatrix(tempLeft, true);
|
|
394
|
+
} else {
|
|
395
|
+
// Counterclockwise
|
|
396
|
+
this.STATES.FRONT = this.#switchMatrix(tempFront, false);
|
|
397
|
+
this.STATES.BACK = this.#switchMatrix(tempBack, true);
|
|
398
|
+
|
|
399
|
+
// Cycle U -> L -> D -> R -> U (inverse of clockwise), rotate CCW
|
|
400
|
+
this.STATES.RIGHT = this.#switchMatrix(tempDown, false);
|
|
401
|
+
this.STATES.DOWN = this.#switchMatrix(tempLeft, false);
|
|
402
|
+
this.STATES.LEFT = this.#switchMatrix(tempUpper, false);
|
|
403
|
+
this.STATES.UPPER = this.#switchMatrix(tempRight, false);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
238
407
|
/**
|
|
239
408
|
* Rotates the (y) axis clockwise or counterclockwise.
|
|
240
409
|
*/
|
|
@@ -341,7 +510,145 @@ class CubeEngine {
|
|
|
341
510
|
* @returns {string|array} The history of movements as an array or string.
|
|
342
511
|
*/
|
|
343
512
|
getMoves(asString = true) {
|
|
344
|
-
return asString ? this.MOVES
|
|
513
|
+
return asString ? this.MOVES.join(" ") : this.MOVES;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Applies a sequence of moves provided as a string.
|
|
518
|
+
* 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.
|
|
519
|
+
* @param {string} sequence - e.g. "R U' F R2 D Dw Uw Rw Rw' Lw Lw2 M M' M2"
|
|
520
|
+
* @param {object} options - { record: boolean } whether to record moves in history (default true)
|
|
521
|
+
*/
|
|
522
|
+
applyMoves(sequence, options = { record: false }) {
|
|
523
|
+
const record = options?.record !== false;
|
|
524
|
+
this.#applyMovesFromString(sequence, record);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Internal: parses and applies moves. If record=false, uses private methods to avoid logging.
|
|
528
|
+
#applyMovesFromString(sequence, record = true) {
|
|
529
|
+
if (typeof sequence !== "string") return;
|
|
530
|
+
const tokens = sequence
|
|
531
|
+
.split(/\s+/)
|
|
532
|
+
.map((t) => t.trim())
|
|
533
|
+
.filter((t) => t.length > 0);
|
|
534
|
+
|
|
535
|
+
for (const token of tokens) {
|
|
536
|
+
const base = token[0];
|
|
537
|
+
const rest = token.slice(1);
|
|
538
|
+
const isDouble = rest.includes("2");
|
|
539
|
+
const isPrime = rest.includes("'");
|
|
540
|
+
|
|
541
|
+
const exec = (fnClockwise, fnCounter) => {
|
|
542
|
+
if (isDouble) {
|
|
543
|
+
// Double turns ignore prime; do two clockwise quarter-turns
|
|
544
|
+
fnClockwise();
|
|
545
|
+
fnClockwise();
|
|
546
|
+
} else {
|
|
547
|
+
if (isPrime) {
|
|
548
|
+
fnCounter();
|
|
549
|
+
} else {
|
|
550
|
+
fnClockwise();
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
switch (base) {
|
|
556
|
+
case 'U':
|
|
557
|
+
{
|
|
558
|
+
const isWide = /w/i.test(rest);
|
|
559
|
+
if (isWide) {
|
|
560
|
+
exec(
|
|
561
|
+
() => (record ? this.rotateUw(true) : this.#rotateUw(true)),
|
|
562
|
+
() => (record ? this.rotateUw(false) : this.#rotateUw(false))
|
|
563
|
+
);
|
|
564
|
+
} else {
|
|
565
|
+
exec(
|
|
566
|
+
() => (record ? this.rotateU(true) : this.#rotateU(true)),
|
|
567
|
+
() => (record ? this.rotateU(false) : this.#rotateU(false))
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
break;
|
|
572
|
+
case 'D':
|
|
573
|
+
{
|
|
574
|
+
const isWide = /w/i.test(rest);
|
|
575
|
+
if (isWide) {
|
|
576
|
+
exec(
|
|
577
|
+
() => (record ? this.rotateDw(true) : this.#rotateDw(true)),
|
|
578
|
+
() => (record ? this.rotateDw(false) : this.#rotateDw(false))
|
|
579
|
+
);
|
|
580
|
+
} else {
|
|
581
|
+
exec(
|
|
582
|
+
() => (record ? this.rotateD(true) : this.#rotateD(true)),
|
|
583
|
+
() => (record ? this.rotateD(false) : this.#rotateD(false))
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
break;
|
|
588
|
+
case 'L':
|
|
589
|
+
{
|
|
590
|
+
const isWide = /w/i.test(rest);
|
|
591
|
+
if (isWide) {
|
|
592
|
+
exec(
|
|
593
|
+
() => (record ? this.rotateLw(true) : this.#rotateLw(true)),
|
|
594
|
+
() => (record ? this.rotateLw(false) : this.#rotateLw(false))
|
|
595
|
+
);
|
|
596
|
+
} else {
|
|
597
|
+
exec(
|
|
598
|
+
() => (record ? this.rotateL(true) : this.#rotateL(true)),
|
|
599
|
+
() => (record ? this.rotateL(false) : this.#rotateL(false))
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
break;
|
|
604
|
+
case 'R':
|
|
605
|
+
{
|
|
606
|
+
const isWide = /w/i.test(rest);
|
|
607
|
+
if (isWide) {
|
|
608
|
+
exec(
|
|
609
|
+
() => (record ? this.rotateRw(true) : this.#rotateRw(true)),
|
|
610
|
+
() => (record ? this.rotateRw(false) : this.#rotateRw(false))
|
|
611
|
+
);
|
|
612
|
+
} else {
|
|
613
|
+
exec(
|
|
614
|
+
() => (record ? this.rotateR(true) : this.#rotateR(true)),
|
|
615
|
+
() => (record ? this.rotateR(false) : this.#rotateR(false))
|
|
616
|
+
);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
break;
|
|
620
|
+
case 'F':
|
|
621
|
+
exec(
|
|
622
|
+
() => (record ? this.rotateF(true) : this.#rotateF(true)),
|
|
623
|
+
() => (record ? this.rotateF(false) : this.#rotateF(false))
|
|
624
|
+
);
|
|
625
|
+
break;
|
|
626
|
+
case 'x':
|
|
627
|
+
exec(
|
|
628
|
+
() => (record ? this.rotateX(true) : this.#rotateX(true)),
|
|
629
|
+
() => (record ? this.rotateX(false) : this.#rotateX(false))
|
|
630
|
+
);
|
|
631
|
+
break;
|
|
632
|
+
case 'y':
|
|
633
|
+
exec(
|
|
634
|
+
() => (record ? this.rotateY(true) : this.#rotateY(true)),
|
|
635
|
+
() => (record ? this.rotateY(false) : this.#rotateY(false))
|
|
636
|
+
);
|
|
637
|
+
break;
|
|
638
|
+
case 'z':
|
|
639
|
+
exec(
|
|
640
|
+
() => (record ? this.rotateZ(true) : this.#rotateZ(true)),
|
|
641
|
+
() => (record ? this.rotateZ(false) : this.#rotateZ(false))
|
|
642
|
+
);
|
|
643
|
+
break;
|
|
644
|
+
case 'M':
|
|
645
|
+
exec(
|
|
646
|
+
() => (record ? this.rotateM(true) : this.#rotateM(true)),
|
|
647
|
+
() => (record ? this.rotateM(false) : this.#rotateM(false))
|
|
648
|
+
);
|
|
649
|
+
break;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
345
652
|
}
|
|
346
653
|
}
|
|
347
654
|
|
package/dist/index.js
CHANGED
|
@@ -45,9 +45,9 @@ __export(src_exports, {
|
|
|
45
45
|
CubeEngine: () => CubeEngine
|
|
46
46
|
});
|
|
47
47
|
module.exports = __toCommonJS(src_exports);
|
|
48
|
-
var _CubeEngine_instances, rotateU_fn, rotateF_fn, rotateR_fn, rotateL_fn, rotateD_fn, rotateX_fn, rotateY_fn, switchMatrix_fn, specialFlip_fn;
|
|
48
|
+
var _CubeEngine_instances, rotateU_fn, rotateF_fn, rotateR_fn, rotateL_fn, rotateD_fn, rotateDw_fn, rotateUw_fn, rotateRw_fn, rotateLw_fn, rotateM_fn, rotateX_fn, rotateZ_fn, rotateY_fn, switchMatrix_fn, specialFlip_fn, applyMovesFromString_fn;
|
|
49
49
|
var CubeEngine = class {
|
|
50
|
-
constructor() {
|
|
50
|
+
constructor(initialScramble) {
|
|
51
51
|
__privateAdd(this, _CubeEngine_instances);
|
|
52
52
|
__publicField(this, "MOVES", []);
|
|
53
53
|
// States object for the rotation
|
|
@@ -89,6 +89,10 @@ var CubeEngine = class {
|
|
|
89
89
|
[COLOR.Y[6], COLOR.Y[7], COLOR.Y[8]]
|
|
90
90
|
]
|
|
91
91
|
});
|
|
92
|
+
if (typeof initialScramble === "string" && initialScramble.trim().length > 0) {
|
|
93
|
+
__privateMethod(this, _CubeEngine_instances, applyMovesFromString_fn).call(this, initialScramble, false);
|
|
94
|
+
this.MOVES = [];
|
|
95
|
+
}
|
|
92
96
|
}
|
|
93
97
|
/**
|
|
94
98
|
* Rotates the (UPPER) layer clockwise or counterclockwise.
|
|
@@ -150,6 +154,66 @@ var CubeEngine = class {
|
|
|
150
154
|
this.MOVES.push("D'");
|
|
151
155
|
}
|
|
152
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* Rotates the wide (DOWN two layers) clockwise or counterclockwise.
|
|
159
|
+
*/
|
|
160
|
+
rotateDw(clockwise = true) {
|
|
161
|
+
if (clockwise) {
|
|
162
|
+
__privateMethod(this, _CubeEngine_instances, rotateDw_fn).call(this, true);
|
|
163
|
+
this.MOVES.push("Dw");
|
|
164
|
+
} else {
|
|
165
|
+
__privateMethod(this, _CubeEngine_instances, rotateDw_fn).call(this, false);
|
|
166
|
+
this.MOVES.push("Dw'");
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Rotates the wide (UPPER two layers) clockwise or counterclockwise.
|
|
171
|
+
*/
|
|
172
|
+
rotateUw(clockwise = true) {
|
|
173
|
+
if (clockwise) {
|
|
174
|
+
__privateMethod(this, _CubeEngine_instances, rotateUw_fn).call(this, true);
|
|
175
|
+
this.MOVES.push("Uw");
|
|
176
|
+
} else {
|
|
177
|
+
__privateMethod(this, _CubeEngine_instances, rotateUw_fn).call(this, false);
|
|
178
|
+
this.MOVES.push("Uw'");
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Rotates the wide (RIGHT two layers) clockwise or counterclockwise.
|
|
183
|
+
*/
|
|
184
|
+
rotateRw(clockwise = true) {
|
|
185
|
+
if (clockwise) {
|
|
186
|
+
__privateMethod(this, _CubeEngine_instances, rotateRw_fn).call(this, true);
|
|
187
|
+
this.MOVES.push("Rw");
|
|
188
|
+
} else {
|
|
189
|
+
__privateMethod(this, _CubeEngine_instances, rotateRw_fn).call(this, false);
|
|
190
|
+
this.MOVES.push("Rw'");
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Rotates the wide (LEFT two layers) clockwise or counterclockwise.
|
|
195
|
+
*/
|
|
196
|
+
rotateLw(clockwise = true) {
|
|
197
|
+
if (clockwise) {
|
|
198
|
+
__privateMethod(this, _CubeEngine_instances, rotateLw_fn).call(this, true);
|
|
199
|
+
this.MOVES.push("Lw");
|
|
200
|
+
} else {
|
|
201
|
+
__privateMethod(this, _CubeEngine_instances, rotateLw_fn).call(this, false);
|
|
202
|
+
this.MOVES.push("Lw'");
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Rotates the middle slice (M) parallel to L/R. Clockwise corresponds to Lw followed by L'.
|
|
207
|
+
*/
|
|
208
|
+
rotateM(clockwise = true) {
|
|
209
|
+
if (clockwise) {
|
|
210
|
+
__privateMethod(this, _CubeEngine_instances, rotateM_fn).call(this, true);
|
|
211
|
+
this.MOVES.push("M");
|
|
212
|
+
} else {
|
|
213
|
+
__privateMethod(this, _CubeEngine_instances, rotateM_fn).call(this, false);
|
|
214
|
+
this.MOVES.push("M'");
|
|
215
|
+
}
|
|
216
|
+
}
|
|
153
217
|
/**
|
|
154
218
|
* Rotates the (x) axis clockwise or counterclockwise.
|
|
155
219
|
*/
|
|
@@ -162,6 +226,18 @@ var CubeEngine = class {
|
|
|
162
226
|
this.MOVES.push("x'");
|
|
163
227
|
}
|
|
164
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Rotates the (z) axis clockwise or counterclockwise.
|
|
231
|
+
*/
|
|
232
|
+
rotateZ(clockwise = true) {
|
|
233
|
+
if (clockwise) {
|
|
234
|
+
__privateMethod(this, _CubeEngine_instances, rotateZ_fn).call(this, true);
|
|
235
|
+
this.MOVES.push("z");
|
|
236
|
+
} else {
|
|
237
|
+
__privateMethod(this, _CubeEngine_instances, rotateZ_fn).call(this, false);
|
|
238
|
+
this.MOVES.push("z'");
|
|
239
|
+
}
|
|
240
|
+
}
|
|
165
241
|
/**
|
|
166
242
|
* Rotates the (y) axis clockwise or counterclockwise.
|
|
167
243
|
*/
|
|
@@ -203,7 +279,17 @@ var CubeEngine = class {
|
|
|
203
279
|
* @returns {string|array} The history of movements as an array or string.
|
|
204
280
|
*/
|
|
205
281
|
getMoves(asString = true) {
|
|
206
|
-
return asString ? this.MOVES
|
|
282
|
+
return asString ? this.MOVES.join(" ") : this.MOVES;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Applies a sequence of moves provided as a string.
|
|
286
|
+
* 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.
|
|
287
|
+
* @param {string} sequence - e.g. "R U' F R2 D Dw Uw Rw Rw' Lw Lw2 M M' M2"
|
|
288
|
+
* @param {object} options - { record: boolean } whether to record moves in history (default true)
|
|
289
|
+
*/
|
|
290
|
+
applyMoves(sequence, options = { record: false }) {
|
|
291
|
+
const record = (options == null ? void 0 : options.record) !== false;
|
|
292
|
+
__privateMethod(this, _CubeEngine_instances, applyMovesFromString_fn).call(this, sequence, record);
|
|
207
293
|
}
|
|
208
294
|
};
|
|
209
295
|
_CubeEngine_instances = new WeakSet();
|
|
@@ -282,6 +368,51 @@ rotateD_fn = function(clockwise = true) {
|
|
|
282
368
|
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, false);
|
|
283
369
|
}
|
|
284
370
|
};
|
|
371
|
+
rotateDw_fn = function(clockwise = true) {
|
|
372
|
+
if (clockwise) {
|
|
373
|
+
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, false);
|
|
374
|
+
__privateMethod(this, _CubeEngine_instances, rotateU_fn).call(this, true);
|
|
375
|
+
} else {
|
|
376
|
+
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, true);
|
|
377
|
+
__privateMethod(this, _CubeEngine_instances, rotateU_fn).call(this, false);
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
rotateUw_fn = function(clockwise = true) {
|
|
381
|
+
if (clockwise) {
|
|
382
|
+
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, true);
|
|
383
|
+
__privateMethod(this, _CubeEngine_instances, rotateD_fn).call(this, true);
|
|
384
|
+
} else {
|
|
385
|
+
__privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, false);
|
|
386
|
+
__privateMethod(this, _CubeEngine_instances, rotateD_fn).call(this, false);
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
rotateRw_fn = function(clockwise = true) {
|
|
390
|
+
if (clockwise) {
|
|
391
|
+
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, true);
|
|
392
|
+
__privateMethod(this, _CubeEngine_instances, rotateL_fn).call(this, true);
|
|
393
|
+
} else {
|
|
394
|
+
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, false);
|
|
395
|
+
__privateMethod(this, _CubeEngine_instances, rotateL_fn).call(this, false);
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
rotateLw_fn = function(clockwise = true) {
|
|
399
|
+
if (clockwise) {
|
|
400
|
+
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, false);
|
|
401
|
+
__privateMethod(this, _CubeEngine_instances, rotateR_fn).call(this, true);
|
|
402
|
+
} else {
|
|
403
|
+
__privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, true);
|
|
404
|
+
__privateMethod(this, _CubeEngine_instances, rotateR_fn).call(this, false);
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
rotateM_fn = function(clockwise = true) {
|
|
408
|
+
if (clockwise) {
|
|
409
|
+
__privateMethod(this, _CubeEngine_instances, rotateLw_fn).call(this, true);
|
|
410
|
+
__privateMethod(this, _CubeEngine_instances, rotateL_fn).call(this, false);
|
|
411
|
+
} else {
|
|
412
|
+
__privateMethod(this, _CubeEngine_instances, rotateLw_fn).call(this, false);
|
|
413
|
+
__privateMethod(this, _CubeEngine_instances, rotateL_fn).call(this, true);
|
|
414
|
+
}
|
|
415
|
+
};
|
|
285
416
|
rotateX_fn = function(clockwise = true) {
|
|
286
417
|
const tempFront = structuredClone(this.STATES.FRONT);
|
|
287
418
|
const tempDown = structuredClone(this.STATES.DOWN);
|
|
@@ -305,6 +436,29 @@ rotateX_fn = function(clockwise = true) {
|
|
|
305
436
|
this.STATES.UPPER = __privateMethod(this, _CubeEngine_instances, specialFlip_fn).call(this, tempBack);
|
|
306
437
|
}
|
|
307
438
|
};
|
|
439
|
+
rotateZ_fn = function(clockwise = true) {
|
|
440
|
+
const tempUpper = structuredClone(this.STATES.UPPER);
|
|
441
|
+
const tempRight = structuredClone(this.STATES.RIGHT);
|
|
442
|
+
const tempDown = structuredClone(this.STATES.DOWN);
|
|
443
|
+
const tempLeft = structuredClone(this.STATES.LEFT);
|
|
444
|
+
const tempFront = structuredClone(this.STATES.FRONT);
|
|
445
|
+
const tempBack = structuredClone(this.STATES.BACK);
|
|
446
|
+
if (clockwise) {
|
|
447
|
+
this.STATES.FRONT = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempFront, true);
|
|
448
|
+
this.STATES.BACK = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempBack, false);
|
|
449
|
+
this.STATES.RIGHT = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempUpper, true);
|
|
450
|
+
this.STATES.DOWN = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempRight, true);
|
|
451
|
+
this.STATES.LEFT = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempDown, true);
|
|
452
|
+
this.STATES.UPPER = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempLeft, true);
|
|
453
|
+
} else {
|
|
454
|
+
this.STATES.FRONT = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempFront, false);
|
|
455
|
+
this.STATES.BACK = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempBack, true);
|
|
456
|
+
this.STATES.RIGHT = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempDown, false);
|
|
457
|
+
this.STATES.DOWN = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempLeft, false);
|
|
458
|
+
this.STATES.LEFT = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempUpper, false);
|
|
459
|
+
this.STATES.UPPER = __privateMethod(this, _CubeEngine_instances, switchMatrix_fn).call(this, tempRight, false);
|
|
460
|
+
}
|
|
461
|
+
};
|
|
308
462
|
rotateY_fn = function(clockwise = true) {
|
|
309
463
|
const tempFront = structuredClone(this.STATES.FRONT);
|
|
310
464
|
const tempRight = structuredClone(this.STATES.RIGHT);
|
|
@@ -349,6 +503,128 @@ switchMatrix_fn = function(matrix, clockwise = true) {
|
|
|
349
503
|
specialFlip_fn = function(matrix) {
|
|
350
504
|
return structuredClone(matrix).reverse().map((row) => [...row].reverse());
|
|
351
505
|
};
|
|
506
|
+
// Internal: parses and applies moves. If record=false, uses private methods to avoid logging.
|
|
507
|
+
applyMovesFromString_fn = function(sequence, record = true) {
|
|
508
|
+
if (typeof sequence !== "string") return;
|
|
509
|
+
const tokens = sequence.split(/\s+/).map((t) => t.trim()).filter((t) => t.length > 0);
|
|
510
|
+
for (const token of tokens) {
|
|
511
|
+
const base = token[0];
|
|
512
|
+
const rest = token.slice(1);
|
|
513
|
+
const isDouble = rest.includes("2");
|
|
514
|
+
const isPrime = rest.includes("'");
|
|
515
|
+
const times = isDouble ? 2 : 1;
|
|
516
|
+
const exec = (fnClockwise, fnCounter) => {
|
|
517
|
+
if (isDouble) {
|
|
518
|
+
fnClockwise();
|
|
519
|
+
fnClockwise();
|
|
520
|
+
} else {
|
|
521
|
+
if (isPrime) {
|
|
522
|
+
fnCounter();
|
|
523
|
+
} else {
|
|
524
|
+
fnClockwise();
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
switch (base) {
|
|
529
|
+
case "U":
|
|
530
|
+
{
|
|
531
|
+
const isWide = /w/i.test(rest);
|
|
532
|
+
if (isWide) {
|
|
533
|
+
exec(
|
|
534
|
+
() => record ? this.rotateUw(true) : __privateMethod(this, _CubeEngine_instances, rotateUw_fn).call(this, true),
|
|
535
|
+
() => record ? this.rotateUw(false) : __privateMethod(this, _CubeEngine_instances, rotateUw_fn).call(this, false)
|
|
536
|
+
);
|
|
537
|
+
} else {
|
|
538
|
+
exec(
|
|
539
|
+
() => record ? this.rotateU(true) : __privateMethod(this, _CubeEngine_instances, rotateU_fn).call(this, true),
|
|
540
|
+
() => record ? this.rotateU(false) : __privateMethod(this, _CubeEngine_instances, rotateU_fn).call(this, false)
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
break;
|
|
545
|
+
case "D":
|
|
546
|
+
{
|
|
547
|
+
const isWide = /w/i.test(rest);
|
|
548
|
+
if (isWide) {
|
|
549
|
+
exec(
|
|
550
|
+
() => record ? this.rotateDw(true) : __privateMethod(this, _CubeEngine_instances, rotateDw_fn).call(this, true),
|
|
551
|
+
() => record ? this.rotateDw(false) : __privateMethod(this, _CubeEngine_instances, rotateDw_fn).call(this, false)
|
|
552
|
+
);
|
|
553
|
+
} else {
|
|
554
|
+
exec(
|
|
555
|
+
() => record ? this.rotateD(true) : __privateMethod(this, _CubeEngine_instances, rotateD_fn).call(this, true),
|
|
556
|
+
() => record ? this.rotateD(false) : __privateMethod(this, _CubeEngine_instances, rotateD_fn).call(this, false)
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
break;
|
|
561
|
+
case "L":
|
|
562
|
+
{
|
|
563
|
+
const isWide = /w/i.test(rest);
|
|
564
|
+
if (isWide) {
|
|
565
|
+
exec(
|
|
566
|
+
() => record ? this.rotateLw(true) : __privateMethod(this, _CubeEngine_instances, rotateLw_fn).call(this, true),
|
|
567
|
+
() => record ? this.rotateLw(false) : __privateMethod(this, _CubeEngine_instances, rotateLw_fn).call(this, false)
|
|
568
|
+
);
|
|
569
|
+
} else {
|
|
570
|
+
exec(
|
|
571
|
+
() => record ? this.rotateL(true) : __privateMethod(this, _CubeEngine_instances, rotateL_fn).call(this, true),
|
|
572
|
+
() => record ? this.rotateL(false) : __privateMethod(this, _CubeEngine_instances, rotateL_fn).call(this, false)
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
break;
|
|
577
|
+
case "R":
|
|
578
|
+
{
|
|
579
|
+
const isWide = /w/i.test(rest);
|
|
580
|
+
if (isWide) {
|
|
581
|
+
exec(
|
|
582
|
+
() => record ? this.rotateRw(true) : __privateMethod(this, _CubeEngine_instances, rotateRw_fn).call(this, true),
|
|
583
|
+
() => record ? this.rotateRw(false) : __privateMethod(this, _CubeEngine_instances, rotateRw_fn).call(this, false)
|
|
584
|
+
);
|
|
585
|
+
} else {
|
|
586
|
+
exec(
|
|
587
|
+
() => record ? this.rotateR(true) : __privateMethod(this, _CubeEngine_instances, rotateR_fn).call(this, true),
|
|
588
|
+
() => record ? this.rotateR(false) : __privateMethod(this, _CubeEngine_instances, rotateR_fn).call(this, false)
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
break;
|
|
593
|
+
case "F":
|
|
594
|
+
exec(
|
|
595
|
+
() => record ? this.rotateF(true) : __privateMethod(this, _CubeEngine_instances, rotateF_fn).call(this, true),
|
|
596
|
+
() => record ? this.rotateF(false) : __privateMethod(this, _CubeEngine_instances, rotateF_fn).call(this, false)
|
|
597
|
+
);
|
|
598
|
+
break;
|
|
599
|
+
case "x":
|
|
600
|
+
exec(
|
|
601
|
+
() => record ? this.rotateX(true) : __privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, true),
|
|
602
|
+
() => record ? this.rotateX(false) : __privateMethod(this, _CubeEngine_instances, rotateX_fn).call(this, false)
|
|
603
|
+
);
|
|
604
|
+
break;
|
|
605
|
+
case "y":
|
|
606
|
+
exec(
|
|
607
|
+
() => record ? this.rotateY(true) : __privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, true),
|
|
608
|
+
() => record ? this.rotateY(false) : __privateMethod(this, _CubeEngine_instances, rotateY_fn).call(this, false)
|
|
609
|
+
);
|
|
610
|
+
break;
|
|
611
|
+
case "z":
|
|
612
|
+
exec(
|
|
613
|
+
() => record ? this.rotateZ(true) : __privateMethod(this, _CubeEngine_instances, rotateZ_fn).call(this, true),
|
|
614
|
+
() => record ? this.rotateZ(false) : __privateMethod(this, _CubeEngine_instances, rotateZ_fn).call(this, false)
|
|
615
|
+
);
|
|
616
|
+
break;
|
|
617
|
+
case "M":
|
|
618
|
+
exec(
|
|
619
|
+
() => record ? this.rotateM(true) : __privateMethod(this, _CubeEngine_instances, rotateM_fn).call(this, true),
|
|
620
|
+
() => record ? this.rotateM(false) : __privateMethod(this, _CubeEngine_instances, rotateM_fn).call(this, false)
|
|
621
|
+
);
|
|
622
|
+
break;
|
|
623
|
+
default:
|
|
624
|
+
break;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
};
|
|
352
628
|
var COLOR = {
|
|
353
629
|
W: ["W", "W", "W", "W", "W", "W", "W", "W", "W"],
|
|
354
630
|
G: ["G", "G", "G", "G", "G", "G", "G", "G", "G"],
|