@logic-pad/core
Version:
152 lines (151 loc) • 5.46 kB
JavaScript
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 <color> 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([]));