### 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.