addes chinese and turkish
This commit is contained in:
parent
2e1a45fe19
commit
5f77e15b18
|
@ -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
|
||||
|
||||
|
|
|
@ -1,2 +1,7 @@
|
|||
/**
|
||||
* Remoes al lduplicates from array
|
||||
*
|
||||
* @param array The array to remove duplicates from
|
||||
*/
|
||||
export const removeDuplicates = <T>(array: T[]): T[] =>
|
||||
Array.from(new Set<T>(array).values())
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<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 _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
|
||||
]
|
||||
|
|
|
@ -10,14 +10,20 @@
|
|||
ondrop="return false;"
|
||||
oncontextmenu="return false"
|
||||
>
|
||||
<!--The react app is rendered here-->
|
||||
<div id="app"></div>
|
||||
|
||||
<!--The splash screen structure-->
|
||||
<div class="Splash">
|
||||
<!--Loading animation-->
|
||||
<div class="loading">
|
||||
<div class="lds-ripple">
|
||||
<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>
|
||||
</div>
|
||||
</body>
|
||||
|
|
13
src/index.ts
13
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)
|
||||
})
|
||||
|
|
17
src/main.tsx
17
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(<App />, document.getElementById('app'))
|
||||
|
||||
// wait for the first render
|
||||
await result
|
||||
}
|
||||
|
|
|
@ -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<supportedLanguage, Translation> = {
|
||||
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'
|
||||
]
|
||||
|
|
53
src/modules/internalisation/translations/chinese.ts
Normal file
53
src/modules/internalisation/translations/chinese.ts
Normal 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}'`
|
||||
}
|
||||
}
|
|
@ -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`
|
||||
}
|
||||
}
|
||||
|
|
53
src/modules/internalisation/translations/turkish.ts
Normal file
53
src/modules/internalisation/translations/turkish.ts
Normal 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 => `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}'`
|
||||
}
|
||||
}
|
|
@ -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'
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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])
|
||||
}
|
||||
`
|
||||
},
|
||||
|
|
|
@ -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 ||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue