@houstonp/rubiks-cube 2.1.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.
Files changed (76) hide show
  1. package/README.md +304 -77
  2. package/package.json +18 -8
  3. package/src/{core.js → core/index.js} +72 -41
  4. package/src/rubiksCube/index.js +3 -0
  5. package/src/rubiksCube/rubiksCubeController.js +111 -0
  6. package/src/{three → rubiksCube3D}/centerPiece.js +37 -2
  7. package/src/{three → rubiksCube3D}/cornerPiece.js +56 -2
  8. package/src/rubiksCube3D/cubeConfig.js +87 -0
  9. package/src/rubiksCube3D/cubeSettings.js +30 -0
  10. package/src/{three → rubiksCube3D}/edgePiece.js +2 -1
  11. package/src/rubiksCube3D/index.js +3 -0
  12. package/src/rubiksCube3D/rubiksCube3D.js +383 -0
  13. package/src/{three → rubiksCube3D}/sticker.js +5 -4
  14. package/src/state/index.js +4 -0
  15. package/src/state/rubiksCubeState.js +471 -0
  16. package/src/state/slice.js +236 -0
  17. package/src/state/stickerState.js +185 -0
  18. package/src/{camera → webComponent}/cameraState.js +17 -25
  19. package/src/webComponent/constants.js +67 -0
  20. package/src/webComponent/index.js +7 -0
  21. package/src/webComponent/rubiksCubeElement.js +379 -0
  22. package/src/{settings.js → webComponent/settings.js} +36 -23
  23. package/tests/common.js +3 -20
  24. package/tests/core.test.js +56 -0
  25. package/tests/rubiksCube.solves.test.js +41 -0
  26. package/tests/rubiksCube3D.solves.test.js +185 -0
  27. package/tests/rubiksCubeState.solves.test.js +35 -0
  28. package/tests/testScrambles.js +194 -0
  29. package/types/{core.d.ts → core/index.d.ts} +45 -48
  30. package/types/rubiksCube/index.d.ts +3 -0
  31. package/types/rubiksCube/rubiksCubeController.d.ts +62 -0
  32. package/types/rubiksCube3D/centerPiece.d.ts +27 -0
  33. package/types/rubiksCube3D/cornerPiece.d.ts +38 -0
  34. package/types/rubiksCube3D/cubeConfig.d.ts +32 -0
  35. package/types/rubiksCube3D/cubeSettings.d.ts +33 -0
  36. package/types/{three → rubiksCube3D}/edgePiece.d.ts +5 -3
  37. package/types/rubiksCube3D/index.d.ts +3 -0
  38. package/types/rubiksCube3D/rubiksCube3D.d.ts +120 -0
  39. package/types/rubiksCube3D/sticker.d.ts +18 -0
  40. package/types/state/index.d.ts +5 -0
  41. package/types/state/rubiksCubeState.d.ts +108 -0
  42. package/types/state/slice.d.ts +46 -0
  43. package/types/state/stickerState.d.ts +34 -0
  44. package/types/webComponent/cameraState.d.ts +22 -0
  45. package/types/webComponent/constants.d.ts +57 -0
  46. package/types/webComponent/index.d.ts +6 -0
  47. package/types/webComponent/rubiksCubeElement.d.ts +89 -0
  48. package/types/{settings.d.ts → webComponent/settings.d.ts} +5 -8
  49. package/src/cube/animationSlice.js +0 -205
  50. package/src/cube/animationState.js +0 -96
  51. package/src/cube/cubeSettings.js +0 -19
  52. package/src/cube/cubeState.js +0 -337
  53. package/src/cube/stickerState.js +0 -188
  54. package/src/index.js +0 -621
  55. package/src/three/cube.js +0 -492
  56. package/tests/cube.five.test.js +0 -126
  57. package/tests/cube.four.test.js +0 -126
  58. package/tests/cube.seven.test.js +0 -126
  59. package/tests/cube.six.test.js +0 -126
  60. package/tests/cube.three.test.js +0 -151
  61. package/tests/cube.two.test.js +0 -125
  62. package/types/camera/cameraState.d.ts +0 -19
  63. package/types/cube/animationSlice.d.ts +0 -26
  64. package/types/cube/animationState.d.ts +0 -41
  65. package/types/cube/cubeSettings.d.ts +0 -17
  66. package/types/cube/cubeState.d.ts +0 -47
  67. package/types/cube/stickerState.d.ts +0 -21
  68. package/types/index.d.ts +0 -87
  69. package/types/three/centerPiece.d.ts +0 -15
  70. package/types/three/cornerPiece.d.ts +0 -24
  71. package/types/three/cube.d.ts +0 -130
  72. package/types/three/sticker.d.ts +0 -15
  73. /package/src/{debouncer.js → webComponent/debouncer.js} +0 -0
  74. /package/src/{globals.ts → webComponent/globals.ts} +0 -0
  75. /package/types/{debouncer.d.ts → webComponent/debouncer.d.ts} +0 -0
  76. /package/types/{globals.d.ts → webComponent/globals.d.ts} +0 -0
@@ -1,337 +0,0 @@
1
- // @ts-check
2
- /**
3
- * @typedef {{x: number,y: number,z: number}} vector
4
- */
5
-
6
- import { CubeTypes, Faces } from '../core';
7
- import { defaultStickerState } from './stickerState';
8
-
9
- /** @typedef {{cubeType: import('../core').CubeType, layers: number[], pieceSize: number, coreSize: number,initialStickerState: import('./stickerState').StickerState, outerLayerMultiplier: number, corners: state[], edges: state[], centers: state[]}} CubeInfo */
10
- /**
11
- * @param {import("../core").CubeType} cubeType
12
- * @return {CubeInfo}
13
- */
14
- export function getCubeInfo(cubeType) {
15
- return {
16
- cubeType: cubeType,
17
- layers: getMiddleLayers(cubeType),
18
- pieceSize: pieceSize(cubeType),
19
- coreSize: coreSize(cubeType),
20
- initialStickerState: defaultStickerState(cubeType),
21
- outerLayerMultiplier: outlerLayerMultiplier(cubeType),
22
- corners: corners,
23
- edges: edges(getMiddleLayers(cubeType)),
24
- centers: centers(getMiddleLayers(cubeType)),
25
- };
26
- }
27
-
28
- export const FaceColors = {
29
- [Faces.B]: 'blue',
30
- [Faces.D]: 'yellow',
31
- [Faces.F]: '#2cbf13',
32
- [Faces.L]: '#fc9a05',
33
- [Faces.R]: 'red',
34
- [Faces.U]: 'white',
35
- };
36
-
37
- /**
38
- * @param {import('three').ColorRepresentation} color
39
- * @return {import('../core').Face}
40
- * */
41
- export const ColorToFace = (color) => {
42
- const face = Object.values(Faces).find((face) => FaceColors[face] === color);
43
- if (!face) {
44
- throw new Error(`Invalid color: ${color}`);
45
- }
46
- return face;
47
- };
48
-
49
- /**
50
- * @param {import("../core").CubeType} cubeType
51
- * @return {number} core size
52
- */
53
- export const outlerLayerMultiplier = (cubeType) => {
54
- switch (cubeType) {
55
- case CubeTypes.Two:
56
- return 1;
57
- case CubeTypes.Three:
58
- return 1;
59
- case CubeTypes.Four:
60
- return 1.1;
61
- case CubeTypes.Five:
62
- return 1.2;
63
- case CubeTypes.Six:
64
- return 1.3;
65
- case CubeTypes.Seven:
66
- return 1.35;
67
- default:
68
- throw new Error(`Unsupported cube type: ${cubeType}`);
69
- }
70
- };
71
-
72
- /**
73
- * @param {import("../core").CubeType} cubeType
74
- * @return {number} core size
75
- */
76
- export const coreSize = (cubeType) => {
77
- switch (cubeType) {
78
- case CubeTypes.Two:
79
- return 2;
80
- case CubeTypes.Three:
81
- return 1.53;
82
- case CubeTypes.Four:
83
- return 1.36;
84
- case CubeTypes.Five:
85
- return 1.3;
86
- case CubeTypes.Six:
87
- return 1.22;
88
- case CubeTypes.Seven:
89
- return 1.21;
90
- default:
91
- throw new Error(`Unsupported cube type: ${cubeType}`);
92
- }
93
- };
94
-
95
- /**
96
- * @param {import("../core").CubeType} cubeType
97
- */
98
- export const getMiddleLayers = (cubeType) => {
99
- switch (cubeType) {
100
- case CubeTypes.Two:
101
- return [];
102
- case CubeTypes.Three:
103
- return [0];
104
- case CubeTypes.Four:
105
- return [-1 / 3, 1 / 3];
106
- case CubeTypes.Five:
107
- return [-1 / 2, 0, 1 / 2];
108
- case CubeTypes.Six:
109
- return [-3 / 5, -1 / 5, 1 / 5, 3 / 5];
110
- case CubeTypes.Seven:
111
- return [-2 / 3, -1 / 3, 0, 1 / 3, 2 / 3];
112
- default:
113
- throw new Error(`Unsupported cube type: ${cubeType}`);
114
- }
115
- };
116
-
117
- /**
118
- * @param {import("../core").CubeType} cubeType
119
- */
120
- export const getAllLayers = (cubeType) => {
121
- return [-1, ...getMiddleLayers(cubeType), 1];
122
- };
123
-
124
- /**
125
- * @param {import("../core").CubeType} cubeType
126
- * @return {number} piece size
127
- */
128
- export const pieceSize = (cubeType) => {
129
- switch (cubeType) {
130
- case CubeTypes.Two:
131
- return 2;
132
- case CubeTypes.Three:
133
- return 1;
134
- case CubeTypes.Four:
135
- return 2 / 3;
136
- case CubeTypes.Five:
137
- return 1 / 2;
138
- case CubeTypes.Six:
139
- return 2 / 5;
140
- case CubeTypes.Seven:
141
- return 1 / 3;
142
- default:
143
- throw new Error(`Unsupported cube type: ${cubeType}`);
144
- }
145
- };
146
-
147
- /**
148
- * @typedef {{position: vector, rotation: vector}} state
149
- */
150
-
151
- /** @type {state[]} */
152
- export const corners = [
153
- {
154
- position: { x: 1, y: 1, z: 1 },
155
- rotation: { x: 0, y: 0, z: 0 },
156
- },
157
- {
158
- position: { x: 1, y: 1, z: -1 },
159
- rotation: { x: 0, y: Math.PI / 2, z: 0 },
160
- },
161
- {
162
- position: { x: 1, y: -1, z: 1 },
163
- rotation: { x: 0, y: Math.PI / 2, z: Math.PI },
164
- },
165
- {
166
- position: { x: 1, y: -1, z: -1 },
167
- rotation: { x: 0, y: Math.PI, z: Math.PI },
168
- },
169
- {
170
- position: { x: -1, y: 1, z: 1 },
171
- rotation: { x: 0, y: -Math.PI / 2, z: 0 },
172
- },
173
- {
174
- position: { x: -1, y: 1, z: -1 },
175
- rotation: { x: 0, y: Math.PI, z: 0 },
176
- },
177
- {
178
- position: { x: -1, y: -1, z: 1 },
179
- rotation: { x: 0, y: 0, z: Math.PI },
180
- },
181
- {
182
- position: { x: -1, y: -1, z: -1 },
183
- rotation: { x: 0, y: -Math.PI / 2, z: Math.PI },
184
- },
185
- ];
186
-
187
- /**
188
- * @param {number[]} layers
189
- * @return {state[]}
190
- */
191
- export const centers = (layers) => [
192
- //right
193
- ...layers.flatMap((layer1) =>
194
- layers.map((layer2) => {
195
- return {
196
- position: { x: 1, y: layer1, z: layer2 },
197
- rotation: { x: 0, y: Math.PI / 2, z: 0 },
198
- };
199
- }),
200
- ),
201
- //up
202
- ...layers.flatMap((layer1) =>
203
- layers.map((layer2) => {
204
- return {
205
- position: { x: layer1, y: 1, z: layer2 },
206
- rotation: { x: -Math.PI / 2, y: 0, z: 0 },
207
- };
208
- }),
209
- ),
210
- //front
211
- ...layers.flatMap((layer1) =>
212
- layers.map((layer2) => {
213
- return {
214
- position: { x: layer1, y: layer2, z: 1 },
215
- rotation: { x: 0, y: 0, z: 0 },
216
- };
217
- }),
218
- ),
219
- //back
220
- ...layers.flatMap((layer1) =>
221
- layers.map((layer2) => {
222
- return {
223
- position: { x: layer1, y: layer2, z: -1 },
224
- rotation: { x: 0, y: Math.PI, z: 0 },
225
- };
226
- }),
227
- ),
228
- //down
229
- ...layers.flatMap((layer1) =>
230
- layers.map((layer2) => {
231
- return {
232
- position: { x: layer1, y: -1, z: layer2 },
233
- rotation: { x: Math.PI / 2, y: 0, z: 0 },
234
- };
235
- }),
236
- ),
237
- //left
238
- ...layers.flatMap((layer1) =>
239
- layers.map((layer2) => {
240
- return {
241
- position: { x: -1, y: layer1, z: layer2 },
242
- rotation: { x: 0, y: -Math.PI / 2, z: 0 },
243
- };
244
- }),
245
- ),
246
- ];
247
-
248
- /**
249
- * @param {number[]} layers
250
- * @return {state[]}
251
- */
252
- export const edges = (layers) => [
253
- // RU
254
- ...layers.map((layer) => {
255
- return {
256
- position: { x: 1, y: 1, z: layer },
257
- rotation: { x: 0, y: Math.PI / 2, z: 0 },
258
- };
259
- }),
260
- // RF
261
- ...layers.map((layer) => {
262
- return {
263
- position: { x: 1, y: layer, z: 1 },
264
- rotation: { x: 0, y: 0, z: -Math.PI / 2 },
265
- };
266
- }),
267
- // RB
268
- ...layers.map((layer) => {
269
- return {
270
- position: { x: 1, y: layer, z: -1 },
271
- rotation: { x: 0, y: Math.PI / 2, z: -Math.PI / 2 },
272
- };
273
- }),
274
- // RD
275
- ...layers.map((layer) => {
276
- return {
277
- position: { x: 1, y: -1, z: layer },
278
- rotation: { x: Math.PI, y: Math.PI / 2, z: 0 },
279
- };
280
- }),
281
- // UF
282
- ...layers.map((layer) => {
283
- return {
284
- position: { x: layer, y: 1, z: 1 },
285
- rotation: { x: 0, y: 0, z: 0 },
286
- };
287
- }),
288
- // UB
289
- ...layers.map((layer) => {
290
- return {
291
- position: { x: layer, y: 1, z: -1 },
292
- rotation: { x: -Math.PI / 2, y: 0, z: 0 },
293
- };
294
- }),
295
- // DF
296
- ...layers.map((layer) => {
297
- return {
298
- position: { x: layer, y: -1, z: 1 },
299
- rotation: { x: Math.PI / 2, y: 0, z: 0 },
300
- };
301
- }),
302
- // DB
303
- ...layers.map((layer) => {
304
- return {
305
- position: { x: layer, y: -1, z: -1 },
306
- rotation: { x: Math.PI, y: 0, z: 0 },
307
- };
308
- }),
309
- // LU
310
- ...layers.map((layer) => {
311
- return {
312
- position: { x: -1, y: 1, z: layer },
313
- rotation: { x: 0, y: -Math.PI / 2, z: 0 },
314
- };
315
- }),
316
- // LF
317
- ...layers.map((layer) => {
318
- return {
319
- position: { x: -1, y: layer, z: 1 },
320
- rotation: { x: 0, y: 0, z: Math.PI / 2 },
321
- };
322
- }),
323
- // LB
324
- ...layers.map((layer) => {
325
- return {
326
- position: { x: -1, y: layer, z: -1 },
327
- rotation: { x: 0, y: -Math.PI / 2, z: Math.PI / 2 },
328
- };
329
- }),
330
- // LD
331
- ...layers.map((layer) => {
332
- return {
333
- position: { x: -1, y: -1, z: layer },
334
- rotation: { x: 0, y: -Math.PI / 2, z: Math.PI },
335
- };
336
- }),
337
- ];
@@ -1,188 +0,0 @@
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
- }