www.spaceplanner.app

Web client to the spaceplanner API
git clone git://jacobedwards.org/www.spaceplanner.app
Log | Files | Refs

commit 54544a004c7e6b2b252943d638042ce00637c4fa
parent 27c5c716642e4ccb12fafcf3f3927a54ac975460
Author: Jacob R. Edwards <jacob@jacobedwards.org>
Date:   Sun, 13 Oct 2024 17:45:47 -0700

Use updatedObject for all objects

This will make future changes much easier and less error-prone.

Diffstat:
Mfiles/floorplans/floorplan/backend.js | 195+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mfiles/floorplans/floorplan/editor.js | 8++++----
2 files changed, 100 insertions(+), 103 deletions(-)

diff --git a/files/floorplans/floorplan/backend.js b/files/floorplans/floorplan/backend.js @@ -451,20 +451,18 @@ export class FloorplanBackend { delete this.cache[t][id] } - addPoint(point, options) { - options = options ?? {} - - if (typeof point.x !== "number" || typeof point.y !== "number") { - throw new Error(`Point's x (${point.x}) and y (${point.y}) are not numbers`) - } - return this.addData(options.replace ?? "points", - { x: Math.round(point.x), y: Math.round(point.y) }, options) - } - - replacePoint(id, newpoint, options) { - options = options ?? {} - options.replace = id - return this.addPoint(newpoint, options) + addPoint(params, id) { + const p = this.updatedObject(params, id, { + x: { + required: true, + parse: parsePos + }, + y: { + required: true, + parse: parsePos + } + }) + return this.addData(id ?? "points", p) } removePoint(id, options) { @@ -494,7 +492,6 @@ export class FloorplanBackend { const validPoint = function(id) { return idType(id) === "pnt" && backend.obj(id) } - const m = this.updatedObject(params, id, { type: { required: true, @@ -534,46 +531,28 @@ export class FloorplanBackend { } addFurniture(params, id) { - params = params ?? {} - - //let f = id ? this.reqObj(id) : {} - let f = {} - - if (params.width != undefined) { - f.width = Math.round(params.width) - if (f.width <= 0) { - throw new Error(params.width + ": rounded width must be greater than zero") - } - } - if (params.depth != undefined) { - f.depth = Math.round(params.depth) - if (f.depth <= 0) { - throw new Error(params.depth + ": rounded depth must be greater than zero") - } - } - if (params.name != undefined) { - if (typeof params.name !== "string") { - throw new Error(params.name + ": Expected string name") - } - f.name = params.name - } - if (params.type != undefined) { - if (typeof params.type !== "string") { - throw new Error("Invalid type") - } - f.type = params.type - } - - if (params.style != undefined) { - if (typeof params.style !== "string") { - throw new Error(params.style + ": Invalid style") + const f = this.updatedObject(params, id, { + width: { + required: true, + parser: parseSize + }, + depth: { + required: true, + parser: parseSize + }, + type: { + required: true, + type: "string" + }, + name: { + type: "string" + }, + // Could do with verifying this + style: { + type: "string" } - f.style = params.style - } + }) - if (f.width == null || f.depth == null || f.type == null) { - throw new Error("Missing required parameters") - } return this.addData(id ?? "furniture", f) } @@ -588,53 +567,41 @@ export class FloorplanBackend { mapFurniture(params, id) { let backend = this - const validInt = function(input, cur) { - let x = Math.round(input ?? cur) - if (isNaN(x)) { - throw new Error(input + " is NaN") - } - return x - } - let parsers = { - x: validInt, - y: validInt, - angle: function(input, cur) { - if (input == undefined) { - return cur ?? 0 - } - let x = validInt(input) - if (x < 0 || x >= 360) { - throw new Error(input + ": Angle must be between 0 and 359 degrees") - } - return x + + let fm = this.updatedObject(params, id, { + x: { + required: true, + parse: parsePos }, - layout: function(input, cur) { - if (input == undefined) { - return cur ?? "1" - } - if (typeof input !== "string") { - throw new Error(input + ": Layout should be a string") - } - return input + y: { + required: true, + parse: parsePos }, - furniture_id: function(id, cur) { - if (id == undefined) { - if (cur == null) { - throw new Error("Missing furniture id") + angle: { + required: true, + default: 0, + parse: function(input) { + let angle = validInt(input) + if (angle < 0 || angle >= 360) { + throw new Error(angle + ": Angle must be between 0 and 359 degrees") } - return cur + return angle } - if (backend.obj(id) == undefined) { - throw new Error("invalid furniture id for furniture map") + }, + layout: { + required: true, + default: "1", + validate: function(input) { + return typeof input === "string" + } + }, + furniture_id: { + required: true, + validate: function(id) { + return backend.cache.furniture_maps[id] != null } - return id } - } - - let fm = id ? this.reqObj(id) : {} - for (let param in parsers) { - fm[param] = parsers[param](params[param], fm ? fm[param] : undefined) - } + }) return this.addData(id ?? "furniture_maps", fm) } @@ -651,14 +618,28 @@ export class FloorplanBackend { updatedObject(params, id, vd) { let obj = id ? structuredClone(this.reqObj(id)) : {} + params = structuredClone(params) for (let k in vd) { let vdk = vd[k] - if (vdk.required && params[k] === null) { - throw new Error(`Cannot delete required parameter ("${k}")`) - } if (params[k] === undefined) { + if (obj[k] !== undefined || vdk.default === undefined) { + continue + } + params[k] = vdk.default + + } + if (params[k] === null) { + if (vdk.required) { + throw new Error(`Cannot delete required parameter ("${k}")`) + } + delete obj[k] continue } + if (typeof vdk.type === "string") { + if (typeof params[k] !== vdk.type) { + throw new Error(`Invalid value for "${k}" parameter (type was ${typeof params[k]} when expecting ${vdk.type}`) + } + } if (typeof vdk.parse === "function") { obj[k] = vdk.parse(params[k]) } else if (typeof vdk.validate === "function") { @@ -666,8 +647,8 @@ export class FloorplanBackend { throw new Error(`Invalid value for "${k}" parameter ("${params[k]}")`) } obj[k] = params[k] - } else { - throw new Error(`"${k}" parameter missing validate or parse function`) + } else if (typeof vdk.type !== "string") { + throw new Error(`"${k}" parameter missing type constraint, or validate or parse function`) } } @@ -1075,3 +1056,19 @@ export function parsePath(path) { } return idString(id) } + +function parseSize(size) { + let n = parsePos(size) + if (n <= 0) { + throw new Error("Size must be greater than 0") + } + return n +} + +function parsePos(pos) { + let n = Math.round(pos) + if (isNaN(n)) { + throw new Error("Invalid coordinate (NaN)") + } + return n +} diff --git a/files/floorplans/floorplan/editor.js b/files/floorplans/floorplan/editor.js @@ -519,6 +519,10 @@ export class FloorplanEditor { return this.backend.addPoint(point) } + movePoint(point, coordinate) { + return this.backend.addPoint(coordinate, getID(point, "points")) + } + remove(...elements) { let later = [] @@ -549,10 +553,6 @@ export class FloorplanEditor { this.backend.removeOrphans() } - movePoint(point, coordinate) { - return this.backend.replacePoint(getID(point, "points"), coordinate) - } - pointAt(point) { return this.thingAt(point, "#points") }