cubing 0.61.0 → 0.61.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/chunks/chunk-BIRBVHTR.js +14 -0
- package/dist/bin/chunks/chunk-BIRBVHTR.js.map +7 -0
- package/dist/bin/order.js +46 -42
- package/dist/bin/order.js.map +2 -2
- package/dist/bin/puzzle-geometry-bin.js +379 -257
- package/dist/bin/puzzle-geometry-bin.js.map +3 -3
- package/dist/bin/scramble.js +124 -102
- package/dist/bin/scramble.js.map +3 -3
- package/dist/lib/cubing/{KPattern-CU9Suh1T.d.ts → PuzzleLoader-CkghxdIL.d.ts} +186 -179
- package/dist/lib/cubing/alg/index.d.ts +2 -2
- package/dist/lib/cubing/bluetooth/index.d.ts +3 -3
- package/dist/lib/cubing/bluetooth/index.js +4 -4
- package/dist/lib/cubing/{bluetooth-puzzle-gTRbIRyj.d.ts → bluetooth-puzzle-c-_IBAdu.d.ts} +1 -1
- package/dist/lib/cubing/chunks/{chunk-PVOSBZRD.js → chunk-3PS5LIPR.js} +3 -3
- package/dist/lib/cubing/chunks/{chunk-PVOSBZRD.js.map → chunk-3PS5LIPR.js.map} +1 -1
- package/dist/lib/cubing/chunks/{chunk-RKTO4CAU.js → chunk-IHFKNNCV.js} +2 -2
- package/dist/lib/cubing/chunks/{chunk-BUZPONAW.js → chunk-LCJT5ROJ.js} +2 -2
- package/dist/lib/cubing/chunks/{chunk-WIZJQ7QS.js → chunk-MZKROP74.js} +15 -15
- package/dist/lib/cubing/chunks/{chunk-RUSWM2KK.js → chunk-QSGI7DXX.js} +5 -5
- package/dist/lib/cubing/chunks/{chunk-RUSWM2KK.js.map → chunk-QSGI7DXX.js.map} +1 -1
- package/dist/lib/cubing/chunks/{chunk-REBGU5ET.js → chunk-T3SF7NHB.js} +2 -2
- package/dist/lib/cubing/chunks/{chunk-PSQEELP4.js → chunk-WAYEJXCG.js} +1 -1
- package/dist/lib/cubing/chunks/chunk-WAYEJXCG.js.map +7 -0
- package/dist/lib/cubing/chunks/{chunk-ABQAUY7H.js → chunk-WI337PMF.js} +3 -3
- package/dist/lib/cubing/chunks/{chunk-OJI4YUWF.js → chunk-ZGT5MZSV.js} +4 -4
- package/dist/lib/cubing/chunks/{chunk-NX2Q6B7Y.js → chunk-ZKJKRQKY.js} +2 -2
- package/dist/lib/cubing/chunks/{chunk-NX2Q6B7Y.js.map → chunk-ZKJKRQKY.js.map} +2 -2
- package/dist/lib/cubing/chunks/{inside-PM6546BQ.js → inside-UAY7NCJR.js} +12 -12
- package/dist/lib/cubing/chunks/{puzzles-dynamic-3x3x3-JWIWLLZA.js → puzzles-dynamic-3x3x3-FYXD7SIU.js} +14 -13
- package/dist/lib/cubing/chunks/puzzles-dynamic-3x3x3-FYXD7SIU.js.map +7 -0
- package/dist/lib/cubing/chunks/{puzzles-dynamic-side-events-BOGUHF4Q.js → puzzles-dynamic-side-events-IMYJ533P.js} +1 -1
- package/dist/lib/cubing/chunks/puzzles-dynamic-side-events-IMYJ533P.js.map +7 -0
- package/dist/lib/cubing/chunks/{search-dynamic-sgs-side-events-SYC27DSG.js → search-dynamic-sgs-side-events-E5KVBK2Y.js} +4 -4
- package/dist/lib/cubing/chunks/{search-dynamic-sgs-unofficial-QGGV4PCJ.js → search-dynamic-sgs-unofficial-IFHNOIEL.js} +4 -4
- package/dist/lib/cubing/chunks/{search-dynamic-solve-4x4x4-IE5W637Q.js → search-dynamic-solve-4x4x4-QVAXVZBA.js} +7 -7
- package/dist/lib/cubing/chunks/search-worker-entry.js +3 -3
- package/dist/lib/cubing/chunks/{twisty-dynamic-3d-LPZQIDD2.js → twisty-dynamic-3d-O6UL3R7C.js} +5 -5
- package/dist/lib/cubing/{index-CORXpckt.d.ts → index-B_8W-2zR.d.ts} +1 -1
- package/dist/lib/cubing/kpuzzle/index.d.ts +1 -1
- package/dist/lib/cubing/kpuzzle/index.js +1 -1
- package/dist/lib/cubing/notation/index.d.ts +1 -1
- package/dist/lib/cubing/notation/index.js +3 -3
- package/dist/lib/cubing/protocol/index.d.ts +1 -1
- package/dist/lib/cubing/protocol/index.js +3 -3
- package/dist/lib/cubing/puzzle-geometry/index.d.ts +2 -2
- package/dist/lib/cubing/puzzle-geometry/index.js +138 -179
- package/dist/lib/cubing/puzzle-geometry/index.js.map +3 -3
- package/dist/lib/cubing/puzzles/index.d.ts +1 -1
- package/dist/lib/cubing/puzzles/index.js +3 -3
- package/dist/lib/cubing/scramble/index.d.ts +2 -2
- package/dist/lib/cubing/scramble/index.js +6 -6
- package/dist/lib/cubing/search/index.d.ts +3 -3
- package/dist/lib/cubing/search/index.js +6 -6
- package/dist/lib/cubing/stream/index.d.ts +2 -2
- package/dist/lib/cubing/twisty/index.d.ts +2 -2
- package/dist/lib/cubing/twisty/index.js +26 -5
- package/dist/lib/cubing/twisty/index.js.map +2 -2
- package/experimental-json-schema/kpuzzle/KPatternData.schema.json +22 -30
- package/experimental-json-schema/kpuzzle/KPuzzleDefinition.schema.json +72 -89
- package/experimental-json-schema/kpuzzle/KTransformationData.schema.json +17 -26
- package/package.json +55 -100
- package/dist/bin/chunks/chunk-J53ID3VX.js +0 -26
- package/dist/bin/chunks/chunk-J53ID3VX.js.map +0 -7
- package/dist/lib/cubing/chunks/chunk-PSQEELP4.js.map +0 -7
- package/dist/lib/cubing/chunks/puzzles-dynamic-3x3x3-JWIWLLZA.js.map +0 -7
- package/dist/lib/cubing/chunks/puzzles-dynamic-side-events-BOGUHF4Q.js.map +0 -7
- /package/dist/lib/cubing/chunks/{chunk-RKTO4CAU.js.map → chunk-IHFKNNCV.js.map} +0 -0
- /package/dist/lib/cubing/chunks/{chunk-BUZPONAW.js.map → chunk-LCJT5ROJ.js.map} +0 -0
- /package/dist/lib/cubing/chunks/{chunk-WIZJQ7QS.js.map → chunk-MZKROP74.js.map} +0 -0
- /package/dist/lib/cubing/chunks/{chunk-REBGU5ET.js.map → chunk-T3SF7NHB.js.map} +0 -0
- /package/dist/lib/cubing/chunks/{chunk-ABQAUY7H.js.map → chunk-WI337PMF.js.map} +0 -0
- /package/dist/lib/cubing/chunks/{chunk-OJI4YUWF.js.map → chunk-ZGT5MZSV.js.map} +0 -0
- /package/dist/lib/cubing/chunks/{inside-PM6546BQ.js.map → inside-UAY7NCJR.js.map} +0 -0
- /package/dist/lib/cubing/chunks/{search-dynamic-sgs-side-events-SYC27DSG.js.map → search-dynamic-sgs-side-events-E5KVBK2Y.js.map} +0 -0
- /package/dist/lib/cubing/chunks/{search-dynamic-sgs-unofficial-QGGV4PCJ.js.map → search-dynamic-sgs-unofficial-IFHNOIEL.js.map} +0 -0
- /package/dist/lib/cubing/chunks/{search-dynamic-solve-4x4x4-IE5W637Q.js.map → search-dynamic-solve-4x4x4-QVAXVZBA.js.map} +0 -0
- /package/dist/lib/cubing/chunks/{twisty-dynamic-3d-LPZQIDD2.js.map → twisty-dynamic-3d-O6UL3R7C.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/bin/puzzle-geometry-bin.ts"],
|
|
4
|
-
"sourcesContent": ["// To run this file directly:\n// bun run src/bin/puzzle-geometry-bin.ts -- <program args>\n\nimport {\n type ExperimentalPuzzleBaseShape,\n type ExperimentalPuzzleCutType,\n type ExperimentalPuzzleGeometryOptions,\n getPG3DNamedPuzzles,\n PuzzleGeometry,\n parsePuzzleDescription,\n} from \"cubing/puzzle-geometry\";\nimport type { PuzzleDescriptionString } from \"cubing/puzzle-geometry/PGPuzzles\";\nimport type {\n PuzzleCutDescription,\n PuzzleDescription,\n} from \"cubing/puzzle-geometry/PuzzleGeometry\";\n\nexport function asstructured(v: any): any {\n if (typeof v === \"string\") {\n return JSON.parse(v);\n }\n return v;\n}\nexport function asboolean(v: any): boolean {\n if (typeof v === \"string\") {\n return v !== \"false\";\n } else {\n return !!v;\n }\n}\nexport function parsePGOptionList(\n optionlist?: any[],\n): ExperimentalPuzzleGeometryOptions {\n const options: ExperimentalPuzzleGeometryOptions = {};\n if (optionlist !== undefined) {\n if (optionlist.length % 2 !== 0) {\n throw new Error(\"Odd length in option list?\");\n }\n for (let i = 0; i < optionlist.length; i += 2) {\n if (optionlist[i] === \"verbose\") {\n options.verbosity = (options.verbosity ?? 0) + 1;\n } else if (optionlist[i] === \"quiet\") {\n options.verbosity = 0;\n } else if (optionlist[i] === \"allmoves\") {\n options.allMoves = asboolean(optionlist[i + 1]);\n } else if (optionlist[i] === \"outerblockmoves\") {\n options.outerBlockMoves = asboolean(optionlist[i + 1]);\n } else if (optionlist[i] === \"vertexmoves\") {\n options.vertexMoves = asboolean(optionlist[i + 1]);\n } else if (optionlist[i] === \"rotations\") {\n options.addRotations = asboolean(optionlist[i + 1]);\n } else if (optionlist[i] === \"cornersets\") {\n options.includeCornerOrbits = asboolean(optionlist[i + 1]);\n } else if (optionlist[i] === \"centersets\") {\n options.includeCenterOrbits = asboolean(optionlist[i + 1]);\n } else if (optionlist[i] === \"edgesets\") {\n options.includeEdgeOrbits = asboolean(optionlist[i + 1]);\n } else if (optionlist[i] === \"omit\") {\n options.excludeOrbits = optionlist[i + 1];\n } else if (optionlist[i] === \"graycorners\") {\n options.grayCorners = asboolean(optionlist[i + 1]);\n } else if (optionlist[i] === \"graycenters\") {\n options.grayCenters = asboolean(optionlist[i + 1]);\n } else if (optionlist[i] === \"grayedges\") {\n options.grayEdges = asboolean(optionlist[i + 1]);\n } else if (optionlist[i] === \"movelist\") {\n options.moveList = asstructured(optionlist[i + 1]);\n } else if (optionlist[i] === \"killorientation\") {\n options.fixedOrientation = asboolean(optionlist[i + 1]);\n } else if (optionlist[i] === \"optimize\") {\n options.optimizeOrbits = asboolean(optionlist[i + 1]);\n } else if (optionlist[i] === \"scramble\") {\n options.scrambleAmount = optionlist[i + 1];\n } else if (optionlist[i] === \"fix\") {\n options.fixedPieceType = optionlist[i + 1];\n } else if (optionlist[i] === \"orientcenters\") {\n options.orientCenters = asboolean(optionlist[i + 1]);\n } else if (optionlist[i] === \"puzzleorientation\") {\n options.puzzleOrientation = asstructured(optionlist[i + 1]);\n } else if (optionlist[i] === \"puzzleorientations\") {\n options.puzzleOrientations = asstructured(optionlist[i + 1]);\n } else {\n throw new Error(\n `Bad option while processing option list ${optionlist[i]}`,\n );\n }\n }\n }\n return options;\n}\n\nlet dosvg = false;\nlet doss = false;\nlet doksolve = false;\nlet dogap = false;\nlet domathematica = false;\nlet docanon = false;\nlet do3d = false;\nif (globalThis.process && process.argv && process.argv.length <= 2) {\n console.log(\n `Usage: puzzle-geometry [options] [puzzle]\n\nOptions:\n--ksolve: write ksolve (tws) file\n--svg: write SVG (default is flat; --3d makes it 3D)\n--gap: write gap\n--mathematica: write mathematica\n--ss: execute Schrier-Sims calculation\n--3d: use 3D format for SVG file\n--canon: write canonical string analysis\n--rotations: include full-puzzle rotations as moves\n--allmoves: includes all moves (i.e., slice moves for 3x3x3)\n--outerblockmoves: use outer block moves rather than slice moves\n--vertexmoves: for tetrahedral puzzles, prefer vertex moves to face moves\n--nocorners: ignore all corners\n--noedges: ignore all edges\n--nocenters: ignore all centers\n--noorientation: ignore orientations\n--orientcenters: give centers an orientation\n--puzzleorientation: for 3D formats, give puzzle orientation\n--moves movenames: restrict moves to this list (e.g, U2,F,r)\n--optimize: optimize tws/ksolve/gap output\n--scramble: scramble solved position\n--fixcorner: choose moves to keep one corner fixed\n--fixedge: choose moves to keep one edge fixed\n--fixcenter: choose moves to keep one center fixed\n--verbose (-v): make verbose\n\nThe puzzle can be given as a geometric description or by name.\nThe geometric description starts with c (cube), t (tetrahedron),\nd (dodecahedron), i (icosahedron), or o (octahedron), then a\nspace, then a series of cuts. Each cut begins with f (for a\ncut parallel to faces), v (for a cut perpendicular to a ray\nfrom the center through a corner), or e (for a cut perpendicular\nto a ray from the center through an edge) followed by a decimal\nnumber giving a distance, where 1 is the distance between the\ncenter of the puzzle and the center of a face.\n\nThe puzzle names recognized are 2x2x2 through 13x13x13, 20x20x20,\nmaster skewb, professor skewb, compy cube, helicopter, dino,\nlittle chop, pyramorphix, mastermorphix, pyraminx, Jing pyraminx,\nmaster paramorphix, megaminx, gigaminx, pentultimate, starminx,\nstarminx 2, pyraminx crystal, chopasaurus, big chop, skewb diamond,\nFTO, Christopher's jewel, octastar, Trajber's octahedron, radio chop,\nicosamate, Regular Astrominx, Regular Astrominx + Big Chop,\nRedicosahedron, Redicosahedron with centers,Icosaminx, and Eitan's star.\n\nExamples:\n puzzlegeometry --ss 2x2x2\n puzzlegeometry --ss --fixcorner 2x2x2\n puzzlegeometry --ss --moves U,F2,r 4x4x4\n puzzlegeometry --ksolve --optimize --moves U,F,R megaminx\n puzzlegeometry --gap --noedges megaminx\n`,\n );\n}\nif (globalThis.process && process.argv && process.argv.length >= 3) {\n let desc: PuzzleDescriptionString | undefined;\n const puzzleList = getPG3DNamedPuzzles();\n let argp = 2;\n const optionlist = [];\n let showargs = true;\n let pascalcomment = false;\n while (argp < process.argv.length && process.argv[argp][0] === \"-\") {\n const option = process.argv[argp++];\n if (option === \"--verbose\" || option === \"-v\") {\n optionlist.push(\"verbose\", true);\n } else if (option === \"--quiet\" || option === \"-q\") {\n optionlist.push(\"quiet\", true);\n showargs = false;\n } else if (option === \"--ksolve\") {\n doksolve = true;\n } else if (option === \"--svg\") {\n showargs = false;\n optionlist.push(\"quiet\", true);\n dosvg = true;\n } else if (option === \"--gap\") {\n dogap = true;\n } else if (option === \"--mathematica\") {\n domathematica = true;\n pascalcomment = true;\n } else if (option === \"--ss\") {\n doss = true;\n } else if (option === \"--3d\") {\n do3d = true;\n } else if (option === \"--canon\") {\n docanon = true;\n } else if (option === \"--rotations\") {\n optionlist.push(\"rotations\", true);\n } else if (option === \"--allmoves\") {\n optionlist.push(\"allmoves\", true);\n } else if (option === \"--outerblockmoves\") {\n optionlist.push(\"outerblockmoves\", true);\n } else if (option === \"--vertexmoves\") {\n optionlist.push(\"vertexmoves\", true);\n } else if (option === \"--nocorners\") {\n optionlist.push(\"cornersets\", false);\n } else if (option === \"--noedges\") {\n optionlist.push(\"edgesets\", false);\n } else if (option === \"--noorientation\") {\n optionlist.push(\"killorientation\", true);\n } else if (option === \"--nocenters\") {\n optionlist.push(\"centersets\", false);\n } else if (option === \"--omit\") {\n optionlist.push(\"omit\", process.argv[argp].split(\",\"));\n argp++;\n } else if (option === \"--moves\") {\n optionlist.push(\"movelist\", process.argv[argp].split(\",\"));\n argp++;\n } else if (option === \"--optimize\") {\n optionlist.push(\"optimize\", true);\n } else if (option === \"--scramble\") {\n optionlist.push(\"scramble\", 100);\n } else if (option === \"--fixcorner\") {\n optionlist.push(\"fix\", \"v\");\n } else if (option === \"--fixedge\") {\n optionlist.push(\"fix\", \"e\");\n } else if (option === \"--fixcenter\") {\n optionlist.push(\"fix\", \"f\");\n } else if (option === \"--orientcenters\") {\n optionlist.push(\"orientcenters\", true);\n } else if (option === \"--puzzleorientation\") {\n optionlist.push(\"puzzleorientation\", process.argv[argp]);\n argp++;\n } else {\n throw new Error(`Bad option: ${option}`);\n }\n }\n for (const [name, curDesc] of Object.entries(puzzleList)) {\n if (name === process.argv[argp]) {\n desc = curDesc;\n break;\n }\n }\n let puzzleDescription: PuzzleDescription;\n if (showargs) {\n if (pascalcomment) {\n console.log(`(* ${process.argv.join(\" \")} *)`);\n } else {\n console.log(`# ${process.argv.join(\" \")}`);\n }\n }\n if (desc !== undefined) {\n const parsed = parsePuzzleDescription(desc);\n if (parsed === null) {\n throw new Error(\"Could not parse puzzle description!\");\n }\n puzzleDescription = parsed;\n argp++;\n } else {\n const cuts: PuzzleCutDescription[] = [];\n const cutarg = argp++;\n while (argp + 1 < process.argv.length && process.argv[argp].length === 1) {\n // TODO: validate cut type\n cuts.push({\n cutType: process.argv[argp] as ExperimentalPuzzleCutType,\n distance: parseFloat(process.argv[argp + 1]),\n });\n argp += 2;\n }\n // TODO: validate shape\n puzzleDescription = {\n shape: process.argv[cutarg] as ExperimentalPuzzleBaseShape,\n cuts,\n };\n }\n const options = parsePGOptionList(optionlist);\n const pg = new PuzzleGeometry(puzzleDescription, options);\n pg.allstickers();\n pg.genperms();\n if (argp < process.argv.length) {\n throw new Error(\"Unprocessed content at end of command line\");\n }\n if (dogap) {\n console.log(pg.writegap());\n } else if (domathematica) {\n console.log(pg.writemathematica());\n } else if (doksolve) {\n console.log(pg.writeksolve()); // TODO: Update arguments\n } else if (dosvg) {\n console.log(pg.generatesvg(undefined, undefined, undefined, do3d));\n } else if (do3d) {\n console.log(JSON.stringify(pg.get3d()));\n } else if (doss) {\n pg.writeSchreierSims(console.log);\n } else if (docanon) {\n pg.showcanon((_) => console.log(_));\n }\n}\n"],
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": []
|
|
4
|
+
"sourcesContent": ["/**\n\nTo run this file directly:\n\n```shell\nbun run ./src/bin/puzzle-geometry-bin.ts -- <program args>\n```\n\nTo test completions:\n\n```shell\n# fish (from repo root)\nset PATH (pwd)/src/test/bin-path $PATH\npuzzle-geometry --completions fish | source\n```\n\n```shell\n# zsh (from repo root)\nautoload -Uz compinit\ncompinit\nexport PATH=$(pwd)/src/test/bin-path:$PATH\nsource <(puzzle-geometry --completions zsh)\n```\n\n*/\n\nimport { argv } from \"node:process\";\nimport {\n argument,\n constant,\n flag,\n integer,\n type Message,\n map,\n merge,\n message,\n multiple,\n type OptionName,\n object,\n option,\n optional,\n or,\n string,\n} from \"@optique/core\";\nimport { run } from \"@optique/run\";\nimport { Move } from \"cubing/alg\";\nimport {\n type ExperimentalPuzzleGeometryOptions,\n getPG3DNamedPuzzles,\n PuzzleGeometry,\n parsePuzzleDescription,\n} from \"cubing/puzzle-geometry\";\nimport { Path } from \"path-class\";\nimport { PrintableShellCommand } from \"printable-shell-command\";\nimport { packageVersion } from \"../metadata/packageVersion\";\n\nconst puzzleList = getPG3DNamedPuzzles();\n\n// TODO: make this a `ValueParser`?\nfunction antiBool(optionName: OptionName, description: Message) {\n return optional(\n map(\n flag(optionName, {\n description,\n }),\n (v) => !v,\n ),\n );\n}\n\n// Include using `...subcommandDefaults` at the *beginning* of a subcommand `object({ \u2026 })`.\nconst subcommandDefaults = {\n commentStyle: constant(\"hash\"),\n forceQuiet: constant(undefined),\n} as const;\n\nconst args = run(\n merge(\n object({\n verbosity: optional(\n or(\n map(multiple(flag(\"--verbose\", \"-v\")), (v) => v.length),\n map(flag(\"--quiet\", \"-q\"), () => 0),\n ),\n ),\n }),\n or(\n object({\n ...subcommandDefaults,\n subcommand: constant(\"KSolve\"),\n subcommandFlag: flag(\"--ksolve\", {\n description: message`Print KSolve (\\`.tws\\`).`,\n }),\n }),\n object({\n ...subcommandDefaults,\n subcommand: constant(\"SVG\"),\n subcommandFlag: flag(\"--svg\", {\n description: message`Print SVG. Forces \\`--quiet\\`.`,\n }),\n commentStyle: constant(\"none\"),\n svg3D: optional(\n option(\"--3d\", {\n description: message`Use 3D format for SVG file.`,\n }),\n ),\n verbosity: constant(0),\n }),\n object({\n ...subcommandDefaults,\n subcommand: constant(\"GAP\"),\n subcommandFlag: flag(\"--gap\", {\n description: message`Print GAP output.`,\n }),\n }),\n object({\n ...subcommandDefaults,\n subcommand: constant(\"Mathematica\"),\n subcommandFlag: flag(\"--mathematica\", {\n description: message`Print Mathematica output.`,\n }),\n commentStyle: constant(\"Pascal\"),\n }),\n object({\n ...subcommandDefaults,\n subcommand: constant(\"Schreier-Sims\"),\n subcommandFlag: flag(\"--ss\", {\n description: message`Perform Schrier-Sims calculation.`,\n }),\n }),\n object({\n ...subcommandDefaults,\n subcommand: constant(\"Canonical string analysis\"),\n subcommandFlag: flag(\"--canon\", {\n description: message`Print canonical string analysis.`,\n }),\n }),\n object({\n ...subcommandDefaults,\n subcommand: constant(\"3D\"),\n subcommandFlag: flag(\"--3d\", {\n description: message`Print 3D information.`,\n }),\n }),\n ),\n object({\n // This doesn't apply to SVG, but we place it here so that it doesn't print once for each non-SVG subcommand in the help string.\n optimizeOrbits: option(\"--optimize\", {\n description: message`Optimize output (when possible).`,\n }),\n addRotations: option(\"--rotations\", {\n description: message`Include full-puzzle rotations as moves.`,\n }),\n allMoves: option(\"--allmoves\", {\n description: message`Includes all moves (i.e., slice moves for 3x3x3).`,\n }),\n outerBlockMoves: option(\"--outerblockmoves\", {\n description: message`Use outer block moves rather than slice moves.`,\n }),\n vertexMoves: option(\"--vertexmoves\", {\n description: message`For tetrahedral puzzles, prefer vertex moves to face moves.`,\n }),\n includeCornerOrbits: antiBool(\n \"--nocorners\",\n message`Ignore all corners.`,\n ),\n excludeOrbits: optional(\n map(\n option(\"--omit\", string({ metavar: \"COMMA_SEPARATED_ORBITS\" }), {\n description: message`Omit orbits.`,\n }),\n (s) => s.split(\",\"),\n ),\n ),\n includeEdgeOrbits: antiBool(\"--noedges\", message`Ignore all edges.`),\n includeCenterOrbits: antiBool(\n \"--nocenters\",\n message`Ignore all centers.`,\n ),\n grayCorners: option(\"--graycorners\", {\n description: message`Gray corners.`,\n }),\n grayEdges: option(\"--grayedges\", { description: message`Gray edges.` }),\n grayCenters: option(\"--graycenters\", {\n description: message`Gray centers.`,\n }),\n fixedOrientation: option(\"--noorientation\", {\n description: message`Ignore orientations.`,\n }),\n orientCenters: option(\"--orientcenters\", {\n description: message`Give centers an orientation.`,\n }),\n }),\n optional(\n or(\n object({\n puzzleOrientation: optional(\n map(\n option(\n \"--puzzleorientation\",\n string({ metavar: \"JSON_STRING\" }),\n {\n description: message`For 3D formats, give puzzle orientation.`,\n },\n ),\n (s) => JSON.parse(s),\n ),\n ),\n puzzleOrientations: constant(undefined),\n }),\n object({\n puzzleOrientation: constant(undefined),\n puzzleOrientations: optional(\n map(\n option(\n \"--puzzleorientations\",\n string({ metavar: \"JSON_STRING\" }),\n {\n description: message`For 3D formats, give puzzle orientations.`,\n },\n ),\n (s) => JSON.parse(s),\n ),\n ),\n }),\n ),\n ),\n object({\n fixedPieceType: optional(\n or(\n map(\n flag(\"--fixcorner\", {\n description: message`Auto-select a subset of moves to keep a corner fixed in place.`,\n }),\n () => \"v\" as const,\n ),\n map(\n flag(\"--fixedge\", {\n description: message`Auto-select a subset of moves to keep an edge fixed in place.`,\n }),\n () => \"e\" as const,\n ),\n map(\n flag(\"--fixcenter\", {\n description: message`Auto-select a subset of moves to keep a center fixed in place.`,\n }),\n () => \"f\" as const,\n ),\n ),\n ),\n // TODO: this doesn't make sense for all subcommands?\n scrambleAmount: optional(\n option(\"--scramble\", integer({ min: 0 }), {\n description: message`Scramble solved position.`,\n }),\n ),\n moveList: optional(\n map(\n option(\"--moves\", string({ metavar: \"COMMA_SEPARATED_MOVES\" }), {\n description: message`Restrict moves to this list. Example: \\\"U2,F,r\\\").`,\n }),\n (s) => s.split(\",\").map((m) => Move.fromString(m)),\n ),\n ),\n puzzle: map(\n argument(string({ metavar: \"PUZZLE\" }), {\n description: message`The puzzle can be given as a geometric description or by name.\nThe geometric description starts with one of:\n\n- \\`c\\` (cube),\\n\n- \\`t\\` (tetrahedron),\\n\n- \\`d\\` (dodecahedron),\\n\n- \\`i\\` (icosahedron),\\n\n- \\`o\\` (octahedron),\\n\n\nthen a space, then a series of cuts. Each cut begins with one of:\n\n- \\`f\\` (for a cut parallel to faces),\\n\n- \\`v\\` (for a cut perpendicular to a ray from the center through a corner),\\n\n- \\`e\\` (for a cut perpendicular to a ray from the center through an edge),\\n\n\nfollowed by a decimal number giving a distance, where 1 is the distance\nbetween the center of the puzzle and the center of a face.\n\nExample description: \\`c f 0 v 0.577350269189626 e 0\\`. Corresponds to: https://alpha.twizzle.net/explore/?puzzle=2x2x2+%2B+dino+%2B+little+chop\n\nThe recognized puzzle names are: ${Object.keys(puzzleList)\n .map((p) => JSON.stringify(p))\n .join(\", \")}`,\n }),\n (s) => {\n const parsed = parsePuzzleDescription(puzzleList[s] ?? s);\n if (parsed === null) {\n throw new Error(\"Could not parse puzzle description!\");\n }\n return parsed;\n },\n ),\n }),\n ),\n {\n programName: new Path(argv[1]).basename.path,\n description: message`\nExamples:\n\n puzzle-geometry --ss 2x2x2\\n\n puzzle-geometry --ss --fixcorner 2x2x2\\n\n puzzle-geometry --ss --moves U,F2,r 4x4x4\\n\n puzzle-geometry --ksolve --optimize --moves U,F,R megaminx\\n\n puzzle-geometry --gap --noedges megaminx\n`,\n help: \"option\",\n completion: {\n mode: \"option\",\n name: \"plural\",\n },\n version: {\n mode: \"option\",\n value: packageVersion,\n },\n },\n);\n\nif (args.verbosity !== 0) {\n const cmd = () => {\n const [command, ...args] = argv;\n return new PrintableShellCommand(command, args).getPrintableCommand({\n argumentLineWrapping: \"inline\",\n });\n };\n\n switch (args.commentStyle) {\n case \"hash\": {\n console.log(`# ${cmd()}`);\n break;\n }\n case \"none\": {\n break;\n }\n case \"Pascal\": {\n console.log(`(* ${cmd()} *)`);\n break;\n }\n default:\n throw new Error(\"Invalid comment style.\") as never;\n }\n}\n\nfunction buildPuzzleGeometry(): PuzzleGeometry {\n const {\n verbosity,\n optimizeOrbits,\n addRotations,\n allMoves,\n outerBlockMoves,\n vertexMoves,\n includeCornerOrbits,\n includeCenterOrbits,\n includeEdgeOrbits,\n excludeOrbits,\n grayCorners,\n grayEdges,\n grayCenters,\n fixedOrientation,\n orientCenters,\n puzzleOrientation,\n puzzleOrientations,\n fixedPieceType,\n scrambleAmount,\n moveList,\n } = args;\n const options: ExperimentalPuzzleGeometryOptions = {\n verbosity,\n optimizeOrbits,\n addRotations,\n allMoves,\n outerBlockMoves,\n vertexMoves,\n includeCornerOrbits,\n includeCenterOrbits,\n includeEdgeOrbits,\n excludeOrbits,\n grayCorners,\n grayEdges,\n grayCenters,\n fixedOrientation,\n orientCenters,\n puzzleOrientation,\n puzzleOrientations,\n fixedPieceType,\n scrambleAmount,\n moveList,\n };\n\n const puzzleGeometry = new PuzzleGeometry(args.puzzle, options);\n // TODO: why are these calls needed?\n puzzleGeometry.allstickers();\n puzzleGeometry.genperms();\n return puzzleGeometry;\n}\n\nswitch (args.subcommand) {\n case \"KSolve\": {\n console.log(buildPuzzleGeometry().writeksolve());\n break;\n }\n case \"SVG\": {\n console.log(\n buildPuzzleGeometry().generatesvg(\n undefined,\n undefined,\n undefined,\n args.svg3D,\n ),\n );\n break;\n }\n case \"GAP\": {\n console.log(buildPuzzleGeometry().writegap());\n break;\n }\n case \"Mathematica\": {\n console.log(buildPuzzleGeometry().writemathematica());\n break;\n }\n case \"Schreier-Sims\": {\n buildPuzzleGeometry().writeSchreierSims(console.log);\n break;\n }\n case \"Canonical string analysis\": {\n buildPuzzleGeometry().showcanon(console.log);\n break;\n }\n case \"3D\": {\n console.log(JSON.stringify(buildPuzzleGeometry().get3d(), null, \" \"));\n break;\n }\n default:\n throw new Error(\"Invalid subcommand.\") as never;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["args"]
|
|
7
7
|
}
|
package/dist/bin/scramble.js
CHANGED
|
@@ -1,98 +1,130 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import
|
|
1
|
+
#!/usr/bin/env -S node --
|
|
2
|
+
import {
|
|
3
|
+
packageVersion
|
|
4
|
+
} from "./chunks/chunk-BIRBVHTR.js";
|
|
3
5
|
|
|
4
6
|
// src/bin/scramble.ts
|
|
5
|
-
import {
|
|
7
|
+
import { argv } from "node:process";
|
|
8
|
+
import {
|
|
9
|
+
argument,
|
|
10
|
+
choice,
|
|
11
|
+
integer,
|
|
12
|
+
map,
|
|
13
|
+
merge,
|
|
14
|
+
message,
|
|
15
|
+
object,
|
|
16
|
+
option,
|
|
17
|
+
withDefault
|
|
18
|
+
} from "@optique/core";
|
|
19
|
+
import { run } from "@optique/run";
|
|
20
|
+
import { eventInfo, twizzleEvents } from "cubing/puzzles";
|
|
6
21
|
import { randomScrambleForEvent } from "cubing/scramble";
|
|
7
22
|
import { setSearchDebug } from "cubing/search";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
number: cmdNumber,
|
|
11
|
-
string: cmdString,
|
|
12
|
-
command,
|
|
13
|
-
flag,
|
|
14
|
-
oneOf,
|
|
15
|
-
option,
|
|
16
|
-
optional,
|
|
17
|
-
positional,
|
|
18
|
-
run
|
|
19
|
-
} = await import("cmd-ts-too");
|
|
20
|
-
var outputFormats = ["text", "link", "json-text"];
|
|
23
|
+
import { Path } from "path-class";
|
|
24
|
+
var outputFormats = ["auto", "text", "link", "json-text"];
|
|
21
25
|
var notationTypes = ["auto", "LGN"];
|
|
22
|
-
var
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
var eventIDs = Object.entries(twizzleEvents).filter(([_, eventInfo2]) => !!eventInfo2.scramblesImplemented).map(([eventID2, _]) => eventID2);
|
|
27
|
+
var args = run(
|
|
28
|
+
merge(
|
|
29
|
+
object({
|
|
30
|
+
amount: withDefault(
|
|
31
|
+
option("--amount", "-n", integer({ metavar: "AMOUNT", min: 1 }), {
|
|
32
|
+
description: message`Amount of scrambles.`
|
|
33
|
+
}),
|
|
34
|
+
1
|
|
35
|
+
),
|
|
36
|
+
notation: withDefault(
|
|
37
|
+
option("--notation", choice(notationTypes, { metavar: "NOTATION" })),
|
|
38
|
+
"auto"
|
|
39
|
+
)
|
|
32
40
|
}),
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
object({
|
|
42
|
+
format: withDefault(
|
|
43
|
+
option("--format", "-f", choice(outputFormats, { metavar: "FORMAT" })),
|
|
44
|
+
"auto"
|
|
45
|
+
)
|
|
38
46
|
}),
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
47
|
+
object({
|
|
48
|
+
// TODO: consolidate this with `format`: https://github.com/dahlia/optique/issues/57
|
|
49
|
+
text: map(
|
|
50
|
+
option("--text", "-t", {
|
|
51
|
+
description: message`Convenient shorthand for \`--format text\`.`
|
|
52
|
+
}),
|
|
53
|
+
() => "text"
|
|
54
|
+
)
|
|
43
55
|
}),
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
short: "t"
|
|
49
|
-
}),
|
|
50
|
-
eventID: positional({
|
|
51
|
-
type: cmdString,
|
|
52
|
-
displayName: "WCA or unofficial event ID"
|
|
56
|
+
object({
|
|
57
|
+
eventID: argument(choice(eventIDs, { metavar: "EVENT_ID" }), {
|
|
58
|
+
description: message`WCA or unoffiical event ID.`
|
|
59
|
+
})
|
|
53
60
|
})
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
),
|
|
62
|
+
{
|
|
63
|
+
programName: new Path(argv[1]).basename.path,
|
|
64
|
+
description: message`Example: order 3x3x3 "R U R' U R U2' R'"`,
|
|
65
|
+
help: "option",
|
|
66
|
+
completion: {
|
|
67
|
+
mode: "option",
|
|
68
|
+
name: "plural"
|
|
69
|
+
},
|
|
70
|
+
version: {
|
|
71
|
+
mode: "option",
|
|
72
|
+
value: packageVersion
|
|
64
73
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
var { amount, format: argsFormat, notation, text, eventID } = args;
|
|
77
|
+
var format = argsFormat ?? text ?? (!process.stdout.isTTY ? "text" : "auto");
|
|
78
|
+
setSearchDebug({ logPerf: false, showWorkerInstantiationWarnings: false });
|
|
79
|
+
function scrambleText(scramble) {
|
|
80
|
+
return scramble.toString({
|
|
81
|
+
// TODO: any
|
|
82
|
+
notation
|
|
83
|
+
// TODO: handle type conversion at arg parse time.
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function scrambleLink(scramble) {
|
|
87
|
+
const url = new URL("https://alpha.twizzle.net/edit/");
|
|
88
|
+
const puzzleID = eventInfo(eventID)?.puzzleID;
|
|
89
|
+
puzzleID && url.searchParams.set("puzzle", puzzleID);
|
|
90
|
+
url.searchParams.set("alg", scrambleText(scramble));
|
|
91
|
+
return url.toString();
|
|
92
|
+
}
|
|
93
|
+
var JSONListPrinter = class {
|
|
94
|
+
#finished = false;
|
|
95
|
+
#firstValuePrintedAlready = false;
|
|
96
|
+
constructor() {
|
|
97
|
+
process.stdout.write("[\n ");
|
|
98
|
+
}
|
|
99
|
+
push(value) {
|
|
100
|
+
if (this.#firstValuePrintedAlready) {
|
|
101
|
+
process.stdout.write(",\n ");
|
|
71
102
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
push(value) {
|
|
79
|
-
if (this.#firstValuePrintedAlready) {
|
|
80
|
-
process.stdout.write(",\n ");
|
|
81
|
-
}
|
|
82
|
-
this.#firstValuePrintedAlready = true;
|
|
83
|
-
process.stdout.write(JSON.stringify(value));
|
|
84
|
-
}
|
|
85
|
-
finish() {
|
|
86
|
-
if (this.#finished) {
|
|
87
|
-
throw new Error("Tried to finish JSON list printing multiple times.");
|
|
88
|
-
}
|
|
89
|
-
this.#finished = true;
|
|
90
|
-
console.log("\n]");
|
|
91
|
-
}
|
|
103
|
+
this.#firstValuePrintedAlready = true;
|
|
104
|
+
process.stdout.write(JSON.stringify(value));
|
|
105
|
+
}
|
|
106
|
+
finish() {
|
|
107
|
+
if (this.#finished) {
|
|
108
|
+
throw new Error("Tried to finish JSON list printing multiple times.");
|
|
92
109
|
}
|
|
110
|
+
this.#finished = true;
|
|
111
|
+
console.log("\n]");
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
function nodeForgetTopLevelAwaitWorkaround(_promise) {
|
|
115
|
+
return Promise.resolve();
|
|
116
|
+
}
|
|
117
|
+
await nodeForgetTopLevelAwaitWorkaround(
|
|
118
|
+
(async () => {
|
|
93
119
|
if (format !== "json-text" && amount === 1) {
|
|
94
120
|
const scramble = await randomScrambleForEvent(eventID);
|
|
95
121
|
switch (format) {
|
|
122
|
+
case "auto": {
|
|
123
|
+
console.log(`${scrambleText(scramble)}
|
|
124
|
+
|
|
125
|
+
\u{1F517} ${scrambleLink(scramble)}`);
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
96
128
|
case "text": {
|
|
97
129
|
console.log(scrambleText(scramble));
|
|
98
130
|
break;
|
|
@@ -107,14 +139,8 @@ var app = command({
|
|
|
107
139
|
"Encountered `json` format in code that is not expected to handle it."
|
|
108
140
|
);
|
|
109
141
|
}
|
|
110
|
-
case "auto": {
|
|
111
|
-
console.log(`${scrambleText(scramble)}
|
|
112
|
-
|
|
113
|
-
\u{1F517} ${scrambleLink(scramble)}`);
|
|
114
|
-
break;
|
|
115
|
-
}
|
|
116
142
|
default: {
|
|
117
|
-
throw new Error("
|
|
143
|
+
throw new Error("Invalid format!");
|
|
118
144
|
}
|
|
119
145
|
}
|
|
120
146
|
} else {
|
|
@@ -122,6 +148,14 @@ var app = command({
|
|
|
122
148
|
for (let i = 0; i < amount; i++) {
|
|
123
149
|
const scramble = await randomScrambleForEvent(eventID);
|
|
124
150
|
switch (format) {
|
|
151
|
+
case "auto": {
|
|
152
|
+
console.log(`// Scramble #${i + 1}
|
|
153
|
+
${scrambleText(scramble)}
|
|
154
|
+
|
|
155
|
+
\u{1F517} ${scrambleLink(scramble)}
|
|
156
|
+
`);
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
125
159
|
case "text": {
|
|
126
160
|
console.log(`// Scramble #${i + 1}`);
|
|
127
161
|
console.log(`${scrambleText(scramble)}
|
|
@@ -138,25 +172,13 @@ var app = command({
|
|
|
138
172
|
jsonListPrinter?.push(scramble.toString());
|
|
139
173
|
break;
|
|
140
174
|
}
|
|
141
|
-
case "auto": {
|
|
142
|
-
console.log(`// Scramble #${i + 1}
|
|
143
|
-
${scrambleText(scramble)}
|
|
144
|
-
|
|
145
|
-
\u{1F517} ${scrambleLink(scramble)}
|
|
146
|
-
`);
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
175
|
default: {
|
|
150
|
-
throw new Error("
|
|
176
|
+
throw new Error("Invalid format!");
|
|
151
177
|
}
|
|
152
178
|
}
|
|
153
179
|
}
|
|
154
180
|
jsonListPrinter?.finish();
|
|
155
181
|
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function nodeForgetTopLevelAwaitWorkaround(_promise) {
|
|
159
|
-
return Promise.resolve();
|
|
160
|
-
}
|
|
161
|
-
await nodeForgetTopLevelAwaitWorkaround(run(binary(app), process.argv));
|
|
182
|
+
})()
|
|
183
|
+
);
|
|
162
184
|
//# sourceMappingURL=scramble.js.map
|
package/dist/bin/scramble.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/bin/scramble.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": []
|
|
4
|
+
"sourcesContent": ["/**\n\nTo run this file directly:\n\n```shell\nbun run ./src/bin/scramble.ts -- 333\n```\n\nTo test completions:\n\n```shell\n# fish (from repo root)\nset PATH (pwd)/src/test/bin-path $PATH\nscramble --completions fish | source\n```\n\n```shell\n# zsh (from repo root)\nautoload -Uz compinit\ncompinit\nexport PATH=$(pwd)/src/test/bin-path:$PATH\nsource <(scramble --completions zsh)\n```\n\n*/\n\nimport { argv } from \"node:process\";\nimport {\n argument,\n choice,\n integer,\n map,\n merge,\n message,\n object,\n option,\n withDefault,\n} from \"@optique/core\";\nimport { run } from \"@optique/run\";\nimport type { Alg } from \"cubing/alg\";\nimport { eventInfo, twizzleEvents } from \"cubing/puzzles\";\nimport { randomScrambleForEvent } from \"cubing/scramble\";\nimport { setSearchDebug } from \"cubing/search\";\nimport { Path } from \"path-class\";\nimport { packageVersion } from \"../metadata/packageVersion\";\n\nconst outputFormats = [\"auto\", \"text\", \"link\", \"json-text\"] as const;\nconst notationTypes = [\"auto\", \"LGN\"] as const;\nconst eventIDs = Object.entries(twizzleEvents)\n .filter(([_, eventInfo]) => !!eventInfo.scramblesImplemented)\n .map(([eventID, _]) => eventID);\n\nconst args = run(\n merge(\n object({\n amount: withDefault(\n option(\"--amount\", \"-n\", integer({ metavar: \"AMOUNT\", min: 1 }), {\n description: message`Amount of scrambles.`,\n }),\n 1,\n ),\n notation: withDefault(\n option(\"--notation\", choice(notationTypes, { metavar: \"NOTATION\" })),\n \"auto\",\n ),\n }),\n object({\n format: withDefault(\n option(\"--format\", \"-f\", choice(outputFormats, { metavar: \"FORMAT\" })),\n \"auto\",\n ),\n }),\n object({\n // TODO: consolidate this with `format`: https://github.com/dahlia/optique/issues/57\n text: map(\n option(\"--text\", \"-t\", {\n description: message`Convenient shorthand for \\`--format text\\`.`,\n }),\n () => \"text\",\n ),\n }),\n object({\n eventID: argument(choice(eventIDs, { metavar: \"EVENT_ID\" }), {\n description: message`WCA or unoffiical event ID.`,\n }),\n }),\n ),\n {\n programName: new Path(argv[1]).basename.path,\n description: message`Example: order 3x3x3 \"R U R' U R U2' R'\"`,\n help: \"option\",\n completion: {\n mode: \"option\",\n name: \"plural\",\n },\n version: {\n mode: \"option\",\n value: packageVersion,\n },\n },\n);\n\nconst { amount, format: argsFormat, notation, text, eventID } = args;\nconst format = argsFormat ?? text ?? (!process.stdout.isTTY ? \"text\" : \"auto\");\n\nsetSearchDebug({ logPerf: false, showWorkerInstantiationWarnings: false });\n\nfunction scrambleText(scramble: Alg): string {\n return scramble.toString({\n // TODO: any\n notation: notation as (typeof notationTypes)[number], // TODO: handle type conversion at arg parse time.\n });\n}\n\nfunction scrambleLink(scramble: Alg): string {\n const url = new URL(\"https://alpha.twizzle.net/edit/\");\n const puzzleID = eventInfo(eventID)?.puzzleID;\n puzzleID && url.searchParams.set(\"puzzle\", puzzleID);\n url.searchParams.set(\"alg\", scrambleText(scramble));\n return url.toString();\n}\n\nclass JSONListPrinter<T> {\n #finished = false;\n #firstValuePrintedAlready = false;\n constructor() {\n process.stdout.write(\"[\\n \");\n }\n\n push(value: T) {\n if (this.#firstValuePrintedAlready) {\n process.stdout.write(\",\\n \");\n }\n this.#firstValuePrintedAlready = true;\n process.stdout.write(JSON.stringify(value));\n }\n\n finish() {\n if (this.#finished) {\n throw new Error(\"Tried to finish JSON list printing multiple times.\");\n }\n this.#finished = true;\n console.log(\"\\n]\");\n }\n}\n\n// Possibly: https://github.com/nodejs/node/issues/55468 Technically we could\n// just remove `await` from the called function, but this is semantically\n// unsound. This function encapsulates the unsoundness.\nfunction nodeForgetTopLevelAwaitWorkaround(\n _promise: Promise<void>,\n): Promise<void> {\n return Promise.resolve();\n}\n\nawait nodeForgetTopLevelAwaitWorkaround(\n (async () => {\n if (format !== \"json-text\" && amount === 1) {\n const scramble = await randomScrambleForEvent(eventID);\n\n switch (format) {\n case \"auto\": {\n console.log(`${scrambleText(scramble)}\n\n\uD83D\uDD17 ${scrambleLink(scramble)}`);\n break;\n }\n case \"text\": {\n console.log(scrambleText(scramble));\n break;\n }\n case \"link\": {\n console.log(scrambleLink(scramble));\n break;\n }\n // @ts-expect-error This is a code guard for future refactoring.\n case \"json-text\": {\n throw new Error(\n \"Encountered `json` format in code that is not expected to handle it.\",\n );\n }\n default: {\n throw new Error(\"Invalid format!\") as never;\n }\n }\n } else {\n const jsonListPrinter: JSONListPrinter<string> | undefined =\n format === \"json-text\" ? new JSONListPrinter() : undefined;\n for (let i = 0; i < amount; i++) {\n const scramble = await randomScrambleForEvent(eventID);\n switch (format) {\n case \"auto\": {\n console.log(`// Scramble #${i + 1}\n${scrambleText(scramble)}\n\n\uD83D\uDD17 ${scrambleLink(scramble)}\n`);\n break;\n }\n case \"text\": {\n console.log(`// Scramble #${i + 1}`);\n console.log(`${scrambleText(scramble)}\\n`);\n break;\n }\n case \"link\": {\n console.log(`// Scramble #${i + 1}`);\n console.log(`${scrambleLink(scramble)}\\n`);\n break;\n }\n case \"json-text\": {\n jsonListPrinter?.push(scramble.toString());\n break;\n }\n default: {\n throw new Error(\"Invalid format!\") as never;\n }\n }\n }\n jsonListPrinter?.finish();\n }\n })(),\n);\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["eventInfo", "eventID"]
|
|
7
7
|
}
|