@houstonp/rubiks-cube 2.0.0 → 3.0.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 +494 -63
- package/package.json +22 -12
- package/src/core/index.js +478 -0
- package/src/rubiksCube/index.js +3 -0
- package/src/rubiksCube/rubiksCubeController.js +111 -0
- package/src/rubiksCube3D/centerPiece.js +79 -0
- package/src/rubiksCube3D/cornerPiece.js +114 -0
- package/src/rubiksCube3D/cubeConfig.js +87 -0
- package/src/rubiksCube3D/cubeSettings.js +30 -0
- package/src/rubiksCube3D/edgePiece.js +51 -0
- package/src/rubiksCube3D/index.js +3 -0
- package/src/rubiksCube3D/rubiksCube3D.js +383 -0
- package/src/rubiksCube3D/sticker.js +38 -0
- package/src/state/index.js +4 -0
- package/src/state/rubiksCubeState.js +471 -0
- package/src/state/slice.js +236 -0
- package/src/state/stickerState.js +185 -0
- package/src/{cameraState.js → webComponent/cameraState.js} +17 -25
- package/src/webComponent/constants.js +67 -0
- package/src/{debouncer.js → webComponent/debouncer.js} +1 -1
- package/src/webComponent/index.js +7 -0
- package/src/webComponent/rubiksCubeElement.js +379 -0
- package/src/{settings.js → webComponent/settings.js} +47 -22
- package/tests/common.js +10 -0
- package/tests/core.test.js +56 -0
- package/tests/rubiksCube.solves.test.js +41 -0
- package/tests/rubiksCube3D.solves.test.js +185 -0
- package/tests/rubiksCubeState.solves.test.js +35 -0
- package/tests/setup.js +36 -0
- package/tests/testScrambles.js +194 -0
- package/types/core/index.d.ts +451 -0
- package/types/rubiksCube/index.d.ts +3 -0
- package/types/rubiksCube/rubiksCubeController.d.ts +62 -0
- package/types/rubiksCube3D/centerPiece.d.ts +27 -0
- package/types/rubiksCube3D/cornerPiece.d.ts +38 -0
- package/types/rubiksCube3D/cubeConfig.d.ts +32 -0
- package/types/rubiksCube3D/cubeSettings.d.ts +33 -0
- package/types/rubiksCube3D/edgePiece.d.ts +18 -0
- package/types/rubiksCube3D/index.d.ts +3 -0
- package/types/rubiksCube3D/rubiksCube3D.d.ts +120 -0
- package/types/rubiksCube3D/sticker.d.ts +18 -0
- package/types/state/index.d.ts +5 -0
- package/types/state/rubiksCubeState.d.ts +108 -0
- package/types/state/slice.d.ts +46 -0
- package/types/state/stickerState.d.ts +34 -0
- package/types/webComponent/cameraState.d.ts +22 -0
- package/types/webComponent/constants.d.ts +57 -0
- package/types/webComponent/index.d.ts +6 -0
- package/types/webComponent/rubiksCubeElement.d.ts +89 -0
- package/types/{settings.d.ts → webComponent/settings.d.ts} +9 -8
- package/src/core.js +0 -127
- package/src/cube/cube.js +0 -324
- package/src/cube/cubeRotation.js +0 -79
- package/src/cube/cubeSettings.js +0 -18
- package/src/cube/cubeState.js +0 -192
- package/src/cube/slice.js +0 -143
- package/src/index.js +0 -496
- package/src/schema.js +0 -22
- package/src/threejs/materials.js +0 -54
- package/src/threejs/pieces.js +0 -100
- package/src/threejs/stickers.js +0 -40
- package/types/cameraState.d.ts +0 -19
- package/types/core.d.ts +0 -125
- package/types/cube/cube.d.ts +0 -102
- package/types/cube/cubeRotation.d.ts +0 -33
- package/types/cube/cubeSettings.d.ts +0 -17
- package/types/cube/cubeState.d.ts +0 -16
- package/types/cube/slice.d.ts +0 -15
- package/types/index.d.ts +0 -65
- package/types/schema.d.ts +0 -11
- package/types/threejs/materials.d.ts +0 -21
- package/types/threejs/pieces.d.ts +0 -28
- package/types/threejs/stickers.d.ts +0 -6
- /package/src/{globals.ts → webComponent/globals.ts} +0 -0
- /package/types/{debouncer.d.ts → webComponent/debouncer.d.ts} +0 -0
- /package/types/{globals.d.ts → webComponent/globals.d.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@houstonp/rubiks-cube",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Rubiks Cube Web Component built with threejs",
|
|
5
5
|
"author": "Houston Pearse",
|
|
6
6
|
"license": "MIT",
|
|
@@ -11,25 +11,32 @@
|
|
|
11
11
|
"renderer",
|
|
12
12
|
"threejs"
|
|
13
13
|
],
|
|
14
|
-
"main": "./src/index.js",
|
|
15
|
-
"types": "./types/index.d.ts",
|
|
16
14
|
"exports": {
|
|
17
|
-
"
|
|
18
|
-
"types": "./types/index.d.ts",
|
|
19
|
-
"default": "./src/index.js"
|
|
15
|
+
"./view": {
|
|
16
|
+
"types": "./types/webComponent/index.d.ts",
|
|
17
|
+
"default": "./src/webComponent/index.js"
|
|
20
18
|
},
|
|
21
|
-
"./
|
|
22
|
-
"types": "./types/
|
|
23
|
-
"default": "./src/
|
|
19
|
+
"./three": {
|
|
20
|
+
"types": "./types/rubiksCube3D/index.d.ts",
|
|
21
|
+
"default": "./src/rubiksCube3D/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./controller": {
|
|
24
|
+
"types": "./types/rubiksCube/index.d.ts",
|
|
25
|
+
"default": "./src/rubiksCube/index.js"
|
|
24
26
|
},
|
|
25
27
|
"./core": {
|
|
26
|
-
"types": "./types/core.d.ts",
|
|
27
|
-
"default": "./src/core.js"
|
|
28
|
+
"types": "./types/core/index.d.ts",
|
|
29
|
+
"default": "./src/core/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./state": {
|
|
32
|
+
"types": "./types/state/index.d.ts",
|
|
33
|
+
"default": "./src/state/index.js"
|
|
28
34
|
}
|
|
29
35
|
},
|
|
30
36
|
"scripts": {
|
|
31
37
|
"build:types": "tsc",
|
|
32
|
-
"watch:types": "tsc --watch"
|
|
38
|
+
"watch:types": "tsc --watch",
|
|
39
|
+
"test": "bun test"
|
|
33
40
|
},
|
|
34
41
|
"dependencies": {
|
|
35
42
|
"gsap": "^3.14.2",
|
|
@@ -44,7 +51,10 @@
|
|
|
44
51
|
},
|
|
45
52
|
"homepage": "https://github.com/houstonpearse/rubiks-cube#readme",
|
|
46
53
|
"devDependencies": {
|
|
54
|
+
"@types/bun": "^1.3.9",
|
|
55
|
+
"@types/jsdom": "^27.0.0",
|
|
47
56
|
"@types/three": "^0.182.0",
|
|
57
|
+
"jsdom": "^28.1.0",
|
|
48
58
|
"typescript": "^5.9.3"
|
|
49
59
|
}
|
|
50
60
|
}
|
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* reverses the direction of a movement or rotation
|
|
5
|
+
* @template {Movement | Rotation} T
|
|
6
|
+
* @param {T} action
|
|
7
|
+
* @returns {T}
|
|
8
|
+
* */
|
|
9
|
+
export function reverse(action) {
|
|
10
|
+
let reversedAction = action;
|
|
11
|
+
if (action.at(-1) === "'") {
|
|
12
|
+
reversedAction = /** @type {T} */ (action.slice(0, -1));
|
|
13
|
+
} else {
|
|
14
|
+
const newAction = /** @type {T} */ (action + "'");
|
|
15
|
+
reversedAction = newAction;
|
|
16
|
+
}
|
|
17
|
+
return reversedAction;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Translates notation meant for a 3x3 into notation a big cube. This is so that 3x3 algorithms can be used on a big cube if desired. eg. for a 6x6 r -> 5r
|
|
22
|
+
* @template {Movement | Rotation} T
|
|
23
|
+
* @param {T} action
|
|
24
|
+
* @param {CubeType} cubeType
|
|
25
|
+
* @returns {T}
|
|
26
|
+
* */
|
|
27
|
+
export function translate(action, cubeType) {
|
|
28
|
+
if (Object.values(Movements.Wide).includes(/** @type {WideMove} **/ (action))) {
|
|
29
|
+
return /** @type {T} */ (LayerCount[cubeType] - 1 + action);
|
|
30
|
+
}
|
|
31
|
+
return action;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @typedef {typeof Movements.Single[keyof typeof Movements.Single]} SingleMove
|
|
36
|
+
* @typedef {typeof Movements.Wide[keyof typeof Movements.Wide]} WideMove
|
|
37
|
+
* @typedef {typeof Movements.Two[keyof typeof Movements.Two]} TwoMove
|
|
38
|
+
* @typedef {typeof Movements.Three[keyof typeof Movements.Three]} ThreeMove
|
|
39
|
+
* @typedef {typeof Movements.Four[keyof typeof Movements.Four]} FourMove
|
|
40
|
+
* @typedef {typeof Movements.Five[keyof typeof Movements.Five]} FiveMove
|
|
41
|
+
* @typedef {typeof Movements.Six[keyof typeof Movements.Six]} SixMove
|
|
42
|
+
* @typedef {SingleMove | WideMove | TwoMove | ThreeMove | FourMove | FiveMove | SixMove} Movement
|
|
43
|
+
*/
|
|
44
|
+
export const Movements = Object.freeze({
|
|
45
|
+
Single: Object.freeze({
|
|
46
|
+
R: 'R',
|
|
47
|
+
R2: 'R2',
|
|
48
|
+
RP: "R'",
|
|
49
|
+
L: 'L',
|
|
50
|
+
L2: 'L2',
|
|
51
|
+
LP: "L'",
|
|
52
|
+
U: 'U',
|
|
53
|
+
U2: 'U2',
|
|
54
|
+
UP: "U'",
|
|
55
|
+
D: 'D',
|
|
56
|
+
D2: 'D2',
|
|
57
|
+
DP: "D'",
|
|
58
|
+
F: 'F',
|
|
59
|
+
F2: 'F2',
|
|
60
|
+
FP: "F'",
|
|
61
|
+
B: 'B',
|
|
62
|
+
B2: 'B2',
|
|
63
|
+
BP: "B'",
|
|
64
|
+
M: 'M',
|
|
65
|
+
M2: 'M2',
|
|
66
|
+
MP: "M'",
|
|
67
|
+
E: 'E',
|
|
68
|
+
E2: 'E2',
|
|
69
|
+
EP: "E'",
|
|
70
|
+
S: 'S',
|
|
71
|
+
S2: 'S2',
|
|
72
|
+
SP: "S'",
|
|
73
|
+
}),
|
|
74
|
+
Wide: Object.freeze({
|
|
75
|
+
Rw: 'Rw',
|
|
76
|
+
Rw2: 'Rw2',
|
|
77
|
+
RwP: "Rw'",
|
|
78
|
+
r: 'r',
|
|
79
|
+
r2: 'r2',
|
|
80
|
+
rP: "r'",
|
|
81
|
+
Lw: 'Lw',
|
|
82
|
+
Lw2: 'Lw2',
|
|
83
|
+
LwP: "Lw'",
|
|
84
|
+
l: 'l',
|
|
85
|
+
l2: 'l2',
|
|
86
|
+
lP: "l'",
|
|
87
|
+
Fw: 'Fw',
|
|
88
|
+
Fw2: 'Fw2',
|
|
89
|
+
FwP: "Fw'",
|
|
90
|
+
f: 'f',
|
|
91
|
+
f2: 'f2',
|
|
92
|
+
fP: "f'",
|
|
93
|
+
Bw: 'Bw',
|
|
94
|
+
Bw2: 'Bw2',
|
|
95
|
+
BwP: "Bw'",
|
|
96
|
+
b: 'b',
|
|
97
|
+
b2: 'b2',
|
|
98
|
+
bP: "b'",
|
|
99
|
+
Uw: 'Uw',
|
|
100
|
+
Uw2: 'Uw2',
|
|
101
|
+
UwP: "Uw'",
|
|
102
|
+
u: 'u',
|
|
103
|
+
u2: 'u2',
|
|
104
|
+
uP: "u'",
|
|
105
|
+
Dw: 'Dw',
|
|
106
|
+
Dw2: 'Dw2',
|
|
107
|
+
DwP: "Dw'",
|
|
108
|
+
d: 'd',
|
|
109
|
+
d2: 'd2',
|
|
110
|
+
dP: "d'",
|
|
111
|
+
}),
|
|
112
|
+
Two: Object.freeze({
|
|
113
|
+
Rw: '2Rw',
|
|
114
|
+
Rw2: '2Rw2',
|
|
115
|
+
RwP: "2Rw'",
|
|
116
|
+
r: '2r',
|
|
117
|
+
r2: '2r2',
|
|
118
|
+
rP: "2r'",
|
|
119
|
+
R: '2R',
|
|
120
|
+
R2: '2R2',
|
|
121
|
+
RP: "2R'",
|
|
122
|
+
Lw: '2Lw',
|
|
123
|
+
Lw2: '2Lw2',
|
|
124
|
+
LwP: "2Lw'",
|
|
125
|
+
l: '2l',
|
|
126
|
+
l2: '2l2',
|
|
127
|
+
lP: "2l'",
|
|
128
|
+
L: '2L',
|
|
129
|
+
L2: '2L2',
|
|
130
|
+
LP: "2L'",
|
|
131
|
+
Fw: '2Fw',
|
|
132
|
+
Fw2: '2Fw2',
|
|
133
|
+
FwP: "2Fw'",
|
|
134
|
+
f: '2f',
|
|
135
|
+
f2: '2f2',
|
|
136
|
+
fP: "2f'",
|
|
137
|
+
F: '2F',
|
|
138
|
+
F2: '2F2',
|
|
139
|
+
FP: "2F'",
|
|
140
|
+
Bw: '2Bw',
|
|
141
|
+
Bw2: '2Bw2',
|
|
142
|
+
BwP: "2Bw'",
|
|
143
|
+
b: '2b',
|
|
144
|
+
b2: '2b2',
|
|
145
|
+
bP: "2b'",
|
|
146
|
+
B: '2B',
|
|
147
|
+
B2: '2B2',
|
|
148
|
+
BP: "2B'",
|
|
149
|
+
Uw: '2Uw',
|
|
150
|
+
Uw2: '2Uw2',
|
|
151
|
+
UwP: "2Uw'",
|
|
152
|
+
u: '2u',
|
|
153
|
+
u2: '2u2',
|
|
154
|
+
uP: "2u'",
|
|
155
|
+
U: '2U',
|
|
156
|
+
U2: '2U2',
|
|
157
|
+
UP: "2U'",
|
|
158
|
+
Dw: '2Dw',
|
|
159
|
+
Dw2: '2Dw2',
|
|
160
|
+
DwP: "2Dw'",
|
|
161
|
+
d: '2d',
|
|
162
|
+
d2: '2d2',
|
|
163
|
+
dP: "2d'",
|
|
164
|
+
D: '2D',
|
|
165
|
+
D2: '2D2',
|
|
166
|
+
DP: "2D'",
|
|
167
|
+
}),
|
|
168
|
+
Three: Object.freeze({
|
|
169
|
+
Rw: '3Rw',
|
|
170
|
+
Rw2: '3Rw2',
|
|
171
|
+
RwP: "3Rw'",
|
|
172
|
+
r: '3r',
|
|
173
|
+
r2: '3r2',
|
|
174
|
+
rP: "3r'",
|
|
175
|
+
R: '3R',
|
|
176
|
+
R2: '3R2',
|
|
177
|
+
RP: "3R'",
|
|
178
|
+
Lw: '3Lw',
|
|
179
|
+
Lw2: '3Lw2',
|
|
180
|
+
LwP: "3Lw'",
|
|
181
|
+
l: '3l',
|
|
182
|
+
l2: '3l2',
|
|
183
|
+
lP: "3l'",
|
|
184
|
+
L: '3L',
|
|
185
|
+
L2: '3L2',
|
|
186
|
+
LP: "3L'",
|
|
187
|
+
Fw: '3Fw',
|
|
188
|
+
Fw2: '3Fw2',
|
|
189
|
+
FwP: "3Fw'",
|
|
190
|
+
f: '3f',
|
|
191
|
+
f2: '3f2',
|
|
192
|
+
fP: "3f'",
|
|
193
|
+
F: '3F',
|
|
194
|
+
F2: '3F2',
|
|
195
|
+
FP: "3F'",
|
|
196
|
+
Bw: '3Bw',
|
|
197
|
+
Bw2: '3Bw2',
|
|
198
|
+
BwP: "3Bw'",
|
|
199
|
+
b: '3b',
|
|
200
|
+
b2: '3b2',
|
|
201
|
+
bP: "3b'",
|
|
202
|
+
B: '3B',
|
|
203
|
+
B2: '3B2',
|
|
204
|
+
BP: "3B'",
|
|
205
|
+
Uw: '3Uw',
|
|
206
|
+
Uw2: '3Uw2',
|
|
207
|
+
UwP: "3Uw'",
|
|
208
|
+
u: '3u',
|
|
209
|
+
u2: '3u2',
|
|
210
|
+
uP: "3u'",
|
|
211
|
+
U: '3U',
|
|
212
|
+
U2: '3U2',
|
|
213
|
+
UP: "3U'",
|
|
214
|
+
Dw: '3Dw',
|
|
215
|
+
Dw2: '3Dw2',
|
|
216
|
+
DwP: "3Dw'",
|
|
217
|
+
d: '3d',
|
|
218
|
+
d2: '3d2',
|
|
219
|
+
dP: "3d'",
|
|
220
|
+
D: '3D',
|
|
221
|
+
D2: '3D2',
|
|
222
|
+
DP: "3D'",
|
|
223
|
+
}),
|
|
224
|
+
Four: Object.freeze({
|
|
225
|
+
Rw: '4Rw',
|
|
226
|
+
Rw2: '4Rw2',
|
|
227
|
+
RwP: "4Rw'",
|
|
228
|
+
r: '4r',
|
|
229
|
+
r2: '4r2',
|
|
230
|
+
rP: "4r'",
|
|
231
|
+
R: '4R',
|
|
232
|
+
R2: '4R2',
|
|
233
|
+
RP: "4R'",
|
|
234
|
+
Lw: '4Lw',
|
|
235
|
+
Lw2: '4Lw2',
|
|
236
|
+
LwP: "4Lw'",
|
|
237
|
+
l: '4l',
|
|
238
|
+
l2: '4l2',
|
|
239
|
+
lP: "4l'",
|
|
240
|
+
L: '4L',
|
|
241
|
+
L2: '4L2',
|
|
242
|
+
LP: "4L'",
|
|
243
|
+
Fw: '4Fw',
|
|
244
|
+
Fw2: '4Fw2',
|
|
245
|
+
FwP: "4Fw'",
|
|
246
|
+
f: '4f',
|
|
247
|
+
f2: '4f2',
|
|
248
|
+
fP: "4f'",
|
|
249
|
+
F: '4F',
|
|
250
|
+
F2: '4F2',
|
|
251
|
+
FP: "4F'",
|
|
252
|
+
Bw: '4Bw',
|
|
253
|
+
Bw2: '4Bw2',
|
|
254
|
+
BwP: "4Bw'",
|
|
255
|
+
b: '4b',
|
|
256
|
+
b2: '4b2',
|
|
257
|
+
bP: "4b'",
|
|
258
|
+
B: '4B',
|
|
259
|
+
B2: '4B2',
|
|
260
|
+
BP: "4B'",
|
|
261
|
+
Uw: '4Uw',
|
|
262
|
+
Uw2: '4Uw2',
|
|
263
|
+
UwP: "4Uw'",
|
|
264
|
+
u: '4u',
|
|
265
|
+
u2: '4u2',
|
|
266
|
+
uP: "4u'",
|
|
267
|
+
U: '4U',
|
|
268
|
+
U2: '4U2',
|
|
269
|
+
UP: "4U'",
|
|
270
|
+
Dw: '4Dw',
|
|
271
|
+
Dw2: '4Dw2',
|
|
272
|
+
DwP: "4Dw'",
|
|
273
|
+
d: '4d',
|
|
274
|
+
d2: '4d2',
|
|
275
|
+
dP: "4d'",
|
|
276
|
+
D: '4D',
|
|
277
|
+
D2: '4D2',
|
|
278
|
+
DP: "4D'",
|
|
279
|
+
}),
|
|
280
|
+
Five: Object.freeze({
|
|
281
|
+
Rw: '5Rw',
|
|
282
|
+
Rw2: '5Rw2',
|
|
283
|
+
RwP: "5Rw'",
|
|
284
|
+
r: '5r',
|
|
285
|
+
r2: '5r2',
|
|
286
|
+
rP: "5r'",
|
|
287
|
+
R: '5R',
|
|
288
|
+
R2: '5R2',
|
|
289
|
+
RP: "5R'",
|
|
290
|
+
Lw: '5Lw',
|
|
291
|
+
Lw2: '5Lw2',
|
|
292
|
+
LwP: "5Lw'",
|
|
293
|
+
l: '5l',
|
|
294
|
+
l2: '5l2',
|
|
295
|
+
lP: "5l'",
|
|
296
|
+
L: '5L',
|
|
297
|
+
L2: '5L2',
|
|
298
|
+
LP: "5L'",
|
|
299
|
+
Fw: '5Fw',
|
|
300
|
+
Fw2: '5Fw2',
|
|
301
|
+
FwP: "5Fw'",
|
|
302
|
+
f: '5f',
|
|
303
|
+
f2: '5f2',
|
|
304
|
+
fP: "5f'",
|
|
305
|
+
F: '5F',
|
|
306
|
+
F2: '5F2',
|
|
307
|
+
FP: "5F'",
|
|
308
|
+
Bw: '5Bw',
|
|
309
|
+
Bw2: '5Bw2',
|
|
310
|
+
BwP: "5Bw'",
|
|
311
|
+
b: '5b',
|
|
312
|
+
b2: '5b2',
|
|
313
|
+
bP: "5b'",
|
|
314
|
+
B: '5B',
|
|
315
|
+
B2: '5B2',
|
|
316
|
+
BP: "5B'",
|
|
317
|
+
Uw: '5Uw',
|
|
318
|
+
Uw2: '5Uw2',
|
|
319
|
+
UwP: "5Uw'",
|
|
320
|
+
u: '5u',
|
|
321
|
+
u2: '5u2',
|
|
322
|
+
uP: "5u'",
|
|
323
|
+
U: '5U',
|
|
324
|
+
U2: '5U2',
|
|
325
|
+
UP: "5U'",
|
|
326
|
+
Dw: '5Dw',
|
|
327
|
+
Dw2: '5Dw2',
|
|
328
|
+
DwP: "5Dw'",
|
|
329
|
+
d: '5d',
|
|
330
|
+
d2: '5d2',
|
|
331
|
+
dP: "5d'",
|
|
332
|
+
D: '5D',
|
|
333
|
+
D2: '5D2',
|
|
334
|
+
DP: "5D'",
|
|
335
|
+
}),
|
|
336
|
+
Six: Object.freeze({
|
|
337
|
+
Rw: '6Rw',
|
|
338
|
+
Rw2: '6Rw2',
|
|
339
|
+
RwP: "6Rw'",
|
|
340
|
+
r: '6r',
|
|
341
|
+
r2: '6r2',
|
|
342
|
+
rP: "6r'",
|
|
343
|
+
R: '6R',
|
|
344
|
+
R2: '6R2',
|
|
345
|
+
RP: "6R'",
|
|
346
|
+
Lw: '6Lw',
|
|
347
|
+
Lw2: '6Lw2',
|
|
348
|
+
LwP: "6Lw'",
|
|
349
|
+
l: '6l',
|
|
350
|
+
l2: '6l2',
|
|
351
|
+
lP: "6l'",
|
|
352
|
+
L: '6L',
|
|
353
|
+
L2: '6L2',
|
|
354
|
+
LP: "6L'",
|
|
355
|
+
Fw: '6Fw',
|
|
356
|
+
Fw2: '6Fw2',
|
|
357
|
+
FwP: "6Fw'",
|
|
358
|
+
f: '6f',
|
|
359
|
+
f2: '6f2',
|
|
360
|
+
fP: "6f'",
|
|
361
|
+
F: '6F',
|
|
362
|
+
F2: '6F2',
|
|
363
|
+
FP: "6F'",
|
|
364
|
+
Bw: '6Bw',
|
|
365
|
+
Bw2: '6Bw2',
|
|
366
|
+
BwP: "6Bw'",
|
|
367
|
+
b: '6b',
|
|
368
|
+
b2: '6b2',
|
|
369
|
+
bP: "6b'",
|
|
370
|
+
B: '6B',
|
|
371
|
+
B2: '6B2',
|
|
372
|
+
BP: "6B'",
|
|
373
|
+
Uw: '6Uw',
|
|
374
|
+
Uw2: '6Uw2',
|
|
375
|
+
UwP: "6Uw'",
|
|
376
|
+
u: '6u',
|
|
377
|
+
u2: '6u2',
|
|
378
|
+
uP: "6u'",
|
|
379
|
+
U: '6U',
|
|
380
|
+
U2: '6U2',
|
|
381
|
+
UP: "6U'",
|
|
382
|
+
Dw: '6Dw',
|
|
383
|
+
Dw2: '6Dw2',
|
|
384
|
+
DwP: "6Dw'",
|
|
385
|
+
d: '6d',
|
|
386
|
+
d2: '6d2',
|
|
387
|
+
dP: "6d'",
|
|
388
|
+
D: '6D',
|
|
389
|
+
D2: '6D2',
|
|
390
|
+
DP: "6D'",
|
|
391
|
+
}),
|
|
392
|
+
/**
|
|
393
|
+
* Build a layer-range move for big-cube notation. e.g. Movements.Range(2, 4, Movements.Wide.Rw) returns '2-4Rw',
|
|
394
|
+
* meaning "rotate layers 2 through 4 from the right face." Accepts wide moves (`Movements.Wide.*`), face
|
|
395
|
+
* moves (`Movements.Single.{R,L,U,D,F,B}` and modifiers), and slice moves (`Movements.Single.{M,E,S}` and
|
|
396
|
+
* modifiers). Already-prefixed moves (`2R`, `2-4Rw`) are rejected.
|
|
397
|
+
* @param {number} lower
|
|
398
|
+
* @param {number} upper
|
|
399
|
+
* @param {WideMove | SingleMove} baseMove
|
|
400
|
+
* @returns {Movement}
|
|
401
|
+
*/
|
|
402
|
+
Range: (lower, upper, baseMove) => {
|
|
403
|
+
if (!Number.isInteger(lower) || !Number.isInteger(upper) || lower < 1 || lower >= upper || upper > 7) {
|
|
404
|
+
throw new Error(`Invalid layer range [${lower}-${upper}]: require integers with 1 <= lower < upper <= 7`);
|
|
405
|
+
}
|
|
406
|
+
const move = /** @type {Movement} */ (`${lower}-${upper}${baseMove}`);
|
|
407
|
+
if (!isMovement(move)) {
|
|
408
|
+
throw new Error(`Invalid range movement: ${move}`);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return move;
|
|
412
|
+
},
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* @typedef {typeof Rotations[keyof typeof Rotations]} Rotation
|
|
417
|
+
*/
|
|
418
|
+
export const Rotations = Object.freeze({
|
|
419
|
+
x: 'x',
|
|
420
|
+
x2: 'x2',
|
|
421
|
+
xP: "x'",
|
|
422
|
+
y: 'y',
|
|
423
|
+
y2: 'y2',
|
|
424
|
+
yP: "y'",
|
|
425
|
+
z: 'z',
|
|
426
|
+
z2: 'z2',
|
|
427
|
+
zP: "z'",
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* @typedef {typeof Faces [keyof typeof Faces]} Face
|
|
432
|
+
*/
|
|
433
|
+
export const Faces = Object.freeze({
|
|
434
|
+
U: 'U',
|
|
435
|
+
D: 'D',
|
|
436
|
+
L: 'L',
|
|
437
|
+
R: 'R',
|
|
438
|
+
F: 'F',
|
|
439
|
+
B: 'B',
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* @typedef {typeof CubeTypes [keyof typeof CubeTypes]} CubeType
|
|
444
|
+
*/
|
|
445
|
+
export const CubeTypes = Object.freeze({
|
|
446
|
+
Two: 'Two',
|
|
447
|
+
Three: 'Three',
|
|
448
|
+
Four: 'Four',
|
|
449
|
+
Five: 'Five',
|
|
450
|
+
Six: 'Six',
|
|
451
|
+
Seven: 'Seven',
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
export const LayerCount = Object.freeze({
|
|
455
|
+
[CubeTypes.Two]: 2,
|
|
456
|
+
[CubeTypes.Three]: 3,
|
|
457
|
+
[CubeTypes.Four]: 4,
|
|
458
|
+
[CubeTypes.Five]: 5,
|
|
459
|
+
[CubeTypes.Six]: 6,
|
|
460
|
+
[CubeTypes.Seven]: 7,
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
*
|
|
465
|
+
* @param {string} rotation
|
|
466
|
+
*/
|
|
467
|
+
export function IsRotation(rotation) {
|
|
468
|
+
return /^([xyz])(\d)?(\')?$/.test(rotation);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
*
|
|
473
|
+
* @param {string} movement
|
|
474
|
+
* @return {boolean}
|
|
475
|
+
*/
|
|
476
|
+
export function isMovement(movement) {
|
|
477
|
+
return /^([1234567]|[123456]-[1234567])?([RLUDFB]w|[RLUDFBMES]|[rludfbmes])([123])?(\')?$/.test(movement);
|
|
478
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/** @import {Slice} from '../state/slice' */
|
|
3
|
+
/** @import {StickerState} from '../state/stickerState' */
|
|
4
|
+
/** @import {CubeType, Movement, Rotation} from '../core' */
|
|
5
|
+
/**
|
|
6
|
+
* @typedef AnimationOptions
|
|
7
|
+
* @property {boolean} [translate]
|
|
8
|
+
* @property {number} [animationSpeedMs]
|
|
9
|
+
* @property {boolean} [reverse]
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {Object} RubiksCubeViewInterface
|
|
13
|
+
* @property {function(Slice, any=): Promise<void>} slice
|
|
14
|
+
* @property {function(StickerState): void} setState
|
|
15
|
+
* @property {function(): void} reset
|
|
16
|
+
* @property {function(CubeType): void} setType
|
|
17
|
+
**/
|
|
18
|
+
|
|
19
|
+
import { CubeTypes } from '../core';
|
|
20
|
+
import { RubiksCubeState } from '../state';
|
|
21
|
+
import { fromKociemba, toKociemba } from '../state/stickerState';
|
|
22
|
+
|
|
23
|
+
export default class RubiksCubeController {
|
|
24
|
+
/**
|
|
25
|
+
* @param {CubeType} cubeType
|
|
26
|
+
* @param {RubiksCubeViewInterface} view
|
|
27
|
+
* */
|
|
28
|
+
constructor(cubeType, view) {
|
|
29
|
+
this.state = new RubiksCubeState(cubeType);
|
|
30
|
+
this.view = view;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* @param {Movement} movement
|
|
34
|
+
* @param {AnimationOptions} [options]
|
|
35
|
+
* @returns {Promise<string>}
|
|
36
|
+
*/
|
|
37
|
+
movement(movement, options) {
|
|
38
|
+
const slice = this.state.move(movement, { reverse: options?.reverse, translate: options?.translate });
|
|
39
|
+
if (slice == null) {
|
|
40
|
+
return Promise.reject(new Error(`Invalid movement: ${movement}`));
|
|
41
|
+
}
|
|
42
|
+
return this.view.slice(slice, { animationSpeedMs: options?.animationSpeedMs }).then(() => toKociemba(this.state.getState()));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @param {Rotation} rotation
|
|
47
|
+
* @param {AnimationOptions} [options]
|
|
48
|
+
* @returns {Promise<string>}
|
|
49
|
+
*/
|
|
50
|
+
rotation(rotation, options) {
|
|
51
|
+
const slice = this.state.rotate(rotation, { reverse: options?.reverse });
|
|
52
|
+
if (slice == null) {
|
|
53
|
+
return Promise.reject(new Error(`Invalid rotation: ${rotation}`));
|
|
54
|
+
}
|
|
55
|
+
return this.view.slice(slice, { animationSpeedMs: options?.animationSpeedMs }).then(() => toKociemba(this.state.getState()));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @param {(Rotation | Movement)[]} actions
|
|
60
|
+
* @param {AnimationOptions} [options]
|
|
61
|
+
* @returns {string}
|
|
62
|
+
*/
|
|
63
|
+
do(actions, options) {
|
|
64
|
+
this.state.do(actions, { translate: options?.translate, reverse: options?.reverse });
|
|
65
|
+
this.view.setState(this.state.getState());
|
|
66
|
+
return toKociemba(this.state.getState());
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @returns {string}
|
|
71
|
+
*/
|
|
72
|
+
reset() {
|
|
73
|
+
this.state.reset();
|
|
74
|
+
this.view.reset();
|
|
75
|
+
return toKociemba(this.state.getState());
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @param {string} kociembaState
|
|
80
|
+
* @returns {boolean}
|
|
81
|
+
*/
|
|
82
|
+
setState(kociembaState) {
|
|
83
|
+
const state = fromKociemba(kociembaState);
|
|
84
|
+
if (state) {
|
|
85
|
+
this.state.setState(state);
|
|
86
|
+
this.view.setState(state);
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @returns {string}
|
|
94
|
+
*/
|
|
95
|
+
getState() {
|
|
96
|
+
return toKociemba(this.state.getState());
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @param {CubeType} cubeType
|
|
101
|
+
* @returns {string}
|
|
102
|
+
*/
|
|
103
|
+
setType(cubeType) {
|
|
104
|
+
if (!Object.values(CubeTypes).includes(cubeType)) {
|
|
105
|
+
throw new Error(`Invalid cube type: ${cubeType}`);
|
|
106
|
+
}
|
|
107
|
+
this.state = new RubiksCubeState(cubeType);
|
|
108
|
+
this.view.setType(cubeType);
|
|
109
|
+
return toKociemba(this.state.getState());
|
|
110
|
+
}
|
|
111
|
+
}
|