cubing 0.57.4 → 0.58.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/lib/cubing/{PuzzleLoader-B7Ly-OAs.d.ts → PuzzleLoader-BskBhUgu.d.ts} +11 -1
  2. package/dist/lib/cubing/alg/index.d.ts +2 -2
  3. package/dist/lib/cubing/alg/index.js +1 -1
  4. package/dist/lib/cubing/bluetooth/index.d.ts +3 -3
  5. package/dist/lib/cubing/bluetooth/index.js +701 -58
  6. package/dist/lib/cubing/bluetooth/index.js.map +4 -4
  7. package/dist/lib/cubing/{bluetooth-puzzle-nh-dCXPL.d.ts → bluetooth-puzzle-BIDZuWiS.d.ts} +1 -1
  8. package/dist/lib/cubing/chunks/{big-puzzle-orientation-SKZG73EB.js → big-puzzle-orientation-CQUVRARW.js} +2 -2
  9. package/dist/lib/cubing/chunks/{chunk-SWKNZGJF.js → chunk-3MMNI5O2.js} +7 -1
  10. package/dist/lib/cubing/chunks/chunk-3MMNI5O2.js.map +7 -0
  11. package/dist/lib/cubing/chunks/{chunk-3U3UEVVD.js → chunk-53UENZ7A.js} +3 -3
  12. package/dist/lib/cubing/chunks/{chunk-GKM2CK6T.js → chunk-7M7ZAS5G.js} +2 -2
  13. package/dist/lib/cubing/chunks/{chunk-7HQOMRBY.js → chunk-BVZN7IXO.js} +3 -3
  14. package/dist/lib/cubing/chunks/{chunk-3YVVF3KK.js → chunk-CZGLT7LF.js} +2 -2
  15. package/dist/lib/cubing/chunks/{chunk-H75BKRPQ.js → chunk-LII4MJEB.js} +5 -5
  16. package/dist/lib/cubing/chunks/{chunk-NJFJ3OMF.js → chunk-SR66SYE2.js} +2 -2
  17. package/dist/lib/cubing/chunks/chunk-SR66SYE2.js.map +7 -0
  18. package/dist/lib/cubing/chunks/{chunk-2H2XY6KQ.js → chunk-WI3YFILD.js} +48 -298
  19. package/dist/lib/cubing/chunks/chunk-WI3YFILD.js.map +7 -0
  20. package/dist/lib/cubing/chunks/{chunk-F7UESNJD.js → chunk-YICS6Q2F.js} +2 -2
  21. package/dist/lib/cubing/chunks/{chunk-666TWRT6.js → chunk-Z4CZPP2W.js} +461 -69
  22. package/dist/lib/cubing/chunks/chunk-Z4CZPP2W.js.map +7 -0
  23. package/dist/lib/cubing/chunks/{chunk-7CZZRWBJ.js → chunk-ZVLDZYZD.js} +3 -3
  24. package/dist/lib/cubing/chunks/{inside-AYMLD6IQ.js → inside-ICFSQUAC.js} +14 -14
  25. package/dist/lib/cubing/chunks/{search-dynamic-sgs-side-events-T4N6YHT7.js → search-dynamic-sgs-side-events-5AC7RH72.js} +6 -6
  26. package/dist/lib/cubing/chunks/{search-dynamic-sgs-unofficial-EQIJODP7.js → search-dynamic-sgs-unofficial-INRHQCBE.js} +6 -6
  27. package/dist/lib/cubing/chunks/{search-dynamic-solve-4x4x4-NT5XKSLV.js → search-dynamic-solve-4x4x4-VNSEVV7B.js} +7 -7
  28. package/dist/lib/cubing/chunks/{search-dynamic-solve-fto-NKAFVO65.js → search-dynamic-solve-fto-BHX3R6ZT.js} +2 -2
  29. package/dist/lib/cubing/chunks/{search-dynamic-solve-kilominx-EDGE5SP4.js → search-dynamic-solve-kilominx-SAJCQILQ.js} +2 -2
  30. package/dist/lib/cubing/chunks/search-worker-entry.js +1 -1
  31. package/dist/lib/cubing/chunks/{twisty-dynamic-3d-FRZJG7S6.js → twisty-dynamic-3d-CCZCZBPC.js} +7 -8
  32. package/dist/lib/cubing/chunks/{twisty-dynamic-3d-FRZJG7S6.js.map → twisty-dynamic-3d-CCZCZBPC.js.map} +1 -1
  33. package/dist/lib/cubing/chunks/{twsearch-WDBATGZX.js → twsearch-T3W5T5WE.js} +4 -4
  34. package/dist/lib/cubing/chunks/twsearch_wasm_bg-Q5AYUFKA-AHAAY6HU.js +10 -0
  35. package/dist/lib/cubing/chunks/twsearch_wasm_bg-Q5AYUFKA-AHAAY6HU.js.map +7 -0
  36. package/dist/lib/cubing/{index-BOJwUPsI.d.ts → index-1uDGfzzz.d.ts} +1 -1
  37. package/dist/lib/cubing/kpuzzle/index.d.ts +1 -1
  38. package/dist/lib/cubing/kpuzzle/index.js +2 -2
  39. package/dist/lib/cubing/notation/index.d.ts +1 -1
  40. package/dist/lib/cubing/notation/index.js +4 -4
  41. package/dist/lib/cubing/protocol/index.d.ts +1 -1
  42. package/dist/lib/cubing/protocol/index.js +4 -4
  43. package/dist/lib/cubing/puzzle-geometry/index.d.ts +2 -2
  44. package/dist/lib/cubing/puzzle-geometry/index.js +1 -1
  45. package/dist/lib/cubing/puzzles/index.d.ts +2 -1
  46. package/dist/lib/cubing/puzzles/index.js +6 -5
  47. package/dist/lib/cubing/scramble/index.d.ts +2 -2
  48. package/dist/lib/cubing/scramble/index.js +6 -6
  49. package/dist/lib/cubing/search/index.d.ts +2 -2
  50. package/dist/lib/cubing/search/index.js +6 -6
  51. package/dist/lib/cubing/stream/index.d.ts +2 -2
  52. package/dist/lib/cubing/stream/index.js +1 -1
  53. package/dist/lib/cubing/twisty/index.d.ts +2 -2
  54. package/dist/lib/cubing/twisty/index.js +7 -7
  55. package/package.json +4 -3
  56. package/dist/lib/cubing/chunks/chunk-2H2XY6KQ.js.map +0 -7
  57. package/dist/lib/cubing/chunks/chunk-666TWRT6.js.map +0 -7
  58. package/dist/lib/cubing/chunks/chunk-NJFJ3OMF.js.map +0 -7
  59. package/dist/lib/cubing/chunks/chunk-SWKNZGJF.js.map +0 -7
  60. package/dist/lib/cubing/chunks/twsearch_wasm_bg-WOVCK52S-RP4VI7OV.js +0 -10
  61. package/dist/lib/cubing/chunks/twsearch_wasm_bg-WOVCK52S-RP4VI7OV.js.map +0 -7
  62. /package/dist/lib/cubing/chunks/{big-puzzle-orientation-SKZG73EB.js.map → big-puzzle-orientation-CQUVRARW.js.map} +0 -0
  63. /package/dist/lib/cubing/chunks/{chunk-3U3UEVVD.js.map → chunk-53UENZ7A.js.map} +0 -0
  64. /package/dist/lib/cubing/chunks/{chunk-GKM2CK6T.js.map → chunk-7M7ZAS5G.js.map} +0 -0
  65. /package/dist/lib/cubing/chunks/{chunk-7HQOMRBY.js.map → chunk-BVZN7IXO.js.map} +0 -0
  66. /package/dist/lib/cubing/chunks/{chunk-3YVVF3KK.js.map → chunk-CZGLT7LF.js.map} +0 -0
  67. /package/dist/lib/cubing/chunks/{chunk-H75BKRPQ.js.map → chunk-LII4MJEB.js.map} +0 -0
  68. /package/dist/lib/cubing/chunks/{chunk-F7UESNJD.js.map → chunk-YICS6Q2F.js.map} +0 -0
  69. /package/dist/lib/cubing/chunks/{chunk-7CZZRWBJ.js.map → chunk-ZVLDZYZD.js.map} +0 -0
  70. /package/dist/lib/cubing/chunks/{inside-AYMLD6IQ.js.map → inside-ICFSQUAC.js.map} +0 -0
  71. /package/dist/lib/cubing/chunks/{search-dynamic-sgs-side-events-T4N6YHT7.js.map → search-dynamic-sgs-side-events-5AC7RH72.js.map} +0 -0
  72. /package/dist/lib/cubing/chunks/{search-dynamic-sgs-unofficial-EQIJODP7.js.map → search-dynamic-sgs-unofficial-INRHQCBE.js.map} +0 -0
  73. /package/dist/lib/cubing/chunks/{search-dynamic-solve-4x4x4-NT5XKSLV.js.map → search-dynamic-solve-4x4x4-VNSEVV7B.js.map} +0 -0
  74. /package/dist/lib/cubing/chunks/{search-dynamic-solve-fto-NKAFVO65.js.map → search-dynamic-solve-fto-BHX3R6ZT.js.map} +0 -0
  75. /package/dist/lib/cubing/chunks/{search-dynamic-solve-kilominx-EDGE5SP4.js.map → search-dynamic-solve-kilominx-SAJCQILQ.js.map} +0 -0
  76. /package/dist/lib/cubing/chunks/{twsearch-WDBATGZX.js.map → twsearch-T3W5T5WE.js.map} +0 -0
@@ -1,23 +1,23 @@
1
1
  import {
2
2
  binaryComponentsToReid3x3x3,
3
3
  twizzleBinaryToBinaryComponents
4
- } from "../chunks/chunk-7HQOMRBY.js";
4
+ } from "../chunks/chunk-BVZN7IXO.js";
5
5
  import {
6
- cube3x3x3,
7
6
  puzzles
8
- } from "../chunks/chunk-2H2XY6KQ.js";
7
+ } from "../chunks/chunk-WI3YFILD.js";
9
8
  import {
9
+ cube3x3x3,
10
10
  experimental3x3x3KPuzzle
11
- } from "../chunks/chunk-666TWRT6.js";
11
+ } from "../chunks/chunk-Z4CZPP2W.js";
12
12
  import {
13
13
  KPattern
14
- } from "../chunks/chunk-3YVVF3KK.js";
14
+ } from "../chunks/chunk-CZGLT7LF.js";
15
15
  import {
16
16
  Alg,
17
17
  Move,
18
18
  experimentalAppendMove,
19
19
  keyToMove
20
- } from "../chunks/chunk-SWKNZGJF.js";
20
+ } from "../chunks/chunk-3MMNI5O2.js";
21
21
 
22
22
  // src/cubing/bluetooth/debug.ts
23
23
  var DEBUG_LOGGING_ENABLED = false;
@@ -268,6 +268,12 @@ async function unsafeEncryptBlockWithIV(key, plaintextBlock, iv) {
268
268
  );
269
269
  return cryptoResult.slice(0, blockSize);
270
270
  }
271
+ async function unsafeEncryptBlock(key, plaintextBlock) {
272
+ return (await unsafeEncryptBlockWithIV(key, plaintextBlock, zeros)).slice(
273
+ 0,
274
+ blockSize
275
+ );
276
+ }
271
277
  async function unsafeDecryptBlock(key, ciphertextBlock) {
272
278
  const paddingBlock = await unsafeEncryptBlockWithIV(
273
279
  key,
@@ -288,6 +294,52 @@ async function unsafeDecryptBlock(key, ciphertextBlock) {
288
294
  return cryptoResult.slice(0, blockSize);
289
295
  }
290
296
 
297
+ // src/cubing/bluetooth/smart-puzzle/common.ts
298
+ var reidEdgeOrder = "UF UR UB UL DF DR DB DL FR FL BR BL".split(" ");
299
+ var reidCornerOrder = "UFR URB UBL ULF DRF DFL DLB DBR".split(" ");
300
+ function rotateLeft(s, i) {
301
+ return s.slice(i) + s.slice(0, i);
302
+ }
303
+ var pieceMap = {};
304
+ reidEdgeOrder.forEach((edge, idx) => {
305
+ for (let i = 0; i < 2; i++) {
306
+ pieceMap[rotateLeft(edge, i)] = { piece: idx, orientation: i };
307
+ }
308
+ });
309
+ reidCornerOrder.forEach((corner, idx) => {
310
+ for (let i = 0; i < 3; i++) {
311
+ pieceMap[rotateLeft(corner, i)] = { piece: idx, orientation: i };
312
+ }
313
+ });
314
+ function getPatternData(stickers, faceOrder3, edgeMappings, cornerMappings) {
315
+ const patternData = {
316
+ CORNERS: {
317
+ pieces: [],
318
+ orientation: []
319
+ },
320
+ EDGES: {
321
+ pieces: [],
322
+ orientation: []
323
+ },
324
+ CENTERS: {
325
+ pieces: [0, 1, 2, 3, 4, 5],
326
+ orientation: [0, 0, 0, 0, 0, 0],
327
+ orientationMod: [1, 1, 1, 1, 1, 1]
328
+ }
329
+ };
330
+ for (const cornerMapping of cornerMappings) {
331
+ const pieceInfo = pieceMap[cornerMapping.map((i) => faceOrder3[stickers[i]]).join("")];
332
+ patternData["CORNERS"].pieces.push(pieceInfo.piece);
333
+ patternData["CORNERS"].orientation.push(pieceInfo.orientation);
334
+ }
335
+ for (const edgeMapping of edgeMappings) {
336
+ const pieceInfo = pieceMap[edgeMapping.map((i) => faceOrder3[stickers[i]]).join("")];
337
+ patternData["EDGES"].pieces.push(pieceInfo.piece);
338
+ patternData["EDGES"].orientation.push(pieceInfo.orientation);
339
+ }
340
+ return patternData;
341
+ }
342
+
291
343
  // src/cubing/bluetooth/smart-puzzle/gan.ts
292
344
  var DEFAULT_INTERVAL_MS = 150;
293
345
  var MAX_LATEST_MOVES = 6;
@@ -454,22 +506,6 @@ function buf2hex(buffer) {
454
506
  (x) => `00${x.toString(16)}`.slice(-2)
455
507
  ).join(" ");
456
508
  }
457
- var reidEdgeOrder = "UF UR UB UL DF DR DB DL FR FL BR BL".split(" ");
458
- var reidCornerOrder = "UFR URB UBL ULF DRF DFL DLB DBR".split(" ");
459
- function rotateLeft(s, i) {
460
- return s.slice(i) + s.slice(0, i);
461
- }
462
- var pieceMap = {};
463
- reidEdgeOrder.forEach((edge, idx) => {
464
- for (let i = 0; i < 2; i++) {
465
- pieceMap[rotateLeft(edge, i)] = { piece: idx, orientation: i };
466
- }
467
- });
468
- reidCornerOrder.forEach((corner, idx) => {
469
- for (let i = 0; i < 3; i++) {
470
- pieceMap[rotateLeft(corner, i)] = { piece: idx, orientation: i };
471
- }
472
- });
473
509
  var gan356iCornerMappings = [
474
510
  [0, 21, 15],
475
511
  [5, 13, 47],
@@ -625,33 +661,15 @@ var GanCube = class _GanCube extends BluetoothPuzzle {
625
661
  v >>= 3;
626
662
  }
627
663
  }
628
- const patternData = {
629
- CORNERS: {
630
- pieces: [],
631
- orientation: []
632
- },
633
- EDGES: {
634
- pieces: [],
635
- orientation: []
636
- },
637
- CENTERS: {
638
- pieces: [0, 1, 2, 3, 4, 5],
639
- orientation: [0, 0, 0, 0, 0, 0],
640
- orientationMod: [1, 1, 1, 1, 1, 1]
641
- // TODO
642
- }
643
- };
644
- for (const cornerMapping of gan356iCornerMappings) {
645
- const pieceInfo = pieceMap[cornerMapping.map((i) => faceOrder[stickers[i]]).join("")];
646
- patternData["CORNERS"].pieces.push(pieceInfo.piece);
647
- patternData["CORNERS"].orientation.push(pieceInfo.orientation);
648
- }
649
- for (const edgeMapping of gan356iEdgeMappings) {
650
- const pieceInfo = pieceMap[edgeMapping.map((i) => faceOrder[stickers[i]]).join("")];
651
- patternData["EDGES"].pieces.push(pieceInfo.piece);
652
- patternData["EDGES"].orientation.push(pieceInfo.orientation);
653
- }
654
- return new KPattern(this.kpuzzle, patternData);
664
+ return new KPattern(
665
+ this.kpuzzle,
666
+ getPatternData(
667
+ stickers,
668
+ faceOrder,
669
+ gan356iEdgeMappings,
670
+ gan356iCornerMappings
671
+ )
672
+ );
655
673
  }
656
674
  async faceletStatus1Characteristic() {
657
675
  this.cachedFaceletStatus1Characteristic = this.cachedFaceletStatus1Characteristic || this.service.getCharacteristic(UUIDs.faceletStatus1Characteristic);
@@ -1198,11 +1216,636 @@ var heykubeConfig = {
1198
1216
  optionalServices: [UUIDs4.heykubeService]
1199
1217
  };
1200
1218
 
1219
+ // src/cubing/bluetooth/smart-puzzle/qiyi.ts
1220
+ var UUIDs5 = {
1221
+ qiyiMainService: 65520,
1222
+ qiyiMainCharacteristic: 65526
1223
+ };
1224
+ var qiyiMoveToBlockMove = {
1225
+ 1: new Move("L", -1),
1226
+ 2: new Move("L"),
1227
+ 3: new Move("R", -1),
1228
+ 4: new Move("R"),
1229
+ 5: new Move("D", -1),
1230
+ 6: new Move("D"),
1231
+ 7: new Move("U", -1),
1232
+ 8: new Move("U"),
1233
+ 9: new Move("F", -1),
1234
+ 10: new Move("F"),
1235
+ 11: new Move("B", -1),
1236
+ 12: new Move("B")
1237
+ };
1238
+ var faceOrder2 = "LRDUFB";
1239
+ var qiyiCornerMappings = [
1240
+ [8, 20, 9],
1241
+ // UFR,
1242
+ [2, 11, 45],
1243
+ // URB,
1244
+ [0, 47, 36],
1245
+ // UBL,
1246
+ [6, 38, 18],
1247
+ // ULF,
1248
+ [29, 15, 26],
1249
+ // DRF,
1250
+ [27, 24, 44],
1251
+ // DFL,
1252
+ [33, 42, 53],
1253
+ // DLB,
1254
+ [35, 51, 17]
1255
+ // DBR,
1256
+ ];
1257
+ var qiyiEdgeMappings = [
1258
+ [7, 19],
1259
+ // UF,
1260
+ [5, 10],
1261
+ // UR,
1262
+ [1, 46],
1263
+ // UB,
1264
+ [3, 37],
1265
+ // UL,
1266
+ [28, 25],
1267
+ // DF,
1268
+ [32, 16],
1269
+ // DR,
1270
+ [34, 52],
1271
+ // DB,
1272
+ [30, 43],
1273
+ // DL,
1274
+ [23, 12],
1275
+ // FR,
1276
+ [21, 41],
1277
+ // FL,
1278
+ [48, 14],
1279
+ // BR,
1280
+ [50, 39]
1281
+ // BL,
1282
+ ];
1283
+ function generateChecksum(data) {
1284
+ const TABLE = new Uint16Array([
1285
+ 0,
1286
+ 49345,
1287
+ 49537,
1288
+ 320,
1289
+ 49921,
1290
+ 960,
1291
+ 640,
1292
+ 49729,
1293
+ 50689,
1294
+ 1728,
1295
+ 1920,
1296
+ 51009,
1297
+ 1280,
1298
+ 50625,
1299
+ 50305,
1300
+ 1088,
1301
+ 52225,
1302
+ 3264,
1303
+ 3456,
1304
+ 52545,
1305
+ 3840,
1306
+ 53185,
1307
+ 52865,
1308
+ 3648,
1309
+ 2560,
1310
+ 51905,
1311
+ 52097,
1312
+ 2880,
1313
+ 51457,
1314
+ 2496,
1315
+ 2176,
1316
+ 51265,
1317
+ 55297,
1318
+ 6336,
1319
+ 6528,
1320
+ 55617,
1321
+ 6912,
1322
+ 56257,
1323
+ 55937,
1324
+ 6720,
1325
+ 7680,
1326
+ 57025,
1327
+ 57217,
1328
+ 8e3,
1329
+ 56577,
1330
+ 7616,
1331
+ 7296,
1332
+ 56385,
1333
+ 5120,
1334
+ 54465,
1335
+ 54657,
1336
+ 5440,
1337
+ 55041,
1338
+ 6080,
1339
+ 5760,
1340
+ 54849,
1341
+ 53761,
1342
+ 4800,
1343
+ 4992,
1344
+ 54081,
1345
+ 4352,
1346
+ 53697,
1347
+ 53377,
1348
+ 4160,
1349
+ 61441,
1350
+ 12480,
1351
+ 12672,
1352
+ 61761,
1353
+ 13056,
1354
+ 62401,
1355
+ 62081,
1356
+ 12864,
1357
+ 13824,
1358
+ 63169,
1359
+ 63361,
1360
+ 14144,
1361
+ 62721,
1362
+ 13760,
1363
+ 13440,
1364
+ 62529,
1365
+ 15360,
1366
+ 64705,
1367
+ 64897,
1368
+ 15680,
1369
+ 65281,
1370
+ 16320,
1371
+ 16e3,
1372
+ 65089,
1373
+ 64001,
1374
+ 15040,
1375
+ 15232,
1376
+ 64321,
1377
+ 14592,
1378
+ 63937,
1379
+ 63617,
1380
+ 14400,
1381
+ 10240,
1382
+ 59585,
1383
+ 59777,
1384
+ 10560,
1385
+ 60161,
1386
+ 11200,
1387
+ 10880,
1388
+ 59969,
1389
+ 60929,
1390
+ 11968,
1391
+ 12160,
1392
+ 61249,
1393
+ 11520,
1394
+ 60865,
1395
+ 60545,
1396
+ 11328,
1397
+ 58369,
1398
+ 9408,
1399
+ 9600,
1400
+ 58689,
1401
+ 9984,
1402
+ 59329,
1403
+ 59009,
1404
+ 9792,
1405
+ 8704,
1406
+ 58049,
1407
+ 58241,
1408
+ 9024,
1409
+ 57601,
1410
+ 8640,
1411
+ 8320,
1412
+ 57409,
1413
+ 40961,
1414
+ 24768,
1415
+ 24960,
1416
+ 41281,
1417
+ 25344,
1418
+ 41921,
1419
+ 41601,
1420
+ 25152,
1421
+ 26112,
1422
+ 42689,
1423
+ 42881,
1424
+ 26432,
1425
+ 42241,
1426
+ 26048,
1427
+ 25728,
1428
+ 42049,
1429
+ 27648,
1430
+ 44225,
1431
+ 44417,
1432
+ 27968,
1433
+ 44801,
1434
+ 28608,
1435
+ 28288,
1436
+ 44609,
1437
+ 43521,
1438
+ 27328,
1439
+ 27520,
1440
+ 43841,
1441
+ 26880,
1442
+ 43457,
1443
+ 43137,
1444
+ 26688,
1445
+ 30720,
1446
+ 47297,
1447
+ 47489,
1448
+ 31040,
1449
+ 47873,
1450
+ 31680,
1451
+ 31360,
1452
+ 47681,
1453
+ 48641,
1454
+ 32448,
1455
+ 32640,
1456
+ 48961,
1457
+ 32e3,
1458
+ 48577,
1459
+ 48257,
1460
+ 31808,
1461
+ 46081,
1462
+ 29888,
1463
+ 30080,
1464
+ 46401,
1465
+ 30464,
1466
+ 47041,
1467
+ 46721,
1468
+ 30272,
1469
+ 29184,
1470
+ 45761,
1471
+ 45953,
1472
+ 29504,
1473
+ 45313,
1474
+ 29120,
1475
+ 28800,
1476
+ 45121,
1477
+ 20480,
1478
+ 37057,
1479
+ 37249,
1480
+ 20800,
1481
+ 37633,
1482
+ 21440,
1483
+ 21120,
1484
+ 37441,
1485
+ 38401,
1486
+ 22208,
1487
+ 22400,
1488
+ 38721,
1489
+ 21760,
1490
+ 38337,
1491
+ 38017,
1492
+ 21568,
1493
+ 39937,
1494
+ 23744,
1495
+ 23936,
1496
+ 40257,
1497
+ 24320,
1498
+ 40897,
1499
+ 40577,
1500
+ 24128,
1501
+ 23040,
1502
+ 39617,
1503
+ 39809,
1504
+ 23360,
1505
+ 39169,
1506
+ 22976,
1507
+ 22656,
1508
+ 38977,
1509
+ 34817,
1510
+ 18624,
1511
+ 18816,
1512
+ 35137,
1513
+ 19200,
1514
+ 35777,
1515
+ 35457,
1516
+ 19008,
1517
+ 19968,
1518
+ 36545,
1519
+ 36737,
1520
+ 20288,
1521
+ 36097,
1522
+ 19904,
1523
+ 19584,
1524
+ 35905,
1525
+ 17408,
1526
+ 33985,
1527
+ 34177,
1528
+ 17728,
1529
+ 34561,
1530
+ 18368,
1531
+ 18048,
1532
+ 34369,
1533
+ 33281,
1534
+ 17088,
1535
+ 17280,
1536
+ 33601,
1537
+ 16640,
1538
+ 33217,
1539
+ 32897,
1540
+ 16448
1541
+ ]);
1542
+ let crc = 65535;
1543
+ for (const dataPoint of data) {
1544
+ const xor = (dataPoint ^ crc) & 255;
1545
+ crc >>= 8;
1546
+ crc ^= TABLE[xor];
1547
+ }
1548
+ return crc;
1549
+ }
1550
+ async function prepareMessage(message, aesKey) {
1551
+ const messageCopyForChecksum = structuredClone(message);
1552
+ const checksum = generateChecksum(messageCopyForChecksum);
1553
+ messageCopyForChecksum.push(checksum & 255);
1554
+ messageCopyForChecksum.push(checksum >> 8);
1555
+ const paddedLength = Math.ceil(messageCopyForChecksum.length / 16) * 16;
1556
+ const paddedArray = new Uint8Array([
1557
+ ...messageCopyForChecksum,
1558
+ ...Array(paddedLength - messageCopyForChecksum.length).fill(0)
1559
+ ]);
1560
+ const encryptedMessage = new Uint8Array(paddedLength);
1561
+ for (let i = 0; i < paddedArray.length / 16; i++) {
1562
+ const encryptedBlock = new Uint8Array(
1563
+ await unsafeEncryptBlock(aesKey, paddedArray.slice(i * 16, (i + 1) * 16))
1564
+ );
1565
+ encryptedMessage.set(encryptedBlock, i * 16);
1566
+ }
1567
+ return encryptedMessage;
1568
+ }
1569
+ async function decryptMessage(encryptedMessage, aesKey) {
1570
+ const decryptedMessage = new Uint8Array(encryptedMessage.length);
1571
+ for (let i = 0; i < encryptedMessage.length / 16; i++) {
1572
+ const decryptedBlock = new Uint8Array(
1573
+ await unsafeDecryptBlock(
1574
+ aesKey,
1575
+ encryptedMessage.slice(i * 16, (i + 1) * 16)
1576
+ )
1577
+ );
1578
+ decryptedMessage.set(decryptedBlock, i * 16);
1579
+ }
1580
+ return decryptedMessage;
1581
+ }
1582
+ function getMacAddress(device) {
1583
+ if (device.name === void 0) {
1584
+ return;
1585
+ }
1586
+ return [
1587
+ 204,
1588
+ 163,
1589
+ 0,
1590
+ 0,
1591
+ parseInt(device.name.slice(10, 12), 16),
1592
+ parseInt(device.name.slice(12, 14), 16)
1593
+ ];
1594
+ }
1595
+ var MAX_TIMESTAMP_COUNT = 12;
1596
+ var TIMESTAMP_SCALE = 1.6;
1597
+ var CUBE_HELLO = 2;
1598
+ var STATE_CHANGE = 3;
1599
+ var QiyiCube = class _QiyiCube extends BluetoothPuzzle {
1600
+ constructor(kpuzzle, aesKey, server) {
1601
+ super();
1602
+ this.kpuzzle = kpuzzle;
1603
+ this.aesKey = aesKey;
1604
+ this.server = server;
1605
+ this.startNotifications().then(this.sendAppHello.bind(this));
1606
+ this.allTimeStamps = /* @__PURE__ */ new Set();
1607
+ this.allTimeStampsQueue = [];
1608
+ }
1609
+ latestTimestamp;
1610
+ allTimeStamps;
1611
+ // Without this set, moves are constantly duplicated
1612
+ allTimeStampsQueue;
1613
+ stickers = [
1614
+ 3,
1615
+ 3,
1616
+ 3,
1617
+ 3,
1618
+ 3,
1619
+ 3,
1620
+ 3,
1621
+ 3,
1622
+ 3,
1623
+ 1,
1624
+ 1,
1625
+ 1,
1626
+ 1,
1627
+ 1,
1628
+ 1,
1629
+ 1,
1630
+ 1,
1631
+ 1,
1632
+ 4,
1633
+ 4,
1634
+ 4,
1635
+ 4,
1636
+ 4,
1637
+ 4,
1638
+ 4,
1639
+ 4,
1640
+ 4,
1641
+ 2,
1642
+ 2,
1643
+ 2,
1644
+ 2,
1645
+ 2,
1646
+ 2,
1647
+ 2,
1648
+ 2,
1649
+ 2,
1650
+ 0,
1651
+ 0,
1652
+ 0,
1653
+ 0,
1654
+ 0,
1655
+ 0,
1656
+ 0,
1657
+ 0,
1658
+ 0,
1659
+ 5,
1660
+ 5,
1661
+ 5,
1662
+ 5,
1663
+ 5,
1664
+ 5,
1665
+ 5,
1666
+ 5,
1667
+ 5
1668
+ ];
1669
+ batteryLevel = 100;
1670
+ static async connect(server) {
1671
+ const aesKey = await importKey(
1672
+ new Uint8Array([
1673
+ 87,
1674
+ 177,
1675
+ 249,
1676
+ 171,
1677
+ 205,
1678
+ 90,
1679
+ 232,
1680
+ 167,
1681
+ 156,
1682
+ 185,
1683
+ 140,
1684
+ 231,
1685
+ 87,
1686
+ 140,
1687
+ 81,
1688
+ 8
1689
+ ])
1690
+ );
1691
+ return new _QiyiCube(await puzzles["3x3x3"].kpuzzle(), aesKey, server);
1692
+ }
1693
+ async sendAppHello() {
1694
+ const mainService = await this.server.getPrimaryService(
1695
+ UUIDs5.qiyiMainService
1696
+ );
1697
+ const mainCharacteristic = await mainService.getCharacteristic(
1698
+ UUIDs5.qiyiMainCharacteristic
1699
+ );
1700
+ for (let macGuessCounter = 0; macGuessCounter < 8; macGuessCounter++) {
1701
+ const mac = getMacAddress(this.server.device);
1702
+ mac[3] = macGuessCounter;
1703
+ const reversedMac = mac.reverse();
1704
+ const appHello = [
1705
+ 254,
1706
+ 21,
1707
+ 0,
1708
+ 0,
1709
+ 0,
1710
+ 0,
1711
+ 0,
1712
+ 0,
1713
+ 0,
1714
+ 0,
1715
+ 0,
1716
+ 0,
1717
+ 0,
1718
+ ...reversedMac
1719
+ ];
1720
+ const appHelloMessage = await prepareMessage(appHello, this.aesKey);
1721
+ await mainCharacteristic.writeValue(appHelloMessage);
1722
+ }
1723
+ }
1724
+ async startNotifications() {
1725
+ const mainService = await this.server.getPrimaryService(
1726
+ UUIDs5.qiyiMainService
1727
+ );
1728
+ const mainCharacteristic = await mainService.getCharacteristic(
1729
+ UUIDs5.qiyiMainCharacteristic
1730
+ );
1731
+ mainCharacteristic.addEventListener(
1732
+ "characteristicvaluechanged",
1733
+ this.cubeMessageHandler.bind(this)
1734
+ );
1735
+ await mainCharacteristic.startNotifications();
1736
+ }
1737
+ async cubeMessageHandler(event) {
1738
+ const characteristic = event.target;
1739
+ const decryptedMessage = await decryptMessage(
1740
+ new Uint8Array(characteristic.value.buffer),
1741
+ this.aesKey
1742
+ );
1743
+ const opCode = decryptedMessage[2];
1744
+ let needsAck = false;
1745
+ switch (opCode) {
1746
+ case CUBE_HELLO: {
1747
+ const initialState = decryptedMessage.slice(7, 34);
1748
+ this.updateState(initialState);
1749
+ this.batteryLevel = decryptedMessage[35];
1750
+ needsAck = true;
1751
+ break;
1752
+ }
1753
+ case STATE_CHANGE: {
1754
+ const state = decryptedMessage.slice(7, 34);
1755
+ this.updateState(state);
1756
+ const latestMove = qiyiMoveToBlockMove[decryptedMessage[34]];
1757
+ const latestTimestamp = new DataView(
1758
+ decryptedMessage.slice(3, 7).buffer
1759
+ ).getInt32(0);
1760
+ const moves = [[latestMove, latestTimestamp]];
1761
+ const previousMoves = new DataView(
1762
+ decryptedMessage.slice(36, 91).buffer
1763
+ );
1764
+ for (let i = previousMoves.byteLength - 1; i > 0 && previousMoves.getUint8(i) !== 255; i -= 5) {
1765
+ const move = qiyiMoveToBlockMove[previousMoves.getUint8(i)];
1766
+ const timestamp = previousMoves.getUint32(i - 4);
1767
+ if (this.latestTimestamp === void 0 || timestamp <= this.latestTimestamp) {
1768
+ continue;
1769
+ }
1770
+ moves.push([move, timestamp]);
1771
+ }
1772
+ moves.sort((a, b) => a[1] - b[1]);
1773
+ for (const move of moves) {
1774
+ const latestAlgLeaf = move[0];
1775
+ const timeStamp = Math.round(move[1] / TIMESTAMP_SCALE);
1776
+ if (!this.allTimeStamps.has(timeStamp)) {
1777
+ this.dispatchAlgLeaf({
1778
+ latestAlgLeaf,
1779
+ timeStamp
1780
+ });
1781
+ this.allTimeStamps.add(timeStamp);
1782
+ this.allTimeStampsQueue.push(timeStamp);
1783
+ if (this.allTimeStampsQueue.length > MAX_TIMESTAMP_COUNT) {
1784
+ this.allTimeStamps.delete(this.allTimeStampsQueue.shift());
1785
+ }
1786
+ }
1787
+ }
1788
+ this.latestTimestamp = latestTimestamp;
1789
+ needsAck = decryptedMessage[91] === 1;
1790
+ break;
1791
+ }
1792
+ default:
1793
+ console.error(`Opcode not implemented: ${opCode}`);
1794
+ break;
1795
+ }
1796
+ if (needsAck) {
1797
+ await characteristic.writeValue(
1798
+ await prepareMessage(
1799
+ [254, 9, ...decryptedMessage.slice(2, 7)],
1800
+ this.aesKey
1801
+ )
1802
+ );
1803
+ }
1804
+ }
1805
+ updateState(state) {
1806
+ this.stickers = Array.from(state).flatMap((twoPieces) => [
1807
+ twoPieces & 15,
1808
+ twoPieces >> 4
1809
+ ]);
1810
+ }
1811
+ name() {
1812
+ return this.server.device.name;
1813
+ }
1814
+ disconnect() {
1815
+ this.server.disconnect();
1816
+ }
1817
+ async getPattern() {
1818
+ return new KPattern(
1819
+ this.kpuzzle,
1820
+ getPatternData(
1821
+ this.stickers,
1822
+ faceOrder2,
1823
+ qiyiEdgeMappings,
1824
+ qiyiCornerMappings
1825
+ )
1826
+ );
1827
+ }
1828
+ getBattery() {
1829
+ return this.batteryLevel;
1830
+ }
1831
+ };
1832
+ var qiyiConfig = {
1833
+ connect: QiyiCube.connect.bind(QiyiCube),
1834
+ prefixes: ["QY-QYSC"],
1835
+ filters: [
1836
+ {
1837
+ namePrefix: "QY-QYSC"
1838
+ }
1839
+ ],
1840
+ optionalServices: [UUIDs5.qiyiMainService]
1841
+ };
1842
+
1201
1843
  // src/cubing/bluetooth/smart-puzzle/connect.ts
1202
1844
  var smartPuzzleConfigs = [
1203
1845
  ganConfig,
1204
1846
  goCubeConfig,
1205
1847
  heykubeConfig,
1848
+ qiyiConfig,
1206
1849
  giiKERConfig
1207
1850
  // GiiKER must be last, due to Xiaomi naming. TODO: enforce this using tests.
1208
1851
  ];
@@ -1224,7 +1867,7 @@ var U_D_SWAP = new Alg("F B R2 L2 B' F'");
1224
1867
  var U_D_UNSWAP = U_D_SWAP.invert();
1225
1868
  var F_B_SWAP = new Alg("U D R2 L2 D' U'");
1226
1869
  var F_B_UNSWAP = F_B_SWAP.invert();
1227
- var UUIDs5 = {
1870
+ var UUIDs6 = {
1228
1871
  ganRobotService: "0000fff0-0000-1000-8000-00805f9b34fb",
1229
1872
  statusCharacteristic: "0000fff2-0000-1000-8000-00805f9b34fb",
1230
1873
  moveCharacteristic: "0000fff3-0000-1000-8000-00805f9b34fb"
@@ -1310,13 +1953,13 @@ var GanRobot = class _GanRobot extends EventTarget {
1310
1953
  // We have to perform async operations before we call the constructor.
1311
1954
  static async connect(server, device) {
1312
1955
  const ganTimerService = await server.getPrimaryService(
1313
- UUIDs5.ganRobotService
1956
+ UUIDs6.ganRobotService
1314
1957
  );
1315
1958
  const statusCharacteristic = await ganTimerService.getCharacteristic(
1316
- UUIDs5.statusCharacteristic
1959
+ UUIDs6.statusCharacteristic
1317
1960
  );
1318
1961
  const moveCharacteristic = await ganTimerService.getCharacteristic(
1319
- UUIDs5.moveCharacteristic
1962
+ UUIDs6.moveCharacteristic
1320
1963
  );
1321
1964
  const timer = new _GanRobot(
1322
1965
  ganTimerService,
@@ -1470,7 +2113,7 @@ var ganTimerConfig = {
1470
2113
  connect: GanRobot.connect.bind(GanRobot),
1471
2114
  prefixes: ["GAN"],
1472
2115
  filters: [{ namePrefix: "GAN" }],
1473
- optionalServices: [UUIDs5.ganRobotService]
2116
+ optionalServices: [UUIDs6.ganRobotService]
1474
2117
  };
1475
2118
 
1476
2119
  // src/cubing/bluetooth/smart-robot/index.ts
@@ -1480,7 +2123,7 @@ async function connectSmartRobot(options) {
1480
2123
  }
1481
2124
 
1482
2125
  // src/cubing/bluetooth/smart-timer/GanTimer.ts
1483
- var UUIDs6 = {
2126
+ var UUIDs7 = {
1484
2127
  ganTimerService: "0000fff0-0000-1000-8000-00805f9b34fb",
1485
2128
  timeCharacteristic: "0000fff2-0000-1000-8000-00805f9b34fb"
1486
2129
  };
@@ -1501,11 +2144,11 @@ var GanTimer = class _GanTimer extends EventTarget {
1501
2144
  // We have to perform async operations before we call the constructor.
1502
2145
  static async connect(server, device) {
1503
2146
  const ganTimerService = await server.getPrimaryService(
1504
- UUIDs6.ganTimerService
2147
+ UUIDs7.ganTimerService
1505
2148
  );
1506
2149
  console.log("Service:", ganTimerService);
1507
2150
  const timeCharacteristic = await ganTimerService.getCharacteristic(
1508
- UUIDs6.timeCharacteristic
2151
+ UUIDs7.timeCharacteristic
1509
2152
  );
1510
2153
  console.log("Characteristic:", timeCharacteristic);
1511
2154
  const timer = new _GanTimer(
@@ -1576,7 +2219,7 @@ var ganTimerConfig2 = {
1576
2219
  connect: GanTimer.connect.bind(GanTimer),
1577
2220
  prefixes: ["GAN"],
1578
2221
  filters: [{ namePrefix: "GAN" }],
1579
- optionalServices: [UUIDs6.ganTimerService]
2222
+ optionalServices: [UUIDs7.ganTimerService]
1580
2223
  };
1581
2224
 
1582
2225
  // src/cubing/bluetooth/smart-timer/index.ts