@logic-pad/core
Version:
212 lines (211 loc) • 6.9 kB
JavaScript
import { Color, Comparison } from '../../primitives.js';
import BanPatternRule from '../../rules/banPatternRule.js';
import CellCountRule from '../../rules/cellCountRule.js';
import ConnectAllRule from '../../rules/connectAllRule.js';
import OffByXRule from '../../rules/offByXRule.js';
import RegionAreaRule from '../../rules/regionAreaRule.js';
import SameShapeRule from '../../rules/sameShapeRule.js';
import SymbolsPerRegionRule from '../../rules/symbolsPerRegionRule.js';
import UndercluedRule from '../../rules/undercluedRule.js';
import UniqueShapeRule from '../../rules/uniqueShapeRule.js';
import { instance as areaNumberInstance, } from '../../symbols/areaNumberSymbol.js';
import { instance as dartInstance, } from '../../symbols/dartSymbol.js';
import { instance as galaxyInstance, } from '../../symbols/galaxySymbol.js';
import { instance as letterInstance, } from '../../symbols/letterSymbol.js';
import { instance as lotusInstance, } from '../../symbols/lotusSymbol.js';
import { instance as minesweeperInstance, } from '../../symbols/minesweeperSymbol.js';
import { instance as viewpointInstance, } from '../../symbols/viewpointSymbol.js';
import TileData from '../../tile.js';
function canonizeTiles(tileData) {
const ret = [];
for (const row of tileData) {
const newRow = [];
for (const tile of row) {
if (tile.exists) {
newRow.push(tile);
}
else {
newRow.push(new TileData(true, false, Color.Gray));
}
}
ret.push(newRow);
}
return ret;
}
export function gridToJson(grid) {
const rules = [];
for (const rule of grid.rules) {
if (rule instanceof ConnectAllRule) {
rules.push({
type: 'connectAll',
color: rule.color,
});
}
else if (rule instanceof BanPatternRule) {
rules.push({
type: 'forbiddenPattern',
pattern: canonizeTiles(rule.pattern.tiles),
});
}
else if (rule instanceof SameShapeRule) {
rules.push({
type: 'sameShape',
color: rule.color,
});
}
else if (rule instanceof UniqueShapeRule) {
rules.push({
type: 'uniqueShape',
color: rule.color,
});
}
else if (rule instanceof RegionAreaRule) {
rules.push({
type: 'regionArea',
color: rule.color,
size: rule.size,
});
}
else if (rule instanceof CellCountRule) {
rules.push({
type: 'cellCount',
color: rule.color,
count: rule.count,
});
}
else if (rule instanceof OffByXRule) {
rules.push({
type: 'offByX',
number: rule.number,
});
}
else if (rule instanceof UndercluedRule) {
continue;
}
else if (rule instanceof SymbolsPerRegionRule) {
let kind;
if (rule.comparison === Comparison.Equal) {
kind = 'exactly';
}
else if (rule.comparison === Comparison.AtLeast) {
kind = 'atLeast';
}
else if (rule.comparison === Comparison.AtMost) {
kind = 'atMost';
}
else {
throw new Error(`Unknown comparison (${rule.comparison})`);
}
rules.push({
type: 'symbolCount',
number: rule.count,
kind,
color: rule.color,
});
}
else if (rule.necessaryForCompletion) {
throw new Error(`Unknown rule type (${rule.explanation})`);
}
}
for (const [rule, symbols] of grid.symbols) {
if (rule === minesweeperInstance.id) {
rules.push({
type: 'minesweeper',
tiles: symbols.map(s => ({
x: Math.floor(s.x),
y: Math.floor(s.y),
number: s.number,
})),
});
}
else if (rule === areaNumberInstance.id) {
rules.push({
type: 'number',
tiles: symbols.map(s => ({
x: Math.floor(s.x),
y: Math.floor(s.y),
number: s.number,
})),
});
}
else if (rule === letterInstance.id) {
rules.push({
type: 'letter',
tiles: symbols.map(s => ({
x: Math.floor(s.x),
y: Math.floor(s.y),
letter: s.letter,
})),
});
}
else if (rule === dartInstance.id) {
rules.push({
type: 'dart',
tiles: symbols.map(s => ({
x: Math.floor(s.x),
y: Math.floor(s.y),
orientation: s.orientation,
number: s.number,
})),
});
}
else if (rule === viewpointInstance.id) {
rules.push({
type: 'viewpoint',
tiles: symbols.map(s => ({
x: Math.floor(s.x),
y: Math.floor(s.y),
number: s.number,
})),
});
}
else if (rule === lotusInstance.id) {
const tiles = symbols.map(s => ({
x: Math.round(s.x * 2),
y: Math.round(s.y * 2),
orientation: s.orientation,
}));
rules.push({
type: 'lotus',
tiles,
});
}
else if (rule === galaxyInstance.id) {
const tiles = symbols.map(s => ({
x: Math.round(s.x * 2),
y: Math.round(s.y * 2),
}));
rules.push({
type: 'galaxy',
tiles,
});
}
else if (symbols.some(s => s.necessaryForCompletion)) {
throw new Error(`Unknown symbol type: ${rule}`);
}
}
const connections = grid.connections.edges.map(edge => {
return {
x1: edge.x1,
y1: edge.y1,
x2: edge.x2,
y2: edge.y2,
};
});
const tiles = grid.tiles.map(row => {
return row.map(tile => {
return {
exists: tile.exists,
fixed: tile.fixed,
color: tile.color,
};
});
});
return {
width: grid.width,
height: grid.height,
connections,
tiles,
rules,
};
}