@logic-pad/core 0.1.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/LICENSE +661 -0
- package/README.md +19 -0
- package/assets/logic-core.global.d.ts +5865 -0
- package/assets/z3-built.js +14723 -0
- package/assets/z3-built.wasm +0 -0
- package/assets/z3-built.worker.js +206 -0
- package/dist/data/config.d.ts +101 -0
- package/dist/data/config.js +55 -0
- package/dist/data/configurable.d.ts +12 -0
- package/dist/data/configurable.js +26 -0
- package/dist/data/dataHelper.d.ts +77 -0
- package/dist/data/dataHelper.js +190 -0
- package/dist/data/events/eventHelper.d.ts +1 -0
- package/dist/data/events/eventHelper.js +6 -0
- package/dist/data/events/onFinalValidation.d.ts +14 -0
- package/dist/data/events/onFinalValidation.js +4 -0
- package/dist/data/events/onGridChange.d.ts +6 -0
- package/dist/data/events/onGridChange.js +4 -0
- package/dist/data/events/onGridResize.d.ts +9 -0
- package/dist/data/events/onGridResize.js +4 -0
- package/dist/data/events/onSetGrid.d.ts +6 -0
- package/dist/data/events/onSetGrid.js +4 -0
- package/dist/data/events/onSymbolValidation.d.ts +18 -0
- package/dist/data/events/onSymbolValidation.js +4 -0
- package/dist/data/grid.d.ts +362 -0
- package/dist/data/grid.js +886 -0
- package/dist/data/gridConnections.d.ts +38 -0
- package/dist/data/gridConnections.js +328 -0
- package/dist/data/instruction.d.ts +19 -0
- package/dist/data/instruction.js +23 -0
- package/dist/data/primitives.d.ts +85 -0
- package/dist/data/primitives.js +90 -0
- package/dist/data/puzzle.d.ts +86 -0
- package/dist/data/puzzle.js +22 -0
- package/dist/data/rules/banPatternRule.d.ts +29 -0
- package/dist/data/rules/banPatternRule.js +133 -0
- package/dist/data/rules/cellCountRule.d.ts +32 -0
- package/dist/data/rules/cellCountRule.js +166 -0
- package/dist/data/rules/completePatternRule.d.ts +22 -0
- package/dist/data/rules/completePatternRule.js +53 -0
- package/dist/data/rules/connectAllRule.d.ts +28 -0
- package/dist/data/rules/connectAllRule.js +113 -0
- package/dist/data/rules/customRule.d.ts +32 -0
- package/dist/data/rules/customRule.js +92 -0
- package/dist/data/rules/foresightRule.d.ts +30 -0
- package/dist/data/rules/foresightRule.js +107 -0
- package/dist/data/rules/index.d.ts +3 -0
- package/dist/data/rules/index.js +10 -0
- package/dist/data/rules/musicControlLine.d.ts +64 -0
- package/dist/data/rules/musicControlLine.js +178 -0
- package/dist/data/rules/musicGridRule.d.ts +46 -0
- package/dist/data/rules/musicGridRule.js +211 -0
- package/dist/data/rules/mysteryRule.d.ts +37 -0
- package/dist/data/rules/mysteryRule.js +164 -0
- package/dist/data/rules/offByXRule.d.ts +30 -0
- package/dist/data/rules/offByXRule.js +134 -0
- package/dist/data/rules/regionAreaRule.d.ts +33 -0
- package/dist/data/rules/regionAreaRule.js +182 -0
- package/dist/data/rules/regionShapeRule.d.ts +22 -0
- package/dist/data/rules/regionShapeRule.js +58 -0
- package/dist/data/rules/rule.d.ts +18 -0
- package/dist/data/rules/rule.js +19 -0
- package/dist/data/rules/rules.gen.d.ts +14 -0
- package/dist/data/rules/rules.gen.js +18 -0
- package/dist/data/rules/sameShapeRule.d.ts +27 -0
- package/dist/data/rules/sameShapeRule.js +88 -0
- package/dist/data/rules/symbolsPerRegionRule.d.ts +37 -0
- package/dist/data/rules/symbolsPerRegionRule.js +211 -0
- package/dist/data/rules/undercluedRule.d.ts +22 -0
- package/dist/data/rules/undercluedRule.js +60 -0
- package/dist/data/rules/uniqueShapeRule.d.ts +27 -0
- package/dist/data/rules/uniqueShapeRule.js +85 -0
- package/dist/data/serializer/allSerializers.d.ts +30 -0
- package/dist/data/serializer/allSerializers.js +64 -0
- package/dist/data/serializer/compressor/allCompressors.d.ts +14 -0
- package/dist/data/serializer/compressor/allCompressors.js +43 -0
- package/dist/data/serializer/compressor/compressorBase.d.ts +16 -0
- package/dist/data/serializer/compressor/compressorBase.js +2 -0
- package/dist/data/serializer/compressor/deflateCompressor.d.ts +7 -0
- package/dist/data/serializer/compressor/deflateCompressor.js +17 -0
- package/dist/data/serializer/compressor/gzipCompressor.d.ts +5 -0
- package/dist/data/serializer/compressor/gzipCompressor.js +9 -0
- package/dist/data/serializer/compressor/streamCompressor.d.ts +6 -0
- package/dist/data/serializer/compressor/streamCompressor.js +36 -0
- package/dist/data/serializer/serializerBase.d.ts +27 -0
- package/dist/data/serializer/serializerBase.js +2 -0
- package/dist/data/serializer/serializer_v0.d.ts +36 -0
- package/dist/data/serializer/serializer_v0.js +426 -0
- package/dist/data/shapes.d.ts +17 -0
- package/dist/data/shapes.js +117 -0
- package/dist/data/solver/allSolvers.d.ts +3 -0
- package/dist/data/solver/allSolvers.js +11 -0
- package/dist/data/solver/backtrack/backtrackSolver.d.ts +9 -0
- package/dist/data/solver/backtrack/backtrackSolver.js +92 -0
- package/dist/data/solver/backtrack/backtrackWorker.d.ts +2 -0
- package/dist/data/solver/backtrack/backtrackWorker.js +295 -0
- package/dist/data/solver/backtrack/data.d.ts +46 -0
- package/dist/data/solver/backtrack/data.js +140 -0
- package/dist/data/solver/backtrack/rules/banPattern.d.ts +9 -0
- package/dist/data/solver/backtrack/rules/banPattern.js +66 -0
- package/dist/data/solver/backtrack/rules/cellCount.d.ts +7 -0
- package/dist/data/solver/backtrack/rules/cellCount.js +30 -0
- package/dist/data/solver/backtrack/rules/connectAll.d.ts +7 -0
- package/dist/data/solver/backtrack/rules/connectAll.js +49 -0
- package/dist/data/solver/backtrack/rules/regionArea.d.ts +8 -0
- package/dist/data/solver/backtrack/rules/regionArea.js +76 -0
- package/dist/data/solver/backtrack/rules/regionShape.d.ts +8 -0
- package/dist/data/solver/backtrack/rules/regionShape.js +62 -0
- package/dist/data/solver/backtrack/rules/sameShape.d.ts +8 -0
- package/dist/data/solver/backtrack/rules/sameShape.js +19 -0
- package/dist/data/solver/backtrack/rules/symbolsPerRegion.d.ts +10 -0
- package/dist/data/solver/backtrack/rules/symbolsPerRegion.js +92 -0
- package/dist/data/solver/backtrack/rules/uniqueShape.d.ts +8 -0
- package/dist/data/solver/backtrack/rules/uniqueShape.js +19 -0
- package/dist/data/solver/backtrack/symbols/areaNumber.d.ts +9 -0
- package/dist/data/solver/backtrack/symbols/areaNumber.js +77 -0
- package/dist/data/solver/backtrack/symbols/dart.d.ts +9 -0
- package/dist/data/solver/backtrack/symbols/dart.js +58 -0
- package/dist/data/solver/backtrack/symbols/directionLinker.d.ts +9 -0
- package/dist/data/solver/backtrack/symbols/directionLinker.js +50 -0
- package/dist/data/solver/backtrack/symbols/galaxy.d.ts +9 -0
- package/dist/data/solver/backtrack/symbols/galaxy.js +19 -0
- package/dist/data/solver/backtrack/symbols/letter.d.ts +9 -0
- package/dist/data/solver/backtrack/symbols/letter.js +100 -0
- package/dist/data/solver/backtrack/symbols/lotus.d.ts +9 -0
- package/dist/data/solver/backtrack/symbols/lotus.js +36 -0
- package/dist/data/solver/backtrack/symbols/minesweeper.d.ts +9 -0
- package/dist/data/solver/backtrack/symbols/minesweeper.js +55 -0
- package/dist/data/solver/backtrack/symbols/myopia.d.ts +7 -0
- package/dist/data/solver/backtrack/symbols/myopia.js +79 -0
- package/dist/data/solver/backtrack/symbols/viewpoint.d.ts +7 -0
- package/dist/data/solver/backtrack/symbols/viewpoint.js +56 -0
- package/dist/data/solver/solver.d.ts +61 -0
- package/dist/data/solver/solver.js +55 -0
- package/dist/data/solver/underclued/undercluedSolver.d.ts +8 -0
- package/dist/data/solver/underclued/undercluedSolver.js +55 -0
- package/dist/data/solver/underclued/undercluedWorker.d.ts +2 -0
- package/dist/data/solver/underclued/undercluedWorker.js +131 -0
- package/dist/data/solver/z3/modules/areaNumberModule.d.ts +9 -0
- package/dist/data/solver/z3/modules/areaNumberModule.js +35 -0
- package/dist/data/solver/z3/modules/cellCountModule.d.ts +9 -0
- package/dist/data/solver/z3/modules/cellCountModule.js +59 -0
- package/dist/data/solver/z3/modules/connectAllModule.d.ts +9 -0
- package/dist/data/solver/z3/modules/connectAllModule.js +32 -0
- package/dist/data/solver/z3/modules/dartModule.d.ts +9 -0
- package/dist/data/solver/z3/modules/dartModule.js +69 -0
- package/dist/data/solver/z3/modules/index.d.ts +3 -0
- package/dist/data/solver/z3/modules/index.js +10 -0
- package/dist/data/solver/z3/modules/letterModule.d.ts +9 -0
- package/dist/data/solver/z3/modules/letterModule.js +41 -0
- package/dist/data/solver/z3/modules/modules.gen.d.ts +8 -0
- package/dist/data/solver/z3/modules/modules.gen.js +12 -0
- package/dist/data/solver/z3/modules/myopiaModule.d.ts +9 -0
- package/dist/data/solver/z3/modules/myopiaModule.js +64 -0
- package/dist/data/solver/z3/modules/regionAreaModule.d.ts +9 -0
- package/dist/data/solver/z3/modules/regionAreaModule.js +48 -0
- package/dist/data/solver/z3/modules/viewpointModule.d.ts +9 -0
- package/dist/data/solver/z3/modules/viewpointModule.js +37 -0
- package/dist/data/solver/z3/modules/z3Module.d.ts +7 -0
- package/dist/data/solver/z3/modules/z3Module.js +3 -0
- package/dist/data/solver/z3/utils.d.ts +2 -0
- package/dist/data/solver/z3/utils.js +26 -0
- package/dist/data/solver/z3/z3Solver.d.ts +10 -0
- package/dist/data/solver/z3/z3Solver.js +134 -0
- package/dist/data/solver/z3/z3SolverContext.d.ts +808 -0
- package/dist/data/solver/z3/z3SolverContext.js +49 -0
- package/dist/data/symbols/areaNumberSymbol.d.ts +30 -0
- package/dist/data/symbols/areaNumberSymbol.js +88 -0
- package/dist/data/symbols/customIconSymbol.d.ts +35 -0
- package/dist/data/symbols/customIconSymbol.js +105 -0
- package/dist/data/symbols/customSymbol.d.ts +23 -0
- package/dist/data/symbols/customSymbol.js +48 -0
- package/dist/data/symbols/customTextSymbol.d.ts +33 -0
- package/dist/data/symbols/customTextSymbol.js +106 -0
- package/dist/data/symbols/dartSymbol.d.ts +35 -0
- package/dist/data/symbols/dartSymbol.js +110 -0
- package/dist/data/symbols/directionLinkerSymbol.d.ts +36 -0
- package/dist/data/symbols/directionLinkerSymbol.js +259 -0
- package/dist/data/symbols/galaxySymbol.d.ts +26 -0
- package/dist/data/symbols/galaxySymbol.js +74 -0
- package/dist/data/symbols/index.d.ts +3 -0
- package/dist/data/symbols/index.js +10 -0
- package/dist/data/symbols/letterSymbol.d.ts +31 -0
- package/dist/data/symbols/letterSymbol.js +137 -0
- package/dist/data/symbols/lotusSymbol.d.ts +29 -0
- package/dist/data/symbols/lotusSymbol.js +132 -0
- package/dist/data/symbols/minesweeperSymbol.d.ts +31 -0
- package/dist/data/symbols/minesweeperSymbol.js +100 -0
- package/dist/data/symbols/multiEntrySymbol.d.ts +11 -0
- package/dist/data/symbols/multiEntrySymbol.js +14 -0
- package/dist/data/symbols/myopiaSymbol.d.ts +34 -0
- package/dist/data/symbols/myopiaSymbol.js +187 -0
- package/dist/data/symbols/numberSymbol.d.ts +19 -0
- package/dist/data/symbols/numberSymbol.js +41 -0
- package/dist/data/symbols/symbol.d.ts +16 -0
- package/dist/data/symbols/symbol.js +51 -0
- package/dist/data/symbols/symbols.gen.d.ts +10 -0
- package/dist/data/symbols/symbols.gen.js +14 -0
- package/dist/data/symbols/viewpointSymbol.d.ts +31 -0
- package/dist/data/symbols/viewpointSymbol.js +106 -0
- package/dist/data/tile.d.ts +26 -0
- package/dist/data/tile.js +68 -0
- package/dist/data/tileConnections.d.ts +25 -0
- package/dist/data/tileConnections.js +74 -0
- package/dist/data/validate.d.ts +5 -0
- package/dist/data/validate.js +131 -0
- package/dist/index.d.ts +96 -0
- package/dist/index.js +100 -0
- package/dist/polyfill/streamPolyfill.d.ts +2 -0
- package/dist/polyfill/streamPolyfill.js +1 -0
- package/package.json +75 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { AnyConfig } from '../config';
|
|
2
|
+
import GridData from '../grid';
|
|
3
|
+
import { RuleState } from '../primitives';
|
|
4
|
+
import { Shape } from '../shapes';
|
|
5
|
+
import Rule, { SearchVariant } from './rule';
|
|
6
|
+
export default class BanPatternRule extends Rule {
|
|
7
|
+
private static readonly EXAMPLE_GRID;
|
|
8
|
+
private static readonly CONFIGS;
|
|
9
|
+
private static readonly SEARCH_VARIANTS;
|
|
10
|
+
readonly pattern: GridData;
|
|
11
|
+
readonly cache: Shape[];
|
|
12
|
+
/**
|
|
13
|
+
* **Don't make this pattern**
|
|
14
|
+
*
|
|
15
|
+
* @param pattern - GridData representing the banned pattern. Only non-gray tiles are considered.
|
|
16
|
+
*/
|
|
17
|
+
constructor(pattern: GridData);
|
|
18
|
+
get id(): string;
|
|
19
|
+
get explanation(): string;
|
|
20
|
+
get configs(): readonly AnyConfig[] | null;
|
|
21
|
+
createExampleGrid(): GridData;
|
|
22
|
+
get searchVariants(): SearchVariant[];
|
|
23
|
+
validateGrid(grid: GridData): RuleState;
|
|
24
|
+
copyWith({ pattern }: {
|
|
25
|
+
pattern?: GridData;
|
|
26
|
+
}): this;
|
|
27
|
+
withPattern(pattern: GridData): this;
|
|
28
|
+
}
|
|
29
|
+
export declare const instance: BanPatternRule;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { ConfigType } from '../config';
|
|
2
|
+
import GridData from '../grid';
|
|
3
|
+
import { array } from '../dataHelper';
|
|
4
|
+
import { Color, State } from '../primitives';
|
|
5
|
+
import { getShapeVariants, tilesToShape } from '../shapes';
|
|
6
|
+
import Rule from './rule';
|
|
7
|
+
class BanPatternRule extends Rule {
|
|
8
|
+
/**
|
|
9
|
+
* **Don't make this pattern**
|
|
10
|
+
*
|
|
11
|
+
* @param pattern - GridData representing the banned pattern. Only non-gray tiles are considered.
|
|
12
|
+
*/
|
|
13
|
+
constructor(pattern) {
|
|
14
|
+
super();
|
|
15
|
+
Object.defineProperty(this, "pattern", {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
configurable: true,
|
|
18
|
+
writable: true,
|
|
19
|
+
value: void 0
|
|
20
|
+
});
|
|
21
|
+
Object.defineProperty(this, "cache", {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
configurable: true,
|
|
24
|
+
writable: true,
|
|
25
|
+
value: void 0
|
|
26
|
+
});
|
|
27
|
+
this.pattern = pattern
|
|
28
|
+
// unlock all tiles
|
|
29
|
+
.withTiles(tiles => tiles.map(row => row.map(t => t.withFixed(false))))
|
|
30
|
+
// strip all symbols and rules
|
|
31
|
+
.withRules([])
|
|
32
|
+
.withSymbols(new Map());
|
|
33
|
+
this.cache = getShapeVariants(tilesToShape(this.pattern.tiles));
|
|
34
|
+
}
|
|
35
|
+
get id() {
|
|
36
|
+
return `ban_pattern`;
|
|
37
|
+
}
|
|
38
|
+
get explanation() {
|
|
39
|
+
return `Don't make this pattern`;
|
|
40
|
+
}
|
|
41
|
+
get configs() {
|
|
42
|
+
return BanPatternRule.CONFIGS;
|
|
43
|
+
}
|
|
44
|
+
createExampleGrid() {
|
|
45
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
46
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
47
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
48
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
49
|
+
this.pattern.forEach((tile, x, y) => {
|
|
50
|
+
if (tile.color !== Color.Gray && tile.exists) {
|
|
51
|
+
minX = Math.min(minX, x);
|
|
52
|
+
minY = Math.min(minY, y);
|
|
53
|
+
maxX = Math.max(maxX, x);
|
|
54
|
+
maxY = Math.max(maxY, y);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
const width = maxX - minX + 1;
|
|
58
|
+
const height = maxY - minY + 1;
|
|
59
|
+
const tiles = array(width, height, (x, y) => {
|
|
60
|
+
const tile = this.pattern.getTile(x + minX, y + minY);
|
|
61
|
+
if (!tile.exists || tile.color !== Color.Gray)
|
|
62
|
+
return tile;
|
|
63
|
+
return tile.withExists(false);
|
|
64
|
+
});
|
|
65
|
+
return new GridData(width, height, tiles);
|
|
66
|
+
}
|
|
67
|
+
get searchVariants() {
|
|
68
|
+
return BanPatternRule.SEARCH_VARIANTS;
|
|
69
|
+
}
|
|
70
|
+
validateGrid(grid) {
|
|
71
|
+
for (const pattern of this.cache) {
|
|
72
|
+
for (let y = 0; y <= grid.height - pattern.height; y++) {
|
|
73
|
+
for (let x = 0; x <= grid.width - pattern.width; x++) {
|
|
74
|
+
let match = true;
|
|
75
|
+
for (const tile of pattern.elements) {
|
|
76
|
+
const t = grid.getTile(x + tile.x, y + tile.y);
|
|
77
|
+
if (!t.exists || t.color !== tile.color) {
|
|
78
|
+
match = false;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (match) {
|
|
83
|
+
return {
|
|
84
|
+
state: State.Error,
|
|
85
|
+
positions: pattern.elements.map(tile => ({
|
|
86
|
+
x: x + tile.x,
|
|
87
|
+
y: y + tile.y,
|
|
88
|
+
})),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return { state: grid.isComplete() ? State.Satisfied : State.Incomplete };
|
|
95
|
+
}
|
|
96
|
+
copyWith({ pattern }) {
|
|
97
|
+
return new BanPatternRule(pattern ?? this.pattern);
|
|
98
|
+
}
|
|
99
|
+
withPattern(pattern) {
|
|
100
|
+
return this.copyWith({ pattern });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
Object.defineProperty(BanPatternRule, "EXAMPLE_GRID", {
|
|
104
|
+
enumerable: true,
|
|
105
|
+
configurable: true,
|
|
106
|
+
writable: true,
|
|
107
|
+
value: Object.freeze(GridData.create(['nnnnn', 'nnnnn', 'wwwwn', 'nnnnn', 'nnnnn']))
|
|
108
|
+
});
|
|
109
|
+
Object.defineProperty(BanPatternRule, "CONFIGS", {
|
|
110
|
+
enumerable: true,
|
|
111
|
+
configurable: true,
|
|
112
|
+
writable: true,
|
|
113
|
+
value: Object.freeze([
|
|
114
|
+
{
|
|
115
|
+
type: ConfigType.Tile,
|
|
116
|
+
default: BanPatternRule.EXAMPLE_GRID,
|
|
117
|
+
resizable: true,
|
|
118
|
+
field: 'pattern',
|
|
119
|
+
description: 'Pattern',
|
|
120
|
+
configurable: true,
|
|
121
|
+
},
|
|
122
|
+
])
|
|
123
|
+
});
|
|
124
|
+
Object.defineProperty(BanPatternRule, "SEARCH_VARIANTS", {
|
|
125
|
+
enumerable: true,
|
|
126
|
+
configurable: true,
|
|
127
|
+
writable: true,
|
|
128
|
+
value: [
|
|
129
|
+
new BanPatternRule(BanPatternRule.EXAMPLE_GRID).searchVariant(),
|
|
130
|
+
]
|
|
131
|
+
});
|
|
132
|
+
export default BanPatternRule;
|
|
133
|
+
export const instance = new BanPatternRule(GridData.create([]));
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AnyConfig } from '../config';
|
|
2
|
+
import GridData from '../grid';
|
|
3
|
+
import { Color, RuleState } from '../primitives';
|
|
4
|
+
import Rule, { SearchVariant } from './rule';
|
|
5
|
+
export default class CellCountRule extends Rule {
|
|
6
|
+
readonly color: Color;
|
|
7
|
+
readonly count: number;
|
|
8
|
+
private static readonly CONFIGS;
|
|
9
|
+
private static readonly EXAMPLE_GRID_LIGHT;
|
|
10
|
+
private static readonly EXAMPLE_GRID_DARK;
|
|
11
|
+
private static readonly SEARCH_VARIANTS;
|
|
12
|
+
/**
|
|
13
|
+
* **There are <count> <color> cells in total**
|
|
14
|
+
*
|
|
15
|
+
* @param color - The color of the cells to count.
|
|
16
|
+
* @param count - The total number of cells of the given color.
|
|
17
|
+
*/
|
|
18
|
+
constructor(color: Color, count: number);
|
|
19
|
+
get id(): string;
|
|
20
|
+
get explanation(): string;
|
|
21
|
+
get configs(): readonly AnyConfig[] | null;
|
|
22
|
+
createExampleGrid(): GridData;
|
|
23
|
+
get searchVariants(): SearchVariant[];
|
|
24
|
+
validateGrid(grid: GridData): RuleState;
|
|
25
|
+
copyWith({ color, count }: {
|
|
26
|
+
color?: Color;
|
|
27
|
+
count?: number;
|
|
28
|
+
}): this;
|
|
29
|
+
withColor(color: Color): this;
|
|
30
|
+
withCount(count: number): this;
|
|
31
|
+
}
|
|
32
|
+
export declare const instance: CellCountRule;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { ConfigType } from '../config';
|
|
2
|
+
import GridData from '../grid';
|
|
3
|
+
import { Color, State } from '../primitives';
|
|
4
|
+
import AreaNumberSymbol from '../symbols/areaNumberSymbol';
|
|
5
|
+
import Rule from './rule';
|
|
6
|
+
class CellCountRule extends Rule {
|
|
7
|
+
/**
|
|
8
|
+
* **There are <count> <color> cells in total**
|
|
9
|
+
*
|
|
10
|
+
* @param color - The color of the cells to count.
|
|
11
|
+
* @param count - The total number of cells of the given color.
|
|
12
|
+
*/
|
|
13
|
+
constructor(color, count) {
|
|
14
|
+
super();
|
|
15
|
+
Object.defineProperty(this, "color", {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
configurable: true,
|
|
18
|
+
writable: true,
|
|
19
|
+
value: color
|
|
20
|
+
});
|
|
21
|
+
Object.defineProperty(this, "count", {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
configurable: true,
|
|
24
|
+
writable: true,
|
|
25
|
+
value: count
|
|
26
|
+
});
|
|
27
|
+
this.color = color;
|
|
28
|
+
this.count = count;
|
|
29
|
+
}
|
|
30
|
+
get id() {
|
|
31
|
+
return `cell_count`;
|
|
32
|
+
}
|
|
33
|
+
get explanation() {
|
|
34
|
+
return `There ${this.count === 1 ? 'is' : 'are'} ${this.count} ${this.color} cell${this.count === 1 ? '' : 's'} *in total*`;
|
|
35
|
+
}
|
|
36
|
+
get configs() {
|
|
37
|
+
return CellCountRule.CONFIGS;
|
|
38
|
+
}
|
|
39
|
+
createExampleGrid() {
|
|
40
|
+
if (this.count < CellCountRule.EXAMPLE_GRID_LIGHT.length) {
|
|
41
|
+
if (this.color === Color.Light) {
|
|
42
|
+
return CellCountRule.EXAMPLE_GRID_LIGHT[this.count];
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
return CellCountRule.EXAMPLE_GRID_DARK[this.count];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const grid = this.color === Color.Light
|
|
50
|
+
? GridData.create(['wbbbb', 'wwbbb', 'wwwbb', 'wwwwb'])
|
|
51
|
+
: GridData.create(['bwwww', 'bbwww', 'bbbww', 'bbbbw']);
|
|
52
|
+
return grid.addSymbol(new AreaNumberSymbol(1, 2, this.count));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
get searchVariants() {
|
|
56
|
+
return CellCountRule.SEARCH_VARIANTS;
|
|
57
|
+
}
|
|
58
|
+
validateGrid(grid) {
|
|
59
|
+
let colored = 0;
|
|
60
|
+
let possible = 0;
|
|
61
|
+
grid.forEach(tile => {
|
|
62
|
+
if (!tile.exists)
|
|
63
|
+
return;
|
|
64
|
+
if (tile.color === this.color)
|
|
65
|
+
colored++;
|
|
66
|
+
if (tile.color === Color.Gray)
|
|
67
|
+
possible++;
|
|
68
|
+
});
|
|
69
|
+
if (colored > this.count || colored + possible < this.count) {
|
|
70
|
+
return { state: State.Error, positions: [] };
|
|
71
|
+
}
|
|
72
|
+
else if (colored === this.count && possible === 0) {
|
|
73
|
+
return { state: State.Satisfied };
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
return { state: State.Incomplete };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
copyWith({ color, count }) {
|
|
80
|
+
return new CellCountRule(color ?? this.color, count ?? this.count);
|
|
81
|
+
}
|
|
82
|
+
withColor(color) {
|
|
83
|
+
return this.copyWith({ color });
|
|
84
|
+
}
|
|
85
|
+
withCount(count) {
|
|
86
|
+
return this.copyWith({ count });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
Object.defineProperty(CellCountRule, "CONFIGS", {
|
|
90
|
+
enumerable: true,
|
|
91
|
+
configurable: true,
|
|
92
|
+
writable: true,
|
|
93
|
+
value: Object.freeze([
|
|
94
|
+
{
|
|
95
|
+
type: ConfigType.Color,
|
|
96
|
+
default: Color.Light,
|
|
97
|
+
allowGray: false,
|
|
98
|
+
field: 'color',
|
|
99
|
+
description: 'Color',
|
|
100
|
+
configurable: true,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
type: ConfigType.Number,
|
|
104
|
+
default: 10,
|
|
105
|
+
min: 0,
|
|
106
|
+
field: 'count',
|
|
107
|
+
description: 'Count',
|
|
108
|
+
configurable: true,
|
|
109
|
+
},
|
|
110
|
+
])
|
|
111
|
+
});
|
|
112
|
+
Object.defineProperty(CellCountRule, "EXAMPLE_GRID_LIGHT", {
|
|
113
|
+
enumerable: true,
|
|
114
|
+
configurable: true,
|
|
115
|
+
writable: true,
|
|
116
|
+
value: Object.freeze([
|
|
117
|
+
GridData.create(['bbbbb', 'bbbbb', 'bbbbb', 'bbbbb']),
|
|
118
|
+
GridData.create(['bbbbb', 'bbbbb', 'bwbbb', 'bbbbb']).withSymbols([
|
|
119
|
+
new AreaNumberSymbol(1, 2, 1),
|
|
120
|
+
]),
|
|
121
|
+
GridData.create(['bbbbb', 'bbbbb', 'bwwbb', 'bbbbb']).withSymbols([
|
|
122
|
+
new AreaNumberSymbol(1, 2, 2),
|
|
123
|
+
]),
|
|
124
|
+
GridData.create(['bbbbb', 'bwbbb', 'bwwbb', 'bbbbb']).withSymbols([
|
|
125
|
+
new AreaNumberSymbol(1, 2, 3),
|
|
126
|
+
]),
|
|
127
|
+
GridData.create(['bbbbb', 'bwwbb', 'bwwbb', 'bbbbb']).withSymbols([
|
|
128
|
+
new AreaNumberSymbol(1, 2, 4),
|
|
129
|
+
]),
|
|
130
|
+
GridData.create(['bbbbb', 'bwwbb', 'bwwwb', 'bbbbb']).withSymbols([
|
|
131
|
+
new AreaNumberSymbol(1, 2, 5),
|
|
132
|
+
]),
|
|
133
|
+
GridData.create(['bbbbb', 'bwwwb', 'bwwwb', 'bbbbb']).withSymbols([
|
|
134
|
+
new AreaNumberSymbol(1, 2, 6),
|
|
135
|
+
]),
|
|
136
|
+
GridData.create(['bbbbb', 'bbbbb', 'wwwbb', 'wwwwb']).withSymbols([
|
|
137
|
+
new AreaNumberSymbol(1, 2, 7),
|
|
138
|
+
]),
|
|
139
|
+
GridData.create(['bbbbb', 'wbbbb', 'wwwbb', 'wwwwb']).withSymbols([
|
|
140
|
+
new AreaNumberSymbol(1, 2, 8),
|
|
141
|
+
]),
|
|
142
|
+
GridData.create(['bbbbb', 'wwbbb', 'wwwbb', 'wwwwb']).withSymbols([
|
|
143
|
+
new AreaNumberSymbol(1, 2, 9),
|
|
144
|
+
]),
|
|
145
|
+
GridData.create(['wbbbb', 'wwbbb', 'wwwbb', 'wwwwb']).withSymbols([
|
|
146
|
+
new AreaNumberSymbol(1, 2, 10),
|
|
147
|
+
]),
|
|
148
|
+
])
|
|
149
|
+
});
|
|
150
|
+
Object.defineProperty(CellCountRule, "EXAMPLE_GRID_DARK", {
|
|
151
|
+
enumerable: true,
|
|
152
|
+
configurable: true,
|
|
153
|
+
writable: true,
|
|
154
|
+
value: Object.freeze(CellCountRule.EXAMPLE_GRID_LIGHT.map(grid => grid.withTiles(tiles => tiles.map(row => row.map(tile => tile.withColor(tile.color === Color.Dark ? Color.Light : Color.Dark))))))
|
|
155
|
+
});
|
|
156
|
+
Object.defineProperty(CellCountRule, "SEARCH_VARIANTS", {
|
|
157
|
+
enumerable: true,
|
|
158
|
+
configurable: true,
|
|
159
|
+
writable: true,
|
|
160
|
+
value: [
|
|
161
|
+
new CellCountRule(Color.Light, 10).searchVariant(),
|
|
162
|
+
new CellCountRule(Color.Dark, 10).searchVariant(),
|
|
163
|
+
]
|
|
164
|
+
});
|
|
165
|
+
export default CellCountRule;
|
|
166
|
+
export const instance = new CellCountRule(Color.Dark, 10);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import GridData from '../grid';
|
|
2
|
+
import { RuleState } from '../primitives';
|
|
3
|
+
import Rule, { SearchVariant } from './rule';
|
|
4
|
+
export default class CompletePatternRule extends Rule {
|
|
5
|
+
private static readonly EXAMPLE_GRID;
|
|
6
|
+
private static readonly SEARCH_VARIANTS;
|
|
7
|
+
/**
|
|
8
|
+
* **Complete the pattern**
|
|
9
|
+
*
|
|
10
|
+
* This rule validates answers based on the provided solution.
|
|
11
|
+
*/
|
|
12
|
+
constructor();
|
|
13
|
+
get id(): string;
|
|
14
|
+
get explanation(): string;
|
|
15
|
+
createExampleGrid(): GridData;
|
|
16
|
+
get searchVariants(): SearchVariant[];
|
|
17
|
+
validateGrid(_grid: GridData): RuleState;
|
|
18
|
+
copyWith(_: object): this;
|
|
19
|
+
get validateWithSolution(): boolean;
|
|
20
|
+
get isSingleton(): boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare const instance: CompletePatternRule;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import GridData from '../grid';
|
|
2
|
+
import { State } from '../primitives';
|
|
3
|
+
import Rule from './rule';
|
|
4
|
+
class CompletePatternRule extends Rule {
|
|
5
|
+
/**
|
|
6
|
+
* **Complete the pattern**
|
|
7
|
+
*
|
|
8
|
+
* This rule validates answers based on the provided solution.
|
|
9
|
+
*/
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
}
|
|
13
|
+
get id() {
|
|
14
|
+
return `complete_pattern`;
|
|
15
|
+
}
|
|
16
|
+
get explanation() {
|
|
17
|
+
return `Complete the pattern`;
|
|
18
|
+
}
|
|
19
|
+
createExampleGrid() {
|
|
20
|
+
return CompletePatternRule.EXAMPLE_GRID;
|
|
21
|
+
}
|
|
22
|
+
get searchVariants() {
|
|
23
|
+
return CompletePatternRule.SEARCH_VARIANTS;
|
|
24
|
+
}
|
|
25
|
+
validateGrid(_grid) {
|
|
26
|
+
return { state: State.Incomplete };
|
|
27
|
+
}
|
|
28
|
+
copyWith(_) {
|
|
29
|
+
return new CompletePatternRule();
|
|
30
|
+
}
|
|
31
|
+
get validateWithSolution() {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
get isSingleton() {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
Object.defineProperty(CompletePatternRule, "EXAMPLE_GRID", {
|
|
39
|
+
enumerable: true,
|
|
40
|
+
configurable: true,
|
|
41
|
+
writable: true,
|
|
42
|
+
value: Object.freeze(GridData.create(['wbwbw', 'bwbwb', 'wbwbw', 'bwbwb']))
|
|
43
|
+
});
|
|
44
|
+
Object.defineProperty(CompletePatternRule, "SEARCH_VARIANTS", {
|
|
45
|
+
enumerable: true,
|
|
46
|
+
configurable: true,
|
|
47
|
+
writable: true,
|
|
48
|
+
value: [
|
|
49
|
+
new CompletePatternRule().searchVariant(),
|
|
50
|
+
]
|
|
51
|
+
});
|
|
52
|
+
export default CompletePatternRule;
|
|
53
|
+
export const instance = new CompletePatternRule();
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AnyConfig } from '../config';
|
|
2
|
+
import GridData from '../grid';
|
|
3
|
+
import { Color, RuleState } from '../primitives';
|
|
4
|
+
import Rule, { SearchVariant } from './rule';
|
|
5
|
+
export default class ConnectAllRule extends Rule {
|
|
6
|
+
readonly color: Color;
|
|
7
|
+
private static readonly CONFIGS;
|
|
8
|
+
private static readonly EXAMPLE_GRID_LIGHT;
|
|
9
|
+
private static readonly EXAMPLE_GRID_DARK;
|
|
10
|
+
private static readonly SEARCH_VARIANTS;
|
|
11
|
+
/**
|
|
12
|
+
* **Connect all <color> cells**
|
|
13
|
+
*
|
|
14
|
+
* @param color - The color of the cells to connect.
|
|
15
|
+
*/
|
|
16
|
+
constructor(color: Color);
|
|
17
|
+
get id(): string;
|
|
18
|
+
get explanation(): string;
|
|
19
|
+
get configs(): readonly AnyConfig[] | null;
|
|
20
|
+
createExampleGrid(): GridData;
|
|
21
|
+
get searchVariants(): SearchVariant[];
|
|
22
|
+
validateGrid(grid: GridData): RuleState;
|
|
23
|
+
copyWith({ color }: {
|
|
24
|
+
color?: Color;
|
|
25
|
+
}): this;
|
|
26
|
+
withColor(color: Color): this;
|
|
27
|
+
}
|
|
28
|
+
export declare const instance: ConnectAllRule;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { ConfigType } from '../config';
|
|
2
|
+
import GridData from '../grid';
|
|
3
|
+
import { array, minBy } from '../dataHelper';
|
|
4
|
+
import { Color, State } from '../primitives';
|
|
5
|
+
import Rule from './rule';
|
|
6
|
+
class ConnectAllRule extends Rule {
|
|
7
|
+
/**
|
|
8
|
+
* **Connect all <color> cells**
|
|
9
|
+
*
|
|
10
|
+
* @param color - The color of the cells to connect.
|
|
11
|
+
*/
|
|
12
|
+
constructor(color) {
|
|
13
|
+
super();
|
|
14
|
+
Object.defineProperty(this, "color", {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
configurable: true,
|
|
17
|
+
writable: true,
|
|
18
|
+
value: color
|
|
19
|
+
});
|
|
20
|
+
this.color = color;
|
|
21
|
+
}
|
|
22
|
+
get id() {
|
|
23
|
+
return `connect_all`;
|
|
24
|
+
}
|
|
25
|
+
get explanation() {
|
|
26
|
+
return `Connect all ${this.color} cells`;
|
|
27
|
+
}
|
|
28
|
+
get configs() {
|
|
29
|
+
return ConnectAllRule.CONFIGS;
|
|
30
|
+
}
|
|
31
|
+
createExampleGrid() {
|
|
32
|
+
return this.color === Color.Light
|
|
33
|
+
? ConnectAllRule.EXAMPLE_GRID_LIGHT
|
|
34
|
+
: ConnectAllRule.EXAMPLE_GRID_DARK;
|
|
35
|
+
}
|
|
36
|
+
get searchVariants() {
|
|
37
|
+
return ConnectAllRule.SEARCH_VARIANTS;
|
|
38
|
+
}
|
|
39
|
+
validateGrid(grid) {
|
|
40
|
+
let complete = true;
|
|
41
|
+
const visited = array(grid.width, grid.height, (i, j) => !(grid.getTile(i, j).exists && grid.getTile(i, j).color === this.color));
|
|
42
|
+
const islands = [];
|
|
43
|
+
while (true) {
|
|
44
|
+
const seed = grid.find((_tile, x, y) => !visited[y][x]);
|
|
45
|
+
if (!seed)
|
|
46
|
+
break;
|
|
47
|
+
const positions = [];
|
|
48
|
+
grid.iterateArea(seed, tile => tile.color === this.color || tile.color === Color.Gray, (tile, x, y) => {
|
|
49
|
+
visited[y][x] = true;
|
|
50
|
+
if (tile.color === Color.Gray)
|
|
51
|
+
complete = false;
|
|
52
|
+
positions.push({ x, y });
|
|
53
|
+
});
|
|
54
|
+
islands.push(positions);
|
|
55
|
+
}
|
|
56
|
+
if (islands.length > 1) {
|
|
57
|
+
return {
|
|
58
|
+
state: State.Error,
|
|
59
|
+
positions: minBy(islands, island => island.length),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
else if (islands.length <= 1) {
|
|
63
|
+
return { state: complete ? State.Satisfied : State.Incomplete };
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
return { state: State.Incomplete }; // not reachable but the TS is not happy
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
copyWith({ color }) {
|
|
70
|
+
return new ConnectAllRule(color ?? this.color);
|
|
71
|
+
}
|
|
72
|
+
withColor(color) {
|
|
73
|
+
return this.copyWith({ color });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
Object.defineProperty(ConnectAllRule, "CONFIGS", {
|
|
77
|
+
enumerable: true,
|
|
78
|
+
configurable: true,
|
|
79
|
+
writable: true,
|
|
80
|
+
value: Object.freeze([
|
|
81
|
+
{
|
|
82
|
+
type: ConfigType.Color,
|
|
83
|
+
default: Color.Light,
|
|
84
|
+
allowGray: false,
|
|
85
|
+
field: 'color',
|
|
86
|
+
description: 'Color',
|
|
87
|
+
configurable: true,
|
|
88
|
+
},
|
|
89
|
+
])
|
|
90
|
+
});
|
|
91
|
+
Object.defineProperty(ConnectAllRule, "EXAMPLE_GRID_LIGHT", {
|
|
92
|
+
enumerable: true,
|
|
93
|
+
configurable: true,
|
|
94
|
+
writable: true,
|
|
95
|
+
value: Object.freeze(GridData.create(['bwwwb', 'bwbww', 'wwwbb', 'wbwww']))
|
|
96
|
+
});
|
|
97
|
+
Object.defineProperty(ConnectAllRule, "EXAMPLE_GRID_DARK", {
|
|
98
|
+
enumerable: true,
|
|
99
|
+
configurable: true,
|
|
100
|
+
writable: true,
|
|
101
|
+
value: Object.freeze(GridData.create(['wbbbw', 'wbwbb', 'bbbww', 'bwbbb']))
|
|
102
|
+
});
|
|
103
|
+
Object.defineProperty(ConnectAllRule, "SEARCH_VARIANTS", {
|
|
104
|
+
enumerable: true,
|
|
105
|
+
configurable: true,
|
|
106
|
+
writable: true,
|
|
107
|
+
value: [
|
|
108
|
+
new ConnectAllRule(Color.Light).searchVariant(),
|
|
109
|
+
new ConnectAllRule(Color.Dark).searchVariant(),
|
|
110
|
+
]
|
|
111
|
+
});
|
|
112
|
+
export default ConnectAllRule;
|
|
113
|
+
export const instance = new ConnectAllRule(Color.Dark);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AnyConfig } from '../config';
|
|
2
|
+
import GridData from '../grid';
|
|
3
|
+
import { RuleState } from '../primitives';
|
|
4
|
+
import Rule, { SearchVariant } from './rule';
|
|
5
|
+
export default class CustomRule extends Rule {
|
|
6
|
+
readonly description: string;
|
|
7
|
+
readonly grid: GridData;
|
|
8
|
+
private static readonly EXAMPLE_GRID;
|
|
9
|
+
static readonly configs: readonly AnyConfig[];
|
|
10
|
+
private static readonly SEARCH_VARIANTS;
|
|
11
|
+
/**
|
|
12
|
+
* A custom rule with a description and thumbnail grid.
|
|
13
|
+
*
|
|
14
|
+
* This rule validates answers based on the provided solution.
|
|
15
|
+
*
|
|
16
|
+
* @param description - The description of the rule.
|
|
17
|
+
* @param grid - The thumbnail grid of the rule, preferably 5x4 in size.
|
|
18
|
+
*/
|
|
19
|
+
constructor(description: string, grid: GridData);
|
|
20
|
+
get id(): string;
|
|
21
|
+
get explanation(): string;
|
|
22
|
+
get configs(): readonly AnyConfig[] | null;
|
|
23
|
+
createExampleGrid(): GridData;
|
|
24
|
+
get searchVariants(): SearchVariant[];
|
|
25
|
+
validateGrid(_grid: GridData): RuleState;
|
|
26
|
+
copyWith({ description, grid, }: {
|
|
27
|
+
description?: string;
|
|
28
|
+
grid?: GridData;
|
|
29
|
+
}): this;
|
|
30
|
+
get validateWithSolution(): boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare const instance: CustomRule;
|