squanlib 1.1.2 → 1.2.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/dist/squanlib.umd.js +77 -36
- package/dist/squanlib.umd.min.js +1 -1
- package/package.json +1 -1
- package/squanlib.js +77 -36
package/dist/squanlib.umd.js
CHANGED
|
@@ -70,7 +70,6 @@
|
|
|
70
70
|
"d2": "-1,5", "d2'": "1,-5",
|
|
71
71
|
"K": "5,2", "K'": "-5,-2",
|
|
72
72
|
"k": "2,5", "k'": "-2,-5",
|
|
73
|
-
"A": "1,0", "A'": "-1,0",
|
|
74
73
|
"G": "5,-4", "G'": "-5,4",
|
|
75
74
|
"g": "4,-5", "g'": "-4,5",
|
|
76
75
|
};
|
|
@@ -277,10 +276,10 @@
|
|
|
277
276
|
* GOOD_FINISHES: moves that are acceptable as the last move
|
|
278
277
|
*/
|
|
279
278
|
static GOOD_FINISHES = new Set([
|
|
280
|
-
"
|
|
281
|
-
"
|
|
282
|
-
"
|
|
283
|
-
"5
|
|
279
|
+
"1,1", "-1,-1", "2,2", "-2,-2", "2,-1", "-2,1", "1,-2", "-1,2",
|
|
280
|
+
"3,0", "-3,0", "0,3", "0,-3", "3,3", "3,-3", "-3,-3", "-3,3",
|
|
281
|
+
"4,1", "-4,-1", "1,4", "-1,-4", "2,-4", "-2,4", "4,-2", "-4,2",
|
|
282
|
+
"5,-1", "-5,1", "-4,5", "-5,4", "6,3",
|
|
284
283
|
]);
|
|
285
284
|
|
|
286
285
|
/**
|
|
@@ -717,14 +716,6 @@
|
|
|
717
716
|
// overrides
|
|
718
717
|
if (alg in this.tempReplacements) return this.tempReplacements[alg];
|
|
719
718
|
|
|
720
|
-
// p scrambles
|
|
721
|
-
let isPScramble = /^p[ /\\|]/.test(alg);
|
|
722
|
-
let startingSlice;
|
|
723
|
-
if (isPScramble) {
|
|
724
|
-
startingSlice = alg.charAt(1) === " " ? "/" : alg.charAt(1);
|
|
725
|
-
alg = alg.slice(2, -3);
|
|
726
|
-
}
|
|
727
|
-
|
|
728
719
|
// legacy character substitutions
|
|
729
720
|
alg = alg
|
|
730
721
|
.replaceAll('&', '-1')
|
|
@@ -733,6 +724,17 @@
|
|
|
733
724
|
.replaceAll('8', '-4')
|
|
734
725
|
.replaceAll('7', '-5');
|
|
735
726
|
|
|
727
|
+
// remove potential move counts, comments
|
|
728
|
+
alg = alg.replaceAll(/\[.*?\]/g, "");
|
|
729
|
+
|
|
730
|
+
// p scrambles
|
|
731
|
+
let isPScramble = /^p[ /\\|]/.test(alg);
|
|
732
|
+
let startingSlice;
|
|
733
|
+
if (isPScramble) {
|
|
734
|
+
startingSlice = alg.charAt(1) === " " ? "/" : alg.charAt(1);
|
|
735
|
+
alg = alg.slice(2, -3);
|
|
736
|
+
}
|
|
737
|
+
|
|
736
738
|
// expand move groups, e.g. "(U U')3" → "U U' U U' U U'"
|
|
737
739
|
for (const group of alg.matchAll(/(\(.*?\))(\d+)/g)) {
|
|
738
740
|
const inner = group[1].replaceAll(/[()]/g, '');
|
|
@@ -1038,10 +1040,22 @@
|
|
|
1038
1040
|
// now go through scramble move by move to apply base karn
|
|
1039
1041
|
let s = alg.split(" ").filter(Boolean);
|
|
1040
1042
|
for (let i = 0; i < s.length; i++) {
|
|
1041
|
-
if (i === 0 && !startsSlice)
|
|
1042
|
-
|
|
1043
|
+
if (i === 0 && !startsSlice) {
|
|
1044
|
+
// even if it's in base karn, we can't karnify
|
|
1045
|
+
s[i] = s[i].replace(",", "");
|
|
1046
|
+
continue;
|
|
1047
|
+
}
|
|
1048
|
+
if (i === s.length - 1 && !endsSlice) {
|
|
1049
|
+
// even if it's in base karn, we can't karnify
|
|
1050
|
+
s[i] = s[i].replace(",", "");
|
|
1051
|
+
break;
|
|
1052
|
+
}
|
|
1043
1053
|
// good to replace
|
|
1044
|
-
|
|
1054
|
+
let inBaseKarn = s[i] in SquanLib.wcaToBaseKarn;
|
|
1055
|
+
s[i] = inBaseKarn ? SquanLib.wcaToBaseKarn[s[i]] : s[i].replace(",", "");
|
|
1056
|
+
// prevent an additional leading slice for first move karn
|
|
1057
|
+
if (inBaseKarn && i === 0) startingSlice = startingSlice.replace("/", "");
|
|
1058
|
+
if (inBaseKarn && i === s.length - 1) endingSlice = "";
|
|
1045
1059
|
}
|
|
1046
1060
|
|
|
1047
1061
|
alg = startingSlice + s.join(" ") + endingSlice;
|
|
@@ -1366,16 +1380,32 @@
|
|
|
1366
1380
|
rated = true;
|
|
1367
1381
|
|
|
1368
1382
|
if (rated && ["/", "\\", "|"].includes(sliceStart)) {
|
|
1369
|
-
|
|
1370
|
-
const slashPos = line.indexOf('/');
|
|
1371
|
-
if (slashPos >= 0)
|
|
1372
|
-
result.alg = line.slice(0, slashPos) + sliceStart + line.slice(slashPos + 1);
|
|
1383
|
+
result.alg = this.injectSliceStart(line, sliceStart);
|
|
1373
1384
|
}
|
|
1374
1385
|
|
|
1375
1386
|
return result;
|
|
1376
1387
|
}).sort((a, b) => b.score - a.score);
|
|
1377
1388
|
}
|
|
1378
1389
|
|
|
1390
|
+
/**
|
|
1391
|
+
* injectSliceStart: injects the slice start into an alg
|
|
1392
|
+
*
|
|
1393
|
+
* @param {string} alg the alg. no extra spaces allowed
|
|
1394
|
+
* @param {string} sliceStart " " | "/" | "\\" | "|"
|
|
1395
|
+
* @returns {string} the alg with slice start injected at the first slice
|
|
1396
|
+
*/
|
|
1397
|
+
injectSliceStart(alg, sliceStart) {
|
|
1398
|
+
let moreThan1 = /[/\\| ]/.test(alg); // is there ANY slice chars?
|
|
1399
|
+
let firstMove = moreThan1 ? alg.match(/^([^/\\| ]*)[/\\| ]/)?.[1] : alg;
|
|
1400
|
+
// only tests if it's a karn
|
|
1401
|
+
if (firstMove in SquanLib.karnToWCA) return sliceStart + alg;
|
|
1402
|
+
if (!moreThan1) return alg; // no slice to inject to
|
|
1403
|
+
|
|
1404
|
+
// guaranteed to have a slice
|
|
1405
|
+
const slashPos = alg.search(/[/\\| ]/);
|
|
1406
|
+
return alg.slice(0, slashPos) + sliceStart + alg.slice(slashPos + 1);
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1379
1409
|
// =========================================================================
|
|
1380
1410
|
// SECTION 8: ALG TRANSFORM
|
|
1381
1411
|
// =========================================================================
|
|
@@ -1396,28 +1426,38 @@
|
|
|
1396
1426
|
/**
|
|
1397
1427
|
* compl: get the complement of a move
|
|
1398
1428
|
*
|
|
1399
|
-
* @param {string} a a move
|
|
1400
|
-
* @returns {string} the complement move
|
|
1401
|
-
* @example "-12" → "5-4"
|
|
1429
|
+
* @param {string} a a move
|
|
1430
|
+
* @returns {string} the complement move with commas
|
|
1431
|
+
* @example "-12" → "5,-4"; "-1,2" → "5,-4"
|
|
1402
1432
|
*/
|
|
1403
1433
|
compl(a) {
|
|
1404
1434
|
if (!a) return a;
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1435
|
+
let u, d;
|
|
1436
|
+
if (a.includes(',')) [u, d] = a.split(",");
|
|
1437
|
+
else {
|
|
1438
|
+
const inx = this.sepIndex(a);
|
|
1439
|
+
[u, d] = [a.slice(0, inx), a.slice(inx)];
|
|
1440
|
+
}
|
|
1441
|
+
return String(this.legalMove(6 + parseInt(u, 10))) + "," +
|
|
1442
|
+
String(this.legalMove(6 + parseInt(d, 10)));
|
|
1408
1443
|
}
|
|
1409
1444
|
|
|
1410
1445
|
/**
|
|
1411
1446
|
* lf: get the layer flip of a move
|
|
1412
1447
|
*
|
|
1413
|
-
* @param {string} a a move
|
|
1448
|
+
* @param {string} a a move
|
|
1414
1449
|
* @returns {string} the layer flip move
|
|
1415
|
-
* @example "-12" → "2-1"
|
|
1450
|
+
* @example "-12" → "2,-1"; "-1,2" → "2,-1"
|
|
1416
1451
|
*/
|
|
1417
1452
|
lf(a) {
|
|
1418
1453
|
if (!a) return a;
|
|
1419
|
-
|
|
1420
|
-
|
|
1454
|
+
let u, d;
|
|
1455
|
+
if (a.includes(',')) [u, d] = a.split(",");
|
|
1456
|
+
else {
|
|
1457
|
+
const inx = this.sepIndex(a);
|
|
1458
|
+
[u, d] = [a.slice(0, inx), a.slice(inx)];
|
|
1459
|
+
}
|
|
1460
|
+
return d + "," + u;
|
|
1421
1461
|
}
|
|
1422
1462
|
|
|
1423
1463
|
/**
|
|
@@ -1430,11 +1470,11 @@
|
|
|
1430
1470
|
compact(algIn) {
|
|
1431
1471
|
let alg = algIn
|
|
1432
1472
|
.replace(/\[.*?\]/g, "")
|
|
1433
|
-
.replace(/[()]/g, "")
|
|
1434
|
-
.replaceAll(" ", "").trim();
|
|
1473
|
+
.replace(/[()]/g, "").trim();
|
|
1435
1474
|
if (this.isKarn(alg)) {
|
|
1436
1475
|
const numeric = this.unkarnify(alg);
|
|
1437
|
-
return numeric.split("/").
|
|
1476
|
+
return numeric.split("/").map(m => {
|
|
1477
|
+
if (!m) return m;
|
|
1438
1478
|
if (!m.includes(","))
|
|
1439
1479
|
throw new Error(
|
|
1440
1480
|
`algToInternal: m doesn't have commas post karnifying: ${m}`
|
|
@@ -1444,7 +1484,7 @@
|
|
|
1444
1484
|
String(this.legalMove(parseInt(d, 10)));
|
|
1445
1485
|
}).join(" ");
|
|
1446
1486
|
}
|
|
1447
|
-
alg = alg.
|
|
1487
|
+
alg = alg.replaceAll(" ", "");
|
|
1448
1488
|
if (alg.includes("/")) {
|
|
1449
1489
|
return alg.split("/").filter(Boolean).map(m => {
|
|
1450
1490
|
if (!m.includes(",")) m = this.addCommas(m);
|
|
@@ -1473,7 +1513,8 @@
|
|
|
1473
1513
|
* @returns {number} how many positions the alg can y2 at
|
|
1474
1514
|
*/
|
|
1475
1515
|
countY2Positions(algIn) {
|
|
1476
|
-
|
|
1516
|
+
// spaces ARE slices, cannot trim or do anything like that
|
|
1517
|
+
const segs = this.compact(algIn).split(" ");
|
|
1477
1518
|
return Math.max(0, segs.length - 3);
|
|
1478
1519
|
}
|
|
1479
1520
|
|
|
@@ -1625,7 +1666,7 @@
|
|
|
1625
1666
|
isOBLCase(l, target) {
|
|
1626
1667
|
const targetPattern = Object.entries(SquanLib.OBLToEnglish)
|
|
1627
1668
|
.find(([, v]) => v === target
|
|
1628
|
-
|
|
1669
|
+
)?.[0];
|
|
1629
1670
|
if (!targetPattern) return false;
|
|
1630
1671
|
// to corner first
|
|
1631
1672
|
if (l[0] !== l[0].toUpperCase()) l = this.shift(l, -1);
|
package/dist/squanlib.umd.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! squanlib | GPL-3.0-or-later | https://github.com/Mattttttttttttttttttttttttttttttt/squan-lib */
|
|
2
|
-
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).squanlib=e()}(this,function(){"use strict";class t{static karnToWCA={U4:"U U' U U'","U4'":"U' U U' U",D4:"D D' D D'","D4'":"D' D D' D",u4:"u u' u u'","u4'":"u' u u' u",d4:"d d' d d'","d4'":"d' d d' d",U3:"U U' U","U3'":"U' U U'",D3:"D D' D","D3'":"D' D D'",u3:"u u' u","u3'":"u' u u'",d3:"d d' d","d3'":"d' d d'",F3:"F F' F","F3'":"F' F F'",f3:"f f' f","f3'":"f' f f'",W:"U U'","W'":"U' U",B:"D D'","B'":"D' D",w:"u u'","w'":"u' u",b:"d d'","b'":"d' d",F2:"F F'","F2'":"F' F",f2:"f f'","f2'":"f' f",UU:"U U","UU'":"U' U'",DD:"D D","DD'":"D' D'",T2:"T T'","T2'":"T' T",t2:"t t'","t2'":"t' t",E2:"E E'","E2'":"E' E","ɇ":"U D","ɇ'":"U' D'","Ɇ":"U D'","Ɇ'":"U' D",U2:"6,0","U2'":"6,0",D2:"0,6",U2D:"6,3","U2D'":"6,-3","U2'D":"6,3","U2'D'":"6,-3",U2D2:"6,6",UD2:"3,6","U'D2":"-3,6",U:"3,0","U'":"-3,0",D:"0,3","D'":"0,-3",E:"3,-3","E'":"-3,3",e:"3,3","e'":"-3,-3",u:"2,-1","u'":"-2,1",d:"-1,2","d'":"1,-2",F:"4,1","F'":"-4,-1",f:"1,4","f'":"-1,-4",T:"2,-4","T'":"-2,4",t:"4,-2","t'":"-4,2",m:"2,2","m'":"-2,-2",M:"1,1","M'":"-1,-1",u2:"5,-1","u2'":"-5,1",d2:"-1,5","d2'":"1,-5",K:"5,2","K'":"-5,-2",k:"2,5","k'":"-2,-5",A:"1,0","A'":"-1,0",G:"5,-4","G'":"-5,4",g:"4,-5","g'":"-4,5"};static shorthandToKarn={bjj:"U' e D'",fjj:"U e' D",e2bjj:"U' e' U'",e2fjj:"U e U",nn:"E E'",jn:"D4'",nj:"U4",jj:"U e' D","bjj+e2":"U' e' U'","-nn":"E' E","-jn":"D4","-nj":"D4'",bpj10:"d m' U","bpj0-1":"u' m D'",fpj10:"u m' D","fpj0-1":"d' m U'",aa10:"u m' u T'","aa0-1":"U m' U t'",fadj10:"D M' d'",dadj10:"D M' d'","fadj0-1":"U' M u","u'adj0-1":"U' M u",badj10:"U M' u'",uadj10:"U M' u'","badj0-1":"D' M d","d'adj0-1":"D' M d",bb10:"T u' e U'","bb0-1":"t d e' D",fdd10:"D e' d t","fdd0-1":"U' e u' T",bdd10:"U e' u T'","bdd0-1":"D' e d' t'",ff10:"d m' d M E","ff0-1":"u' m U' M T",fv10:"d4","fv0-1":"d4'",vf10:"u4","vf0-1":"u4'",y2fv10:"u d' u -5,4",jf10:"w D' u T'","jf0-1":"w' D u' T",fj10:"b U' d t","fj0-1":"b' U d' t'",jr00:"e' w e",jr10:"e' b e","jr0-1":"e' w' e","jr1-1":"e' b' e",rj00:"e b' e'",rj10:"e w e'","rj0-1":"e b' e'","rj1-1":"e w e'",jv10:"b D d d2'","jv0-1":"b' D' d' d2",vj10:"w U u u2'","vj0-1":"w' U' u' u2",kk10:"u m' U E'","kk0-1":"U m' u E'",opp10:"u2 u2'","opp0-1":"u2' u2",pn10:"T T'","pn0-1":"t t'",px10:"f' d3' f'","px0-1":"f d3 f",xp10:"F' u3' F'","xp0-1":"F u3 F",tt10:"d m' F' u2'",fss10:"u M D' E'","fss0-1":"D' M u E'",bss10:"D M' u' E","bss0-1":"U' M d E",vv10:"u M u m' E'",zz10:"u M t' M D'","zz0-1":"D' M t' M u","30adj10":"U M' u'","-30adj0-1":"U' M u","03adj10":"D M' d'",obopp00:"1,0/M' F M' F M'/0,1","oaopp1-1":"0,1/M' u' M' u' M'/0,1",but00:"",also00:"","done!00":"0,0"};static alignmentIndependent=new Set(["bjj","fjj","nn","jn","nj","e2bjj","e2fjj","jj","bjj+e2","-nn","-jn","-nj"]);static wcaToBaseKarn={"6,0":"U2","6,3":"U2D","6,-3":"U2D'","6,6":"U2D2","0,6":"D2","3,6":"UD2","-3,6":"U'D2","3,0":"U","-3,0":"U'","0,3":"D","0,-3":"D'","3,-3":"E","-3,3":"E'","3,3":"e","-3,-3":"e'","2,-1":"u","-2,1":"u'","-1,2":"d","1,-2":"d'","4,1":"F","-4,-1":"F'","1,4":"f","-1,-4":"f'","2,-4":"T","-2,4":"T'","4,-2":"t","-4,2":"t'","2,2":"m","-2,-2":"m'","1,1":"M","-1,-1":"M'","5,-1":"u2","-5,1":"u2'","-1,5":"d2","1,-5":"d2'","5,2":"K","-5,-2":"K'","2,5":"k","-2,-5":"k'"};static baseKarnToHighKarn={"U U' U U'":"U4","U' U U' U":"U4'","D D' D D'":"D4","D' D D' D":"D4'","u u' u u'":"u4","u' u u' u":"u4'","d d' d d'":"d4","d' d d' d":"d4'","U U' U":"U3","U' U U'":"U3'","D D' D":"D3","D' D D'":"D3'","u u' u":"u3","u' u u'":"u3'","d d' d":"d3","d' d d'":"d3'","F F' F":"F3","F' F F'":"F3'","f f' f":"f3","f' f f'":"f3'","U U'":"W","U' U":"W'","D D'":"B","D' D":"B'","u u'":"w","u' u":"w'","d d'":"b","d' d":"b'","F F'":"F2","F' F":"F2'","f f'":"f2","f' f":"f2'","U U":"UU","U' U'":"UU'","D D":"DD","D' D'":"DD'"};static A_MOVES=[[3,0],[-3,0],[0,3],[0,-3],[3,3],[2,-1],[-1,2],[-4,-1],[-1,-4],[2,-4],[2,2],[-1,-1],[5,-1]];static a_MOVES=[[3,0],[-3,0],[0,3],[0,-3],[3,3],[-2,1],[1,-2],[4,1],[1,4],[-2,4],[-2,-2],[1,1],[-5,1]];static OPTIM={"/0,0/":"","/3,3/3,3/":"-3,-3/-3,-3","/-3,-3/-3,-3/":"3,3/3,3","/2,2/-2,-2/":"2,2/-2,-2","/-2,-2/2,2/":"-2,-2/2,2","/1,1/-1,-1/":"1,1/-1,-1","/-1,-1/1,1/":"-1,-1/1,1","/2,-4/-2,4/2,-4/":"2,-4/-2,4/2,-4","/-2,4/2,-4/-2,4/":"-2,4/2,-4/-2,4","/5,-1/-5,1/5,-1/":"5,-1/-5,1/5,-1","/-5,1/5,-1/-5,1/":"-5,1/5,-1/-5,1"};static CLOSEST_MAP=new Map([[-5,-6],[-4,-3],[-3,-3],[-2,-3],[-1,0],[0,0],[1,0],[2,3],[3,3],[4,3],[5,6],[6,6]]);static MOVE_VALUES=new Map([["A/0,3",16],["A/0,6",1],["A/0,-3",18],["A/3,0",16],["A/3,3",12],["A/3,6",0],["A/3,-3",13],["A/6,0",12],["A/6,3",11],["A/6,6",2],["A/6,-3",12],["A/-3,0",9],["A/-3,3",13],["A/-3,6",4],["A/-3,-3",12],["A\\0,3",17],["A\\0,6",1],["A\\0,-3",8],["A\\3,0",6],["A\\3,3",14],["A\\3,6",1],["A\\3,-3",12],["A\\6,0",14],["A\\6,3",11],["A\\6,6",5],["A\\6,-3",8],["A\\-3,0",11],["A\\-3,3",14],["A\\-3,6",6],["A\\-3,-3",9],["a/0,3",5],["a/0,6",5],["a/0,-3",12],["a/3,0",17],["a/3,3",10],["a/3,6",5],["a/3,-3",7],["a/6,0",4],["a/6,3",2],["a/6,6",0],["a/6,-3",3],["a/-3,0",18],["a/-3,3",12],["a/-3,6",7],["a/-3,-3",11],["a\\0,3",5],["a\\0,6",5],["a\\0,-3",5],["a\\3,0",16],["a\\3,3",11],["a\\3,6",4],["a\\3,-3",6],["a\\6,0",4],["a\\6,3",2],["a\\6,6",0],["a\\6,-3",1],["a\\-3,0",15],["a\\-3,3",10],["a\\-3,6",2],["a\\-3,-3",5],["/1,-2",4],["\\1,-2",17],["/-1,2",15],["\\-1,2",14],["/1,-5",3],["\\1,-5",1],["/-1,5",8],["\\-1,5",3],["/1,4",7],["\\1,4",14],["/-1,-4",12],["\\-1,-4",9],["/1,1",11],["\\1,1",20],["/-1,-1",20],["\\-1,-1",10],["/2,-1",20],["\\2,-1",12],["/-2,1",14],["\\-2,1",18],["/2,2",12],["\\2,2",13],["/-2,-2",14],["\\-2,-2",8],["/2,5",5],["\\2,5",3],["/-2,-5",4],["\\-2,-5",3],["/2,-4",14],["\\2,-4",6],["/-2,4",13],["\\-2,4",13],["/4,4",5],["\\4,4",12],["/-4,-4",12],["\\-4,-4",4],["/4,1",6],["\\4,1",13],["/-4,-1",16],["\\-4,-1",6],["/4,-2",12],["\\4,-2",9],["/-4,2",16],["\\-4,2",13],["/4,-5",2],["\\4,-5",5],["/-4,5",13],["\\-4,5",3],["/5,5",1],["\\5,5",4],["/-5,-5",2],["\\-5,-5",0],["/5,2",6],["\\5,2",10],["/-5,-2",12],["\\-5,-2",13],["/5,-1",11],["\\5,-1",7],["/-5,1",14],["\\-5,1",15],["/5,-4",2],["\\5,-4",2],["/-5,4",12],["\\-5,4",14]]);static GOOD_FINISHES=new Set(["11","-1-1","22","-2-2","2-1","-21","1-2","-12","30","-30","03","0-3","33","3-3","-3-3","-33","41","-4-1","14","-1-4","2-4","-24","4-2","-42","5-1","-51","-45","-54","63"]);static OBLToEnglish={BBbBBbBBbBBb:"solved",BBwWWwWWwWWw:"1c",BBwBBwWWwWWw:"cadj",BBwWWwBBwWWw:"copp",BBwBBwBBwWWw:"3c",BBwBBwBBwBBw:"4e",WWbWWbWWbWWw:"3e",WWbWWwWWbWWw:"line",WWbWWbWWwWWw:"L",WWbWWwWWwWWw:"1e",WWbBBwWWwWWw:"left pair",BBbWWwWWwWWw:"right pair",BBwWWwWWbWWw:"left arrow",BBwWWbWWwWWw:"right arrow",WWbBBbWWwWWw:"gem",WWwWWbWWbBBw:"left knight",BBbWWbWWwWWw:"right knight",WWwWWbWWwBBb:"left axe",BBwWWbWWwWWb:"right axe",BBwWWbWWbWWw:"squid",WWwWWbBBbWWb:"left thumb",WWbBBbWWwWWb:"right thumb",WWwBBbWWbWWb:"left bunny",WWbWWbBBwWWb:"right bunny",BBbBBwWWwWWw:"shell",BBwWWwWWbBBw:"left bird",BBwBBbWWwWWw:"right bird",BBwWWbWWwBBw:"hazard",BBbBBbWWwWWw:"left kite",WWwWWbBBbBBw:"right kite",BBwBBwWWbWWb:"left cut",BBwBBbWWbWWw:"right cut",BBbBBwWWbWWw:"black T",WWwWWbBBwBBb:"white T",WWbBBwWWbBBw:"left N",WWwBBbWWwBBb:"right N",WWbBBbWWwBBw:"black tie",BBwWWwBBbWWb:"white tie",BBbWWwBBwWWw:"left yoshi",WWwBBwWWbBBw:"right yoshi"};static OBLToState=Object.fromEntries(Object.entries(this.OBLToEnglish).map(([t,e])=>[e,t]));static NAMING={solved:"O","1c":"D",cadj:"J",copp:"V","3c":"M","4e":"Q","3e":"W",line:"F",L:"L","1e":"E","left pair":"Pw","right pair":"Pc","left arrow":"Aw","right arrow":"Ac",gem:"G","left knight":"Hw","right knight":"Hc","left axe":"Xc","right axe":"Xw",squid:"S","left thumb":"THw","right thumb":"THc","left bunny":"Uc","right bunny":"Uw",shell:"SH","left bird":"Bc","right bird":"Bw",hazard:"Z","left kite":"Kc","right kite":"Kw","left cut":"Cw","right cut":"Cc","black T":"Tu","white T":"Td","left N":"Nw","right N":"Nc","black tie":"Iu","white tie":"Id","left yoshi":"Yc","right yoshi":"Yw"};static OBL_ANGLES={solved:"-","1c":"UR",cadj:"R",copp:"/","3c":"DR","4e":"-","3e":"D",line:"—",L:"DR","1e":"R","left pair":"DR","right pair":"UR","left arrow":"UR","right arrow":"UR",gem:"DR","left knight":"L","right knight":"R","left axe":"L","right axe":"R",squid:"UR","left thumb":"DL","right thumb":"DR","left bunny":"DR","right bunny":"DL",shell:"R","left bird":"R","right bird":"U",hazard:"U","left kite":"R","right kite":"L","left cut":"R","right cut":"R","black T":"R","white T":"R","left N":"\\","right N":"\\","black tie":"DR","white tie":"DR","left yoshi":"UL","right yoshi":"UR"};static nextAngle={"-":"-","/":"\\","\\":"/","—":"|","|":"—",U:"R",R:"D",D:"L",L:"U",UR:"DR",DR:"DL",DL:"UL",UL:"UR"};static get HALF_L(){return 6}static get LAYERL(){return 12}static get THREE_FOUR_L(){return 18}static get CUBEL(){return 24}static get SOLVED(){return"bBBbBBbBBbBBwWWwWWwWWwWW"}static POSSIBLE_OBL=[["","solved","solved"],["","1c","1c"],["","cadj","cadj"],["","cadj","copp"],["","copp","copp"],["","3c","3c"],["","4e","4e"],["","3e","3e"],["","line","line"],["","L","line"],["","L","L"],["","1e","1e"],["good","pair","pair"],["bad","pair","pair"],["good","arrow","pair"],["bad","arrow","pair"],["good","arrow","arrow"],["bad","arrow","arrow"],["","gem","gem"],["","gem","knight"],["","gem","axe"],["","gem","squid"],["good","knight","knight"],["bad","knight","knight"],["good","knight","axe"],["bad","knight","axe"],["same","axe","axe"],["diff","axe","axe"],["","squid","knight"],["","squid","axe"],["","squid","squid"],["good","thumb","thumb"],["bad","thumb","thumb"],["good","thumb","bunny"],["bad","thumb","bunny"],["good","bunny","bunny"],["bad","bunny","bunny"],["","shell","shell"],["","shell","bird"],["","shell","hazard"],["","yoshi","shell"],["good","bird","bird"],["bad","bird","bird"],["","bird","hazard"],["","hazard","hazard"],["good","yoshi","bird"],["bad","yoshi","bird"],["","yoshi","hazard"],["same","yoshi","yoshi"],["diff","yoshi","yoshi"],["good","kite","kite"],["bad","kite","kite"],["good","kite","cut"],["bad","kite","cut"],["","kite","T"],["good","kite","N"],["bad","kite","N"],["","kite","tie"],["","cut","T"],["good","cut","N"],["bad","cut","N"],["","cut","tie"],["good","cut","cut"],["bad","cut","cut"],["good","T","T"],["bad","T","T"],["","T","N"],["good","T","tie"],["bad","T","tie"],["good","N","N"],["bad","N","N"],["","tie","N"],["good","tie","tie"],["bad","tie","tie"]];static OBL_LEN={"solved/solved":0,"1c/1c":5,"cadj/cadj":4,"cadj/copp":5,"copp/copp":2,"3c/3c":5,"4e/4e":4,"3e/3e":5,"line/line":2,"L/line":5,"L/L":4,"1e/1e":5,"good pair/pair":2,"bad pair/pair":4,"good arrow/pair":3,"bad arrow/pair":4,"good arrow/arrow":3,"bad arrow/arrow":4,"gem/gem":4,"gem/knight":4,"gem/axe":3,"gem/squid":4,"good knight/knight":4,"bad knight/knight":5,"good knight/axe":3,"bad knight/axe":4,"same axe/axe":5,"diff axe/axe":5,"squid/knight":4,"squid/axe":4,"squid/squid":5,"good thumb/thumb":2,"bad thumb/thumb":5,"good thumb/bunny":4,"bad thumb/bunny":4,"good bunny/bunny":3,"bad bunny/bunny":5,"shell/shell":4,"shell/bird":4,"shell/hazard":4,"yoshi/shell":3,"good bird/bird":4,"bad bird/bird":5,"bird/hazard":4,"hazard/hazard":5,"good yoshi/bird":3,"bad yoshi/bird":4,"yoshi/hazard":4,"same yoshi/yoshi":5,"diff yoshi/yoshi":5,"good kite/kite":1,"bad kite/kite":5,"good kite/cut":3,"bad kite/cut":6,"kite/T":4,"good kite/N":3,"bad kite/N":4,"kite/tie":4,"cut/T":4,"good cut/N":4,"bad cut/N":5,"cut/tie":4,"good cut/cut":3,"bad cut/cut":6,"good T/T":3,"bad T/T":4,"T/N":5,"good T/tie":3,"bad T/tie":4,"good N/N":2,"bad N/N":4,"tie/N":5,"good tie/tie":3,"bad tie/tie":4};static OBL_TRANSLATION={"solved/solved":["solved/solved"],"1c/1c":["1c/1c"],"cadj/cadj":["cadj/cadj"],"cadj/copp":["cadj/copp"],"copp/copp":["copp/copp"],"3c/3c":["3c/3c"],"4e/4e":["4e/4e"],"3e/3e":["3e/3e"],"line/line":["line/line"],"L/line":["L/line"],"L/L":["L/L"],"1e/1e":["1e/1e"],"good pair/pair":["left pair/left pair","right pair/right pair"],"bad pair/pair":["left pair/right pair"],"good arrow/pair":["left arrow/right pair","right arrow/left pair"],"bad arrow/pair":["left arrow/left pair","right arrow/right pair"],"good arrow/arrow":["left arrow/left arrow","right arrow/right arrow"],"bad arrow/arrow":["left arrow/right arrow"],"gem/gem":["gem/gem"],"gem/knight":["gem/left knight","gem/right knight"],"gem/axe":["gem/left axe","gem/right axe"],"gem/squid":["gem/squid"],"good knight/knight":["left knight/right knight"],"bad knight/knight":["left knight/left knight","right knight/right knight"],"good knight/axe":["left knight/left axe","right knight/right axe"],"bad knight/axe":["left knight/right axe","right knight/left axe"],"same axe/axe":["left axe/left axe","right axe/right axe"],"diff axe/axe":["left axe/right axe"],"squid/knight":["squid/left knight","squid/right knight"],"squid/axe":["squid/left axe","squid/right axe"],"squid/squid":["squid/squid"],"good thumb/thumb":["left thumb/left thumb","right thumb/right thumb"],"bad thumb/thumb":["left thumb/right thumb"],"good thumb/bunny":["left thumb/right bunny","right thumb/left bunny"],"bad thumb/bunny":["left thumb/left bunny","right thumb/right bunny"],"good bunny/bunny":["left bunny/left bunny","right bunny/right bunny"],"bad bunny/bunny":["left bunny/right bunny"],"shell/shell":["shell/shell"],"shell/bird":["shell/left bird","shell/right bird"],"shell/hazard":["shell/hazard"],"yoshi/shell":["left yoshi/shell","right yoshi/shell"],"good bird/bird":["left bird/right bird"],"bad bird/bird":["left bird/left bird","right bird/right bird"],"bird/hazard":["left bird/hazard","right bird/hazard"],"hazard/hazard":["hazard/hazard"],"good yoshi/bird":["left yoshi/left bird","right yoshi/right bird"],"bad yoshi/bird":["left yoshi/right bird","right yoshi/left bird"],"yoshi/hazard":["left yoshi/hazard","right yoshi/hazard"],"same yoshi/yoshi":["left yoshi/left yoshi","right yoshi/right yoshi"],"diff yoshi/yoshi":["left yoshi/right yoshi"],"good kite/kite":["left kite/left kite","right kite/right kite"],"bad kite/kite":["left kite/right kite"],"good kite/cut":["left kite/left cut","right kite/right cut"],"bad kite/cut":["left kite/right cut","right kite/left cut"],"kite/T":["left kite/black T","left kite/white T","right kite/black T","right kite/white T"],"good kite/N":["left kite/right N","right kite/left N"],"bad kite/N":["left kite/left N","right kite/right N"],"kite/tie":["left kite/black tie","left kite/white tie","right kite/black tie","right kite/white tie"],"cut/T":["left cut/black T","left cut/white T","right cut/black T","right cut/white T"],"good cut/N":["left cut/left N","right cut/right N"],"bad cut/N":["left cut/right N","right cut/left N"],"cut/tie":["left cut/black tie","left cut/white tie","right cut/black tie","right cut/white tie"],"good cut/cut":["left cut/left cut","right cut/right cut"],"bad cut/cut":["left cut/right cut"],"good T/T":["black T/black T","white T/white T"],"bad T/T":["black T/white T"],"T/N":["black T/left N","black T/right N","white T/left N","white T/right N"],"good T/tie":["black T/black tie","white T/white tie"],"bad T/tie":["black T/white tie","white T/black tie"],"good N/N":["left N/left N","right N/right N"],"bad N/N":["left N/right N"],"tie/N":["black tie/left N","black tie/right N","white tie/left N","white tie/right N"],"good tie/tie":["black tie/black tie","white tie/white tie"],"bad tie/tie":["black tie/white tie"]};static CORNERS=[[""],["1","3","5","7"],["13","15","17","35","37","57"],["135","137","157","357"],["1357"]];static EDGES=[[""],["2","4","6","8"],["24","26","28","46","48","68"],["246","248","268","468"],["2468"]];static TOTAL_CORNERS=["","1","3","5","7","13","15","17","35","37","57","135","137","157","357","1357"];static TOTAL_EDGES=["","2","4","6","8","24","26","28","46","48","68","246","248","268","468","2468"];constructor(t={"meow :3":"meow :3"}){this.tempReplacements={...t}}setTempReplacements(t){return this.tempReplacements={...t},this}addTempReplacements(t){return Object.assign(this.tempReplacements,t),this}dictReplace(t,e){const i=new RegExp(Object.keys(e).map(t=>t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join("|"),"g");let r;do{r=t,t=t.replace(i,t=>e[t])}while(t!==r);return t}addCommas(t){return t.split(/[/\\| ]/).map(t=>{if(!t||isNaN(Number(t.replaceAll("-","")))||t.includes(","))return t;switch(t.length){case 1:return t+",0";case 2:return"-"===t.charAt(0)?t+",0":t[0]+","+t[1];case 3:return"-"===t.charAt(0)?t.slice(0,2)+","+t[2]:t[0]+","+t.slice(1);case 4:return t.slice(0,2)+","+t.slice(2);default:throw new Error(`"${t}" is not a valid karn numeric move`)}}).join(" ")}isKarn(t){return/[a-zA-Z]/.test(t)}getAlignmentMove(t,e){return(t?"1":"0")+(e?"-1":"0")}getAlignment(t){if(!t)return{topA:!1,bottomA:!1};if(!(t=this.addCommas(t)).includes(","))throw new Error("getAlignment: move is weird: "+t);const[e,i]=t.split(",");return{topA:"0"!==e,bottomA:"0"!==i}}unkarnifyHelp(e){if(e=(e=e.trim().replaceAll(/[()]/g,"")).replaceAll(/ ([\/\\\|]) /g,"$1"),/[\/\\\|]{2,}/.test(e))throw new Error("unkarnifyHelp: Two slices in a row.");if(!this.isKarn(e))return e;let i,r;/[/\\| ]/.test(e)?(i=e.match(/^([^/\\| ]*)[/\\| ]/)?.[1],r=e.match(/[/\\| ]([^/\\| ]*)$/)?.[1]):i=r=e;let a=["/","\\","|"].includes(e.charAt(0))?e.charAt(0):i in t.karnToWCA?"/":"",n="/"===e.at(-1)||r in t.karnToWCA?"/":"";e=e.replaceAll(/[/\\| ]+/g," ");let s=(e=this.addCommas(e)).split(" ").filter(Boolean);for(let e=0;e<s.length;e++)s[e]in t.karnToWCA&&(s[e]=t.karnToWCA[s[e]].split(" "));s=s.flat();for(let e=0;e<s.length;e++)s[e]in t.karnToWCA&&(s[e]=t.karnToWCA[s[e]]);if(e=(e=a+s.join("/")+n).replaceAll(/ +/g,""),/[\/\\\|]{2,}/.test(e))throw new Error("unkarnifyHelp: Two slices in a row post-replacements.");return e}unkarnify(t){if(t in this.tempReplacements)return this.tempReplacements[t];let e,i=/^p[ /\\|]/.test(t);i&&(e=" "===t.charAt(1)?"/":t.charAt(1),t=t.slice(2,-3)),t=t.replaceAll("&","-1").replaceAll("^","-2").replaceAll("9","-3").replaceAll("8","-4").replaceAll("7","-5");for(const e of t.matchAll(/(\(.*?\))(\d+)/g)){const i=e[1].replaceAll(/[()]/g,""),r=parseInt(e[2],10);t=t.replace(e[0],Array(r).fill(i).join(" "))}let r=this.replaceShorthands(this.unkarnifyHelp(t));return i&&(["/","\\","|"].includes(r.charAt(0))&&(r=r.slice(1)),r="p"+e+r+"/p'"),r=r.replaceAll(/\/+/g,"/"),r}replaceShorthands(e){const i=e.split(/[\/\\\|]/);if(i.every(e=>!e||!this.isKarn(e)||" "+e+" "in t.karnToWCA))return this.unkarnifyHelp(e);let r=!1,a=!1;for(const n of i)if(n)if(n.includes(",")){const[t,e]=n.split(",");parseInt(t,10)%3!=0&&(r=!r),parseInt(e,10)%3!=0&&(a=!a)}else{const i=t.alignmentIndependent.has(n.toLowerCase())?n.toLowerCase():n.toLowerCase()+this.getAlignmentMove(r,a),s=t.shorthandToKarn[i];if(void 0===s)throw new Error(`replaceShorthands: "${n}" with alignment ${this.getAlignmentMove(r,a)} is not defined.`);e=e.replace(n,s);for(const t of this.unkarnifyHelp(s).split("/")){if(!t)continue;const[e,i]=t.split(",");parseInt(e,10)%3!=0&&(r=!r),parseInt(i,10)%3!=0&&(a=!a)}}return this.unkarnifyHelp(e)}parseScramble(t){const e=[],i=t.replace(/[\/\\\|]/g," / ").trim().split(/\s+/).filter(Boolean);for(let t of i)if(t.startsWith("p"))e.push({type:"turn",top:0,bottom:0});else if("/"===t)e.push({type:"twist"});else{if(t=this.addCommas(t.replace(/[()]/g,"")),!t.includes(","))throw new Error(`parseScramble: move: ${t} is weird.`);const[i,r]=t.split(",").map(t=>parseInt(t.trim(),10));isNaN(i)||isNaN(r)||e.push({type:"turn",top:i,bottom:r})}return e}twist(t,e){return{tlHex:t.slice(0,6)+e.slice(0,6),blHex:t.slice(6)+e.slice(6)}}doSlice(e){const[i,r,a,n]=[e.slice(0,t.HALF_L),e.slice(t.HALF_L,t.LAYERL),e.slice(t.LAYERL,t.THREE_FOUR_L),e.slice(t.THREE_FOUR_L,t.CUBEL)],s=t=>t===t.toUpperCase();if(![i,r,a,n].map(t=>!s(t.at(0))||s(t.at(1))&&!s(t.at(-1))||s(t.at(-2))).every(Boolean))throw new Error("doSlice: unsliceable position encountered");return a+r+i+n}algToHex(t){let e="011233455677",i="998bbaddcffe";for(const r of this.parseScramble(this.unkarnify(t)))"twist"===r.type?({tlHex:e,blHex:i}=this.twist(e,i)):(e=this.shift(e,-r.top),i=this.shift(i,-r.bottom));return{tlHex:e,blHex:i}}doMoves(e,i){void 0===i&&(i=t.SOLVED);for(const t of this.unkarnify(e).split("/")){const e=t.trim();if(""!==e){const[t,r]=e.split(",").map(Number);i=this.moveCube(i,t,r)}i=this.doSlice(i)}return this.doSlice(i)}moveCube(e,i,r){return this.shift(e.slice(0,t.LAYERL),i)+this.shift(e.slice(t.LAYERL),r)}invertScramble(t){return t?this.unkarnify(t).trim().split("/").reverse().map(t=>{const e=(t=t.trim()).includes("(")?t.match(/\(([^)]+)\)/)?.[1]:t.includes(",")?t:null;if(!e)return t;const i=e.split(",").map(t=>{const e=parseInt(t.trim(),10);return isNaN(e)?t.trim():String(-e)}).join(",");return t.includes("(")?`(${i})`:i}).join("/"):t}isPBL(t){let{tlHex:e,blHex:i}=t,r=[...e],a=[...i];return r[1]===r[2]&&r[4]===r[5]&&r[7]===r[8]&&r[10]===r[11]&&(parseInt(r[0],10)%2==0&&parseInt(r[1],10)%2==1&&parseInt(r[3],10)%2==0&&parseInt(r[4],10)%2==1&&parseInt(r[6],10)%2==0&&parseInt(r[7],10)%2==1&&parseInt(r[9],10)%2==0&&parseInt(r[10],10)%2==1&&(!!(r.includes("0")&&r.includes("1")&&r.includes("2")&&r.includes("3")&&r.includes("4")&&r.includes("5")&&r.includes("6")&&r.includes("7"))&&(a[0]===a[1]&&a[3]===a[4]&&a[6]===a[7]&&a[9]===a[10]&&(parseInt(a[0],16)%2==1&&parseInt(a[2],16)%2==0&&parseInt(a[3],16)%2==1&&parseInt(a[5],16)%2==0&&parseInt(a[6],16)%2==1&&parseInt(a[8],16)%2==0&&parseInt(a[9],16)%2==1&&parseInt(a[11],16)%2==0&&!!(a.includes("8")&&a.includes("9")&&a.includes("a")&&a.includes("b")&&a.includes("c")&&a.includes("d")&&a.includes("e")&&a.includes("f"))))))}karnify(e){if(e=e.trim(),/[\/\\\|]{2,}/.test(e))throw new Error("karnify: Two slices in a row.");if(this.isKarn(e))throw new Error("karnify: Alg has letters. Try unkarnifying first.");let i=["/","\\","|"].includes(e.charAt(0)),r=i?e.charAt(0):"",a="/"===e.at(-1),n=a?"/":"",s=(e=e.replaceAll(/[/\\| ]+/g," ")).split(" ").filter(Boolean);for(let e=0;e<s.length;e++)if(0!==e||i){if(e===s.length-1&&!a)break;s[e]=t.wcaToBaseKarn[s[e]]?t.wcaToBaseKarn[s[e]]:s[e].replace(",","")}return e=r+s.join(" ")+n,e=this.dictReplace(e,t.baseKarnToHighKarn)}legalMove(t){return(t%=12)<-5?t+12:t>6?t-12:t}addMoves(t,e){if(!t&&!e)throw new Error("addMoves: both moves are empty.");if(!t)return e;if(!e)return t;const i={A:"a",a:"A"};if(t in i&&e in i)throw new Error("addMoves: both moves cannot be alignment markers.");if(t in i){const r=parseInt(e.split(",")[0],10);return this.changesAlignment(r)?i[t]:t}if(e in i){const r=parseInt(t.split(",")[0],10);return this.changesAlignment(r)?i[e]:e}const[r,a]=t.split(",").map(Number),[n,s]=e.split(",").map(Number);return`${this.legalMove(r+n)},${this.legalMove(a+s)}`}changesAlignment(t){return t%3!=0}optimize(e){const i=Object.keys(t.OPTIM);for(;this.dictReplace(e,t.OPTIM)!==e;){const r=e.split("/").map(t=>t.trim());let a=0,n=!1;for(let s=0;s<e.length&&!n;s++)if("/"===e[s]){a++;for(const l of i)if(!(e.length-1-s<l.length)&&e.slice(s,s+l.length)===l){if("/0,0/"===l)r[a-1]=this.addMoves(r[a-1],r[a+1]),r.splice(a,2);else{const e=l.split("/").length,i=t.OPTIM[l].split("/"),n=e-2;r[a-1]=this.addMoves(r[a-1],i.shift()),r[a+e-2]=this.addMoves(r[a+e-2],i.pop()),r.splice(a,n,...i)}e=r.join("/"),n=!0;break}}}return e}getMoveValue(e,i,r){let a=r.indexOf(",");if(-1===a&&(a=this.addCommas(r).indexOf(","),-1===a))throw new Error(`getMoveValue: move: ${r} is weird`);const n=i?"/":"\\";let s;return s=parseInt(r.slice(0,a),10)%3==0?(e?"A":"a")+n+r:n+r,t.MOVE_VALUES.get(s)??5}getOverwork(e){const i=[],r=[];for(const t of e){let e=t.indexOf(",");if(-1===e){if(e=this.addCommas(t).indexOf(","),-1===e)throw new Error(`getOverwork: in moves, m: ${t} is weird.`)}i.push(parseInt(t.slice(0,e),10)||0),r.push(parseInt(t.slice(e+1),10)||0)}let a=0,n=0,s=0,l=0,o=0;for(const e of i){if(6===e||e<0){if(s++,!t.CLOSEST_MAP.has(e))throw new Error("getOverwork: top move is weird: "+e);l+=Math.abs(t.CLOSEST_MAP.get(e)),o+=Math.abs(e),s>1&&l>3&&(a+=o,o=0)}else s=0,l=0,o=0}s=0,l=0,o=0;for(const e of r){if(e>0){if(s++,!t.CLOSEST_MAP.has(e))throw new Error("getOverwork: top move is weird: "+e);l+=Math.abs(t.CLOSEST_MAP.get(e)),o+=Math.abs(e),s>1&&l>3&&(a+=o,o=0)}else s=0,l=0,o=0}for(let t=0;t+1<i.length;t++)i[t]+i[t+1]===0&&n++,r[t]+r[t+1]===0&&n++;return{movement:a,bonus:n}}rateAlg(t,e=!1,i={}){const r=i.W1??34,a=i.W2??100,n=i.W3??38,s=i.W4??500,l=i.W5??10;let o=t.replace(/\[.*$/,"").trim();const h=(this.isKarn(o)?this.unkarnify(o):o.replaceAll(" ","")).split("/").filter((t,e)=>0===e||""!==t.trim()).map(t=>t.trim()),d=h.length-1;if(d<=0)return{score:s,sliceStart:" "};let c=0,u=0,g=!1,f=!0;for(let i=0;i<h.length-1;i++){let r=h[i],a=r.indexOf(",");if(-1===a&&(r=r?this.addCommas(r):"0,0",a=r.indexOf(","),-1===a))throw new Error(`rateAlg:\nalg: ${t}\nmove: ${r}\nis weird.`);const n=parseInt(r.slice(0,a),10);if(isNaN(n))throw new Error(`rateAlg:\nalg: ${t}\nmove: ${r}\nis weird.`);0!==i?(c+=this.getMoveValue(g,f,r),u+=this.getMoveValue(g,!f,r),g=g!==(n%3!=0),f=!f):(g=e!==(n%3!=0),f=!0)}const b=r*Math.max(c,u)/d;let p="|";Math.abs(c-u)/d>5&&(p=c>u?"/":"\\");const w=a*d,m=h.slice(1,-1),{movement:W,bonus:B}=this.getOverwork(m);return{score:b-w-n*W/d+B*l/d+s,sliceStart:p}}rateAndSort(t,e=""){let i=!1;if(e){const t=e[0];i=/[A-HU-W]/i.test(t)}return t.map(t=>{const e=t.indexOf("["),r=e>0?t.slice(0,e).trim():t.trim();let a={alg:t,score:500},n=!1,s=" ";const l=this.isKarn(r)?this.unkarnify(r):r;if(({score:a.score,sliceStart:s}=this.rateAlg(l,i)),n=!0,["/","\\","|"].includes(s)){const e=t.indexOf("/");e>=0&&(a.alg=t.slice(0,e)+s+t.slice(e+1))}return a}).sort((t,e)=>e.score-t.score)}sepIndex(t){let e=0;for(const i of t)if(e++,/\d/.test(i))break;return e}compl(t){if(!t)return t;const e=this.sepIndex(t);return String(this.legalMove(6+parseInt(t.slice(0,e),10)))+String(this.legalMove(6+parseInt(t.slice(e),10)))}lf(t){if(!t)return t;const e=this.sepIndex(t);return t.slice(e)+t.slice(0,e)}compact(t){let e=t.replace(/\[.*?\]/g,"").replace(/[()]/g,"").replaceAll(" ","").trim();if(this.isKarn(e)){return this.unkarnify(e).split("/").filter(Boolean).map(t=>{if(!t.includes(","))throw new Error(`algToInternal: m doesn't have commas post karnifying: ${t}`);const[e,i]=t.split(",");return String(this.legalMove(parseInt(e,10)))+String(this.legalMove(parseInt(i,10)))}).join(" ")}return e=e.trim(),e.includes("/")?e.split("/").filter(Boolean).map(t=>{if(t.includes(",")||(t=this.addCommas(t)),!t.includes(","))throw new Error(`algToInternal: m doesn't have commas post addComma: ${t}`);const[e,i]=t.split(",");return String(this.legalMove(parseInt(e,10)))+String(this.legalMove(parseInt(i,10)))}).join(" "):e.split(" ").filter(t=>t).map(t=>{const e=t.includes(",")?t.split(","):[t.slice(0,this.sepIndex(t)),t.slice(this.sepIndex(t))];return String(this.legalMove(parseInt(e[0],10)))+String(this.legalMove(parseInt(e[1],10)))}).join(" ")}countY2Positions(t){const e=this.compact(t).split(" ").filter(t=>t);return Math.max(0,e.length-3)}applyY2s(e,i,r=null){let a=e.replaceAll(/\[.*?\]/g,"").trim();i||(i=[]);const n=this.isKarn(a),s=null===r?n:r;a=this.unkarnify(e);let l=a.split("/");const o=l[0],h=l[l.length-1];let d=!1,c=!1;for(let t=1;t<=l.length-3;t++){let e=l[t];e=c?this.lf(e):e,i.includes(t)&&(e=this.compl(e),d=!d),c=d?!c:c,l[t]=e}const u=l.length-2;c&&(l[u]=this.lf(l[u])),d!==c&&(l[u]=this.compl(l[u]));const g=l[u];for(let t=0;t<l.length;t++)l[t]=this.addCommas(l[t]);a=l.join("/");let f="";g&&!t.GOOD_FINISHES.has(g)&&(f+=" (bad finish)");const{topA:b,bottomA:p}=this.getAlignment(o),{topA:w,bottomA:m}=this.getAlignment(h);return b!==p&&b!==w&&w!==m&&(f+=" (alignment changes in CS)"),s&&(a=this.karnify(a)),a+f}layerFlip(t){const e={b:"w",B:"W",w:"b",W:"B"};return[...t].map(t=>{if(t in e)return e[t];throw new Error("layerFlip: unrecognized character: "+t)}).join("")}shift(t,e){return e=(-e%t.length+t.length)%t.length,t.slice(e)+t.slice(0,e)}oblName(t){return t[0]?`${t[0]} ${t[1]}/${t[2]}`:`${t[1]}/${t[2]}`}layerFlipName(t){const e=(t=t.replace("/"," ")).split(" ");return 2===e.length?e[1]+"/"+e[0]:e[0]+" "+e[2]+"/"+e[1]}speToNonSpe(e){const[i,r]=e.split("/"),a=i.split(" ").pop(),n=r.split(" ").pop(),s=t.POSSIBLE_OBL.filter(t=>t.includes(a)&&t.includes(n)).map(t=>this.oblName(t));for(const i of s){const r=t.OBL_TRANSLATION[i]||[];for(const t of r){if(t===e)return i;const[r,a]=t.split("/");if(`${a}/${r}`===e)return this.layerFlipName(i)}}throw new Error(`speToNonSpe: No non-specific OBL found for: ${e}`)}isOBLCase(e,i){const r=Object.entries(t.OBLToEnglish).find(([,t])=>t===i)?.[0];if(!r)return!1;e[0]!==e[0].toUpperCase()&&(e=this.shift(e,-1));for(let t=0;t<4;t++)if(r===this.shift(e,-3*t))return t;if(!["T","tie"].includes(i.split(" ").pop())){const t=this.layerFlip(e);for(let e=0;e<4;e++)if(r===this.shift(t,-3*e))return e}return!1}layerToOBL(e){for(const i of Object.keys(t.OBLToState))if(this.isOBLCase(e,i))return{obl:i,angleOffset:this.isOBLCase(e,i)};throw new Error("layerToOBL: no OBL matched layer: "+e)}getAngle(e,i,r,a){let n=t.OBL_ANGLES[e],s=t.OBL_ANGLES[i];for(let e=0;e<r%4;e++)n=t.nextAngle[n];for(let e=0;e<a%4;e++)s=t.nextAngle[s];return`${n} ${s}`}cubeToSpe(e){return[this.layerToOBL(e.slice(0,t.LAYERL)),this.layerToOBL(e.slice(t.LAYERL))]}getOBLLen(t){return t in OBL_LEN?OBL_LEN[t]:OBL_LEN[layer_flip_name(t)]}stateToLen(t,e){return this.getOBLLen(this.speToNonSpe(t+"/"+e))}getOBLNaming(e,i){return t.NAMING[e]+"/"+t.NAMING[i]}stateToMatt(e){let i=e.slice(0,t.LAYERL),r=e.slice(t.LAYERL);i=i[0]!==i[0].toLowerCase()?this.shift(i,3):this.shift(i,2),r=r[0]!==r[0].toLowerCase()?this.shift(r,3):this.shift(r,2);let a="",n=1;for(let e=0;e<t.LAYERL;e+=3)"B"===i[e]&&(a+=n),"b"===i[e+2]&&(a+=n+1),n+=2;a=""===a?"- ":a+" ",n=1;for(let e=0;e<t.LAYERL;e+=3)"B"===r[e]&&(a+=n),"b"===r[e+2]&&(a+=n+1),n+=2;return" "===a[a.length-1]?a+"-":a}mattToLayer(t){const e=["W","W","w","W","W","w","W","W","w","W","W","w"];for(const i of t){const t=parseInt(i,10);t%2!=0?(e[3*Math.floor(t/2)]="B",e[3*Math.floor(t/2)+1]="B"):e[3*Math.floor(t/2)-1]="b"}return e.join("")}mattToNonSpe(t){const[e,i]=t.split(" ");return this.speToNonSpe(`${this.layerToOBL(this.mattToLayer(e))}/${this.layerToOBL(this.mattToLayer(i))}`)}sortOblp(t){return[...t].sort().join("")}}return t});
|
|
2
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).squanlib=e()}(this,function(){"use strict";class t{static karnToWCA={U4:"U U' U U'","U4'":"U' U U' U",D4:"D D' D D'","D4'":"D' D D' D",u4:"u u' u u'","u4'":"u' u u' u",d4:"d d' d d'","d4'":"d' d d' d",U3:"U U' U","U3'":"U' U U'",D3:"D D' D","D3'":"D' D D'",u3:"u u' u","u3'":"u' u u'",d3:"d d' d","d3'":"d' d d'",F3:"F F' F","F3'":"F' F F'",f3:"f f' f","f3'":"f' f f'",W:"U U'","W'":"U' U",B:"D D'","B'":"D' D",w:"u u'","w'":"u' u",b:"d d'","b'":"d' d",F2:"F F'","F2'":"F' F",f2:"f f'","f2'":"f' f",UU:"U U","UU'":"U' U'",DD:"D D","DD'":"D' D'",T2:"T T'","T2'":"T' T",t2:"t t'","t2'":"t' t",E2:"E E'","E2'":"E' E","ɇ":"U D","ɇ'":"U' D'","Ɇ":"U D'","Ɇ'":"U' D",U2:"6,0","U2'":"6,0",D2:"0,6",U2D:"6,3","U2D'":"6,-3","U2'D":"6,3","U2'D'":"6,-3",U2D2:"6,6",UD2:"3,6","U'D2":"-3,6",U:"3,0","U'":"-3,0",D:"0,3","D'":"0,-3",E:"3,-3","E'":"-3,3",e:"3,3","e'":"-3,-3",u:"2,-1","u'":"-2,1",d:"-1,2","d'":"1,-2",F:"4,1","F'":"-4,-1",f:"1,4","f'":"-1,-4",T:"2,-4","T'":"-2,4",t:"4,-2","t'":"-4,2",m:"2,2","m'":"-2,-2",M:"1,1","M'":"-1,-1",u2:"5,-1","u2'":"-5,1",d2:"-1,5","d2'":"1,-5",K:"5,2","K'":"-5,-2",k:"2,5","k'":"-2,-5",G:"5,-4","G'":"-5,4",g:"4,-5","g'":"-4,5"};static shorthandToKarn={bjj:"U' e D'",fjj:"U e' D",e2bjj:"U' e' U'",e2fjj:"U e U",nn:"E E'",jn:"D4'",nj:"U4",jj:"U e' D","bjj+e2":"U' e' U'","-nn":"E' E","-jn":"D4","-nj":"D4'",bpj10:"d m' U","bpj0-1":"u' m D'",fpj10:"u m' D","fpj0-1":"d' m U'",aa10:"u m' u T'","aa0-1":"U m' U t'",fadj10:"D M' d'",dadj10:"D M' d'","fadj0-1":"U' M u","u'adj0-1":"U' M u",badj10:"U M' u'",uadj10:"U M' u'","badj0-1":"D' M d","d'adj0-1":"D' M d",bb10:"T u' e U'","bb0-1":"t d e' D",fdd10:"D e' d t","fdd0-1":"U' e u' T",bdd10:"U e' u T'","bdd0-1":"D' e d' t'",ff10:"d m' d M E","ff0-1":"u' m U' M T",fv10:"d4","fv0-1":"d4'",vf10:"u4","vf0-1":"u4'",y2fv10:"u d' u -5,4",jf10:"w D' u T'","jf0-1":"w' D u' T",fj10:"b U' d t","fj0-1":"b' U d' t'",jr00:"e' w e",jr10:"e' b e","jr0-1":"e' w' e","jr1-1":"e' b' e",rj00:"e b' e'",rj10:"e w e'","rj0-1":"e b' e'","rj1-1":"e w e'",jv10:"b D d d2'","jv0-1":"b' D' d' d2",vj10:"w U u u2'","vj0-1":"w' U' u' u2",kk10:"u m' U E'","kk0-1":"U m' u E'",opp10:"u2 u2'","opp0-1":"u2' u2",pn10:"T T'","pn0-1":"t t'",px10:"f' d3' f'","px0-1":"f d3 f",xp10:"F' u3' F'","xp0-1":"F u3 F",tt10:"d m' F' u2'",fss10:"u M D' E'","fss0-1":"D' M u E'",bss10:"D M' u' E","bss0-1":"U' M d E",vv10:"u M u m' E'",zz10:"u M t' M D'","zz0-1":"D' M t' M u","30adj10":"U M' u'","-30adj0-1":"U' M u","03adj10":"D M' d'",obopp00:"1,0/M' F M' F M'/0,1","oaopp1-1":"0,1/M' u' M' u' M'/0,1",but00:"",also00:"","done!00":"0,0"};static alignmentIndependent=new Set(["bjj","fjj","nn","jn","nj","e2bjj","e2fjj","jj","bjj+e2","-nn","-jn","-nj"]);static wcaToBaseKarn={"6,0":"U2","6,3":"U2D","6,-3":"U2D'","6,6":"U2D2","0,6":"D2","3,6":"UD2","-3,6":"U'D2","3,0":"U","-3,0":"U'","0,3":"D","0,-3":"D'","3,-3":"E","-3,3":"E'","3,3":"e","-3,-3":"e'","2,-1":"u","-2,1":"u'","-1,2":"d","1,-2":"d'","4,1":"F","-4,-1":"F'","1,4":"f","-1,-4":"f'","2,-4":"T","-2,4":"T'","4,-2":"t","-4,2":"t'","2,2":"m","-2,-2":"m'","1,1":"M","-1,-1":"M'","5,-1":"u2","-5,1":"u2'","-1,5":"d2","1,-5":"d2'","5,2":"K","-5,-2":"K'","2,5":"k","-2,-5":"k'"};static baseKarnToHighKarn={"U U' U U'":"U4","U' U U' U":"U4'","D D' D D'":"D4","D' D D' D":"D4'","u u' u u'":"u4","u' u u' u":"u4'","d d' d d'":"d4","d' d d' d":"d4'","U U' U":"U3","U' U U'":"U3'","D D' D":"D3","D' D D'":"D3'","u u' u":"u3","u' u u'":"u3'","d d' d":"d3","d' d d'":"d3'","F F' F":"F3","F' F F'":"F3'","f f' f":"f3","f' f f'":"f3'","U U'":"W","U' U":"W'","D D'":"B","D' D":"B'","u u'":"w","u' u":"w'","d d'":"b","d' d":"b'","F F'":"F2","F' F":"F2'","f f'":"f2","f' f":"f2'","U U":"UU","U' U'":"UU'","D D":"DD","D' D'":"DD'"};static A_MOVES=[[3,0],[-3,0],[0,3],[0,-3],[3,3],[2,-1],[-1,2],[-4,-1],[-1,-4],[2,-4],[2,2],[-1,-1],[5,-1]];static a_MOVES=[[3,0],[-3,0],[0,3],[0,-3],[3,3],[-2,1],[1,-2],[4,1],[1,4],[-2,4],[-2,-2],[1,1],[-5,1]];static OPTIM={"/0,0/":"","/3,3/3,3/":"-3,-3/-3,-3","/-3,-3/-3,-3/":"3,3/3,3","/2,2/-2,-2/":"2,2/-2,-2","/-2,-2/2,2/":"-2,-2/2,2","/1,1/-1,-1/":"1,1/-1,-1","/-1,-1/1,1/":"-1,-1/1,1","/2,-4/-2,4/2,-4/":"2,-4/-2,4/2,-4","/-2,4/2,-4/-2,4/":"-2,4/2,-4/-2,4","/5,-1/-5,1/5,-1/":"5,-1/-5,1/5,-1","/-5,1/5,-1/-5,1/":"-5,1/5,-1/-5,1"};static CLOSEST_MAP=new Map([[-5,-6],[-4,-3],[-3,-3],[-2,-3],[-1,0],[0,0],[1,0],[2,3],[3,3],[4,3],[5,6],[6,6]]);static MOVE_VALUES=new Map([["A/0,3",16],["A/0,6",1],["A/0,-3",18],["A/3,0",16],["A/3,3",12],["A/3,6",0],["A/3,-3",13],["A/6,0",12],["A/6,3",11],["A/6,6",2],["A/6,-3",12],["A/-3,0",9],["A/-3,3",13],["A/-3,6",4],["A/-3,-3",12],["A\\0,3",17],["A\\0,6",1],["A\\0,-3",8],["A\\3,0",6],["A\\3,3",14],["A\\3,6",1],["A\\3,-3",12],["A\\6,0",14],["A\\6,3",11],["A\\6,6",5],["A\\6,-3",8],["A\\-3,0",11],["A\\-3,3",14],["A\\-3,6",6],["A\\-3,-3",9],["a/0,3",5],["a/0,6",5],["a/0,-3",12],["a/3,0",17],["a/3,3",10],["a/3,6",5],["a/3,-3",7],["a/6,0",4],["a/6,3",2],["a/6,6",0],["a/6,-3",3],["a/-3,0",18],["a/-3,3",12],["a/-3,6",7],["a/-3,-3",11],["a\\0,3",5],["a\\0,6",5],["a\\0,-3",5],["a\\3,0",16],["a\\3,3",11],["a\\3,6",4],["a\\3,-3",6],["a\\6,0",4],["a\\6,3",2],["a\\6,6",0],["a\\6,-3",1],["a\\-3,0",15],["a\\-3,3",10],["a\\-3,6",2],["a\\-3,-3",5],["/1,-2",4],["\\1,-2",17],["/-1,2",15],["\\-1,2",14],["/1,-5",3],["\\1,-5",1],["/-1,5",8],["\\-1,5",3],["/1,4",7],["\\1,4",14],["/-1,-4",12],["\\-1,-4",9],["/1,1",11],["\\1,1",20],["/-1,-1",20],["\\-1,-1",10],["/2,-1",20],["\\2,-1",12],["/-2,1",14],["\\-2,1",18],["/2,2",12],["\\2,2",13],["/-2,-2",14],["\\-2,-2",8],["/2,5",5],["\\2,5",3],["/-2,-5",4],["\\-2,-5",3],["/2,-4",14],["\\2,-4",6],["/-2,4",13],["\\-2,4",13],["/4,4",5],["\\4,4",12],["/-4,-4",12],["\\-4,-4",4],["/4,1",6],["\\4,1",13],["/-4,-1",16],["\\-4,-1",6],["/4,-2",12],["\\4,-2",9],["/-4,2",16],["\\-4,2",13],["/4,-5",2],["\\4,-5",5],["/-4,5",13],["\\-4,5",3],["/5,5",1],["\\5,5",4],["/-5,-5",2],["\\-5,-5",0],["/5,2",6],["\\5,2",10],["/-5,-2",12],["\\-5,-2",13],["/5,-1",11],["\\5,-1",7],["/-5,1",14],["\\-5,1",15],["/5,-4",2],["\\5,-4",2],["/-5,4",12],["\\-5,4",14]]);static GOOD_FINISHES=new Set(["1,1","-1,-1","2,2","-2,-2","2,-1","-2,1","1,-2","-1,2","3,0","-3,0","0,3","0,-3","3,3","3,-3","-3,-3","-3,3","4,1","-4,-1","1,4","-1,-4","2,-4","-2,4","4,-2","-4,2","5,-1","-5,1","-4,5","-5,4","6,3"]);static OBLToEnglish={BBbBBbBBbBBb:"solved",BBwWWwWWwWWw:"1c",BBwBBwWWwWWw:"cadj",BBwWWwBBwWWw:"copp",BBwBBwBBwWWw:"3c",BBwBBwBBwBBw:"4e",WWbWWbWWbWWw:"3e",WWbWWwWWbWWw:"line",WWbWWbWWwWWw:"L",WWbWWwWWwWWw:"1e",WWbBBwWWwWWw:"left pair",BBbWWwWWwWWw:"right pair",BBwWWwWWbWWw:"left arrow",BBwWWbWWwWWw:"right arrow",WWbBBbWWwWWw:"gem",WWwWWbWWbBBw:"left knight",BBbWWbWWwWWw:"right knight",WWwWWbWWwBBb:"left axe",BBwWWbWWwWWb:"right axe",BBwWWbWWbWWw:"squid",WWwWWbBBbWWb:"left thumb",WWbBBbWWwWWb:"right thumb",WWwBBbWWbWWb:"left bunny",WWbWWbBBwWWb:"right bunny",BBbBBwWWwWWw:"shell",BBwWWwWWbBBw:"left bird",BBwBBbWWwWWw:"right bird",BBwWWbWWwBBw:"hazard",BBbBBbWWwWWw:"left kite",WWwWWbBBbBBw:"right kite",BBwBBwWWbWWb:"left cut",BBwBBbWWbWWw:"right cut",BBbBBwWWbWWw:"black T",WWwWWbBBwBBb:"white T",WWbBBwWWbBBw:"left N",WWwBBbWWwBBb:"right N",WWbBBbWWwBBw:"black tie",BBwWWwBBbWWb:"white tie",BBbWWwBBwWWw:"left yoshi",WWwBBwWWbBBw:"right yoshi"};static OBLToState=Object.fromEntries(Object.entries(this.OBLToEnglish).map(([t,e])=>[e,t]));static NAMING={solved:"O","1c":"D",cadj:"J",copp:"V","3c":"M","4e":"Q","3e":"W",line:"F",L:"L","1e":"E","left pair":"Pw","right pair":"Pc","left arrow":"Aw","right arrow":"Ac",gem:"G","left knight":"Hw","right knight":"Hc","left axe":"Xc","right axe":"Xw",squid:"S","left thumb":"THw","right thumb":"THc","left bunny":"Uc","right bunny":"Uw",shell:"SH","left bird":"Bc","right bird":"Bw",hazard:"Z","left kite":"Kc","right kite":"Kw","left cut":"Cw","right cut":"Cc","black T":"Tu","white T":"Td","left N":"Nw","right N":"Nc","black tie":"Iu","white tie":"Id","left yoshi":"Yc","right yoshi":"Yw"};static OBL_ANGLES={solved:"-","1c":"UR",cadj:"R",copp:"/","3c":"DR","4e":"-","3e":"D",line:"—",L:"DR","1e":"R","left pair":"DR","right pair":"UR","left arrow":"UR","right arrow":"UR",gem:"DR","left knight":"L","right knight":"R","left axe":"L","right axe":"R",squid:"UR","left thumb":"DL","right thumb":"DR","left bunny":"DR","right bunny":"DL",shell:"R","left bird":"R","right bird":"U",hazard:"U","left kite":"R","right kite":"L","left cut":"R","right cut":"R","black T":"R","white T":"R","left N":"\\","right N":"\\","black tie":"DR","white tie":"DR","left yoshi":"UL","right yoshi":"UR"};static nextAngle={"-":"-","/":"\\","\\":"/","—":"|","|":"—",U:"R",R:"D",D:"L",L:"U",UR:"DR",DR:"DL",DL:"UL",UL:"UR"};static get HALF_L(){return 6}static get LAYERL(){return 12}static get THREE_FOUR_L(){return 18}static get CUBEL(){return 24}static get SOLVED(){return"bBBbBBbBBbBBwWWwWWwWWwWW"}static POSSIBLE_OBL=[["","solved","solved"],["","1c","1c"],["","cadj","cadj"],["","cadj","copp"],["","copp","copp"],["","3c","3c"],["","4e","4e"],["","3e","3e"],["","line","line"],["","L","line"],["","L","L"],["","1e","1e"],["good","pair","pair"],["bad","pair","pair"],["good","arrow","pair"],["bad","arrow","pair"],["good","arrow","arrow"],["bad","arrow","arrow"],["","gem","gem"],["","gem","knight"],["","gem","axe"],["","gem","squid"],["good","knight","knight"],["bad","knight","knight"],["good","knight","axe"],["bad","knight","axe"],["same","axe","axe"],["diff","axe","axe"],["","squid","knight"],["","squid","axe"],["","squid","squid"],["good","thumb","thumb"],["bad","thumb","thumb"],["good","thumb","bunny"],["bad","thumb","bunny"],["good","bunny","bunny"],["bad","bunny","bunny"],["","shell","shell"],["","shell","bird"],["","shell","hazard"],["","yoshi","shell"],["good","bird","bird"],["bad","bird","bird"],["","bird","hazard"],["","hazard","hazard"],["good","yoshi","bird"],["bad","yoshi","bird"],["","yoshi","hazard"],["same","yoshi","yoshi"],["diff","yoshi","yoshi"],["good","kite","kite"],["bad","kite","kite"],["good","kite","cut"],["bad","kite","cut"],["","kite","T"],["good","kite","N"],["bad","kite","N"],["","kite","tie"],["","cut","T"],["good","cut","N"],["bad","cut","N"],["","cut","tie"],["good","cut","cut"],["bad","cut","cut"],["good","T","T"],["bad","T","T"],["","T","N"],["good","T","tie"],["bad","T","tie"],["good","N","N"],["bad","N","N"],["","tie","N"],["good","tie","tie"],["bad","tie","tie"]];static OBL_LEN={"solved/solved":0,"1c/1c":5,"cadj/cadj":4,"cadj/copp":5,"copp/copp":2,"3c/3c":5,"4e/4e":4,"3e/3e":5,"line/line":2,"L/line":5,"L/L":4,"1e/1e":5,"good pair/pair":2,"bad pair/pair":4,"good arrow/pair":3,"bad arrow/pair":4,"good arrow/arrow":3,"bad arrow/arrow":4,"gem/gem":4,"gem/knight":4,"gem/axe":3,"gem/squid":4,"good knight/knight":4,"bad knight/knight":5,"good knight/axe":3,"bad knight/axe":4,"same axe/axe":5,"diff axe/axe":5,"squid/knight":4,"squid/axe":4,"squid/squid":5,"good thumb/thumb":2,"bad thumb/thumb":5,"good thumb/bunny":4,"bad thumb/bunny":4,"good bunny/bunny":3,"bad bunny/bunny":5,"shell/shell":4,"shell/bird":4,"shell/hazard":4,"yoshi/shell":3,"good bird/bird":4,"bad bird/bird":5,"bird/hazard":4,"hazard/hazard":5,"good yoshi/bird":3,"bad yoshi/bird":4,"yoshi/hazard":4,"same yoshi/yoshi":5,"diff yoshi/yoshi":5,"good kite/kite":1,"bad kite/kite":5,"good kite/cut":3,"bad kite/cut":6,"kite/T":4,"good kite/N":3,"bad kite/N":4,"kite/tie":4,"cut/T":4,"good cut/N":4,"bad cut/N":5,"cut/tie":4,"good cut/cut":3,"bad cut/cut":6,"good T/T":3,"bad T/T":4,"T/N":5,"good T/tie":3,"bad T/tie":4,"good N/N":2,"bad N/N":4,"tie/N":5,"good tie/tie":3,"bad tie/tie":4};static OBL_TRANSLATION={"solved/solved":["solved/solved"],"1c/1c":["1c/1c"],"cadj/cadj":["cadj/cadj"],"cadj/copp":["cadj/copp"],"copp/copp":["copp/copp"],"3c/3c":["3c/3c"],"4e/4e":["4e/4e"],"3e/3e":["3e/3e"],"line/line":["line/line"],"L/line":["L/line"],"L/L":["L/L"],"1e/1e":["1e/1e"],"good pair/pair":["left pair/left pair","right pair/right pair"],"bad pair/pair":["left pair/right pair"],"good arrow/pair":["left arrow/right pair","right arrow/left pair"],"bad arrow/pair":["left arrow/left pair","right arrow/right pair"],"good arrow/arrow":["left arrow/left arrow","right arrow/right arrow"],"bad arrow/arrow":["left arrow/right arrow"],"gem/gem":["gem/gem"],"gem/knight":["gem/left knight","gem/right knight"],"gem/axe":["gem/left axe","gem/right axe"],"gem/squid":["gem/squid"],"good knight/knight":["left knight/right knight"],"bad knight/knight":["left knight/left knight","right knight/right knight"],"good knight/axe":["left knight/left axe","right knight/right axe"],"bad knight/axe":["left knight/right axe","right knight/left axe"],"same axe/axe":["left axe/left axe","right axe/right axe"],"diff axe/axe":["left axe/right axe"],"squid/knight":["squid/left knight","squid/right knight"],"squid/axe":["squid/left axe","squid/right axe"],"squid/squid":["squid/squid"],"good thumb/thumb":["left thumb/left thumb","right thumb/right thumb"],"bad thumb/thumb":["left thumb/right thumb"],"good thumb/bunny":["left thumb/right bunny","right thumb/left bunny"],"bad thumb/bunny":["left thumb/left bunny","right thumb/right bunny"],"good bunny/bunny":["left bunny/left bunny","right bunny/right bunny"],"bad bunny/bunny":["left bunny/right bunny"],"shell/shell":["shell/shell"],"shell/bird":["shell/left bird","shell/right bird"],"shell/hazard":["shell/hazard"],"yoshi/shell":["left yoshi/shell","right yoshi/shell"],"good bird/bird":["left bird/right bird"],"bad bird/bird":["left bird/left bird","right bird/right bird"],"bird/hazard":["left bird/hazard","right bird/hazard"],"hazard/hazard":["hazard/hazard"],"good yoshi/bird":["left yoshi/left bird","right yoshi/right bird"],"bad yoshi/bird":["left yoshi/right bird","right yoshi/left bird"],"yoshi/hazard":["left yoshi/hazard","right yoshi/hazard"],"same yoshi/yoshi":["left yoshi/left yoshi","right yoshi/right yoshi"],"diff yoshi/yoshi":["left yoshi/right yoshi"],"good kite/kite":["left kite/left kite","right kite/right kite"],"bad kite/kite":["left kite/right kite"],"good kite/cut":["left kite/left cut","right kite/right cut"],"bad kite/cut":["left kite/right cut","right kite/left cut"],"kite/T":["left kite/black T","left kite/white T","right kite/black T","right kite/white T"],"good kite/N":["left kite/right N","right kite/left N"],"bad kite/N":["left kite/left N","right kite/right N"],"kite/tie":["left kite/black tie","left kite/white tie","right kite/black tie","right kite/white tie"],"cut/T":["left cut/black T","left cut/white T","right cut/black T","right cut/white T"],"good cut/N":["left cut/left N","right cut/right N"],"bad cut/N":["left cut/right N","right cut/left N"],"cut/tie":["left cut/black tie","left cut/white tie","right cut/black tie","right cut/white tie"],"good cut/cut":["left cut/left cut","right cut/right cut"],"bad cut/cut":["left cut/right cut"],"good T/T":["black T/black T","white T/white T"],"bad T/T":["black T/white T"],"T/N":["black T/left N","black T/right N","white T/left N","white T/right N"],"good T/tie":["black T/black tie","white T/white tie"],"bad T/tie":["black T/white tie","white T/black tie"],"good N/N":["left N/left N","right N/right N"],"bad N/N":["left N/right N"],"tie/N":["black tie/left N","black tie/right N","white tie/left N","white tie/right N"],"good tie/tie":["black tie/black tie","white tie/white tie"],"bad tie/tie":["black tie/white tie"]};static CORNERS=[[""],["1","3","5","7"],["13","15","17","35","37","57"],["135","137","157","357"],["1357"]];static EDGES=[[""],["2","4","6","8"],["24","26","28","46","48","68"],["246","248","268","468"],["2468"]];static TOTAL_CORNERS=["","1","3","5","7","13","15","17","35","37","57","135","137","157","357","1357"];static TOTAL_EDGES=["","2","4","6","8","24","26","28","46","48","68","246","248","268","468","2468"];constructor(t={"meow :3":"meow :3"}){this.tempReplacements={...t}}setTempReplacements(t){return this.tempReplacements={...t},this}addTempReplacements(t){return Object.assign(this.tempReplacements,t),this}dictReplace(t,e){const i=new RegExp(Object.keys(e).map(t=>t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join("|"),"g");let r;do{r=t,t=t.replace(i,t=>e[t])}while(t!==r);return t}addCommas(t){return t.split(/[/\\| ]/).map(t=>{if(!t||isNaN(Number(t.replaceAll("-","")))||t.includes(","))return t;switch(t.length){case 1:return t+",0";case 2:return"-"===t.charAt(0)?t+",0":t[0]+","+t[1];case 3:return"-"===t.charAt(0)?t.slice(0,2)+","+t[2]:t[0]+","+t.slice(1);case 4:return t.slice(0,2)+","+t.slice(2);default:throw new Error(`"${t}" is not a valid karn numeric move`)}}).join(" ")}isKarn(t){return/[a-zA-Z]/.test(t)}getAlignmentMove(t,e){return(t?"1":"0")+(e?"-1":"0")}getAlignment(t){if(!t)return{topA:!1,bottomA:!1};if(!(t=this.addCommas(t)).includes(","))throw new Error("getAlignment: move is weird: "+t);const[e,i]=t.split(",");return{topA:"0"!==e,bottomA:"0"!==i}}unkarnifyHelp(e){if(e=(e=e.trim().replaceAll(/[()]/g,"")).replaceAll(/ ([\/\\\|]) /g,"$1"),/[\/\\\|]{2,}/.test(e))throw new Error("unkarnifyHelp: Two slices in a row.");if(!this.isKarn(e))return e;let i,r;/[/\\| ]/.test(e)?(i=e.match(/^([^/\\| ]*)[/\\| ]/)?.[1],r=e.match(/[/\\| ]([^/\\| ]*)$/)?.[1]):i=r=e;let a=["/","\\","|"].includes(e.charAt(0))?e.charAt(0):i in t.karnToWCA?"/":"",n="/"===e.at(-1)||r in t.karnToWCA?"/":"";e=e.replaceAll(/[/\\| ]+/g," ");let s=(e=this.addCommas(e)).split(" ").filter(Boolean);for(let e=0;e<s.length;e++)s[e]in t.karnToWCA&&(s[e]=t.karnToWCA[s[e]].split(" "));s=s.flat();for(let e=0;e<s.length;e++)s[e]in t.karnToWCA&&(s[e]=t.karnToWCA[s[e]]);if(e=(e=a+s.join("/")+n).replaceAll(/ +/g,""),/[\/\\\|]{2,}/.test(e))throw new Error("unkarnifyHelp: Two slices in a row post-replacements.");return e}unkarnify(t){if(t in this.tempReplacements)return this.tempReplacements[t];t=(t=t.replaceAll("&","-1").replaceAll("^","-2").replaceAll("9","-3").replaceAll("8","-4").replaceAll("7","-5")).replaceAll(/\[.*?\]/g,"");let e,i=/^p[ /\\|]/.test(t);i&&(e=" "===t.charAt(1)?"/":t.charAt(1),t=t.slice(2,-3));for(const e of t.matchAll(/(\(.*?\))(\d+)/g)){const i=e[1].replaceAll(/[()]/g,""),r=parseInt(e[2],10);t=t.replace(e[0],Array(r).fill(i).join(" "))}let r=this.replaceShorthands(this.unkarnifyHelp(t));return i&&(["/","\\","|"].includes(r.charAt(0))&&(r=r.slice(1)),r="p"+e+r+"/p'"),r=r.replaceAll(/\/+/g,"/"),r}replaceShorthands(e){const i=e.split(/[\/\\\|]/);if(i.every(e=>!e||!this.isKarn(e)||" "+e+" "in t.karnToWCA))return this.unkarnifyHelp(e);let r=!1,a=!1;for(const n of i)if(n)if(n.includes(",")){const[t,e]=n.split(",");parseInt(t,10)%3!=0&&(r=!r),parseInt(e,10)%3!=0&&(a=!a)}else{const i=t.alignmentIndependent.has(n.toLowerCase())?n.toLowerCase():n.toLowerCase()+this.getAlignmentMove(r,a),s=t.shorthandToKarn[i];if(void 0===s)throw new Error(`replaceShorthands: "${n}" with alignment ${this.getAlignmentMove(r,a)} is not defined.`);e=e.replace(n,s);for(const t of this.unkarnifyHelp(s).split("/")){if(!t)continue;const[e,i]=t.split(",");parseInt(e,10)%3!=0&&(r=!r),parseInt(i,10)%3!=0&&(a=!a)}}return this.unkarnifyHelp(e)}parseScramble(t){const e=[],i=t.replace(/[\/\\\|]/g," / ").trim().split(/\s+/).filter(Boolean);for(let t of i)if(t.startsWith("p"))e.push({type:"turn",top:0,bottom:0});else if("/"===t)e.push({type:"twist"});else{if(t=this.addCommas(t.replace(/[()]/g,"")),!t.includes(","))throw new Error(`parseScramble: move: ${t} is weird.`);const[i,r]=t.split(",").map(t=>parseInt(t.trim(),10));isNaN(i)||isNaN(r)||e.push({type:"turn",top:i,bottom:r})}return e}twist(t,e){return{tlHex:t.slice(0,6)+e.slice(0,6),blHex:t.slice(6)+e.slice(6)}}doSlice(e){const[i,r,a,n]=[e.slice(0,t.HALF_L),e.slice(t.HALF_L,t.LAYERL),e.slice(t.LAYERL,t.THREE_FOUR_L),e.slice(t.THREE_FOUR_L,t.CUBEL)],s=t=>t===t.toUpperCase();if(![i,r,a,n].map(t=>!s(t.at(0))||s(t.at(1))&&!s(t.at(-1))||s(t.at(-2))).every(Boolean))throw new Error("doSlice: unsliceable position encountered");return a+r+i+n}algToHex(t){let e="011233455677",i="998bbaddcffe";for(const r of this.parseScramble(this.unkarnify(t)))"twist"===r.type?({tlHex:e,blHex:i}=this.twist(e,i)):(e=this.shift(e,-r.top),i=this.shift(i,-r.bottom));return{tlHex:e,blHex:i}}doMoves(e,i){void 0===i&&(i=t.SOLVED);for(const t of this.unkarnify(e).split("/")){const e=t.trim();if(""!==e){const[t,r]=e.split(",").map(Number);i=this.moveCube(i,t,r)}i=this.doSlice(i)}return this.doSlice(i)}moveCube(e,i,r){return this.shift(e.slice(0,t.LAYERL),i)+this.shift(e.slice(t.LAYERL),r)}invertScramble(t){return t?this.unkarnify(t).trim().split("/").reverse().map(t=>{const e=(t=t.trim()).includes("(")?t.match(/\(([^)]+)\)/)?.[1]:t.includes(",")?t:null;if(!e)return t;const i=e.split(",").map(t=>{const e=parseInt(t.trim(),10);return isNaN(e)?t.trim():String(-e)}).join(",");return t.includes("(")?`(${i})`:i}).join("/"):t}isPBL(t){let{tlHex:e,blHex:i}=t,r=[...e],a=[...i];return r[1]===r[2]&&r[4]===r[5]&&r[7]===r[8]&&r[10]===r[11]&&(parseInt(r[0],10)%2==0&&parseInt(r[1],10)%2==1&&parseInt(r[3],10)%2==0&&parseInt(r[4],10)%2==1&&parseInt(r[6],10)%2==0&&parseInt(r[7],10)%2==1&&parseInt(r[9],10)%2==0&&parseInt(r[10],10)%2==1&&(!!(r.includes("0")&&r.includes("1")&&r.includes("2")&&r.includes("3")&&r.includes("4")&&r.includes("5")&&r.includes("6")&&r.includes("7"))&&(a[0]===a[1]&&a[3]===a[4]&&a[6]===a[7]&&a[9]===a[10]&&(parseInt(a[0],16)%2==1&&parseInt(a[2],16)%2==0&&parseInt(a[3],16)%2==1&&parseInt(a[5],16)%2==0&&parseInt(a[6],16)%2==1&&parseInt(a[8],16)%2==0&&parseInt(a[9],16)%2==1&&parseInt(a[11],16)%2==0&&!!(a.includes("8")&&a.includes("9")&&a.includes("a")&&a.includes("b")&&a.includes("c")&&a.includes("d")&&a.includes("e")&&a.includes("f"))))))}karnify(e){if(e=e.trim(),/[\/\\\|]{2,}/.test(e))throw new Error("karnify: Two slices in a row.");if(this.isKarn(e))throw new Error("karnify: Alg has letters. Try unkarnifying first.");let i=["/","\\","|"].includes(e.charAt(0)),r=i?e.charAt(0):"",a="/"===e.at(-1),n=a?"/":"",s=(e=e.replaceAll(/[/\\| ]+/g," ")).split(" ").filter(Boolean);for(let e=0;e<s.length;e++){if(0===e&&!i){s[e]=s[e].replace(",","");continue}if(e===s.length-1&&!a){s[e]=s[e].replace(",","");break}let l=s[e]in t.wcaToBaseKarn;s[e]=l?t.wcaToBaseKarn[s[e]]:s[e].replace(",",""),l&&0===e&&(r=r.replace("/","")),l&&e===s.length-1&&(n="")}return e=r+s.join(" ")+n,e=this.dictReplace(e,t.baseKarnToHighKarn)}legalMove(t){return(t%=12)<-5?t+12:t>6?t-12:t}addMoves(t,e){if(!t&&!e)throw new Error("addMoves: both moves are empty.");if(!t)return e;if(!e)return t;const i={A:"a",a:"A"};if(t in i&&e in i)throw new Error("addMoves: both moves cannot be alignment markers.");if(t in i){const r=parseInt(e.split(",")[0],10);return this.changesAlignment(r)?i[t]:t}if(e in i){const r=parseInt(t.split(",")[0],10);return this.changesAlignment(r)?i[e]:e}const[r,a]=t.split(",").map(Number),[n,s]=e.split(",").map(Number);return`${this.legalMove(r+n)},${this.legalMove(a+s)}`}changesAlignment(t){return t%3!=0}optimize(e){const i=Object.keys(t.OPTIM);for(;this.dictReplace(e,t.OPTIM)!==e;){const r=e.split("/").map(t=>t.trim());let a=0,n=!1;for(let s=0;s<e.length&&!n;s++)if("/"===e[s]){a++;for(const l of i)if(!(e.length-1-s<l.length)&&e.slice(s,s+l.length)===l){if("/0,0/"===l)r[a-1]=this.addMoves(r[a-1],r[a+1]),r.splice(a,2);else{const e=l.split("/").length,i=t.OPTIM[l].split("/"),n=e-2;r[a-1]=this.addMoves(r[a-1],i.shift()),r[a+e-2]=this.addMoves(r[a+e-2],i.pop()),r.splice(a,n,...i)}e=r.join("/"),n=!0;break}}}return e}getMoveValue(e,i,r){let a=r.indexOf(",");if(-1===a&&(a=this.addCommas(r).indexOf(","),-1===a))throw new Error(`getMoveValue: move: ${r} is weird`);const n=i?"/":"\\";let s;return s=parseInt(r.slice(0,a),10)%3==0?(e?"A":"a")+n+r:n+r,t.MOVE_VALUES.get(s)??5}getOverwork(e){const i=[],r=[];for(const t of e){let e=t.indexOf(",");if(-1===e){if(e=this.addCommas(t).indexOf(","),-1===e)throw new Error(`getOverwork: in moves, m: ${t} is weird.`)}i.push(parseInt(t.slice(0,e),10)||0),r.push(parseInt(t.slice(e+1),10)||0)}let a=0,n=0,s=0,l=0,o=0;for(const e of i){if(6===e||e<0){if(s++,!t.CLOSEST_MAP.has(e))throw new Error("getOverwork: top move is weird: "+e);l+=Math.abs(t.CLOSEST_MAP.get(e)),o+=Math.abs(e),s>1&&l>3&&(a+=o,o=0)}else s=0,l=0,o=0}s=0,l=0,o=0;for(const e of r){if(e>0){if(s++,!t.CLOSEST_MAP.has(e))throw new Error("getOverwork: top move is weird: "+e);l+=Math.abs(t.CLOSEST_MAP.get(e)),o+=Math.abs(e),s>1&&l>3&&(a+=o,o=0)}else s=0,l=0,o=0}for(let t=0;t+1<i.length;t++)i[t]+i[t+1]===0&&n++,r[t]+r[t+1]===0&&n++;return{movement:a,bonus:n}}rateAlg(t,e=!1,i={}){const r=i.W1??34,a=i.W2??100,n=i.W3??38,s=i.W4??500,l=i.W5??10;let o=t.replace(/\[.*$/,"").trim();const h=(this.isKarn(o)?this.unkarnify(o):o.replaceAll(" ","")).split("/").filter((t,e)=>0===e||""!==t.trim()).map(t=>t.trim()),d=h.length-1;if(d<=0)return{score:s,sliceStart:" "};let c=0,u=0,g=!1,f=!0;for(let i=0;i<h.length-1;i++){let r=h[i],a=r.indexOf(",");if(-1===a&&(r=r?this.addCommas(r):"0,0",a=r.indexOf(","),-1===a))throw new Error(`rateAlg:\nalg: ${t}\nmove: ${r}\nis weird.`);const n=parseInt(r.slice(0,a),10);if(isNaN(n))throw new Error(`rateAlg:\nalg: ${t}\nmove: ${r}\nis weird.`);0!==i?(c+=this.getMoveValue(g,f,r),u+=this.getMoveValue(g,!f,r),g=g!==(n%3!=0),f=!f):(g=e!==(n%3!=0),f=!0)}const b=r*Math.max(c,u)/d;let p="|";Math.abs(c-u)/d>5&&(p=c>u?"/":"\\");const w=a*d,m=h.slice(1,-1),{movement:W,bonus:B}=this.getOverwork(m);return{score:b-w-n*W/d+B*l/d+s,sliceStart:p}}rateAndSort(t,e=""){let i=!1;if(e){const t=e[0];i=/[A-HU-W]/i.test(t)}return t.map(t=>{const e=t.indexOf("["),r=e>0?t.slice(0,e).trim():t.trim();let a={alg:t,score:500},n=!1,s=" ";const l=this.isKarn(r)?this.unkarnify(r):r;return({score:a.score,sliceStart:s}=this.rateAlg(l,i)),n=!0,["/","\\","|"].includes(s)&&(a.alg=this.injectSliceStart(t,s)),a}).sort((t,e)=>e.score-t.score)}injectSliceStart(e,i){let r=/[/\\| ]/.test(e);if((r?e.match(/^([^/\\| ]*)[/\\| ]/)?.[1]:e)in t.karnToWCA)return i+e;if(!r)return e;const a=e.search(/[/\\| ]/);return e.slice(0,a)+i+e.slice(a+1)}sepIndex(t){let e=0;for(const i of t)if(e++,/\d/.test(i))break;return e}compl(t){if(!t)return t;let e,i;if(t.includes(","))[e,i]=t.split(",");else{const r=this.sepIndex(t);[e,i]=[t.slice(0,r),t.slice(r)]}return String(this.legalMove(6+parseInt(e,10)))+","+String(this.legalMove(6+parseInt(i,10)))}lf(t){if(!t)return t;let e,i;if(t.includes(","))[e,i]=t.split(",");else{const r=this.sepIndex(t);[e,i]=[t.slice(0,r),t.slice(r)]}return i+","+e}compact(t){let e=t.replace(/\[.*?\]/g,"").replace(/[()]/g,"").trim();if(this.isKarn(e)){return this.unkarnify(e).split("/").map(t=>{if(!t)return t;if(!t.includes(","))throw new Error(`algToInternal: m doesn't have commas post karnifying: ${t}`);const[e,i]=t.split(",");return String(this.legalMove(parseInt(e,10)))+String(this.legalMove(parseInt(i,10)))}).join(" ")}return e=e.replaceAll(" ",""),e.includes("/")?e.split("/").filter(Boolean).map(t=>{if(t.includes(",")||(t=this.addCommas(t)),!t.includes(","))throw new Error(`algToInternal: m doesn't have commas post addComma: ${t}`);const[e,i]=t.split(",");return String(this.legalMove(parseInt(e,10)))+String(this.legalMove(parseInt(i,10)))}).join(" "):e.split(" ").filter(t=>t).map(t=>{const e=t.includes(",")?t.split(","):[t.slice(0,this.sepIndex(t)),t.slice(this.sepIndex(t))];return String(this.legalMove(parseInt(e[0],10)))+String(this.legalMove(parseInt(e[1],10)))}).join(" ")}countY2Positions(t){const e=this.compact(t).split(" ");return Math.max(0,e.length-3)}applyY2s(e,i,r=null){let a=e.replaceAll(/\[.*?\]/g,"").trim();i||(i=[]);const n=this.isKarn(a),s=null===r?n:r;a=this.unkarnify(e);let l=a.split("/");const o=l[0],h=l[l.length-1];let d=!1,c=!1;for(let t=1;t<=l.length-3;t++){let e=l[t];e=c?this.lf(e):e,i.includes(t)&&(e=this.compl(e),d=!d),c=d?!c:c,l[t]=e}const u=l.length-2;c&&(l[u]=this.lf(l[u])),d!==c&&(l[u]=this.compl(l[u]));const g=l[u];for(let t=0;t<l.length;t++)l[t]=this.addCommas(l[t]);a=l.join("/");let f="";g&&!t.GOOD_FINISHES.has(g)&&(f+=" (bad finish)");const{topA:b,bottomA:p}=this.getAlignment(o),{topA:w,bottomA:m}=this.getAlignment(h);return b!==p&&b!==w&&w!==m&&(f+=" (alignment changes in CS)"),s&&(a=this.karnify(a)),a+f}layerFlip(t){const e={b:"w",B:"W",w:"b",W:"B"};return[...t].map(t=>{if(t in e)return e[t];throw new Error("layerFlip: unrecognized character: "+t)}).join("")}shift(t,e){return e=(-e%t.length+t.length)%t.length,t.slice(e)+t.slice(0,e)}oblName(t){return t[0]?`${t[0]} ${t[1]}/${t[2]}`:`${t[1]}/${t[2]}`}layerFlipName(t){const e=(t=t.replace("/"," ")).split(" ");return 2===e.length?e[1]+"/"+e[0]:e[0]+" "+e[2]+"/"+e[1]}speToNonSpe(e){const[i,r]=e.split("/"),a=i.split(" ").pop(),n=r.split(" ").pop(),s=t.POSSIBLE_OBL.filter(t=>t.includes(a)&&t.includes(n)).map(t=>this.oblName(t));for(const i of s){const r=t.OBL_TRANSLATION[i]||[];for(const t of r){if(t===e)return i;const[r,a]=t.split("/");if(`${a}/${r}`===e)return this.layerFlipName(i)}}throw new Error(`speToNonSpe: No non-specific OBL found for: ${e}`)}isOBLCase(e,i){const r=Object.entries(t.OBLToEnglish).find(([,t])=>t===i)?.[0];if(!r)return!1;e[0]!==e[0].toUpperCase()&&(e=this.shift(e,-1));for(let t=0;t<4;t++)if(r===this.shift(e,-3*t))return t;if(!["T","tie"].includes(i.split(" ").pop())){const t=this.layerFlip(e);for(let e=0;e<4;e++)if(r===this.shift(t,-3*e))return e}return!1}layerToOBL(e){for(const i of Object.keys(t.OBLToState))if(this.isOBLCase(e,i))return{obl:i,angleOffset:this.isOBLCase(e,i)};throw new Error("layerToOBL: no OBL matched layer: "+e)}getAngle(e,i,r,a){let n=t.OBL_ANGLES[e],s=t.OBL_ANGLES[i];for(let e=0;e<r%4;e++)n=t.nextAngle[n];for(let e=0;e<a%4;e++)s=t.nextAngle[s];return`${n} ${s}`}cubeToSpe(e){return[this.layerToOBL(e.slice(0,t.LAYERL)),this.layerToOBL(e.slice(t.LAYERL))]}getOBLLen(t){return t in OBL_LEN?OBL_LEN[t]:OBL_LEN[layer_flip_name(t)]}stateToLen(t,e){return this.getOBLLen(this.speToNonSpe(t+"/"+e))}getOBLNaming(e,i){return t.NAMING[e]+"/"+t.NAMING[i]}stateToMatt(e){let i=e.slice(0,t.LAYERL),r=e.slice(t.LAYERL);i=i[0]!==i[0].toLowerCase()?this.shift(i,3):this.shift(i,2),r=r[0]!==r[0].toLowerCase()?this.shift(r,3):this.shift(r,2);let a="",n=1;for(let e=0;e<t.LAYERL;e+=3)"B"===i[e]&&(a+=n),"b"===i[e+2]&&(a+=n+1),n+=2;a=""===a?"- ":a+" ",n=1;for(let e=0;e<t.LAYERL;e+=3)"B"===r[e]&&(a+=n),"b"===r[e+2]&&(a+=n+1),n+=2;return" "===a[a.length-1]?a+"-":a}mattToLayer(t){const e=["W","W","w","W","W","w","W","W","w","W","W","w"];for(const i of t){const t=parseInt(i,10);t%2!=0?(e[3*Math.floor(t/2)]="B",e[3*Math.floor(t/2)+1]="B"):e[3*Math.floor(t/2)-1]="b"}return e.join("")}mattToNonSpe(t){const[e,i]=t.split(" ");return this.speToNonSpe(`${this.layerToOBL(this.mattToLayer(e))}/${this.layerToOBL(this.mattToLayer(i))}`)}sortOblp(t){return[...t].sort().join("")}}return t});
|
package/package.json
CHANGED
package/squanlib.js
CHANGED
|
@@ -63,7 +63,6 @@ export default class SquanLib {
|
|
|
63
63
|
"d2": "-1,5", "d2'": "1,-5",
|
|
64
64
|
"K": "5,2", "K'": "-5,-2",
|
|
65
65
|
"k": "2,5", "k'": "-2,-5",
|
|
66
|
-
"A": "1,0", "A'": "-1,0",
|
|
67
66
|
"G": "5,-4", "G'": "-5,4",
|
|
68
67
|
"g": "4,-5", "g'": "-4,5",
|
|
69
68
|
};
|
|
@@ -270,10 +269,10 @@ export default class SquanLib {
|
|
|
270
269
|
* GOOD_FINISHES: moves that are acceptable as the last move
|
|
271
270
|
*/
|
|
272
271
|
static GOOD_FINISHES = new Set([
|
|
273
|
-
"
|
|
274
|
-
"
|
|
275
|
-
"
|
|
276
|
-
"5
|
|
272
|
+
"1,1", "-1,-1", "2,2", "-2,-2", "2,-1", "-2,1", "1,-2", "-1,2",
|
|
273
|
+
"3,0", "-3,0", "0,3", "0,-3", "3,3", "3,-3", "-3,-3", "-3,3",
|
|
274
|
+
"4,1", "-4,-1", "1,4", "-1,-4", "2,-4", "-2,4", "4,-2", "-4,2",
|
|
275
|
+
"5,-1", "-5,1", "-4,5", "-5,4", "6,3",
|
|
277
276
|
]);
|
|
278
277
|
|
|
279
278
|
/**
|
|
@@ -710,14 +709,6 @@ export default class SquanLib {
|
|
|
710
709
|
// overrides
|
|
711
710
|
if (alg in this.tempReplacements) return this.tempReplacements[alg];
|
|
712
711
|
|
|
713
|
-
// p scrambles
|
|
714
|
-
let isPScramble = /^p[ /\\|]/.test(alg);
|
|
715
|
-
let startingSlice;
|
|
716
|
-
if (isPScramble) {
|
|
717
|
-
startingSlice = alg.charAt(1) === " " ? "/" : alg.charAt(1);
|
|
718
|
-
alg = alg.slice(2, -3);
|
|
719
|
-
}
|
|
720
|
-
|
|
721
712
|
// legacy character substitutions
|
|
722
713
|
alg = alg
|
|
723
714
|
.replaceAll('&', '-1')
|
|
@@ -726,6 +717,17 @@ export default class SquanLib {
|
|
|
726
717
|
.replaceAll('8', '-4')
|
|
727
718
|
.replaceAll('7', '-5');
|
|
728
719
|
|
|
720
|
+
// remove potential move counts, comments
|
|
721
|
+
alg = alg.replaceAll(/\[.*?\]/g, "");
|
|
722
|
+
|
|
723
|
+
// p scrambles
|
|
724
|
+
let isPScramble = /^p[ /\\|]/.test(alg);
|
|
725
|
+
let startingSlice;
|
|
726
|
+
if (isPScramble) {
|
|
727
|
+
startingSlice = alg.charAt(1) === " " ? "/" : alg.charAt(1);
|
|
728
|
+
alg = alg.slice(2, -3);
|
|
729
|
+
}
|
|
730
|
+
|
|
729
731
|
// expand move groups, e.g. "(U U')3" → "U U' U U' U U'"
|
|
730
732
|
for (const group of alg.matchAll(/(\(.*?\))(\d+)/g)) {
|
|
731
733
|
const inner = group[1].replaceAll(/[()]/g, '');
|
|
@@ -1031,10 +1033,22 @@ export default class SquanLib {
|
|
|
1031
1033
|
// now go through scramble move by move to apply base karn
|
|
1032
1034
|
let s = alg.split(" ").filter(Boolean);
|
|
1033
1035
|
for (let i = 0; i < s.length; i++) {
|
|
1034
|
-
if (i === 0 && !startsSlice)
|
|
1035
|
-
|
|
1036
|
+
if (i === 0 && !startsSlice) {
|
|
1037
|
+
// even if it's in base karn, we can't karnify
|
|
1038
|
+
s[i] = s[i].replace(",", "");
|
|
1039
|
+
continue;
|
|
1040
|
+
}
|
|
1041
|
+
if (i === s.length - 1 && !endsSlice) {
|
|
1042
|
+
// even if it's in base karn, we can't karnify
|
|
1043
|
+
s[i] = s[i].replace(",", "");
|
|
1044
|
+
break;
|
|
1045
|
+
}
|
|
1036
1046
|
// good to replace
|
|
1037
|
-
|
|
1047
|
+
let inBaseKarn = s[i] in SquanLib.wcaToBaseKarn;
|
|
1048
|
+
s[i] = inBaseKarn ? SquanLib.wcaToBaseKarn[s[i]] : s[i].replace(",", "");
|
|
1049
|
+
// prevent an additional leading slice for first move karn
|
|
1050
|
+
if (inBaseKarn && i === 0) startingSlice = startingSlice.replace("/", "");
|
|
1051
|
+
if (inBaseKarn && i === s.length - 1) endingSlice = "";
|
|
1038
1052
|
}
|
|
1039
1053
|
|
|
1040
1054
|
alg = startingSlice + s.join(" ") + endingSlice;
|
|
@@ -1359,16 +1373,32 @@ export default class SquanLib {
|
|
|
1359
1373
|
rated = true;
|
|
1360
1374
|
|
|
1361
1375
|
if (rated && ["/", "\\", "|"].includes(sliceStart)) {
|
|
1362
|
-
|
|
1363
|
-
const slashPos = line.indexOf('/');
|
|
1364
|
-
if (slashPos >= 0)
|
|
1365
|
-
result.alg = line.slice(0, slashPos) + sliceStart + line.slice(slashPos + 1);
|
|
1376
|
+
result.alg = this.injectSliceStart(line, sliceStart);
|
|
1366
1377
|
}
|
|
1367
1378
|
|
|
1368
1379
|
return result;
|
|
1369
1380
|
}).sort((a, b) => b.score - a.score);
|
|
1370
1381
|
}
|
|
1371
1382
|
|
|
1383
|
+
/**
|
|
1384
|
+
* injectSliceStart: injects the slice start into an alg
|
|
1385
|
+
*
|
|
1386
|
+
* @param {string} alg the alg. no extra spaces allowed
|
|
1387
|
+
* @param {string} sliceStart " " | "/" | "\\" | "|"
|
|
1388
|
+
* @returns {string} the alg with slice start injected at the first slice
|
|
1389
|
+
*/
|
|
1390
|
+
injectSliceStart(alg, sliceStart) {
|
|
1391
|
+
let moreThan1 = /[/\\| ]/.test(alg); // is there ANY slice chars?
|
|
1392
|
+
let firstMove = moreThan1 ? alg.match(/^([^/\\| ]*)[/\\| ]/)?.[1] : alg;
|
|
1393
|
+
// only tests if it's a karn
|
|
1394
|
+
if (firstMove in SquanLib.karnToWCA) return sliceStart + alg;
|
|
1395
|
+
if (!moreThan1) return alg; // no slice to inject to
|
|
1396
|
+
|
|
1397
|
+
// guaranteed to have a slice
|
|
1398
|
+
const slashPos = alg.search(/[/\\| ]/);
|
|
1399
|
+
return alg.slice(0, slashPos) + sliceStart + alg.slice(slashPos + 1);
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1372
1402
|
// =========================================================================
|
|
1373
1403
|
// SECTION 8: ALG TRANSFORM
|
|
1374
1404
|
// =========================================================================
|
|
@@ -1389,28 +1419,38 @@ export default class SquanLib {
|
|
|
1389
1419
|
/**
|
|
1390
1420
|
* compl: get the complement of a move
|
|
1391
1421
|
*
|
|
1392
|
-
* @param {string} a a move
|
|
1393
|
-
* @returns {string} the complement move
|
|
1394
|
-
* @example "-12" → "5-4"
|
|
1422
|
+
* @param {string} a a move
|
|
1423
|
+
* @returns {string} the complement move with commas
|
|
1424
|
+
* @example "-12" → "5,-4"; "-1,2" → "5,-4"
|
|
1395
1425
|
*/
|
|
1396
1426
|
compl(a) {
|
|
1397
1427
|
if (!a) return a;
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1428
|
+
let u, d;
|
|
1429
|
+
if (a.includes(',')) [u, d] = a.split(",");
|
|
1430
|
+
else {
|
|
1431
|
+
const inx = this.sepIndex(a);
|
|
1432
|
+
[u, d] = [a.slice(0, inx), a.slice(inx)];
|
|
1433
|
+
}
|
|
1434
|
+
return String(this.legalMove(6 + parseInt(u, 10))) + "," +
|
|
1435
|
+
String(this.legalMove(6 + parseInt(d, 10)));
|
|
1401
1436
|
}
|
|
1402
1437
|
|
|
1403
1438
|
/**
|
|
1404
1439
|
* lf: get the layer flip of a move
|
|
1405
1440
|
*
|
|
1406
|
-
* @param {string} a a move
|
|
1441
|
+
* @param {string} a a move
|
|
1407
1442
|
* @returns {string} the layer flip move
|
|
1408
|
-
* @example "-12" → "2-1"
|
|
1443
|
+
* @example "-12" → "2,-1"; "-1,2" → "2,-1"
|
|
1409
1444
|
*/
|
|
1410
1445
|
lf(a) {
|
|
1411
1446
|
if (!a) return a;
|
|
1412
|
-
|
|
1413
|
-
|
|
1447
|
+
let u, d;
|
|
1448
|
+
if (a.includes(',')) [u, d] = a.split(",");
|
|
1449
|
+
else {
|
|
1450
|
+
const inx = this.sepIndex(a);
|
|
1451
|
+
[u, d] = [a.slice(0, inx), a.slice(inx)];
|
|
1452
|
+
}
|
|
1453
|
+
return d + "," + u;
|
|
1414
1454
|
}
|
|
1415
1455
|
|
|
1416
1456
|
/**
|
|
@@ -1423,11 +1463,11 @@ export default class SquanLib {
|
|
|
1423
1463
|
compact(algIn) {
|
|
1424
1464
|
let alg = algIn
|
|
1425
1465
|
.replace(/\[.*?\]/g, "")
|
|
1426
|
-
.replace(/[()]/g, "")
|
|
1427
|
-
.replaceAll(" ", "").trim();
|
|
1466
|
+
.replace(/[()]/g, "").trim();
|
|
1428
1467
|
if (this.isKarn(alg)) {
|
|
1429
1468
|
const numeric = this.unkarnify(alg);
|
|
1430
|
-
return numeric.split("/").
|
|
1469
|
+
return numeric.split("/").map(m => {
|
|
1470
|
+
if (!m) return m;
|
|
1431
1471
|
if (!m.includes(","))
|
|
1432
1472
|
throw new Error(
|
|
1433
1473
|
`algToInternal: m doesn't have commas post karnifying: ${m}`
|
|
@@ -1437,7 +1477,7 @@ export default class SquanLib {
|
|
|
1437
1477
|
String(this.legalMove(parseInt(d, 10)));
|
|
1438
1478
|
}).join(" ");
|
|
1439
1479
|
}
|
|
1440
|
-
alg = alg.
|
|
1480
|
+
alg = alg.replaceAll(" ", "");
|
|
1441
1481
|
if (alg.includes("/")) {
|
|
1442
1482
|
return alg.split("/").filter(Boolean).map(m => {
|
|
1443
1483
|
if (!m.includes(",")) m = this.addCommas(m);
|
|
@@ -1466,7 +1506,8 @@ export default class SquanLib {
|
|
|
1466
1506
|
* @returns {number} how many positions the alg can y2 at
|
|
1467
1507
|
*/
|
|
1468
1508
|
countY2Positions(algIn) {
|
|
1469
|
-
|
|
1509
|
+
// spaces ARE slices, cannot trim or do anything like that
|
|
1510
|
+
const segs = this.compact(algIn).split(" ");
|
|
1470
1511
|
return Math.max(0, segs.length - 3);
|
|
1471
1512
|
}
|
|
1472
1513
|
|
|
@@ -1618,7 +1659,7 @@ export default class SquanLib {
|
|
|
1618
1659
|
isOBLCase(l, target) {
|
|
1619
1660
|
const targetPattern = Object.entries(SquanLib.OBLToEnglish)
|
|
1620
1661
|
.find(([, v]) => v === target
|
|
1621
|
-
|
|
1662
|
+
)?.[0];
|
|
1622
1663
|
if (!targetPattern) return false;
|
|
1623
1664
|
// to corner first
|
|
1624
1665
|
if (l[0] !== l[0].toUpperCase()) l = this.shift(l, -1);
|