Spaces:
Running
Running
Upload 8 files
Browse files- README.md +23 -10
- app.js +1371 -0
- index.html +708 -19
- json/coll.json.js +424 -0
- json/f2l.json.js +409 -0
- json/oll.json.js +633 -0
- json/pll.json.js +248 -0
- json/zbll.json.js +0 -0
README.md
CHANGED
|
@@ -1,10 +1,23 @@
|
|
| 1 |
-
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
-
sdk: static
|
| 7 |
-
pinned: false
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: One-Handed 3x3 Rubik's Cube
|
| 3 |
+
emoji: 🧊
|
| 4 |
+
colorFrom: indigo
|
| 5 |
+
colorTo: pink
|
| 6 |
+
sdk: static
|
| 7 |
+
pinned: false
|
| 8 |
+
license: mit
|
| 9 |
+
---
|
| 10 |
+
|
| 11 |
+
# One-Handed 3x3 Rubik's Cube
|
| 12 |
+
|
| 13 |
+
Interactive 3D visualization and one-handed (OH) algorithm reference for speedcubing.
|
| 14 |
+
|
| 15 |
+
## Features
|
| 16 |
+
|
| 17 |
+
- 3D interactive Rubik's Cube (Three.js)
|
| 18 |
+
- OH-optimized algorithms for F2L, OLL, PLL, COLL, and ZBLL
|
| 19 |
+
- Click any algorithm to see it solve the case on the cube
|
| 20 |
+
- Step-by-step mode: advance one move at a time
|
| 21 |
+
- Keyboard shortcuts for moves and step navigation
|
| 22 |
+
|
| 23 |
+
Created by Andy Kong
|
app.js
ADDED
|
@@ -0,0 +1,1371 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// ============================================================
|
| 2 |
+
// 3D Rubik's Cube Visualization & OH Algorithm Player
|
| 3 |
+
// Built with Three.js
|
| 4 |
+
// ============================================================
|
| 5 |
+
|
| 6 |
+
let scene, camera, renderer, controls;
|
| 7 |
+
let cubeGroup;
|
| 8 |
+
let cubies = [];
|
| 9 |
+
let isAnimating = false;
|
| 10 |
+
let moveQueue = [];
|
| 11 |
+
|
| 12 |
+
// Colors: White, Yellow, Red, Orange, Blue, Green (as CSS strings for canvas)
|
| 13 |
+
const FACE_COLORS = {
|
| 14 |
+
U: '#ffdd00', // Yellow - top
|
| 15 |
+
D: '#ffffff', // White - bottom
|
| 16 |
+
R: '#ee0000', // Red - right
|
| 17 |
+
L: '#ff8800', // Orange - left
|
| 18 |
+
F: '#0051ff', // Blue - front
|
| 19 |
+
B: '#00aa33', // Green - back
|
| 20 |
+
X: '#1a1a1a' // Black - internal
|
| 21 |
+
};
|
| 22 |
+
|
| 23 |
+
const GAP = 1.02; // Gap between cubies
|
| 24 |
+
|
| 25 |
+
// ============ INITIALIZATION ============
|
| 26 |
+
|
| 27 |
+
function init() {
|
| 28 |
+
const canvas = document.getElementById('cube-canvas');
|
| 29 |
+
const container = canvas.parentElement;
|
| 30 |
+
|
| 31 |
+
scene = new THREE.Scene();
|
| 32 |
+
scene.background = new THREE.Color(0x141425);
|
| 33 |
+
|
| 34 |
+
camera = new THREE.PerspectiveCamera(40, container.clientWidth / 400, 0.1, 100);
|
| 35 |
+
camera.position.set(5.5, 4.2, 5.5);
|
| 36 |
+
|
| 37 |
+
renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true });
|
| 38 |
+
renderer.setSize(container.clientWidth, 400);
|
| 39 |
+
renderer.setPixelRatio(window.devicePixelRatio);
|
| 40 |
+
|
| 41 |
+
// Lighting - use Phong materials so we just need decent lighting
|
| 42 |
+
const ambientLight = new THREE.AmbientLight(0xffffff, 0.7);
|
| 43 |
+
scene.add(ambientLight);
|
| 44 |
+
|
| 45 |
+
const mainLight = new THREE.DirectionalLight(0xffffff, 0.6);
|
| 46 |
+
mainLight.position.set(5, 10, 7);
|
| 47 |
+
scene.add(mainLight);
|
| 48 |
+
|
| 49 |
+
const fillLight = new THREE.DirectionalLight(0xffffff, 0.3);
|
| 50 |
+
fillLight.position.set(-5, 0, -5);
|
| 51 |
+
scene.add(fillLight);
|
| 52 |
+
|
| 53 |
+
// Orbit controls
|
| 54 |
+
controls = new THREE.OrbitControls(camera, renderer.domElement);
|
| 55 |
+
controls.enableDamping = true;
|
| 56 |
+
controls.dampingFactor = 0.08;
|
| 57 |
+
controls.minDistance = 4;
|
| 58 |
+
controls.maxDistance = 14;
|
| 59 |
+
controls.enablePan = false;
|
| 60 |
+
|
| 61 |
+
// Create cube
|
| 62 |
+
createCube();
|
| 63 |
+
|
| 64 |
+
// Handle resize
|
| 65 |
+
window.addEventListener('resize', onResize);
|
| 66 |
+
|
| 67 |
+
// Start render loop
|
| 68 |
+
animate();
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
function onResize() {
|
| 72 |
+
const container = document.getElementById('cube-canvas').parentElement;
|
| 73 |
+
camera.aspect = container.clientWidth / 400;
|
| 74 |
+
camera.updateProjectionMatrix();
|
| 75 |
+
renderer.setSize(container.clientWidth, 400);
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
// ============ CANVAS TEXTURE STICKER ============
|
| 79 |
+
|
| 80 |
+
// Creates a texture with a rounded-corner sticker on a black background
|
| 81 |
+
function createStickerTexture(color) {
|
| 82 |
+
const size = 256;
|
| 83 |
+
const canvas2d = document.createElement('canvas');
|
| 84 |
+
canvas2d.width = size;
|
| 85 |
+
canvas2d.height = size;
|
| 86 |
+
const ctx = canvas2d.getContext('2d');
|
| 87 |
+
|
| 88 |
+
// Black background (the gap / body color)
|
| 89 |
+
ctx.fillStyle = '#111111';
|
| 90 |
+
ctx.fillRect(0, 0, size, size);
|
| 91 |
+
|
| 92 |
+
// Draw rounded rectangle sticker
|
| 93 |
+
const padding = 20; // border around sticker
|
| 94 |
+
const radius = 28; // corner radius
|
| 95 |
+
const x = padding;
|
| 96 |
+
const y = padding;
|
| 97 |
+
const w = size - padding * 2;
|
| 98 |
+
const h = size - padding * 2;
|
| 99 |
+
|
| 100 |
+
ctx.beginPath();
|
| 101 |
+
ctx.moveTo(x + radius, y);
|
| 102 |
+
ctx.lineTo(x + w - radius, y);
|
| 103 |
+
ctx.quadraticCurveTo(x + w, y, x + w, y + radius);
|
| 104 |
+
ctx.lineTo(x + w, y + h - radius);
|
| 105 |
+
ctx.quadraticCurveTo(x + w, y + h, x + w - radius, y + h);
|
| 106 |
+
ctx.lineTo(x + radius, y + h);
|
| 107 |
+
ctx.quadraticCurveTo(x, y + h, x, y + h - radius);
|
| 108 |
+
ctx.lineTo(x, y + radius);
|
| 109 |
+
ctx.quadraticCurveTo(x, y, x + radius, y);
|
| 110 |
+
ctx.closePath();
|
| 111 |
+
|
| 112 |
+
ctx.fillStyle = color;
|
| 113 |
+
ctx.fill();
|
| 114 |
+
|
| 115 |
+
// Subtle highlight gradient on sticker for depth
|
| 116 |
+
const grad = ctx.createLinearGradient(x, y, x, y + h);
|
| 117 |
+
grad.addColorStop(0, 'rgba(255,255,255,0.15)');
|
| 118 |
+
grad.addColorStop(0.5, 'rgba(255,255,255,0)');
|
| 119 |
+
grad.addColorStop(1, 'rgba(0,0,0,0.1)');
|
| 120 |
+
ctx.fillStyle = grad;
|
| 121 |
+
ctx.fill();
|
| 122 |
+
|
| 123 |
+
const texture = new THREE.CanvasTexture(canvas2d);
|
| 124 |
+
texture.needsUpdate = true;
|
| 125 |
+
return texture;
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
// Black face texture (for internal faces with no sticker)
|
| 129 |
+
function createBlackTexture() {
|
| 130 |
+
const size = 64;
|
| 131 |
+
const canvas2d = document.createElement('canvas');
|
| 132 |
+
canvas2d.width = size;
|
| 133 |
+
canvas2d.height = size;
|
| 134 |
+
const ctx = canvas2d.getContext('2d');
|
| 135 |
+
ctx.fillStyle = '#111111';
|
| 136 |
+
ctx.fillRect(0, 0, size, size);
|
| 137 |
+
const texture = new THREE.CanvasTexture(canvas2d);
|
| 138 |
+
texture.needsUpdate = true;
|
| 139 |
+
return texture;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
// Cache textures
|
| 143 |
+
const textureCache = {};
|
| 144 |
+
function getStickerTexture(colorKey) {
|
| 145 |
+
if (!textureCache[colorKey]) {
|
| 146 |
+
if (colorKey === 'X') {
|
| 147 |
+
textureCache[colorKey] = createBlackTexture();
|
| 148 |
+
} else {
|
| 149 |
+
textureCache[colorKey] = createStickerTexture(FACE_COLORS[colorKey]);
|
| 150 |
+
}
|
| 151 |
+
}
|
| 152 |
+
return textureCache[colorKey];
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
// ============ CUBE CREATION ============
|
| 156 |
+
|
| 157 |
+
function createCubie(x, y, z) {
|
| 158 |
+
const size = 0.97;
|
| 159 |
+
const geometry = new THREE.BoxGeometry(size, size, size);
|
| 160 |
+
|
| 161 |
+
// Determine which color each face gets
|
| 162 |
+
// Three.js box face order: +X, -X, +Y, -Y, +Z, -Z
|
| 163 |
+
const faceColors = [
|
| 164 |
+
x === 1 ? 'R' : 'X', // +X Right
|
| 165 |
+
x === -1 ? 'L' : 'X', // -X Left
|
| 166 |
+
y === 1 ? 'U' : 'X', // +Y Up
|
| 167 |
+
y === -1 ? 'D' : 'X', // -Y Down
|
| 168 |
+
z === 1 ? 'F' : 'X', // +Z Front
|
| 169 |
+
z === -1 ? 'B' : 'X', // -Z Back
|
| 170 |
+
];
|
| 171 |
+
|
| 172 |
+
const materials = faceColors.map(key => {
|
| 173 |
+
return new THREE.MeshPhongMaterial({
|
| 174 |
+
map: getStickerTexture(key),
|
| 175 |
+
specular: 0x222222,
|
| 176 |
+
shininess: 30
|
| 177 |
+
});
|
| 178 |
+
});
|
| 179 |
+
|
| 180 |
+
const cubie = new THREE.Mesh(geometry, materials);
|
| 181 |
+
cubie.position.set(x * GAP, y * GAP, z * GAP);
|
| 182 |
+
cubie.userData = { x, y, z };
|
| 183 |
+
|
| 184 |
+
return cubie;
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
function createCube() {
|
| 188 |
+
cubeGroup = new THREE.Group();
|
| 189 |
+
cubies = [];
|
| 190 |
+
|
| 191 |
+
for (let x = -1; x <= 1; x++) {
|
| 192 |
+
for (let y = -1; y <= 1; y++) {
|
| 193 |
+
for (let z = -1; z <= 1; z++) {
|
| 194 |
+
if (x === 0 && y === 0 && z === 0) continue;
|
| 195 |
+
const cubie = createCubie(x, y, z);
|
| 196 |
+
cubies.push(cubie);
|
| 197 |
+
cubeGroup.add(cubie);
|
| 198 |
+
}
|
| 199 |
+
}
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
scene.add(cubeGroup);
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
// ============ ANIMATION LOOP ============
|
| 206 |
+
|
| 207 |
+
function animate() {
|
| 208 |
+
requestAnimationFrame(animate);
|
| 209 |
+
controls.update();
|
| 210 |
+
renderer.render(scene, camera);
|
| 211 |
+
}
|
| 212 |
+
|
| 213 |
+
// ============ MOVE SYSTEM ============
|
| 214 |
+
|
| 215 |
+
// Wide moves = outer layer + middle layer
|
| 216 |
+
// Rotations = entire cube
|
| 217 |
+
// Returns {axis, layers[], angle} for 3D animation
|
| 218 |
+
function get3DMoveDef(moveStr) {
|
| 219 |
+
const PI = Math.PI;
|
| 220 |
+
const H = PI / 2;
|
| 221 |
+
switch(moveStr) {
|
| 222 |
+
// Face moves
|
| 223 |
+
case 'R': return { axis:'x', layers:[1], angle:-H };
|
| 224 |
+
case 'Ri': return { axis:'x', layers:[1], angle:H };
|
| 225 |
+
case 'R2': return { axis:'x', layers:[1], angle:-PI };
|
| 226 |
+
case 'L': return { axis:'x', layers:[-1], angle:H };
|
| 227 |
+
case 'Li': return { axis:'x', layers:[-1], angle:-H };
|
| 228 |
+
case 'L2': return { axis:'x', layers:[-1], angle:PI };
|
| 229 |
+
case 'U': return { axis:'y', layers:[1], angle:-H };
|
| 230 |
+
case 'Ui': return { axis:'y', layers:[1], angle:H };
|
| 231 |
+
case 'U2': return { axis:'y', layers:[1], angle:-PI };
|
| 232 |
+
case 'D': return { axis:'y', layers:[-1], angle:H };
|
| 233 |
+
case 'Di': return { axis:'y', layers:[-1], angle:-H };
|
| 234 |
+
case 'D2': return { axis:'y', layers:[-1], angle:PI };
|
| 235 |
+
case 'F': return { axis:'z', layers:[1], angle:-H };
|
| 236 |
+
case 'Fi': return { axis:'z', layers:[1], angle:H };
|
| 237 |
+
case 'F2': return { axis:'z', layers:[1], angle:-PI };
|
| 238 |
+
case 'B': return { axis:'z', layers:[-1], angle:H };
|
| 239 |
+
case 'Bi': return { axis:'z', layers:[-1], angle:-H };
|
| 240 |
+
case 'B2': return { axis:'z', layers:[-1], angle:PI };
|
| 241 |
+
// Wide moves (2 layers)
|
| 242 |
+
case 'r': return { axis:'x', layers:[1,0], angle:-H };
|
| 243 |
+
case 'ri': return { axis:'x', layers:[1,0], angle:H };
|
| 244 |
+
case 'r2': return { axis:'x', layers:[1,0], angle:-PI };
|
| 245 |
+
case 'l': return { axis:'x', layers:[-1,0], angle:H };
|
| 246 |
+
case 'li': return { axis:'x', layers:[-1,0], angle:-H };
|
| 247 |
+
case 'l2': return { axis:'x', layers:[-1,0], angle:PI };
|
| 248 |
+
case 'u': return { axis:'y', layers:[1,0], angle:-H };
|
| 249 |
+
case 'ui': return { axis:'y', layers:[1,0], angle:H };
|
| 250 |
+
case 'u2': return { axis:'y', layers:[1,0], angle:-PI };
|
| 251 |
+
case 'd': return { axis:'y', layers:[-1,0], angle:H };
|
| 252 |
+
case 'di': return { axis:'y', layers:[-1,0], angle:-H };
|
| 253 |
+
case 'd2': return { axis:'y', layers:[-1,0], angle:PI };
|
| 254 |
+
case 'f': return { axis:'z', layers:[1,0], angle:-H };
|
| 255 |
+
case 'fi': return { axis:'z', layers:[1,0], angle:H };
|
| 256 |
+
case 'f2': return { axis:'z', layers:[1,0], angle:-PI };
|
| 257 |
+
case 'b': return { axis:'z', layers:[-1,0], angle:H };
|
| 258 |
+
case 'bi': return { axis:'z', layers:[-1,0], angle:-H };
|
| 259 |
+
case 'b2': return { axis:'z', layers:[-1,0], angle:PI };
|
| 260 |
+
// Rotations (all 3 layers)
|
| 261 |
+
case 'x': return { axis:'x', layers:[1,0,-1], angle:-H };
|
| 262 |
+
case 'xi': return { axis:'x', layers:[1,0,-1], angle:H };
|
| 263 |
+
case 'x2': return { axis:'x', layers:[1,0,-1], angle:-PI };
|
| 264 |
+
case 'y': return { axis:'y', layers:[1,0,-1], angle:-H };
|
| 265 |
+
case 'yi': return { axis:'y', layers:[1,0,-1], angle:H };
|
| 266 |
+
case 'y2': return { axis:'y', layers:[1,0,-1], angle:-PI };
|
| 267 |
+
case 'z': return { axis:'z', layers:[1,0,-1], angle:-H };
|
| 268 |
+
case 'zi': return { axis:'z', layers:[1,0,-1], angle:H };
|
| 269 |
+
case 'z2': return { axis:'z', layers:[1,0,-1], angle:-PI };
|
| 270 |
+
// M slice (follows L direction = +x rotation for middle)
|
| 271 |
+
case 'M': return { axis:'x', layers:[0], angle:H };
|
| 272 |
+
case 'Mi': return { axis:'x', layers:[0], angle:-H };
|
| 273 |
+
case 'M2': return { axis:'x', layers:[0], angle:PI };
|
| 274 |
+
// S slice (follows F direction)
|
| 275 |
+
case 'S': return { axis:'z', layers:[0], angle:-H };
|
| 276 |
+
case 'Si': return { axis:'z', layers:[0], angle:H };
|
| 277 |
+
case 'S2': return { axis:'z', layers:[0], angle:PI };
|
| 278 |
+
default: return null;
|
| 279 |
+
}
|
| 280 |
+
}
|
| 281 |
+
|
| 282 |
+
function getCubiesOnLayers(axis, layers) {
|
| 283 |
+
const threshold = 0.5;
|
| 284 |
+
return cubies.filter(cubie => {
|
| 285 |
+
const pos = cubie.position;
|
| 286 |
+
for (const layer of layers) {
|
| 287 |
+
if (axis === 'x' && Math.abs(pos.x - layer * GAP) < threshold) return true;
|
| 288 |
+
if (axis === 'y' && Math.abs(pos.y - layer * GAP) < threshold) return true;
|
| 289 |
+
if (axis === 'z' && Math.abs(pos.z - layer * GAP) < threshold) return true;
|
| 290 |
+
}
|
| 291 |
+
return false;
|
| 292 |
+
});
|
| 293 |
+
}
|
| 294 |
+
|
| 295 |
+
function animateMove(axis, layers, angle, duration = 300) {
|
| 296 |
+
return new Promise(resolve => {
|
| 297 |
+
const layerCubies = getCubiesOnLayers(axis, layers);
|
| 298 |
+
if (layerCubies.length === 0) {
|
| 299 |
+
resolve();
|
| 300 |
+
return;
|
| 301 |
+
}
|
| 302 |
+
|
| 303 |
+
const rotationGroup = new THREE.Group();
|
| 304 |
+
scene.add(rotationGroup);
|
| 305 |
+
|
| 306 |
+
// Move cubies to rotation group
|
| 307 |
+
layerCubies.forEach(cubie => {
|
| 308 |
+
cubeGroup.remove(cubie);
|
| 309 |
+
rotationGroup.add(cubie);
|
| 310 |
+
});
|
| 311 |
+
|
| 312 |
+
const startTime = Date.now();
|
| 313 |
+
const axisVec = new THREE.Vector3(
|
| 314 |
+
axis === 'x' ? 1 : 0,
|
| 315 |
+
axis === 'y' ? 1 : 0,
|
| 316 |
+
axis === 'z' ? 1 : 0
|
| 317 |
+
);
|
| 318 |
+
|
| 319 |
+
function step() {
|
| 320 |
+
const elapsed = Date.now() - startTime;
|
| 321 |
+
const t = Math.min(elapsed / duration, 1);
|
| 322 |
+
// Smooth easing
|
| 323 |
+
const eased = t < 0.5
|
| 324 |
+
? 4 * t * t * t
|
| 325 |
+
: 1 - Math.pow(-2 * t + 2, 3) / 2;
|
| 326 |
+
|
| 327 |
+
rotationGroup.setRotationFromAxisAngle(axisVec, angle * eased);
|
| 328 |
+
|
| 329 |
+
if (t < 1) {
|
| 330 |
+
requestAnimationFrame(step);
|
| 331 |
+
} else {
|
| 332 |
+
// Finalize - apply rotation to each cubie
|
| 333 |
+
rotationGroup.setRotationFromAxisAngle(axisVec, angle);
|
| 334 |
+
rotationGroup.updateMatrixWorld();
|
| 335 |
+
|
| 336 |
+
layerCubies.forEach(cubie => {
|
| 337 |
+
cubie.applyMatrix4(rotationGroup.matrixWorld);
|
| 338 |
+
cubie.position.x = Math.round(cubie.position.x / GAP) * GAP;
|
| 339 |
+
cubie.position.y = Math.round(cubie.position.y / GAP) * GAP;
|
| 340 |
+
cubie.position.z = Math.round(cubie.position.z / GAP) * GAP;
|
| 341 |
+
rotationGroup.remove(cubie);
|
| 342 |
+
cubeGroup.add(cubie);
|
| 343 |
+
});
|
| 344 |
+
|
| 345 |
+
scene.remove(rotationGroup);
|
| 346 |
+
resolve();
|
| 347 |
+
}
|
| 348 |
+
}
|
| 349 |
+
|
| 350 |
+
step();
|
| 351 |
+
});
|
| 352 |
+
}
|
| 353 |
+
|
| 354 |
+
async function doMove(moveStr) {
|
| 355 |
+
if (isAnimating) return;
|
| 356 |
+
isAnimating = true;
|
| 357 |
+
|
| 358 |
+
const def = get3DMoveDef(moveStr);
|
| 359 |
+
if (def) {
|
| 360 |
+
await animateMove(def.axis, def.layers, def.angle, 250);
|
| 361 |
+
}
|
| 362 |
+
|
| 363 |
+
isAnimating = false;
|
| 364 |
+
processQueue();
|
| 365 |
+
}
|
| 366 |
+
|
| 367 |
+
async function processQueue() {
|
| 368 |
+
if (moveQueue.length === 0 || isAnimating) return;
|
| 369 |
+
isAnimating = true;
|
| 370 |
+
|
| 371 |
+
const move = moveQueue.shift();
|
| 372 |
+
const def = get3DMoveDef(move);
|
| 373 |
+
if (def) {
|
| 374 |
+
await animateMove(def.axis, def.layers, def.angle, 180);
|
| 375 |
+
}
|
| 376 |
+
|
| 377 |
+
isAnimating = false;
|
| 378 |
+
|
| 379 |
+
if (moveQueue.length > 0) {
|
| 380 |
+
processQueue();
|
| 381 |
+
}
|
| 382 |
+
}
|
| 383 |
+
|
| 384 |
+
// ============ NOTATION PARSER ============
|
| 385 |
+
|
| 386 |
+
function parseAlgorithm(notation) {
|
| 387 |
+
// Convert standard notation to our internal format
|
| 388 |
+
// Normalize curly quotes to straight apostrophes
|
| 389 |
+
notation = notation.replace(/\u2019/g, "'");
|
| 390 |
+
// Normalize X'2 to X2 (e.g., U'2 = U2, R'2 = R2)
|
| 391 |
+
notation = notation.replace(/([RUDLFBrudlfb])'2/g, '$12');
|
| 392 |
+
// Normalize X2' to X2 (e.g., U2' = U2, R2' = R2)
|
| 393 |
+
notation = notation.replace(/([RUDLFBrudlfb])2'/g, '$12');
|
| 394 |
+
const moves = [];
|
| 395 |
+
const tokens = notation.replace(/\(/g, '').replace(/\)/g, '').trim().split(/\s+/);
|
| 396 |
+
|
| 397 |
+
for (const token of tokens) {
|
| 398 |
+
let move = '';
|
| 399 |
+
if (token === "R") move = 'R';
|
| 400 |
+
else if (token === "R'" || token === "R\u2019") move = 'Ri';
|
| 401 |
+
else if (token === "R2") move = 'R2';
|
| 402 |
+
else if (token === "L") move = 'L';
|
| 403 |
+
else if (token === "L'" || token === "L\u2019") move = 'Li';
|
| 404 |
+
else if (token === "L2") move = 'L2';
|
| 405 |
+
else if (token === "U") move = 'U';
|
| 406 |
+
else if (token === "U'" || token === "U\u2019") move = 'Ui';
|
| 407 |
+
else if (token === "U2") move = 'U2';
|
| 408 |
+
else if (token === "D") move = 'D';
|
| 409 |
+
else if (token === "D'" || token === "D\u2019") move = 'Di';
|
| 410 |
+
else if (token === "D2") move = 'D2';
|
| 411 |
+
else if (token === "F") move = 'F';
|
| 412 |
+
else if (token === "F'" || token === "F\u2019") move = 'Fi';
|
| 413 |
+
else if (token === "F2") move = 'F2';
|
| 414 |
+
else if (token === "B") move = 'B';
|
| 415 |
+
else if (token === "B'" || token === "B\u2019") move = 'Bi';
|
| 416 |
+
else if (token === "B2") move = 'B2';
|
| 417 |
+
// Wide moves
|
| 418 |
+
else if (token === "r") move = 'r';
|
| 419 |
+
else if (token === "r'" || token === "r\u2019") move = 'ri';
|
| 420 |
+
else if (token === "r2") move = 'r2';
|
| 421 |
+
else if (token === "l") move = 'l';
|
| 422 |
+
else if (token === "l'" || token === "l\u2019") move = 'li';
|
| 423 |
+
else if (token === "l2") move = 'l2';
|
| 424 |
+
else if (token === "u") move = 'u';
|
| 425 |
+
else if (token === "u'" || token === "u\u2019") move = 'ui';
|
| 426 |
+
else if (token === "u2") move = 'u2';
|
| 427 |
+
else if (token === "d") move = 'd';
|
| 428 |
+
else if (token === "d'" || token === "d\u2019") move = 'di';
|
| 429 |
+
else if (token === "d2") move = 'd2';
|
| 430 |
+
else if (token === "f") move = 'f';
|
| 431 |
+
else if (token === "f'" || token === "f\u2019") move = 'fi';
|
| 432 |
+
else if (token === "f2") move = 'f2';
|
| 433 |
+
else if (token === "b") move = 'b';
|
| 434 |
+
else if (token === "b'" || token === "b\u2019") move = 'bi';
|
| 435 |
+
else if (token === "b2") move = 'b2';
|
| 436 |
+
// Rotations
|
| 437 |
+
else if (token === "x") move = 'x';
|
| 438 |
+
else if (token === "x'" || token === "x\u2019") move = 'xi';
|
| 439 |
+
else if (token === "x2") move = 'x2';
|
| 440 |
+
else if (token === "y") move = 'y';
|
| 441 |
+
else if (token === "y'" || token === "y\u2019") move = 'yi';
|
| 442 |
+
else if (token === "y2") move = 'y2';
|
| 443 |
+
else if (token === "z") move = 'z';
|
| 444 |
+
else if (token === "z'" || token === "z\u2019") move = 'zi';
|
| 445 |
+
else if (token === "z2") move = 'z2';
|
| 446 |
+
// M, S, E slice moves
|
| 447 |
+
else if (token === "M") move = 'M';
|
| 448 |
+
else if (token === "M'" || token === "M\u2019") move = 'Mi';
|
| 449 |
+
else if (token === "M2") move = 'M2';
|
| 450 |
+
else if (token === "S") move = 'S';
|
| 451 |
+
else if (token === "S'" || token === "S\u2019") move = 'Si';
|
| 452 |
+
else if (token === "S2") move = 'S2';
|
| 453 |
+
|
| 454 |
+
if (move) moves.push(move);
|
| 455 |
+
}
|
| 456 |
+
return moves;
|
| 457 |
+
}
|
| 458 |
+
|
| 459 |
+
function playAlgorithm(notation) {
|
| 460 |
+
if (isAnimating || moveQueue.length > 0) return;
|
| 461 |
+
|
| 462 |
+
const moves = parseAlgorithm(notation);
|
| 463 |
+
if (moves.length === 0) return;
|
| 464 |
+
|
| 465 |
+
document.getElementById('scramble-display').textContent = 'Playing: ' + notation;
|
| 466 |
+
moveQueue.push(...moves);
|
| 467 |
+
processQueue();
|
| 468 |
+
|
| 469 |
+
// Reset display after animation completes
|
| 470 |
+
const totalTime = moves.length * 280;
|
| 471 |
+
setTimeout(() => {
|
| 472 |
+
document.getElementById('scramble-display').textContent = 'Drag to rotate \u2022 Scroll to zoom';
|
| 473 |
+
}, totalTime);
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
+
// Invert a single move token (e.g., 'R' -> 'Ri', 'Ri' -> 'R', 'R2' -> 'R2')
|
| 477 |
+
function invertMove(move) {
|
| 478 |
+
if (move.endsWith('2')) return move; // double moves are self-inverse
|
| 479 |
+
if (move.endsWith('i')) return move.slice(0, -1); // Ri -> R
|
| 480 |
+
return move + 'i'; // R -> Ri
|
| 481 |
+
}
|
| 482 |
+
|
| 483 |
+
// Setup the case (apply inverse of algorithm instantly) then play the solve animated
|
| 484 |
+
async function setupAndSolve(notation) {
|
| 485 |
+
if (isAnimating || moveQueue.length > 0) return;
|
| 486 |
+
cancelStepMode();
|
| 487 |
+
|
| 488 |
+
// Focus the pop-out window if cube is popped out
|
| 489 |
+
if (cubePopWindow && !cubePopWindow.closed) {
|
| 490 |
+
cubePopWindow.focus();
|
| 491 |
+
}
|
| 492 |
+
|
| 493 |
+
// Reset cube first
|
| 494 |
+
scene.remove(cubeGroup);
|
| 495 |
+
createCube();
|
| 496 |
+
|
| 497 |
+
const moves = parseAlgorithm(notation);
|
| 498 |
+
if (moves.length === 0) return;
|
| 499 |
+
|
| 500 |
+
// Compute inverse sequence (reversed order, each move inverted)
|
| 501 |
+
const inverseMoves = moves.slice().reverse().map(invertMove);
|
| 502 |
+
|
| 503 |
+
// Apply the inverse instantly (no animation) to set up the case
|
| 504 |
+
document.getElementById('scramble-display').textContent = 'Setting up case...';
|
| 505 |
+
|
| 506 |
+
isAnimating = true;
|
| 507 |
+
for (const move of inverseMoves) {
|
| 508 |
+
const def = get3DMoveDef(move);
|
| 509 |
+
if (def) {
|
| 510 |
+
await animateMove(def.axis, def.layers, def.angle, 40);
|
| 511 |
+
}
|
| 512 |
+
}
|
| 513 |
+
isAnimating = false;
|
| 514 |
+
|
| 515 |
+
// Brief pause to let user see the scrambled state
|
| 516 |
+
await new Promise(r => setTimeout(r, 600));
|
| 517 |
+
|
| 518 |
+
// Now play the solution animated
|
| 519 |
+
document.getElementById('scramble-display').textContent = 'Solving: ' + notation;
|
| 520 |
+
moveQueue.push(...moves);
|
| 521 |
+
processQueue();
|
| 522 |
+
|
| 523 |
+
const totalTime = moves.length * 280;
|
| 524 |
+
setTimeout(() => {
|
| 525 |
+
document.getElementById('scramble-display').textContent = 'Solved! \u2714';
|
| 526 |
+
}, totalTime);
|
| 527 |
+
}
|
| 528 |
+
|
| 529 |
+
// ============ STEP BY STEP MODE ============
|
| 530 |
+
|
| 531 |
+
let stepMoves = [];
|
| 532 |
+
let stepIndex = 0;
|
| 533 |
+
let stepTotal = 0;
|
| 534 |
+
let stepNotation = '';
|
| 535 |
+
let stepActive = false;
|
| 536 |
+
|
| 537 |
+
function cancelStepMode() {
|
| 538 |
+
stepActive = false;
|
| 539 |
+
stepMoves = [];
|
| 540 |
+
stepIndex = 0;
|
| 541 |
+
hideStepPanel();
|
| 542 |
+
}
|
| 543 |
+
|
| 544 |
+
function hideStepPanel() {
|
| 545 |
+
const panel = document.getElementById('step-panel');
|
| 546 |
+
if (panel) panel.style.display = 'none';
|
| 547 |
+
// Also hide step controls in pop-out window
|
| 548 |
+
if (cubePopWindow && !cubePopWindow.closed) {
|
| 549 |
+
const popStepCtrl = cubePopWindow.document.getElementById('step-controls-pop');
|
| 550 |
+
if (popStepCtrl) popStepCtrl.style.display = 'none';
|
| 551 |
+
}
|
| 552 |
+
}
|
| 553 |
+
|
| 554 |
+
function showStepPanel() {
|
| 555 |
+
let panel = document.getElementById('step-panel');
|
| 556 |
+
if (!panel) {
|
| 557 |
+
panel = document.createElement('div');
|
| 558 |
+
panel.id = 'step-panel';
|
| 559 |
+
document.querySelector('.cube-section').appendChild(panel);
|
| 560 |
+
}
|
| 561 |
+
panel.style.display = 'flex';
|
| 562 |
+
// Default position: top-right corner, beside the cube
|
| 563 |
+
panel.style.left = 'auto';
|
| 564 |
+
panel.style.right = '15px';
|
| 565 |
+
panel.style.top = '15px';
|
| 566 |
+
panel.style.bottom = 'auto';
|
| 567 |
+
panel.style.transform = 'none';
|
| 568 |
+
updateStepPanel();
|
| 569 |
+
// Also show step controls in pop-out window
|
| 570 |
+
if (cubePopWindow && !cubePopWindow.closed) {
|
| 571 |
+
const popStepCtrl = cubePopWindow.document.getElementById('step-controls-pop');
|
| 572 |
+
if (popStepCtrl) popStepCtrl.style.display = 'flex';
|
| 573 |
+
}
|
| 574 |
+
}
|
| 575 |
+
|
| 576 |
+
// ============ DRAG FUNCTIONALITY ============
|
| 577 |
+
|
| 578 |
+
let isDragging = false;
|
| 579 |
+
let dragOffsetX = 0;
|
| 580 |
+
let dragOffsetY = 0;
|
| 581 |
+
|
| 582 |
+
function initPanelDrag() {
|
| 583 |
+
const handle = document.getElementById('step-drag-handle');
|
| 584 |
+
if (!handle) return;
|
| 585 |
+
|
| 586 |
+
handle.addEventListener('mousedown', startDrag);
|
| 587 |
+
handle.addEventListener('touchstart', startDragTouch, { passive: false });
|
| 588 |
+
}
|
| 589 |
+
|
| 590 |
+
function startDrag(e) {
|
| 591 |
+
e.preventDefault();
|
| 592 |
+
const panel = document.getElementById('step-panel');
|
| 593 |
+
if (!panel) return;
|
| 594 |
+
|
| 595 |
+
isDragging = true;
|
| 596 |
+
|
| 597 |
+
// Get current panel position
|
| 598 |
+
const rect = panel.getBoundingClientRect();
|
| 599 |
+
const parentRect = panel.parentElement.getBoundingClientRect();
|
| 600 |
+
|
| 601 |
+
// Switch from right-based to left-based absolute positioning
|
| 602 |
+
panel.style.transform = 'none';
|
| 603 |
+
panel.style.right = 'auto';
|
| 604 |
+
panel.style.left = (rect.left - parentRect.left) + 'px';
|
| 605 |
+
panel.style.top = (rect.top - parentRect.top) + 'px';
|
| 606 |
+
panel.style.bottom = 'auto';
|
| 607 |
+
|
| 608 |
+
dragOffsetX = e.clientX - rect.left;
|
| 609 |
+
dragOffsetY = e.clientY - rect.top;
|
| 610 |
+
|
| 611 |
+
document.addEventListener('mousemove', onDrag);
|
| 612 |
+
document.addEventListener('mouseup', stopDrag);
|
| 613 |
+
}
|
| 614 |
+
|
| 615 |
+
function startDragTouch(e) {
|
| 616 |
+
e.preventDefault();
|
| 617 |
+
const touch = e.touches[0];
|
| 618 |
+
const panel = document.getElementById('step-panel');
|
| 619 |
+
if (!panel) return;
|
| 620 |
+
|
| 621 |
+
isDragging = true;
|
| 622 |
+
|
| 623 |
+
const rect = panel.getBoundingClientRect();
|
| 624 |
+
const parentRect = panel.parentElement.getBoundingClientRect();
|
| 625 |
+
|
| 626 |
+
panel.style.transform = 'none';
|
| 627 |
+
panel.style.right = 'auto';
|
| 628 |
+
panel.style.left = (rect.left - parentRect.left) + 'px';
|
| 629 |
+
panel.style.top = (rect.top - parentRect.top) + 'px';
|
| 630 |
+
panel.style.bottom = 'auto';
|
| 631 |
+
|
| 632 |
+
dragOffsetX = touch.clientX - rect.left;
|
| 633 |
+
dragOffsetY = touch.clientY - rect.top;
|
| 634 |
+
|
| 635 |
+
document.addEventListener('touchmove', onDragTouch, { passive: false });
|
| 636 |
+
document.addEventListener('touchend', stopDrag);
|
| 637 |
+
}
|
| 638 |
+
|
| 639 |
+
function onDrag(e) {
|
| 640 |
+
if (!isDragging) return;
|
| 641 |
+
const panel = document.getElementById('step-panel');
|
| 642 |
+
if (!panel) return;
|
| 643 |
+
|
| 644 |
+
const parentRect = panel.parentElement.getBoundingClientRect();
|
| 645 |
+
let newX = e.clientX - parentRect.left - dragOffsetX;
|
| 646 |
+
let newY = e.clientY - parentRect.top - dragOffsetY;
|
| 647 |
+
|
| 648 |
+
// Constrain within parent
|
| 649 |
+
newX = Math.max(0, Math.min(newX, parentRect.width - panel.offsetWidth));
|
| 650 |
+
newY = Math.max(0, Math.min(newY, parentRect.height - panel.offsetHeight));
|
| 651 |
+
|
| 652 |
+
panel.style.left = newX + 'px';
|
| 653 |
+
panel.style.top = newY + 'px';
|
| 654 |
+
}
|
| 655 |
+
|
| 656 |
+
function onDragTouch(e) {
|
| 657 |
+
if (!isDragging) return;
|
| 658 |
+
e.preventDefault();
|
| 659 |
+
const touch = e.touches[0];
|
| 660 |
+
const panel = document.getElementById('step-panel');
|
| 661 |
+
if (!panel) return;
|
| 662 |
+
|
| 663 |
+
const parentRect = panel.parentElement.getBoundingClientRect();
|
| 664 |
+
let newX = touch.clientX - parentRect.left - dragOffsetX;
|
| 665 |
+
let newY = touch.clientY - parentRect.top - dragOffsetY;
|
| 666 |
+
|
| 667 |
+
newX = Math.max(0, Math.min(newX, parentRect.width - panel.offsetWidth));
|
| 668 |
+
newY = Math.max(0, Math.min(newY, parentRect.height - panel.offsetHeight));
|
| 669 |
+
|
| 670 |
+
panel.style.left = newX + 'px';
|
| 671 |
+
panel.style.top = newY + 'px';
|
| 672 |
+
}
|
| 673 |
+
|
| 674 |
+
function stopDrag() {
|
| 675 |
+
isDragging = false;
|
| 676 |
+
document.removeEventListener('mousemove', onDrag);
|
| 677 |
+
document.removeEventListener('mouseup', stopDrag);
|
| 678 |
+
document.removeEventListener('touchmove', onDragTouch);
|
| 679 |
+
document.removeEventListener('touchend', stopDrag);
|
| 680 |
+
}
|
| 681 |
+
|
| 682 |
+
function updateStepPanel() {
|
| 683 |
+
const panel = document.getElementById('step-panel');
|
| 684 |
+
if (!panel) return;
|
| 685 |
+
|
| 686 |
+
const tokens = parseAlgorithmTokens(stepNotation);
|
| 687 |
+
|
| 688 |
+
// Build move display with highlighting
|
| 689 |
+
let movesHtml = '';
|
| 690 |
+
for (let i = 0; i < tokens.length; i++) {
|
| 691 |
+
if (i < stepIndex) {
|
| 692 |
+
movesHtml += '<span class="step-done">' + tokens[i] + '</span> ';
|
| 693 |
+
} else if (i === stepIndex) {
|
| 694 |
+
movesHtml += '<span class="step-current">' + tokens[i] + '</span> ';
|
| 695 |
+
} else {
|
| 696 |
+
movesHtml += '<span class="step-pending">' + tokens[i] + '</span> ';
|
| 697 |
+
}
|
| 698 |
+
}
|
| 699 |
+
|
| 700 |
+
const isComplete = stepIndex >= stepTotal;
|
| 701 |
+
|
| 702 |
+
let html = '<div class="drag-handle" id="step-drag-handle">☰ Drag to move</div>';
|
| 703 |
+
html += '<div class="step-content">';
|
| 704 |
+
html += '<div class="step-info">';
|
| 705 |
+
html += '<div class="step-counter">Step ' + Math.min(stepIndex + 1, stepTotal) + ' / ' + stepTotal + '</div>';
|
| 706 |
+
html += '<div class="step-moves-display">' + movesHtml + '</div>';
|
| 707 |
+
html += '</div>';
|
| 708 |
+
html += '<div class="step-buttons">';
|
| 709 |
+
if (stepIndex > 0) {
|
| 710 |
+
html += '<button class="step-btn step-btn-prev" onclick="executePrevStep()">◀ Prev</button>';
|
| 711 |
+
}
|
| 712 |
+
if (isComplete) {
|
| 713 |
+
html += '<button class="step-btn step-btn-done" onclick="cancelStepMode()">✔ Done</button>';
|
| 714 |
+
} else {
|
| 715 |
+
html += '<button class="step-btn step-btn-next" onclick="executeNextStep()">Next Step ▶</button>';
|
| 716 |
+
}
|
| 717 |
+
html += '<button class="step-btn step-btn-cancel" onclick="cancelStepMode()">Cancel</button>';
|
| 718 |
+
html += '</div>';
|
| 719 |
+
html += '</div>';
|
| 720 |
+
|
| 721 |
+
panel.innerHTML = html;
|
| 722 |
+
|
| 723 |
+
// Attach drag listeners after render
|
| 724 |
+
initPanelDrag();
|
| 725 |
+
|
| 726 |
+
// Sync step info to pop-out window
|
| 727 |
+
if (cubePopWindow && !cubePopWindow.closed) {
|
| 728 |
+
const popInfo = cubePopWindow.document.getElementById('step-info-pop');
|
| 729 |
+
if (popInfo) {
|
| 730 |
+
let popHtml = '<div class="step-counter">Step ' + Math.min(stepIndex + 1, stepTotal) + ' / ' + stepTotal + '</div>';
|
| 731 |
+
popHtml += '<div class="step-moves">' + movesHtml + '</div>';
|
| 732 |
+
popInfo.innerHTML = popHtml;
|
| 733 |
+
}
|
| 734 |
+
}
|
| 735 |
+
}
|
| 736 |
+
|
| 737 |
+
// Parse notation keeping original tokens for display
|
| 738 |
+
function parseAlgorithmTokens(notation) {
|
| 739 |
+
notation = notation.replace(/\u2019/g, "'");
|
| 740 |
+
return notation.replace(/\(/g, '').replace(/\)/g, '').trim().split(/\s+/);
|
| 741 |
+
}
|
| 742 |
+
|
| 743 |
+
async function startStepByStep(notation) {
|
| 744 |
+
if (isAnimating || moveQueue.length > 0) return;
|
| 745 |
+
cancelStepMode();
|
| 746 |
+
|
| 747 |
+
// Focus the pop-out window if cube is popped out
|
| 748 |
+
if (cubePopWindow && !cubePopWindow.closed) {
|
| 749 |
+
cubePopWindow.focus();
|
| 750 |
+
}
|
| 751 |
+
|
| 752 |
+
// Reset cube first
|
| 753 |
+
scene.remove(cubeGroup);
|
| 754 |
+
createCube();
|
| 755 |
+
|
| 756 |
+
const moves = parseAlgorithm(notation);
|
| 757 |
+
if (moves.length === 0) return;
|
| 758 |
+
|
| 759 |
+
// Compute inverse sequence to set up the case
|
| 760 |
+
const inverseMoves = moves.slice().reverse().map(invertMove);
|
| 761 |
+
|
| 762 |
+
document.getElementById('scramble-display').textContent = 'Setting up case...';
|
| 763 |
+
|
| 764 |
+
isAnimating = true;
|
| 765 |
+
for (const move of inverseMoves) {
|
| 766 |
+
const def = get3DMoveDef(move);
|
| 767 |
+
if (def) {
|
| 768 |
+
await animateMove(def.axis, def.layers, def.angle, 40);
|
| 769 |
+
}
|
| 770 |
+
}
|
| 771 |
+
isAnimating = false;
|
| 772 |
+
|
| 773 |
+
// Enter step mode
|
| 774 |
+
stepMoves = moves;
|
| 775 |
+
stepIndex = 0;
|
| 776 |
+
stepTotal = moves.length;
|
| 777 |
+
stepNotation = notation;
|
| 778 |
+
stepActive = true;
|
| 779 |
+
|
| 780 |
+
document.getElementById('scramble-display').textContent = 'Step-by-step: Click "Next Step" to advance';
|
| 781 |
+
showStepPanel();
|
| 782 |
+
|
| 783 |
+
// Ensure pop-out step controls are visible (retry after short delay for timing)
|
| 784 |
+
if (cubePopWindow && !cubePopWindow.closed) {
|
| 785 |
+
setTimeout(function() {
|
| 786 |
+
const popStepCtrl = cubePopWindow.document.getElementById('step-controls-pop');
|
| 787 |
+
if (popStepCtrl) popStepCtrl.style.display = 'flex';
|
| 788 |
+
}, 200);
|
| 789 |
+
}
|
| 790 |
+
}
|
| 791 |
+
|
| 792 |
+
async function executeNextStep() {
|
| 793 |
+
if (!stepActive || isAnimating || stepIndex >= stepTotal) return;
|
| 794 |
+
|
| 795 |
+
const move = stepMoves[stepIndex];
|
| 796 |
+
const def = get3DMoveDef(move);
|
| 797 |
+
|
| 798 |
+
if (def) {
|
| 799 |
+
isAnimating = true;
|
| 800 |
+
await animateMove(def.axis, def.layers, def.angle, 350);
|
| 801 |
+
isAnimating = false;
|
| 802 |
+
}
|
| 803 |
+
|
| 804 |
+
stepIndex++;
|
| 805 |
+
|
| 806 |
+
if (stepIndex >= stepTotal) {
|
| 807 |
+
document.getElementById('scramble-display').textContent = 'Solved! \u2714';
|
| 808 |
+
} else {
|
| 809 |
+
const tokens = parseAlgorithmTokens(stepNotation);
|
| 810 |
+
document.getElementById('scramble-display').textContent =
|
| 811 |
+
'Step ' + (stepIndex + 1) + '/' + stepTotal + ': next is ' + tokens[stepIndex];
|
| 812 |
+
}
|
| 813 |
+
|
| 814 |
+
updateStepPanel();
|
| 815 |
+
}
|
| 816 |
+
|
| 817 |
+
async function executePrevStep() {
|
| 818 |
+
if (!stepActive || isAnimating || stepIndex <= 0) return;
|
| 819 |
+
|
| 820 |
+
// Undo the previous move by applying its inverse
|
| 821 |
+
stepIndex--;
|
| 822 |
+
const move = stepMoves[stepIndex];
|
| 823 |
+
const inverseMove = invertMove(move);
|
| 824 |
+
const def = get3DMoveDef(inverseMove);
|
| 825 |
+
|
| 826 |
+
if (def) {
|
| 827 |
+
isAnimating = true;
|
| 828 |
+
await animateMove(def.axis, def.layers, def.angle, 350);
|
| 829 |
+
isAnimating = false;
|
| 830 |
+
}
|
| 831 |
+
|
| 832 |
+
const tokens = parseAlgorithmTokens(stepNotation);
|
| 833 |
+
document.getElementById('scramble-display').textContent =
|
| 834 |
+
'Step ' + (stepIndex + 1) + '/' + stepTotal + ': next is ' + tokens[stepIndex];
|
| 835 |
+
|
| 836 |
+
updateStepPanel();
|
| 837 |
+
}
|
| 838 |
+
|
| 839 |
+
// ============ SCRAMBLE & RESET ============
|
| 840 |
+
|
| 841 |
+
function scrambleCube() {
|
| 842 |
+
if (isAnimating || moveQueue.length > 0) return;
|
| 843 |
+
|
| 844 |
+
const scramblePool = ['R','Ri','R2','L','Li','L2','U','Ui','U2','D','Di','D2','F','Fi','F2','B','Bi','B2'];
|
| 845 |
+
const scrambleMoves = [];
|
| 846 |
+
|
| 847 |
+
for (let i = 0; i < 20; i++) {
|
| 848 |
+
const move = scramblePool[Math.floor(Math.random() * scramblePool.length)];
|
| 849 |
+
scrambleMoves.push(move);
|
| 850 |
+
}
|
| 851 |
+
|
| 852 |
+
document.getElementById('scramble-display').textContent = 'Scrambling...';
|
| 853 |
+
moveQueue.push(...scrambleMoves);
|
| 854 |
+
processQueue();
|
| 855 |
+
|
| 856 |
+
setTimeout(() => {
|
| 857 |
+
document.getElementById('scramble-display').textContent = 'Scrambled! Try an algorithm.';
|
| 858 |
+
}, scrambleMoves.length * 210);
|
| 859 |
+
}
|
| 860 |
+
|
| 861 |
+
function resetCube() {
|
| 862 |
+
if (isAnimating) return;
|
| 863 |
+
moveQueue = [];
|
| 864 |
+
|
| 865 |
+
// Remove existing cube and recreate
|
| 866 |
+
scene.remove(cubeGroup);
|
| 867 |
+
createCube();
|
| 868 |
+
|
| 869 |
+
document.getElementById('scramble-display').textContent = 'Cube reset! Drag to rotate \u2022 Scroll to zoom';
|
| 870 |
+
}
|
| 871 |
+
|
| 872 |
+
// ============ UI RENDERING ============
|
| 873 |
+
|
| 874 |
+
let currentSection = 'f2l';
|
| 875 |
+
|
| 876 |
+
// ============ TOP VIEW DIAGRAM GENERATOR ============
|
| 877 |
+
// Computes the top-view diagram by simulating the algorithm inverse on a solved cube
|
| 878 |
+
// This guarantees the diagram matches exactly what the 3D cube shows
|
| 879 |
+
|
| 880 |
+
const DIAG_COLORS = {
|
| 881 |
+
U: '#ffdd00', // Yellow (top)
|
| 882 |
+
D: '#ffffff', // White (bottom)
|
| 883 |
+
R: '#ee0000', // Red
|
| 884 |
+
L: '#ff8800', // Orange
|
| 885 |
+
F: '#0051ff', // Blue
|
| 886 |
+
B: '#00aa33', // Green
|
| 887 |
+
X: '#444444' // Grey (unknown/internal)
|
| 888 |
+
};
|
| 889 |
+
|
| 890 |
+
// Mini cube state simulator for computing top-view diagrams
|
| 891 |
+
// State: 6 faces x 9 stickers = 54 values
|
| 892 |
+
// Face order: U, D, R, L, F, B
|
| 893 |
+
// Sticker order per face (looking at face):
|
| 894 |
+
// 0 1 2
|
| 895 |
+
// 3 4 5
|
| 896 |
+
// 6 7 8
|
| 897 |
+
function createSolvedState() {
|
| 898 |
+
return {
|
| 899 |
+
U: ['U','U','U','U','U','U','U','U','U'],
|
| 900 |
+
D: ['D','D','D','D','D','D','D','D','D'],
|
| 901 |
+
R: ['R','R','R','R','R','R','R','R','R'],
|
| 902 |
+
L: ['L','L','L','L','L','L','L','L','L'],
|
| 903 |
+
F: ['F','F','F','F','F','F','F','F','F'],
|
| 904 |
+
B: ['B','B','B','B','B','B','B','B','B']
|
| 905 |
+
};
|
| 906 |
+
}
|
| 907 |
+
|
| 908 |
+
function cloneState(s) {
|
| 909 |
+
return {
|
| 910 |
+
U: [...s.U], D: [...s.D], R: [...s.R],
|
| 911 |
+
L: [...s.L], F: [...s.F], B: [...s.B]
|
| 912 |
+
};
|
| 913 |
+
}
|
| 914 |
+
|
| 915 |
+
// Apply a single move to the state
|
| 916 |
+
function applyMoveToState(state, move) {
|
| 917 |
+
let s = cloneState(state);
|
| 918 |
+
switch(move) {
|
| 919 |
+
case 'U': return moveU(s);
|
| 920 |
+
case 'Ui': return moveU(moveU(moveU(s)));
|
| 921 |
+
case 'U2': return moveU(moveU(s));
|
| 922 |
+
case 'D': return moveD(s);
|
| 923 |
+
case 'Di': return moveD(moveD(moveD(s)));
|
| 924 |
+
case 'D2': return moveD(moveD(s));
|
| 925 |
+
case 'R': return moveR(s);
|
| 926 |
+
case 'Ri': return moveR(moveR(moveR(s)));
|
| 927 |
+
case 'R2': return moveR(moveR(s));
|
| 928 |
+
case 'L': return moveL(s);
|
| 929 |
+
case 'Li': return moveL(moveL(moveL(s)));
|
| 930 |
+
case 'L2': return moveL(moveL(s));
|
| 931 |
+
case 'F': return moveF(s);
|
| 932 |
+
case 'Fi': return moveF(moveF(moveF(s)));
|
| 933 |
+
case 'F2': return moveF(moveF(s));
|
| 934 |
+
case 'B': return moveB(s);
|
| 935 |
+
case 'Bi': return moveB(moveB(moveB(s)));
|
| 936 |
+
case 'B2': return moveB(moveB(s));
|
| 937 |
+
// Wide moves: r = R + M' (M' same direction as R)
|
| 938 |
+
case 'r': s = moveR(s); return moveMx(s);
|
| 939 |
+
case 'ri': s = moveR(moveR(moveR(s))); return moveMx(moveMx(moveMx(s)));
|
| 940 |
+
case 'r2': s = moveR(moveR(s)); return moveMx(moveMx(s));
|
| 941 |
+
case 'l': s = moveL(s); return moveMxi(s);
|
| 942 |
+
case 'li': s = moveL(moveL(moveL(s))); return moveMxi(moveMxi(moveMxi(s)));
|
| 943 |
+
case 'l2': s = moveL(moveL(s)); return moveMxi(moveMxi(s));
|
| 944 |
+
case 'u': s = moveU(s); return moveMy(s);
|
| 945 |
+
case 'ui': s = moveU(moveU(moveU(s))); return moveMy(moveMy(moveMy(s)));
|
| 946 |
+
case 'u2': s = moveU(moveU(s)); return moveMy(moveMy(s));
|
| 947 |
+
case 'd': s = moveD(s); return moveMyi(s);
|
| 948 |
+
case 'di': s = moveD(moveD(moveD(s))); return moveMyi(moveMyi(moveMyi(s)));
|
| 949 |
+
case 'd2': s = moveD(moveD(s)); return moveMyi(moveMyi(s));
|
| 950 |
+
case 'f': s = moveF(s); return moveMz(s);
|
| 951 |
+
case 'fi': s = moveF(moveF(moveF(s))); return moveMz(moveMz(moveMz(s)));
|
| 952 |
+
case 'f2': s = moveF(moveF(s)); return moveMz(moveMz(s));
|
| 953 |
+
case 'b': s = moveB(s); return moveMzi(s);
|
| 954 |
+
case 'bi': s = moveB(moveB(moveB(s))); return moveMzi(moveMzi(moveMzi(s)));
|
| 955 |
+
case 'b2': s = moveB(moveB(s)); return moveMzi(moveMzi(s));
|
| 956 |
+
// Rotations: x follows R, y follows U, z follows F
|
| 957 |
+
// Physical R direction: F→U→B→D (sticker at F moves to U position)
|
| 958 |
+
// moveR implements this: new U = old F (F→U) ✓
|
| 959 |
+
// Physical L direction: U→F→D→B (opposite of R)
|
| 960 |
+
// So for x (R direction on ALL layers): left layer needs L' = moveL³
|
| 961 |
+
case 'x': s = moveR(s); s = moveMx(s); return moveL(moveL(moveL(s)));
|
| 962 |
+
case 'xi': s = moveR(moveR(moveR(s))); s = moveMx(moveMx(moveMx(s))); return moveL(s);
|
| 963 |
+
case 'x2': s = moveR(moveR(s)); s = moveMx(moveMx(s)); return moveL(moveL(s));
|
| 964 |
+
case 'y': s = moveU(s); s = moveMy(s); return moveD(moveD(moveD(s)));
|
| 965 |
+
case 'yi': s = moveU(moveU(moveU(s))); s = moveMy(moveMy(moveMy(s))); return moveD(s);
|
| 966 |
+
case 'y2': s = moveU(moveU(s)); s = moveMy(moveMy(s)); return moveD(moveD(s));
|
| 967 |
+
case 'z': s = moveF(s); s = moveMz(s); return moveB(moveB(moveB(s)));
|
| 968 |
+
case 'zi': s = moveF(moveF(moveF(s))); s = moveMz(moveMz(moveMz(s))); return moveB(s);
|
| 969 |
+
case 'z2': s = moveF(moveF(s)); s = moveMz(moveMz(s)); return moveB(moveB(s));
|
| 970 |
+
// M slice (between R and L, follows L direction = opposite of R)
|
| 971 |
+
case 'M': return moveMx(moveMx(moveMx(s)));
|
| 972 |
+
case 'Mi': return moveMx(s);
|
| 973 |
+
case 'M2': return moveMx(moveMx(s));
|
| 974 |
+
// S slice (between F and B, follows F direction)
|
| 975 |
+
case 'S': return moveMz(s);
|
| 976 |
+
case 'Si': return moveMz(moveMz(moveMz(s)));
|
| 977 |
+
case 'S2': return moveMz(moveMz(s));
|
| 978 |
+
default: return s;
|
| 979 |
+
}
|
| 980 |
+
}
|
| 981 |
+
|
| 982 |
+
// Middle slice moves for state simulation
|
| 983 |
+
// Mx = M slice following R direction (between R and L, rotates like R)
|
| 984 |
+
// Mx = Middle slice (same cycle direction as moveR for consistency)
|
| 985 |
+
function moveMx(s) {
|
| 986 |
+
const tmp = [s.U[1],s.U[4],s.U[7]];
|
| 987 |
+
s.U[1]=s.F[1]; s.U[4]=s.F[4]; s.U[7]=s.F[7];
|
| 988 |
+
s.F[1]=s.D[1]; s.F[4]=s.D[4]; s.F[7]=s.D[7];
|
| 989 |
+
s.D[1]=s.B[7]; s.D[4]=s.B[4]; s.D[7]=s.B[1];
|
| 990 |
+
s.B[7]=tmp[0]; s.B[4]=tmp[1]; s.B[1]=tmp[2];
|
| 991 |
+
return s;
|
| 992 |
+
}
|
| 993 |
+
function moveMxi(s) { return moveMx(moveMx(moveMx(s))); }
|
| 994 |
+
|
| 995 |
+
// My = E slice following U direction (between U and D, rotates like U)
|
| 996 |
+
function moveMy(s) {
|
| 997 |
+
const tmp = [s.F[3],s.F[4],s.F[5]];
|
| 998 |
+
s.F[3]=s.R[3]; s.F[4]=s.R[4]; s.F[5]=s.R[5];
|
| 999 |
+
s.R[3]=s.B[3]; s.R[4]=s.B[4]; s.R[5]=s.B[5];
|
| 1000 |
+
s.B[3]=s.L[3]; s.B[4]=s.L[4]; s.B[5]=s.L[5];
|
| 1001 |
+
s.L[3]=tmp[0]; s.L[4]=tmp[1]; s.L[5]=tmp[2];
|
| 1002 |
+
return s;
|
| 1003 |
+
}
|
| 1004 |
+
function moveMyi(s) { return moveMy(moveMy(moveMy(s))); }
|
| 1005 |
+
|
| 1006 |
+
// Mz = S slice following F direction (between F and B, rotates like F)
|
| 1007 |
+
function moveMz(s) {
|
| 1008 |
+
const tmp = [s.U[3],s.U[4],s.U[5]];
|
| 1009 |
+
s.U[3]=s.L[7]; s.U[4]=s.L[4]; s.U[5]=s.L[1];
|
| 1010 |
+
s.L[1]=s.D[3]; s.L[4]=s.D[4]; s.L[7]=s.D[5];
|
| 1011 |
+
s.D[3]=s.R[7]; s.D[4]=s.R[4]; s.D[5]=s.R[1];
|
| 1012 |
+
s.R[1]=tmp[0]; s.R[4]=tmp[1]; s.R[7]=tmp[2];
|
| 1013 |
+
return s;
|
| 1014 |
+
}
|
| 1015 |
+
function moveMzi(s) { return moveMz(moveMz(moveMz(s))); }
|
| 1016 |
+
|
| 1017 |
+
function rotateFaceCW(face) {
|
| 1018 |
+
return [face[6],face[3],face[0],face[7],face[4],face[1],face[8],face[5],face[2]];
|
| 1019 |
+
}
|
| 1020 |
+
|
| 1021 |
+
function moveU(s) {
|
| 1022 |
+
s.U = rotateFaceCW(s.U);
|
| 1023 |
+
const tmp = [s.F[0],s.F[1],s.F[2]];
|
| 1024 |
+
s.F[0]=s.R[0]; s.F[1]=s.R[1]; s.F[2]=s.R[2];
|
| 1025 |
+
s.R[0]=s.B[0]; s.R[1]=s.B[1]; s.R[2]=s.B[2];
|
| 1026 |
+
s.B[0]=s.L[0]; s.B[1]=s.L[1]; s.B[2]=s.L[2];
|
| 1027 |
+
s.L[0]=tmp[0]; s.L[1]=tmp[1]; s.L[2]=tmp[2];
|
| 1028 |
+
return s;
|
| 1029 |
+
}
|
| 1030 |
+
|
| 1031 |
+
function moveD(s) {
|
| 1032 |
+
s.D = rotateFaceCW(s.D);
|
| 1033 |
+
const tmp = [s.F[6],s.F[7],s.F[8]];
|
| 1034 |
+
s.F[6]=s.L[6]; s.F[7]=s.L[7]; s.F[8]=s.L[8];
|
| 1035 |
+
s.L[6]=s.B[6]; s.L[7]=s.B[7]; s.L[8]=s.B[8];
|
| 1036 |
+
s.B[6]=s.R[6]; s.B[7]=s.R[7]; s.B[8]=s.R[8];
|
| 1037 |
+
s.R[6]=tmp[0]; s.R[7]=tmp[1]; s.R[8]=tmp[2];
|
| 1038 |
+
return s;
|
| 1039 |
+
}
|
| 1040 |
+
|
| 1041 |
+
function moveR(s) {
|
| 1042 |
+
s.R = rotateFaceCW(s.R);
|
| 1043 |
+
const tmp = [s.U[2],s.U[5],s.U[8]];
|
| 1044 |
+
s.U[2]=s.F[2]; s.U[5]=s.F[5]; s.U[8]=s.F[8];
|
| 1045 |
+
s.F[2]=s.D[2]; s.F[5]=s.D[5]; s.F[8]=s.D[8];
|
| 1046 |
+
s.D[2]=s.B[6]; s.D[5]=s.B[3]; s.D[8]=s.B[0];
|
| 1047 |
+
s.B[6]=tmp[0]; s.B[3]=tmp[1]; s.B[0]=tmp[2];
|
| 1048 |
+
return s;
|
| 1049 |
+
}
|
| 1050 |
+
|
| 1051 |
+
function moveL(s) {
|
| 1052 |
+
s.L = rotateFaceCW(s.L);
|
| 1053 |
+
const tmp = [s.U[0],s.U[3],s.U[6]];
|
| 1054 |
+
s.U[0]=s.B[8]; s.U[3]=s.B[5]; s.U[6]=s.B[2];
|
| 1055 |
+
s.B[8]=s.D[0]; s.B[5]=s.D[3]; s.B[2]=s.D[6];
|
| 1056 |
+
s.D[0]=s.F[0]; s.D[3]=s.F[3]; s.D[6]=s.F[6];
|
| 1057 |
+
s.F[0]=tmp[0]; s.F[3]=tmp[1]; s.F[6]=tmp[2];
|
| 1058 |
+
return s;
|
| 1059 |
+
}
|
| 1060 |
+
|
| 1061 |
+
function moveF(s) {
|
| 1062 |
+
s.F = rotateFaceCW(s.F);
|
| 1063 |
+
const tmp = [s.U[6],s.U[7],s.U[8]];
|
| 1064 |
+
s.U[6]=s.L[8]; s.U[7]=s.L[5]; s.U[8]=s.L[2];
|
| 1065 |
+
s.L[2]=s.D[0]; s.L[5]=s.D[1]; s.L[8]=s.D[2];
|
| 1066 |
+
s.D[0]=s.R[6]; s.D[1]=s.R[3]; s.D[2]=s.R[0];
|
| 1067 |
+
s.R[0]=tmp[0]; s.R[3]=tmp[1]; s.R[6]=tmp[2];
|
| 1068 |
+
return s;
|
| 1069 |
+
}
|
| 1070 |
+
|
| 1071 |
+
function moveB(s) {
|
| 1072 |
+
s.B = rotateFaceCW(s.B);
|
| 1073 |
+
const tmp = [s.U[0],s.U[1],s.U[2]];
|
| 1074 |
+
s.U[0]=s.R[2]; s.U[1]=s.R[5]; s.U[2]=s.R[8];
|
| 1075 |
+
s.R[2]=s.D[8]; s.R[5]=s.D[7]; s.R[8]=s.D[6];
|
| 1076 |
+
s.D[6]=s.L[0]; s.D[7]=s.L[3]; s.D[8]=s.L[6];
|
| 1077 |
+
s.L[0]=tmp[2]; s.L[3]=tmp[1]; s.L[6]=tmp[0];
|
| 1078 |
+
return s;
|
| 1079 |
+
}
|
| 1080 |
+
|
| 1081 |
+
// Compute the cube state after applying the inverse of an algorithm (setup state)
|
| 1082 |
+
function computeSetupState(notation) {
|
| 1083 |
+
const moves = parseAlgorithm(notation);
|
| 1084 |
+
if (moves.length === 0) return createSolvedState();
|
| 1085 |
+
|
| 1086 |
+
// Inverse: reverse order, invert each move
|
| 1087 |
+
const inverseMoves = moves.slice().reverse().map(invertMove);
|
| 1088 |
+
|
| 1089 |
+
let state = createSolvedState();
|
| 1090 |
+
for (const move of inverseMoves) {
|
| 1091 |
+
state = applyMoveToState(state, move);
|
| 1092 |
+
}
|
| 1093 |
+
return state;
|
| 1094 |
+
}
|
| 1095 |
+
|
| 1096 |
+
function generateTopViewSVG(section, caseName, caseDesc, firstAlgNotation) {
|
| 1097 |
+
// Only generate for OLL, PLL, COLL, ZBLL
|
| 1098 |
+
if (section === 'f2l') return '';
|
| 1099 |
+
if (!firstAlgNotation) return '';
|
| 1100 |
+
|
| 1101 |
+
const state = computeSetupState(firstAlgNotation);
|
| 1102 |
+
|
| 1103 |
+
const size = 80;
|
| 1104 |
+
const cell = size / 5;
|
| 1105 |
+
const topStart = cell;
|
| 1106 |
+
const r = 2;
|
| 1107 |
+
|
| 1108 |
+
let svg = '<svg width="' + size + '" height="' + size + '" viewBox="0 0 ' + size + ' ' + size + '" xmlns="http://www.w3.org/2000/svg">';
|
| 1109 |
+
svg += '<rect width="' + size + '" height="' + size + '" fill="#1a1a1a" rx="4"/>';
|
| 1110 |
+
|
| 1111 |
+
// Draw top face (3x3 grid) - state.U
|
| 1112 |
+
for (let row = 0; row < 3; row++) {
|
| 1113 |
+
for (let col = 0; col < 3; col++) {
|
| 1114 |
+
const color = DIAG_COLORS[state.U[row * 3 + col]] || '#444';
|
| 1115 |
+
const x = topStart + col * cell;
|
| 1116 |
+
const y = topStart + row * cell;
|
| 1117 |
+
svg += '<rect x="' + (x+1) + '" y="' + (y+1) + '" width="' + (cell-2) + '" height="' + (cell-2) + '" fill="' + color + '" rx="' + r + '"/>';
|
| 1118 |
+
}
|
| 1119 |
+
}
|
| 1120 |
+
|
| 1121 |
+
// Side stickers visible from top:
|
| 1122 |
+
// Top of diagram = Back face top row (reversed because viewing from opposite side): B[2], B[1], B[0]
|
| 1123 |
+
for (let i = 0; i < 3; i++) {
|
| 1124 |
+
const color = DIAG_COLORS[state.B[2 - i]] || '#444';
|
| 1125 |
+
const x = topStart + i * cell;
|
| 1126 |
+
const y = 0;
|
| 1127 |
+
svg += '<rect x="' + (x+1) + '" y="' + (y+1) + '" width="' + (cell-2) + '" height="' + (cell-2) + '" fill="' + color + '" rx="' + r + '"/>';
|
| 1128 |
+
}
|
| 1129 |
+
// Right of diagram = Right face top row (back to front): R[2], R[1], R[0]
|
| 1130 |
+
for (let i = 0; i < 3; i++) {
|
| 1131 |
+
const color = DIAG_COLORS[state.R[2 - i]] || '#444';
|
| 1132 |
+
const x = topStart + 3 * cell;
|
| 1133 |
+
const y = topStart + i * cell;
|
| 1134 |
+
svg += '<rect x="' + (x+1) + '" y="' + (y+1) + '" width="' + (cell-2) + '" height="' + (cell-2) + '" fill="' + color + '" rx="' + r + '"/>';
|
| 1135 |
+
}
|
| 1136 |
+
// Bottom of diagram = Front face top row: F[0], F[1], F[2]
|
| 1137 |
+
for (let i = 0; i < 3; i++) {
|
| 1138 |
+
const color = DIAG_COLORS[state.F[i]] || '#444';
|
| 1139 |
+
const x = topStart + i * cell;
|
| 1140 |
+
const y = topStart + 3 * cell;
|
| 1141 |
+
svg += '<rect x="' + (x+1) + '" y="' + (y+1) + '" width="' + (cell-2) + '" height="' + (cell-2) + '" fill="' + color + '" rx="' + r + '"/>';
|
| 1142 |
+
}
|
| 1143 |
+
// Left of diagram = Left face top row: L[0], L[1], L[2] (front to back)
|
| 1144 |
+
for (let i = 0; i < 3; i++) {
|
| 1145 |
+
const color = DIAG_COLORS[state.L[i]] || '#444';
|
| 1146 |
+
const x = 0;
|
| 1147 |
+
const y = topStart + i * cell;
|
| 1148 |
+
svg += '<rect x="' + (x+1) + '" y="' + (y+1) + '" width="' + (cell-2) + '" height="' + (cell-2) + '" fill="' + color + '" rx="' + r + '"/>';
|
| 1149 |
+
}
|
| 1150 |
+
|
| 1151 |
+
svg += '</svg>';
|
| 1152 |
+
return svg;
|
| 1153 |
+
}
|
| 1154 |
+
|
| 1155 |
+
function renderAlgorithms(section, filterGroup) {
|
| 1156 |
+
currentSection = section;
|
| 1157 |
+
const data = OH_ALGORITHMS[section];
|
| 1158 |
+
const container = document.getElementById('algorithm-section');
|
| 1159 |
+
|
| 1160 |
+
let html = `<h2>${data.title}</h2>`;
|
| 1161 |
+
html += `<p class="description">${data.description}</p>`;
|
| 1162 |
+
|
| 1163 |
+
// Add group filter tabs for ZBLL, COLL, and F2L
|
| 1164 |
+
if (section === 'zbll' || section === 'coll' || section === 'f2l') {
|
| 1165 |
+
const groups = [];
|
| 1166 |
+
const groupSet = new Set();
|
| 1167 |
+
for (const c of data.cases) {
|
| 1168 |
+
const g = c.case || c.name.split(' ')[0];
|
| 1169 |
+
if (!groupSet.has(g)) { groupSet.add(g); groups.push(g); }
|
| 1170 |
+
}
|
| 1171 |
+
html += '<div class="group-tabs">';
|
| 1172 |
+
html += `<button class="group-tab ${!filterGroup ? 'active' : ''}" onclick="renderAlgorithms('${section}')">All</button>`;
|
| 1173 |
+
for (const g of groups) {
|
| 1174 |
+
const active = filterGroup === g ? 'active' : '';
|
| 1175 |
+
html += `<button class="group-tab ${active}" onclick="renderAlgorithms('${section}','${g}')">${g}</button>`;
|
| 1176 |
+
}
|
| 1177 |
+
html += '</div>';
|
| 1178 |
+
}
|
| 1179 |
+
|
| 1180 |
+
// Filter cases by group if specified
|
| 1181 |
+
let cases = data.cases;
|
| 1182 |
+
if (filterGroup) {
|
| 1183 |
+
cases = data.cases.filter(c => (c.case || c.name.split(' ')[0]) === filterGroup);
|
| 1184 |
+
}
|
| 1185 |
+
|
| 1186 |
+
html += '<div class="alg-grid">';
|
| 1187 |
+
|
| 1188 |
+
for (const caseData of cases) {
|
| 1189 |
+
html += `<div class="alg-card">`;
|
| 1190 |
+
|
| 1191 |
+
// Top view diagram + case info in a row
|
| 1192 |
+
const firstAlg = caseData.algs[0] ? caseData.algs[0].notation : '';
|
| 1193 |
+
|
| 1194 |
+
// Generate VisualCube 3D image for F2L cases
|
| 1195 |
+
if (section === 'f2l' && firstAlg) {
|
| 1196 |
+
const vcAlg = firstAlg.replace(/\(/g, '').replace(/\)/g, '').replace(/\u2019/g, "'").replace(/\u2032/g, "'");
|
| 1197 |
+
const vcUrl = `https://visualcube.api.cubing.net/visualcube.php?fmt=svg&size=150&case=${encodeURIComponent(vcAlg)}&bg=t&cc=black`;
|
| 1198 |
+
html += `<div class="alg-card-header">`;
|
| 1199 |
+
html += `<div class="alg-diagram"><img src="${vcUrl}" alt="${caseData.name}" class="f2l-case-img" loading="lazy"></div>`;
|
| 1200 |
+
html += `<div class="alg-card-info">`;
|
| 1201 |
+
html += `<div class="case-name">${caseData.name}</div>`;
|
| 1202 |
+
html += `<h4>${caseData.case}</h4>`;
|
| 1203 |
+
html += `</div></div>`;
|
| 1204 |
+
} else if (section === 'f2l' && !firstAlg) {
|
| 1205 |
+
// Solved case (F2L 37)
|
| 1206 |
+
html += `<div class="alg-card-header">`;
|
| 1207 |
+
html += `<div class="alg-diagram"><img src="https://visualcube.api.cubing.net/visualcube.php?fmt=svg&size=150&bg=t&cc=black" alt="${caseData.name}" class="f2l-case-img" loading="lazy"></div>`;
|
| 1208 |
+
html += `<div class="alg-card-info">`;
|
| 1209 |
+
html += `<div class="case-name">${caseData.name}</div>`;
|
| 1210 |
+
html += `<h4>${caseData.case}</h4>`;
|
| 1211 |
+
html += `</div></div>`;
|
| 1212 |
+
} else {
|
| 1213 |
+
const diagram = generateTopViewSVG(section, caseData.name, caseData.case, firstAlg);
|
| 1214 |
+
if (diagram) {
|
| 1215 |
+
html += `<div class="alg-card-header">`;
|
| 1216 |
+
html += `<div class="alg-diagram">${diagram}</div>`;
|
| 1217 |
+
html += `<div class="alg-card-info">`;
|
| 1218 |
+
html += `<div class="case-name">${caseData.name}</div>`;
|
| 1219 |
+
html += `<h4>${caseData.case}</h4>`;
|
| 1220 |
+
html += `</div></div>`;
|
| 1221 |
+
} else {
|
| 1222 |
+
html += `<div class="case-name">${caseData.name}</div>`;
|
| 1223 |
+
html += `<h4>${caseData.case}</h4>`;
|
| 1224 |
+
}
|
| 1225 |
+
}
|
| 1226 |
+
|
| 1227 |
+
for (const alg of caseData.algs) {
|
| 1228 |
+
const escaped = alg.notation.replace(/'/g, "\\'").replace(/\u2019/g, "\\'");
|
| 1229 |
+
html += `<div class="alg-row">`;
|
| 1230 |
+
html += `<div class="alg-notation" onclick="setupAndSolve('${escaped}')" title="Click to setup case & watch the solve">${alg.notation}</div>`;
|
| 1231 |
+
html += `<div class="alg-meta">`;
|
| 1232 |
+
html += `<span>${alg.note}</span>`;
|
| 1233 |
+
html += `<span class="moves">${alg.moves} moves</span>`;
|
| 1234 |
+
html += `<button class="step-by-step-btn" onclick="startStepByStep('${escaped}')" title="Step through one move at a time">Step by Step</button>`;
|
| 1235 |
+
html += `</div>`;
|
| 1236 |
+
html += `</div>`;
|
| 1237 |
+
}
|
| 1238 |
+
|
| 1239 |
+
html += `</div>`;
|
| 1240 |
+
}
|
| 1241 |
+
|
| 1242 |
+
html += '</div>';
|
| 1243 |
+
container.innerHTML = html;
|
| 1244 |
+
}
|
| 1245 |
+
|
| 1246 |
+
// ============ NAVIGATION ============
|
| 1247 |
+
|
| 1248 |
+
function setupNavigation() {
|
| 1249 |
+
const navItems = document.querySelectorAll('.nav-item');
|
| 1250 |
+
|
| 1251 |
+
navItems.forEach(item => {
|
| 1252 |
+
item.addEventListener('click', () => {
|
| 1253 |
+
navItems.forEach(n => {
|
| 1254 |
+
n.classList.remove('active');
|
| 1255 |
+
n.setAttribute('aria-pressed', 'false');
|
| 1256 |
+
});
|
| 1257 |
+
item.classList.add('active');
|
| 1258 |
+
item.setAttribute('aria-pressed', 'true');
|
| 1259 |
+
|
| 1260 |
+
const section = item.getAttribute('data-section');
|
| 1261 |
+
renderAlgorithms(section);
|
| 1262 |
+
});
|
| 1263 |
+
|
| 1264 |
+
// Keyboard support
|
| 1265 |
+
item.addEventListener('keydown', (e) => {
|
| 1266 |
+
if (e.key === 'Enter' || e.key === ' ') {
|
| 1267 |
+
e.preventDefault();
|
| 1268 |
+
item.click();
|
| 1269 |
+
}
|
| 1270 |
+
});
|
| 1271 |
+
});
|
| 1272 |
+
}
|
| 1273 |
+
|
| 1274 |
+
// ============ KEYBOARD SHORTCUTS ============
|
| 1275 |
+
|
| 1276 |
+
document.addEventListener('keydown', (e) => {
|
| 1277 |
+
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
|
| 1278 |
+
|
| 1279 |
+
// Step mode: space or right arrow advances, left arrow goes back
|
| 1280 |
+
if (stepActive) {
|
| 1281 |
+
if (e.key === ' ' || e.key === 'ArrowRight' || e.key === 'Enter') {
|
| 1282 |
+
e.preventDefault();
|
| 1283 |
+
executeNextStep();
|
| 1284 |
+
return;
|
| 1285 |
+
}
|
| 1286 |
+
if (e.key === 'ArrowLeft') {
|
| 1287 |
+
e.preventDefault();
|
| 1288 |
+
executePrevStep();
|
| 1289 |
+
return;
|
| 1290 |
+
}
|
| 1291 |
+
if (e.key === 'Escape') {
|
| 1292 |
+
cancelStepMode();
|
| 1293 |
+
return;
|
| 1294 |
+
}
|
| 1295 |
+
}
|
| 1296 |
+
|
| 1297 |
+
const key = e.key.toLowerCase();
|
| 1298 |
+
const shift = e.shiftKey;
|
| 1299 |
+
|
| 1300 |
+
switch (key) {
|
| 1301 |
+
case 'r': doMove(shift ? 'Ri' : 'R'); break;
|
| 1302 |
+
case 'u': doMove(shift ? 'Ui' : 'U'); break;
|
| 1303 |
+
case 'f': doMove(shift ? 'Fi' : 'F'); break;
|
| 1304 |
+
case 'l': doMove(shift ? 'Li' : 'L'); break;
|
| 1305 |
+
case 'd': doMove(shift ? 'Di' : 'D'); break;
|
| 1306 |
+
case 'b': doMove(shift ? 'Bi' : 'B'); break;
|
| 1307 |
+
case 's': scrambleCube(); break;
|
| 1308 |
+
case 'escape': resetCube(); break;
|
| 1309 |
+
}
|
| 1310 |
+
});
|
| 1311 |
+
|
| 1312 |
+
// ============ STARTUP ============
|
| 1313 |
+
|
| 1314 |
+
function toggleMoveButtons() {
|
| 1315 |
+
const panel = document.getElementById('move-buttons');
|
| 1316 |
+
const btn = document.getElementById('toggle-moves-btn');
|
| 1317 |
+
if (panel.style.display === 'none') {
|
| 1318 |
+
panel.style.display = 'flex';
|
| 1319 |
+
btn.textContent = 'Moves ▲';
|
| 1320 |
+
} else {
|
| 1321 |
+
panel.style.display = 'none';
|
| 1322 |
+
btn.textContent = 'Moves ▼';
|
| 1323 |
+
}
|
| 1324 |
+
}
|
| 1325 |
+
|
| 1326 |
+
// ============ COLLAPSE / FULLSCREEN 3D VIEW ============
|
| 1327 |
+
|
| 1328 |
+
let cubePopWindow = null; // kept for compatibility with showStepPanel/hideStepPanel references
|
| 1329 |
+
|
| 1330 |
+
function toggleCollapse() {
|
| 1331 |
+
const cubeSection = document.getElementById('cube-section');
|
| 1332 |
+
const btn = document.getElementById('popout-btn');
|
| 1333 |
+
|
| 1334 |
+
if (cubeSection.classList.contains('collapsed')) {
|
| 1335 |
+
cubeSection.classList.remove('collapsed');
|
| 1336 |
+
btn.innerHTML = '▲ Hide';
|
| 1337 |
+
btn.title = 'Collapse 3D view for more algorithm space';
|
| 1338 |
+
onResize();
|
| 1339 |
+
} else {
|
| 1340 |
+
cubeSection.classList.remove('fullscreen');
|
| 1341 |
+
cubeSection.classList.add('collapsed');
|
| 1342 |
+
btn.innerHTML = '▼ Show';
|
| 1343 |
+
btn.title = 'Show 3D view';
|
| 1344 |
+
}
|
| 1345 |
+
}
|
| 1346 |
+
|
| 1347 |
+
function toggleFullscreen() {
|
| 1348 |
+
const cubeSection = document.getElementById('cube-section');
|
| 1349 |
+
const fsBtn = document.getElementById('fullscreen-btn');
|
| 1350 |
+
|
| 1351 |
+
if (cubeSection.classList.contains('fullscreen')) {
|
| 1352 |
+
cubeSection.classList.remove('fullscreen');
|
| 1353 |
+
fsBtn.innerHTML = '⛶ Full';
|
| 1354 |
+
fsBtn.title = 'Full screen 3D view';
|
| 1355 |
+
onResize();
|
| 1356 |
+
} else {
|
| 1357 |
+
cubeSection.classList.remove('collapsed');
|
| 1358 |
+
cubeSection.classList.add('fullscreen');
|
| 1359 |
+
fsBtn.innerHTML = '✖ Exit';
|
| 1360 |
+
fsBtn.title = 'Exit full screen';
|
| 1361 |
+
// Update canvas size for fullscreen
|
| 1362 |
+
const container = document.getElementById('cube-canvas').parentElement;
|
| 1363 |
+
camera.aspect = container.clientWidth / (window.innerHeight - 120);
|
| 1364 |
+
camera.updateProjectionMatrix();
|
| 1365 |
+
renderer.setSize(container.clientWidth, window.innerHeight - 120);
|
| 1366 |
+
// Also show the collapse button properly
|
| 1367 |
+
document.getElementById('popout-btn').innerHTML = '▲ Hide';
|
| 1368 |
+
}
|
| 1369 |
+
}
|
| 1370 |
+
|
| 1371 |
+
// Startup is handled by index.html after JSON files load
|
index.html
CHANGED
|
@@ -1,19 +1,708 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>One-Handed 3x3 Rubik's Cube - OH Algorithms</title>
|
| 7 |
+
<style>
|
| 8 |
+
* {
|
| 9 |
+
margin: 0;
|
| 10 |
+
padding: 0;
|
| 11 |
+
box-sizing: border-box;
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
body {
|
| 15 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| 16 |
+
background: #1a1a2e;
|
| 17 |
+
color: #e0e0e0;
|
| 18 |
+
overflow-x: hidden;
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
header {
|
| 22 |
+
background: linear-gradient(135deg, #16213e, #0f3460);
|
| 23 |
+
padding: 20px 40px;
|
| 24 |
+
text-align: center;
|
| 25 |
+
border-bottom: 2px solid #e94560;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
header h1 {
|
| 29 |
+
font-size: 2rem;
|
| 30 |
+
color: #fff;
|
| 31 |
+
text-shadow: 0 0 10px rgba(233, 69, 96, 0.5);
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
header p {
|
| 35 |
+
color: #aaa;
|
| 36 |
+
margin-top: 5px;
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
.container {
|
| 40 |
+
display: flex;
|
| 41 |
+
min-height: calc(100vh - 100px);
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
.sidebar {
|
| 45 |
+
width: 280px;
|
| 46 |
+
background: #16213e;
|
| 47 |
+
padding: 20px;
|
| 48 |
+
border-right: 1px solid #0f3460;
|
| 49 |
+
overflow-y: auto;
|
| 50 |
+
max-height: calc(100vh - 100px);
|
| 51 |
+
position: sticky;
|
| 52 |
+
top: 0;
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
.sidebar h3 {
|
| 56 |
+
color: #e94560;
|
| 57 |
+
margin-bottom: 15px;
|
| 58 |
+
font-size: 1.1rem;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
.nav-item {
|
| 62 |
+
padding: 12px 16px;
|
| 63 |
+
margin: 4px 0;
|
| 64 |
+
border-radius: 8px;
|
| 65 |
+
cursor: pointer;
|
| 66 |
+
transition: all 0.3s ease;
|
| 67 |
+
font-size: 0.95rem;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
.nav-item:hover {
|
| 71 |
+
background: #0f3460;
|
| 72 |
+
transform: translateX(5px);
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
.nav-item.active {
|
| 76 |
+
background: #e94560;
|
| 77 |
+
color: #fff;
|
| 78 |
+
font-weight: bold;
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
.main-content {
|
| 82 |
+
flex: 1;
|
| 83 |
+
display: flex;
|
| 84 |
+
flex-direction: column;
|
| 85 |
+
height: calc(100vh - 100px);
|
| 86 |
+
overflow: hidden;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
.cube-section {
|
| 90 |
+
display: flex;
|
| 91 |
+
justify-content: center;
|
| 92 |
+
align-items: center;
|
| 93 |
+
padding: 20px;
|
| 94 |
+
background: radial-gradient(ellipse at center, #1a1a35 0%, #0a0a18 100%);
|
| 95 |
+
border-bottom: 1px solid #333;
|
| 96 |
+
min-height: 420px;
|
| 97 |
+
position: relative;
|
| 98 |
+
flex-shrink: 0;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
.cube-section.collapsed {
|
| 102 |
+
min-height: 0;
|
| 103 |
+
height: 40px;
|
| 104 |
+
padding: 8px 20px;
|
| 105 |
+
justify-content: flex-start;
|
| 106 |
+
align-items: center;
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
.cube-section.collapsed canvas,
|
| 110 |
+
.cube-section.collapsed .controls,
|
| 111 |
+
.cube-section.collapsed .scramble-display,
|
| 112 |
+
.cube-section.collapsed .move-buttons,
|
| 113 |
+
.cube-section.collapsed #step-panel {
|
| 114 |
+
display: none !important;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
.cube-section.fullscreen {
|
| 118 |
+
position: fixed;
|
| 119 |
+
top: 0;
|
| 120 |
+
left: 0;
|
| 121 |
+
right: 0;
|
| 122 |
+
bottom: 0;
|
| 123 |
+
min-height: 100vh;
|
| 124 |
+
z-index: 999;
|
| 125 |
+
border: none;
|
| 126 |
+
padding: 10px;
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
.cube-section.fullscreen #cube-canvas {
|
| 130 |
+
height: calc(100vh - 120px);
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
.popout-btn {
|
| 134 |
+
position: absolute;
|
| 135 |
+
top: 10px;
|
| 136 |
+
right: 10px;
|
| 137 |
+
padding: 6px 14px;
|
| 138 |
+
border: 1px solid #4fc3f7;
|
| 139 |
+
border-radius: 6px;
|
| 140 |
+
background: rgba(15, 52, 96, 0.8);
|
| 141 |
+
color: #4fc3f7;
|
| 142 |
+
cursor: pointer;
|
| 143 |
+
font-size: 0.8rem;
|
| 144 |
+
z-index: 10;
|
| 145 |
+
transition: all 0.2s;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
.popout-btn:hover {
|
| 149 |
+
background: #4fc3f7;
|
| 150 |
+
color: #0a0a18;
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
.cube-section.collapsed .popout-btn {
|
| 154 |
+
position: static;
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
.fullscreen-btn {
|
| 158 |
+
position: absolute;
|
| 159 |
+
top: 10px;
|
| 160 |
+
right: 100px;
|
| 161 |
+
padding: 6px 14px;
|
| 162 |
+
border: 1px solid #2ecc71;
|
| 163 |
+
border-radius: 6px;
|
| 164 |
+
background: rgba(15, 52, 96, 0.8);
|
| 165 |
+
color: #2ecc71;
|
| 166 |
+
cursor: pointer;
|
| 167 |
+
font-size: 0.8rem;
|
| 168 |
+
z-index: 10;
|
| 169 |
+
transition: all 0.2s;
|
| 170 |
+
}
|
| 171 |
+
|
| 172 |
+
.fullscreen-btn:hover {
|
| 173 |
+
background: #2ecc71;
|
| 174 |
+
color: #0a0a18;
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
#cube-canvas {
|
| 178 |
+
width: 100%;
|
| 179 |
+
height: 400px;
|
| 180 |
+
border-radius: 12px;
|
| 181 |
+
display: block;
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
.controls {
|
| 185 |
+
position: absolute;
|
| 186 |
+
bottom: 20px;
|
| 187 |
+
left: 50%;
|
| 188 |
+
transform: translateX(-50%);
|
| 189 |
+
display: flex;
|
| 190 |
+
gap: 8px;
|
| 191 |
+
flex-wrap: wrap;
|
| 192 |
+
justify-content: center;
|
| 193 |
+
z-index: 10;
|
| 194 |
+
max-width: 600px;
|
| 195 |
+
}
|
| 196 |
+
|
| 197 |
+
.control-btn {
|
| 198 |
+
padding: 8px 14px;
|
| 199 |
+
border: none;
|
| 200 |
+
border-radius: 6px;
|
| 201 |
+
background: #0f3460;
|
| 202 |
+
color: #fff;
|
| 203 |
+
cursor: pointer;
|
| 204 |
+
font-size: 0.85rem;
|
| 205 |
+
transition: all 0.2s;
|
| 206 |
+
}
|
| 207 |
+
|
| 208 |
+
.control-btn:hover {
|
| 209 |
+
background: #e94560;
|
| 210 |
+
transform: scale(1.05);
|
| 211 |
+
}
|
| 212 |
+
|
| 213 |
+
.algorithm-section {
|
| 214 |
+
flex: 1;
|
| 215 |
+
padding: 30px;
|
| 216 |
+
overflow-y: auto;
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
.algorithm-section h2 {
|
| 220 |
+
color: #e94560;
|
| 221 |
+
margin-bottom: 10px;
|
| 222 |
+
font-size: 1.6rem;
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
.algorithm-section .description {
|
| 226 |
+
color: #888;
|
| 227 |
+
margin-bottom: 25px;
|
| 228 |
+
line-height: 1.6;
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
.alg-grid {
|
| 232 |
+
display: grid;
|
| 233 |
+
grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
|
| 234 |
+
gap: 16px;
|
| 235 |
+
}
|
| 236 |
+
|
| 237 |
+
.alg-card {
|
| 238 |
+
background: #16213e;
|
| 239 |
+
border: 1px solid #0f3460;
|
| 240 |
+
border-radius: 12px;
|
| 241 |
+
padding: 18px;
|
| 242 |
+
transition: all 0.3s ease;
|
| 243 |
+
}
|
| 244 |
+
|
| 245 |
+
.alg-card:hover {
|
| 246 |
+
border-color: #e94560;
|
| 247 |
+
transform: translateY(-2px);
|
| 248 |
+
box-shadow: 0 4px 15px rgba(233, 69, 96, 0.2);
|
| 249 |
+
}
|
| 250 |
+
|
| 251 |
+
.alg-card h4 {
|
| 252 |
+
color: #fff;
|
| 253 |
+
margin-bottom: 8px;
|
| 254 |
+
font-size: 1rem;
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
.alg-card .case-name {
|
| 258 |
+
color: #e94560;
|
| 259 |
+
font-weight: bold;
|
| 260 |
+
font-size: 0.9rem;
|
| 261 |
+
margin-bottom: 6px;
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
.alg-card-header {
|
| 265 |
+
display: flex;
|
| 266 |
+
align-items: center;
|
| 267 |
+
gap: 14px;
|
| 268 |
+
margin-bottom: 10px;
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
.alg-diagram {
|
| 272 |
+
flex-shrink: 0;
|
| 273 |
+
}
|
| 274 |
+
|
| 275 |
+
.alg-diagram svg {
|
| 276 |
+
display: block;
|
| 277 |
+
border-radius: 4px;
|
| 278 |
+
}
|
| 279 |
+
|
| 280 |
+
.alg-diagram .f2l-case-img {
|
| 281 |
+
display: block;
|
| 282 |
+
width: 120px;
|
| 283 |
+
height: 120px;
|
| 284 |
+
border-radius: 4px;
|
| 285 |
+
}
|
| 286 |
+
|
| 287 |
+
.alg-card-info {
|
| 288 |
+
flex: 1;
|
| 289 |
+
min-width: 0;
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
.alg-card-info .case-name {
|
| 293 |
+
color: #e94560;
|
| 294 |
+
font-weight: bold;
|
| 295 |
+
font-size: 0.9rem;
|
| 296 |
+
margin-bottom: 4px;
|
| 297 |
+
}
|
| 298 |
+
|
| 299 |
+
.alg-card-info h4 {
|
| 300 |
+
color: #fff;
|
| 301 |
+
font-size: 0.95rem;
|
| 302 |
+
margin: 0;
|
| 303 |
+
}
|
| 304 |
+
|
| 305 |
+
.alg-notation {
|
| 306 |
+
font-family: 'Courier New', monospace;
|
| 307 |
+
background: #0a0a1a;
|
| 308 |
+
padding: 10px 14px;
|
| 309 |
+
border-radius: 6px;
|
| 310 |
+
font-size: 0.85rem;
|
| 311 |
+
color: #4fc3f7;
|
| 312 |
+
margin: 6px 0;
|
| 313 |
+
word-break: break-all;
|
| 314 |
+
cursor: pointer;
|
| 315 |
+
transition: background 0.2s;
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
.alg-notation:hover {
|
| 319 |
+
background: #1a1a3a;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
.alg-notation:hover::after {
|
| 323 |
+
content: ' [click to setup & solve]';
|
| 324 |
+
color: #e94560;
|
| 325 |
+
font-size: 0.7rem;
|
| 326 |
+
}
|
| 327 |
+
|
| 328 |
+
.alg-meta {
|
| 329 |
+
display: flex;
|
| 330 |
+
justify-content: space-between;
|
| 331 |
+
align-items: center;
|
| 332 |
+
margin-top: 8px;
|
| 333 |
+
font-size: 0.8rem;
|
| 334 |
+
color: #666;
|
| 335 |
+
}
|
| 336 |
+
|
| 337 |
+
.alg-meta .moves {
|
| 338 |
+
background: #0f3460;
|
| 339 |
+
padding: 2px 8px;
|
| 340 |
+
border-radius: 4px;
|
| 341 |
+
color: #4fc3f7;
|
| 342 |
+
}
|
| 343 |
+
|
| 344 |
+
.info-badge {
|
| 345 |
+
display: inline-block;
|
| 346 |
+
background: #e94560;
|
| 347 |
+
color: #fff;
|
| 348 |
+
padding: 2px 8px;
|
| 349 |
+
border-radius: 10px;
|
| 350 |
+
font-size: 0.75rem;
|
| 351 |
+
margin-left: 8px;
|
| 352 |
+
}
|
| 353 |
+
|
| 354 |
+
.scramble-display {
|
| 355 |
+
position: absolute;
|
| 356 |
+
top: 15px;
|
| 357 |
+
left: 50%;
|
| 358 |
+
transform: translateX(-50%);
|
| 359 |
+
background: rgba(15, 52, 96, 0.9);
|
| 360 |
+
padding: 8px 16px;
|
| 361 |
+
border-radius: 6px;
|
| 362 |
+
font-family: 'Courier New', monospace;
|
| 363 |
+
font-size: 0.9rem;
|
| 364 |
+
color: #4fc3f7;
|
| 365 |
+
z-index: 10;
|
| 366 |
+
}
|
| 367 |
+
|
| 368 |
+
.sub-section {
|
| 369 |
+
margin-bottom: 30px;
|
| 370 |
+
}
|
| 371 |
+
|
| 372 |
+
.sub-section h3 {
|
| 373 |
+
color: #fff;
|
| 374 |
+
margin-bottom: 12px;
|
| 375 |
+
padding-bottom: 6px;
|
| 376 |
+
border-bottom: 1px solid #333;
|
| 377 |
+
}
|
| 378 |
+
|
| 379 |
+
@media (max-width: 900px) {
|
| 380 |
+
.container {
|
| 381 |
+
flex-direction: column;
|
| 382 |
+
}
|
| 383 |
+
.sidebar {
|
| 384 |
+
width: 100%;
|
| 385 |
+
max-height: 200px;
|
| 386 |
+
position: relative;
|
| 387 |
+
display: flex;
|
| 388 |
+
flex-wrap: wrap;
|
| 389 |
+
gap: 8px;
|
| 390 |
+
align-items: center;
|
| 391 |
+
}
|
| 392 |
+
.sidebar h3:last-of-type, .sidebar p, .sidebar hr {
|
| 393 |
+
display: none;
|
| 394 |
+
}
|
| 395 |
+
.alg-grid {
|
| 396 |
+
grid-template-columns: 1fr;
|
| 397 |
+
}
|
| 398 |
+
.cube-section {
|
| 399 |
+
min-height: 350px;
|
| 400 |
+
}
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
/* Group filter tabs for ZBLL/COLL */
|
| 404 |
+
.group-tabs {
|
| 405 |
+
display: flex;
|
| 406 |
+
gap: 6px;
|
| 407 |
+
flex-wrap: wrap;
|
| 408 |
+
margin-bottom: 20px;
|
| 409 |
+
padding-bottom: 15px;
|
| 410 |
+
border-bottom: 1px solid #333;
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
.group-tab {
|
| 414 |
+
padding: 8px 16px;
|
| 415 |
+
border: 1px solid #0f3460;
|
| 416 |
+
border-radius: 6px;
|
| 417 |
+
background: #0f0f23;
|
| 418 |
+
color: #888;
|
| 419 |
+
cursor: pointer;
|
| 420 |
+
font-size: 0.85rem;
|
| 421 |
+
transition: all 0.2s;
|
| 422 |
+
}
|
| 423 |
+
|
| 424 |
+
.group-tab:hover {
|
| 425 |
+
background: #0f3460;
|
| 426 |
+
color: #fff;
|
| 427 |
+
}
|
| 428 |
+
|
| 429 |
+
.group-tab.active {
|
| 430 |
+
background: #e94560;
|
| 431 |
+
color: #fff;
|
| 432 |
+
border-color: #e94560;
|
| 433 |
+
font-weight: bold;
|
| 434 |
+
}
|
| 435 |
+
|
| 436 |
+
/* Step-by-step button in algorithm cards */
|
| 437 |
+
.step-by-step-btn {
|
| 438 |
+
padding: 3px 10px;
|
| 439 |
+
border: 1px solid #4fc3f7;
|
| 440 |
+
border-radius: 4px;
|
| 441 |
+
background: transparent;
|
| 442 |
+
color: #4fc3f7;
|
| 443 |
+
cursor: pointer;
|
| 444 |
+
font-size: 0.75rem;
|
| 445 |
+
transition: all 0.2s;
|
| 446 |
+
white-space: nowrap;
|
| 447 |
+
}
|
| 448 |
+
|
| 449 |
+
.step-by-step-btn:hover {
|
| 450 |
+
background: #4fc3f7;
|
| 451 |
+
color: #0a0a1a;
|
| 452 |
+
}
|
| 453 |
+
|
| 454 |
+
/* Step panel overlay on cube */
|
| 455 |
+
#step-panel {
|
| 456 |
+
display: none;
|
| 457 |
+
position: absolute;
|
| 458 |
+
top: 15px;
|
| 459 |
+
right: 15px;
|
| 460 |
+
left: auto;
|
| 461 |
+
bottom: auto;
|
| 462 |
+
transform: none;
|
| 463 |
+
background: rgba(10, 10, 30, 0.95);
|
| 464 |
+
border: 1px solid #4fc3f7;
|
| 465 |
+
border-radius: 12px;
|
| 466 |
+
padding: 0;
|
| 467 |
+
z-index: 20;
|
| 468 |
+
flex-direction: column;
|
| 469 |
+
align-items: center;
|
| 470 |
+
gap: 12px;
|
| 471 |
+
min-width: 280px;
|
| 472 |
+
max-width: 40%;
|
| 473 |
+
backdrop-filter: blur(8px);
|
| 474 |
+
cursor: default;
|
| 475 |
+
user-select: none;
|
| 476 |
+
}
|
| 477 |
+
|
| 478 |
+
#step-panel .drag-handle {
|
| 479 |
+
width: 100%;
|
| 480 |
+
padding: 8px 16px;
|
| 481 |
+
cursor: grab;
|
| 482 |
+
background: rgba(79, 195, 247, 0.15);
|
| 483 |
+
border-radius: 12px 12px 0 0;
|
| 484 |
+
text-align: center;
|
| 485 |
+
font-size: 0.75rem;
|
| 486 |
+
color: #4fc3f7;
|
| 487 |
+
border-bottom: 1px solid rgba(79, 195, 247, 0.2);
|
| 488 |
+
}
|
| 489 |
+
|
| 490 |
+
#step-panel .drag-handle:active {
|
| 491 |
+
cursor: grabbing;
|
| 492 |
+
}
|
| 493 |
+
|
| 494 |
+
#step-panel .step-content {
|
| 495 |
+
padding: 14px 20px;
|
| 496 |
+
display: flex;
|
| 497 |
+
flex-direction: column;
|
| 498 |
+
align-items: center;
|
| 499 |
+
gap: 12px;
|
| 500 |
+
}
|
| 501 |
+
|
| 502 |
+
.step-info {
|
| 503 |
+
text-align: center;
|
| 504 |
+
width: 100%;
|
| 505 |
+
}
|
| 506 |
+
|
| 507 |
+
.step-counter {
|
| 508 |
+
font-size: 0.85rem;
|
| 509 |
+
color: #888;
|
| 510 |
+
margin-bottom: 8px;
|
| 511 |
+
}
|
| 512 |
+
|
| 513 |
+
.step-moves-display {
|
| 514 |
+
font-family: 'Courier New', monospace;
|
| 515 |
+
font-size: 1rem;
|
| 516 |
+
line-height: 1.8;
|
| 517 |
+
word-wrap: break-word;
|
| 518 |
+
}
|
| 519 |
+
|
| 520 |
+
.step-done {
|
| 521 |
+
color: #555;
|
| 522 |
+
text-decoration: line-through;
|
| 523 |
+
}
|
| 524 |
+
|
| 525 |
+
.step-current {
|
| 526 |
+
color: #fff;
|
| 527 |
+
background: #e94560;
|
| 528 |
+
padding: 2px 6px;
|
| 529 |
+
border-radius: 4px;
|
| 530 |
+
font-weight: bold;
|
| 531 |
+
font-size: 1.1rem;
|
| 532 |
+
}
|
| 533 |
+
|
| 534 |
+
.step-pending {
|
| 535 |
+
color: #4fc3f7;
|
| 536 |
+
}
|
| 537 |
+
|
| 538 |
+
.step-buttons {
|
| 539 |
+
display: flex;
|
| 540 |
+
gap: 10px;
|
| 541 |
+
}
|
| 542 |
+
|
| 543 |
+
.step-btn {
|
| 544 |
+
padding: 8px 18px;
|
| 545 |
+
border: none;
|
| 546 |
+
border-radius: 6px;
|
| 547 |
+
cursor: pointer;
|
| 548 |
+
font-size: 0.9rem;
|
| 549 |
+
font-weight: bold;
|
| 550 |
+
transition: all 0.2s;
|
| 551 |
+
}
|
| 552 |
+
|
| 553 |
+
.step-btn-next {
|
| 554 |
+
background: #e94560;
|
| 555 |
+
color: #fff;
|
| 556 |
+
}
|
| 557 |
+
|
| 558 |
+
.step-btn-next:hover {
|
| 559 |
+
background: #ff6b85;
|
| 560 |
+
transform: scale(1.05);
|
| 561 |
+
}
|
| 562 |
+
|
| 563 |
+
.step-btn-prev {
|
| 564 |
+
background: #0f3460;
|
| 565 |
+
color: #4fc3f7;
|
| 566 |
+
border: 1px solid #4fc3f7;
|
| 567 |
+
}
|
| 568 |
+
|
| 569 |
+
.step-btn-prev:hover {
|
| 570 |
+
background: #4fc3f7;
|
| 571 |
+
color: #0a0a1a;
|
| 572 |
+
}
|
| 573 |
+
|
| 574 |
+
.step-btn-done {
|
| 575 |
+
background: #2ecc71;
|
| 576 |
+
color: #fff;
|
| 577 |
+
}
|
| 578 |
+
|
| 579 |
+
.step-btn-cancel {
|
| 580 |
+
background: #333;
|
| 581 |
+
color: #aaa;
|
| 582 |
+
border: 1px solid #555;
|
| 583 |
+
}
|
| 584 |
+
|
| 585 |
+
.step-btn-cancel:hover {
|
| 586 |
+
background: #555;
|
| 587 |
+
color: #fff;
|
| 588 |
+
}
|
| 589 |
+
</style>
|
| 590 |
+
</head>
|
| 591 |
+
<body>
|
| 592 |
+
<header>
|
| 593 |
+
<h1>🧊 One-Handed 3x3 Rubik's Cube</h1>
|
| 594 |
+
<p>Interactive 3D Visualization & OH Algorithm Reference</p>
|
| 595 |
+
</header>
|
| 596 |
+
|
| 597 |
+
<div class="container">
|
| 598 |
+
<nav class="sidebar" role="navigation" aria-label="Algorithm categories">
|
| 599 |
+
<h3>📚 Algorithm Sets</h3>
|
| 600 |
+
<div class="nav-item active" data-section="f2l" tabindex="0" role="button" aria-pressed="true">F2L <span class="info-badge">42 cases</span></div>
|
| 601 |
+
<div class="nav-item" data-section="oll" tabindex="0" role="button" aria-pressed="false">OLL <span class="info-badge">57 cases</span></div>
|
| 602 |
+
<div class="nav-item" data-section="pll" tabindex="0" role="button" aria-pressed="false">PLL <span class="info-badge">21 cases</span></div>
|
| 603 |
+
<div class="nav-item" data-section="coll" tabindex="0" role="button" aria-pressed="false">COLL <span class="info-badge">40 cases</span></div>
|
| 604 |
+
<div class="nav-item" data-section="zbll" tabindex="0" role="button" aria-pressed="false">ZBLL <span class="info-badge">subset</span></div>
|
| 605 |
+
<hr style="border-color: #333; margin: 20px 0;">
|
| 606 |
+
<h3>ℹ️ Tips</h3>
|
| 607 |
+
<p style="font-size:0.85rem; color:#888; line-height:1.5;">
|
| 608 |
+
• Click algorithm: auto setup & solve<br>
|
| 609 |
+
• "Step by Step": one move at a time<br>
|
| 610 |
+
• Space/Arrow to advance steps<br>
|
| 611 |
+
• Drag to rotate camera<br>
|
| 612 |
+
• Scroll to zoom<br>
|
| 613 |
+
• Keyboard: R/U/F/L/D/B (Shift=inverse)
|
| 614 |
+
</p>
|
| 615 |
+
<div style="margin-top: 20px; padding-top: 15px; border-top: 1px solid #333; font-size: 0.8rem; color: #666; text-align: center;">
|
| 616 |
+
Created by Andy Kong
|
| 617 |
+
</div>
|
| 618 |
+
<div style="margin-top: 10px; text-align: center;">
|
| 619 |
+
<button onclick="document.getElementById('about-modal').style.display='flex'" style="padding: 6px 16px; border: 1px solid #4fc3f7; border-radius: 6px; background: transparent; color: #4fc3f7; cursor: pointer; font-size: 0.8rem;">About</button>
|
| 620 |
+
</div>
|
| 621 |
+
</nav>
|
| 622 |
+
|
| 623 |
+
<div class="main-content">
|
| 624 |
+
<div class="cube-section" id="cube-section">
|
| 625 |
+
<button class="fullscreen-btn" id="fullscreen-btn" onclick="toggleFullscreen()" title="Full screen 3D view">⛶ Full</button>
|
| 626 |
+
<button class="popout-btn" id="popout-btn" onclick="toggleCollapse()" title="Collapse 3D view for more algorithm space">▲ Hide</button>
|
| 627 |
+
<div class="scramble-display" id="scramble-display">Drag to rotate • Scroll to zoom</div>
|
| 628 |
+
<canvas id="cube-canvas"></canvas>
|
| 629 |
+
<div class="controls">
|
| 630 |
+
<button class="control-btn" style="background:#333;border:1px solid #4fc3f7;color:#4fc3f7" onclick="toggleMoveButtons()" id="toggle-moves-btn">Moves ▼</button>
|
| 631 |
+
<button class="control-btn" style="background:#e94560" onclick="scrambleCube()" aria-label="Scramble cube">Scramble</button>
|
| 632 |
+
<button class="control-btn" style="background:#2ecc71" onclick="resetCube()" aria-label="Reset cube">Reset</button>
|
| 633 |
+
</div>
|
| 634 |
+
<div class="controls move-buttons" id="move-buttons" style="bottom: 60px; display: none;">
|
| 635 |
+
<button class="control-btn" onclick="doMove('R')">R</button>
|
| 636 |
+
<button class="control-btn" onclick="doMove('Ri')">R'</button>
|
| 637 |
+
<button class="control-btn" onclick="doMove('U')">U</button>
|
| 638 |
+
<button class="control-btn" onclick="doMove('Ui')">U'</button>
|
| 639 |
+
<button class="control-btn" onclick="doMove('F')">F</button>
|
| 640 |
+
<button class="control-btn" onclick="doMove('Fi')">F'</button>
|
| 641 |
+
<button class="control-btn" onclick="doMove('L')">L</button>
|
| 642 |
+
<button class="control-btn" onclick="doMove('Li')">L'</button>
|
| 643 |
+
<button class="control-btn" onclick="doMove('D')">D</button>
|
| 644 |
+
<button class="control-btn" onclick="doMove('Di')">D'</button>
|
| 645 |
+
<button class="control-btn" onclick="doMove('B')">B</button>
|
| 646 |
+
<button class="control-btn" onclick="doMove('Bi')">B'</button>
|
| 647 |
+
<button class="control-btn" onclick="doMove('r')">r</button>
|
| 648 |
+
<button class="control-btn" onclick="doMove('ri')">r'</button>
|
| 649 |
+
<button class="control-btn" onclick="doMove('u')">u</button>
|
| 650 |
+
<button class="control-btn" onclick="doMove('ui')">u'</button>
|
| 651 |
+
<button class="control-btn" onclick="doMove('l')">l</button>
|
| 652 |
+
<button class="control-btn" onclick="doMove('li')">l'</button>
|
| 653 |
+
<button class="control-btn" onclick="doMove('x')">x</button>
|
| 654 |
+
<button class="control-btn" onclick="doMove('xi')">x'</button>
|
| 655 |
+
<button class="control-btn" onclick="doMove('y')">y</button>
|
| 656 |
+
<button class="control-btn" onclick="doMove('yi')">y'</button>
|
| 657 |
+
<button class="control-btn" onclick="doMove('z')">z</button>
|
| 658 |
+
<button class="control-btn" onclick="doMove('zi')">z'</button>
|
| 659 |
+
</div>
|
| 660 |
+
</div>
|
| 661 |
+
|
| 662 |
+
<div class="algorithm-section" id="algorithm-section">
|
| 663 |
+
<!-- Algorithms rendered by JS -->
|
| 664 |
+
</div>
|
| 665 |
+
</div>
|
| 666 |
+
</div>
|
| 667 |
+
|
| 668 |
+
<div id="about-modal" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.8); z-index:1000; justify-content:center; align-items:center;">
|
| 669 |
+
<div style="background:#16213e; border:1px solid #4fc3f7; border-radius:12px; padding:30px; max-width:600px; width:90%; max-height:80vh; overflow-y:auto;">
|
| 670 |
+
<h2 style="color:#e94560; margin-bottom:15px;">About This App</h2>
|
| 671 |
+
<p style="color:#ccc; line-height:1.7; margin-bottom:15px;">
|
| 672 |
+
This is an interactive 3D visualization and algorithm reference for <strong>one-handed (OH) 3x3 Rubik's Cube solving</strong>. It includes algorithms for F2L, OLL, PLL, COLL, and ZBLL — all optimized for one-handed execution using primarily R, U, and F moves.
|
| 673 |
+
</p>
|
| 674 |
+
<h3 style="color:#4fc3f7; margin-bottom:10px;">Algorithm Sources</h3>
|
| 675 |
+
<ul style="color:#aaa; line-height:2; list-style:none; padding:0;">
|
| 676 |
+
<li>• <a href="https://www.speedsolving.com/wiki/index.php/First_Two_Layers" target="_blank" style="color:#4fc3f7;">Speedsolving.com Wiki - F2L Algorithms</a></li>
|
| 677 |
+
<li>• <a href="https://cubeskills.com/uploads/pdf/tutorials/onehanded-oll-algorithms.pdf" target="_blank" style="color:#4fc3f7;">CubeSkills - OH OLL Algorithms (PDF)</a></li>
|
| 678 |
+
<li>• <a href="https://www.cubeskills.com/uploads/pdf/tutorials/onehanded-pll-algorithms.pdf" target="_blank" style="color:#4fc3f7;">CubeSkills - OH PLL Algorithms (PDF)</a></li>
|
| 679 |
+
<li>• <a href="https://www.cubeskills.com/uploads/pdf/tutorials/onehanded-coll-algorithms.pdf" target="_blank" style="color:#4fc3f7;">CubeSkills - OH COLL Algorithms (PDF)</a></li>
|
| 680 |
+
<li>• <a href="https://cubingapp.com/algorithms/ZBLL" target="_blank" style="color:#4fc3f7;">CubingApp - ZBLL Algorithms</a></li>
|
| 681 |
+
</ul>
|
| 682 |
+
<p style="color:#888; margin-top:15px; font-size:0.85rem;">
|
| 683 |
+
One-handed solving uses the same CFOP method as two-handed, but algorithms are chosen for ergonomics with a single hand. Common techniques include table-assisted solving and z-rotation for better grip.
|
| 684 |
+
</p>
|
| 685 |
+
<div style="text-align:center; margin-top:20px;">
|
| 686 |
+
<button onclick="document.getElementById('about-modal').style.display='none'" style="padding:10px 30px; background:#e94560; color:#fff; border:none; border-radius:6px; cursor:pointer; font-size:0.9rem;">Close</button>
|
| 687 |
+
</div>
|
| 688 |
+
</div>
|
| 689 |
+
</div>
|
| 690 |
+
|
| 691 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
| 692 |
+
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script>
|
| 693 |
+
<script src="app.js"></script>
|
| 694 |
+
<script src="json/f2l.json.js"></script>
|
| 695 |
+
<script src="json/oll.json.js"></script>
|
| 696 |
+
<script src="json/pll.json.js"></script>
|
| 697 |
+
<script src="json/coll.json.js"></script>
|
| 698 |
+
<script src="json/zbll.json.js"></script>
|
| 699 |
+
<script>
|
| 700 |
+
// OH_ALGORITHMS is assembled from the .json.js files above
|
| 701 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 702 |
+
init();
|
| 703 |
+
setupNavigation();
|
| 704 |
+
renderAlgorithms('f2l');
|
| 705 |
+
});
|
| 706 |
+
</script>
|
| 707 |
+
</body>
|
| 708 |
+
</html>
|
json/coll.json.js
ADDED
|
@@ -0,0 +1,424 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
OH_ALGORITHMS.coll = {
|
| 2 |
+
"title": "OH COLL - Corners of Last Layer",
|
| 3 |
+
"description": "COLL algorithms from CubeSkills OH COLL PDF by Feliks Zemdegs. Solves corner orientation and permutation while edges are oriented.",
|
| 4 |
+
"cases": [
|
| 5 |
+
{
|
| 6 |
+
"name": "S 1",
|
| 7 |
+
"case": "Sune",
|
| 8 |
+
"algs": [
|
| 9 |
+
{
|
| 10 |
+
"notation": "R U R' U R U2 R'",
|
| 11 |
+
"moves": 7,
|
| 12 |
+
"note": "Sune"
|
| 13 |
+
}
|
| 14 |
+
]
|
| 15 |
+
},
|
| 16 |
+
{
|
| 17 |
+
"name": "S 2",
|
| 18 |
+
"case": "Sune",
|
| 19 |
+
"algs": [
|
| 20 |
+
{
|
| 21 |
+
"notation": "R' U2 L U' R U L' U R' U R",
|
| 22 |
+
"moves": 11,
|
| 23 |
+
"note": "COLL"
|
| 24 |
+
}
|
| 25 |
+
]
|
| 26 |
+
},
|
| 27 |
+
{
|
| 28 |
+
"name": "S 3",
|
| 29 |
+
"case": "Sune",
|
| 30 |
+
"algs": [
|
| 31 |
+
{
|
| 32 |
+
"notation": "R U' L' U R' U' L",
|
| 33 |
+
"moves": 7,
|
| 34 |
+
"note": "COLL"
|
| 35 |
+
}
|
| 36 |
+
]
|
| 37 |
+
},
|
| 38 |
+
{
|
| 39 |
+
"name": "S 4",
|
| 40 |
+
"case": "Sune",
|
| 41 |
+
"algs": [
|
| 42 |
+
{
|
| 43 |
+
"notation": "L' R U R' U' L U2 R U2 R'",
|
| 44 |
+
"moves": 10,
|
| 45 |
+
"note": "COLL"
|
| 46 |
+
}
|
| 47 |
+
]
|
| 48 |
+
},
|
| 49 |
+
{
|
| 50 |
+
"name": "S 5",
|
| 51 |
+
"case": "Sune",
|
| 52 |
+
"algs": [
|
| 53 |
+
{
|
| 54 |
+
"notation": "L' U2 L U2 R U' L' U L R'",
|
| 55 |
+
"moves": 10,
|
| 56 |
+
"note": "COLL"
|
| 57 |
+
}
|
| 58 |
+
]
|
| 59 |
+
},
|
| 60 |
+
{
|
| 61 |
+
"name": "S 6",
|
| 62 |
+
"case": "Sune",
|
| 63 |
+
"algs": [
|
| 64 |
+
{
|
| 65 |
+
"notation": "y' R U R' U R U' R D R' U' R D' R2",
|
| 66 |
+
"moves": 13,
|
| 67 |
+
"note": "COLL"
|
| 68 |
+
}
|
| 69 |
+
]
|
| 70 |
+
},
|
| 71 |
+
{
|
| 72 |
+
"name": "AS 1",
|
| 73 |
+
"case": "Antisune",
|
| 74 |
+
"algs": [
|
| 75 |
+
{
|
| 76 |
+
"notation": "y R U2 R' U' R U' R'",
|
| 77 |
+
"moves": 7,
|
| 78 |
+
"note": "Antisune"
|
| 79 |
+
}
|
| 80 |
+
]
|
| 81 |
+
},
|
| 82 |
+
{
|
| 83 |
+
"name": "AS 2",
|
| 84 |
+
"case": "Antisune",
|
| 85 |
+
"algs": [
|
| 86 |
+
{
|
| 87 |
+
"notation": "y2 R' U' R U' L U' R' U L' U2 R",
|
| 88 |
+
"moves": 11,
|
| 89 |
+
"note": "COLL"
|
| 90 |
+
}
|
| 91 |
+
]
|
| 92 |
+
},
|
| 93 |
+
{
|
| 94 |
+
"name": "AS 3",
|
| 95 |
+
"case": "Antisune",
|
| 96 |
+
"algs": [
|
| 97 |
+
{
|
| 98 |
+
"notation": "y2 L' U R U' L U R'",
|
| 99 |
+
"moves": 7,
|
| 100 |
+
"note": "COLL"
|
| 101 |
+
}
|
| 102 |
+
]
|
| 103 |
+
},
|
| 104 |
+
{
|
| 105 |
+
"name": "AS 4",
|
| 106 |
+
"case": "Antisune",
|
| 107 |
+
"algs": [
|
| 108 |
+
{
|
| 109 |
+
"notation": "y2 R L' U' L U R' U2 L' U2 L",
|
| 110 |
+
"moves": 10,
|
| 111 |
+
"note": "COLL"
|
| 112 |
+
}
|
| 113 |
+
]
|
| 114 |
+
},
|
| 115 |
+
{
|
| 116 |
+
"name": "AS 5",
|
| 117 |
+
"case": "Antisune",
|
| 118 |
+
"algs": [
|
| 119 |
+
{
|
| 120 |
+
"notation": "y2 R U2 R' U2 L' U R U' R' L",
|
| 121 |
+
"moves": 10,
|
| 122 |
+
"note": "COLL"
|
| 123 |
+
}
|
| 124 |
+
]
|
| 125 |
+
},
|
| 126 |
+
{
|
| 127 |
+
"name": "AS 6",
|
| 128 |
+
"case": "Antisune",
|
| 129 |
+
"algs": [
|
| 130 |
+
{
|
| 131 |
+
"notation": "y R' U' R U' R' U R' D' R U R' D R2",
|
| 132 |
+
"moves": 13,
|
| 133 |
+
"note": "COLL"
|
| 134 |
+
}
|
| 135 |
+
]
|
| 136 |
+
},
|
| 137 |
+
{
|
| 138 |
+
"name": "L 1",
|
| 139 |
+
"case": "L",
|
| 140 |
+
"algs": [
|
| 141 |
+
{
|
| 142 |
+
"notation": "y R U2 R' U' R U R' U' R U R' U' R U' R'",
|
| 143 |
+
"moves": 15,
|
| 144 |
+
"note": "COLL"
|
| 145 |
+
}
|
| 146 |
+
]
|
| 147 |
+
},
|
| 148 |
+
{
|
| 149 |
+
"name": "L 2",
|
| 150 |
+
"case": "L",
|
| 151 |
+
"algs": [
|
| 152 |
+
{
|
| 153 |
+
"notation": "y2 R U2 L' U L U2 R' L' U L",
|
| 154 |
+
"moves": 10,
|
| 155 |
+
"note": "COLL"
|
| 156 |
+
}
|
| 157 |
+
]
|
| 158 |
+
},
|
| 159 |
+
{
|
| 160 |
+
"name": "L 3",
|
| 161 |
+
"case": "L",
|
| 162 |
+
"algs": [
|
| 163 |
+
{
|
| 164 |
+
"notation": "y' R U2 R D R' U2 R D' R2",
|
| 165 |
+
"moves": 9,
|
| 166 |
+
"note": "COLL"
|
| 167 |
+
}
|
| 168 |
+
]
|
| 169 |
+
},
|
| 170 |
+
{
|
| 171 |
+
"name": "L 4",
|
| 172 |
+
"case": "L",
|
| 173 |
+
"algs": [
|
| 174 |
+
{
|
| 175 |
+
"notation": "y2 R' U2 R' D' R U2 R' D R2",
|
| 176 |
+
"moves": 9,
|
| 177 |
+
"note": "COLL"
|
| 178 |
+
}
|
| 179 |
+
]
|
| 180 |
+
},
|
| 181 |
+
{
|
| 182 |
+
"name": "L 5",
|
| 183 |
+
"case": "L",
|
| 184 |
+
"algs": [
|
| 185 |
+
{
|
| 186 |
+
"notation": "y' L' R U R' U' L U R U' R'",
|
| 187 |
+
"moves": 10,
|
| 188 |
+
"note": "COLL"
|
| 189 |
+
}
|
| 190 |
+
]
|
| 191 |
+
},
|
| 192 |
+
{
|
| 193 |
+
"name": "L 6",
|
| 194 |
+
"case": "L",
|
| 195 |
+
"algs": [
|
| 196 |
+
{
|
| 197 |
+
"notation": "y2 x' U' R U L' U' R' U r",
|
| 198 |
+
"moves": 8,
|
| 199 |
+
"note": "COLL"
|
| 200 |
+
}
|
| 201 |
+
]
|
| 202 |
+
},
|
| 203 |
+
{
|
| 204 |
+
"name": "T 1",
|
| 205 |
+
"case": "T",
|
| 206 |
+
"algs": [
|
| 207 |
+
{
|
| 208 |
+
"notation": "R U2 R' U' R U' R2 U2 R U R' U R",
|
| 209 |
+
"moves": 13,
|
| 210 |
+
"note": "COLL"
|
| 211 |
+
}
|
| 212 |
+
]
|
| 213 |
+
},
|
| 214 |
+
{
|
| 215 |
+
"name": "T 2",
|
| 216 |
+
"case": "T",
|
| 217 |
+
"algs": [
|
| 218 |
+
{
|
| 219 |
+
"notation": "y2 F R U R' U' R U' R' U' R U R' F'",
|
| 220 |
+
"moves": 13,
|
| 221 |
+
"note": "COLL"
|
| 222 |
+
}
|
| 223 |
+
]
|
| 224 |
+
},
|
| 225 |
+
{
|
| 226 |
+
"name": "T 3",
|
| 227 |
+
"case": "T",
|
| 228 |
+
"algs": [
|
| 229 |
+
{
|
| 230 |
+
"notation": "R' U R U2 L' R' U R U' L",
|
| 231 |
+
"moves": 10,
|
| 232 |
+
"note": "COLL"
|
| 233 |
+
}
|
| 234 |
+
]
|
| 235 |
+
},
|
| 236 |
+
{
|
| 237 |
+
"name": "T 4",
|
| 238 |
+
"case": "T",
|
| 239 |
+
"algs": [
|
| 240 |
+
{
|
| 241 |
+
"notation": "y2 R U' R2 D' r U2 r' D R2 U R'",
|
| 242 |
+
"moves": 11,
|
| 243 |
+
"note": "COLL"
|
| 244 |
+
}
|
| 245 |
+
]
|
| 246 |
+
},
|
| 247 |
+
{
|
| 248 |
+
"name": "T 5",
|
| 249 |
+
"case": "T",
|
| 250 |
+
"algs": [
|
| 251 |
+
{
|
| 252 |
+
"notation": "y' r' U' R U L U' R' U x",
|
| 253 |
+
"moves": 9,
|
| 254 |
+
"note": "COLL"
|
| 255 |
+
}
|
| 256 |
+
]
|
| 257 |
+
},
|
| 258 |
+
{
|
| 259 |
+
"name": "T 6",
|
| 260 |
+
"case": "T",
|
| 261 |
+
"algs": [
|
| 262 |
+
{
|
| 263 |
+
"notation": "y' r U R' U' L' U R U' x'",
|
| 264 |
+
"moves": 9,
|
| 265 |
+
"note": "COLL"
|
| 266 |
+
}
|
| 267 |
+
]
|
| 268 |
+
},
|
| 269 |
+
{
|
| 270 |
+
"name": "U 1",
|
| 271 |
+
"case": "U",
|
| 272 |
+
"algs": [
|
| 273 |
+
{
|
| 274 |
+
"notation": "y2 R U R' U R U2 R2 U' R U' R' U2 R",
|
| 275 |
+
"moves": 13,
|
| 276 |
+
"note": "COLL"
|
| 277 |
+
}
|
| 278 |
+
]
|
| 279 |
+
},
|
| 280 |
+
{
|
| 281 |
+
"name": "U 2",
|
| 282 |
+
"case": "U",
|
| 283 |
+
"algs": [
|
| 284 |
+
{
|
| 285 |
+
"notation": "F R U' R' U R U R' U R U' R' F'",
|
| 286 |
+
"moves": 13,
|
| 287 |
+
"note": "COLL"
|
| 288 |
+
}
|
| 289 |
+
]
|
| 290 |
+
},
|
| 291 |
+
{
|
| 292 |
+
"name": "U 3",
|
| 293 |
+
"case": "U",
|
| 294 |
+
"algs": [
|
| 295 |
+
{
|
| 296 |
+
"notation": "y2 R2 D R' U2 R D' R' U2 R'",
|
| 297 |
+
"moves": 9,
|
| 298 |
+
"note": "COLL"
|
| 299 |
+
}
|
| 300 |
+
]
|
| 301 |
+
},
|
| 302 |
+
{
|
| 303 |
+
"name": "U 4",
|
| 304 |
+
"case": "U",
|
| 305 |
+
"algs": [
|
| 306 |
+
{
|
| 307 |
+
"notation": "R2 D' R U2 R' D R U2 R",
|
| 308 |
+
"moves": 9,
|
| 309 |
+
"note": "COLL"
|
| 310 |
+
}
|
| 311 |
+
]
|
| 312 |
+
},
|
| 313 |
+
{
|
| 314 |
+
"name": "U 5",
|
| 315 |
+
"case": "U",
|
| 316 |
+
"algs": [
|
| 317 |
+
{
|
| 318 |
+
"notation": "y2 R' U R U' x' U L' U L U2 R U' R' U x",
|
| 319 |
+
"moves": 13,
|
| 320 |
+
"note": "COLL"
|
| 321 |
+
}
|
| 322 |
+
]
|
| 323 |
+
},
|
| 324 |
+
{
|
| 325 |
+
"name": "U 6",
|
| 326 |
+
"case": "U",
|
| 327 |
+
"algs": [
|
| 328 |
+
{
|
| 329 |
+
"notation": "R' U2 R F U' R' U' R U F'",
|
| 330 |
+
"moves": 10,
|
| 331 |
+
"note": "COLL"
|
| 332 |
+
}
|
| 333 |
+
]
|
| 334 |
+
},
|
| 335 |
+
{
|
| 336 |
+
"name": "Pi 1",
|
| 337 |
+
"case": "Pi",
|
| 338 |
+
"algs": [
|
| 339 |
+
{
|
| 340 |
+
"notation": "R U2 R2 U' R2 U' R2 U2 R",
|
| 341 |
+
"moves": 9,
|
| 342 |
+
"note": "COLL"
|
| 343 |
+
}
|
| 344 |
+
]
|
| 345 |
+
},
|
| 346 |
+
{
|
| 347 |
+
"name": "Pi 2",
|
| 348 |
+
"case": "Pi",
|
| 349 |
+
"algs": [
|
| 350 |
+
{
|
| 351 |
+
"notation": "R U' R' U2 L' U R U' L R' U2 R U R'",
|
| 352 |
+
"moves": 14,
|
| 353 |
+
"note": "COLL"
|
| 354 |
+
}
|
| 355 |
+
]
|
| 356 |
+
},
|
| 357 |
+
{
|
| 358 |
+
"name": "Pi 3",
|
| 359 |
+
"case": "Pi",
|
| 360 |
+
"algs": [
|
| 361 |
+
{
|
| 362 |
+
"notation": "y L' U R U' L U R' R' U' R U' R' U2 R",
|
| 363 |
+
"moves": 14,
|
| 364 |
+
"note": "COLL"
|
| 365 |
+
}
|
| 366 |
+
]
|
| 367 |
+
},
|
| 368 |
+
{
|
| 369 |
+
"name": "Pi 4",
|
| 370 |
+
"case": "Pi",
|
| 371 |
+
"algs": [
|
| 372 |
+
{
|
| 373 |
+
"notation": "y' R' U2 R U R' U R R U' L' U R' U' L",
|
| 374 |
+
"moves": 14,
|
| 375 |
+
"note": "COLL"
|
| 376 |
+
}
|
| 377 |
+
]
|
| 378 |
+
},
|
| 379 |
+
{
|
| 380 |
+
"name": "H 1",
|
| 381 |
+
"case": "H",
|
| 382 |
+
"algs": [
|
| 383 |
+
{
|
| 384 |
+
"notation": "R U R' U R U' R' U R U2 R'",
|
| 385 |
+
"moves": 11,
|
| 386 |
+
"note": "COLL"
|
| 387 |
+
}
|
| 388 |
+
]
|
| 389 |
+
},
|
| 390 |
+
{
|
| 391 |
+
"name": "H 2",
|
| 392 |
+
"case": "H",
|
| 393 |
+
"algs": [
|
| 394 |
+
{
|
| 395 |
+
"notation": "y F R U R' U' R U R' U' R U R' U' F'",
|
| 396 |
+
"moves": 14,
|
| 397 |
+
"note": "COLL"
|
| 398 |
+
}
|
| 399 |
+
]
|
| 400 |
+
},
|
| 401 |
+
{
|
| 402 |
+
"name": "H 3",
|
| 403 |
+
"case": "H",
|
| 404 |
+
"algs": [
|
| 405 |
+
{
|
| 406 |
+
"notation": "F R U' R' U R U2 R' U' R U R' U' F'",
|
| 407 |
+
"moves": 14,
|
| 408 |
+
"note": "COLL"
|
| 409 |
+
}
|
| 410 |
+
]
|
| 411 |
+
},
|
| 412 |
+
{
|
| 413 |
+
"name": "H 4",
|
| 414 |
+
"case": "H",
|
| 415 |
+
"algs": [
|
| 416 |
+
{
|
| 417 |
+
"notation": "R U R' U R U L' U R' U' L",
|
| 418 |
+
"moves": 11,
|
| 419 |
+
"note": "COLL"
|
| 420 |
+
}
|
| 421 |
+
]
|
| 422 |
+
}
|
| 423 |
+
]
|
| 424 |
+
};
|
json/f2l.json.js
ADDED
|
@@ -0,0 +1,409 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const OH_ALGORITHMS = {};
|
| 2 |
+
OH_ALGORITHMS.f2l = {
|
| 3 |
+
"title": "F2L - First Two Layers",
|
| 4 |
+
"description": "F2L algorithms from Speedsolving.com Wiki. 42 cases (including solved case). Multiple algorithms per case - select your preferred one.",
|
| 5 |
+
"cases": [
|
| 6 |
+
{
|
| 7 |
+
"name": "F2L 1",
|
| 8 |
+
"case": "Basic Insert",
|
| 9 |
+
"algs": [
|
| 10 |
+
{ "notation": "U (R U' R')", "moves": 4, "note": "Main" },
|
| 11 |
+
{ "notation": "R' F R F'", "moves": 4, "note": "Alt" },
|
| 12 |
+
{ "notation": "U2 (R U2 R')", "moves": 4, "note": "Alt 2" }
|
| 13 |
+
]
|
| 14 |
+
},
|
| 15 |
+
{
|
| 16 |
+
"name": "F2L 2",
|
| 17 |
+
"case": "Basic Insert",
|
| 18 |
+
"algs": [
|
| 19 |
+
{ "notation": "y' U' (R' U R)", "moves": 4, "note": "Main" },
|
| 20 |
+
{ "notation": "U' (F' U F)", "moves": 4, "note": "Alt" },
|
| 21 |
+
{ "notation": "F R' F' R", "moves": 4, "note": "Alt 2" },
|
| 22 |
+
{ "notation": "y U' (L' U L)", "moves": 4, "note": "Alt 3" },
|
| 23 |
+
{ "notation": "d' L' U L", "moves": 4, "note": "Alt 4" }
|
| 24 |
+
]
|
| 25 |
+
},
|
| 26 |
+
{
|
| 27 |
+
"name": "F2L 3",
|
| 28 |
+
"case": "Basic Insert",
|
| 29 |
+
"algs": [
|
| 30 |
+
{ "notation": "F' U' F", "moves": 3, "note": "Main" },
|
| 31 |
+
{ "notation": "y' (R' U' R)", "moves": 3, "note": "Alt" },
|
| 32 |
+
{ "notation": "y (L' U' L)", "moves": 3, "note": "Alt 2" }
|
| 33 |
+
]
|
| 34 |
+
},
|
| 35 |
+
{
|
| 36 |
+
"name": "F2L 4",
|
| 37 |
+
"case": "Basic Insert",
|
| 38 |
+
"algs": [
|
| 39 |
+
{ "notation": "(R U R')", "moves": 3, "note": "Main" },
|
| 40 |
+
{ "notation": "y F U F'", "moves": 3, "note": "Alt" },
|
| 41 |
+
{ "notation": "y' f R f'", "moves": 3, "note": "Alt 2" }
|
| 42 |
+
]
|
| 43 |
+
},
|
| 44 |
+
{
|
| 45 |
+
"name": "F2L 5",
|
| 46 |
+
"case": "Reposition Edge",
|
| 47 |
+
"algs": [
|
| 48 |
+
{ "notation": "(U' R U R') U2 (R U' R')", "moves": 8, "note": "Main" },
|
| 49 |
+
{ "notation": "(U' R U R') U (R' F R F')", "moves": 9, "note": "Alt" },
|
| 50 |
+
{ "notation": "U' (R U R') U' R U2 R'", "moves": 8, "note": "Alt 2" }
|
| 51 |
+
]
|
| 52 |
+
},
|
| 53 |
+
{
|
| 54 |
+
"name": "F2L 6",
|
| 55 |
+
"case": "Reposition Edge",
|
| 56 |
+
"algs": [
|
| 57 |
+
{ "notation": "d (R' U' R) U2' (R' U R)", "moves": 8, "note": "Main" },
|
| 58 |
+
{ "notation": "y' (U R' U' R) U2 (R' U R)", "moves": 8, "note": "Alt" },
|
| 59 |
+
{ "notation": "U' (r U' R' U) (R U r')", "moves": 7, "note": "Alt 2" },
|
| 60 |
+
{ "notation": "y F2 (R U R' U') F2", "moves": 6, "note": "Alt 3" }
|
| 61 |
+
]
|
| 62 |
+
},
|
| 63 |
+
{
|
| 64 |
+
"name": "F2L 7",
|
| 65 |
+
"case": "Reposition Edge",
|
| 66 |
+
"algs": [
|
| 67 |
+
{ "notation": "U' (R U2' R') U2 (R U' R')", "moves": 8, "note": "Main" },
|
| 68 |
+
{ "notation": "(U' R U2 R') (U' R U2 R')", "moves": 8, "note": "Alt" }
|
| 69 |
+
]
|
| 70 |
+
},
|
| 71 |
+
{
|
| 72 |
+
"name": "F2L 8",
|
| 73 |
+
"case": "Reposition Edge",
|
| 74 |
+
"algs": [
|
| 75 |
+
{ "notation": "d (R' U2 R) U2' (R' U R)", "moves": 8, "note": "Main" },
|
| 76 |
+
{ "notation": "y' U (R' U2 R) U2 (R' U R)", "moves": 8, "note": "Alt" },
|
| 77 |
+
{ "notation": "U (R' F R F') (R' F R F') (R U' R')", "moves": 11, "note": "Alt 2" },
|
| 78 |
+
{ "notation": "(r' U2) (R2 U R2 U r)", "moves": 7, "note": "Alt 3" }
|
| 79 |
+
]
|
| 80 |
+
},
|
| 81 |
+
{
|
| 82 |
+
"name": "F2L 9",
|
| 83 |
+
"case": "Reposition Edge and Flip Corner",
|
| 84 |
+
"algs": [
|
| 85 |
+
{ "notation": "U' R U' R' U (F' U' F)", "moves": 8, "note": "Main" },
|
| 86 |
+
{ "notation": "U' R U' R' d R' U' R", "moves": 8, "note": "Alt" },
|
| 87 |
+
{ "notation": "d (R' U' R U') (R' U' R)", "moves": 8, "note": "Alt 2" },
|
| 88 |
+
{ "notation": "F (R U R' U') F' R U' R'", "moves": 9, "note": "Alt 3" },
|
| 89 |
+
{ "notation": "y F2 (U R U' R') F2", "moves": 6, "note": "Alt 4" }
|
| 90 |
+
]
|
| 91 |
+
},
|
| 92 |
+
{
|
| 93 |
+
"name": "F2L 10",
|
| 94 |
+
"case": "Reposition Edge and Flip Corner",
|
| 95 |
+
"algs": [
|
| 96 |
+
{ "notation": "U' (R U R' U)(R U R')", "moves": 8, "note": "Main" },
|
| 97 |
+
{ "notation": "R d' R U R' U2 F'", "moves": 7, "note": "Alt" },
|
| 98 |
+
{ "notation": "U F' U F U' R U R'", "moves": 8, "note": "Alt 2" },
|
| 99 |
+
{ "notation": "d R' U R d' R U R'", "moves": 8, "note": "Alt 3" }
|
| 100 |
+
]
|
| 101 |
+
},
|
| 102 |
+
{
|
| 103 |
+
"name": "F2L 11",
|
| 104 |
+
"case": "Reposition Edge and Flip Corner",
|
| 105 |
+
"algs": [
|
| 106 |
+
{ "notation": "U' (R U2' R') U (F' U' F)", "moves": 8, "note": "Main" },
|
| 107 |
+
{ "notation": "U' (R U2' R') d (R' U' R)", "moves": 8, "note": "Alt" },
|
| 108 |
+
{ "notation": "y' R U2 R2 U' R2 U' R'", "moves": 7, "note": "Alt 2" }
|
| 109 |
+
]
|
| 110 |
+
},
|
| 111 |
+
{
|
| 112 |
+
"name": "F2L 12",
|
| 113 |
+
"case": "Reposition Edge and Flip Corner",
|
| 114 |
+
"algs": [
|
| 115 |
+
{ "notation": "R U' R' U R U' R' U2 R U' R'", "moves": 11, "note": "Main" },
|
| 116 |
+
{ "notation": "R' U2 R2 U R2 U R", "moves": 7, "note": "Alt" },
|
| 117 |
+
{ "notation": "(U R U' R') U' (R U R' U') (R U R')", "moves": 12, "note": "Alt 2" },
|
| 118 |
+
{ "notation": "R U R' U (R' F R F') (R U R')", "moves": 11, "note": "Alt 3" }
|
| 119 |
+
]
|
| 120 |
+
},
|
| 121 |
+
{
|
| 122 |
+
"name": "F2L 13",
|
| 123 |
+
"case": "Reposition Edge and Flip Corner",
|
| 124 |
+
"algs": [
|
| 125 |
+
{ "notation": "d (R' U R U') (R' U' R)", "moves": 8, "note": "Main" },
|
| 126 |
+
{ "notation": "y' U (R' U R U') (R' U' R)", "moves": 8, "note": "Alt" },
|
| 127 |
+
{ "notation": "(R U' R') U (R' F R F') (R U' R')", "moves": 11, "note": "Alt 2" }
|
| 128 |
+
]
|
| 129 |
+
},
|
| 130 |
+
{
|
| 131 |
+
"name": "F2L 14",
|
| 132 |
+
"case": "Reposition Edge and Flip Corner",
|
| 133 |
+
"algs": [
|
| 134 |
+
{ "notation": "U' (R U' R' U) (R U R')", "moves": 8, "note": "Main" }
|
| 135 |
+
]
|
| 136 |
+
},
|
| 137 |
+
{
|
| 138 |
+
"name": "F2L 15",
|
| 139 |
+
"case": "Split Pair by Going Over",
|
| 140 |
+
"algs": [
|
| 141 |
+
{ "notation": "(F' U F) U2 (R U R')", "moves": 7, "note": "Main" },
|
| 142 |
+
{ "notation": "U (R' F R F') U (R U R')", "moves": 9, "note": "Alt" },
|
| 143 |
+
{ "notation": "R U2 R' U R U R' U R U' R'", "moves": 11, "note": "Alt 2" },
|
| 144 |
+
{ "notation": "R U R' U2 R U' R' U R U' R'", "moves": 11, "note": "Alt 3" },
|
| 145 |
+
{ "notation": "R U' R U2' R2' U' R2 U' R2'", "moves": 9, "note": "Alt 4" }
|
| 146 |
+
]
|
| 147 |
+
},
|
| 148 |
+
{
|
| 149 |
+
"name": "F2L 16",
|
| 150 |
+
"case": "Split Pair by Going Over",
|
| 151 |
+
"algs": [
|
| 152 |
+
{ "notation": "(R U' R') U2 (F' U' F)", "moves": 7, "note": "Main" },
|
| 153 |
+
{ "notation": "(R U' R' U) d (R' U' R)", "moves": 8, "note": "Alt" },
|
| 154 |
+
{ "notation": "U R (F R U R' U' F') R'", "moves": 9, "note": "Alt 2" }
|
| 155 |
+
]
|
| 156 |
+
},
|
| 157 |
+
{
|
| 158 |
+
"name": "F2L 17",
|
| 159 |
+
"case": "Split Pair by Going Over",
|
| 160 |
+
"algs": [
|
| 161 |
+
{ "notation": "(R U2 R') U' (R U R')", "moves": 7, "note": "Main" }
|
| 162 |
+
]
|
| 163 |
+
},
|
| 164 |
+
{
|
| 165 |
+
"name": "F2L 18",
|
| 166 |
+
"case": "Split Pair by Going Over",
|
| 167 |
+
"algs": [
|
| 168 |
+
{ "notation": "y' (R' U2 R) U (R' U' R)", "moves": 7, "note": "Main" },
|
| 169 |
+
{ "notation": "y (L' U2 L) U (L' U' L)", "moves": 7, "note": "Alt" },
|
| 170 |
+
{ "notation": "(R U R' U') (R U R' U') F R' F' R", "moves": 12, "note": "Alt 2" },
|
| 171 |
+
{ "notation": "(R' F R F') (R U' R' U) (R U' R')", "moves": 11, "note": "Alt 3" }
|
| 172 |
+
]
|
| 173 |
+
},
|
| 174 |
+
{
|
| 175 |
+
"name": "F2L 19",
|
| 176 |
+
"case": "Pair Made on Side",
|
| 177 |
+
"algs": [
|
| 178 |
+
{ "notation": "U (R U2 R') U (R U' R')", "moves": 8, "note": "Main" },
|
| 179 |
+
{ "notation": "(R U' R' U) (R U' R' U) R U R'", "moves": 11, "note": "Alt" }
|
| 180 |
+
]
|
| 181 |
+
},
|
| 182 |
+
{
|
| 183 |
+
"name": "F2L 20",
|
| 184 |
+
"case": "Pair Made on Side",
|
| 185 |
+
"algs": [
|
| 186 |
+
{ "notation": "y' U' (R' U2 R) U' (R' U R)", "moves": 8, "note": "Main" },
|
| 187 |
+
{ "notation": "U' (R U' R2' F R F') (R U' R')", "moves": 10, "note": "Alt" },
|
| 188 |
+
{ "notation": "y' (R' U R U') (R' U R U') R' U' R", "moves": 11, "note": "Alt 2" }
|
| 189 |
+
]
|
| 190 |
+
},
|
| 191 |
+
{
|
| 192 |
+
"name": "F2L 21",
|
| 193 |
+
"case": "Pair Made on Side",
|
| 194 |
+
"algs": [
|
| 195 |
+
{ "notation": "(R U' R') U2 (R U R')", "moves": 7, "note": "Main" },
|
| 196 |
+
{ "notation": "U2 (R U R' U)(R U' R')", "moves": 8, "note": "Alt" }
|
| 197 |
+
]
|
| 198 |
+
},
|
| 199 |
+
{
|
| 200 |
+
"name": "F2L 22",
|
| 201 |
+
"case": "Pair Made on Side",
|
| 202 |
+
"algs": [
|
| 203 |
+
{ "notation": "y' (R' U R) U2 (R' U' R)", "moves": 7, "note": "Main" },
|
| 204 |
+
{ "notation": "y' U2 (R' U' R U') (R' U R)", "moves": 8, "note": "Alt" },
|
| 205 |
+
{ "notation": "r U' r' U2 r U r'", "moves": 7, "note": "Alt 2" },
|
| 206 |
+
{ "notation": "U (F R U R' U' F') R U R' U2'", "moves": 11, "note": "Alt 3" }
|
| 207 |
+
]
|
| 208 |
+
},
|
| 209 |
+
{
|
| 210 |
+
"name": "F2L 23",
|
| 211 |
+
"case": "Weird",
|
| 212 |
+
"algs": [
|
| 213 |
+
{ "notation": "U2 R2 U2 (R' U' R U') R2", "moves": 8, "note": "Main" },
|
| 214 |
+
{ "notation": "U (F R' F' R) U (R U R')", "moves": 8, "note": "Alt" },
|
| 215 |
+
{ "notation": "U R U' R' U' R U' R' U R U' R'", "moves": 12, "note": "Alt 2" },
|
| 216 |
+
{ "notation": "(R U R' U') U' (R U R' U')(R U R')", "moves": 12, "note": "Alt 3" },
|
| 217 |
+
{ "notation": "R U' R' U' (R U R') U2 (R U R')", "moves": 11, "note": "Alt 4" },
|
| 218 |
+
{ "notation": "R2 U R' U R U2 R' U' R'", "moves": 9, "note": "Alt 5" }
|
| 219 |
+
]
|
| 220 |
+
},
|
| 221 |
+
{
|
| 222 |
+
"name": "F2L 24",
|
| 223 |
+
"case": "Weird",
|
| 224 |
+
"algs": [
|
| 225 |
+
{ "notation": "F U (R U' R' F')(R U' R')", "moves": 9, "note": "Main" },
|
| 226 |
+
{ "notation": "y' (R' U' R U) U (R' U' R U)(R' U' R)", "moves": 12, "note": "Alt" },
|
| 227 |
+
{ "notation": "y' U2 R2 U2 (R U R' U) R2", "moves": 8, "note": "Alt 2" },
|
| 228 |
+
{ "notation": "U' (R U) (R2' F R F') (R U' R')", "moves": 10, "note": "Alt 3" },
|
| 229 |
+
{ "notation": "(R U R' U) (R U R' U') (F R' F' R)", "moves": 12, "note": "Alt 4" },
|
| 230 |
+
{ "notation": "(R U R' U) (R U2 R') F' U2 F", "moves": 11, "note": "Alt 5" }
|
| 231 |
+
]
|
| 232 |
+
},
|
| 233 |
+
{
|
| 234 |
+
"name": "F2L 25",
|
| 235 |
+
"case": "Corner in Place, Edge in U Face",
|
| 236 |
+
"algs": [
|
| 237 |
+
{ "notation": "U' (R' F R F') (R U R')", "moves": 8, "note": "Main" },
|
| 238 |
+
{ "notation": "R' U' R' U' R' U R U R", "moves": 9, "note": "Alt" },
|
| 239 |
+
{ "notation": "U' (F' U F) U (R U' R')", "moves": 7, "note": "Alt 2" },
|
| 240 |
+
{ "notation": "R' F' R U R U' R' F", "moves": 8, "note": "Alt 3" },
|
| 241 |
+
{ "notation": "(U') F' R U R' U' R' F R", "moves": 9, "note": "Alt 4" },
|
| 242 |
+
{ "notation": "(R U' R' U') (R U' R' U) (R U R')", "moves": 11, "note": "Alt 5" }
|
| 243 |
+
]
|
| 244 |
+
},
|
| 245 |
+
{
|
| 246 |
+
"name": "F2L 26",
|
| 247 |
+
"case": "Corner in Place, Edge in U Face",
|
| 248 |
+
"algs": [
|
| 249 |
+
{ "notation": "U (R U' R') (F R' F' R)", "moves": 8, "note": "Main" },
|
| 250 |
+
{ "notation": "y' R U R U R U' R' U' R'", "moves": 9, "note": "Alt" },
|
| 251 |
+
{ "notation": "U (R U' R') U' (F' U F)", "moves": 8, "note": "Alt 2" },
|
| 252 |
+
{ "notation": "r U r' U2 r U r' U2 r U' r'", "moves": 11, "note": "Alt 3" }
|
| 253 |
+
]
|
| 254 |
+
},
|
| 255 |
+
{
|
| 256 |
+
"name": "F2L 27",
|
| 257 |
+
"case": "Corner in Place, Edge in U Face",
|
| 258 |
+
"algs": [
|
| 259 |
+
{ "notation": "(R U' R' U)(R U' R')", "moves": 7, "note": "Main" },
|
| 260 |
+
{ "notation": "(R U' R2)(F R F')", "moves": 6, "note": "Alt" }
|
| 261 |
+
]
|
| 262 |
+
},
|
| 263 |
+
{
|
| 264 |
+
"name": "F2L 28",
|
| 265 |
+
"case": "Corner in Place, Edge in U Face",
|
| 266 |
+
"algs": [
|
| 267 |
+
{ "notation": "(R U R' U') F R' F' R", "moves": 8, "note": "Main" },
|
| 268 |
+
{ "notation": "(R U R') d (R' U2 R)", "moves": 7, "note": "Alt" },
|
| 269 |
+
{ "notation": "y (L' U L U') (L' U L)", "moves": 7, "note": "Alt 2" },
|
| 270 |
+
{ "notation": "y' (R' U R U')(R' U R)", "moves": 7, "note": "Alt 3" },
|
| 271 |
+
{ "notation": "(R U R') U (F' U2 F)", "moves": 7, "note": "Alt 4" }
|
| 272 |
+
]
|
| 273 |
+
},
|
| 274 |
+
{
|
| 275 |
+
"name": "F2L 29",
|
| 276 |
+
"case": "Corner in Place, Edge in U Face",
|
| 277 |
+
"algs": [
|
| 278 |
+
{ "notation": "y' (R' U' R U)(R' U' R)", "moves": 7, "note": "Main" },
|
| 279 |
+
{ "notation": "U2 (R U' R') y' (R' U' R)", "moves": 7, "note": "Alt" },
|
| 280 |
+
{ "notation": "(R' F R F') (R' F R F')", "moves": 8, "note": "Alt 2" },
|
| 281 |
+
{ "notation": "(R' F R F') (U R U' R')", "moves": 8, "note": "Alt 3" }
|
| 282 |
+
]
|
| 283 |
+
},
|
| 284 |
+
{
|
| 285 |
+
"name": "F2L 30",
|
| 286 |
+
"case": "Corner in Place, Edge in U Face",
|
| 287 |
+
"algs": [
|
| 288 |
+
{ "notation": "(R U R' U')(R U R')", "moves": 7, "note": "Main" },
|
| 289 |
+
{ "notation": "U2 (F' U F)(R U R')", "moves": 7, "note": "Alt" },
|
| 290 |
+
{ "notation": "U' (R U2 R') U2 (R U R')", "moves": 8, "note": "Alt 2" }
|
| 291 |
+
]
|
| 292 |
+
},
|
| 293 |
+
{
|
| 294 |
+
"name": "F2L 31",
|
| 295 |
+
"case": "Edge in Place, Corner in U Face",
|
| 296 |
+
"algs": [
|
| 297 |
+
{ "notation": "(R U' R') d (R' U R)", "moves": 7, "note": "Main" },
|
| 298 |
+
{ "notation": "(R U' R' U)(F' U F)", "moves": 7, "note": "Alt" },
|
| 299 |
+
{ "notation": "U' (R' F R F') (R U' R')", "moves": 8, "note": "Alt 2" },
|
| 300 |
+
{ "notation": "R U2 R' U' F R' F' R", "moves": 8, "note": "Alt 3" }
|
| 301 |
+
]
|
| 302 |
+
},
|
| 303 |
+
{
|
| 304 |
+
"name": "F2L 32",
|
| 305 |
+
"case": "Edge in Place, Corner in U Face",
|
| 306 |
+
"algs": [
|
| 307 |
+
{ "notation": "(R U R' U') (R U R' U') (R U R')", "moves": 11, "note": "Main" },
|
| 308 |
+
{ "notation": "(U R U' R') (U R U' R') (U R U' R')", "moves": 12, "note": "Alt" },
|
| 309 |
+
{ "notation": "U' (R U R' U') (R U R' U) (R U' R')", "moves": 12, "note": "Alt 2" }
|
| 310 |
+
]
|
| 311 |
+
},
|
| 312 |
+
{
|
| 313 |
+
"name": "F2L 33",
|
| 314 |
+
"case": "Edge in Place, Corner in U Face",
|
| 315 |
+
"algs": [
|
| 316 |
+
{ "notation": "U' (R U' R') U2' (R U' R')", "moves": 8, "note": "Main" },
|
| 317 |
+
{ "notation": "(U' R U' R') U2 (R U' R')", "moves": 8, "note": "Alt" },
|
| 318 |
+
{ "notation": "y U' (L' U' L) U2 (L' U' L)", "moves": 8, "note": "Alt 2" }
|
| 319 |
+
]
|
| 320 |
+
},
|
| 321 |
+
{
|
| 322 |
+
"name": "F2L 34",
|
| 323 |
+
"case": "Edge in Place, Corner in U Face",
|
| 324 |
+
"algs": [
|
| 325 |
+
{ "notation": "U (F' U F) U2 (F' U F)", "moves": 8, "note": "Main" },
|
| 326 |
+
{ "notation": "U' (R U2' R') U (R U R')", "moves": 8, "note": "Alt" },
|
| 327 |
+
{ "notation": "U (R U R') U2 (R U R')", "moves": 8, "note": "Alt 2" },
|
| 328 |
+
{ "notation": "d (R' U R) U2 (R' U R)", "moves": 8, "note": "Alt 3" },
|
| 329 |
+
{ "notation": "y (U L' U L) U2 (L' U L)", "moves": 8, "note": "Alt 4" }
|
| 330 |
+
]
|
| 331 |
+
},
|
| 332 |
+
{
|
| 333 |
+
"name": "F2L 35",
|
| 334 |
+
"case": "Edge in Place, Corner in U Face",
|
| 335 |
+
"algs": [
|
| 336 |
+
{ "notation": "U' R U R' U (F' U' F)", "moves": 8, "note": "Main" },
|
| 337 |
+
{ "notation": "(U' R U R') d (R' U' R)", "moves": 8, "note": "Alt" },
|
| 338 |
+
{ "notation": "U2 (R U' R') U' (F' U' F)", "moves": 8, "note": "Alt 2" }
|
| 339 |
+
]
|
| 340 |
+
},
|
| 341 |
+
{
|
| 342 |
+
"name": "F2L 36",
|
| 343 |
+
"case": "Edge in Place, Corner in U Face",
|
| 344 |
+
"algs": [
|
| 345 |
+
{ "notation": "U F' U' F U' (R U R')", "moves": 8, "note": "Main" },
|
| 346 |
+
{ "notation": "U2 (R' F R F') U2 (R U R')", "moves": 9, "note": "Alt" },
|
| 347 |
+
{ "notation": "y' U (R' U' R U') y (R U R')", "moves": 8, "note": "Alt 2" }
|
| 348 |
+
]
|
| 349 |
+
},
|
| 350 |
+
{
|
| 351 |
+
"name": "F2L 37",
|
| 352 |
+
"case": "Edge and Corner in Place",
|
| 353 |
+
"algs": [
|
| 354 |
+
{ "notation": "", "moves": 0, "note": "Solved" }
|
| 355 |
+
]
|
| 356 |
+
},
|
| 357 |
+
{
|
| 358 |
+
"name": "F2L 38",
|
| 359 |
+
"case": "Edge and Corner in Place",
|
| 360 |
+
"algs": [
|
| 361 |
+
{ "notation": "(R' F R F') (R U' R' U) (R U' R' U2) (R U' R')", "moves": 15, "note": "Main" },
|
| 362 |
+
{ "notation": "(R U' R') d (R' U2 R) U2' (R' U R)", "moves": 10, "note": "Alt" },
|
| 363 |
+
{ "notation": "(R U R') U2 (R U2 R') d (R' U' R)", "moves": 11, "note": "Alt 2" },
|
| 364 |
+
{ "notation": "(R2 U2) (F R2 F') (U2 R' U R')", "moves": 9, "note": "Alt 3" },
|
| 365 |
+
{ "notation": "(R U R' U')(R U2 R' d)(R' U' R U' R' U R)", "moves": 15, "note": "Alt 4" }
|
| 366 |
+
]
|
| 367 |
+
},
|
| 368 |
+
{
|
| 369 |
+
"name": "F2L 39",
|
| 370 |
+
"case": "Edge and Corner in Place",
|
| 371 |
+
"algs": [
|
| 372 |
+
{ "notation": "(R U' R') U' (R U R') U2 (R U' R')", "moves": 11, "note": "Main" },
|
| 373 |
+
{ "notation": "y' (R' U' R) U2 (R' U R U') (R' U' R)", "moves": 11, "note": "Alt" },
|
| 374 |
+
{ "notation": "(R U R' U') (R U2 R') U' (R U R')", "moves": 11, "note": "Alt 2" }
|
| 375 |
+
]
|
| 376 |
+
},
|
| 377 |
+
{
|
| 378 |
+
"name": "F2L 40",
|
| 379 |
+
"case": "Edge and Corner in Place",
|
| 380 |
+
"algs": [
|
| 381 |
+
{ "notation": "(R U' R' U)(R U2' R') U (R U' R')", "moves": 11, "note": "Main" },
|
| 382 |
+
{ "notation": "(R U R') U2 (R U' R' U)(R U R')", "moves": 11, "note": "Alt" },
|
| 383 |
+
{ "notation": "(R U2) (R U R' U) (R U2 R2')", "moves": 9, "note": "Alt 2" },
|
| 384 |
+
{ "notation": "y' R2 U2 R U R' U R U2 R", "moves": 9, "note": "Alt 3" }
|
| 385 |
+
]
|
| 386 |
+
},
|
| 387 |
+
{
|
| 388 |
+
"name": "F2L 41",
|
| 389 |
+
"case": "Edge and Corner in Place",
|
| 390 |
+
"algs": [
|
| 391 |
+
{ "notation": "(r U' r') U2 (r U r') (R U R')", "moves": 11, "note": "Main" },
|
| 392 |
+
{ "notation": "(R U' R') d (R' U' R U') (R' U' R)", "moves": 11, "note": "Alt" },
|
| 393 |
+
{ "notation": "R U' R' U' R U' R' d R' U' R", "moves": 11, "note": "Alt 2" },
|
| 394 |
+
{ "notation": "R (F U R U' R' F') U' R'", "moves": 9, "note": "Alt 3" }
|
| 395 |
+
]
|
| 396 |
+
},
|
| 397 |
+
{
|
| 398 |
+
"name": "F2L 42",
|
| 399 |
+
"case": "Edge and Corner in Place",
|
| 400 |
+
"algs": [
|
| 401 |
+
{ "notation": "(R U' R') (r U' r') U2 (r U r')", "moves": 11, "note": "Main" },
|
| 402 |
+
{ "notation": "(R U' R' U) d (R' U' R U') (R' U R)", "moves": 12, "note": "Alt" },
|
| 403 |
+
{ "notation": "(R U' R' U2) y' (R' U' R U' R' U R)", "moves": 12, "note": "Alt 2" },
|
| 404 |
+
{ "notation": "(R U R' U') (R U' R') U2 (F' U' F)", "moves": 11, "note": "Alt 3" },
|
| 405 |
+
{ "notation": "R U (F R U R' U' F') R'", "moves": 9, "note": "Alt 4" }
|
| 406 |
+
]
|
| 407 |
+
}
|
| 408 |
+
]
|
| 409 |
+
};
|
json/oll.json.js
ADDED
|
@@ -0,0 +1,633 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
OH_ALGORITHMS.oll = {
|
| 2 |
+
"title": "OH OLL - Orientation of Last Layer",
|
| 3 |
+
"description": "OH OLL algorithms from CubeSkills by Feliks Zemdegs. 57 cases.",
|
| 4 |
+
"cases": [
|
| 5 |
+
{
|
| 6 |
+
"name": "OLL 1",
|
| 7 |
+
"case": "No Edges",
|
| 8 |
+
"algs": [
|
| 9 |
+
{
|
| 10 |
+
"notation": "y R U' R2 D' r U' r' D R2 U R'",
|
| 11 |
+
"moves": 12,
|
| 12 |
+
"note": "OH OLL"
|
| 13 |
+
}
|
| 14 |
+
]
|
| 15 |
+
},
|
| 16 |
+
{
|
| 17 |
+
"name": "OLL 2",
|
| 18 |
+
"case": "No Edges",
|
| 19 |
+
"algs": [
|
| 20 |
+
{
|
| 21 |
+
"notation": "y r U r' U2 R U2 R' U2 r U' r'",
|
| 22 |
+
"moves": 12,
|
| 23 |
+
"note": "OH OLL"
|
| 24 |
+
}
|
| 25 |
+
]
|
| 26 |
+
},
|
| 27 |
+
{
|
| 28 |
+
"name": "OLL 3",
|
| 29 |
+
"case": "No Edges",
|
| 30 |
+
"algs": [
|
| 31 |
+
{
|
| 32 |
+
"notation": "y r' R2 U R' U r U2 r' U r R'",
|
| 33 |
+
"moves": 12,
|
| 34 |
+
"note": "OH OLL"
|
| 35 |
+
}
|
| 36 |
+
]
|
| 37 |
+
},
|
| 38 |
+
{
|
| 39 |
+
"name": "OLL 4",
|
| 40 |
+
"case": "No Edges",
|
| 41 |
+
"algs": [
|
| 42 |
+
{
|
| 43 |
+
"notation": "y r' R U' r U2 r' U' R U' R2 r",
|
| 44 |
+
"moves": 12,
|
| 45 |
+
"note": "OH OLL"
|
| 46 |
+
}
|
| 47 |
+
]
|
| 48 |
+
},
|
| 49 |
+
{
|
| 50 |
+
"name": "OLL 5",
|
| 51 |
+
"case": "Square",
|
| 52 |
+
"algs": [
|
| 53 |
+
{
|
| 54 |
+
"notation": "r' U2 R U R' U r",
|
| 55 |
+
"moves": 7,
|
| 56 |
+
"note": "OH OLL"
|
| 57 |
+
}
|
| 58 |
+
]
|
| 59 |
+
},
|
| 60 |
+
{
|
| 61 |
+
"name": "OLL 6",
|
| 62 |
+
"case": "Square",
|
| 63 |
+
"algs": [
|
| 64 |
+
{
|
| 65 |
+
"notation": "r U2 R' U' R U' r'",
|
| 66 |
+
"moves": 7,
|
| 67 |
+
"note": "OH OLL"
|
| 68 |
+
}
|
| 69 |
+
]
|
| 70 |
+
},
|
| 71 |
+
{
|
| 72 |
+
"name": "OLL 7",
|
| 73 |
+
"case": "Lightning Bolt",
|
| 74 |
+
"algs": [
|
| 75 |
+
{
|
| 76 |
+
"notation": "r U R' U R U2 r'",
|
| 77 |
+
"moves": 7,
|
| 78 |
+
"note": "OH OLL"
|
| 79 |
+
}
|
| 80 |
+
]
|
| 81 |
+
},
|
| 82 |
+
{
|
| 83 |
+
"name": "OLL 8",
|
| 84 |
+
"case": "Lightning Bolt",
|
| 85 |
+
"algs": [
|
| 86 |
+
{
|
| 87 |
+
"notation": "r' U' R U' R' U2 r",
|
| 88 |
+
"moves": 7,
|
| 89 |
+
"note": "OH OLL"
|
| 90 |
+
}
|
| 91 |
+
]
|
| 92 |
+
},
|
| 93 |
+
{
|
| 94 |
+
"name": "OLL 9",
|
| 95 |
+
"case": "Fish",
|
| 96 |
+
"algs": [
|
| 97 |
+
{
|
| 98 |
+
"notation": "R U R' U' R' F R2 U R' U' F'",
|
| 99 |
+
"moves": 11,
|
| 100 |
+
"note": "OH OLL"
|
| 101 |
+
}
|
| 102 |
+
]
|
| 103 |
+
},
|
| 104 |
+
{
|
| 105 |
+
"name": "OLL 10",
|
| 106 |
+
"case": "Fish",
|
| 107 |
+
"algs": [
|
| 108 |
+
{
|
| 109 |
+
"notation": "y r R2 U2 R U R' U R U r' R",
|
| 110 |
+
"moves": 12,
|
| 111 |
+
"note": "OH OLL"
|
| 112 |
+
}
|
| 113 |
+
]
|
| 114 |
+
},
|
| 115 |
+
{
|
| 116 |
+
"name": "OLL 11",
|
| 117 |
+
"case": "Lightning Bolt",
|
| 118 |
+
"algs": [
|
| 119 |
+
{
|
| 120 |
+
"notation": "r' R2 U R' U R U2 R' U r R'",
|
| 121 |
+
"moves": 11,
|
| 122 |
+
"note": "OH OLL"
|
| 123 |
+
}
|
| 124 |
+
]
|
| 125 |
+
},
|
| 126 |
+
{
|
| 127 |
+
"name": "OLL 12",
|
| 128 |
+
"case": "Lightning Bolt",
|
| 129 |
+
"algs": [
|
| 130 |
+
{
|
| 131 |
+
"notation": "r R2 U' R U' R' U2 R U' r' R",
|
| 132 |
+
"moves": 11,
|
| 133 |
+
"note": "OH OLL"
|
| 134 |
+
}
|
| 135 |
+
]
|
| 136 |
+
},
|
| 137 |
+
{
|
| 138 |
+
"name": "OLL 13",
|
| 139 |
+
"case": "Knight Move",
|
| 140 |
+
"algs": [
|
| 141 |
+
{
|
| 142 |
+
"notation": "F U R U2 R' U' R U R' F'",
|
| 143 |
+
"moves": 10,
|
| 144 |
+
"note": "OH OLL"
|
| 145 |
+
}
|
| 146 |
+
]
|
| 147 |
+
},
|
| 148 |
+
{
|
| 149 |
+
"name": "OLL 14",
|
| 150 |
+
"case": "Knight Move",
|
| 151 |
+
"algs": [
|
| 152 |
+
{
|
| 153 |
+
"notation": "y2 r' U r U r' U' r y R U' R'",
|
| 154 |
+
"moves": 12,
|
| 155 |
+
"note": "OH OLL"
|
| 156 |
+
}
|
| 157 |
+
]
|
| 158 |
+
},
|
| 159 |
+
{
|
| 160 |
+
"name": "OLL 15",
|
| 161 |
+
"case": "Knight Move",
|
| 162 |
+
"algs": [
|
| 163 |
+
{
|
| 164 |
+
"notation": "r' U' r R' U' R U r' U r",
|
| 165 |
+
"moves": 10,
|
| 166 |
+
"note": "OH OLL"
|
| 167 |
+
}
|
| 168 |
+
]
|
| 169 |
+
},
|
| 170 |
+
{
|
| 171 |
+
"name": "OLL 16",
|
| 172 |
+
"case": "Knight Move",
|
| 173 |
+
"algs": [
|
| 174 |
+
{
|
| 175 |
+
"notation": "r U r' R U R' U' r U' r'",
|
| 176 |
+
"moves": 10,
|
| 177 |
+
"note": "OH OLL"
|
| 178 |
+
}
|
| 179 |
+
]
|
| 180 |
+
},
|
| 181 |
+
{
|
| 182 |
+
"name": "OLL 17",
|
| 183 |
+
"case": "No Edges",
|
| 184 |
+
"algs": [
|
| 185 |
+
{
|
| 186 |
+
"notation": "y F R' F' R U2 R U' y R U' R' F'",
|
| 187 |
+
"moves": 13,
|
| 188 |
+
"note": "OH OLL"
|
| 189 |
+
}
|
| 190 |
+
]
|
| 191 |
+
},
|
| 192 |
+
{
|
| 193 |
+
"name": "OLL 18",
|
| 194 |
+
"case": "No Edges",
|
| 195 |
+
"algs": [
|
| 196 |
+
{
|
| 197 |
+
"notation": "r U R' U R U2 r' r' U' R U' R' U2 r",
|
| 198 |
+
"moves": 14,
|
| 199 |
+
"note": "OH OLL"
|
| 200 |
+
}
|
| 201 |
+
]
|
| 202 |
+
},
|
| 203 |
+
{
|
| 204 |
+
"name": "OLL 19",
|
| 205 |
+
"case": "No Edges",
|
| 206 |
+
"algs": [
|
| 207 |
+
{
|
| 208 |
+
"notation": "r' U2 R U R' U r2 U2 R' U' R U' r'",
|
| 209 |
+
"moves": 13,
|
| 210 |
+
"note": "OH OLL"
|
| 211 |
+
}
|
| 212 |
+
]
|
| 213 |
+
},
|
| 214 |
+
{
|
| 215 |
+
"name": "OLL 20",
|
| 216 |
+
"case": "No Edges",
|
| 217 |
+
"algs": [
|
| 218 |
+
{
|
| 219 |
+
"notation": "r' R U R U R' U' r2 R2 U R U' r'",
|
| 220 |
+
"moves": 13,
|
| 221 |
+
"note": "OH OLL"
|
| 222 |
+
}
|
| 223 |
+
]
|
| 224 |
+
},
|
| 225 |
+
{
|
| 226 |
+
"name": "OLL 21",
|
| 227 |
+
"case": "OCLL",
|
| 228 |
+
"algs": [
|
| 229 |
+
{
|
| 230 |
+
"notation": "R U2 R' U' R U R' U' R U' R'",
|
| 231 |
+
"moves": 11,
|
| 232 |
+
"note": "OH OLL"
|
| 233 |
+
}
|
| 234 |
+
]
|
| 235 |
+
},
|
| 236 |
+
{
|
| 237 |
+
"name": "OLL 22",
|
| 238 |
+
"case": "OCLL",
|
| 239 |
+
"algs": [
|
| 240 |
+
{
|
| 241 |
+
"notation": "R U2 R2 U' R2 U' R2 U2 R",
|
| 242 |
+
"moves": 9,
|
| 243 |
+
"note": "OH OLL"
|
| 244 |
+
}
|
| 245 |
+
]
|
| 246 |
+
},
|
| 247 |
+
{
|
| 248 |
+
"name": "OLL 23",
|
| 249 |
+
"case": "OCLL",
|
| 250 |
+
"algs": [
|
| 251 |
+
{
|
| 252 |
+
"notation": "R U R' U R U2 R2 U' R U' R' U2 R",
|
| 253 |
+
"moves": 13,
|
| 254 |
+
"note": "OH OLL"
|
| 255 |
+
}
|
| 256 |
+
]
|
| 257 |
+
},
|
| 258 |
+
{
|
| 259 |
+
"name": "OLL 24",
|
| 260 |
+
"case": "OCLL",
|
| 261 |
+
"algs": [
|
| 262 |
+
{
|
| 263 |
+
"notation": "y' R U' R' U2 R U R' U2 R U R' U R U' R'",
|
| 264 |
+
"moves": 16,
|
| 265 |
+
"note": "OH OLL"
|
| 266 |
+
}
|
| 267 |
+
]
|
| 268 |
+
},
|
| 269 |
+
{
|
| 270 |
+
"name": "OLL 25",
|
| 271 |
+
"case": "OCLL",
|
| 272 |
+
"algs": [
|
| 273 |
+
{
|
| 274 |
+
"notation": "y2 F R U' R' U' R U2 R' U' F'",
|
| 275 |
+
"moves": 11,
|
| 276 |
+
"note": "OH OLL"
|
| 277 |
+
}
|
| 278 |
+
]
|
| 279 |
+
},
|
| 280 |
+
{
|
| 281 |
+
"name": "OLL 26",
|
| 282 |
+
"case": "OCLL",
|
| 283 |
+
"algs": [
|
| 284 |
+
{
|
| 285 |
+
"notation": "R U2 R' U' R U' R'",
|
| 286 |
+
"moves": 7,
|
| 287 |
+
"note": "OH OLL"
|
| 288 |
+
}
|
| 289 |
+
]
|
| 290 |
+
},
|
| 291 |
+
{
|
| 292 |
+
"name": "OLL 27",
|
| 293 |
+
"case": "OCLL",
|
| 294 |
+
"algs": [
|
| 295 |
+
{
|
| 296 |
+
"notation": "R U R' U R U2 R'",
|
| 297 |
+
"moves": 7,
|
| 298 |
+
"note": "OH OLL"
|
| 299 |
+
}
|
| 300 |
+
]
|
| 301 |
+
},
|
| 302 |
+
{
|
| 303 |
+
"name": "OLL 28",
|
| 304 |
+
"case": "Corners Correct",
|
| 305 |
+
"algs": [
|
| 306 |
+
{
|
| 307 |
+
"notation": "r U R' U' r' R U R U' R'",
|
| 308 |
+
"moves": 10,
|
| 309 |
+
"note": "OH OLL"
|
| 310 |
+
}
|
| 311 |
+
]
|
| 312 |
+
},
|
| 313 |
+
{
|
| 314 |
+
"name": "OLL 29",
|
| 315 |
+
"case": "Awkward",
|
| 316 |
+
"algs": [
|
| 317 |
+
{
|
| 318 |
+
"notation": "y R U R' U' R U' R' F' U' F R U R'",
|
| 319 |
+
"moves": 14,
|
| 320 |
+
"note": "OH OLL"
|
| 321 |
+
}
|
| 322 |
+
]
|
| 323 |
+
},
|
| 324 |
+
{
|
| 325 |
+
"name": "OLL 30",
|
| 326 |
+
"case": "Awkward",
|
| 327 |
+
"algs": [
|
| 328 |
+
{
|
| 329 |
+
"notation": "y' F U R U2 R' U' R U2 R' U' F'",
|
| 330 |
+
"moves": 12,
|
| 331 |
+
"note": "OH OLL"
|
| 332 |
+
}
|
| 333 |
+
]
|
| 334 |
+
},
|
| 335 |
+
{
|
| 336 |
+
"name": "OLL 31",
|
| 337 |
+
"case": "P-Shape",
|
| 338 |
+
"algs": [
|
| 339 |
+
{
|
| 340 |
+
"notation": "R' U' F U R U' R' F' R",
|
| 341 |
+
"moves": 9,
|
| 342 |
+
"note": "OH OLL"
|
| 343 |
+
}
|
| 344 |
+
]
|
| 345 |
+
},
|
| 346 |
+
{
|
| 347 |
+
"name": "OLL 32",
|
| 348 |
+
"case": "P-Shape",
|
| 349 |
+
"algs": [
|
| 350 |
+
{
|
| 351 |
+
"notation": "y x' U' R U R' x U' R' U' R U R' U R",
|
| 352 |
+
"moves": 15,
|
| 353 |
+
"note": "OH OLL"
|
| 354 |
+
}
|
| 355 |
+
]
|
| 356 |
+
},
|
| 357 |
+
{
|
| 358 |
+
"name": "OLL 33",
|
| 359 |
+
"case": "T-Shape",
|
| 360 |
+
"algs": [
|
| 361 |
+
{
|
| 362 |
+
"notation": "R U R' U' R' F R F'",
|
| 363 |
+
"moves": 8,
|
| 364 |
+
"note": "OH OLL"
|
| 365 |
+
}
|
| 366 |
+
]
|
| 367 |
+
},
|
| 368 |
+
{
|
| 369 |
+
"name": "OLL 34",
|
| 370 |
+
"case": "C-Shape",
|
| 371 |
+
"algs": [
|
| 372 |
+
{
|
| 373 |
+
"notation": "R U R2 U' R' F R U R U' F'",
|
| 374 |
+
"moves": 11,
|
| 375 |
+
"note": "OH OLL"
|
| 376 |
+
}
|
| 377 |
+
]
|
| 378 |
+
},
|
| 379 |
+
{
|
| 380 |
+
"name": "OLL 35",
|
| 381 |
+
"case": "Fish",
|
| 382 |
+
"algs": [
|
| 383 |
+
{
|
| 384 |
+
"notation": "R U2 R2 F R F' R U2 R'",
|
| 385 |
+
"moves": 9,
|
| 386 |
+
"note": "OH OLL"
|
| 387 |
+
}
|
| 388 |
+
]
|
| 389 |
+
},
|
| 390 |
+
{
|
| 391 |
+
"name": "OLL 36",
|
| 392 |
+
"case": "W-Shape",
|
| 393 |
+
"algs": [
|
| 394 |
+
{
|
| 395 |
+
"notation": "R' U' R U' R' U R U x' R U' R' U",
|
| 396 |
+
"moves": 12,
|
| 397 |
+
"note": "OH OLL"
|
| 398 |
+
}
|
| 399 |
+
]
|
| 400 |
+
},
|
| 401 |
+
{
|
| 402 |
+
"name": "OLL 37",
|
| 403 |
+
"case": "Fish",
|
| 404 |
+
"algs": [
|
| 405 |
+
{
|
| 406 |
+
"notation": "F R U' R' U' R U R' F'",
|
| 407 |
+
"moves": 9,
|
| 408 |
+
"note": "OH OLL"
|
| 409 |
+
}
|
| 410 |
+
]
|
| 411 |
+
},
|
| 412 |
+
{
|
| 413 |
+
"name": "OLL 38",
|
| 414 |
+
"case": "W-Shape",
|
| 415 |
+
"algs": [
|
| 416 |
+
{
|
| 417 |
+
"notation": "R U R' U R U' R' U' R' F R F'",
|
| 418 |
+
"moves": 12,
|
| 419 |
+
"note": "OH OLL"
|
| 420 |
+
}
|
| 421 |
+
]
|
| 422 |
+
},
|
| 423 |
+
{
|
| 424 |
+
"name": "OLL 39",
|
| 425 |
+
"case": "Lightning Bolt",
|
| 426 |
+
"algs": [
|
| 427 |
+
{
|
| 428 |
+
"notation": "y2 R U R' F' U' F U R U2 R'",
|
| 429 |
+
"moves": 11,
|
| 430 |
+
"note": "OH OLL"
|
| 431 |
+
}
|
| 432 |
+
]
|
| 433 |
+
},
|
| 434 |
+
{
|
| 435 |
+
"name": "OLL 40",
|
| 436 |
+
"case": "Lightning Bolt",
|
| 437 |
+
"algs": [
|
| 438 |
+
{
|
| 439 |
+
"notation": "R' F R U R' U' F' U R",
|
| 440 |
+
"moves": 9,
|
| 441 |
+
"note": "OH OLL"
|
| 442 |
+
}
|
| 443 |
+
]
|
| 444 |
+
},
|
| 445 |
+
{
|
| 446 |
+
"name": "OLL 41",
|
| 447 |
+
"case": "Awkward",
|
| 448 |
+
"algs": [
|
| 449 |
+
{
|
| 450 |
+
"notation": "R U R' U R U2 R' F R U R' U' F'",
|
| 451 |
+
"moves": 13,
|
| 452 |
+
"note": "OH OLL"
|
| 453 |
+
}
|
| 454 |
+
]
|
| 455 |
+
},
|
| 456 |
+
{
|
| 457 |
+
"name": "OLL 42",
|
| 458 |
+
"case": "Awkward",
|
| 459 |
+
"algs": [
|
| 460 |
+
{
|
| 461 |
+
"notation": "R' U' R U' R' U2 R F R U R' U' F'",
|
| 462 |
+
"moves": 13,
|
| 463 |
+
"note": "OH OLL"
|
| 464 |
+
}
|
| 465 |
+
]
|
| 466 |
+
},
|
| 467 |
+
{
|
| 468 |
+
"name": "OLL 43",
|
| 469 |
+
"case": "P-Shape",
|
| 470 |
+
"algs": [
|
| 471 |
+
{
|
| 472 |
+
"notation": "y R' U' F' U F R",
|
| 473 |
+
"moves": 7,
|
| 474 |
+
"note": "OH OLL"
|
| 475 |
+
}
|
| 476 |
+
]
|
| 477 |
+
},
|
| 478 |
+
{
|
| 479 |
+
"name": "OLL 44",
|
| 480 |
+
"case": "P-Shape",
|
| 481 |
+
"algs": [
|
| 482 |
+
{
|
| 483 |
+
"notation": "f R U R' U' f'",
|
| 484 |
+
"moves": 6,
|
| 485 |
+
"note": "OH OLL"
|
| 486 |
+
}
|
| 487 |
+
]
|
| 488 |
+
},
|
| 489 |
+
{
|
| 490 |
+
"name": "OLL 45",
|
| 491 |
+
"case": "T-Shape",
|
| 492 |
+
"algs": [
|
| 493 |
+
{
|
| 494 |
+
"notation": "F R U R' U' F'",
|
| 495 |
+
"moves": 6,
|
| 496 |
+
"note": "OH OLL"
|
| 497 |
+
}
|
| 498 |
+
]
|
| 499 |
+
},
|
| 500 |
+
{
|
| 501 |
+
"name": "OLL 46",
|
| 502 |
+
"case": "C-Shape",
|
| 503 |
+
"algs": [
|
| 504 |
+
{
|
| 505 |
+
"notation": "R' U' R' F R F' U R",
|
| 506 |
+
"moves": 8,
|
| 507 |
+
"note": "OH OLL"
|
| 508 |
+
}
|
| 509 |
+
]
|
| 510 |
+
},
|
| 511 |
+
{
|
| 512 |
+
"name": "OLL 47",
|
| 513 |
+
"case": "L-Shape",
|
| 514 |
+
"algs": [
|
| 515 |
+
{
|
| 516 |
+
"notation": "R' U' R' F R F' R' F R F' U R",
|
| 517 |
+
"moves": 12,
|
| 518 |
+
"note": "OH OLL"
|
| 519 |
+
}
|
| 520 |
+
]
|
| 521 |
+
},
|
| 522 |
+
{
|
| 523 |
+
"name": "OLL 48",
|
| 524 |
+
"case": "L-Shape",
|
| 525 |
+
"algs": [
|
| 526 |
+
{
|
| 527 |
+
"notation": "F R U R' U' R U R' U' F'",
|
| 528 |
+
"moves": 10,
|
| 529 |
+
"note": "OH OLL"
|
| 530 |
+
}
|
| 531 |
+
]
|
| 532 |
+
},
|
| 533 |
+
{
|
| 534 |
+
"name": "OLL 49",
|
| 535 |
+
"case": "L-Shape",
|
| 536 |
+
"algs": [
|
| 537 |
+
{
|
| 538 |
+
"notation": "r U' r2 U r2 U r2 U' r",
|
| 539 |
+
"moves": 9,
|
| 540 |
+
"note": "OH OLL"
|
| 541 |
+
}
|
| 542 |
+
]
|
| 543 |
+
},
|
| 544 |
+
{
|
| 545 |
+
"name": "OLL 50",
|
| 546 |
+
"case": "L-Shape",
|
| 547 |
+
"algs": [
|
| 548 |
+
{
|
| 549 |
+
"notation": "r' U r2 U' r2 U' r2 U r'",
|
| 550 |
+
"moves": 9,
|
| 551 |
+
"note": "OH OLL"
|
| 552 |
+
}
|
| 553 |
+
]
|
| 554 |
+
},
|
| 555 |
+
{
|
| 556 |
+
"name": "OLL 51",
|
| 557 |
+
"case": "I-Shape",
|
| 558 |
+
"algs": [
|
| 559 |
+
{
|
| 560 |
+
"notation": "f R U R' U' R U R' U' f'",
|
| 561 |
+
"moves": 10,
|
| 562 |
+
"note": "OH OLL"
|
| 563 |
+
}
|
| 564 |
+
]
|
| 565 |
+
},
|
| 566 |
+
{
|
| 567 |
+
"name": "OLL 52",
|
| 568 |
+
"case": "I-Shape",
|
| 569 |
+
"algs": [
|
| 570 |
+
{
|
| 571 |
+
"notation": "R U R' U R U' y R U' R' F'",
|
| 572 |
+
"moves": 11,
|
| 573 |
+
"note": "OH OLL"
|
| 574 |
+
}
|
| 575 |
+
]
|
| 576 |
+
},
|
| 577 |
+
{
|
| 578 |
+
"name": "OLL 53",
|
| 579 |
+
"case": "L-Shape",
|
| 580 |
+
"algs": [
|
| 581 |
+
{
|
| 582 |
+
"notation": "r' U' R U' R' U R U' R' U2 r",
|
| 583 |
+
"moves": 11,
|
| 584 |
+
"note": "OH OLL"
|
| 585 |
+
}
|
| 586 |
+
]
|
| 587 |
+
},
|
| 588 |
+
{
|
| 589 |
+
"name": "OLL 54",
|
| 590 |
+
"case": "L-Shape",
|
| 591 |
+
"algs": [
|
| 592 |
+
{
|
| 593 |
+
"notation": "r U R' U R U' R' U R U2 r'",
|
| 594 |
+
"moves": 11,
|
| 595 |
+
"note": "OH OLL"
|
| 596 |
+
}
|
| 597 |
+
]
|
| 598 |
+
},
|
| 599 |
+
{
|
| 600 |
+
"name": "OLL 55",
|
| 601 |
+
"case": "I-Shape",
|
| 602 |
+
"algs": [
|
| 603 |
+
{
|
| 604 |
+
"notation": "r U2 R' U' R2 r' U R' U' r U' r'",
|
| 605 |
+
"moves": 12,
|
| 606 |
+
"note": "OH OLL"
|
| 607 |
+
}
|
| 608 |
+
]
|
| 609 |
+
},
|
| 610 |
+
{
|
| 611 |
+
"name": "OLL 56",
|
| 612 |
+
"case": "I-Shape",
|
| 613 |
+
"algs": [
|
| 614 |
+
{
|
| 615 |
+
"notation": "r' U' r U' R' U R U' R' U R r' U r",
|
| 616 |
+
"moves": 14,
|
| 617 |
+
"note": "OH OLL"
|
| 618 |
+
}
|
| 619 |
+
]
|
| 620 |
+
},
|
| 621 |
+
{
|
| 622 |
+
"name": "OLL 57",
|
| 623 |
+
"case": "Corners Correct",
|
| 624 |
+
"algs": [
|
| 625 |
+
{
|
| 626 |
+
"notation": "R U R' U' r R' U R U' r'",
|
| 627 |
+
"moves": 10,
|
| 628 |
+
"note": "OH OLL"
|
| 629 |
+
}
|
| 630 |
+
]
|
| 631 |
+
}
|
| 632 |
+
]
|
| 633 |
+
};
|
json/pll.json.js
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
OH_ALGORITHMS.pll = {
|
| 2 |
+
"title": "OH PLL - Permutation of Last Layer",
|
| 3 |
+
"description": "OH PLL algorithms from CubeSkills by Feliks Zemdegs. All 21 cases.",
|
| 4 |
+
"cases": [
|
| 5 |
+
{
|
| 6 |
+
"name": "Ub (bar back)",
|
| 7 |
+
"case": "Edges Only",
|
| 8 |
+
"algs": [
|
| 9 |
+
{
|
| 10 |
+
"notation": "z U' R U' R' U' R' U' R U R U2",
|
| 11 |
+
"moves": 11,
|
| 12 |
+
"note": "OH"
|
| 13 |
+
}
|
| 14 |
+
]
|
| 15 |
+
},
|
| 16 |
+
{
|
| 17 |
+
"name": "Ub (bar front)",
|
| 18 |
+
"case": "Edges Only",
|
| 19 |
+
"algs": [
|
| 20 |
+
{
|
| 21 |
+
"notation": "R' U R' U' R' U' R' U R U R2",
|
| 22 |
+
"moves": 11,
|
| 23 |
+
"note": "OH"
|
| 24 |
+
}
|
| 25 |
+
]
|
| 26 |
+
},
|
| 27 |
+
{
|
| 28 |
+
"name": "Ua",
|
| 29 |
+
"case": "Edges Only",
|
| 30 |
+
"algs": [
|
| 31 |
+
{
|
| 32 |
+
"notation": "R U' R U R U R U' R' U' R2",
|
| 33 |
+
"moves": 11,
|
| 34 |
+
"note": "OH"
|
| 35 |
+
}
|
| 36 |
+
]
|
| 37 |
+
},
|
| 38 |
+
{
|
| 39 |
+
"name": "Z",
|
| 40 |
+
"case": "Edges Only",
|
| 41 |
+
"algs": [
|
| 42 |
+
{
|
| 43 |
+
"notation": "y R' U' R U' R U R U' R' U R U R2 U' R' U2",
|
| 44 |
+
"moves": 16,
|
| 45 |
+
"note": "OH"
|
| 46 |
+
}
|
| 47 |
+
]
|
| 48 |
+
},
|
| 49 |
+
{
|
| 50 |
+
"name": "H",
|
| 51 |
+
"case": "Edges Only",
|
| 52 |
+
"algs": [
|
| 53 |
+
{
|
| 54 |
+
"notation": "R2 U2 R U2 R2 U2 R2 U2 R U2 R2",
|
| 55 |
+
"moves": 11,
|
| 56 |
+
"note": "OH"
|
| 57 |
+
}
|
| 58 |
+
]
|
| 59 |
+
},
|
| 60 |
+
{
|
| 61 |
+
"name": "Aa",
|
| 62 |
+
"case": "Corners Only",
|
| 63 |
+
"algs": [
|
| 64 |
+
{
|
| 65 |
+
"notation": "x R' U R' D2 R U' R' D2 R2 x'",
|
| 66 |
+
"moves": 9,
|
| 67 |
+
"note": "OH"
|
| 68 |
+
}
|
| 69 |
+
]
|
| 70 |
+
},
|
| 71 |
+
{
|
| 72 |
+
"name": "Ab",
|
| 73 |
+
"case": "Corners Only",
|
| 74 |
+
"algs": [
|
| 75 |
+
{
|
| 76 |
+
"notation": "x R2 D2 R U R' D2 R U' R x'",
|
| 77 |
+
"moves": 9,
|
| 78 |
+
"note": "OH"
|
| 79 |
+
}
|
| 80 |
+
]
|
| 81 |
+
},
|
| 82 |
+
{
|
| 83 |
+
"name": "E",
|
| 84 |
+
"case": "Corners Only",
|
| 85 |
+
"algs": [
|
| 86 |
+
{
|
| 87 |
+
"notation": "x' R U' R' D R U R' D' R U R' D R U' R' D' x",
|
| 88 |
+
"moves": 16,
|
| 89 |
+
"note": "OH"
|
| 90 |
+
}
|
| 91 |
+
]
|
| 92 |
+
},
|
| 93 |
+
{
|
| 94 |
+
"name": "Ra",
|
| 95 |
+
"case": "Adjacent Corners",
|
| 96 |
+
"algs": [
|
| 97 |
+
{
|
| 98 |
+
"notation": "R U R' F' R U2 R' U2 R' F R U R U2 R'",
|
| 99 |
+
"moves": 15,
|
| 100 |
+
"note": "OH"
|
| 101 |
+
}
|
| 102 |
+
]
|
| 103 |
+
},
|
| 104 |
+
{
|
| 105 |
+
"name": "Rb",
|
| 106 |
+
"case": "Adjacent Corners",
|
| 107 |
+
"algs": [
|
| 108 |
+
{
|
| 109 |
+
"notation": "R' U2 R' D' R U' R' D R U R U' R' U' R",
|
| 110 |
+
"moves": 15,
|
| 111 |
+
"note": "OH"
|
| 112 |
+
}
|
| 113 |
+
]
|
| 114 |
+
},
|
| 115 |
+
{
|
| 116 |
+
"name": "Ja",
|
| 117 |
+
"case": "Adjacent Corners",
|
| 118 |
+
"algs": [
|
| 119 |
+
{
|
| 120 |
+
"notation": "R' U L' U2 R U' R' U2 R L",
|
| 121 |
+
"moves": 10,
|
| 122 |
+
"note": "OH"
|
| 123 |
+
}
|
| 124 |
+
]
|
| 125 |
+
},
|
| 126 |
+
{
|
| 127 |
+
"name": "Jb",
|
| 128 |
+
"case": "Adjacent Corners",
|
| 129 |
+
"algs": [
|
| 130 |
+
{
|
| 131 |
+
"notation": "R U2 R' U' R U2 L' U R' U' L",
|
| 132 |
+
"moves": 11,
|
| 133 |
+
"note": "OH"
|
| 134 |
+
}
|
| 135 |
+
]
|
| 136 |
+
},
|
| 137 |
+
{
|
| 138 |
+
"name": "T",
|
| 139 |
+
"case": "Adjacent Corners",
|
| 140 |
+
"algs": [
|
| 141 |
+
{
|
| 142 |
+
"notation": "R U R' U' R' F R2 U' R' U' R U R' F'",
|
| 143 |
+
"moves": 14,
|
| 144 |
+
"note": "OH"
|
| 145 |
+
}
|
| 146 |
+
]
|
| 147 |
+
},
|
| 148 |
+
{
|
| 149 |
+
"name": "F",
|
| 150 |
+
"case": "Adjacent Corners",
|
| 151 |
+
"algs": [
|
| 152 |
+
{
|
| 153 |
+
"notation": "R' U' F' R U R' U' R' F R2 U' R' U' R U R' U R",
|
| 154 |
+
"moves": 18,
|
| 155 |
+
"note": "OH"
|
| 156 |
+
}
|
| 157 |
+
]
|
| 158 |
+
},
|
| 159 |
+
{
|
| 160 |
+
"name": "V",
|
| 161 |
+
"case": "Diagonal Corners",
|
| 162 |
+
"algs": [
|
| 163 |
+
{
|
| 164 |
+
"notation": "R' U R U' x' U R U2 R' U' R U' R' U2 R U R' U'",
|
| 165 |
+
"moves": 17,
|
| 166 |
+
"note": "OH"
|
| 167 |
+
}
|
| 168 |
+
]
|
| 169 |
+
},
|
| 170 |
+
{
|
| 171 |
+
"name": "Y",
|
| 172 |
+
"case": "Diagonal Corners",
|
| 173 |
+
"algs": [
|
| 174 |
+
{
|
| 175 |
+
"notation": "F R U' R' U' R U R' F' R U R' U' R' F R F'",
|
| 176 |
+
"moves": 17,
|
| 177 |
+
"note": "OH"
|
| 178 |
+
}
|
| 179 |
+
]
|
| 180 |
+
},
|
| 181 |
+
{
|
| 182 |
+
"name": "Na",
|
| 183 |
+
"case": "Diagonal Corners",
|
| 184 |
+
"algs": [
|
| 185 |
+
{
|
| 186 |
+
"notation": "L U' R U2 L' U R' L U' R U2 L' U R'",
|
| 187 |
+
"moves": 14,
|
| 188 |
+
"note": "OH"
|
| 189 |
+
}
|
| 190 |
+
]
|
| 191 |
+
},
|
| 192 |
+
{
|
| 193 |
+
"name": "Nb",
|
| 194 |
+
"case": "Diagonal Corners",
|
| 195 |
+
"algs": [
|
| 196 |
+
{
|
| 197 |
+
"notation": "R' U L' U2 R U' L R' U L' U2 R U' L",
|
| 198 |
+
"moves": 14,
|
| 199 |
+
"note": "OH"
|
| 200 |
+
}
|
| 201 |
+
]
|
| 202 |
+
},
|
| 203 |
+
{
|
| 204 |
+
"name": "Ga",
|
| 205 |
+
"case": "G Perms",
|
| 206 |
+
"algs": [
|
| 207 |
+
{
|
| 208 |
+
"notation": "R2 U R' U R' U' R U' R2 D U' R' U R D'",
|
| 209 |
+
"moves": 15,
|
| 210 |
+
"note": "OH"
|
| 211 |
+
}
|
| 212 |
+
]
|
| 213 |
+
},
|
| 214 |
+
{
|
| 215 |
+
"name": "Gb",
|
| 216 |
+
"case": "G Perms",
|
| 217 |
+
"algs": [
|
| 218 |
+
{
|
| 219 |
+
"notation": "y' R' U' R U D' R2 U R' U R U' R U' R2 D",
|
| 220 |
+
"moves": 15,
|
| 221 |
+
"note": "OH"
|
| 222 |
+
}
|
| 223 |
+
]
|
| 224 |
+
},
|
| 225 |
+
{
|
| 226 |
+
"name": "Gc",
|
| 227 |
+
"case": "G Perms",
|
| 228 |
+
"algs": [
|
| 229 |
+
{
|
| 230 |
+
"notation": "R2 U' R U' R U R' U R2 D' U R U' R' D",
|
| 231 |
+
"moves": 15,
|
| 232 |
+
"note": "OH"
|
| 233 |
+
}
|
| 234 |
+
]
|
| 235 |
+
},
|
| 236 |
+
{
|
| 237 |
+
"name": "Gd",
|
| 238 |
+
"case": "G Perms",
|
| 239 |
+
"algs": [
|
| 240 |
+
{
|
| 241 |
+
"notation": "D' R U R' U' D R2 U' R U' R' U R' U R2",
|
| 242 |
+
"moves": 15,
|
| 243 |
+
"note": "OH"
|
| 244 |
+
}
|
| 245 |
+
]
|
| 246 |
+
}
|
| 247 |
+
]
|
| 248 |
+
};
|
json/zbll.json.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|