### Redux Store Setup with createStore, registerReducer, registerSagas
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Dynamically assemble the Redux store at startup by registering reducers and sagas from feature modules. `createStore` then integrates these with a self-restarting root saga.
```typescript
import { createStore, registerReducer, registerSagas } from "core/redux/store";
// In a feature's init-store.ts:
import robotReducer from "app/robot/store/reducer";
import robotSagas from "app/robot/store/sagas";
import { watchSnackbarActions } from "core/snackbar/sagas";
registerReducer("robot", robotReducer);
registerSagas(robotSagas);
// robotSagas = [watchForScrambleSubmitted, watchForBluetoothDeviceSelected,
// watchForRobotConnected, watchForAppInitialized]
// In the app entry point (index.tsx):
const store = createStore();
// All registered sagas run wrapped in makeRestartable (auto-restart on crash)
// Run an additional saga manually (e.g. for snackbar notifications):
store.runSaga(watchSnackbarActions, snackbarRef);
```
--------------------------------
### Algorithm Validation, Parsing, and Inversion
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Utilities for processing algorithm move strings. `validateAlgorithm` checks against WCA notation, `parseAlgorithm` converts to integer indexes (optionally returning cube rotations), and `invertAlgorithm` reverses and inverts moves. `formatAlgorithm` converts integer indexes back to a string.
```typescript
import {
validateAlgorithm,
parseAlgorithm,
invertAlgorithm,
formatAlgorithm,
} from "core/cube/libs/algorithms";
// Validate: supports F R U B L D f r u b l d x y z M S E and modifiers 2 '
validateAlgorithm("R U R' U'"); // true
validateAlgorithm("R U R' U' Q"); // false — unknown move Q
// Parse to integer move indexes (0=F, 1=F2, 2=F', 3=R, 4=R2, 5=R' …)
parseAlgorithm("R U R'");
// => [3, 6, 5] (R=3, U=6, R'=5)
// With returnTotalRotation=true, also returns cube rotation moves encountered
const [moves, rotation] = parseAlgorithm("x R U R'", true);
// moves applied after stripping rotation, rotation = ["x"]
// Invert an algorithm
invertAlgorithm("R U R' U'");
// => "U R U' R'"
// Convert integer array back to string
formatAlgorithm([3, 6, 5]);
// => "R U R'"
```
--------------------------------
### Algorithm Utilities
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Utilities for validating, parsing, and inverting algorithm move strings.
```APIDOC
## `validateAlgorithm` / `parseAlgorithm` / `invertAlgorithm` — Algorithm utilities
### Description
`validateAlgorithm` checks a move string against the full WCA notation regex (including wide moves and rotations). `parseAlgorithm` normalises wide moves and cube rotations, then converts to an integer array. `invertAlgorithm` reverses and inverts every move in a sequence, supporting rotations.
### Functions
- `validateAlgorithm(algorithm: string): boolean` - Checks if a move string is valid WCA notation.
- `parseAlgorithm(algorithm: string, returnTotalRotation?: boolean): [number[], string[] | undefined]` - Parses a move string into an integer array of moves, optionally returning cube rotations.
- `invertAlgorithm(algorithm: string): string` - Reverses and inverts every move in a sequence.
- `formatAlgorithm(moves: number[]): string` - Converts an integer array of moves back to a string.
### Request Example
```typescript
import {
validateAlgorithm,
parseAlgorithm,
invertAlgorithm,
formatAlgorithm,
} from "core/cube/libs/algorithms";
// Validate: supports F R U B L D f r u b l d x y z M S E and modifiers 2 '
validateAlgorithm("R U R' U'"); // true
validateAlgorithm("R U R' U' Q"); // false — unknown move Q
// Parse to integer move indexes (0=F, 1=F2, 2=F', 3=R, 4=R2, 5=R' …)
parseAlgorithm("R U R'");
// => [3, 6, 5] (R=3, U=6, R'=5)
// With returnTotalRotation=true, also returns cube rotation moves encountered
const [moves, rotation] = parseAlgorithm("x R U R'", true);
// moves applied after stripping rotation, rotation = ["x"]
// Invert an algorithm
invertAlgorithm("R U R' U'");
// => "U R U' R'"
// Convert integer array back to string
formatAlgorithm([3, 6, 5]);
// => "R U R'"
```
### Response
- `validateAlgorithm`: `true` if valid, `false` otherwise.
- `parseAlgorithm`: An array containing the parsed moves and optionally the rotation.
- `invertAlgorithm`: The inverted algorithm string.
- `formatAlgorithm`: The formatted algorithm string.
```
--------------------------------
### getGANEncoding
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Encodes a standard WCA move notation string into an array of Uint8Array chunks suitable for Bluetooth transmission to the GAN Robot.
```APIDOC
## getGANEncoding
### Description
Converts a standard WCA move notation string into an array of `Uint8Array` chunks ready to write to the robot's GATT scramble characteristic. Each pair of moves is packed into one byte (nibble per move), and the robot's 18-character per-write limit is respected by chunking. Double-turn moves (`R2`) are automatically expanded to two singles because the robot occasionally fails on them.
### Method Signature
`getGANEncoding(scramble: string): Uint8Array[]`
### Parameters
- **scramble** (string) - Required - The scramble string in standard WCA notation.
### Request Example
```typescript
import { getGANEncoding } from "app/robot/store/sagas";
const scramble = "R F D L' B R2";
const chunks: Uint8Array[] = getGANEncoding(scramble);
// "R2" -> "R R" first, so the normalized string is "R F D L' B R R"
// Move codes: R=0, F=3, D=6, L'=11, B=12, R=0, R=0
// Paired encoding: [0*16+3]=3, [6*16+11]=107, [12*16+0]=192, [0*16+15]=15
// => [ Uint8Array([3, 107, 192, 15]) ]
// Multiple chunks (>16 encoded bytes) happen for long scrambles:
const longScramble = "R F D L' B R' F2 D2 L B' R F D' L2 B R' F D L'";
const multiChunk = getGANEncoding(longScramble);
// => [ Uint8Array([...16 bytes...]), Uint8Array([...remaining bytes...]) ]
```
```
--------------------------------
### Robot Connection and Scramble Dispatch with Redux Actions
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Drive robot lifecycle using Redux Toolkit actions. Dispatch `bluetoothDeviceSelected` after device selection and `scrambleSubmitted` to execute a scramble on the robot. The saga layer handles connection, verification, and execution.
```typescript
import { useDispatch } from "react-redux";
import {
bluetoothDeviceSelected,
scrambleSubmitted,
robotConnected,
robotDisconnected,
} from "app/robot/store/actions";
import { PRIMARY_SERVICE, DEVICE_INFO_SERVICE } from "app/robot/bluetooth";
// In a React component:
const dispatch = useDispatch();
// 1. Prompt the user to select a GAN device, then hand it to the saga
const handleConnect = async () => {
const device = await navigator.bluetooth.requestDevice({
filters: [{ namePrefix: "GAN-" }],
optionalServices: [PRIMARY_SERVICE, DEVICE_INFO_SERVICE],
});
dispatch(bluetoothDeviceSelected(device));
// Saga verifies model number === "GAN ROBOTCUBE", dispatches robotConnected
// or shows an error snackbar for wrong device types (GANDeviceTypeError)
};
// 2. Send a scramble to the connected robot
dispatch(scrambleSubmitted("R F2 D L' B R' D F L'"));
// Saga chunks the encoding and polls ROBOT_STATUS_CHARACTERISTIC until done
// 3. Disconnect is detected automatically via gattserverdisconnected event
// and dispatches robotDisconnected() internally
```
--------------------------------
### getScrambleForPieces
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Generates a robot-executable scramble that leaves only the specified edge and corner pieces in a scrambled state, with all other pieces solved. The function randomizes piece positions and orientations, enforces parity, applies the five-side solver twice, and retries until the resulting state is not accidentally already solved per the supplied predicate.
```APIDOC
## `getScrambleForPieces` — Generate a CFOP-stage partial scramble
### Description
Generates a robot-executable scramble that leaves only the specified edge and corner pieces in a scrambled state, with all other pieces solved. The function randomizes piece positions and orientations, enforces parity, applies the five-side solver twice (first to get a standard solve, then again to eliminate U turns), and retries until the resulting state is not accidentally already solved per the supplied predicate.
### Parameters
- `edges` (Edges[]) - An array of edge pieces to scramble.
- `corners` (Corners[]) - An array of corner pieces to scramble.
- `solveCriteria` (function) - A predicate function to check if the scramble is accidentally solved.
- `orientLastLayer` (boolean, optional) - If true, do not randomize orientation (pieces are already oriented).
### Request Example
```typescript
import getScrambleForPieces from "core/cube/libs/scramble-pieces";
import { Edges, Corners } from "core/cube/libs/cube";
import { isOLLSolved } from "core/cube/scramblers/solve-criteria";
// Scramble only top-layer edges and corners (OLL training)
const ollScramble = getScrambleForPieces(
[Edges.UR, Edges.UF, Edges.UL, Edges.UB], // edges to scramble
[Corners.URF, Corners.UFL, Corners.ULB, Corners.UBR], // corners to scramble
isOLLSolved // retry if this is accidentally true
);
// => "R F2 D L' B2 D' R F L'" or false on failure
```
### Response
- Returns a string representing the robot-executable scramble, or `false` on failure.
```
--------------------------------
### generateScramble
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Generates a pseudo-random, non-repeating scramble string using five-face moves. It guarantees the result is not accidentally in a solved state. Optional custom predicates and move counts can be supplied.
```APIDOC
## generateScramble
### Description
Generates a pseudo-random, non-repeating 24-move scramble string using five-face moves (no U turns), guaranteeing the result is not accidentally in a solved state (with respect to the top cross by default). An optional custom `isSolved` predicate and move count can be supplied.
### Method Signature
`generateScramble(moveCount?: number, isSolved?: (cubeState: any) => boolean): string`
### Parameters
- **moveCount** (number) - Optional - The desired number of moves in the scramble. Defaults to 24.
- **isSolved** (function) - Optional - A predicate function that determines if the cube is considered solved. Defaults to a check for the top cross being solved.
### Request Example
```typescript
import { generateScramble } from "core/cube/scramblers/full";
import { isCrossSolved, isF2LSolved } from "core/cube/scramblers/solve-criteria";
// Default: 24-move scramble, guaranteed top-cross is not solved
const scramble = generateScramble();
// => "R F2 D L' B R2 D' F L2 B' R D2 F' L B2 D R' F2 L' B D' R2 F L'"
// Custom length and predicate: 26-move scramble for Cross training
const crossScramble = generateScramble(26, isCrossSolved);
// => "B2 L D2 F' R2 B L' D F2 R B' ..."
// For F2L training (cross must not be solved either)
const f2lScramble = generateScramble(24, isF2LSolved);
```
```
--------------------------------
### fiveSideSolver / solveCube
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Solves a Rubik's cube using a modified Kociemba algorithm restricted to five-face moves (R, F, B, L, D). It can accept either a scramble string or a cube state object.
```APIDOC
## fiveSideSolver / solveCube
### Description
`fiveSideSolver` accepts either a standard WCA scramble string or a pre-computed coordinate index array and returns a robot-executable solution using only R, F, B, L, D moves (no U). `solveCube` accepts a raw `CubeIndexes` state object and delegates to `fiveSideSolver`. Both return `false` if no solution is found within `maxDepth` moves (default 40).
### Method Signatures
`fiveSideSolver(scramble: string | number[], maxDepth?: number): string | false`
`solveCube(cubeState: CubeIndexes, maxDepth?: number): string | false`
### Parameters
- **scramble** (string | number[]) - Required for `fiveSideSolver` - The scramble string in WCA notation or a pre-computed coordinate index array.
- **cubeState** (CubeIndexes) - Required for `solveCube` - The current state of the cube.
- **maxDepth** (number) - Optional - The maximum number of moves allowed for the solution. Defaults to 40.
### Request Example
```typescript
import { fiveSideSolver, solveCube } from "core/cube/solvers/five-side-solver";
import { doAlgorithm } from "core/cube/libs/cube";
// Solve from a scramble string (returns inverse = the scramble to apply)
const solution = fiveSideSolver("R U R' U' R' F R2 U' R' U' R U R' F'");
// => "F R' U R U' R U2 R' F'" (only 5-face moves)
// Solve with explicit max depth
const shortSolution = fiveSideSolver("R F D", 20);
// => "D' F' R'" or false if no solution within 20 moves
// Solve from a CubeIndexes state
const cubeState = doAlgorithm("R U R' F");
const stateSolution = solveCube(cubeState);
// => e.g. "F' R U' R'"
// Must call initialize() before first use (done automatically in index.tsx):
import { fiveSideSearch } from "core/cube/solvers/five-side-solver";
fiveSideSearch.initialize();
```
```
--------------------------------
### Detect Web Bluetooth Support
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Checks if the browser supports the Web Bluetooth API. Use this at startup to conditionally display Bluetooth connection options or an incompatibility message. Supported in Chrome 85+ desktop/Android; not in Firefox or Safari/iOS.
```typescript
import { detectBluetoothSupport } from "core/utils/feature-detection";
if (!detectBluetoothSupport()) {
// Show IncompatibleBrowserDialog or disable the connect button
console.warn("Web Bluetooth is not available in this browser.");
// Works in Chrome 85+ desktop/Android; NOT supported in Firefox or Safari/iOS
}
```
--------------------------------
### Generate Random Full Scramble (TypeScript)
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Generates a pseudo-random, non-repeating scramble string using five-face moves. Guarantees the result is not accidentally in a solved state. Can customize move count and the solved state predicate.
```typescript
import { generateScramble } from "core/cube/scramblers/full";
import { isCrossSolved, isF2LSolved } from "core/cube/scramblers/solve-criteria";
// Default: 24-move scramble, guaranteed top-cross is not solved
const scramble = generateScramble();
// => "R F2 D L' B R2 D' F L2 B' R D2 F' L B2 D R' F2 L' B D' R2 F L'"
// Custom length and predicate: 26-move scramble for Cross training
const crossScramble = generateScramble(26, isCrossSolved);
// => "B2 L D2 F' R2 B L' D F2 R B' ..."
// For F2L training (cross must not be solved either)
const f2lScramble = generateScramble(24, isF2LSolved);
```
--------------------------------
### Generate Scramble for Specific Pieces
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Generates a robot-executable scramble that targets only specified edge and corner pieces. It randomizes positions and orientations, enforces parity, and retries until the state is not accidentally solved according to a predicate. Use when you need to train specific piece permutations or orientations.
```typescript
import getScrambleForPieces from "core/cube/libs/scramble-pieces";
import { Edges, Corners } from "core/cube/libs/cube";
import { isOLLSolved } from "core/cube/scramblers/solve-criteria";
// Scramble only top-layer edges and corners (OLL training)
const ollScramble = getScrambleForPieces(
[Edges.UR, Edges.UF, Edges.UL, Edges.UB], // edges to scramble
[Corners.URF, Corners.UFL, Corners.ULB, Corners.UBR], // corners to scramble
isOLLSolved // retry if this is accidentally true
);
// => "R F2 D L' B2 D' R F L'" or false on failure
// Scramble only top corners (2nd look OLL)
const secondLookOLL = getScrambleForPieces(
[],
[Corners.URF, Corners.UFL, Corners.ULB, Corners.UBR],
isOLLSolved
);
```
```typescript
// PLL: orient last layer pieces (orientLastLayer = true)
const pllScramble = getScrambleForPieces(
[Edges.UR, Edges.UF, Edges.UL, Edges.UB],
[Corners.URF, Corners.UFL, Corners.ULB, Corners.UBR],
isCubeSolved,
true // do not randomise orientation (pieces are already oriented)
);
```
--------------------------------
### Check CFOP Stage Completion with Solve Criteria Predicates
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Utilize pure functions to test if a `CubeIndexes` state meets specific CFOP stage requirements. These predicates serve as scramble guards and F2L-scramble generation helpers.
```typescript
import { doAlgorithm } from "core/cube/libs/cube";
import {
isCrossSolved,
isF2LSolved,
isOLLSolved,
isFirstLookOLLSolved,
isCubeSolved,
isFirstLookPLLSolved,
} from "core/cube/scramblers/solve-criteria";
const state = doAlgorithm("R F D L' B");
isCrossSolved(state); // true if DB, DF, DL, DR edges are placed & oriented
isF2LSolved(state); // true if cross + all middle-layer pieces solved
isFirstLookOLLSolved(state); // true if F2L done + top edges oriented
isOLLSolved(state); // true if F2L done + entire top layer oriented
isFirstLookPLLSolved(state); // true if OLL done + top corners permuted (any U rotation)
isCubeSolved(state); // true if every piece is in home position
// Example: generate scrambles until top cross is genuinely scrambled
let s: string;
do { s = generateScramble(); }
while (isCrossSolved(doAlgorithm(s)));
```
--------------------------------
### Kociemba Five-Side Solver (TypeScript)
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Solves a cube using only R, F, B, L, D moves (no U turns), accepting either a scramble string or pre-computed coordinate index array. Returns `false` if no solution is found within `maxDepth` moves. `solveCube` accepts a raw `CubeIndexes` state object.
```typescript
import { fiveSideSolver, solveCube } from "core/cube/solvers/five-side-solver";
import { doAlgorithm } from "core/cube/libs/cube";
// Solve from a scramble string (returns inverse = the scramble to apply)
const solution = fiveSideSolver("R U R' U' R' F R2 U' R' U' R U R' F'");
// => "F R' U R U' R U2 R' F'" (only 5-face moves)
// Solve with explicit max depth
const shortSolution = fiveSideSolver("R F D", 20);
// => "D' F' R'" or false if no solution within 20 moves
// Solve from a CubeIndexes state
const cubeState = doAlgorithm("R U R' F");
const stateSolution = solveCube(cubeState);
// => e.g. "F' R U' R'"
// Must call initialize() before first use (done automatically in index.tsx):
import { fiveSideSearch } from "core/cube/solvers/five-side-solver";
fiveSideSearch.initialize();
```
--------------------------------
### Encode Scramble for Bluetooth Transmission (TypeScript)
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Converts a WCA move notation string into `Uint8Array` chunks for robot GATT characteristic writing. Packs pairs of moves into bytes and chunks data to respect the robot's 18-character limit per write. Expands double-turn moves (`R2`) to two singles.
```typescript
import { getGANEncoding } from "app/robot/store/sagas";
const scramble = "R F D L' B R2";
const chunks: Uint8Array[] = getGANEncoding(scramble);
// "R2" -> "R R" first, so the normalized string is "R F D L' B R R"
// Move codes: R=0, F=3, D=6, L'=11, B=12, R=0, R=0
// Paired encoding: [0*16+3]=3, [6*16+11]=107, [12*16+0]=192, [0*16+15]=15
// => [ Uint8Array([3, 107, 192, 15]) ]
// Multiple chunks (>16 encoded bytes) happen for long scrambles:
const longScramble = "R F D L' B R' F2 D2 L B' R F D' L2 B R' F D L'";
const multiChunk = getGANEncoding(longScramble);
// => [ Uint8Array([...16 bytes...]), Uint8Array([...remaining bytes...]) ]
```
--------------------------------
### getFaceletArray
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Computes the cube facelet colours for SVG preview.
```APIDOC
## `getFaceletArray` — Compute cube face colours for SVG preview
### Description
Given a `CubeIndexes` state and an optional `FaceletArrayFilter`, returns a 54-element string array of face-colour keys (`"U"`, `"R"`, `"F"`, `"D"`, `"L"`, `"B"`, or `"G"` for grey/hidden). Used by `CubePreview` to render the SVG net.
### Parameters
- `cubeState` (CubeIndexes) - The current state of the cube.
- `options` (object, optional) - Options for filtering facelets.
- `filter` (FaceletArrayFilter) - Specifies which pieces to show.
- `edges` (number[]) - Array of edge indices to display.
- `corners` (number[]) - Array of corner indices to display.
### Request Example
```typescript
import { doAlgorithm } from "core/cube/libs/cube";
import { getFaceletArray, FaceletArrayFilter } from "core/cube/libs/cube-preview";
const cubeState = doAlgorithm("R U R' U'");
// Full cube — all 54 facelets coloured
const allFacelets = getFaceletArray(cubeState);
// => ["U","R","U","U","U","F","U","U","R", ...54 items]
// Filtered: only show cross edges (D-layer edges), everything else grey
const crossFilter: FaceletArrayFilter = {
edges: [4, 5, 6, 7], // Edges.DR, DF, DL, DB
};
const filtered = getFaceletArray(cubeState, { filter: crossFilter });
// Non-cross facelets become "G" (rendered as gray in SVG)
```
### Response
- Returns a 54-element string array representing the facelet colours.
```
--------------------------------
### Compute Cube Facelet Colors for SVG Preview
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Computes a 54-element string array representing face colors for SVG rendering. It takes a `CubeIndexes` state and an optional `FaceletArrayFilter` to specify which facelets to color, with others defaulting to grey.
```typescript
import { doAlgorithm } from "core/cube/libs/cube";
import { getFaceletArray, FaceletArrayFilter } from "core/cube/libs/cube-preview";
const cubeState = doAlgorithm("R U R' U'");
// Full cube — all 54 facelets coloured
const allFacelets = getFaceletArray(cubeState);
// => ["U","R","U","U","U","F","U","U","R", ...54 items]
// Filtered: only show cross edges (D-layer edges), everything else grey
const crossFilter: FaceletArrayFilter = {
edges: [4, 5, 6, 7], // Edges.DR, DF, DL, DB
};
const filtered = getFaceletArray(cubeState, { filter: crossFilter });
// Non-cross facelets become "G" (rendered as gray in SVG)
```
--------------------------------
### Render Cube Net with CubePreview Component
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Use the CubePreview component to render an SVG net of a cube's state from a scramble code. It accepts optional filters to highlight specific pieces and color maps for custom color schemes.
```tsx
import { CubePreview } from "app/cube-preview";
import { Edges, Corners } from "core/cube/libs/cube";
// Basic usage — full cube preview
// CFOP OLL preview: only show F2L + top face, use inverted colour scheme
const ollFilter = {
edges: [4, 5, 6, 7, 8, 9, 10, 11], // all middle/bottom edges
corners: [4, 5, 6, 7], // bottom corners
facelets: ["U"], // U-face always shown
};
const invertedColors = {
U: "yellow", R: "red", F: "blue",
D: "white", L: "orange", B: "green", G: "gray",
};
// Empty string = solved cube preview
```
--------------------------------
### CFOP Stage-Specific Scramble Generators
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Convenience functions for generating scrambles for OLL and PLL stages of the CFOP method. These wrap `getScrambleForPieces` for common use cases. Each returns a robot-executable move string or `false` on failure.
```typescript
import {
generateOLLScramble,
generateFirstLookOLLScramble,
generateSecondLookOLLScramble,
generatePLLScramble,
generateFirstLookPLLScramble,
generateSecondLookPLLScramble,
} from "core/cube/scramblers/cfop";
// Full OLL: scramble all U-layer edges + corners (orientation only)
const oll = generateOLLScramble();
// => "R2 D' F L B' R D F' L2 B" or false
// 1st look OLL: only edge orientation on top layer
const ollLook1 = generateFirstLookOLLScramble();
// 2nd look OLL: only corner orientation on top layer
const ollLook2 = generateSecondLookOLLScramble();
// Full PLL: scramble top-layer edges + corners (permutation only)
const pll = generatePLLScramble();
// 1st look PLL: corners only
const pllLook1 = generateFirstLookPLLScramble();
// 2nd look PLL: edges only
const pllLook2 = generateSecondLookPLLScramble();
```
--------------------------------
### CFOP scramble generators
Source: https://context7.com/rsimp/gan-scrambler/llms.txt
Convenience functions for generating scrambles for each CFOP last-layer stage.
```APIDOC
## CFOP scramble generators — Stage-specific scramble helpers
### Description
Six convenience functions wrapping `getScrambleForPieces` for each CFOP last-layer stage. Each returns a robot-executable move string or `false`.
### Functions
- `generateOLLScramble()`: Full OLL: scramble all U-layer edges + corners (orientation only).
- `generateFirstLookOLLScramble()`: 1st look OLL: only edge orientation on top layer.
- `generateSecondLookOLLScramble()`: 2nd look OLL: only corner orientation on top layer.
- `generatePLLScramble()`: Full PLL: scramble top-layer edges + corners (permutation only).
- `generateFirstLookPLLScramble()`: 1st look PLL: corners only.
- `generateSecondLookPLLScramble()`: 2nd look PLL: edges only.
### Request Example
```typescript
import {
generateOLLScramble,
generateFirstLookOLLScramble,
generateSecondLookOLLScramble,
generatePLLScramble,
generateFirstLookPLLScramble,
generateSecondLookPLLScramble,
} from "core/cube/scramblers/cfop";
// Full OLL: scramble all U-layer edges + corners (orientation only)
const oll = generateOLLScramble();
// => "R2 D' F L B' R D F' L2 B" or false
```
### Response
- Returns a string representing the robot-executable scramble, or `false`.
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.