我有新的 Giiker cube i3s,它具有加密状态。Giiker cube i3 并非如此。
可以在此处找到解码加密状态的逻辑。
https://github.com/kabelbinder/giiker/blob/50db5d58e0417749fe5815e72856b90a1afa43b1/index.js#L326
下面是解密和解析的逻辑。
const turns = {
0: 1,
1: 2,
2: -1,
8: -2,
};
const faces = ['B', 'D', 'L', 'U', 'R', 'F'];
_parseCubeValue (value) {
const state = {
cornerPositions: [],
cornerOrientations: [],
edgePositions: [],
edgeOrientations: []
};
const moves = [];
if (value.getUint8(18) == 0xa7) { // decrypt
var key = [176, 81, 104, 224, 86, 137, 237, 119, 38, 26, 193, 161, 210, 126, 150, 81, 93, 13, 236, 249, 89, 235, 88, 24, 113, 81, 214, 131, 130, 199, 2, 169, 39, 165, 171, 41];
var k = value.getUint8(19);
var k1 = k >> 4 & 0xf;
var k2 = k & 0xf;
for (let i = 0; i < value.byteLength; i++) {
const move = (value.getUint8(i) + key[i + k1] + key[i + k2]) & 0xff;
const highNibble = move >> 4;
const lowNibble = move & 0b1111;
if (i < 4) {
state.cornerPositions.push(highNibble, lowNibble);
} else if (i < 8) {
state.cornerOrientations.push(highNibble, lowNibble);
} else if (i < 14) {
state.edgePositions.push(highNibble, lowNibble);
} else if (i < 16) {
state.edgeOrientations.push(!!(move & 0b10000000));
state.edgeOrientations.push(!!(move & 0b01000000));
state.edgeOrientations.push(!!(move & 0b00100000));
state.edgeOrientations.push(!!(move & 0b00010000));
if (i === 14) {
state.edgeOrientations.push(!!(move & 0b00001000));
state.edgeOrientations.push(!!(move & 0b00000100));
state.edgeOrientations.push(!!(move & 0b00000010));
state.edgeOrientations.push(!!(move & 0b00000001));
}
} else {
moves.push(this._parseMove(highNibble, lowNibble));
}
}
}
else { // not encrypted
for (let i = 0; i < value.byteLength; i++) {
const move = value.getUint8(i)
const highNibble = move >> 4;
const lowNibble = move & 0b1111;
if (i < 4) {
state.cornerPositions.push(highNibble, lowNibble);
} else if (i < 8) {
state.cornerOrientations.push(highNibble, lowNibble);
} else if (i < 14) {
state.edgePositions.push(highNibble, lowNibble);
} else if (i < 16) {
state.edgeOrientations.push(!!(move & 0b10000000));
state.edgeOrientations.push(!!(move & 0b01000000));
state.edgeOrientations.push(!!(move & 0b00100000));
state.edgeOrientations.push(!!(move & 0b00010000));
if (i === 14) {
state.edgeOrientations.push(!!(move & 0b00001000));
state.edgeOrientations.push(!!(move & 0b00000100));
state.edgeOrientations.push(!!(move & 0b00000010));
state.edgeOrientations.push(!!(move & 0b00000001));
}
} else {
moves.push(this._parseMove(highNibble, lowNibble));
}
}
}
return {state, moves};
}
_parseMove (faceIndex, turnIndex) {
const face = faces[faceIndex - 1];
const amount = turns[turnIndex - 1];
let notation = face;
switch (amount) {
case 2: notation = `${face}2`; break;
case -1: notation = `${face}'`; break;
case -2: notation = `${face}2'`; break;
}
return {face, amount, notation};
}