From d6ba5609e8fbfefeb6ffc6144c0c850b0c1acd33 Mon Sep 17 00:00:00 2001 From: prescientmoon Date: Thu, 28 Nov 2024 14:58:57 +0100 Subject: [PATCH] Fix light bulb errors (also add a dev mode to build script) --- build.js | 9 +- package.json | 64 +++++------ src/index.ts | 6 +- .../activation/classes/ExecutionQueue.ts | 92 ++++++++-------- src/modules/saving/templates/light.ts | 2 +- src/modules/simulation/classes/Gate.ts | 55 +++++----- src/modules/simulation/constants.ts | 3 +- src/modules/storage/classes/LocalStore.ts | 100 +++++++++--------- 8 files changed, 170 insertions(+), 161 deletions(-) diff --git a/build.js b/build.js index 5809460..c59b790 100644 --- a/build.js +++ b/build.js @@ -5,15 +5,17 @@ import * as fs from 'fs' const serve = process.env.ESBUILD_SERVE === '1' const baseurl = process.env.ESBUILD_BASEURL || '' +const nodeEnv = process.env.NODE_ENV +const isProd = nodeEnv !== 'development' console.log(`Building with baseurl ${baseurl}`) const ctx = await esbuild.context({ entryPoints: ['src/index.ts'], - minify: true, + minify: isProd, bundle: true, metafile: true, - splitting: true, + splitting: isProd, outdir: 'dist', format: 'esm', target: ['es2020'], @@ -23,7 +25,8 @@ const ctx = await esbuild.context({ '.svg': 'file' }, define: { - 'process.env.BASEURL': JSON.stringify(baseurl) + 'process.env.BASEURL': JSON.stringify(baseurl), + 'process.env.NODE_ENV': JSON.stringify(nodeEnv) }, plugins: [ htmlPlugin({ diff --git a/package.json b/package.json index ba2264d..aa62e9d 100644 --- a/package.json +++ b/package.json @@ -1,34 +1,34 @@ { - "name": "erratic-gate", - "version": "1.0.0", - "type": "module", - "scripts": { - "dev": "ESBUILD_SERVE=1 node ./build.js", - "build": "node ./build.js", - "check": "tsc" - }, - "devDependencies": { - "@craftamap/esbuild-plugin-html": "^0.6.1", - "@types/deepmerge": "^2.2.0", - "@types/mainloop.js": "^1.0.5", - "@types/node": "^20.8.9", - "@types/react-dom": "^18.2.14", - "@types/react-router-dom": "^4.3.4", - "esbuild": "^0.19.5", - "esbuild-sass-plugin": "^2.16.0", - "typescript": "^5.0.2" - }, - "dependencies": { - "@eix-js/utils": "0.0.6", - "@material-ui/core": "^4.2.1", - "deepmerge": "^4.0.0", - "keycode": "^2.2.0", - "mainloop.js": "^1.0.4", - "react": "^16.8.6", - "react-dom": "^16.8.6", - "react-router-dom": "^5.0.1", - "react-toastify": "^5.3.2", - "rxjs": "^6.5.2", - "rxjs-hooks": "^0.5.1" - } + "name": "erratic-gate", + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "NODE_ENV=development ESBUILD_SERVE=1 node ./build.js", + "build": "node ./build.js", + "check": "tsc" + }, + "devDependencies": { + "@craftamap/esbuild-plugin-html": "^0.6.1", + "@types/deepmerge": "^2.2.0", + "@types/mainloop.js": "^1.0.5", + "@types/node": "^20.8.9", + "@types/react-dom": "^18.2.14", + "@types/react-router-dom": "^4.3.4", + "esbuild": "^0.19.5", + "esbuild-sass-plugin": "^2.16.0", + "typescript": "^5.0.2" + }, + "dependencies": { + "@eix-js/utils": "0.0.6", + "@material-ui/core": "^4.2.1", + "deepmerge": "^4.0.0", + "keycode": "^2.2.0", + "mainloop.js": "^1.0.4", + "react": "^16.8.6", + "react-dom": "^16.8.6", + "react-router-dom": "^5.0.1", + "react-toastify": "^5.3.2", + "rxjs": "^6.5.2", + "rxjs-hooks": "^0.5.1" + } } diff --git a/src/index.ts b/src/index.ts index df2c8fd..d8dd73b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -33,7 +33,11 @@ async function main() { } } -new EventSource('/esbuild').addEventListener('change', () => location.reload()) +if (process.env.BASEURL === 'development') { + new EventSource('/esbuild').addEventListener('change', () => + location.reload() + ) +} // Call entry main().catch((error) => { diff --git a/src/modules/activation/classes/ExecutionQueue.ts b/src/modules/activation/classes/ExecutionQueue.ts index 45a519c..5747b39 100644 --- a/src/modules/activation/classes/ExecutionQueue.ts +++ b/src/modules/activation/classes/ExecutionQueue.ts @@ -5,68 +5,68 @@ import { filter, take } from 'rxjs/operators' * Keeps track of what a task should do and where the output should be delivered */ export interface Task { - output: Subject - execute: () => Promise + output: Subject + execute: () => Promise } /** * Used to execute a number of async tasks */ export class ExecutionQueue { - /** - * An array of all the tasks wich need to be executed - */ - private tasks: Task[] = [] + /** + * An array of all the tasks wich need to be executed + */ + private tasks: Task[] = [] - /** - * Keeps track of the current task - */ - private current: Promise | null + /** + * Keeps track of the current task + */ + private current: Promise | null - /** - * Wheather the tasks should continue beeing executed - */ - public active = true + /** + * Whether the tasks should continue being executed + */ + public active = true - /** - * Adds a new task to the queue - * - * @param task The task to add - */ - public push(task: () => Promise) { - const executionSubject = new Subject() - const executionPromise = executionSubject.pipe(take(1)).toPromise() + /** + * Adds a new task to the queue + * + * @param task The task to add + */ + public push(task: () => Promise) { + const executionSubject = new Subject() + const executionPromise = executionSubject.pipe(take(1)).toPromise() - this.tasks.push({ - output: executionSubject, - execute: task - }) + this.tasks.push({ + output: executionSubject, + execute: task + }) - if (!this.current) { - this.next() - } - - return executionPromise + if (!this.current) { + this.next() } - /** - * Executes the next task in the queue - */ - private next() { - const task = this.tasks.shift() + return executionPromise + } - if (task) { - this.current = task.execute() + /** + * Executes the next task in the queue + */ + private next() { + const task = this.tasks.shift() - this.current.then(result => { - task.output.next(result) + if (task) { + this.current = task.execute() - if (this.active) { - this.next() - } - }) - } else { - this.current = null + this.current.then((result) => { + task.output.next(result) + + if (this.active) { + this.next() } + }) + } else { + this.current = null } + } } diff --git a/src/modules/saving/templates/light.ts b/src/modules/saving/templates/light.ts index b99c17d..ae29c33 100644 --- a/src/modules/saving/templates/light.ts +++ b/src/modules/saving/templates/light.ts @@ -24,7 +24,7 @@ const lightTemplate: PartialTemplate = { activation: ` const { main, active } = context.colors - context.color(context.getBinary(2) ? active : main) + context.color(context.getBinary(0) ? active : main) ` }, integration: { diff --git a/src/modules/simulation/classes/Gate.ts b/src/modules/simulation/classes/Gate.ts index 9c56192..04bcfd5 100644 --- a/src/modules/simulation/classes/Gate.ts +++ b/src/modules/simulation/classes/Gate.ts @@ -295,8 +295,9 @@ export class Gate { props: Property[] = this.template.properties.data, target: GateProps = this.props, path: string[] = [] - ) { + ): boolean { // We don't want to update until every prop has been created + let shouldUpdate = false let lockUpdates = true if (this.template.properties.enabled) { @@ -304,7 +305,7 @@ export class Gate { if (isGroup(prop)) { const { groupName } = prop target[groupName] = {} as GateProps - this.assignProps( + shouldUpdate ||= this.assignProps( typeof source[groupName] === 'object' ? (source[groupName] as PropsSave) : {}, @@ -312,36 +313,38 @@ export class Gate { target[groupName] as GateProps, [...path, groupName] ) + } else { + const { name, base, needsUpdate } = prop + shouldUpdate ||= needsUpdate || false - continue + const subject = new BehaviorSubject( + source.hasOwnProperty(name) ? source[name] : base + ) + + target[name] = subject + + this.subscriptions.push( + subject.subscribe((value) => { + if (!lockUpdates && needsUpdate && path.length === 0) { + return this.update() + } + + if (path.length === 0) { + return + } + + this.updateNestedProp([...path, name], value) + }) + ) } - - const { name, base, needsUpdate } = prop - - const subject = new BehaviorSubject( - source.hasOwnProperty(name) ? source[name] : base - ) - - target[name] = subject - - this.subscriptions.push( - subject.subscribe((value) => { - if (!lockUpdates && needsUpdate && path.length === 0) { - return this.update() - } - - if (path.length === 0) { - return - } - - this.updateNestedProp([...path, name], value) - }) - ) } } lockUpdates = false - this.update() + + if (path.length === 0 && shouldUpdate) this.update() + + return shouldUpdate } /** diff --git a/src/modules/simulation/constants.ts b/src/modules/simulation/constants.ts index 5d2f1df..6dc2827 100644 --- a/src/modules/simulation/constants.ts +++ b/src/modules/simulation/constants.ts @@ -1,6 +1,5 @@ -import { GateTemplate, Property, RawProp } from './types/GateTemplate' +import { GateTemplate, RawProp } from './types/GateTemplate' import { categories } from '../saving/data/categories' -import { getRendererSafely } from '../logic-gates/helpers/getRendererSafely' export const DefaultGateTemplate: GateTemplate = { metadata: { diff --git a/src/modules/storage/classes/LocalStore.ts b/src/modules/storage/classes/LocalStore.ts index 606b925..ec30aa3 100644 --- a/src/modules/storage/classes/LocalStore.ts +++ b/src/modules/storage/classes/LocalStore.ts @@ -1,59 +1,59 @@ export class LocalStore { - public constructor(public name: string) { - if (!localStorage.getItem(name)) { - localStorage.setItem(name, '{}') - } + public constructor(public name: string) { + if (!localStorage.getItem(name)) { + localStorage.setItem(name, '{}') + } + } + + public getAll(): Record { + const raw = localStorage.getItem(this.name) + + if (!raw) + throw new Error( + `An error occured when accesing ${this.name} in the local storage!` + ) + else { + return JSON.parse(raw) + } + } + + public ls(): string[] { + return Object.keys(this.getAll()) + } + + public *[Symbol.iterator](): Iterable { + for (const item of this.ls()) { + return this.get(item) + } + } + + public get(key = 'index'): T | undefined { + return this.getAll()[key] + } + + public set(key: string | T, value?: T) { + let finalKey = key as string + let finalValue = value as T + + if (typeof key !== 'string' || value === undefined) { + finalKey = 'index' + finalValue = key as T } - public getAll(): Record { - const raw = localStorage.getItem(this.name) + const currentData = this.getAll() - if (!raw) - throw new Error( - `An error occured when accesing ${this.name} in the local storage!` - ) - else { - return JSON.parse(raw) - } - } + currentData[finalKey] = finalValue + localStorage.setItem(this.name, JSON.stringify(currentData)) + } - public ls(): string[] { - return Object.keys(this.getAll()) - } + public delete(key = 'index') { + const all = this.getAll() + const last = all[key] - public *[Symbol.iterator](): Iterable { - for (const item of this.ls()) { - return this.get(item) - } - } + delete all[key] - public get(key = 'index'): T | undefined { - return this.getAll()[key] - } + localStorage.setItem(this.name, JSON.stringify(all)) - public set(key: string | T, value?: T) { - let finalKey = key as string - let finalValue = value as T - - if (typeof key !== 'string' || value === undefined) { - finalKey = 'index' - finalValue = key as T - } - - const currentData = this.getAll() - - currentData[finalKey] = finalValue - localStorage.setItem(this.name, JSON.stringify(currentData)) - } - - public delete(key = 'index') { - const all = this.getAll() - const last = all[key] - - delete all[key] - - localStorage.setItem(this.name, JSON.stringify(all)) - - return last - } + return last + } }