@logic-pad/core 0.23.2 → 0.25.0
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/assets/logic-core.global.d.ts +53 -0
- package/dist/benchmark/helper.d.ts +21 -0
- package/dist/benchmark/helper.js +34 -0
- package/dist/benchmark/prepareBench.js +140 -0
- package/dist/benchmark/runBench.js +206 -0
- package/dist/{data → src/data}/dataHelper.js +4 -18
- package/dist/{data → src/data}/grid.js +22 -70
- package/dist/{data → src/data}/gridZones.js +1 -6
- package/dist/{data → src/data}/rules/banPatternRule.js +19 -50
- package/dist/{data → src/data}/rules/cellCountPerZoneRule.js +2 -6
- package/dist/{data → src/data}/rules/cellCountRule.js +62 -96
- package/dist/{data → src/data}/rules/completePatternRule.js +6 -22
- package/dist/{data → src/data}/rules/connectAllRule.js +20 -50
- package/dist/{data → src/data}/rules/connectZonesRule.js +28 -58
- package/dist/{data → src/data}/rules/containsShapeRule.js +29 -65
- package/dist/{data → src/data}/rules/customRule.js +28 -57
- package/dist/{data → src/data}/rules/differentCountPerZoneRule.js +33 -68
- package/dist/{data → src/data}/rules/exactCountPerZoneRule.js +43 -82
- package/dist/{data → src/data}/rules/foresightRule.js +50 -87
- package/dist/{data → src/data}/rules/lyingSymbolRule.js +37 -88
- package/dist/{data → src/data}/rules/musicControlLine.js +69 -131
- package/dist/{data → src/data}/rules/musicGridRule.js +43 -76
- package/dist/{data → src/data}/rules/mysteryRule.js +29 -58
- package/dist/src/data/rules/noLoopsRule.d.ts +29 -0
- package/dist/src/data/rules/noLoopsRule.js +111 -0
- package/dist/{data → src/data}/rules/offByXRule.js +49 -74
- package/dist/{data → src/data}/rules/perfectionRule.js +8 -28
- package/dist/{data → src/data}/rules/regionAreaRule.js +47 -86
- package/dist/{data → src/data}/rules/regionShapeRule.js +2 -6
- package/dist/{data → src/data}/rules/rules.gen.d.ts +1 -0
- package/dist/{data → src/data}/rules/rules.gen.js +1 -0
- package/dist/{data → src/data}/rules/sameCountPerZoneRule.js +33 -68
- package/dist/{data → src/data}/rules/sameShapeRule.js +18 -44
- package/dist/{data → src/data}/rules/symbolsPerRegionRule.js +52 -90
- package/dist/{data → src/data}/rules/undercluedRule.js +11 -27
- package/dist/{data → src/data}/rules/uniqueShapeRule.js +18 -44
- package/dist/{data → src/data}/rules/wrapAroundRule.js +99 -138
- package/dist/{data → src/data}/serializer/serializer_checksum.js +1 -9
- package/dist/{data → src/data}/serializer/serializer_v0.js +1 -9
- package/dist/{data → src/data}/solver/auto/autoSolver.js +12 -39
- package/dist/{data → src/data}/solver/backtrack/backtrackSolver.js +15 -39
- package/dist/{data → src/data}/solver/backtrack/backtrackWorker.js +1 -1
- package/dist/{data → src/data}/solver/backtrack/data.js +16 -48
- package/dist/{data → src/data}/solver/backtrack/rules/banPattern.js +1 -6
- package/dist/{data → src/data}/solver/backtrack/rules/cellCount.js +1 -6
- package/dist/{data → src/data}/solver/backtrack/rules/connectAll.js +1 -6
- package/dist/{data → src/data}/solver/backtrack/rules/regionArea.js +1 -6
- package/dist/{data → src/data}/solver/backtrack/rules/regionShape.js +1 -6
- package/dist/{data → src/data}/solver/backtrack/rules/sameShape.js +1 -6
- package/dist/{data → src/data}/solver/backtrack/rules/symbolsPerRegion.js +2 -12
- package/dist/{data → src/data}/solver/backtrack/rules/uniqueShape.js +1 -6
- package/dist/{data → src/data}/solver/backtrack/symbols/areaNumber.js +1 -6
- package/dist/{data → src/data}/solver/backtrack/symbols/dart.js +1 -6
- package/dist/{data → src/data}/solver/backtrack/symbols/directionLinker.js +3 -13
- package/dist/{data → src/data}/solver/backtrack/symbols/focus.js +3 -13
- package/dist/{data → src/data}/solver/backtrack/symbols/galaxy.js +1 -6
- package/dist/{data → src/data}/solver/backtrack/symbols/letter.js +2 -12
- package/dist/{data → src/data}/solver/backtrack/symbols/lotus.js +1 -6
- package/dist/{data → src/data}/solver/backtrack/symbols/minesweeper.js +3 -13
- package/dist/{data → src/data}/solver/backtrack/symbols/myopia.js +1 -6
- package/dist/{data → src/data}/solver/backtrack/symbols/viewpoint.js +1 -6
- package/dist/{data → src/data}/solver/cspuz/cspuzSolver.js +22 -46
- package/dist/{data → src/data}/solver/eventIteratingSolver.js +9 -12
- package/dist/{data → src/data}/solver/solver.js +1 -8
- package/dist/src/data/solver/universal/universalSolver.js +20 -0
- package/dist/src/data/solver/universal/universalWorker.d.ts +1 -0
- package/dist/{data → src/data}/solver/z3/modules/areaNumberModule.js +1 -9
- package/dist/{data → src/data}/solver/z3/modules/cellCountModule.js +1 -9
- package/dist/{data → src/data}/solver/z3/modules/connectAllModule.js +1 -9
- package/dist/{data → src/data}/solver/z3/modules/dartModule.js +1 -9
- package/dist/{data → src/data}/solver/z3/modules/letterModule.js +1 -9
- package/dist/{data → src/data}/solver/z3/modules/myopiaModule.js +1 -9
- package/dist/{data → src/data}/solver/z3/modules/regionAreaModule.js +1 -9
- package/dist/{data → src/data}/solver/z3/modules/viewpointModule.js +1 -9
- package/dist/{data → src/data}/solver/z3/z3Solver.js +4 -27
- package/dist/{data → src/data}/solver/z3/z3SolverContext.js +3 -12
- package/dist/{data → src/data}/symbols/areaNumberSymbol.js +28 -44
- package/dist/{data → src/data}/symbols/customIconSymbol.js +40 -64
- package/dist/{data → src/data}/symbols/customSymbol.js +4 -12
- package/dist/{data → src/data}/symbols/customTextSymbol.js +40 -64
- package/dist/{data → src/data}/symbols/dartSymbol.js +39 -59
- package/dist/{data → src/data}/symbols/directionLinkerSymbol.js +34 -63
- package/dist/src/data/symbols/everyLetterSymbol.d.ts +32 -0
- package/dist/src/data/symbols/everyLetterSymbol.js +117 -0
- package/dist/{data → src/data}/symbols/focusSymbol.js +49 -69
- package/dist/{data → src/data}/symbols/galaxySymbol.js +12 -31
- package/dist/{data → src/data}/symbols/hiddenSymbol.js +34 -62
- package/dist/{data → src/data}/symbols/houseSymbol.js +39 -67
- package/dist/{data → src/data}/symbols/letterSymbol.js +40 -68
- package/dist/{data → src/data}/symbols/lotusSymbol.js +58 -81
- package/dist/{data → src/data}/symbols/minesweeperSymbol.js +30 -46
- package/dist/{data → src/data}/symbols/myopiaSymbol.js +45 -69
- package/dist/{data → src/data}/symbols/numberSymbol.js +6 -18
- package/dist/{data → src/data}/symbols/symbol.js +4 -12
- package/dist/{data → src/data}/symbols/symbols.gen.d.ts +1 -0
- package/dist/{data → src/data}/symbols/symbols.gen.js +1 -0
- package/dist/{data → src/data}/symbols/viewpointSymbol.js +26 -42
- package/dist/{data → src/data}/tile.js +6 -18
- package/dist/src/data/validateAsync.js +71 -0
- package/dist/src/data/validateAsyncWorker.d.ts +1 -0
- package/dist/{index.d.ts → src/index.d.ts} +3 -1
- package/dist/{index.js → src/index.js} +3 -1
- package/package.json +6 -2
- package/dist/data/solver/universal/universalSolver.js +0 -38
- package/dist/data/validateAsync.js +0 -128
- /package/dist/{data/solver/backtrack/backtrackWorker.d.ts → benchmark/prepareBench.d.ts} +0 -0
- /package/dist/{data/solver/cspuz/cspuzWorker.d.ts → benchmark/runBench.d.ts} +0 -0
- /package/dist/{data → src/data}/config.d.ts +0 -0
- /package/dist/{data → src/data}/config.js +0 -0
- /package/dist/{data → src/data}/configurable.d.ts +0 -0
- /package/dist/{data → src/data}/configurable.js +0 -0
- /package/dist/{data → src/data}/dataHelper.d.ts +0 -0
- /package/dist/{data → src/data}/events/eventHelper.d.ts +0 -0
- /package/dist/{data → src/data}/events/eventHelper.js +0 -0
- /package/dist/{data → src/data}/events/onFinalValidation.d.ts +0 -0
- /package/dist/{data → src/data}/events/onFinalValidation.js +0 -0
- /package/dist/{data → src/data}/events/onGetTile.d.ts +0 -0
- /package/dist/{data → src/data}/events/onGetTile.js +0 -0
- /package/dist/{data → src/data}/events/onGridChange.d.ts +0 -0
- /package/dist/{data → src/data}/events/onGridChange.js +0 -0
- /package/dist/{data → src/data}/events/onGridResize.d.ts +0 -0
- /package/dist/{data → src/data}/events/onGridResize.js +0 -0
- /package/dist/{data → src/data}/events/onSetGrid.d.ts +0 -0
- /package/dist/{data → src/data}/events/onSetGrid.js +0 -0
- /package/dist/{data → src/data}/events/onSymbolDisplay.d.ts +0 -0
- /package/dist/{data → src/data}/events/onSymbolDisplay.js +0 -0
- /package/dist/{data → src/data}/events/onSymbolMerge.d.ts +0 -0
- /package/dist/{data → src/data}/events/onSymbolMerge.js +0 -0
- /package/dist/{data → src/data}/events/onSymbolValidation.d.ts +0 -0
- /package/dist/{data → src/data}/events/onSymbolValidation.js +0 -0
- /package/dist/{data → src/data}/grid.d.ts +0 -0
- /package/dist/{data → src/data}/gridConnections.d.ts +0 -0
- /package/dist/{data → src/data}/gridConnections.js +0 -0
- /package/dist/{data → src/data}/gridZones.d.ts +0 -0
- /package/dist/{data → src/data}/instruction.d.ts +0 -0
- /package/dist/{data → src/data}/instruction.js +0 -0
- /package/dist/{data → src/data}/primitives.d.ts +0 -0
- /package/dist/{data → src/data}/primitives.js +0 -0
- /package/dist/{data → src/data}/puzzle.d.ts +0 -0
- /package/dist/{data → src/data}/puzzle.js +0 -0
- /package/dist/{data → src/data}/rules/banPatternRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/cellCountPerZoneRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/cellCountRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/completePatternRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/connectAllRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/connectZonesRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/containsShapeRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/customRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/differentCountPerZoneRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/exactCountPerZoneRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/foresightRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/index.d.ts +0 -0
- /package/dist/{data → src/data}/rules/index.js +0 -0
- /package/dist/{data → src/data}/rules/lyingSymbolRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/musicControlLine.d.ts +0 -0
- /package/dist/{data → src/data}/rules/musicGridRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/mysteryRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/offByXRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/perfectionRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/regionAreaRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/regionShapeRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/rule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/rule.js +0 -0
- /package/dist/{data → src/data}/rules/sameCountPerZoneRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/sameShapeRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/symbolsPerRegionRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/undercluedRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/uniqueShapeRule.d.ts +0 -0
- /package/dist/{data → src/data}/rules/wrapAroundRule.d.ts +0 -0
- /package/dist/{data → src/data}/serializer/allSerializers.d.ts +0 -0
- /package/dist/{data → src/data}/serializer/allSerializers.js +0 -0
- /package/dist/{data → src/data}/serializer/compressor/allCompressors.d.ts +0 -0
- /package/dist/{data → src/data}/serializer/compressor/allCompressors.js +0 -0
- /package/dist/{data → src/data}/serializer/compressor/checksumCompressor.d.ts +0 -0
- /package/dist/{data → src/data}/serializer/compressor/checksumCompressor.js +0 -0
- /package/dist/{data → src/data}/serializer/compressor/compressorBase.d.ts +0 -0
- /package/dist/{data → src/data}/serializer/compressor/compressorBase.js +0 -0
- /package/dist/{data → src/data}/serializer/compressor/deflateCompressor.d.ts +0 -0
- /package/dist/{data → src/data}/serializer/compressor/deflateCompressor.js +0 -0
- /package/dist/{data → src/data}/serializer/compressor/gzipCompressor.d.ts +0 -0
- /package/dist/{data → src/data}/serializer/compressor/gzipCompressor.js +0 -0
- /package/dist/{data → src/data}/serializer/compressor/streamCompressor.d.ts +0 -0
- /package/dist/{data → src/data}/serializer/compressor/streamCompressor.js +0 -0
- /package/dist/{data → src/data}/serializer/serializerBase.d.ts +0 -0
- /package/dist/{data → src/data}/serializer/serializerBase.js +0 -0
- /package/dist/{data → src/data}/serializer/serializer_checksum.d.ts +0 -0
- /package/dist/{data → src/data}/serializer/serializer_v0.d.ts +0 -0
- /package/dist/{data → src/data}/shapes.d.ts +0 -0
- /package/dist/{data → src/data}/shapes.js +0 -0
- /package/dist/{data → src/data}/solver/allSolvers.d.ts +0 -0
- /package/dist/{data → src/data}/solver/allSolvers.js +0 -0
- /package/dist/{data → src/data}/solver/auto/autoSolver.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/backtrackSolver.d.ts +0 -0
- /package/dist/{data/solver/universal/universalWorker.d.ts → src/data/solver/backtrack/backtrackWorker.d.ts} +0 -0
- /package/dist/{data → src/data}/solver/backtrack/data.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/rules/banPattern.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/rules/cellCount.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/rules/connectAll.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/rules/regionArea.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/rules/regionShape.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/rules/sameShape.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/rules/symbolsPerRegion.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/rules/uniqueShape.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/symbols/areaNumber.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/symbols/dart.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/symbols/directionLinker.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/symbols/focus.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/symbols/galaxy.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/symbols/letter.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/symbols/lotus.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/symbols/minesweeper.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/symbols/myopia.d.ts +0 -0
- /package/dist/{data → src/data}/solver/backtrack/symbols/viewpoint.d.ts +0 -0
- /package/dist/{data → src/data}/solver/cspuz/cspuzSolver.d.ts +0 -0
- /package/dist/{data/validateAsyncWorker.d.ts → src/data/solver/cspuz/cspuzWorker.d.ts} +0 -0
- /package/dist/{data → src/data}/solver/cspuz/cspuzWorker.js +0 -0
- /package/dist/{data → src/data}/solver/cspuz/jsonify.d.ts +0 -0
- /package/dist/{data → src/data}/solver/cspuz/jsonify.js +0 -0
- /package/dist/{data → src/data}/solver/eventIteratingSolver.d.ts +0 -0
- /package/dist/{data → src/data}/solver/solver.d.ts +0 -0
- /package/dist/{data → src/data}/solver/universal/universalSolver.d.ts +0 -0
- /package/dist/{data → src/data}/solver/universal/universalWorker.js +0 -0
- /package/dist/{data → src/data}/solver/z3/modules/areaNumberModule.d.ts +0 -0
- /package/dist/{data → src/data}/solver/z3/modules/cellCountModule.d.ts +0 -0
- /package/dist/{data → src/data}/solver/z3/modules/connectAllModule.d.ts +0 -0
- /package/dist/{data → src/data}/solver/z3/modules/dartModule.d.ts +0 -0
- /package/dist/{data → src/data}/solver/z3/modules/index.d.ts +0 -0
- /package/dist/{data → src/data}/solver/z3/modules/index.js +0 -0
- /package/dist/{data → src/data}/solver/z3/modules/letterModule.d.ts +0 -0
- /package/dist/{data → src/data}/solver/z3/modules/modules.gen.d.ts +0 -0
- /package/dist/{data → src/data}/solver/z3/modules/modules.gen.js +0 -0
- /package/dist/{data → src/data}/solver/z3/modules/myopiaModule.d.ts +0 -0
- /package/dist/{data → src/data}/solver/z3/modules/regionAreaModule.d.ts +0 -0
- /package/dist/{data → src/data}/solver/z3/modules/viewpointModule.d.ts +0 -0
- /package/dist/{data → src/data}/solver/z3/modules/z3Module.d.ts +0 -0
- /package/dist/{data → src/data}/solver/z3/modules/z3Module.js +0 -0
- /package/dist/{data → src/data}/solver/z3/utils.d.ts +0 -0
- /package/dist/{data → src/data}/solver/z3/utils.js +0 -0
- /package/dist/{data → src/data}/solver/z3/z3Solver.d.ts +0 -0
- /package/dist/{data → src/data}/solver/z3/z3SolverContext.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/areaNumberSymbol.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/customIconSymbol.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/customSymbol.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/customTextSymbol.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/dartSymbol.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/directionLinkerSymbol.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/focusSymbol.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/galaxySymbol.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/hiddenSymbol.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/houseSymbol.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/index.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/index.js +0 -0
- /package/dist/{data → src/data}/symbols/letterSymbol.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/lotusSymbol.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/minesweeperSymbol.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/myopiaSymbol.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/numberSymbol.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/symbol.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/viewpointSymbol.d.ts +0 -0
- /package/dist/{data → src/data}/tile.d.ts +0 -0
- /package/dist/{data → src/data}/tileConnections.d.ts +0 -0
- /package/dist/{data → src/data}/tileConnections.js +0 -0
- /package/dist/{data → src/data}/validate.d.ts +0 -0
- /package/dist/{data → src/data}/validate.js +0 -0
- /package/dist/{data → src/data}/validateAsync.d.ts +0 -0
- /package/dist/{data → src/data}/validateAsyncWorker.js +0 -0
- /package/dist/{polyfill → src/polyfill}/streamPolyfill.d.ts +0 -0
- /package/dist/{polyfill → src/polyfill}/streamPolyfill.js +0 -0
|
@@ -1929,6 +1929,28 @@ declare global {
|
|
|
1929
1929
|
withVisible(visible: boolean): this;
|
|
1930
1930
|
static cleanSolution(solution: GridData, baseGrid?: GridData): GridData;
|
|
1931
1931
|
}
|
|
1932
|
+
export declare class NoLoopsRule extends Rule {
|
|
1933
|
+
readonly color: Color;
|
|
1934
|
+
readonly title = 'No Loops';
|
|
1935
|
+
private static readonly CONFIGS;
|
|
1936
|
+
private static readonly EXAMPLE_GRID_LIGHT;
|
|
1937
|
+
private static readonly EXAMPLE_GRID_DARK;
|
|
1938
|
+
private static readonly SEARCH_VARIANTS;
|
|
1939
|
+
/**
|
|
1940
|
+
* **No loops in <color> cells**
|
|
1941
|
+
*
|
|
1942
|
+
* @param color - The color of the cells to check.
|
|
1943
|
+
*/
|
|
1944
|
+
constructor(color: Color);
|
|
1945
|
+
get id(): string;
|
|
1946
|
+
get explanation(): string;
|
|
1947
|
+
get configs(): readonly AnyConfig[] | null;
|
|
1948
|
+
createExampleGrid(): GridData;
|
|
1949
|
+
get searchVariants(): SearchVariant[];
|
|
1950
|
+
validateGrid(grid: GridData): RuleState;
|
|
1951
|
+
copyWith({ color }: { color?: Color }): this;
|
|
1952
|
+
withColor(color: Color): this;
|
|
1953
|
+
}
|
|
1932
1954
|
export declare class OffByXRule
|
|
1933
1955
|
extends Rule
|
|
1934
1956
|
implements SymbolValidationHandler
|
|
@@ -3162,6 +3184,37 @@ declare global {
|
|
|
3162
3184
|
withText(text: string): this;
|
|
3163
3185
|
withRotation(rotation: number): this;
|
|
3164
3186
|
}
|
|
3187
|
+
export declare class EveryLetterSymbol extends Symbol$1 {
|
|
3188
|
+
readonly x: number;
|
|
3189
|
+
readonly y: number;
|
|
3190
|
+
readonly letter: string;
|
|
3191
|
+
readonly title = 'Hollow Letter';
|
|
3192
|
+
private static readonly CONFIGS;
|
|
3193
|
+
private static readonly EXAMPLE_GRID;
|
|
3194
|
+
/**
|
|
3195
|
+
* **Include each Hollow Letter once per region**
|
|
3196
|
+
*
|
|
3197
|
+
* @param x - The x-coordinate of the symbol.
|
|
3198
|
+
* @param y - The y-coordinate of the symbol.
|
|
3199
|
+
* @param letter - The letter of the symbol.
|
|
3200
|
+
*/
|
|
3201
|
+
constructor(x: number, y: number, letter: string);
|
|
3202
|
+
get id(): string;
|
|
3203
|
+
get explanation(): string;
|
|
3204
|
+
get configs(): readonly AnyConfig[] | null;
|
|
3205
|
+
createExampleGrid(): GridData;
|
|
3206
|
+
validateSymbol(grid: GridData): State;
|
|
3207
|
+
copyWith({
|
|
3208
|
+
x,
|
|
3209
|
+
y,
|
|
3210
|
+
letter,
|
|
3211
|
+
}: {
|
|
3212
|
+
x?: number;
|
|
3213
|
+
y?: number;
|
|
3214
|
+
letter?: string;
|
|
3215
|
+
}): this;
|
|
3216
|
+
withLetter(letter: string): this;
|
|
3217
|
+
}
|
|
3165
3218
|
export declare class HiddenSymbol
|
|
3166
3219
|
extends Symbol$1
|
|
3167
3220
|
implements SymbolDisplayHandler
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Puzzle } from '../src/data/puzzle.js';
|
|
2
|
+
import CompressorBase from '../src/data/serializer/compressor/compressorBase.js';
|
|
3
|
+
declare class BunCompressor extends CompressorBase {
|
|
4
|
+
get id(): string;
|
|
5
|
+
compress(input: string): Promise<string>;
|
|
6
|
+
decompress(input: string): Promise<string>;
|
|
7
|
+
}
|
|
8
|
+
export declare const bunCompressor: BunCompressor;
|
|
9
|
+
export interface PuzzleEntry {
|
|
10
|
+
pid: number;
|
|
11
|
+
difficulty: number;
|
|
12
|
+
puzzleLink: string;
|
|
13
|
+
}
|
|
14
|
+
export interface BenchmarkEntry {
|
|
15
|
+
pid: number;
|
|
16
|
+
supported: boolean;
|
|
17
|
+
solveTime: number;
|
|
18
|
+
solveCorrect: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare function parseLink(link: string): Promise<Puzzle>;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Serializer } from '../src/data/serializer/allSerializers.js';
|
|
2
|
+
import { encode, decode } from 'uint8-to-base64';
|
|
3
|
+
import CompressorBase from '../src/data/serializer/compressor/compressorBase.js';
|
|
4
|
+
const decoder = new TextDecoder();
|
|
5
|
+
const encoder = new TextEncoder();
|
|
6
|
+
class BunCompressor extends CompressorBase {
|
|
7
|
+
get id() {
|
|
8
|
+
return 'dfl';
|
|
9
|
+
}
|
|
10
|
+
compress(input) {
|
|
11
|
+
const data = Bun.deflateSync(encoder.encode(input), {
|
|
12
|
+
library: 'libdeflate',
|
|
13
|
+
level: 12,
|
|
14
|
+
});
|
|
15
|
+
return Promise.resolve(`${this.id}_${encode(data).replace(/\+/g, '-').replace(/\//g, '_')}`);
|
|
16
|
+
}
|
|
17
|
+
decompress(input) {
|
|
18
|
+
const data = decode(input.replace(`${this.id}_`, '').replace(/-/g, '+').replace(/_/g, '/'));
|
|
19
|
+
const result = Bun.inflateSync(data, {
|
|
20
|
+
library: 'libdeflate',
|
|
21
|
+
level: 12,
|
|
22
|
+
});
|
|
23
|
+
return Promise.resolve(decoder.decode(result));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export const bunCompressor = new BunCompressor();
|
|
27
|
+
export async function parseLink(link) {
|
|
28
|
+
const url = new URL(link);
|
|
29
|
+
const data = url.searchParams.get('d');
|
|
30
|
+
if (data === null) {
|
|
31
|
+
throw new Error('Missing data parameter');
|
|
32
|
+
}
|
|
33
|
+
return Serializer.parsePuzzle(await bunCompressor.decompress(data));
|
|
34
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { parseArgs } from 'util';
|
|
2
|
+
import { allSolvers } from '../src/data/solver/allSolvers.js';
|
|
3
|
+
import { parseLink } from './helper.js';
|
|
4
|
+
import PQueue from 'p-queue';
|
|
5
|
+
const allPuzzlesPath = 'benchmark/data/all_puzzles_logic_pad.json';
|
|
6
|
+
const { values, positionals } = parseArgs({
|
|
7
|
+
args: Bun.argv,
|
|
8
|
+
options: {
|
|
9
|
+
maxTime: {
|
|
10
|
+
type: 'string',
|
|
11
|
+
default: '10',
|
|
12
|
+
short: 't',
|
|
13
|
+
},
|
|
14
|
+
maxCount: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
default: '99999',
|
|
17
|
+
short: 'c',
|
|
18
|
+
},
|
|
19
|
+
concurrency: {
|
|
20
|
+
type: 'string',
|
|
21
|
+
default: '4',
|
|
22
|
+
short: 'n',
|
|
23
|
+
},
|
|
24
|
+
help: {
|
|
25
|
+
type: 'boolean',
|
|
26
|
+
short: 'h',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
strict: true,
|
|
30
|
+
allowPositionals: true,
|
|
31
|
+
});
|
|
32
|
+
positionals.splice(0, 2); // Remove "bun" and script name
|
|
33
|
+
if (values.help || positionals.length !== 1) {
|
|
34
|
+
console.log(`
|
|
35
|
+
Usage: bun bench:prepare <solver> [options]
|
|
36
|
+
|
|
37
|
+
Options:
|
|
38
|
+
-t, --maxTime <number> Maximum seconds allowed for each solve (default: 10)
|
|
39
|
+
-c, --maxCount <number> Maximum number of puzzles included (default: 100)
|
|
40
|
+
-n, --concurrency <number> Number of solves to run concurrently (default: 4)
|
|
41
|
+
-h, --help Show this help message
|
|
42
|
+
|
|
43
|
+
Solver:
|
|
44
|
+
Name of the solver to benchmark. Available solvers are:
|
|
45
|
+
${[...allSolvers.keys()].map(s => ` - ${s}`).join('\n')}
|
|
46
|
+
`);
|
|
47
|
+
process.exit(0);
|
|
48
|
+
}
|
|
49
|
+
const maxTime = parseFloat(values.maxTime) * 1000;
|
|
50
|
+
const maxCount = parseInt(values.maxCount);
|
|
51
|
+
const solverName = positionals[0];
|
|
52
|
+
const solver = allSolvers.get(solverName);
|
|
53
|
+
if (!solver) {
|
|
54
|
+
console.error(`Error: Solver "${solverName}" not found.`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
const allPuzzles = (await Bun.file(allPuzzlesPath).json());
|
|
58
|
+
allPuzzles.sort(() => Math.random() - 0.5);
|
|
59
|
+
const results = [];
|
|
60
|
+
const pqueue = new PQueue({ concurrency: 4 });
|
|
61
|
+
function printEntry(benchmarkEntry, entryId, solverId, pid) {
|
|
62
|
+
if (benchmarkEntry.supported) {
|
|
63
|
+
console.log(`${solverId}\t| ${entryId} / ${allPuzzles.length}\t| ${pid}\t| ${Number.isNaN(benchmarkEntry.solveTime)
|
|
64
|
+
? 'timeout'
|
|
65
|
+
: `${benchmarkEntry.solveTime.toFixed(0)}ms`} ${benchmarkEntry.solveCorrect ? '✓' : '✗'}`);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
console.log(`${solverId}\t| ${entryId} / ${allPuzzles.length}\t| ${pid}\t| unsupported`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
console.log('Available\t| Selected\t| PID\t| Result');
|
|
72
|
+
for (const entry of allPuzzles) {
|
|
73
|
+
if (results.filter(r => r.result.solveCorrect && r.result.supported).length >=
|
|
74
|
+
maxCount) {
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
const puzzle = await parseLink(entry.puzzleLink);
|
|
78
|
+
void pqueue.add(async () => {
|
|
79
|
+
if (!solver.isGridSupported(puzzle.grid)) {
|
|
80
|
+
results.push({
|
|
81
|
+
puzzle: entry,
|
|
82
|
+
result: {
|
|
83
|
+
pid: entry.pid,
|
|
84
|
+
supported: false,
|
|
85
|
+
solveTime: Number.NaN,
|
|
86
|
+
solveCorrect: false,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
printEntry(results[results.length - 1].result, results.length, solverName, entry.pid);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const startTime = performance.now();
|
|
93
|
+
const abortController = new AbortController();
|
|
94
|
+
const benchmarkEntry = {
|
|
95
|
+
pid: entry.pid,
|
|
96
|
+
supported: true,
|
|
97
|
+
solveTime: Number.NaN,
|
|
98
|
+
solveCorrect: false,
|
|
99
|
+
};
|
|
100
|
+
let step = 0;
|
|
101
|
+
const handle = setTimeout(() => {
|
|
102
|
+
abortController.abort();
|
|
103
|
+
}, maxTime);
|
|
104
|
+
try {
|
|
105
|
+
for await (const solution of solver.solve(puzzle.grid, abortController.signal)) {
|
|
106
|
+
if (step === 0) {
|
|
107
|
+
const solveCorrect = solution?.colorEquals(puzzle.solution) ?? false;
|
|
108
|
+
if (!solveCorrect)
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
benchmarkEntry.solveCorrect = solution === null;
|
|
113
|
+
if (benchmarkEntry.solveCorrect)
|
|
114
|
+
benchmarkEntry.solveTime = performance.now() - startTime;
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
step++;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
benchmarkEntry.solveCorrect = false;
|
|
122
|
+
}
|
|
123
|
+
clearTimeout(handle);
|
|
124
|
+
results.push({ puzzle: entry, result: benchmarkEntry });
|
|
125
|
+
printEntry(results[results.length - 1].result, results.length, solverName, entry.pid);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
await pqueue.onIdle();
|
|
129
|
+
const selectedPuzzles = results.filter(r => r.result.solveCorrect && r.result.supported);
|
|
130
|
+
const benchmarkEntries = selectedPuzzles.map(r => r.result);
|
|
131
|
+
await Bun.write(`benchmark/data/bench_${solverName}_puzzles.json`, JSON.stringify(selectedPuzzles.map(r => r.puzzle), null, 2));
|
|
132
|
+
await Bun.write(`benchmark/data/bench_${solverName}_results.json`, JSON.stringify(benchmarkEntries, null, 2));
|
|
133
|
+
console.log(`
|
|
134
|
+
Benchmark preparation completed. Selected ${selectedPuzzles.length} puzzles.
|
|
135
|
+
|
|
136
|
+
- Solver: ${solverName} Max Time: ${maxTime}ms Max Count: ${maxCount}
|
|
137
|
+
- Average time: ${benchmarkEntries.filter(e => !Number.isNaN(e.solveTime)).reduce((a, b) => a + b.solveTime, 0) / benchmarkEntries.filter(e => !Number.isNaN(e.solveTime)).length}ms
|
|
138
|
+
- Number of timeouts: ${benchmarkEntries.filter(e => Number.isNaN(e.solveTime)).length}
|
|
139
|
+
- Solve correctness: ${benchmarkEntries.filter(e => e.solveCorrect).length} / ${benchmarkEntries.length}
|
|
140
|
+
`);
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { parseArgs } from 'util';
|
|
2
|
+
import { allSolvers } from '../src/data/solver/allSolvers.js';
|
|
3
|
+
import { parseLink } from './helper.js';
|
|
4
|
+
import PQueue from 'p-queue';
|
|
5
|
+
const { values, positionals } = parseArgs({
|
|
6
|
+
args: Bun.argv,
|
|
7
|
+
options: {
|
|
8
|
+
maxTime: {
|
|
9
|
+
type: 'string',
|
|
10
|
+
default: '10',
|
|
11
|
+
short: 't',
|
|
12
|
+
},
|
|
13
|
+
maxCount: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
default: '99999',
|
|
16
|
+
short: 'c',
|
|
17
|
+
},
|
|
18
|
+
concurrency: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
default: '4',
|
|
21
|
+
short: 'n',
|
|
22
|
+
},
|
|
23
|
+
help: {
|
|
24
|
+
type: 'boolean',
|
|
25
|
+
short: 'h',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
strict: true,
|
|
29
|
+
allowPositionals: true,
|
|
30
|
+
});
|
|
31
|
+
positionals.splice(0, 2); // Remove "bun" and script name
|
|
32
|
+
if (values.help || positionals.length === 0) {
|
|
33
|
+
console.log(`
|
|
34
|
+
Usage: bun bench:run <solver> [options]
|
|
35
|
+
|
|
36
|
+
Options:
|
|
37
|
+
-t, --maxTime <number> Maximum seconds allowed for each solve (default: 10)
|
|
38
|
+
-c, --maxCount <number> Maximum number of puzzles included (default: 100)
|
|
39
|
+
-n, --concurrency <number> Number of solves to run concurrently (default: 4)
|
|
40
|
+
-h, --help Show this help message
|
|
41
|
+
|
|
42
|
+
Solvers available for benchmarking:
|
|
43
|
+
${[...allSolvers.keys()].map(s => ` - ${s}`).join('\n')}
|
|
44
|
+
`);
|
|
45
|
+
process.exit(0);
|
|
46
|
+
}
|
|
47
|
+
const maxTime = parseFloat(values.maxTime) * 1000;
|
|
48
|
+
const maxCount = parseInt(values.maxCount);
|
|
49
|
+
const concurrency = parseInt(values.concurrency);
|
|
50
|
+
for (const name of positionals) {
|
|
51
|
+
if (!allSolvers.has(name)) {
|
|
52
|
+
console.error(`Error: Solver "${name}" not found.`);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const allPuzzles = (await Bun.file(`benchmark/data/bench_${positionals[0]}_puzzles.json`).json());
|
|
57
|
+
allPuzzles.sort(() => Math.random() - 0.5);
|
|
58
|
+
allPuzzles.splice(maxCount);
|
|
59
|
+
const benchmarkEntries = Object.fromEntries(positionals.map(name => [
|
|
60
|
+
name,
|
|
61
|
+
allPuzzles.map(p => ({
|
|
62
|
+
pid: p.pid,
|
|
63
|
+
supported: false,
|
|
64
|
+
solveTime: Number.NaN,
|
|
65
|
+
solveCorrect: false,
|
|
66
|
+
})),
|
|
67
|
+
]));
|
|
68
|
+
const pqueue = new PQueue({ concurrency });
|
|
69
|
+
function printEntry(benchmarkEntry, entryId, solverId, pid) {
|
|
70
|
+
if (benchmarkEntry.supported) {
|
|
71
|
+
console.log(`${solverId}\t| ${entryId} / ${allPuzzles.length}\t| ${pid}\t| ${Number.isNaN(benchmarkEntry.solveTime)
|
|
72
|
+
? 'timeout'
|
|
73
|
+
: `${benchmarkEntry.solveTime.toFixed(0)}ms`} ${benchmarkEntry.solveCorrect ? '✓' : '✗'}`);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
console.log(`${solverId}\t| ${entryId} / ${allPuzzles.length}\t| ${pid}\t| unsupported`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
console.log('Solver \t| Trial \t| PID\t| Result');
|
|
80
|
+
console.log();
|
|
81
|
+
for (let i = 0; i < allPuzzles.length; i++) {
|
|
82
|
+
const entry = allPuzzles[i];
|
|
83
|
+
const solvers = positionals.slice().sort(() => Math.random() - 0.5);
|
|
84
|
+
const puzzle = await parseLink(entry.puzzleLink);
|
|
85
|
+
for (const solverId of solvers) {
|
|
86
|
+
const solver = allSolvers.get(solverId);
|
|
87
|
+
void pqueue.add(async () => {
|
|
88
|
+
if (!solver.isGridSupported(puzzle.grid)) {
|
|
89
|
+
benchmarkEntries[solverId][i] = {
|
|
90
|
+
pid: entry.pid,
|
|
91
|
+
supported: false,
|
|
92
|
+
solveTime: Number.NaN,
|
|
93
|
+
solveCorrect: false,
|
|
94
|
+
};
|
|
95
|
+
printEntry(benchmarkEntries[solverId][i], i + 1, solverId, entry.pid);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const startTime = performance.now();
|
|
99
|
+
const abortController = new AbortController();
|
|
100
|
+
const benchmarkEntry = {
|
|
101
|
+
pid: entry.pid,
|
|
102
|
+
supported: true,
|
|
103
|
+
solveTime: Number.NaN,
|
|
104
|
+
solveCorrect: false,
|
|
105
|
+
};
|
|
106
|
+
let step = 0;
|
|
107
|
+
const handle = setTimeout(() => {
|
|
108
|
+
abortController.abort();
|
|
109
|
+
}, maxTime);
|
|
110
|
+
try {
|
|
111
|
+
for await (const solution of solver.solve(puzzle.grid, abortController.signal)) {
|
|
112
|
+
if (step === 0) {
|
|
113
|
+
const solveCorrect = solution?.colorEquals(puzzle.solution) ?? false;
|
|
114
|
+
if (!solveCorrect)
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
benchmarkEntry.solveCorrect = solution === null;
|
|
119
|
+
if (benchmarkEntry.solveCorrect)
|
|
120
|
+
benchmarkEntry.solveTime = performance.now() - startTime;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
step++;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
benchmarkEntry.solveCorrect = false;
|
|
128
|
+
}
|
|
129
|
+
clearTimeout(handle);
|
|
130
|
+
benchmarkEntries[solverId][i] = benchmarkEntry;
|
|
131
|
+
printEntry(benchmarkEntry, i + 1, solverId, entry.pid);
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
await pqueue.onIdle();
|
|
136
|
+
const results = positionals.map(name => ({
|
|
137
|
+
solver: name,
|
|
138
|
+
fastestCount: 0,
|
|
139
|
+
solve25: 0,
|
|
140
|
+
solve50: 0,
|
|
141
|
+
solve75: 0,
|
|
142
|
+
solveSD: 0,
|
|
143
|
+
unsupportedCount: 0,
|
|
144
|
+
incorrectCount: 0,
|
|
145
|
+
}));
|
|
146
|
+
for (let i = 0; i < benchmarkEntries[positionals[0]].length; i++) {
|
|
147
|
+
let fastestSolveTime = Number.POSITIVE_INFINITY;
|
|
148
|
+
let fastestSolverIndex = null;
|
|
149
|
+
for (let j = 0; j < positionals.length; j++) {
|
|
150
|
+
const entry = benchmarkEntries[positionals[j]][i];
|
|
151
|
+
if (!entry.supported) {
|
|
152
|
+
results[j].unsupportedCount++;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (entry.solveCorrect && !Number.isNaN(entry.solveTime)) {
|
|
156
|
+
if (entry.solveTime < fastestSolveTime) {
|
|
157
|
+
fastestSolveTime = entry.solveTime;
|
|
158
|
+
fastestSolverIndex = j;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
results[j].incorrectCount++;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (fastestSolverIndex !== null) {
|
|
166
|
+
results[fastestSolverIndex].fastestCount++;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
for (let j = 0; j < positionals.length; j++) {
|
|
170
|
+
const entries = benchmarkEntries[positionals[j]].filter(e => e.supported && e.solveCorrect && !Number.isNaN(e.solveTime));
|
|
171
|
+
// 25th percentile
|
|
172
|
+
const times = entries.map(e => e.solveTime).sort((a, b) => a - b);
|
|
173
|
+
results[j].solve25 =
|
|
174
|
+
times.length === 0
|
|
175
|
+
? Number.NaN
|
|
176
|
+
: times[Math.floor((times.length - 1) * 0.25)];
|
|
177
|
+
// 50th percentile (median)
|
|
178
|
+
results[j].solve50 =
|
|
179
|
+
times.length === 0
|
|
180
|
+
? Number.NaN
|
|
181
|
+
: times[Math.floor((times.length - 1) * 0.5)];
|
|
182
|
+
// 75th percentile
|
|
183
|
+
results[j].solve75 =
|
|
184
|
+
times.length === 0
|
|
185
|
+
? Number.NaN
|
|
186
|
+
: times[Math.floor((times.length - 1) * 0.75)];
|
|
187
|
+
// Standard deviation
|
|
188
|
+
const mean = times.reduce((sum, time) => sum + time, 0) / (times.length || 1);
|
|
189
|
+
const variance = times.reduce((sum, time) => sum + (time - mean) ** 2, 0) /
|
|
190
|
+
(times.length || 1);
|
|
191
|
+
results[j].solveSD = Math.sqrt(variance);
|
|
192
|
+
}
|
|
193
|
+
console.log('\nBenchmark Results:');
|
|
194
|
+
for (const result of results) {
|
|
195
|
+
console.log(`
|
|
196
|
+
${result.solver}:
|
|
197
|
+
Fastest Solves: ${result.fastestCount}
|
|
198
|
+
Solve time:
|
|
199
|
+
P25: ${Number.isNaN(result.solve25) ? 'N/A' : `${result.solve25.toFixed(2)}ms`}
|
|
200
|
+
P50: ${Number.isNaN(result.solve50) ? 'N/A' : `${result.solve50.toFixed(2)}ms`}
|
|
201
|
+
P75: ${Number.isNaN(result.solve75) ? 'N/A' : `${result.solve75.toFixed(2)}ms`}
|
|
202
|
+
SD: ${Number.isNaN(result.solveSD) ? 'N/A' : `${result.solveSD.toFixed(2)}ms`}
|
|
203
|
+
Unsupported Puzzles: ${result.unsupportedCount}
|
|
204
|
+
Incorrect Solutions: ${result.incorrectCount}
|
|
205
|
+
`);
|
|
206
|
+
}
|
|
@@ -199,19 +199,11 @@ export function unescape(text, escapeCharacters = '=,:|') {
|
|
|
199
199
|
return result + text.substring(index);
|
|
200
200
|
}
|
|
201
201
|
export class CachedAccess {
|
|
202
|
+
getter;
|
|
203
|
+
static UNCACHED = Symbol('uncached');
|
|
204
|
+
cache = CachedAccess.UNCACHED;
|
|
202
205
|
constructor(getter) {
|
|
203
|
-
|
|
204
|
-
enumerable: true,
|
|
205
|
-
configurable: true,
|
|
206
|
-
writable: true,
|
|
207
|
-
value: getter
|
|
208
|
-
});
|
|
209
|
-
Object.defineProperty(this, "cache", {
|
|
210
|
-
enumerable: true,
|
|
211
|
-
configurable: true,
|
|
212
|
-
writable: true,
|
|
213
|
-
value: CachedAccess.UNCACHED
|
|
214
|
-
});
|
|
206
|
+
this.getter = getter;
|
|
215
207
|
}
|
|
216
208
|
static of(getter) {
|
|
217
209
|
return new CachedAccess(getter);
|
|
@@ -223,9 +215,3 @@ export class CachedAccess {
|
|
|
223
215
|
return this.cache;
|
|
224
216
|
}
|
|
225
217
|
}
|
|
226
|
-
Object.defineProperty(CachedAccess, "UNCACHED", {
|
|
227
|
-
enumerable: true,
|
|
228
|
-
configurable: true,
|
|
229
|
-
writable: true,
|
|
230
|
-
value: Symbol('uncached')
|
|
231
|
-
});
|
|
@@ -13,6 +13,19 @@ export const NEIGHBOR_OFFSETS = [
|
|
|
13
13
|
{ x: 0, y: 1 },
|
|
14
14
|
];
|
|
15
15
|
export default class GridData {
|
|
16
|
+
width;
|
|
17
|
+
height;
|
|
18
|
+
tiles;
|
|
19
|
+
connections;
|
|
20
|
+
zones;
|
|
21
|
+
symbols;
|
|
22
|
+
rules;
|
|
23
|
+
// Important rules are cached for quick access
|
|
24
|
+
/* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */
|
|
25
|
+
musicGrid = CachedAccess.of(() => this.findRule(rule => rule.id === MajorRule.MusicGrid));
|
|
26
|
+
completePattern = CachedAccess.of(() => this.findRule(rule => rule.id === MajorRule.CompletePattern));
|
|
27
|
+
underclued = CachedAccess.of(() => this.findRule(rule => rule.id === MajorRule.Underclued));
|
|
28
|
+
wrapAround = CachedAccess.of(() => this.findRule(rule => rule.id === MajorRule.WrapAround));
|
|
16
29
|
/* eslint-enable @typescript-eslint/no-unsafe-enum-comparison */
|
|
17
30
|
/**
|
|
18
31
|
* Create a new grid with tiles, connections, symbols and rules.
|
|
@@ -26,74 +39,8 @@ export default class GridData {
|
|
|
26
39
|
* @param rules The rules of the grid.
|
|
27
40
|
*/
|
|
28
41
|
constructor(width, height, tiles, connections, zones, symbols, rules) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
configurable: true,
|
|
32
|
-
writable: true,
|
|
33
|
-
value: width
|
|
34
|
-
});
|
|
35
|
-
Object.defineProperty(this, "height", {
|
|
36
|
-
enumerable: true,
|
|
37
|
-
configurable: true,
|
|
38
|
-
writable: true,
|
|
39
|
-
value: height
|
|
40
|
-
});
|
|
41
|
-
Object.defineProperty(this, "tiles", {
|
|
42
|
-
enumerable: true,
|
|
43
|
-
configurable: true,
|
|
44
|
-
writable: true,
|
|
45
|
-
value: void 0
|
|
46
|
-
});
|
|
47
|
-
Object.defineProperty(this, "connections", {
|
|
48
|
-
enumerable: true,
|
|
49
|
-
configurable: true,
|
|
50
|
-
writable: true,
|
|
51
|
-
value: void 0
|
|
52
|
-
});
|
|
53
|
-
Object.defineProperty(this, "zones", {
|
|
54
|
-
enumerable: true,
|
|
55
|
-
configurable: true,
|
|
56
|
-
writable: true,
|
|
57
|
-
value: void 0
|
|
58
|
-
});
|
|
59
|
-
Object.defineProperty(this, "symbols", {
|
|
60
|
-
enumerable: true,
|
|
61
|
-
configurable: true,
|
|
62
|
-
writable: true,
|
|
63
|
-
value: void 0
|
|
64
|
-
});
|
|
65
|
-
Object.defineProperty(this, "rules", {
|
|
66
|
-
enumerable: true,
|
|
67
|
-
configurable: true,
|
|
68
|
-
writable: true,
|
|
69
|
-
value: void 0
|
|
70
|
-
});
|
|
71
|
-
// Important rules are cached for quick access
|
|
72
|
-
/* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */
|
|
73
|
-
Object.defineProperty(this, "musicGrid", {
|
|
74
|
-
enumerable: true,
|
|
75
|
-
configurable: true,
|
|
76
|
-
writable: true,
|
|
77
|
-
value: CachedAccess.of(() => this.findRule(rule => rule.id === MajorRule.MusicGrid))
|
|
78
|
-
});
|
|
79
|
-
Object.defineProperty(this, "completePattern", {
|
|
80
|
-
enumerable: true,
|
|
81
|
-
configurable: true,
|
|
82
|
-
writable: true,
|
|
83
|
-
value: CachedAccess.of(() => this.findRule(rule => rule.id === MajorRule.CompletePattern))
|
|
84
|
-
});
|
|
85
|
-
Object.defineProperty(this, "underclued", {
|
|
86
|
-
enumerable: true,
|
|
87
|
-
configurable: true,
|
|
88
|
-
writable: true,
|
|
89
|
-
value: CachedAccess.of(() => this.findRule(rule => rule.id === MajorRule.Underclued))
|
|
90
|
-
});
|
|
91
|
-
Object.defineProperty(this, "wrapAround", {
|
|
92
|
-
enumerable: true,
|
|
93
|
-
configurable: true,
|
|
94
|
-
writable: true,
|
|
95
|
-
value: CachedAccess.of(() => this.findRule(rule => rule.id === MajorRule.WrapAround))
|
|
96
|
-
});
|
|
42
|
+
this.width = width;
|
|
43
|
+
this.height = height;
|
|
97
44
|
this.width = width;
|
|
98
45
|
this.height = height;
|
|
99
46
|
this.tiles = tiles ?? array(width, height, () => TileData.empty());
|
|
@@ -906,10 +853,15 @@ export default class GridData {
|
|
|
906
853
|
})));
|
|
907
854
|
const symbols = new Map();
|
|
908
855
|
for (const [id, symbolList] of this.symbols) {
|
|
909
|
-
const newSymbolList = symbolList
|
|
856
|
+
const newSymbolList = symbolList
|
|
857
|
+
.filter(symbol => symbol.x >= origin.x &&
|
|
910
858
|
symbol.y >= origin.y &&
|
|
911
859
|
symbol.x < origin.x + width &&
|
|
912
|
-
symbol.y < origin.y + height)
|
|
860
|
+
symbol.y < origin.y + height)
|
|
861
|
+
.map(symbol => symbol.copyWith({
|
|
862
|
+
x: symbol.x - origin.x,
|
|
863
|
+
y: symbol.y - origin.y,
|
|
864
|
+
}));
|
|
913
865
|
if (newSymbolList.length > 0)
|
|
914
866
|
symbols.set(id, newSymbolList);
|
|
915
867
|
}
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import { isSameEdge } from './dataHelper.js';
|
|
2
2
|
export default class GridZones {
|
|
3
|
+
edges;
|
|
3
4
|
constructor(edges) {
|
|
4
|
-
Object.defineProperty(this, "edges", {
|
|
5
|
-
enumerable: true,
|
|
6
|
-
configurable: true,
|
|
7
|
-
writable: true,
|
|
8
|
-
value: void 0
|
|
9
|
-
});
|
|
10
5
|
this.edges = GridZones.deduplicateEdges(edges ?? []);
|
|
11
6
|
}
|
|
12
7
|
addEdge(edge) {
|