chore: bump version to 0.0.29
All checks were successful
Deploy to Production / deploy (push) Successful in 9s

This commit is contained in:
2026-02-22 20:31:54 +00:00
parent a9881bb5fa
commit a75c148a5b
7 changed files with 104 additions and 119 deletions

View File

@@ -191,16 +191,16 @@ export class CubeModel {
cubie.faces[FACES.FRONT] = f[FACES.RIGHT];
}
} else if (axis === 'z') {
if (direction === 1) { // Up -> Right -> Down -> Left -> Up (CW)
cubie.faces[FACES.RIGHT] = f[FACES.UP];
cubie.faces[FACES.DOWN] = f[FACES.RIGHT];
cubie.faces[FACES.LEFT] = f[FACES.DOWN];
cubie.faces[FACES.UP] = f[FACES.LEFT];
} else { // Up -> Left -> Down -> Right -> Up (CCW)
if (direction === 1) { // CCW: Up -> Left -> Down -> Right -> Up
cubie.faces[FACES.LEFT] = f[FACES.UP];
cubie.faces[FACES.DOWN] = f[FACES.LEFT];
cubie.faces[FACES.RIGHT] = f[FACES.DOWN];
cubie.faces[FACES.UP] = f[FACES.RIGHT];
} else { // CW: Up -> Right -> Down -> Left -> Up
cubie.faces[FACES.RIGHT] = f[FACES.UP];
cubie.faces[FACES.DOWN] = f[FACES.RIGHT];
cubie.faces[FACES.LEFT] = f[FACES.DOWN];
cubie.faces[FACES.UP] = f[FACES.LEFT];
}
}
}

View File

@@ -1,4 +1,5 @@
import { State } from 'rubiks-js/src/state/index.js';
import { CubeModel } from './CubeModel.js';
// Static order definitions from rubiks-js source
const CORNER_ORDER = ['URF', 'ULF', 'ULB', 'URB', 'DRF', 'DLF', 'DLB', 'DRB'];
@@ -113,32 +114,27 @@ const getEdgeColors = (name) => {
export class RubiksJSModel {
constructor() {
this.state = new State(false); // trackCenters=false
this.visual = new CubeModel();
}
reset() {
// State doesn't have a reset method exposed directly?
// We can just create a new state.
this.state = new State(false);
this.visual = new CubeModel();
}
rotateLayer(axis, index, dir) {
// Map to standard notation
// axis: 'x', 'y', 'z'
// index: 1 (top/right/front), -1 (bottom/left/back)
// dir: 1 (Visual CCW), -1 (Visual CW)
let move = '';
if (axis === 'y') {
if (index === 1) move = dir === 1 ? "U'" : "U";
else if (index === -1) move = dir === 1 ? "D'" : "D"; // Fixed: dir=1 (CCW) -> D'
else if (index === -1) move = dir === 1 ? "D'" : "D";
}
else if (axis === 'x') {
if (index === 1) move = dir === 1 ? "R'" : "R";
else if (index === -1) move = dir === 1 ? "L'" : "L"; // Fixed: dir=1 (CCW) -> L'
else if (index === -1) move = dir === 1 ? "L'" : "L";
}
else if (axis === 'z') {
if (index === 1) move = dir === 1 ? "F'" : "F";
else if (index === -1) move = dir === 1 ? "B'" : "B"; // Fixed: dir=1 (CCW) -> B'
else if (index === -1) move = dir === 1 ? "B'" : "B";
}
if (move) {
@@ -149,109 +145,24 @@ export class RubiksJSModel {
} catch (e) {
console.error('[RubiksJSModel] Failed to apply move:', move, e);
}
this.visual.rotateLayer(axis, index, dir);
}
}
applyTurn(move) {
if (!move) return;
try {
this.state.applyTurn(move);
} catch (e) {
console.error('[RubiksJSModel] Failed to apply direct move:', move, e);
}
this.visual.applyMove(move);
}
toCubies() {
// Decode state
const encoded = this.state.encode();
// console.log('[RubiksJSModel] Encoded state:', encoded);
const binaryString = atob(encoded);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
// Decode Corners (first 5 bytes)
// p: bytes[0] + (bytes[1] << 8) + (bytes[2] << 16)
let pC = bytes[0] + (bytes[1] << 8) + (bytes[2] << 16);
let oC = bytes[3] + (bytes[4] << 8);
const cornerPerms = [];
const cornerOrients = [];
for (let i = 7; i >= 0; i--) {
const p1 = pC & 0b111;
cornerPerms[i] = CORNER_ORDER[p1];
pC = pC >> 3;
const o1 = oC & 0b11;
cornerOrients[i] = o1;
oC = oC >> 2;
}
// Decode Edges (next 8 bytes)
// 6 bytes for permutation (each byte has 2 nibbles)
// 2 bytes for orientation
const edgePerms = [];
const edgeOrients = [];
// Permutation
for (let i = 0; i < 6; i++) {
const byte = bytes[5 + i];
const p1 = byte & 0b1111;
const p2 = (byte >> 4) & 0b1111;
edgePerms[i * 2] = EDGE_ORDER[p1];
edgePerms[i * 2 + 1] = EDGE_ORDER[p2];
}
// Orientation
let oE = bytes[11] + (bytes[12] << 8);
for (let i = 11; i >= 0; i--) {
edgeOrients[i] = oE & 0b1;
oE = oE >> 1;
}
const cubies = [...CENTERS];
// Map Corners
for (let i = 0; i < 8; i++) {
const pieceName = cornerPerms[i]; // e.g. 'URF'
const orientation = cornerOrients[i]; // 0, 1, 2
const slot = CORNER_SLOTS[i]; // Slot definition
const baseColors = getCornerColors(pieceName); // ['white', 'red', 'green']
const slotFaces = CORNER_FACES[slot.id]; // ['up', 'right', 'front']
// Apply orientation
// Formula: Color at SlotKey[k] is PieceColor[(k + o) % 3]
const faces = {};
faces[slotFaces[0]] = baseColors[(0 + orientation) % 3];
faces[slotFaces[1]] = baseColors[(1 + orientation) % 3];
faces[slotFaces[2]] = baseColors[(2 + orientation) % 3];
cubies.push({ id: `corn${i}`, x: slot.x, y: slot.y, z: slot.z, faces });
}
// Map Edges
for (let i = 0; i < 12; i++) {
const pieceName = edgePerms[i];
const orientation = edgeOrients[i]; // 0, 1
const slot = EDGE_SLOTS[i];
const baseColors = getEdgeColors(pieceName); // ['white', 'green']
const slotFaces = EDGE_FACES[slot.id]; // ['up', 'front']
const faces = {};
// If orientation is 1 (Flip), we swap.
// But we need to be careful about which face is primary (0).
// Logic: if o=0, faces match. if o=1, swap.
// Adjust for specific edges if needed?
// For now assume standard behavior:
if (orientation === 0) {
faces[slotFaces[0]] = baseColors[0];
faces[slotFaces[1]] = baseColors[1];
} else {
faces[slotFaces[0]] = baseColors[1];
faces[slotFaces[1]] = baseColors[0];
}
cubies.push({ id: `edge${i}`, x: slot.x, y: slot.y, z: slot.z, faces });
}
return cubies;
return this.visual.toCubies();
}
validate() {