@logic-pad/core
Version:
183 lines (182 loc) • 6.54 kB
JavaScript
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 <color> regions have area <size>**
*
* @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);