UNPKG

@logic-pad/core

Version:
183 lines (182 loc) 6.54 kB
import { ConfigType } from '../config.js'; import GridData from '../grid.js'; import { array } from '../dataHelper.js'; import { Color, State } from '../primitives.js'; import TileData from '../tile.js'; import Rule from './rule.js'; class RegionAreaRule extends Rule { /** * **All &lt;color&gt; regions have area &lt;size&gt;** * * @param color - The color of the regions. * @param size - The area of the regions. */ constructor(color, size) { super(); Object.defineProperty(this, "color", { enumerable: true, configurable: true, writable: true, value: color }); Object.defineProperty(this, "size", { enumerable: true, configurable: true, writable: true, value: size }); this.color = color; this.size = size; } get id() { return `region_area`; } get explanation() { return `All ${this.color} regions have area ${this.size}`; } get configs() { return RegionAreaRule.CONFIGS; } createExampleGrid() { if (this.size < RegionAreaRule.EXAMPLE_GRID_DARK.length) { switch (this.color) { case Color.Dark: return RegionAreaRule.EXAMPLE_GRID_DARK[this.size]; case Color.Light: return RegionAreaRule.EXAMPLE_GRID_LIGHT[this.size]; case Color.Gray: return RegionAreaRule.EXAMPLE_GRID_GRAY[this.size]; } } else { let count = this.size; const tiles = array(5, 4, (x, y) => { count--; return new TileData(true, false, count >= 0 ? this.color : this.color === Color.Gray ? x % 2 !== y % 2 ? Color.Dark : Color.Light : this.color === Color.Light ? Color.Dark : Color.Light); }); return GridData.create(5, 4, tiles); } } get searchVariants() { return RegionAreaRule.SEARCH_VARIANTS; } validateGrid(grid) { const visited = array(grid.width, grid.height, (i, j) => !(grid.getTile(i, j).exists && grid.getTile(i, j).color === this.color)); let complete = true; while (true) { const seed = grid.find((_tile, x, y) => !visited[y][x]); if (!seed) break; const completed = []; const gray = []; grid.iterateArea({ x: seed.x, y: seed.y }, tile => tile.color === this.color, (_, x, y) => { completed.push({ x, y }); visited[y][x] = true; }); if (this.color === Color.Gray) { gray.push(...completed); } else { grid.iterateArea({ x: seed.x, y: seed.y }, tile => tile.color === Color.Gray || tile.color === this.color, (_, x, y) => { gray.push({ x, y }); }); } if (completed.length > this.size) { return { state: State.Error, positions: completed }; } else if (gray.length < this.size) { return { state: State.Error, positions: gray }; } else if (completed.length !== this.size || completed.length !== gray.length) { complete = false; } } return complete ? { state: State.Satisfied } : { state: State.Incomplete }; } copyWith({ color, size }) { return new RegionAreaRule(color ?? this.color, size ?? this.size); } withColor(color) { return this.copyWith({ color }); } withSize(size) { return this.copyWith({ size }); } } Object.defineProperty(RegionAreaRule, "CONFIGS", { enumerable: true, configurable: true, writable: true, value: Object.freeze([ { type: ConfigType.Color, default: Color.Dark, allowGray: false, field: 'color', description: 'Color', configurable: true, }, { type: ConfigType.Number, default: 2, min: 0, field: 'size', description: 'Region Size', configurable: true, }, ]) }); Object.defineProperty(RegionAreaRule, "EXAMPLE_GRID_DARK", { enumerable: true, configurable: true, writable: true, value: Object.freeze([ GridData.create(['wwwww', 'wwwww', 'wwwww', 'wwwww']), GridData.create(['bwwbw', 'wbwwb', 'bwbww', 'wbwwb']), GridData.create(['bbwbb', 'wwbww', 'wwbww', 'wwwbb']), GridData.create(['bbwww', 'bwbwb', 'wbbwb', 'wwwwb']), GridData.create(['bwbbb', 'bbwwb', 'bwbbw', 'wwbbw']), GridData.create(['bbbww', 'bbwbw', 'wwbbb', 'wwwbw']), GridData.create(['bbbww', 'bbbwb', 'wwwbb', 'wwbbb']), GridData.create(['bbbbb', 'bbwww', 'wwwbb', 'bbbbb']), GridData.create(['bbbbw', 'bbbww', 'bwwww', 'wwwww']), GridData.create(['wwwww', 'bbbbb', 'bbwbb', 'wwwww']), GridData.create(['bbbbb', 'bbbww', 'bbwww', 'wwwww']), ]) }); Object.defineProperty(RegionAreaRule, "EXAMPLE_GRID_LIGHT", { enumerable: true, configurable: true, writable: true, value: Object.freeze(RegionAreaRule.EXAMPLE_GRID_DARK.map(grid => GridData.create(grid.width, grid.height, grid.tiles.map(row => row.map(tile => tile.withColor(tile.color === Color.Dark ? Color.Light : Color.Dark)))))) }); Object.defineProperty(RegionAreaRule, "EXAMPLE_GRID_GRAY", { enumerable: true, configurable: true, writable: true, value: Object.freeze(RegionAreaRule.EXAMPLE_GRID_DARK.map(grid => GridData.create(grid.width, grid.height, grid.tiles.map((row, y) => row.map((tile, x) => tile.withColor(tile.color === Color.Dark ? Color.Gray : x % 2 !== y % 2 ? Color.Dark : Color.Light)))))) }); Object.defineProperty(RegionAreaRule, "SEARCH_VARIANTS", { enumerable: true, configurable: true, writable: true, value: [ new RegionAreaRule(Color.Dark, 2).searchVariant(), new RegionAreaRule(Color.Light, 2).searchVariant(), ] }); export default RegionAreaRule; export const instance = new RegionAreaRule(Color.Dark, 2);