@houstonp/rubiks-cube 1.5.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +280 -170
- package/package.json +33 -3
- package/src/camera/cameraState.js +81 -0
- package/src/core.js +447 -0
- package/src/cube/animationSlice.js +205 -0
- package/src/cube/animationState.js +96 -0
- package/src/cube/cubeSettings.js +19 -0
- package/src/cube/cubeState.js +285 -139
- package/src/cube/stickerState.js +188 -0
- package/src/debouncer.js +16 -0
- package/src/globals.ts +9 -0
- package/src/index.js +621 -0
- package/src/settings.js +138 -0
- package/src/three/centerPiece.js +44 -0
- package/src/three/cornerPiece.js +60 -0
- package/src/three/cube.js +492 -0
- package/src/three/edgePiece.js +50 -0
- package/src/three/sticker.js +37 -0
- package/tests/common.js +27 -0
- package/tests/cube.five.test.js +126 -0
- package/tests/cube.four.test.js +126 -0
- package/tests/cube.seven.test.js +126 -0
- package/tests/cube.six.test.js +126 -0
- package/tests/cube.three.test.js +151 -0
- package/tests/cube.two.test.js +125 -0
- package/tests/setup.js +36 -0
- package/types/camera/cameraState.d.ts +19 -0
- package/types/core.d.ts +454 -0
- package/types/cube/animationSlice.d.ts +26 -0
- package/types/cube/animationState.d.ts +41 -0
- package/types/cube/cubeSettings.d.ts +17 -0
- package/types/cube/cubeState.d.ts +47 -0
- package/types/cube/stickerState.d.ts +21 -0
- package/types/debouncer.d.ts +13 -0
- package/types/globals.d.ts +7 -0
- package/types/index.d.ts +87 -0
- package/types/settings.d.ts +38 -0
- package/types/three/centerPiece.d.ts +15 -0
- package/types/three/cornerPiece.d.ts +24 -0
- package/types/three/cube.d.ts +130 -0
- package/types/three/edgePiece.d.ts +16 -0
- package/types/three/sticker.d.ts +15 -0
- package/.prettierrc +0 -7
- package/index.js +0 -274
- package/src/cube/cube.js +0 -276
- package/src/cube/cubeRotation.js +0 -63
- package/src/threejs/materials.js +0 -42
- package/src/threejs/pieces.js +0 -103
- package/src/threejs/stickers.js +0 -48
- package/src/utils/debouncer.js +0 -7
- package/src/utils/rotation.js +0 -53
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/** @typedef {{ up: import('../core').Face[][], down: import('../core').Face[][], front: import('../core').Face[][], back: import('../core').Face[][], left: import('../core').Face[][], right: import('../core').Face[][] }} StickerState*/
|
|
3
|
+
|
|
4
|
+
import { CubeTypes, Faces } from '../core';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param {import('../core').CubeType} cubeType
|
|
9
|
+
* @return {StickerState}
|
|
10
|
+
*/
|
|
11
|
+
export const defaultStickerState = (cubeType) => {
|
|
12
|
+
const length = 0;
|
|
13
|
+
switch (cubeType) {
|
|
14
|
+
case CubeTypes.Two:
|
|
15
|
+
return initialStickerState(2);
|
|
16
|
+
case CubeTypes.Three:
|
|
17
|
+
return initialStickerState(3);
|
|
18
|
+
case CubeTypes.Four:
|
|
19
|
+
return initialStickerState(4);
|
|
20
|
+
case CubeTypes.Five:
|
|
21
|
+
return initialStickerState(5);
|
|
22
|
+
case CubeTypes.Six:
|
|
23
|
+
return initialStickerState(6);
|
|
24
|
+
case CubeTypes.Seven:
|
|
25
|
+
return initialStickerState(7);
|
|
26
|
+
default:
|
|
27
|
+
throw new Error(`Unsupported cube type: ${cubeType}`);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
*
|
|
33
|
+
* @param {number} layerCount
|
|
34
|
+
* @returns {StickerState}
|
|
35
|
+
*/
|
|
36
|
+
const initialStickerState = (layerCount) => {
|
|
37
|
+
const state = {
|
|
38
|
+
right: Array.from({ length: layerCount }, () => Array.from({ length: layerCount }, () => Faces.R)),
|
|
39
|
+
up: Array.from({ length: layerCount }, () => Array.from({ length: layerCount }, () => Faces.U)),
|
|
40
|
+
front: Array.from({ length: layerCount }, () => Array.from({ length: layerCount }, () => Faces.F)),
|
|
41
|
+
back: Array.from({ length: layerCount }, () => Array.from({ length: layerCount }, () => Faces.B)),
|
|
42
|
+
down: Array.from({ length: layerCount }, () => Array.from({ length: layerCount }, () => Faces.D)),
|
|
43
|
+
left: Array.from({ length: layerCount }, () => Array.from({ length: layerCount }, () => Faces.L)),
|
|
44
|
+
};
|
|
45
|
+
return state;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
*
|
|
50
|
+
* @param {import('../core').CubeType} cubeType
|
|
51
|
+
* @return {StickerState}
|
|
52
|
+
*/
|
|
53
|
+
export const getEmptyStickerState = (cubeType) => {
|
|
54
|
+
const length = 0;
|
|
55
|
+
switch (cubeType) {
|
|
56
|
+
case CubeTypes.Two:
|
|
57
|
+
return emptyStickerState(2);
|
|
58
|
+
case CubeTypes.Three:
|
|
59
|
+
return emptyStickerState(3);
|
|
60
|
+
case CubeTypes.Four:
|
|
61
|
+
return emptyStickerState(4);
|
|
62
|
+
case CubeTypes.Five:
|
|
63
|
+
return emptyStickerState(5);
|
|
64
|
+
case CubeTypes.Six:
|
|
65
|
+
return emptyStickerState(6);
|
|
66
|
+
case CubeTypes.Seven:
|
|
67
|
+
return emptyStickerState(7);
|
|
68
|
+
default:
|
|
69
|
+
throw new Error(`Unsupported cube type: ${cubeType}`);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
*
|
|
74
|
+
* @param {number} layerCount
|
|
75
|
+
* @returns {StickerState}
|
|
76
|
+
*/
|
|
77
|
+
const emptyStickerState = (layerCount) => {
|
|
78
|
+
const state = {
|
|
79
|
+
right: Array.from({ length: layerCount }, () => []),
|
|
80
|
+
up: Array.from({ length: layerCount }, () => []),
|
|
81
|
+
front: Array.from({ length: layerCount }, () => []),
|
|
82
|
+
back: Array.from({ length: layerCount }, () => []),
|
|
83
|
+
down: Array.from({ length: layerCount }, () => []),
|
|
84
|
+
left: Array.from({ length: layerCount }, () => []),
|
|
85
|
+
};
|
|
86
|
+
return state;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @param {StickerState} stickerState
|
|
91
|
+
* @returns {string}
|
|
92
|
+
*/
|
|
93
|
+
export function toKociemba(stickerState) {
|
|
94
|
+
return `${stickerState.up.flat().join('')}${stickerState.right.flat().join('')}${stickerState.front.flat().join('')}${stickerState.down.flat().join('')}${stickerState.left.flat().join('')}${stickerState.back.flat().join('')}`;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {string} kociembaString
|
|
99
|
+
* @param {import('../core').CubeType} cubeType
|
|
100
|
+
* @returns {StickerState | undefined} stickerState
|
|
101
|
+
*/
|
|
102
|
+
export function fromKociemba(kociembaString, cubeType) {
|
|
103
|
+
const length = kociembaString.length;
|
|
104
|
+
switch (cubeType) {
|
|
105
|
+
case CubeTypes.Two:
|
|
106
|
+
if (length != 6 * 2 ** 2) {
|
|
107
|
+
console.error('Invalid state string length. Length must be 24 for 2x2 cubes.');
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
return fromKociembaWithLayerCount(kociembaString, 2);
|
|
111
|
+
case CubeTypes.Three:
|
|
112
|
+
if (length != 6 * 3 ** 2) {
|
|
113
|
+
console.error('Invalid state string length. Length must be 54 for 3x3 cubes.');
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
return fromKociembaWithLayerCount(kociembaString, 3);
|
|
117
|
+
case CubeTypes.Four:
|
|
118
|
+
if (length != 6 * 4 ** 2) {
|
|
119
|
+
console.error('Invalid state string length. Length must be 96 for 4x4 cubes.');
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
return fromKociembaWithLayerCount(kociembaString, 4);
|
|
123
|
+
case CubeTypes.Five:
|
|
124
|
+
if (length != 6 * 5 ** 2) {
|
|
125
|
+
console.error('Invalid state string length. Length must be 150 for 5x5 cubes.');
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
return fromKociembaWithLayerCount(kociembaString, 5);
|
|
129
|
+
case CubeTypes.Six:
|
|
130
|
+
if (length != 6 * 6 ** 2) {
|
|
131
|
+
console.error('Invalid state string length. Length must be 216 for 6x6 cubes.');
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
return fromKociembaWithLayerCount(kociembaString, 6);
|
|
135
|
+
case CubeTypes.Seven:
|
|
136
|
+
if (length != 6 * 7 ** 2) {
|
|
137
|
+
console.error('Invalid state string length. Length must be 294 for 7x7 cubes.');
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
return fromKociembaWithLayerCount(kociembaString, 7);
|
|
141
|
+
default:
|
|
142
|
+
undefined;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @param {string} kociembaString
|
|
148
|
+
* @param {number} layerCount
|
|
149
|
+
* @returns {StickerState | undefined } stickerState
|
|
150
|
+
*/
|
|
151
|
+
function fromKociembaWithLayerCount(kociembaString, layerCount) {
|
|
152
|
+
let stickerState = emptyStickerState(layerCount);
|
|
153
|
+
for (let i = 0; i < 6; i++) {
|
|
154
|
+
const faceString = kociembaString.slice(i * layerCount ** 2, (i + 1) * layerCount ** 2);
|
|
155
|
+
for (let j = 0; j < layerCount; j++) {
|
|
156
|
+
const rowString = faceString.slice(j * layerCount, (j + 1) * layerCount);
|
|
157
|
+
for (let k = 0; k < layerCount; k++) {
|
|
158
|
+
const face = Object.values(Faces).find((face) => rowString[k] === face);
|
|
159
|
+
if (!face) {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
switch (i) {
|
|
163
|
+
case 0:
|
|
164
|
+
stickerState.up[j][k] = face;
|
|
165
|
+
break;
|
|
166
|
+
case 1:
|
|
167
|
+
stickerState.right[j][k] = face;
|
|
168
|
+
break;
|
|
169
|
+
case 2:
|
|
170
|
+
stickerState.front[j][k] = face;
|
|
171
|
+
break;
|
|
172
|
+
case 3:
|
|
173
|
+
stickerState.down[j][k] = face;
|
|
174
|
+
break;
|
|
175
|
+
case 4:
|
|
176
|
+
stickerState.left[j][k] = face;
|
|
177
|
+
break;
|
|
178
|
+
case 5:
|
|
179
|
+
stickerState.back[j][k] = face;
|
|
180
|
+
break;
|
|
181
|
+
default:
|
|
182
|
+
throw new Error(`Invalid value for i - [${i}]. i should be between [0,5] inclusive.`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return stickerState;
|
|
188
|
+
}
|
package/src/debouncer.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* @param {number} delay
|
|
4
|
+
* @param {{ (entries: { contentRect: { width: number; height: number; }; }[]): void; apply?: any; }} f
|
|
5
|
+
*/
|
|
6
|
+
export function debounce(f, delay) {
|
|
7
|
+
let timer = 0;
|
|
8
|
+
/**
|
|
9
|
+
* @this {any}
|
|
10
|
+
* @param {any[]} args
|
|
11
|
+
*/
|
|
12
|
+
return function (...args) {
|
|
13
|
+
clearTimeout(timer);
|
|
14
|
+
timer = window.setTimeout(() => f.apply(this, args), delay);
|
|
15
|
+
};
|
|
16
|
+
}
|