From 0929719a845897cc8567cf972e07a69a71f0fa6f Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Thu, 30 Nov 2023 13:29:08 -0500 Subject: Migrate to a full rails app --- app/assets/javascripts/serializer.js | 365 +++++++++++++++++++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 app/assets/javascripts/serializer.js (limited to 'app/assets/javascripts/serializer.js') diff --git a/app/assets/javascripts/serializer.js b/app/assets/javascripts/serializer.js new file mode 100644 index 0000000..70c7f0f --- /dev/null +++ b/app/assets/javascripts/serializer.js @@ -0,0 +1,365 @@ +namespace(function() { + +window.serializePuzzle = function(puzzle) { + var s = new Serializer('w') + var version = 0 + + s.writeInt(version) + s.writeByte(puzzle.width) + s.writeByte(puzzle.height) + s.writeString(puzzle.name) + + var genericFlags = 0 + if (puzzle.autoSolved) genericFlags |= GENERIC_FLAG_AUTOSOLVED + if (puzzle.symmetry) { + genericFlags |= GENERIC_FLAG_SYMMETRICAL + if (puzzle.symmetry.x) genericFlags |= GENERIC_FLAG_SYMMETRY_X + if (puzzle.symmetry.y) genericFlags |= GENERIC_FLAG_SYMMETRY_Y + } + if (puzzle.pillar) genericFlags |= GENERIC_FLAG_PILLAR + s.writeByte(genericFlags) + for (var x=0; x 0) { + s.writeInt(puzzle.path.length) + s.writeByte(startPos.x) + s.writeByte(startPos.y) + for (var dir of puzzle.path) s.writeByte(dir) + } + } else { + s.writeInt(0) + } + + var settingsFlags = 0 + if (puzzle.settings.NEGATIONS_CANCEL_NEGATIONS) settingsFlags |= SETTINGS_FLAG_NCN + if (puzzle.settings.SHAPELESS_ZERO_POLY) settingsFlags |= SETTINGS_FLAG_SZP + if (puzzle.settings.PRECISE_POLYOMINOS) settingsFlags |= SETTINGS_FLAG_PP + if (puzzle.settings.FLASH_FOR_ERRORS) settingsFlags |= SETTINGS_FLAG_FFE + if (puzzle.settings.FAT_STARTPOINTS) settingsFlags |= SETTINGS_FLAG_FS + if (puzzle.settings.CUSTOM_MECHANICS) settingsFlags |= SETTINGS_FLAG_CM + if (puzzle.settings.INVISIBLE_SYMMETRY) settingsFlags |= SETTINGS_FLAG_IS + s.writeByte(settingsFlags) + + s.writeByte(puzzle.symType) + + return s.str() +} + +window.deserializePuzzle = function(data) { + // Data is JSON, so decode it with the old deserializer + if (data[0] == '{') return Puzzle.deserialize(data) + + var s = new Serializer('r', data) + var version = s.readInt() + if (version > 0) throw Error('Cannot read data from unknown version: ' + version) + + var width = s.readByte() + var height = s.readByte() + var puzzle = new Puzzle(Math.floor(width / 2), Math.floor(height / 2)) + puzzle.name = s.readString() + + var genericFlags = s.readByte() + puzzle.autoSolved = genericFlags & GENERIC_FLAG_AUTOSOLVED + puzzle.symType = SYM_TYPE_NONE + if ((genericFlags & GENERIC_FLAG_SYMMETRICAL) != 0) { + if ((genericFlags & GENERIC_FLAG_SYMMETRY_X) != 0) { + if ((genericFlags & GENERIC_FLAG_SYMMETRY_Y) != 0) { + puzzle.symType = SYM_TYPE_ROTATIONAL + } else { + puzzle.symType = SYM_TYPE_VERTICAL + } + } else if ((genericFlags & GENERIC_FLAG_SYMMETRY_Y) != 0) { + puzzle.symType = SYM_TYPE_HORIZONTAL + } + } + puzzle.pillar = (genericFlags & GENERIC_FLAG_PILLAR) != 0 + for (var x=0; x 0) { + var path = [{ + 'x': s.readByte(), + 'y': s.readByte(), + }] + for (var i=0; i= numBytes) + } + + readByte() { + this._checkRead() + return this.data.charCodeAt(this.index++) + } + + writeByte(b) { + if (b < 0 || b > 0xFF) throw Error('Cannot write out-of-range byte ' + b) + this.data += String.fromCharCode(b) + } + + readInt() { + var b1 = this.readByte() << 0 + var b2 = this.readByte() << 8 + var b3 = this.readByte() << 16 + var b4 = this.readByte() << 24 + return b1 | b2 | b3 | b4 + } + + writeInt(i) { + if (i < 0 || i > 0xFFFFFFFF) throw Error('Cannot write out-of-range int ' + i) + var b1 = (i & 0x000000FF) >> 0 + var b2 = (i & 0x0000FF00) >> 8 + var b3 = (i & 0x00FF0000) >> 16 + var b4 = (i & 0xFF000000) >> 24 + this.writeByte(b1) + this.writeByte(b2) + this.writeByte(b3) + this.writeByte(b4) + } + + readLong() { + var i1 = this.readInt() << 32 + var i2 = this.readInt() + return i1 | i2 + } + + writeLong(l) { + if (l < 0 || l > 0xFFFFFFFFFFFFFFFF) throw Error('Cannot write out-of-range long ' + l) + var i1 = l & 0xFFFFFFFF + var i2 = (l - i1) / 0x100000000 + this.writeInt(i1) + this.writeInt(i2) + } + + readString() { + var len = this.readInt() + this._checkRead(len) + var str = this.data.substr(this.index, len) + this.index += len + return str + } + + writeString(s) { + if (s == null) { + this.writeInt(0) + return + } + this.writeInt(s.length) + this.data += s + } + + readColor() { + var r = this.readByte().toString() + var g = this.readByte().toString() + var b = this.readByte().toString() + var a = this.readByte().toString() + return 'rgba(' + r + ', ' + g + ', ' + b + ', ' + a + ')' + } + + writeColor(c) { + // Adapted from https://gist.github.com/njvack/02ad8efcb0d552b0230d + this.colorConverter.fillStyle = 'rgba(0, 0, 0, 0)' // Load a default in case we are passed garbage + this.colorConverter.clearRect(0, 0, 1, 1) + this.colorConverter.fillStyle = c + this.colorConverter.fillRect(0, 0, 1, 1) + var rgba = this.colorConverter.getImageData(0, 0, 1, 1).data + this.writeByte(rgba[0]) + this.writeByte(rgba[1]) + this.writeByte(rgba[2]) + this.writeByte(rgba[3]) + } + + readCell() { + var cellType = this.readByte() + if (cellType === CELL_TYPE_NULL) return null + + var cell = {} + cell.dir = null + cell.line = 0 + if (cellType === CELL_TYPE_LINE) { + cell.type = 'line' + cell.line = this.readByte() + var dot = this.readByte() + if (dot != 0) cell.dot = dot + var gap = this.readByte() + if (gap != 0) cell.gap = gap + } else if (cellType === CELL_TYPE_SQUARE) { + cell.type = 'square' + cell.color = this.readColor() + } else if (cellType === CELL_TYPE_STAR) { + cell.type = 'star' + cell.color = this.readColor() + } else if (cellType === CELL_TYPE_NEGA) { + cell.type = 'nega' + cell.color = this.readColor() + } else if (cellType === CELL_TYPE_TRIANGLE) { + cell.type = 'triangle' + cell.color = this.readColor() + cell.count = this.readByte() + } else if (cellType === CELL_TYPE_POLY) { + cell.type = 'poly' + cell.color = this.readColor() + cell.polyshape = this.readLong() + } else if (cellType === CELL_TYPE_YLOP) { + cell.type = 'ylop' + cell.color = this.readColor() + cell.polyshape = this.readLong() + } else if (cellType == CELL_TYPE_NONCE) { + cell.type = 'nonce' + } + + var startEnd = this.readByte() + if (startEnd & CELL_START) cell.start = true + if (startEnd & CELL_END_LEFT) cell.end = 'left' + if (startEnd & CELL_END_RIGHT) cell.end = 'right' + if (startEnd & CELL_END_TOP) cell.end = 'top' + if (startEnd & CELL_END_BOTTOM) cell.end = 'bottom' + + return cell + } + + + writeCell(cell) { + if (cell == null) { + this.writeByte(CELL_TYPE_NULL) + return + } + + // Write cell type, then cell data, then generic data. + // Note that cell type starts at 1, since 0 is the "null type". + if (cell.type == 'line') { + this.writeByte(CELL_TYPE_LINE) + this.writeByte(cell.line) + this.writeByte(cell.dot) + this.writeByte(cell.gap) + } else if (cell.type == 'square') { + this.writeByte(CELL_TYPE_SQUARE) + this.writeColor(cell.color) + } else if (cell.type == 'star') { + this.writeByte(CELL_TYPE_STAR) + this.writeColor(cell.color) + } else if (cell.type == 'nega') { + this.writeByte(CELL_TYPE_NEGA) + this.writeColor(cell.color) + } else if (cell.type == 'triangle') { + this.writeByte(CELL_TYPE_TRIANGLE) + this.writeColor(cell.color) + this.writeByte(cell.count) + } else if (cell.type == 'poly') { + this.writeByte(CELL_TYPE_POLY) + this.writeColor(cell.color) + this.writeLong(cell.polyshape) + } else if (cell.type == 'ylop') { + this.writeByte(CELL_TYPE_YLOP) + this.writeColor(cell.color) + this.writeLong(cell.polyshape) + } + + var startEnd = 0 + if (cell.start === true) startEnd |= CELL_START + if (cell.end == 'left') startEnd |= CELL_END_LEFT + if (cell.end == 'right') startEnd |= CELL_END_RIGHT + if (cell.end == 'top') startEnd |= CELL_END_TOP + if (cell.end == 'bottom') startEnd |= CELL_END_BOTTOM + this.writeByte(startEnd) + } +} + +var CELL_TYPE_NULL = 0 +var CELL_TYPE_LINE = 1 +var CELL_TYPE_SQUARE = 2 +var CELL_TYPE_STAR = 3 +var CELL_TYPE_NEGA = 4 +var CELL_TYPE_TRIANGLE = 5 +var CELL_TYPE_POLY = 6 +var CELL_TYPE_YLOP = 7 +var CELL_TYPE_NONCE = 8 + +var CELL_START = 1 +var CELL_END_LEFT = 2 +var CELL_END_RIGHT = 4 +var CELL_END_TOP = 8 +var CELL_END_BOTTOM = 16 + +var GENERIC_FLAG_AUTOSOLVED = 1 +var GENERIC_FLAG_SYMMETRICAL = 2 +var GENERIC_FLAG_SYMMETRY_X = 4 +var GENERIC_FLAG_SYMMETRY_Y = 8 +var GENERIC_FLAG_PILLAR = 16 + +var SETTINGS_FLAG_NCN = 1 +var SETTINGS_FLAG_SZP = 2 +var SETTINGS_FLAG_PP = 4 +var SETTINGS_FLAG_FFE = 8 +var SETTINGS_FLAG_FS = 16 +var SETTINGS_FLAG_CM = 32 +var SETTINGS_FLAG_IS = 64 + +}) -- cgit 1.4.1