addes chinese and turkish

This commit is contained in:
Matei Adriel 2019-08-04 00:55:22 +03:00
parent 2e1a45fe19
commit 5f77e15b18
16 changed files with 266 additions and 54 deletions

View file

@ -23,7 +23,7 @@ Many thanks to:
- Multiple simulations support - Multiple simulations support
- Integrated circuits - Integrated circuits
- Multiple bits per pin - 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 ## Playing with the source

View file

@ -1,2 +1,7 @@
/**
* Remoes al lduplicates from array
*
* @param array The array to remove duplicates from
*/
export const removeDuplicates = <T>(array: T[]): T[] => export const removeDuplicates = <T>(array: T[]): T[] =>
Array.from(new Set<T>(array).values()) Array.from(new Set<T>(array).values())

View file

@ -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) => { export const getSafeErrorStack = (error: any) => {
const errorString: string = error.toString() const errorString: string = error.toString()
const stackString: string = error.stack const stackString: string = error.stack

View file

@ -1,10 +1,22 @@
import { allCombinations } from '../../../modules/simulation/helpers/allCombinations' import { allCombinations } from '../../../modules/simulation/helpers/allCombinations'
import { BehaviorSubject } from 'rxjs' import { BehaviorSubject } from 'rxjs'
import { vector2 } from '../types/vector2' import { vector2 } from '../types/vector2'
import { vector4 } from '../types/vector4'
export class Transform { export class Transform {
/**
* Gets the position as a subject
*/
public positionSubject = new BehaviorSubject<vector2>([0, 0]) public positionSubject = new BehaviorSubject<vector2>([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 constructor(
public _position: vector2 = [0, 0], public _position: vector2 = [0, 0],
public scale: vector2 = [1, 1], public scale: vector2 = [1, 1],
@ -13,12 +25,18 @@ export class Transform {
this.updatePositionSubject() this.updatePositionSubject()
} }
/**
* Gets the boundng box of the transform
*/
public getBoundingBox() { public getBoundingBox() {
const result = [...this.position, ...this.scale] as vector4 const result = [...this.position, ...this.scale] as vector4
return result return result
} }
/**
* Gets an array of all points in the transform
*/
public getPoints() { public getPoints() {
const combinations = Array.from(allCombinations([0, 1], [0, 1])) const combinations = Array.from(allCombinations([0, 1], [0, 1]))
@ -31,17 +49,6 @@ export class Transform {
return points as vector2[] 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 * Pushes the current position trough the position subject
*/ */
@ -65,74 +72,106 @@ export class Transform {
this.updatePositionSubject() this.updatePositionSubject()
} }
/** Short forms for random stuff */ /**
* The first element of the position vector
*/
get x() { get x() {
return this.position[0] return this.position[0]
} }
/**
* The second element of the position vector
*/
get y() { get y() {
return this.position[1] return this.position[1]
} }
/**
* The first element of the scale vector
*/
get width() { get width() {
return this.scale[0] return this.scale[0]
} }
/**
* The second element of the scale vector
*/
get height() { get height() {
return this.scale[1] return this.scale[1]
} }
/**
* The minimum x position of the buonding box
*/
get minX() { get minX() {
return Math.min(this.x, this.x + this.width) return Math.min(this.x, this.x + this.width)
} }
/**
* The maximum x position of the bounding box
*/
get maxX() { get maxX() {
return Math.max(this.x, this.x + this.width) return Math.max(this.x, this.x + this.width)
} }
/**
* The minimum y position of the buonding box
*/
get minY() { get minY() {
return Math.min(this.y, this.y + this.height) return Math.min(this.y, this.y + this.height)
} }
/**
* The maximum y position of the buonding box
*/
get maxY() { get maxY() {
return Math.max(this.y, this.y + this.height) return Math.max(this.y, this.y + this.height)
} }
/**
* The center of the bounding box
*/
get center() { get center() {
return [this.x + this.width / 2, this.y + this.height / 2] as vector2 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) { set x(value: number) {
this.position = [value, this.y] this.position = [value, this.y]
this.updatePositionSubject() this.updatePositionSubject()
} }
/**
* Sets the second element of the position vector
*
* @param value The value to set y to
*/
set y(value: number) { set y(value: number) {
this.position = [this.x, value] this.position = [this.x, value]
this.updatePositionSubject() this.updatePositionSubject()
} }
/**
* Sets the first element of the scale vector
*
* @param value The value to set the width to
*/
set width(value: number) { set width(value: number) {
this.scale = [value, this.height] 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) { set height(value: number) {
this.scale = [this.width, value] 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
]

View file

@ -10,14 +10,20 @@
ondrop="return false;" ondrop="return false;"
oncontextmenu="return false" oncontextmenu="return false"
> >
<!--The react app is rendered here-->
<div id="app"></div> <div id="app"></div>
<!--The splash screen structure-->
<div class="Splash"> <div class="Splash">
<!--Loading animation-->
<div class="loading"> <div class="loading">
<div class="lds-ripple"> <div class="lds-ripple">
<div></div> <div></div>
<div></div> <div></div>
</div> </div>
</div> </div>
<!--In case someone tries to laod this with js disabled-->
<noscript> JavaScript must be enabled to run this app. </noscript> <noscript> JavaScript must be enabled to run this app. </noscript>
</div> </div>
</body> </body>

View file

@ -1,27 +1,40 @@
import { Splash } from './modules/splash/classes/Splash' import { Splash } from './modules/splash/classes/Splash'
/**
* The function wich is run when the app is loaded
*/
async function main() { async function main() {
// Create splash screen variable
let splash: Splash | undefined = undefined let splash: Splash | undefined = undefined
try { try {
// instantiate splash screen
splash = new Splash() splash = new Splash()
} catch {} } catch {}
try { try {
// import main app
const app = await import('./main') const app = await import('./main')
// wait for app to start
await app.start() await app.start()
} catch (error) { } catch (error) {
// show the error to the client
if (splash) splash.setError(error) if (splash) splash.setError(error)
// log the error to the console
console.error(error.stack || error) console.error(error.stack || error)
return return
} }
// hide splash screen if it exists
if (splash) { if (splash) {
splash.fade() splash.fade()
} }
} }
// Call entry
main().catch(error => { main().catch(error => {
// if the error handling error has an error, log that error
console.error('Error loading app', error) console.error('Error loading app', error)
}) })

View file

@ -11,7 +11,11 @@ import { logWelcome } from './modules/core/helpers/logWelcome'
import { initRenderer } from './modules/simulationRenderer/helpers/initRenderer' import { initRenderer } from './modules/simulationRenderer/helpers/initRenderer'
import { updateLogicGateList } from './modules/logic-gates/subjects/LogicGateList' import { updateLogicGateList } from './modules/logic-gates/subjects/LogicGateList'
/**
* The function wich does the heavy lifting for starting the app
*/
export const start = async () => { export const start = async () => {
// This will resolve at the first render
const result = loadSubject const result = loadSubject
.pipe( .pipe(
filter(a => a), filter(a => a),
@ -19,14 +23,27 @@ export const start = async () => {
) )
.toPromise() .toPromise()
// Handle possible errors
handleErrors() handleErrors()
// Create main renderer for the app
initRenderer() initRenderer()
// Register key bindings
initKeyBindings() initKeyBindings()
// Update base templates
initBaseTemplates() initBaseTemplates()
// Easter egg
logWelcome() logWelcome()
// Update the logic gates in local storage
updateLogicGateList() updateLogicGateList()
// Render app component
render(<App />, document.getElementById('app')) render(<App />, document.getElementById('app'))
// wait for the first render
await result await result
} }

View file

@ -3,6 +3,8 @@ import { Translation } from './types/TranslationInterface'
import { EnglishTranslation } from './translations/english' import { EnglishTranslation } from './translations/english'
import { RomanianTranslation } from './translations/romanian' import { RomanianTranslation } from './translations/romanian'
import { DutchTranslation } from './translations/nederlands' import { DutchTranslation } from './translations/nederlands'
import { MandarinTranslation } from './translations/chinese'
import { TurkishTranslation } from './translations/turkish'
/** /**
* Object with all translations * Object with all translations
@ -10,11 +12,15 @@ import { DutchTranslation } from './translations/nederlands'
export const translations: Record<supportedLanguage, Translation> = { export const translations: Record<supportedLanguage, Translation> = {
english: EnglishTranslation, english: EnglishTranslation,
['română']: RomanianTranslation, ['română']: RomanianTranslation,
dutch: DutchTranslation dutch: DutchTranslation,
['中文']: MandarinTranslation,
['türkçe']: TurkishTranslation
} }
export const allSupportedLanguages: supportedLanguage[] = [ export const allSupportedLanguages: supportedLanguage[] = [
'english', 'english',
'română', 'română',
'dutch' 'dutch',
'中文',
'türkçe'
] ]

View file

@ -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}'`
}
}

View file

@ -9,23 +9,23 @@ export const DutchTranslation: Translation = {
createSimulation: 'Maak simulatie', createSimulation: 'Maak simulatie',
logicGates: 'Logische poorten', logicGates: 'Logische poorten',
openSimulation: 'Open simulatie', openSimulation: 'Open simulatie',
simulation: 'Todo', simulation: 'Simulatie',
language: 'Taal', language: 'Taal',
backToSimulation: 'Todo', backToSimulation: 'Terug naar simulatie',
backToGates: 'Todo' backToGates: 'Terug naar poorten'
}, },
actions: { actions: {
'delete selection': 'Todo', 'delete selection': 'Delete selectie',
'select all': 'Todo', 'select all': 'Selecteer alles',
clean: 'Todo', clean: 'Verwijder',
refresh: 'Todo', refresh: 'Ververs',
save: 'Todo', save: 'opslaan',
undo: 'Todo', undo: 'ongedaan maken',
'delete simulation': `Todo`, 'delete simulation': 'Delete simulatie',
copy: 'Todo', copy: 'Kopieer',
cut: 'Todo', cut: 'Knippen',
duplicate: 'Todo', duplicate: 'Dupliceer',
paste: 'Todo' paste: 'Plak'
}, },
createSimulation: { createSimulation: {
mode: { mode: {
@ -44,12 +44,12 @@ export const DutchTranslation: Translation = {
createdSimulation: name => `Simulatie '${name}' succesvol gecreerd`, createdSimulation: name => `Simulatie '${name}' succesvol gecreerd`,
switchedToSimulation: name => switchedToSimulation: name =>
`Succesvol veranderd naar simulatie '${name}'`, `Succesvol veranderd naar simulatie '${name}'`,
savedSimulation: name => `Simulatie succesvol opgeslagen '${name}'`, savedSimulation: name => "Simulatie succesvol opgeslagen '${name}'",
compiledIc: name => `IC gecompileerd: ${name}`, compiledIc: name => "IC gecompileerd: '${name}'",
cleaned: name => `${name} gewist`, cleaned: name => `'${name}' gewist`,
refreshed: name => `${name} ververst`, refreshed: name => `'${name}' ververst`,
undone: name => `${name} ongedaan gemaakt`, undone: name => `'${name}' ongedaan gemaakt`,
deletedSimulation: name => `Todo`, deletedSimulation: name => `Simulatie '${name}' verwijderd`,
addedGate: name => 'Todo' addedGate: name => `Poort '${name}' toegevoegd`
} }
} }

View file

@ -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 => `ı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}'`
}
}

View file

@ -1,4 +1,9 @@
/** /**
* Type containing the names of all supported languages * 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'

View file

@ -18,7 +18,7 @@ const bitMergerTemplate: PartialTemplate = {
const a = context.get(0) const a = context.get(0)
const b = context.get(1) const b = context.get(1)
context.set(0, a + b) context.set(0, b + a)
` `
}, },
category: categories.compressing, category: categories.compressing,

View file

@ -21,7 +21,7 @@ const bitSplitterTemplate: PartialTemplate = {
] ]
for (let index = 0; index < 2; index++ ) { for (let index = 0; index < 2; index++ ) {
context.set(index, chunks[index]) context.set(index, chunks[1 - index])
} }
` `
}, },

View file

@ -1,5 +1,11 @@
import { Transform } from '../../../common/math/classes/Transform' 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) => { export const aabbCollisionDetection = (rect1: Transform, rect2: Transform) => {
return !( return !(
rect1.maxX < rect2.minX || rect1.maxX < rect2.minX ||

View file

@ -1,12 +1,16 @@
import express, { static as _static } from 'express' import express, { static as _static } from 'express'
import { resolve } from 'path' import { resolve } from 'path'
// create express app
const app = express() const app = express()
// serve static assets
app.use(_static(__dirname)) app.use(_static(__dirname))
// serve single page application
app.get('*', (rex, res) => { app.get('*', (rex, res) => {
res.sendFile(resolve(__dirname, 'index.html')) res.sendFile(resolve(__dirname, 'index.html'))
}) })
// listen to the port from .env (default to 8080)
app.listen(process.env.PORT || 8080) app.listen(process.env.PORT || 8080)