UNPKG

@vscubing/cubing

Version:

A collection of JavaScript cubing libraries.

1,347 lines (1,286 loc) 85.9 kB
import { Texture, Object3D, Raycaster, PerspectiveCamera, Scene, WebGLRenderer } from 'three'; type ExperimentalNotationType = "auto" | "LGN"; interface ExperimentalSerializationOptions { notation?: ExperimentalNotationType; } declare enum IterationDirection { Forwards = 1, Backwards = -1 } declare abstract class Comparable { is(c: any): boolean; as<T>(c: new (...args: any) => T): T | null; abstract isIdentical(other: Comparable): boolean; } interface Repeatable extends Comparable { experimentalExpand(iterDir?: IterationDirection, depth?: number): Generator<AlgLeaf>; } declare abstract class AlgCommon<T extends Alg | AlgNode> extends Comparable implements Repeatable { constructor(); get log(): (message?: any) => void; abstract toString(experimentalSerializationOptions?: ExperimentalSerializationOptions): string; abstract invert(): T; abstract experimentalExpand(iterDir: IterationDirection): Generator<AlgLeaf>; } interface QuantumMoveModifications { outerLayer?: number; innerLayer?: number; family?: string; } declare class QuantumMove extends Comparable { #private; constructor(family: string, innerLayer?: number | null, outerLayer?: number | null); static fromString(s: string): QuantumMove; modified(modifications: QuantumMoveModifications): QuantumMove; isIdentical(other: QuantumMove): boolean; /** @deprecated */ get family(): string; /** @deprecated */ get outerLayer(): number | null; /** @deprecated */ get innerLayer(): number | null; experimentalExpand(): Generator<AlgLeaf>; toString(experimentalSerializationOptions?: ExperimentalSerializationOptions): string; } interface MoveModifications { outerLayer?: number; innerLayer?: number; family?: string; amount?: number; } /** @category Alg Nodes */ declare class Move extends AlgCommon<Move> { #private; constructor(...args: [QuantumMove] | [QuantumMove, number] | [string] | [string, number]); isIdentical(other: Comparable): boolean; invert(): Move; experimentalExpand(iterDir?: IterationDirection): Generator<AlgLeaf>; get quantum(): QuantumMove; modified(modifications: MoveModifications): Move; static fromString(s: string): Move; get amount(): number; /** @deprecated */ get type(): string; /** @deprecated */ get family(): string; /** @deprecated */ get outerLayer(): number | undefined; /** @deprecated */ get innerLayer(): number | undefined; toString(experimentalSerializationOptions?: ExperimentalSerializationOptions): string; } /** @category Alg Nodes */ declare class Pause extends AlgCommon<Pause> { experimentalNISSGrouping?: Grouping; toString(experimentalSerializationOptions?: ExperimentalSerializationOptions): string; isIdentical(other: Comparable): boolean; invert(): Pause; experimentalExpand(_iterDir?: IterationDirection, _depth?: number): Generator<AlgLeaf>; } /** @category Alg Nodes */ declare class Grouping extends AlgCommon<Grouping> { #private; experimentalNISSPlaceholder?: Pause; constructor(algSource: FlexibleAlgSource, amount?: number); isIdentical(other: Comparable): boolean; get alg(): Alg; get amount(): number; /** @deprecated */ get experimentalRepetitionSuffix(): string; invert(): Grouping; experimentalExpand(iterDir?: IterationDirection, depth?: number): Generator<AlgLeaf>; static fromString(): Grouping; toString(experimentalSerializationOptions?: ExperimentalSerializationOptions): string; experimentalAsSquare1Tuple(): [moveU: Move, moveD: Move] | null; } /** @category Alg Nodes */ declare class LineComment extends AlgCommon<LineComment> { #private; constructor(commentText: string); get text(): string; isIdentical(other: Comparable): boolean; invert(): LineComment; experimentalExpand(_iterDir?: IterationDirection, _depth?: number): Generator<AlgLeaf>; toString(experimentalSerializationOptions?: ExperimentalSerializationOptions): string; } /** @category Alg Nodes */ declare class Commutator extends AlgCommon<Commutator> { #private; constructor(aSource: FlexibleAlgSource, bSource: FlexibleAlgSource); get A(): Alg; get B(): Alg; isIdentical(other: Comparable): boolean; invert(): Commutator; experimentalExpand(iterDir?: IterationDirection, depth?: number): Generator<AlgLeaf>; toString(experimentalSerializationOptions?: ExperimentalSerializationOptions): string; } /** @category Alg Nodes */ declare class Conjugate extends AlgCommon<Conjugate> { #private; constructor(aSource: FlexibleAlgSource, bSource: FlexibleAlgSource); get A(): Alg; get B(): Alg; isIdentical(other: Comparable): boolean; invert(): Conjugate; experimentalExpand(iterDir: IterationDirection, depth?: number): Generator<AlgLeaf>; toString(experimentalSerializationOptions?: ExperimentalSerializationOptions): string; } /** @category Alg Nodes */ declare class Newline extends AlgCommon<Newline> { toString(experimentalSerializationOptions?: ExperimentalSerializationOptions): string; isIdentical(other: Comparable): boolean; invert(): Newline; experimentalExpand(_iterDir?: IterationDirection, _depth?: number): Generator<AlgLeaf>; } /** @category Alg Nodes */ type AlgLeaf = Move | LineComment | Newline | Pause; /** @category Alg Nodes */ type AlgBranch = Grouping | Conjugate | Commutator; /** @category Alg Nodes */ type AlgNode = AlgLeaf | AlgBranch; declare const DEFAULT_DIRECTIONAL = "any-direction"; type QuantumDirectionalCancellation = typeof DEFAULT_DIRECTIONAL | "same-direction" | "none"; type ModWrap = "none" | "gravity" | "canonical-centered" | "canonical-positive" | "preserve-sign"; interface AppendCancelOptions { directional?: QuantumDirectionalCancellation; puzzleSpecificModWrap?: ModWrap; } interface AppendOptions { cancel?: boolean | AppendCancelOptions; puzzleLoader?: { puzzleSpecificSimplifyOptions?: PuzzleSpecificSimplifyOptions; }; puzzleSpecificSimplifyOptions?: PuzzleSpecificSimplifyOptions; } interface SimplifyOptions extends AppendOptions { depth?: number | null; } interface PuzzleSpecificAxisSimplifyInfo { areQuantumMovesSameAxis: (quantumMove1: QuantumMove, quantumMove2: QuantumMove) => boolean; simplifySameAxisMoves: (moves: Move[], quantumMod: boolean) => Move[]; } interface PuzzleSpecificSimplifyOptions { quantumMoveOrder?: (quantumMove: QuantumMove) => number; axis?: PuzzleSpecificAxisSimplifyInfo; } type FlexibleAlgSource = string | Iterable<AlgNode> | Alg; /** * `Alg` is a class that encapsulates a structured alg. To create an `Alg` from a string, use: * * new Alg("R U R'"); // Convenient * Alg.fromString(dynamicString); // Recommended when the string input is user-provided. * * Once you have an `Alg`, you can call methods to transform it: * * new Alg("[[R: U], R U R2']").expand().experimentalSimplify({cancel: true}).invert().log() * * To convert an `Alg` to a string, use .toString(): * * new Alg("R U F").invert().toString(); * * If you need to debug, you may also find it convenient to use .log(): * * if (alg.isIdentical(alg.invert())) { * alg.log("A self-inverse!") * } * * For more information, see: {@link https://js.cubing.net/cubing/alg/} * * @category Alg */ declare class Alg extends AlgCommon<Alg> { #private; constructor(alg?: FlexibleAlgSource); /** * Checks whether this Alg is structurally identical to another Alg. This * essentially means that they are written identically apart from whitespace. * * const alg1 = new Alg("R U L'"); * const alg2 = new Alg("L U' R'").invert(); * // true * alg1.isIdentical(alg2); * * // false * new Alg("[R, U]").isIdentical(new Alg("R U R' U'")); * // true * new Alg("[R, U]").expand().isIdentical(new Alg("R U R' U'")); * * Note that .isIdentical() efficiently compares algorithms, but mainly exists * to help optimize code when the structure of an algorithm hasn't changed. * There are many ways to write the "same" alg on most puzzles, but is * *highly* recommended to avoid expanding two Alg instances to compare them, * since that can easily slow your program to a crawl if someone inputs an alg * containing a large repetition. In general, you should use `cubing/kpuzzle` * to compare if two algs have the same effect on a puzzle. * * Also note that parser annotations are not taken into account while comparing * algs: * * const alg = new Alg([new Move("R"), new Move("U2")]); * // true, even though one of the algs has parser annotations * alg.isIdentical(new Alg("R U2")) * */ isIdentical(other: Comparable): boolean; /** * Returns the inverse of the given alg. * * Note that that this does not make any assumptions about what puzzle the alg * is for. For example, U2 is its own inverse on a cube, but U2' has the same * effect U3 (and not U2) on Megaminx: * * // Outputs: R U2' L' * new Alg("L U2 R'").invert().log(); */ invert(): Alg; /** @deprecated Use {@link Alg.expand} instead. */ experimentalExpand(iterDir?: IterationDirection, depth?: number): Generator<AlgLeaf>; /** * Expands all Grouping, Commutator, and Conjugate parts nested inside the * alg. * * // F R U R' U' F' * new Alg("[F: [R, U]]").expand().log(); * * // F [R, U] F' * new Alg("[F: [R, U]]").expand(({ depth: 1 }).log(); * * Avoid calling this on a user-provided alg unless the user explicitly asks * to see the expanded alg. Otherwise, it's easy to make your program freeze * when someone passes in an alg like: (R U)10000000 * * Generally, if you want to perform an operation on an entire alg, you'll * want to use something based on the `Traversal` mechanism, like countMoves() * from `cubing/notation`. */ expand(options?: { depth?: number; }): Alg; /** @deprecated */ experimentalLeafMoves(): Generator<Move>; concat(input: FlexibleAlgSource): Alg; /** @deprecated */ experimentalIsEmpty(): boolean; static fromString(s: string): Alg; /** @deprecated */ units(): Generator<AlgNode>; childAlgNodes(): Generator<AlgNode>; /** @deprecated */ experimentalNumUnits(): number; experimentalNumChildAlgNodes(): number; /** @deprecated */ get type(): string; /** * Converts the Alg to a string: * * const alg = new Alg([new Move("R"), new Move("U2"), new Move("L")]) * // R U2 L * console.log(alg.toString()) */ toString(experimentalSerializationOptions?: ExperimentalSerializationOptions): string; /** * `experimentalSimplify` can perform several mostly-syntactic simplifications on an alg: * * // Logs: R' U3 * import { Alg } from "@vscubing/cubing/alg"; * new Alg("R R2' U U2").experimentalSimplify({ cancel: true }).log() * * You can pass in a `PuzzleLoader` (currently only for 3x3x3) for puzzle-specific simplifications: * * // Logs: R' U' * import { Alg } from "@vscubing/cubing/alg"; * import { cube3x3x3 } from "@vscubing/cubing/puzzles"; * new Alg("R R2' U U2").experimentalSimplify({ cancel: true, puzzleLoader: cube3x3x3 }).log() * * You can also cancel only moves that are in the same direction: * * // Logs: R R2' U' * import { Alg } from "@vscubing/cubing/alg"; * import { cube3x3x3 } from "@vscubing/cubing/puzzles"; * new Alg("R R2' U U2").experimentalSimplify({ * cancel: { directional: "same-direction" }, * puzzleLoader: cube3x3x3 * }).log() * * Additionally, you can specify how moves are "wrapped": * * import { Alg } from "@vscubing/cubing/alg"; * import { cube3x3x3 } from "@vscubing/cubing/puzzles"; * * function example(puzzleSpecificModWrap) { * alg.experimentalSimplify({ * cancel: { puzzleSpecificModWrap }, * puzzleLoader: cube3x3x3 * }).log() * } * * const alg = new Alg("R7' . R6' . R5' . R6") * example("none") // R7' . R6' . R5' . R6 * example("gravity") // R . R2' . R' . R2 * example("canonical-centered") // R . R2 . R' . R2 * example("canonical-positive") // R . R2 . R3 . R2 * example("preserve-sign") // R3' . R2' . R' . R2 * * Same-axis and simultaneous move canonicalization is not implemented yet: * * // Logs: R L R * import { Alg } from "@vscubing/cubing/alg"; * import { cube3x3x3 } from "@vscubing/cubing/puzzles"; * new Alg("R L R").experimentalSimplify({ cancel: true, puzzleLoader: cube3x3x3 }).log() */ experimentalSimplify(options?: SimplifyOptions): Alg; /** @deprecated See {@link experimentalSimplify} */ simplify(options?: SimplifyOptions): Alg; } interface NotationMapper { notationToInternal(move: Move): Move | null; notationToExternal(move: Move): Move | null; } declare function parseOptions(argv: string[]): { puzzleDescription: PuzzleDescription | null; options: PuzzleGeometryOptions; }; type FaceName = string; type OrientationDirection = [number, number, number]; type FaceBasedOrientationDescription = [ [ FaceName, OrientationDirection ], [ FaceName, OrientationDirection ] ]; type BaseFaceCount = 4 | 6 | 8 | 12 | 20; type FaceBasedOrientationDescriptionLookup = Record<BaseFaceCount, FaceBasedOrientationDescription>; declare class PuzzleGeometryFullOptions { verbosity: number; allMoves: boolean; outerBlockMoves: boolean; vertexMoves: boolean; addRotations: boolean; moveList: string[] | null; fixedOrientation: boolean; fixedPieceType: null | "e" | "v" | "f"; orientCenters: boolean; includeCornerOrbits: boolean; includeCenterOrbits: boolean; includeEdgeOrbits: boolean; excludeOrbits: string[]; optimizeOrbits: boolean; grayCorners: boolean; grayCenters: boolean; grayEdges: boolean; puzzleOrientation: FaceBasedOrientationDescription | null; puzzleOrientations: FaceBasedOrientationDescriptionLookup | null; scrambleAmount: number; constructor(options?: PuzzleGeometryOptions); } type PuzzleGeometryOptions = Partial<PuzzleGeometryFullOptions>; declare class Perm { n: number; p: number[]; constructor(a: number[]); toString(): string; mul(p2: Perm): Perm; rmul(p2: Perm): Perm; inv(): Perm; compareTo(p2: Perm): number; toGap(): string; toMathematica(): string; order(): number; } declare class KTransformation { #private; readonly kpuzzle: KPuzzle; readonly transformationData: KTransformationData; constructor(kpuzzle: KPuzzle, transformationData: KTransformationData); toJSON(): any; invert(): KTransformation; isIdentityTransformation(): boolean; /** @deprecated */ static experimentalConstructIdentity(kpuzzle: KPuzzle): KTransformation; isIdentical(t2: KTransformation): boolean; /** @deprecated */ apply(source: KTransformationSource): KTransformation; applyTransformation(t2: KTransformation): KTransformation; applyMove(move: Move | string): KTransformation; applyAlg(alg: Alg | string): KTransformation; toKPattern(): KPattern; repetitionOrder(): number; selfMultiply(amount: number): KTransformation; } declare class KPattern { readonly kpuzzle: KPuzzle; readonly patternData: KPatternData; constructor(kpuzzle: KPuzzle, patternData: KPatternData); toJSON(): any; static fromTransformation(transformation: KTransformation): KPattern; /** @deprecated */ apply(source: KTransformationSource): KPattern; applyTransformation(transformation: KTransformation): KPattern; applyMove(move: Move | string): KPattern; applyAlg(alg: Alg | string): KPattern; isIdentical(other: KPattern): boolean; /** @deprecated */ experimentalToTransformation(): KTransformation | null; experimentalIsSolved(options: { ignorePuzzleOrientation: boolean; ignoreCenterOrientation: boolean; }): boolean; } type KPatternData = Record<string, KPatternOrbitData>; interface KPatternOrbitData { pieces: number[]; orientation: number[]; /** Each piece may have an "orientation mod" that means "the orientation of * this piece is known mod [value]". * * Suppose `.numOrientations` for this orbit has a value of N. This is * considered the default value for the orientation mod of each piece in the * orbit. * * - Each entry must be one of the following: * - A proper divisor of N. * - For example: if N is 12, then one of: 1, 2, 3, 6 * - The special value 0, indicating the default value (N). * - This indicates that the orientation of a piece is fully known, i.e. * that its "orientation mod" is the default value (N). However, such a * value is recorded as 0 instead of N, in order to make it simpler to * implement and debug pattern logic involving the default value. * - If `.orientationMod[i]` is a proper divisor of N (i.e. not 0), then * `.orientation[i]` must be less than `.orientationMod[i]`. That is, the * orientation values must be individually "normalized" for each piece. * - If the `orientationMod` field is not present, then every piece is * considered to have the default value for its "orientation mod". * * For a "real-world" example of this concept, consider a traditional analog * 12-hour clock dial, like one that might hang on the wall in a school room. * Although there are 24 hours in a day, A.M. and P.M. times are not * distinguishable on such a clock. Since 3:00 (AM) and 15:00 are not * distinguishable, we would read either of those times as 3:00 with an * implicit "orientation mod" of 12. * * For most puzzles, however, we care about "visual" indistinguishability * rather than "temporal" indistinguishability. To adapt the previous example, * imagine a 24-hour clock with 24 hour marks around the dial, but where the * hour hand is symmetric and points equally at the current hour as well as * its diametic opposite (like a compass needle but painted all in one color). * This has the same set of "valid patterns" as a normal 12-hour clock. Such a * clock also has an "orientation mod" of 12, but where the multiples of the * modulus have been "unfolded" to show their full symmetry instead of being * implicit. * * For a non-trivial puzzle example, consider Eitan's FisherTwist, a shape mod * of the 3x3x3 cube: * https://www.hknowstore.com/locale/en-US/item.aspx?corpname=nowstore&itemid=97eb4e89-367e-4d02-b7f0-34e5e7f3cd12 * * - The 4 equatorial centers have C₂ symmetry — it is possible to rotate any * of these centers 180° without a visible change to the state. This means * that the possible orientations "loop" after incrementing the orientation * by 2 (two turns clockwise), and therefore the "orientation mod" of a * given piece is only 2. * - If we apply a counter-clockwise rotation to one of these centers, the * transformation applies an orientation of 3. But the net orientation is * recorded as a normalized value of 1 instead, because 3 (mod 2) ≡ 1 (mod * 2). * - The 2 polar centers (U and D) have no distinguishable rotations. This * means that their orientation is "known mod 1" — any transformation of one * of these centers is indistinguishable from another transformation of the * same center, and all of them are mapped to a value of 0 (the only * possible value that exists mod 1). * * For 3x3x3: * * - When solving a normal 3x3x3, center orientations are conventionally * ignored. This is similar to the polar center case for Eitan's * FisherTwist, and the "orientation mod" of each piece is 1. This is also * the core motivating use case. * - For a supercube * (https://experiments.cubing.net/cubing.js/twisty/supercube.html) or the * general case of a "picture cube", all four center orientations are * distinguishable for every center. This means all centers have the default * orientation mod of 4. As documented above, this can be recorded with a * `.orientationMod` of `[0, 0, 0, 0, 0, 0]`, or equivalently by omitting * the `.orientationMod` field. * - When modeling a real 3x3x3 speedcube, it is common to have a logo on a * single sticker. If you want to model the exact visually distinguishable * states of such a puzzles, it is possible to use an `.orientationMod` such * as `[0, 1, 1, 1, 1, 1]`. For example, this can make it easy to find an * alg for a given case "while keeping the logo the same", without placing * more restrictions on other centers (which could make the search slower or * produce longer solutions). * * For those with a mathematical background, you may notice a relationship to * the concept of a coset (https://en.wikipedia.org/wiki/Coset). For example, * consider the group of patterns of a `KPuzzle` (without indistinguishable * pieces) generated by a set of transformations. We can assign each set of * piece orbits an orientation mod value (which must be identical for all * constituent pieces of the same orbit). Each such choice generates a set of * valid `KPattern`s that forms a subgroup, and each set of valid `.orientation` * values defines one coset of this set. However, note that the set of valid * `KPattern`s does *not* form a group when there are any pieces with different * `.orientationMod` values that share an orbit. * * -------- * * Note that the concept of "orientation mod" exclusively applies to `KPattern`, * not `KTransformation`. If we tried to apply the orientation mod * calculations to the *transformations* of Eitan's FisherTwist, then `SWAP = * [U, M' E2 M]` would be indistinguishable from the identity. This would mean * that if we calculated `SWAP` and then used this calculation for `S SWAP * S'`, then we would conclude that it has no net effect. However, `S SWAP S'` * does *not* have the same effect as doing nothing — it visibly rotates the L * and R centers! (In mathematical terms: the set of `KTransformation`s would * not form a valid set of semigroup actions, due to broken associativity.) * * Although there are times that we could theoretically save some time/space * by ignoring some information when it's not needed for working with certain * `KTransformation`s (e.g. ignoring all center orientations for 3x3x3), it is * more practical for each `KTransformation` to always track the full range * for each piece's `.orientation`. For example: * * - This is simpler, both conceptually and in code. * - This allows changing the set of moves for a puzzle, without recalculating * cached transformations or certain lookup tables (useful for alg * searches). * - This allows swapping out a normal 3x3x3 in a `<twisty-player>` for a * picture cube, without re-calculating the center orientations of the * current alg. * * These use cases may not be strictly "necessary", but the opposite behaviour * might be surprising or frustrating if someone does not expect it. So we * implement it this way. * * Informally, the `KTransformation` has the full responsibility for tracking * "what really happens" — even if the effect is invisible in some cases, * while the `KPattern` tracks both what "is" and what "isn't" known. **/ orientationMod?: number[]; } type KTransformationData = Record<string, KTransformationOrbitData>; interface KTransformationOrbitData { permutation: number[]; orientationDelta: number[]; } interface KPuzzleOrbitDefinition { orbitName: string; numPieces: number; numOrientations: number; } interface KPuzzleDefinition { name: string; orbits: KPuzzleOrbitDefinition[]; defaultPattern: KPatternData; moves: Record<string, KTransformationData>; derivedMoves?: Record<string, string>; experimentalIsPatternSolved?: (kpattern: KPattern, options: { ignorePuzzleOrientation: boolean; ignoreCenterOrientation: boolean; }) => boolean; } declare class PGOrbitDef { size: number; mod: number; constructor(size: number, mod: number); reassemblySize(): bigint; } declare class PGOrbitsDef { orbitnames: string[]; private orbitdefs; solved: VisibleState; movenames: string[]; moveops: PGTransform[]; isRotation: boolean[]; forcenames: boolean[]; constructor(orbitnames: string[], orbitdefs: PGOrbitDef[], solved: VisibleState, movenames: string[], moveops: PGTransform[], isRotation: boolean[], forcenames: boolean[]); toKTransformationData(t: PGTransform): KTransformationData; toKPatternData(t: PGTransform): KPatternData; static transformToKTransformationData(orbitnames: string[], t: PGTransform): KTransformationData; private describeSet; toKsolve(name: string, mapper?: NotationMapper): string[]; toKPuzzleDefinition(includemoves: boolean): KPuzzleDefinition; optimize(): PGOrbitsDef; scramble(n: number): void; getScrambleTransformation(n: number): PGTransform; reassemblySize(): bigint; } declare class PGOrbit { perm: number[]; ori: number[]; orimod: number; private static ktransformationCache; static e(n: number, mod: number): PGOrbit; constructor(perm: number[], ori: number[], orimod: number); mul(b: PGOrbit): PGOrbit; inv(): PGOrbit; equal(b: PGOrbit): boolean; killOri(): this; toPerm(): Perm; identicalPieces(): number[][]; order(): number; isIdentity(): boolean; private zeroOris; remap(no: number[], on: number[], nv: number): PGOrbit; remapVS(no: number[], nv: number): PGOrbit; appendDefinition(result: string[], name: string, useVS: boolean, concise?: boolean): void; toKTransformationOrbitData(): KTransformationOrbitData; toKPatternOrbitData(): KPatternOrbitData; } declare class PGTransformBase { orbits: PGOrbit[]; constructor(orbits: PGOrbit[]); internalMul(b: PGTransformBase): PGOrbit[]; protected internalInv(): PGOrbit[]; equal(b: PGTransformBase): boolean; protected killOri(): this; toPerm(): Perm; identicalPieces(): number[][]; order(): number; } declare class PGTransform extends PGTransformBase { mul(b: PGTransform): PGTransform; mulScalar(n: number): PGTransform; inv(): PGTransform; e(): PGTransform; } declare class VisibleState extends PGTransformBase { mul(b: PGTransform): VisibleState; } type PuzzleDescriptionString = string; declare const PGPuzzles: { [name: string]: PuzzleDescriptionString; }; type PuzzleName = keyof typeof PGPuzzles; declare class Quat { a: number; b: number; c: number; d: number; constructor(a: number, b: number, c: number, d: number); mul(q: Quat): Quat; toString(): string; dist(q: Quat): number; len(): number; cross(q: Quat): Quat; dot(q: Quat): number; normalize(): Quat; makenormal(): Quat; normalizeplane(): Quat; smul(m: number): Quat; sum(q: Quat): Quat; sub(q: Quat): Quat; angle(): number; invrot(): Quat; det3x3(a00: number, a01: number, a02: number, a10: number, a11: number, a12: number, a20: number, a21: number, a22: number): number; rotateplane(q: Quat): Quat; orthogonal(): Quat; pointrotation(b: Quat): Quat; unproject(b: Quat): Quat; rotatepoint(q: Quat): Quat; rotateface(face: Quat[]): Quat[]; intersect3(p2: Quat, p3: Quat): Quat | false; side(x: number): number; /** * Cuts a face by this plane, or returns null if there * is no intersection. * @param face The face to cut. */ cutface(face: Quat[]): Quat[][] | null; cutfaces(faces: Quat[][]): Quat[][]; faceside(face: Quat[]): number; sameplane(p: Quat): boolean; makecut(r: number): Quat; } interface TextureMapper { getuv(fn: number, threed: number[]): number[]; } interface StickerDatSticker { coords: number[]; color: string; orbit: string; ord: number; ori: number; face: number; isDup?: boolean; } interface StickerDatFace { coords: number[]; name: string; } type StickerDatAxis = { coordinates: number[]; quantumMove: Move; order: number; }; interface StickerDat { stickers: StickerDatSticker[]; faces: StickerDatFace[]; axis: StickerDatAxis[]; unswizzle(mv: Move): Move | null; notationMapper: NotationMapper; textureMapper: TextureMapper; } declare function getPG3DNamedPuzzles(): { [s: string]: PuzzleDescriptionString; }; declare function getPuzzleDescriptionString(puzzleName: PuzzleName): PuzzleDescriptionString; declare const PUZZLE_BASE_SHAPES: readonly ["c", "t", "o", "d", "i"]; type PuzzleBaseShape = (typeof PUZZLE_BASE_SHAPES)[number]; declare const PUZZLE_CUT_TYPES: readonly ["f", "v", "e"]; type PuzzleCutType = (typeof PUZZLE_CUT_TYPES)[number]; type PuzzleCutDescription = { cutType: PuzzleCutType; distance: number; }; type PuzzleDescription = { shape: PuzzleBaseShape; cuts: PuzzleCutDescription[]; }; declare function parsePuzzleDescription(s: PuzzleDescriptionString): PuzzleDescription | null; declare function getPuzzleGeometryByDesc(desc: string, options?: PuzzleGeometryOptions): PuzzleGeometry; declare function getPuzzleGeometryByName(puzzleName: PuzzleName, options?: PuzzleGeometryOptions): PuzzleGeometry; type MoveSetGeo = [string, string, string, string, number]; /** @category PuzzleGeometry */ declare class PuzzleGeometry { puzzleDescription: PuzzleDescription; private rotations; baseplanerot: Quat[]; private baseplanes; private facenames; private faceplanes; private edgenames; private vertexnames; private geonormals; private moveplanes; private moveplanes2; moveplanesets: Quat[][]; private moveplanenormals; movesetorders: number[]; movesetgeos: MoveSetGeo[]; private basefaces; private faces; private facecentermass; private baseFaceCount; stickersperface: number; shortedge: number; private markedface; cubies: number[][]; private vertexdistance; private edgedistance; private facetocubie; private facetoord; private moverotations; private facelisthash; private cubiesetnames; private cubieords; private cubiesetnums; private cubieordnums; private orbitoris; private cubievaluemap; private cubiesetcubies; cmovesbyslice: number[][][]; parsedmovelist: [ string | undefined, number, number, number, boolean, number ][]; private duplicatedFaces; private duplicatedCubies; private fixedCubie; private net; private colors; private swizzler; notationMapper: NotationMapper; private addNotationMapper; private setReidOrder; private options; constructor(puzzleDescription: PuzzleDescription, options: PuzzleGeometryOptions); create(puzzleDescription: PuzzleDescription): void; private keyface; private keyface2; private keyface3; private findface; private project2d; allstickers(): void; unswizzle(mv: Move): Move | null; private stringToBlockMove; parseMove(move: Move): [string | undefined, number, number, number, boolean, number]; private parsemove; genperms(): void; private getboundarygeometry; private getmovesets; private graybyori; private skipbyori; private skipcubie; private header; writegap(): string; writemathematica(): string; writeksolve(name?: string): string; getKPuzzleDefinition(fortwisty?: boolean, includemoves?: boolean): KPuzzleDefinition; getMoveFromBits(moverange: number[], amount: number, inverted: boolean, axiscmoves: number[][], setmoves: number[] | undefined, movesetorder: number): PGTransform; private omitSet; private diffmvsets; getOrbitsDef(fortwisty: boolean, includemoves?: boolean): PGOrbitsDef; getScramble(n?: number): KTransformationData; getMovesAsPerms(): Perm[]; showcanon(disp: (s: string) => void): void; getsolved(): Perm; private getOrientationRotation; private getInitial3DRotation; private generate2dmapping; generatesvg(w?: number, h?: number, trim?: number, threed?: boolean): string; get3d(options?: { stickerColors?: string[]; darkIgnoredOrbits?: boolean; }): StickerDat; getGeoNormal(geoname: string): number[] | undefined; private getfaceindex; textForTwizzleExplorer(): string; writeSchreierSims(tw: (s: string) => void): void; } declare class PGNotation { private pg; private orbitNames; constructor(pg: PuzzleGeometry, od: PGOrbitsDef); lookupMove(move: Move): KTransformationData | null; remapKPuzzleDefinition(kpuzzleDefinition: KPuzzleDefinition): KPuzzleDefinition; } type KTransformationSource = Alg | Move | string | KTransformation; declare class KPuzzle { #private; readonly definition: KPuzzleDefinition; private experimentalPGNotation; constructor(definition: KPuzzleDefinition, options?: { experimentalPGNotation?: PGNotation; }); lookupOrbitDefinition(orbitName: string): KPuzzleOrbitDefinition; name(): string; identityTransformation(): KTransformation; moveToTransformation(move: Move | string): KTransformation; algToTransformation(alg: Alg | string): KTransformation; /** @deprecated */ toTransformation(source: KTransformationSource): KTransformation; defaultPattern(): KPattern; canConvertDefaultPatternToUniqueTransformation(): boolean; } declare const experimentalStickerings: Record<string, { groups?: Partial<Record<PuzzleID, string>>; }>; type FaceletMeshStickeringMask = "regular" | "dim" | "oriented" | "experimentalOriented2" | "ignored" | "invisible" | "mystery"; type FaceletStickeringMask = { mask: FaceletMeshStickeringMask; hintMask?: FaceletMeshStickeringMask; }; type PieceStickeringMask = { facelets: (FaceletMeshStickeringMask | FaceletStickeringMask | null)[]; }; type OrbitStickeringMask = { pieces: (PieceStickeringMask | null)[]; }; type StickeringMask = { specialBehaviour?: "picture"; name?: string; orbits: Record<string, OrbitStickeringMask>; }; type MillisecondTimestamp = number; type Duration = MillisecondTimestamp; type Timestamp = MillisecondTimestamp; declare enum Direction { Forwards = 1, Paused = 0, Backwards = -1 } interface MoveInProgress { move: Move; direction: Direction; fraction: number; } type PuzzlePosition = { pattern: KPattern; movesInProgress: MoveInProgress[]; }; declare enum BoundaryType { Move = "move", EntireTimeline = "entire-timeline" } interface TimeRange { start: MillisecondTimestamp; end: MillisecondTimestamp; } interface UserVisibleError { errors: string[]; } declare class UserVisibleErrorTracker extends SimpleTwistyPropSource<UserVisibleError> { getDefaultValue(): UserVisibleError; reset(): void; protected canReuseValue(_v1: UserVisibleError, _v2: UserVisibleError): boolean; } type InputRecord = Record<string, any>; type InputProps<T extends InputRecord> = { [s in keyof T]: TwistyPropParent<T[s]>; }; interface SourceEventDetail<OutputType> { sourceProp: TwistyPropSource<OutputType, any>; value: Promise<OutputType>; generation: number; } type SourceEvent<T> = CustomEvent<SourceEventDetail<T>>; type PromiseOrValue<T> = T | Promise<T>; declare abstract class TwistyPropParent<T> { #private; abstract get(): Promise<T>; canReuse(v1: T, v2: T): boolean; protected canReuseValue(_v1: T, _v2: T): boolean; debugGetChildren(): TwistyPropDerived<any, any>[]; protected addChild(child: TwistyPropDerived<any, any>): void; protected removeChild(child: TwistyPropDerived<any, any>): void; protected lastSourceGeneration: number; protected markStale(sourceEvent: SourceEvent<any>): void; /** @deprecated */ addRawListener(listener: () => void, options?: { initial: boolean; }): void; /** @deprecated */ removeRawListener(listener: () => void): void; addFreshListener(listener: (value: T) => void): void; removeFreshListener(listener: (value: T) => void): void; } declare abstract class TwistyPropSource<OutputType, InputType = OutputType> extends TwistyPropParent<OutputType> { #private; abstract getDefaultValue(): PromiseOrValue<OutputType>; constructor(initialValue?: PromiseOrValue<InputType>); set(input: PromiseOrValue<InputType>): void; get(): Promise<OutputType>; protected deriveFromPromiseOrValue(input: PromiseOrValue<InputType>, oldValuePromise: Promise<OutputType>): Promise<OutputType>; protected abstract derive(input: InputType, oldValuePromise: Promise<OutputType>): PromiseOrValue<OutputType>; } declare abstract class SimpleTwistyPropSource<SimpleType> extends TwistyPropSource<SimpleType> { protected derive(input: SimpleType): PromiseOrValue<SimpleType>; } declare const NO_VALUE: unique symbol; type NoValueType = typeof NO_VALUE; declare abstract class TwistyPropDerived<InputTypes extends InputRecord, OutputType> extends TwistyPropParent<OutputType> { #private; protected userVisibleErrorTracker?: UserVisibleErrorTracker | undefined; constructor(parents: InputProps<InputTypes>, userVisibleErrorTracker?: UserVisibleErrorTracker | undefined); get(): Promise<OutputType>; protected abstract derive(input: InputTypes): PromiseOrValue<OutputType>; } type SimpleDirection = Direction.Forwards | Direction.Backwards; interface PlayingInfo { playing: boolean; direction: SimpleDirection; untilBoundary: BoundaryType; loop: boolean; } declare class PlayingInfoProp extends TwistyPropSource<PlayingInfo, Partial<PlayingInfo>> { getDefaultValue(): Promise<PlayingInfo>; protected derive(newInfo: Partial<PlayingInfo>, oldValuePromise: Promise<PlayingInfo>): Promise<PlayingInfo>; protected canReuseValue(v1: PlayingInfo, v2: PlayingInfo): boolean; } declare class ArbitraryStringProp extends SimpleTwistyPropSource<string | null> { getDefaultValue(): string | null; } declare class URLProp extends TwistyPropSource<URL | null, URL | string | null> { getDefaultValue(): URL | null; derive(input: URL | string | null): URL | null; } declare class AlgIssues { readonly warnings: readonly string[]; readonly errors: readonly string[]; constructor(issues?: { warnings?: string[]; errors?: string[]; }); add(issues?: { warnings?: string[]; errors?: string[]; }): AlgIssues; /** @deprecated */ log(): void; } interface AlgWithIssues { alg: Alg; issues: AlgIssues; } declare class AlgProp extends TwistyPropSource<AlgWithIssues, Alg | string> { getDefaultValue(): AlgWithIssues; protected canReuseValue(v1: AlgWithIssues, v2: AlgWithIssues): boolean; protected derive(newAlg: Alg | string): Promise<AlgWithIssues>; } type AlgTransformationPropInputs = { setupAlg: AlgWithIssues; kpuzzle: KPuzzle; }; declare class AlgTransformationProp extends TwistyPropDerived<AlgTransformationPropInputs, KTransformation> { derive(input: AlgTransformationPropInputs): KTransformation; } type AnimatedLeafAlgNode = Move | Pause; interface CurrentMove { move: Move; direction: Direction; fraction: number; startTimestamp: MillisecondTimestamp; endTimestamp: MillisecondTimestamp; } interface CurrentMoveInfo { patternIndex: number; currentMoves: CurrentMove[]; movesFinishing: CurrentMove[]; movesFinished: CurrentMove[]; movesStarting: CurrentMove[]; latestStart: number; earliestEnd: number; } interface AlgIndexer { getAnimLeaf(index: number): AnimatedLeafAlgNode | null; indexToMoveStartTimestamp(index: number): Timestamp; patternAtIndex(index: number, startPattern?: KPattern): KPattern; transformationAtIndex(index: number): KTransformation; numAnimatedLeaves(): number; timestampToIndex(timestamp: Timestamp): number; algDuration(): Duration; moveDuration(index: number): number; timestampToPosition?: (timestamp: Timestamp, startPattern?: KPattern) => PuzzlePosition; currentMoveInfo?: (timestamp: Timestamp) => CurrentMoveInfo; } declare const setupToLocations: { start: boolean; end: boolean; }; type SetupToLocation = keyof typeof setupToLocations; declare class SetupAnchorProp extends SimpleTwistyPropSource<SetupToLocation> { getDefaultValue(): SetupToLocation; } interface AnchorTransformationPropInputs { setupTransformation: KTransformation | null; setupAnchor: SetupToLocation; setupAlgTransformation: KTransformation; indexer: AlgIndexer; } declare class AnchorTransformationProp extends TwistyPropDerived<AnchorTransformationPropInputs, KTransformation> { derive(inputs: AnchorTransformationPropInputs): KTransformation; } interface AnimationTimelineLeaf { animLeaf: AlgLeaf; start: number; end: number; } type AnimationTimelineLeaves = AnimationTimelineLeaf[]; declare class AnimationTimelineLeavesRequestProp extends SimpleTwistyPropSource<AnimationTimelineLeaf[] | null> { getDefaultValue(): AnimationTimelineLeaf[] | null; } interface CatchUpMove { move: Move | null; amount: number; } declare class CatchUpMoveProp extends SimpleTwistyPropSource<CatchUpMove> { getDefaultValue(): CatchUpMove; protected canReuseValue(v1: CatchUpMove, v2: CatchUpMove): boolean; } interface CurrentLeavesSimplifiedPropInputs { currentMoveInfo: CurrentMoveInfo; } interface CurrentLeavesSimplified { patternIndex: number; movesFinishing: Move[]; movesFinished: Move[]; } declare class CurrentLeavesSimplifiedProp extends TwistyPropDerived<CurrentLeavesSimplifiedPropInputs, CurrentLeavesSimplified> { protected derive(inputs: CurrentLeavesSimplifiedPropInputs): CurrentLeavesSimplified; protected canReuseValue(v1: CurrentLeavesSimplified, v2: CurrentLeavesSimplified): boolean; } declare const smartTimestamps: { auto: boolean; start: boolean; end: boolean; anchor: boolean; "opposite-anchor": boolean; }; type TimestampRequest = MillisecondTimestamp | keyof typeof smartTimestamps; declare class TimestampRequestProp extends SimpleTwistyPropSource<TimestampRequest> { getDefaultValue(): TimestampRequest; set(v: PromiseOrValue<TimestampRequest>): void; protected validInput(v: TimestampRequest): boolean; } interface DetailedTimelineInfoInputs { timestampRequest: TimestampRequest; timeRange: TimeRange; setupAnchor: SetupToLocation; setupAlg: AlgWithIssues; } interface DetailedTimelineInfo { timestamp: MillisecondTimestamp; timeRange: TimeRange; atStart: boolean; atEnd: boolean; } declare class DetailedTimelineInfoProp extends TwistyPropDerived<DetailedTimelineInfoInputs, DetailedTimelineInfo> { #private; protected derive(inputs: DetailedTimelineInfoInputs): DetailedTimelineInfo; protected canReuseValue(v1: DetailedTimelineInfo, v2: DetailedTimelineInfo): boolean; } interface PositionPropInputs { indexer: AlgIndexer; detailedTimelineInfo: DetailedTimelineInfo; catchUpMove: CatchUpMove; } declare class CurrentMoveInfoProp extends TwistyPropDerived<PositionPropInputs, CurrentMoveInfo> { derive(inputs: PositionPropInputs): CurrentMoveInfo; } interface CurrentTransformationPropInputs { anchoredStart: KTransformation; currentLeavesSimplified: CurrentLeavesSimplified; indexer: AlgIndexer; } declare class CurrentPatternProp extends TwistyPropDerived<CurrentTransformationPropInputs, KPattern> { derive(inputs: CurrentTransformationPropInputs): KPattern; } declare const visualizationFormats: { readonly "3D": true; readonly "2D": true; readonly "experimental-2D-LL": true; readonly "experimental-2D-LL-face": true; readonly PG3D: true; }; type VisualizationFormat = keyof typeof visualizationFormats; type VisualizationFormatWithAuto = VisualizationFormat | "auto"; declare class VisualizationFormatProp extends SimpleTwistyPropSource<VisualizationFormatWithAuto> { getDefaultValue(): VisualizationFormatWithAuto; } type VisualizationStrategyPropInputs = { visualizationRequest: VisualizationFormatWithAuto; puzzleID: PuzzleID; }; type VisualizationStrategy = "Cube3D" | "2D" | "experimental-2D-LL" | "experimental-2D-LL-face" | "PG3D"; declare class VisualizationStrategyProp extends TwistyPropDerived<VisualizationStrategyPropInputs, VisualizationStrategy> { derive(inputs: VisualizationStrategyPropInputs): VisualizationStrategy; } declare const puzzleIDs: { "3x3x3": boolean; custom: boolean; "2x2x2": boolean; "4x4x4": boolean; "5x5x5": boolean; "6x6x6": boolean; "7x7x7": boolean; "40x40x40": boolean; megaminx: boolean; pyraminx: boolean; square1: boolean; clock: boolean; skewb: boolean; fto: boolean; gigaminx: boolean; master_tetraminx: boolean; kilominx: boolean; redi_cube: boolean; baby_fto: boolean; melindas2x2x2x2: boolean; tri_quad: boolean; loopover: boolean; }; type PuzzleID = keyof typeof puzzleIDs; declare class PuzzleIDRequestProp extends SimpleTwistyPropSource<PuzzleID | NoValueType> { getDefaultValue(): PuzzleID | NoValueType; } declare const indexerStrategyNames: { auto: boolean; simple: boolean; tree: boolean; simultaneous: boolean; }; type IndexerStrategyName = keyof typeof indexerStrategyNames; declare class IndexerConstructorRequestProp extends SimpleTwistyPropSource<IndexerStrategyName> { getDefaultValue(): IndexerStrategyName; } type IndexerConstructor = new (kpuzzle: KPuzzle, alg: Alg, options?: { animationTimelineLeaves?: AnimationTimelineLeaves | null; }) => AlgIndexer; interface IndexerConstructorPropInputs { puzzle: PuzzleID; alg: AlgWithIssues; visualizationStrategy: VisualizationStrategy; indexerConstructorRequest: IndexerStrategyName; animationTimelineLeaves: AnimationTimelineLeaves | null; } declare class IndexerConstructorProp extends TwistyPropDerived<IndexerConstructorPropInputs, IndexerConstructor> { derive(inputs: IndexerConstructorPropInputs): IndexerConstructor; } type IndexerPropInputs = { indexerConstructor: IndexerConstructor; algWithIssues: AlgWithIssues; kpuzzle: KPuzzle; animationTimelineLeaves: AnimationTimelineLeaves | null; }; declare class IndexerProp extends TwistyPropDerived<IndexerPropInputs, AlgIndexer> { derive(input: IndexerPropInputs): AlgIndexer; } interface LegacyPositionPropInputs { currentMoveInfo: CurrentMoveInfo; currentPattern: KPattern; } declare class LegacyPositionProp extends TwistyPropDerived<LegacyPositionPropInputs, PuzzlePosition> { derive(inputs: LegacyPositionPropInputs): PuzzlePosition; } declare class PuzzleAlgProp extends TwistyPropDerived<{ algWithIssues: AlgWithIssues; kpuzzle: KPuzzle; }, AlgWithIssues> { derive(inputs: { algWithIssues: AlgWithIssues; kpuzzle: KPuzzle; }): Promise<AlgWithIssues>; } declare class SetupTransformationProp extends SimpleTwistyPropSource<KTransformation | null> { getDefaultValue(): KTransformation | null; } declare class KPuzzleProp extends TwistyPropDerived<{ puzzleLoader: PuzzleLoader; }, KPuzzle> { derive(inputs: { puzzleLoader: PuzzleLoader; }): Promise<KPuzzle>; } declare class PGPuzzleDescriptionStringProp extends SimpleTwistyPropSource<PuzzleDescriptionString | NoValueType> { getDefaultValue(): PuzzleDescriptionString | NoValueType; } declare class PuzzleIDProp extends TwistyPropDerived<{ puzzleLoader: PuzzleLoader; }, PuzzleID> { derive(inputs: { puzzleLoader: PuzzleLoader; }): Promise<PuzzleID>; } interface PuzzleLoaderPropInputs { puzzleIDRequest: PuzzleID | NoValueType; puzzleDescriptionRequest: PuzzleDescriptionString | NoValueType; } declare class PuzzleLoaderProp extends TwistyPropDerived<PuzzleLoaderPropInputs, PuzzleLoader> { derive(inputs: PuzzleLoaderPropInputs): PuzzleLoader; } declare let HTMLElementShim: typeof HTMLElement; declare class ManagedCustomElement extends HTMLElementShim { readonly shadow: ShadowRoot; readonly contentWrapper: HTMLDivElement; constructor(options?: { mode?: "open" | "closed"; }); protected addCSS(cssSource: CSSStyleSheet): void; protected removeCSS(cssSource: CSSStyleSheet): void; addElement<T extends Node>(element: T): T; prependElement<T extends Node>(element: T): void; removeElement<T extends Node>(element: T): T; } declare const viewerLinkPages: { twizzle: boolean; "experimental-twizzle-explorer": boolean; none: boolean; }; type ViewerLinkPage = keyof typeof viewerLinkPages; type ViewerLinkPageWithAuto =