diff --git a/README.md b/README.md index 66aa6f1..20e55d8 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Many thanks to: - Multiple simulations support - Integrated circuits - Multiple bits per pin -- Multiple language support: Romanian, English, Dutch & more in the future +- Multiple language support: Romanian, English, Dutch, Turkish, Chinese & more in the future ## Playing with the source diff --git a/src/common/lang/arrays/helpers/removeDuplicates.ts b/src/common/lang/arrays/helpers/removeDuplicates.ts index 1f7c2d5..71f0989 100644 --- a/src/common/lang/arrays/helpers/removeDuplicates.ts +++ b/src/common/lang/arrays/helpers/removeDuplicates.ts @@ -1,2 +1,7 @@ +/** + * Remoes al lduplicates from array + * + * @param array The array to remove duplicates from + */ export const removeDuplicates = (array: T[]): T[] => Array.from(new Set(array).values()) diff --git a/src/common/lang/errors/helpers/getSafeErrorStack.ts b/src/common/lang/errors/helpers/getSafeErrorStack.ts index 183aec7..e06491e 100644 --- a/src/common/lang/errors/helpers/getSafeErrorStack.ts +++ b/src/common/lang/errors/helpers/getSafeErrorStack.ts @@ -1,3 +1,8 @@ +/** + * Gets safe error stack from error + * + * @param error The error to get the safe erro stack from + */ export const getSafeErrorStack = (error: any) => { const errorString: string = error.toString() const stackString: string = error.stack diff --git a/src/common/math/classes/Transform.ts b/src/common/math/classes/Transform.ts index 33b7714..bda352c 100644 --- a/src/common/math/classes/Transform.ts +++ b/src/common/math/classes/Transform.ts @@ -1,10 +1,22 @@ import { allCombinations } from '../../../modules/simulation/helpers/allCombinations' import { BehaviorSubject } from 'rxjs' import { vector2 } from '../types/vector2' +import { vector4 } from '../types/vector4' export class Transform { + /** + * Gets the position as a subject + */ public positionSubject = new BehaviorSubject([0, 0]) + /** + * Class used to represend the position scale and rotation + * of a body in 2d space + * + * @param _position The initial position + * @param scale The initial scale + * @param rotation The initial scale of the object + */ public constructor( public _position: vector2 = [0, 0], public scale: vector2 = [1, 1], @@ -13,12 +25,18 @@ export class Transform { this.updatePositionSubject() } + /** + * Gets the boundng box of the transform + */ public getBoundingBox() { const result = [...this.position, ...this.scale] as vector4 return result } + /** + * Gets an array of all points in the transform + */ public getPoints() { const combinations = Array.from(allCombinations([0, 1], [0, 1])) @@ -31,17 +49,6 @@ export class Transform { return points as vector2[] } - public getEdges() { - const points = this.getPoints() - const edges = [] - - for (let index = 0; index < points.length; index++) { - edges.push([points[index], points[(index + 1) % points.length]]) - } - - return edges as [vector2, vector2][] - } - /** * Pushes the current position trough the position subject */ @@ -65,74 +72,106 @@ export class Transform { this.updatePositionSubject() } - /** Short forms for random stuff */ - + /** + * The first element of the position vector + */ get x() { return this.position[0] } + /** + * The second element of the position vector + */ get y() { return this.position[1] } + /** + * The first element of the scale vector + */ get width() { return this.scale[0] } + /** + * The second element of the scale vector + */ get height() { return this.scale[1] } + /** + * The minimum x position of the buonding box + */ get minX() { return Math.min(this.x, this.x + this.width) } + /** + * The maximum x position of the bounding box + */ get maxX() { return Math.max(this.x, this.x + this.width) } + /** + * The minimum y position of the buonding box + */ get minY() { return Math.min(this.y, this.y + this.height) } + /** + * The maximum y position of the buonding box + */ get maxY() { return Math.max(this.y, this.y + this.height) } + /** + * The center of the bounding box + */ get center() { return [this.x + this.width / 2, this.y + this.height / 2] as vector2 } + /** + * Sets the first element of the position vector + * + * @param value The value to set x to + */ set x(value: number) { this.position = [value, this.y] this.updatePositionSubject() } + /** + * Sets the second element of the position vector + * + * @param value The value to set y to + */ set y(value: number) { this.position = [this.x, value] this.updatePositionSubject() } + /** + * Sets the first element of the scale vector + * + * @param value The value to set the width to + */ set width(value: number) { this.scale = [value, this.height] } + /** + * Sets the second element of the scale vector + * + * @param value The value to set the height to + */ set height(value: number) { this.scale = [this.width, value] } } - -export type vector3 = [number, number, number] -export type vector4 = [number, number, number, number] -export type vector8 = [ - number, - number, - number, - number, - number, - number, - number, - number -] diff --git a/src/index.html b/src/index.html index 112bb03..8af508a 100644 --- a/src/index.html +++ b/src/index.html @@ -10,14 +10,20 @@ ondrop="return false;" oncontextmenu="return false" > +
+ +
+
+ +
diff --git a/src/index.ts b/src/index.ts index 4b257bc..e46a089 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,27 +1,40 @@ import { Splash } from './modules/splash/classes/Splash' +/** + * The function wich is run when the app is loaded + */ async function main() { + // Create splash screen variable let splash: Splash | undefined = undefined try { + // instantiate splash screen splash = new Splash() } catch {} try { + // import main app const app = await import('./main') + // wait for app to start await app.start() } catch (error) { + // show the error to the client if (splash) splash.setError(error) + + // log the error to the console console.error(error.stack || error) return } + // hide splash screen if it exists if (splash) { splash.fade() } } +// Call entry main().catch(error => { + // if the error handling error has an error, log that error console.error('Error loading app', error) }) diff --git a/src/main.tsx b/src/main.tsx index e4a9244..886b5b6 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -11,7 +11,11 @@ import { logWelcome } from './modules/core/helpers/logWelcome' import { initRenderer } from './modules/simulationRenderer/helpers/initRenderer' import { updateLogicGateList } from './modules/logic-gates/subjects/LogicGateList' +/** + * The function wich does the heavy lifting for starting the app + */ export const start = async () => { + // This will resolve at the first render const result = loadSubject .pipe( filter(a => a), @@ -19,14 +23,27 @@ export const start = async () => { ) .toPromise() + // Handle possible errors handleErrors() + + // Create main renderer for the app initRenderer() + + // Register key bindings initKeyBindings() + + // Update base templates initBaseTemplates() + + // Easter egg logWelcome() + + // Update the logic gates in local storage updateLogicGateList() + // Render app component render(, document.getElementById('app')) + // wait for the first render await result } diff --git a/src/modules/internalisation/constants.ts b/src/modules/internalisation/constants.ts index 42e19b6..3ad8061 100644 --- a/src/modules/internalisation/constants.ts +++ b/src/modules/internalisation/constants.ts @@ -3,6 +3,8 @@ import { Translation } from './types/TranslationInterface' import { EnglishTranslation } from './translations/english' import { RomanianTranslation } from './translations/romanian' import { DutchTranslation } from './translations/nederlands' +import { MandarinTranslation } from './translations/chinese' +import { TurkishTranslation } from './translations/turkish' /** * Object with all translations @@ -10,11 +12,15 @@ import { DutchTranslation } from './translations/nederlands' export const translations: Record = { english: EnglishTranslation, ['română']: RomanianTranslation, - dutch: DutchTranslation + dutch: DutchTranslation, + ['中文']: MandarinTranslation, + ['türkçe']: TurkishTranslation } export const allSupportedLanguages: supportedLanguage[] = [ 'english', 'română', - 'dutch' + 'dutch', + '中文', + 'türkçe' ] diff --git a/src/modules/internalisation/translations/chinese.ts b/src/modules/internalisation/translations/chinese.ts new file mode 100644 index 0000000..21a6f79 --- /dev/null +++ b/src/modules/internalisation/translations/chinese.ts @@ -0,0 +1,53 @@ +import { Translation } from '../types/TranslationInterface' + +/** + * The enaglish translation + */ +export const MandarinTranslation: Translation = { + language: '中文', + sidebar: { + createSimulation: '创作', + logicGates: '逻辑门', + openSimulation: '打开模拟', + simulation: '模拟', + language: '语言', + backToSimulation: '回到模拟', + backToGates: '回到逻辑门' + }, + createSimulation: { + mode: { + question: '你想要创造什么样的模拟?', + options: { + ic: '集成电路', + project: '项目' + } + }, + name: { + question: '你希望你的模拟交什么?' + } + }, + actions: { + save: '存盘', + clean: '清理', + refresh: '刷新', + undo: '消除', + paste: '粘贴', + copy: '重做', + duplicate: '复制', + cut: '剪切', + 'select all': '全选', + 'delete selection': '删去选着', + 'delete simulation': '删去模拟' + }, + messages: { + createdSimulation: name => `成功创建了模拟 '${name}'`, + switchedToSimulation: name => `成功切换到模拟 '${name}'`, + savedSimulation: name => `成功存盘了模拟 '${name}'`, + compiledIc: name => `成功编译了电路 '${name}'`, + cleaned: name => `成功清理了模拟 '${name}'`, + refreshed: name => `成功刷新了模拟 '${name}'`, + undone: name => `成功消除了模拟 '${name}'`, + deletedSimulation: name => `成功删去了模拟 '${name}'`, + addedGate: name => `成功加了逻辑门 '${name}'` + } +} diff --git a/src/modules/internalisation/translations/nederlands.ts b/src/modules/internalisation/translations/nederlands.ts index 6a87a42..5c75917 100644 --- a/src/modules/internalisation/translations/nederlands.ts +++ b/src/modules/internalisation/translations/nederlands.ts @@ -9,23 +9,23 @@ export const DutchTranslation: Translation = { createSimulation: 'Maak simulatie', logicGates: 'Logische poorten', openSimulation: 'Open simulatie', - simulation: 'Todo', + simulation: 'Simulatie', language: 'Taal', - backToSimulation: 'Todo', - backToGates: 'Todo' + backToSimulation: 'Terug naar simulatie', + backToGates: 'Terug naar poorten' }, actions: { - 'delete selection': 'Todo', - 'select all': 'Todo', - clean: 'Todo', - refresh: 'Todo', - save: 'Todo', - undo: 'Todo', - 'delete simulation': `Todo`, - copy: 'Todo', - cut: 'Todo', - duplicate: 'Todo', - paste: 'Todo' + 'delete selection': 'Delete selectie', + 'select all': 'Selecteer alles', + clean: 'Verwijder', + refresh: 'Ververs', + save: 'opslaan', + undo: 'ongedaan maken', + 'delete simulation': 'Delete simulatie', + copy: 'Kopieer', + cut: 'Knippen', + duplicate: 'Dupliceer', + paste: 'Plak' }, createSimulation: { mode: { @@ -44,12 +44,12 @@ export const DutchTranslation: Translation = { createdSimulation: name => `Simulatie '${name}' succesvol gecreerd`, switchedToSimulation: name => `Succesvol veranderd naar simulatie '${name}'`, - savedSimulation: name => `Simulatie succesvol opgeslagen '${name}'`, - compiledIc: name => `IC gecompileerd: ${name}`, - cleaned: name => `${name} gewist`, - refreshed: name => `${name} ververst`, - undone: name => `${name} ongedaan gemaakt`, - deletedSimulation: name => `Todo`, - addedGate: name => 'Todo' + savedSimulation: name => "Simulatie succesvol opgeslagen '${name}'", + compiledIc: name => "IC gecompileerd: '${name}'", + cleaned: name => `'${name}' gewist`, + refreshed: name => `'${name}' ververst`, + undone: name => `'${name}' ongedaan gemaakt`, + deletedSimulation: name => `Simulatie '${name}' verwijderd`, + addedGate: name => `Poort '${name}' toegevoegd` } } diff --git a/src/modules/internalisation/translations/turkish.ts b/src/modules/internalisation/translations/turkish.ts new file mode 100644 index 0000000..fb88acd --- /dev/null +++ b/src/modules/internalisation/translations/turkish.ts @@ -0,0 +1,53 @@ +import { Translation } from '../types/TranslationInterface' + +/** + * The enaglish translation + */ +export const TurkishTranslation: Translation = { + language: 'türkçe', + sidebar: { + createSimulation: 'defter yaziyor', + logicGates: 'kapilar', + openSimulation: 'defter açiyor', + simulation: 'defter', + language: 'dil', + backToSimulation: "defter'e geri dön", + backToGates: 'kapilara geri dön' + }, + createSimulation: { + mode: { + question: 'bu defter türü ne?', + options: { + ic: 'defter gibi kapi', + project: 'Proje' + } + }, + name: { + question: 'bu defter ad ne?' + } + }, + actions: { + save: 'kayit', + clean: 'temizleyor', + refresh: 'feranlatiyor', + undo: 'geri almc', + paste: 'yapistirıyor', + copy: 'tuturuyor', + duplicate: 'klonuyor', + cut: 'kırpıyor', + 'select all': 'seç her şey', + 'delete selection': 'seçım siliyor', + 'delete simulation': 'Defter siliyor' + }, + messages: { + createdSimulation: name => `dizüstü çizdi '${name}'`, + switchedToSimulation: name => `açılan not defteri'${name}'`, + savedSimulation: name => `kaydedilmiş defter '${name}'`, + compiledIc: name => `derlenmiş kapı '${name}'`, + cleaned: name => `temizlenmiş defter '${name}'`, + refreshed: name => `yenilenmiş defter '${name}'`, + undone: name => `geri alındı '${name}'`, + deletedSimulation: name => `silinmiş defter '${name}'`, + addedGate: name => `eklenen kapı '${name}'` + } +} diff --git a/src/modules/internalisation/types/supportedLanguages.ts b/src/modules/internalisation/types/supportedLanguages.ts index 2e348c5..b7cc0b4 100644 --- a/src/modules/internalisation/types/supportedLanguages.ts +++ b/src/modules/internalisation/types/supportedLanguages.ts @@ -1,4 +1,9 @@ -/** +/** * Type containing the names of all supported languages */ -export type supportedLanguage = 'română' | 'english' | 'dutch' +export type supportedLanguage = + | 'română' + | 'english' + | 'dutch' + | '中文' + | 'türkçe' diff --git a/src/modules/saving/templates/bitMerger.ts b/src/modules/saving/templates/bitMerger.ts index 83e5c0f..b5a14bd 100644 --- a/src/modules/saving/templates/bitMerger.ts +++ b/src/modules/saving/templates/bitMerger.ts @@ -18,7 +18,7 @@ const bitMergerTemplate: PartialTemplate = { const a = context.get(0) const b = context.get(1) - context.set(0, a + b) + context.set(0, b + a) ` }, category: categories.compressing, diff --git a/src/modules/saving/templates/bitSplitter.ts b/src/modules/saving/templates/bitSplitter.ts index a1b981d..4465b58 100644 --- a/src/modules/saving/templates/bitSplitter.ts +++ b/src/modules/saving/templates/bitSplitter.ts @@ -21,7 +21,7 @@ const bitSplitterTemplate: PartialTemplate = { ] for (let index = 0; index < 2; index++ ) { - context.set(index, chunks[index]) + context.set(index, chunks[1 - index]) } ` }, diff --git a/src/modules/simulationRenderer/helpers/aabb.ts b/src/modules/simulationRenderer/helpers/aabb.ts index b23fc78..8cd1eba 100644 --- a/src/modules/simulationRenderer/helpers/aabb.ts +++ b/src/modules/simulationRenderer/helpers/aabb.ts @@ -1,5 +1,11 @@ import { Transform } from '../../../common/math/classes/Transform' +/** + * Checks collision between 2 rects + * + * @param rect1 The first rect + * @param rect2 The second rect + */ export const aabbCollisionDetection = (rect1: Transform, rect2: Transform) => { return !( rect1.maxX < rect2.minX || diff --git a/src/server.ts b/src/server.ts index 2b341ff..fc9d7d3 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,12 +1,16 @@ import express, { static as _static } from 'express' import { resolve } from 'path' +// create express app const app = express() +// serve static assets app.use(_static(__dirname)) +// serve single page application app.get('*', (rex, res) => { res.sendFile(resolve(__dirname, 'index.html')) }) +// listen to the port from .env (default to 8080) app.listen(process.env.PORT || 8080)