@logic-pad/core 0.24.0 → 0.25.1
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 +22 -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 +15 -68
- 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 +11 -40
- 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/{data → src/data}/symbols/everyLetterSymbol.js +37 -65
- 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/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} +2 -1
- package/dist/{index.js → src/index.js} +2 -1
- package/package.json +13 -10
- 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/everyLetterSymbol.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/symbols.gen.d.ts +0 -0
- /package/dist/{data → src/data}/symbols/symbols.gen.js +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
|
|
@@ -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());
|
|
@@ -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) {
|
|
@@ -4,7 +4,25 @@ import { array } from '../dataHelper.js';
|
|
|
4
4
|
import { Color, State } from '../primitives.js';
|
|
5
5
|
import { getShapeVariants, sanitizePatternGrid, tilesToShape, } from '../shapes.js';
|
|
6
6
|
import Rule from './rule.js';
|
|
7
|
-
class BanPatternRule extends Rule {
|
|
7
|
+
export default class BanPatternRule extends Rule {
|
|
8
|
+
title = 'Ban Pattern';
|
|
9
|
+
static EXAMPLE_GRID = Object.freeze(GridData.create(['nnnnn', 'nnnnn', 'wwwwn', 'nnnnn', 'nnnnn']));
|
|
10
|
+
static CONFIGS = Object.freeze([
|
|
11
|
+
{
|
|
12
|
+
type: ConfigType.Shape,
|
|
13
|
+
default: BanPatternRule.EXAMPLE_GRID,
|
|
14
|
+
resizable: true,
|
|
15
|
+
field: 'pattern',
|
|
16
|
+
description: 'Pattern',
|
|
17
|
+
explanation: 'The pattern to be banned. Can be a mix of dark and light tiles.',
|
|
18
|
+
configurable: true,
|
|
19
|
+
},
|
|
20
|
+
]);
|
|
21
|
+
static SEARCH_VARIANTS = [
|
|
22
|
+
new BanPatternRule(BanPatternRule.EXAMPLE_GRID).searchVariant(),
|
|
23
|
+
];
|
|
24
|
+
pattern;
|
|
25
|
+
cache;
|
|
8
26
|
/**
|
|
9
27
|
* **Don't make this pattern**
|
|
10
28
|
*
|
|
@@ -12,24 +30,6 @@ class BanPatternRule extends Rule {
|
|
|
12
30
|
*/
|
|
13
31
|
constructor(pattern) {
|
|
14
32
|
super();
|
|
15
|
-
Object.defineProperty(this, "title", {
|
|
16
|
-
enumerable: true,
|
|
17
|
-
configurable: true,
|
|
18
|
-
writable: true,
|
|
19
|
-
value: 'Ban Pattern'
|
|
20
|
-
});
|
|
21
|
-
Object.defineProperty(this, "pattern", {
|
|
22
|
-
enumerable: true,
|
|
23
|
-
configurable: true,
|
|
24
|
-
writable: true,
|
|
25
|
-
value: void 0
|
|
26
|
-
});
|
|
27
|
-
Object.defineProperty(this, "cache", {
|
|
28
|
-
enumerable: true,
|
|
29
|
-
configurable: true,
|
|
30
|
-
writable: true,
|
|
31
|
-
value: void 0
|
|
32
|
-
});
|
|
33
33
|
this.pattern = sanitizePatternGrid(pattern);
|
|
34
34
|
this.cache = getShapeVariants(tilesToShape(this.pattern.tiles));
|
|
35
35
|
}
|
|
@@ -122,35 +122,4 @@ class BanPatternRule extends Rule {
|
|
|
122
122
|
return this.copyWith({ pattern });
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
|
-
Object.defineProperty(BanPatternRule, "EXAMPLE_GRID", {
|
|
126
|
-
enumerable: true,
|
|
127
|
-
configurable: true,
|
|
128
|
-
writable: true,
|
|
129
|
-
value: Object.freeze(GridData.create(['nnnnn', 'nnnnn', 'wwwwn', 'nnnnn', 'nnnnn']))
|
|
130
|
-
});
|
|
131
|
-
Object.defineProperty(BanPatternRule, "CONFIGS", {
|
|
132
|
-
enumerable: true,
|
|
133
|
-
configurable: true,
|
|
134
|
-
writable: true,
|
|
135
|
-
value: Object.freeze([
|
|
136
|
-
{
|
|
137
|
-
type: ConfigType.Shape,
|
|
138
|
-
default: BanPatternRule.EXAMPLE_GRID,
|
|
139
|
-
resizable: true,
|
|
140
|
-
field: 'pattern',
|
|
141
|
-
description: 'Pattern',
|
|
142
|
-
explanation: 'The pattern to be banned. Can be a mix of dark and light tiles.',
|
|
143
|
-
configurable: true,
|
|
144
|
-
},
|
|
145
|
-
])
|
|
146
|
-
});
|
|
147
|
-
Object.defineProperty(BanPatternRule, "SEARCH_VARIANTS", {
|
|
148
|
-
enumerable: true,
|
|
149
|
-
configurable: true,
|
|
150
|
-
writable: true,
|
|
151
|
-
value: [
|
|
152
|
-
new BanPatternRule(BanPatternRule.EXAMPLE_GRID).searchVariant(),
|
|
153
|
-
]
|
|
154
|
-
});
|
|
155
|
-
export default BanPatternRule;
|
|
156
125
|
export const instance = new BanPatternRule(GridData.create([]));
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Color } from '../primitives.js';
|
|
2
2
|
import Rule from './rule.js';
|
|
3
3
|
export default class CellCountPerZoneRule extends Rule {
|
|
4
|
+
color;
|
|
4
5
|
get configExplanation() {
|
|
5
6
|
return 'Use the zone tool to define areas on the grid.';
|
|
6
7
|
}
|
|
@@ -9,12 +10,7 @@ export default class CellCountPerZoneRule extends Rule {
|
|
|
9
10
|
*/
|
|
10
11
|
constructor(color) {
|
|
11
12
|
super();
|
|
12
|
-
|
|
13
|
-
enumerable: true,
|
|
14
|
-
configurable: true,
|
|
15
|
-
writable: true,
|
|
16
|
-
value: color
|
|
17
|
-
});
|
|
13
|
+
this.color = color;
|
|
18
14
|
this.color = color;
|
|
19
15
|
}
|
|
20
16
|
getZoneCounts(grid) {
|