xpuz
Version:
Parses and creates crossword puzzle files
188 lines (169 loc) • 6 kB
JavaScript
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var reduce = require("lodash/reduce");
var isEqual = require("lodash/isEqual");
var PuzzleMixin = require("./puzzle-mixin");
/**
* Info object
*
* @typedef PuzzleInfo
*
* @memberof xpuz.Puzzle
*
* @prop {?string} title - the title of the puzzle
* @prop {?string} author - the author of the puzzle
* @prop {?string} publisher - the publisher of the puzzle
* @prop {?string} copyright - the copyright of the puzzle
* @prop {?string} intro - the introductory text of the puzzle
* @prop {?*} difficulty - the difficulty level of the puzzle
* @prop {?object} formatExtra - any extra data for a specific file format
* (e.g. .puz files have a version string)
*/
/**
* Represents a puzzle object
*
* @memberof xpuz
* @mixes xpuz.PuzzleMixin
*/
var Puzzle =
/**
* @param {object} args - the constructor args
* @param {Types.Grid} args.grid - a two-dimensional array representing the puzzle grid
* @param {{across: object<number, string>, down: object<number, string>}} args.clues - a list of clues
* for across and down, with each collection having the key as the clue number and the value as the clue
* text (e.g. `{across: { 3: "some clue" }}`)
* @param {Array<Array<?string>>} [args.userSolution] - the currently filled in guesses of the user stored with this
* puzzle instance. Two dimensional array with the same dimensions as `grid`, where each cell is either a string
* or `null` (for block cells)
* @param {xpuz.Puzzle.PuzzleInfo} [args.info] - information about the puzzle
* @param {object} [args.extensions] - extra, possibly implementation-specific information about the puzzle, such as timer
* information
*/
function Puzzle(_ref) {
var _this = this;
var grid = _ref.grid,
clues = _ref.clues,
userSolution = _ref.userSolution,
info = _ref.info,
extensions = _ref.extensions;
_classCallCheck(this, Puzzle);
_defineProperty(this, "toJSON", function () {
return {
grid: _this.grid,
clues: _this.clues,
userSolution: _this.userSolution,
info: _this.info,
extensions: _this.extensions
};
});
_defineProperty(this, "clone", function () {
return new Puzzle({
grid: _this.grid.map(function (row) {
return row.map(function (cell) {
return Object.assign({}, cell);
} // Clone (shallow) cell object
);
}),
clues: {
across: reduce(_this.clues.across, function (cloned, clue, clueNumber) {
cloned[clueNumber] = clue;
return cloned;
}, {}),
down: reduce(_this.clues.down, function (cloned, clue, clueNumber) {
cloned[clueNumber] = clue;
return cloned;
}, {})
},
userSolution: _this.userSolution.map(function (row) {
return row.map(function (cell) {
return cell;
} // Values in userSolution are just strings
);
}),
info: Object.assign({}, _this.info),
extensions: JSON.parse(JSON.stringify(_this.extensions)) // Deep clone
});
});
/**
* The definition of the puzzle grid. It is represented as an array of rows, so
* `grid[0]` is the first row of the puzzle.
*
* @type Array<Array<Types.GridCell>>
* @instance
*/
this.grid = Puzzle.processGrid(grid || []); // processGrid() is defined in PuzzleMixin
/**
* Listing of clues for the puzzle
*
* @type object
* @instance
*
* @property {object} across - an object mapping clue numbers to clue texts for across clues
* @property {object} down - an object mapping clue numbers to clue texts for down clues
*/
this.clues = clues || {
across: {},
down: {}
};
info = info || {};
/**
* An object of various puzzle information, such as author, title, copyright, etc.
*
* @type object
* @instance
*
* @property {string} [title] - the title of the puzzle
* @property {string} [author] - the author of the puzzle
* @property {string} [publisher] - the publisher of the puzzle
* @property {string} [copyright] - the copyright text of the puzzle
* @property {*} [difficulty] - the difficulty level of the puzzle
* @property {string} [intro] - the introductory text of the puzzle
* @property {?object} [formatExtra] - any additional format-specific data
*/
this.info = {
title: info.title || "",
author: info.author || "",
copyright: info.copyright || "",
publisher: info.publisher || "",
difficulty: info.difficulty || "",
intro: info.intro || "",
formatExtra: info.formatExtra || void 0
};
/**
* A structure representing the current solution as the user has filled it out.
* The structure is similar to {@link xpuz.Puzzle#grid|grid}, but
* each item is a string containing the user's current answer--an empty string
* if the corresponding grid cell is not filled in, a non-empty string if it's
* filled in.
*
* @type Array<string[]>
* @instance
*/
this.userSolution = userSolution || grid.map(function (row) {
return row.map(function (cell) {
return cell.isBlockCell ? null : "";
});
});
/**
* A collection of extra, possibly implementation-dependent data about the puzzle,
* such as timer information.
*
* @type object
* @instance
*/
this.extensions = extensions || {};
}
/**
* Returns this puzzle as a plain Javascript object, suitable for serializing to JSON.
*
* @method
*
* @returns {object} object representation of this puzzle object
*/
;
PuzzleMixin({
constructor: Puzzle,
equalityTest: isEqual
});
exports = module.exports = Puzzle;
//# sourceMappingURL=puzzle.js.map