@ajhaa/react-crossword
Version:
A fork of Jared Reisingers crossword package
264 lines (216 loc) • 6.59 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isAcross = isAcross;
exports.otherDirection = otherDirection;
exports.calculateExtents = calculateExtents;
exports.createEmptyGrid = createEmptyGrid;
exports.fillClues = fillClues;
exports.createGridData = createGridData;
exports.byNumber = byNumber;
exports.clearGuesses = clearGuesses;
exports.saveGuesses = saveGuesses;
exports.serializeGuesses = serializeGuesses;
exports.loadGuesses = loadGuesses;
exports.deserializeGuesses = deserializeGuesses;
exports.findCorrectAnswers = findCorrectAnswers;
exports.bothDirections = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var directionInfo = {
across: {
primary: 'col',
orthogonal: 'row'
},
down: {
primary: 'row',
orthogonal: 'col'
}
};
var bothDirections = Object.keys(directionInfo);
exports.bothDirections = bothDirections;
function isAcross(direction) {
return direction === 'across';
}
function otherDirection(direction) {
return isAcross(direction) ? 'down' : 'across';
}
function calculateExtents(data, direction) {
var _ref2;
var dir = directionInfo[direction];
var primaryMax = 0;
var orthogonalMax = 0;
Object.entries(data[direction]).forEach(function (_ref) {
var i = _ref[0],
info = _ref[1];
var primary = info[dir.primary] + info.answer.length - 1;
if (primary > primaryMax) {
primaryMax = primary;
}
var orthogonal = info[dir.orthogonal];
if (orthogonal > orthogonalMax) {
orthogonalMax = orthogonal;
}
});
return _ref2 = {}, _ref2[dir.primary] = primaryMax, _ref2[dir.orthogonal] = orthogonalMax, _ref2;
}
var emptyCellData = {
used: false,
number: null,
answer: '',
guess: '',
locked: false,
// row: r,
// col: c,
across: null,
down: null,
questionCorrect: false
};
function createEmptyGrid(size) {
var gridData = Array(size); // Rather than [x][y] in column-major order, the cells are indexed as
// [row][col] in row-major order.
for (var r = 0; r < size; r++) {
gridData[r] = Array(size);
for (var c = 0; c < size; c++) {
gridData[r][c] = (0, _extends2["default"])((0, _extends2["default"])({}, emptyCellData), {}, {
row: r,
col: c
});
}
}
return gridData;
}
function fillClues(gridData, clues, data, direction) {
var dir = directionInfo[direction];
Object.entries(data[direction]).forEach(function (_ref3) {
var number = _ref3[0],
info = _ref3[1];
var rowStart = info.row,
colStart = info.col,
clue = info.clue,
answer = info.answer;
for (var i = 0; i < answer.length; i++) {
var row = rowStart + (dir.primary === 'row' ? i : 0);
var col = colStart + (dir.primary === 'col' ? i : 0);
var cellData = gridData[row][col]; // TODO?: check to ensure the answer is the same if it's already set?
cellData.used = true;
cellData.answer = answer[i];
cellData[direction] = number;
if (i === 0) {
// TODO?: check to ensure the number is the same if it's already set?
cellData.number = number;
}
}
clues[direction].push({
number: number,
clue: clue
});
});
clues[direction].sort(byNumber);
} // Given the "nice format" for a crossword, generate the usable data optimized
// for rendering and our interactivity.
function createGridData(data) {
var acrossMax = calculateExtents(data, 'across');
var downMax = calculateExtents(data, 'down');
var size = Math.max.apply(Math, Object.values(acrossMax).concat(Object.values(downMax))) + 1;
var gridData = createEmptyGrid(size); // Now fill with answers... and also collect the clues
var clues = {
across: [],
down: []
};
fillClues(gridData, clues, data, 'across');
fillClues(gridData, clues, data, 'down');
return {
size: size,
gridData: gridData,
clues: clues
};
} // sort helper for clues...
function byNumber(a, b) {
var aNum = Number.parseInt(a.number, 10);
var bNum = Number.parseInt(b.number, 10);
return aNum - bNum;
}
function clearGuesses(storageKey) {
if (!window.localStorage) {
return;
}
window.localStorage.removeItem(storageKey);
}
function saveGuesses(gridData, storageKey) {
var _window = window,
localStorage = _window.localStorage;
if (!localStorage) {
return;
}
var guesses = serializeGuesses(gridData);
var saveData = {
date: Date.now(),
guesses: guesses
};
localStorage.setItem(storageKey, JSON.stringify(saveData));
}
function serializeGuesses(gridData) {
var guesses = gridData.reduce(function (memo, row, r) {
return row.reduce(function (memoInner, cellData, c) {
var guess = cellData.guess;
if (guess !== '') {
memoInner[r + "_" + c] = cellData.guess;
}
return memoInner;
}, memo);
}, {});
return guesses;
}
function loadGuesses(gridData, storageKey) {
var _window2 = window,
localStorage = _window2.localStorage;
if (!localStorage) {
return;
}
var saveRaw = localStorage.getItem(storageKey);
if (!saveRaw) {
return;
}
var saveData = JSON.parse(saveRaw); // TODO: check date for expiration?
deserializeGuesses(gridData, saveData.guesses);
}
function deserializeGuesses(gridData, guesses) {
Object.entries(guesses).forEach(function (_ref4) {
var key = _ref4[0],
val = _ref4[1];
var _key$split = key.split('_'),
r = _key$split[0],
c = _key$split[1]; // ignore any out-of-bounds guesses!
if (r <= gridData.length - 1 && c <= gridData[0].length - 1) {
gridData[r][c].guess = val;
}
});
}
function findCorrectAnswers(data, gridData) {
var correctAnswers = [];
bothDirections.forEach(function (direction) {
var across = isAcross(direction);
Object.entries(data[direction]).forEach(function (_ref5) {
var num = _ref5[0],
info = _ref5[1];
var row = info.row,
col = info.col;
var correct = true;
for (var i = 0; i < info.answer.length; i++) {
var r = across ? row : row + i;
var c = across ? col + i : col;
if (gridData[r][c].guess !== info.answer[i]) {
correct = false;
break;
}
}
if (correct) {
// same args as notifyCorrect: direction, number, answer
correctAnswers.push([direction, num, info.answer]);
}
});
});
return correctAnswers;
}