UNPKG

@logic-pad/core

Version:
152 lines (151 loc) 5.46 kB
import { ConfigType } from '../config.js'; import { array } from '../dataHelper.js'; import GridData from '../grid.js'; import { Color, State } from '../primitives.js'; import { getShapeVariants, sanitizePatternGrid, tilesToShape, } from '../shapes.js'; import RegionShapeRule from './regionShapeRule.js'; class ContainsShapeRule extends RegionShapeRule { /** * **All &lt;color&gt; areas must contain this pattern** * * @param color - The color of the regions to compare. * @param pattern - GridData representing the required pattern. Only non-gray tiles are considered. */ constructor(color, pattern) { super(color); Object.defineProperty(this, "pattern", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "cache", { enumerable: true, configurable: true, writable: true, value: void 0 }); this.pattern = sanitizePatternGrid(pattern, t => t.color === color ? t : t.withColor(Color.Gray)); this.cache = getShapeVariants(tilesToShape(this.pattern.tiles)); } get id() { return `contains_shape`; } get explanation() { return `All ${this.color} areas must contain this pattern`; } get configs() { return ContainsShapeRule.CONFIGS; } createExampleGrid() { let minX = Number.POSITIVE_INFINITY; let minY = Number.POSITIVE_INFINITY; let maxX = Number.NEGATIVE_INFINITY; let maxY = Number.NEGATIVE_INFINITY; this.pattern.forEach((tile, x, y) => { if (tile.color !== Color.Gray && tile.exists) { minX = Math.min(minX, x); minY = Math.min(minY, y); maxX = Math.max(maxX, x); maxY = Math.max(maxY, y); } }); const width = maxX - minX + 1; const height = maxY - minY + 1; const tiles = array(width, height, (x, y) => { const tile = this.pattern.getTile(x + minX, y + minY); if (!tile.exists || tile.color !== Color.Gray) return tile; return tile.withExists(false); }); return GridData.create(width, height, tiles); } get searchVariants() { return ContainsShapeRule.SEARCH_VARIANTS; } validateGrid(grid) { const { regions, complete } = this.getShapeRegions(grid); const errorRegion = regions.find(r => { for (const pattern of this.cache) { if (r.shape.elements.length < pattern.elements.length) continue; for (let y = 0; y <= r.shape.height - pattern.height; y++) { for (let x = 0; x <= r.shape.width - pattern.width; x++) { let match = true; for (const element of pattern.elements) { const tile = r.shape.elements.find(e => e.x === x + element.x && e.y === y + element.y); if (!tile || tile.color !== element.color) { match = false; break; } } if (match) return false; } } } return true; }); if (errorRegion) { return { state: State.Error, positions: errorRegion.positions, }; } else { return { state: complete ? State.Satisfied : State.Incomplete }; } } copyWith({ color, pattern, }) { return new ContainsShapeRule(color ?? this.color, pattern ?? this.pattern); } withPattern(pattern) { return this.copyWith({ pattern }); } } Object.defineProperty(ContainsShapeRule, "EXAMPLE_GRID_LIGHT", { enumerable: true, configurable: true, writable: true, value: Object.freeze(GridData.create(['nnnnn', 'nnnnn', 'wwwwn', 'nnnnn', 'nnnnn'])) }); Object.defineProperty(ContainsShapeRule, "EXAMPLE_GRID_DARK", { enumerable: true, configurable: true, writable: true, value: Object.freeze(GridData.create(['nnnnn', 'nnnnn', 'bbbbn', 'nnnnn', 'nnnnn'])) }); Object.defineProperty(ContainsShapeRule, "CONFIGS", { enumerable: true, configurable: true, writable: true, value: Object.freeze([ { type: ConfigType.Color, default: Color.Light, allowGray: false, field: 'color', description: 'Color', configurable: true, }, { type: ConfigType.Tile, default: ContainsShapeRule.EXAMPLE_GRID_LIGHT, resizable: true, field: 'pattern', description: 'Pattern', configurable: true, }, ]) }); Object.defineProperty(ContainsShapeRule, "SEARCH_VARIANTS", { enumerable: true, configurable: true, writable: true, value: [ new ContainsShapeRule(Color.Light, ContainsShapeRule.EXAMPLE_GRID_LIGHT).searchVariant(), new ContainsShapeRule(Color.Dark, ContainsShapeRule.EXAMPLE_GRID_DARK).searchVariant(), ] }); export default ContainsShapeRule; export const instance = new ContainsShapeRule(Color.Dark, GridData.create([]));