fixed rgb light, new info page
This commit is contained in:
parent
8a51c5ad52
commit
fddba4e55e
10
src/assets/comparator.svg
Normal file
10
src/assets/comparator.svg
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<svg width="800" height="800" viewBox="0 0 800 800" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="800" height="800" fill="#00B512"/>
|
||||||
|
<path d="M314 438H336.331M383.435 377L356.045 438H336.331M383.435 377H411M383.435 377H364.768L336.331 438" stroke="white" stroke-width="10"/>
|
||||||
|
<path d="M288 519.5V281L512 401L288 519.5Z" stroke="white" stroke-width="10"/>
|
||||||
|
<path d="M512.5 403H584.5" stroke="white" stroke-width="10"/>
|
||||||
|
<path d="M429 356H501" stroke="white" stroke-width="10"/>
|
||||||
|
<path d="M429 446H501" stroke="white" stroke-width="10"/>
|
||||||
|
<path d="M216 316H288" stroke="white" stroke-width="10"/>
|
||||||
|
<path d="M216 482H288" stroke="white" stroke-width="10"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 670 B |
7
src/assets/merger.svg
Normal file
7
src/assets/merger.svg
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<svg width="800" height="800" viewBox="0 0 800 800" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="800" height="800" fill="#DB00FF"/>
|
||||||
|
<path d="M352.11 400L283 492H312L386.5 400L312 308H283L352.11 400Z" fill="white"/>
|
||||||
|
<path d="M312 308H283L352.11 400L283 492H312M312 308H413.682C413.682 308 497.243 308 495.986 400C494.729 492 413.682 492 413.682 492H312M312 308L386.5 400L312 492" stroke="white" stroke-width="10"/>
|
||||||
|
<path d="M228 333H306.5M228 467.5H306.5" stroke="white" stroke-width="10"/>
|
||||||
|
<path d="M493.5 396H572M228 333H306.5M228 467.5H306.5" stroke="white" stroke-width="10"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 603 B |
7
src/assets/splitter.svg
Normal file
7
src/assets/splitter.svg
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<svg width="800" height="800" viewBox="0 0 800 800" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="800" height="800" transform="translate(800 800) rotate(-180)" fill="#DB00FF"/>
|
||||||
|
<path d="M447.89 400L517 308H488L413.5 400L488 492H517L447.89 400Z" fill="white"/>
|
||||||
|
<path d="M488 492H517L447.89 400L517 308H488M488 492H386.318C386.318 492 302.757 492 304.014 400C305.271 308 386.318 308 386.318 308H488M488 492L413.5 400L488 308" stroke="white" stroke-width="10"/>
|
||||||
|
<path d="M572 467H493.5M572 332.5H493.5" stroke="white" stroke-width="10"/>
|
||||||
|
<path d="M306.5 404H228M572 467H493.5M572 332.5H493.5" stroke="white" stroke-width="10"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 647 B |
7
src/common/lang/strings/firstCharUpperCase.ts
Normal file
7
src/common/lang/strings/firstCharUpperCase.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
/**
|
||||||
|
* Makes the first char of a string uppercase
|
||||||
|
*
|
||||||
|
* @param name The string to convert
|
||||||
|
*/
|
||||||
|
export const firstCharUpperCase = (name: string) =>
|
||||||
|
`${name[0].toUpperCase()}${name.substr(1)}`
|
|
@ -16,4 +16,5 @@ body {
|
||||||
background-color: $bg;
|
background-color: $bg;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import Root from './Root'
|
||||||
import LogicGatePage from '../../logic-gates/components/LogicGatesPage'
|
import LogicGatePage from '../../logic-gates/components/LogicGatesPage'
|
||||||
import { loadSubject } from '../subjects/loadedSubject'
|
import { loadSubject } from '../subjects/loadedSubject'
|
||||||
import { CustomRouter } from './CustomRouter'
|
import { CustomRouter } from './CustomRouter'
|
||||||
|
import LogicGateInfoPage from '../../logic-gate-info/components/LogicGateInfoPage'
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -33,6 +34,7 @@ const App = () => {
|
||||||
|
|
||||||
<Route path="/" component={Root} exact />
|
<Route path="/" component={Root} exact />
|
||||||
<Route path="/gates" component={LogicGatePage} />
|
<Route path="/gates" component={LogicGatePage} />
|
||||||
|
<Route path="/info/:name" component={LogicGateInfoPage} />
|
||||||
</CustomRouter>
|
</CustomRouter>
|
||||||
</Theme>
|
</Theme>
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,11 @@ const CreateSimulationButton = () => {
|
||||||
const translation = useTranslation()
|
const translation = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ListItem button className="contained" onClick={handleCreating}>
|
<ListItem
|
||||||
|
button
|
||||||
|
className="contained create-simulation"
|
||||||
|
onClick={handleCreating}
|
||||||
|
>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<Icon>note_add</Icon>
|
<Icon>note_add</Icon>
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
|
|
|
@ -9,16 +9,19 @@ import { useTranslation } from '../../internalisation/helpers/useLanguage'
|
||||||
export interface CreateSimulationOption {
|
export interface CreateSimulationOption {
|
||||||
mode: simulationMode
|
mode: simulationMode
|
||||||
icon: string
|
icon: string
|
||||||
|
id: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createSimulationOptions: CreateSimulationOption[] = [
|
export const createSimulationOptions: CreateSimulationOption[] = [
|
||||||
{
|
{
|
||||||
mode: 'project',
|
mode: 'project',
|
||||||
icon: 'gamepad'
|
icon: 'gamepad',
|
||||||
|
id: 'create-project'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'memory',
|
icon: 'memory',
|
||||||
mode: 'ic'
|
mode: 'ic',
|
||||||
|
id: 'create-ic'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -52,7 +55,10 @@ const CreateSimulation = () => {
|
||||||
CreateSimulationStore.actions.next('submit')
|
CreateSimulationStore.actions.next('submit')
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="create-option-icon">
|
<div
|
||||||
|
className={`create-option-icon ${option.id}`}
|
||||||
|
id={option.id}
|
||||||
|
>
|
||||||
<Icon>{option.icon}</Icon>
|
<Icon>{option.icon}</Icon>
|
||||||
</div>
|
</div>
|
||||||
<div className="create-option-name" id={option.mode}>
|
<div className="create-option-name" id={option.mode}>
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
@import '../../core/styles/mixins/flex.scss';
|
||||||
|
|
||||||
|
#logic-gate-info-page {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 12rem auto;
|
||||||
|
grid-template-rows: 15rem auto 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#logic-gate-info-page > * {
|
||||||
|
padding: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gate-info-top-right > #gate-info-title {
|
||||||
|
font-size: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gate-info-io-table {
|
||||||
|
@include flex();
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gate-info-io-table,
|
||||||
|
#gate-info-read-more {
|
||||||
|
grid-column: 1 / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gate-info-io-table-paper {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#gate-info-read-more > a {
|
||||||
|
color: #8888ff;
|
||||||
|
}
|
47
src/modules/logic-gate-info/components/LogicGateInfoPage.tsx
Normal file
47
src/modules/logic-gate-info/components/LogicGateInfoPage.tsx
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import React, { Fragment } from 'react'
|
||||||
|
import '../../logic-gates/components/GatePreview.scss'
|
||||||
|
import './LogicGateInfoPage.scss'
|
||||||
|
import { withRouter, Redirect } from 'react-router'
|
||||||
|
import GatePreview from '../../logic-gates/components/GatePreview'
|
||||||
|
import { getTemplateSafely } from '../../logic-gates/helpers/getTemplateSafely'
|
||||||
|
import { firstCharUpperCase } from '../../../common/lang/strings/firstCharUpperCase'
|
||||||
|
import { descriptions } from '../data/descriptions'
|
||||||
|
import LogicGateIoTable from './LogicGateIoTable'
|
||||||
|
|
||||||
|
export default withRouter(props => {
|
||||||
|
try {
|
||||||
|
const name = props.match.params.name.toLowerCase()
|
||||||
|
const template = getTemplateSafely(name)
|
||||||
|
const description = descriptions[name] || ''
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="page" id="logic-gate-info-page">
|
||||||
|
<div className="gate-preview">
|
||||||
|
<GatePreview template={template} />
|
||||||
|
</div>
|
||||||
|
<div id="gate-info-top-right">
|
||||||
|
<div id="gate-info-title">{firstCharUpperCase(name)}</div>
|
||||||
|
<div className="gate-info-description">{description}</div>
|
||||||
|
</div>
|
||||||
|
<div id="gate-info-io-table">
|
||||||
|
<LogicGateIoTable name={name} />
|
||||||
|
</div>
|
||||||
|
<div id="gate-info-read-more">
|
||||||
|
Read more: <br />
|
||||||
|
{template.info.map((url, index) => {
|
||||||
|
return (
|
||||||
|
<Fragment key={index}>
|
||||||
|
<a target="_blank" href={url}>
|
||||||
|
{url}
|
||||||
|
</a>
|
||||||
|
<br />
|
||||||
|
</Fragment>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
return <Redirect to="/gates" />
|
||||||
|
}
|
||||||
|
})
|
41
src/modules/logic-gate-info/components/LogicGateIoTable.tsx
Normal file
41
src/modules/logic-gate-info/components/LogicGateIoTable.tsx
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { ioTables } from '../data/tables'
|
||||||
|
import Table from '@material-ui/core/Table'
|
||||||
|
import TableBody from '@material-ui/core/TableBody'
|
||||||
|
import TableCell from '@material-ui/core/TableCell'
|
||||||
|
import TableHead from '@material-ui/core/TableHead'
|
||||||
|
import TableRow from '@material-ui/core/TableRow'
|
||||||
|
import Paper from '@material-ui/core/Paper'
|
||||||
|
|
||||||
|
export default ({ name }: { name: string }) => {
|
||||||
|
const ioTable = ioTables[name] || {}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper id="gate-info-io-table-paper">
|
||||||
|
<Table>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
{ioTable.columns.map((heading, index) => {
|
||||||
|
return <TableCell key={index}>{heading}</TableCell>
|
||||||
|
})}
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{ioTable.data.map((row, index) => {
|
||||||
|
return (
|
||||||
|
<TableRow key={index}>
|
||||||
|
{row.map((data, index) => {
|
||||||
|
return (
|
||||||
|
<TableCell key={index}>
|
||||||
|
{data}
|
||||||
|
</TableCell>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</TableRow>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</Paper>
|
||||||
|
)
|
||||||
|
}
|
51
src/modules/logic-gate-info/data/descriptions.ts
Normal file
51
src/modules/logic-gate-info/data/descriptions.ts
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
const carryExplanation = (half = true) => `
|
||||||
|
The carry out is necessary to preserve the bit count
|
||||||
|
(the maximum sum of 2 n-bit integers ${
|
||||||
|
half ? '' : 'and a carry'
|
||||||
|
} beeing 1 << (n + 1) - ${half ? 2 : 1})
|
||||||
|
`
|
||||||
|
|
||||||
|
export const descriptions: Record<string, string> = {
|
||||||
|
not: `
|
||||||
|
The not gate is one of the most basic logic gates.
|
||||||
|
It outputs the inverse of the input
|
||||||
|
`,
|
||||||
|
and: `
|
||||||
|
The and gate outputs true only if both inputs are true.
|
||||||
|
The and gate is the logic equivalent of f(x, y) = x * y
|
||||||
|
`,
|
||||||
|
or: `
|
||||||
|
The or gate outputs true if any of the inputs is true.
|
||||||
|
The or gate is the logic equivalent of f(x, y) = x + y - x * y
|
||||||
|
`,
|
||||||
|
nand: `
|
||||||
|
The nand gate only outputs true if none or one of the inputs is true.
|
||||||
|
The nand gate is the logic equivalent of f(x, y) = 1 - x * y
|
||||||
|
`,
|
||||||
|
nor: `
|
||||||
|
The nor gate only outputs true if none of the inputs is true.
|
||||||
|
The nor gate is the logic equivalent of f(x, y) = 1 + x * y - (x + y)
|
||||||
|
`,
|
||||||
|
xor: `
|
||||||
|
The xor gate (also known as the 'exclusive or' gate) only outputs true if one and only one of the inputs is true.
|
||||||
|
The xor gate is the logic equivalent of f(x, y) = x + y - 2 * x * y
|
||||||
|
`,
|
||||||
|
xnor: `
|
||||||
|
The xnor gate (also known as the 'not exlusive or' gate) only outputs true if none or both the inputs are true.
|
||||||
|
The xnor gate is the logic equivalent of f(x, y) = 1 - |x - y|
|
||||||
|
`,
|
||||||
|
'half adder': `
|
||||||
|
The half adder is used to add 2 numbers. It outputs a result and a carry.
|
||||||
|
${carryExplanation()}
|
||||||
|
The half adder is the logic equivalent of f(x, y) = { x + y - 2 * x * y, x * y }
|
||||||
|
`,
|
||||||
|
'full adder': `
|
||||||
|
The full adder is the building block for almos all math related circuit.
|
||||||
|
The full adder is used to add 2 number and a carry. It outputs a result and a carry.
|
||||||
|
${carryExplanation(false)}
|
||||||
|
The full adder is the logic equivalent of f(x, y, z) = {
|
||||||
|
x + y + z + 4 * x * y * z - 2 * (x * y + y * z + z * x),
|
||||||
|
x * y + y * z + z * x - 2 * x * y * z
|
||||||
|
}
|
||||||
|
`
|
||||||
|
}
|
59
src/modules/logic-gate-info/data/tables.ts
Normal file
59
src/modules/logic-gate-info/data/tables.ts
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
import {
|
||||||
|
allCombinations,
|
||||||
|
recursiveCombinations
|
||||||
|
} from '../../simulation/helpers/allCombinations'
|
||||||
|
|
||||||
|
const _2i1oColumns = ['Input A', 'Input B', 'Output']
|
||||||
|
|
||||||
|
const adderData = (half = true) => {
|
||||||
|
return recursiveCombinations([0, 1], half ? 2 : 3).map(combination => {
|
||||||
|
const a = combination[0] + combination[1] + (half ? 0 : combination[2])
|
||||||
|
|
||||||
|
return [...combination, Number(a % 2 === 1), Number(a >= 2)]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ioTables: Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
columns: string[]
|
||||||
|
data: number[][]
|
||||||
|
}
|
||||||
|
> = {
|
||||||
|
not: {
|
||||||
|
columns: ['Input', 'Output'],
|
||||||
|
data: [[0, 1], [1, 0]]
|
||||||
|
},
|
||||||
|
and: {
|
||||||
|
columns: _2i1oColumns,
|
||||||
|
data: [[0, 0, 0], [0, 1, 0], [1, 0, 0], [1, 1, 1]]
|
||||||
|
},
|
||||||
|
or: {
|
||||||
|
columns: _2i1oColumns,
|
||||||
|
data: [[0, 0, 0], [0, 1, 1], [1, 0, 1], [1, 1, 1]]
|
||||||
|
},
|
||||||
|
nor: {
|
||||||
|
columns: _2i1oColumns,
|
||||||
|
data: [[0, 0, 1], [0, 1, 0], [1, 0, 0], [1, 1, 0]]
|
||||||
|
},
|
||||||
|
nand: {
|
||||||
|
columns: _2i1oColumns,
|
||||||
|
data: [[0, 0, 1], [0, 1, 1], [1, 0, 1], [1, 1, 0]]
|
||||||
|
},
|
||||||
|
xor: {
|
||||||
|
columns: _2i1oColumns,
|
||||||
|
data: [[0, 0, 0], [0, 1, 1], [1, 0, 1], [1, 1, 0]]
|
||||||
|
},
|
||||||
|
xnor: {
|
||||||
|
columns: _2i1oColumns,
|
||||||
|
data: [[0, 0, 1], [0, 1, 0], [1, 0, 0], [1, 1, 1]]
|
||||||
|
},
|
||||||
|
'half adder': {
|
||||||
|
columns: ['x', 'y', 'sum', 'carry out'],
|
||||||
|
data: adderData()
|
||||||
|
},
|
||||||
|
'full adder': {
|
||||||
|
columns: ['carry in', 'x', 'y', 'sum', 'carry out'],
|
||||||
|
data: adderData(false)
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,23 +3,18 @@ import Icon from '@material-ui/core/Icon'
|
||||||
import IconButton from '@material-ui/core/IconButton'
|
import IconButton from '@material-ui/core/IconButton'
|
||||||
import { LogicGateProps } from '../types/LogicGateProps'
|
import { LogicGateProps } from '../types/LogicGateProps'
|
||||||
import { randomItem } from '../../internalisation/helpers/randomItem'
|
import { randomItem } from '../../internalisation/helpers/randomItem'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
|
||||||
const GateInfo = ({ template }: LogicGateProps) => {
|
const GateInfo = ({ name }: { name: string }) => {
|
||||||
const info = template.info
|
|
||||||
|
|
||||||
if (info.length === 0) {
|
|
||||||
return <></>
|
|
||||||
} else {
|
|
||||||
return (
|
return (
|
||||||
<div className="gate-info-icon">
|
<div className="gate-info-icon">
|
||||||
<a href={randomItem(info)} target="blank">
|
<Link to={`/info/${name}`}>
|
||||||
<IconButton aria-label="info">
|
<IconButton aria-label="info">
|
||||||
<Icon>info</Icon>
|
<Icon>info</Icon>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</a>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
export default GateInfo
|
export default GateInfo
|
||||||
|
|
8
src/modules/logic-gates/components/GatePreview.scss
Normal file
8
src/modules/logic-gates/components/GatePreview.scss
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
.gate-preview > * {
|
||||||
|
display: block;
|
||||||
|
height: 10em;
|
||||||
|
width: 10em;
|
||||||
|
border-radius: 1em;
|
||||||
|
|
||||||
|
margin: 1em;
|
||||||
|
}
|
|
@ -1,16 +1,8 @@
|
||||||
@import '../../core/styles/mixins/flex.scss';
|
@import '../../core/styles/mixins/flex.scss';
|
||||||
|
@import './GatePreview.scss';
|
||||||
|
|
||||||
$gate-margin: 1em;
|
$gate-margin: 1em;
|
||||||
|
|
||||||
.gate > section > .gate-preview > * {
|
|
||||||
display: block;
|
|
||||||
height: 10em;
|
|
||||||
width: 10em;
|
|
||||||
border-radius: 1em;
|
|
||||||
|
|
||||||
margin: $gate-margin;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gate:hover {
|
.gate:hover {
|
||||||
border: 2px solid white !important;
|
border: 2px solid white !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import './LogicGate.scss'
|
import './LogicGate.scss'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import GateInfo from './GateInfo'
|
import GateInfo from './GateInfo'
|
||||||
import GateSettings from './GateSettings'
|
|
||||||
import AddGate from './AddGate'
|
import AddGate from './AddGate'
|
||||||
import { addGateFromTemplate } from '../helpers/addGateFromTemplate'
|
import { addGateFromTemplate } from '../helpers/addGateFromTemplate'
|
||||||
import DeleteGateIcon from './DeleteGate'
|
import DeleteGateIcon from './DeleteGate'
|
||||||
import GatePreview from './GatePreview'
|
import GatePreview from './GatePreview'
|
||||||
import { LogicGateProps } from '../types/LogicGateProps'
|
import { LogicGateProps } from '../types/LogicGateProps'
|
||||||
|
import { firstCharUpperCase } from '../../../common/lang/strings/firstCharUpperCase'
|
||||||
|
|
||||||
const LogicGate = ({ template }: LogicGateProps) => {
|
const LogicGate = ({ template }: LogicGateProps) => {
|
||||||
const rawName = template.metadata.name
|
const rawName = template.metadata.name
|
||||||
const name = `${rawName[0].toUpperCase()}${rawName.substr(1)}`
|
const name = firstCharUpperCase(rawName)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="gate">
|
<div className="gate">
|
||||||
|
@ -27,8 +27,9 @@ const LogicGate = ({ template }: LogicGateProps) => {
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<div className="gate-icons">
|
<div className="gate-icons">
|
||||||
<GateInfo template={template} />
|
{!template.tags.includes('integrated') && (
|
||||||
{/* <GateSettings template={template} /> */}
|
<GateInfo name={name} />
|
||||||
|
)}
|
||||||
<AddGate template={template} />
|
<AddGate template={template} />
|
||||||
<DeleteGateIcon template={template} />
|
<DeleteGateIcon template={template} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -16,6 +16,9 @@ import halfAdderTemplate from './templates/halfAdder'
|
||||||
import fullAdderTemplate from './templates/fullAdder'
|
import fullAdderTemplate from './templates/fullAdder'
|
||||||
import _4bitEncoderTemplate from './templates/4bitEncoder'
|
import _4bitEncoderTemplate from './templates/4bitEncoder'
|
||||||
import _4bitDecoderTemplate from './templates/4bitDecoder'
|
import _4bitDecoderTemplate from './templates/4bitDecoder'
|
||||||
|
import comparatorTemplate from './templates/comparator'
|
||||||
|
import bitMergerTemplate from './templates/bitMerger'
|
||||||
|
import bitSplitterTemplate from './templates/bitSplitter'
|
||||||
|
|
||||||
export const defaultSimulationName = 'default'
|
export const defaultSimulationName = 'default'
|
||||||
export const baseTemplates: DeepPartial<GateTemplate>[] = [
|
export const baseTemplates: DeepPartial<GateTemplate>[] = [
|
||||||
|
@ -34,7 +37,10 @@ export const baseTemplates: DeepPartial<GateTemplate>[] = [
|
||||||
halfAdderTemplate,
|
halfAdderTemplate,
|
||||||
fullAdderTemplate,
|
fullAdderTemplate,
|
||||||
_4bitEncoderTemplate,
|
_4bitEncoderTemplate,
|
||||||
_4bitDecoderTemplate
|
_4bitDecoderTemplate,
|
||||||
|
comparatorTemplate,
|
||||||
|
bitMergerTemplate,
|
||||||
|
bitSplitterTemplate
|
||||||
// commentTemplate
|
// commentTemplate
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
31
src/modules/saving/templates/bitMerger.ts
Normal file
31
src/modules/saving/templates/bitMerger.ts
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import { PartialTemplate } from '../types/PartialTemplate'
|
||||||
|
import { categories } from '../data/categories'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The template of the bitMerger gate
|
||||||
|
*/
|
||||||
|
const bitMergerTemplate: PartialTemplate = {
|
||||||
|
metadata: {
|
||||||
|
name: 'bit merger'
|
||||||
|
},
|
||||||
|
pins: {
|
||||||
|
inputs: {
|
||||||
|
count: 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
code: {
|
||||||
|
activation: `
|
||||||
|
const a = context.get(0)
|
||||||
|
const b = context.get(1)
|
||||||
|
|
||||||
|
context.set(0, a + b)
|
||||||
|
`
|
||||||
|
},
|
||||||
|
category: categories.compressing,
|
||||||
|
material: {
|
||||||
|
type: 'image',
|
||||||
|
fill: require('../../../assets/merger')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default bitMergerTemplate
|
40
src/modules/saving/templates/bitSplitter.ts
Normal file
40
src/modules/saving/templates/bitSplitter.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import { PartialTemplate } from '../types/PartialTemplate'
|
||||||
|
import { categories } from '../data/categories'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The template of the bitSplitter gate
|
||||||
|
*/
|
||||||
|
const bitSplitterTemplate: PartialTemplate = {
|
||||||
|
metadata: {
|
||||||
|
name: 'bit splitter'
|
||||||
|
},
|
||||||
|
code: {
|
||||||
|
activation: `
|
||||||
|
const a = context.get(0)
|
||||||
|
const l = a.length + (a.length % 2 === 1)
|
||||||
|
const b = context.toLength(a, l)
|
||||||
|
const half = b.length / 2
|
||||||
|
|
||||||
|
const chunks = [
|
||||||
|
b.substr(0, half),
|
||||||
|
b.substr(half)
|
||||||
|
]
|
||||||
|
|
||||||
|
for (let index = 0; index < 2; index++ ) {
|
||||||
|
context.set(index, chunks[index])
|
||||||
|
}
|
||||||
|
`
|
||||||
|
},
|
||||||
|
material: {
|
||||||
|
type: 'image',
|
||||||
|
fill: require('../../../assets/splitter')
|
||||||
|
},
|
||||||
|
category: categories.compressing,
|
||||||
|
pins: {
|
||||||
|
outputs: {
|
||||||
|
count: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default bitSplitterTemplate
|
40
src/modules/saving/templates/comparator.ts
Normal file
40
src/modules/saving/templates/comparator.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import { PartialTemplate } from '../types/PartialTemplate'
|
||||||
|
import { categories } from '../data/categories'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The template of the comparator gate
|
||||||
|
*/
|
||||||
|
const comparatorTemplate: PartialTemplate = {
|
||||||
|
metadata: {
|
||||||
|
name: 'comparator'
|
||||||
|
},
|
||||||
|
info: ['https://www.technobyte.org/comparator/'],
|
||||||
|
category: categories.math,
|
||||||
|
code: {
|
||||||
|
activation: `
|
||||||
|
const a = context.getBinary(0)
|
||||||
|
const b = context.getBinary(1)
|
||||||
|
|
||||||
|
context.setBinary(0, Number(a > b))
|
||||||
|
context.setBinary(1, Number(a === b))
|
||||||
|
context.setBinary(2, Number(a < b))
|
||||||
|
`
|
||||||
|
},
|
||||||
|
pins: {
|
||||||
|
inputs: {
|
||||||
|
count: 2
|
||||||
|
},
|
||||||
|
outputs: {
|
||||||
|
count: 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
material: {
|
||||||
|
type: 'image',
|
||||||
|
fill: require('../../../assets/comparator.svg')
|
||||||
|
},
|
||||||
|
shape: {
|
||||||
|
scale: [125, 125]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default comparatorTemplate
|
|
@ -24,7 +24,12 @@ const fullAdderTemplate: PartialTemplate = {
|
||||||
count: 2
|
count: 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
category: categories.math
|
category: categories.math,
|
||||||
|
info: [
|
||||||
|
'https://www.elprocus.com/half-adder-and-full-adder/',
|
||||||
|
'https://en.wikipedia.org/wiki/Adder_(electronics)',
|
||||||
|
'https://www.geeksforgeeks.org/full-adder-digital-electronics/'
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default fullAdderTemplate
|
export default fullAdderTemplate
|
||||||
|
|
|
@ -24,7 +24,12 @@ const halfAdderTemplate: PartialTemplate = {
|
||||||
count: 2
|
count: 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
category: categories.math
|
category: categories.math,
|
||||||
|
info: [
|
||||||
|
'https://www.elprocus.com/half-adder-and-full-adder/',
|
||||||
|
'https://en.wikipedia.org/wiki/Adder_(electronics)',
|
||||||
|
'http://isweb.redwoods.edu/instruct/calderwoodd/diglogic/half-add.htm'
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default halfAdderTemplate
|
export default halfAdderTemplate
|
||||||
|
|
|
@ -22,7 +22,8 @@ const rgbLightTemplate: PartialTemplate = {
|
||||||
},
|
},
|
||||||
code: {
|
code: {
|
||||||
activation: `
|
activation: `
|
||||||
const color = (context.get(0) << 2) + (context.get(1) << 1) + context.get(2)
|
const get = (index) => context.getBinary(index) & 1
|
||||||
|
const color = (get(0) << 2) + (get(1) << 1) + get(2)
|
||||||
|
|
||||||
if (color === 0){
|
if (color === 0){
|
||||||
context.color(context.colors.main)
|
context.color(context.colors.main)
|
||||||
|
|
|
@ -6,3 +6,19 @@ export function* allCombinations<T>(first: T[], second: T[]): Iterable<[T, T]> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const recursiveCombinations = <T>(values: T[], depth = 2) => {
|
||||||
|
if (depth === 0) {
|
||||||
|
return [[]]
|
||||||
|
}
|
||||||
|
|
||||||
|
const combinations: T[][] = []
|
||||||
|
|
||||||
|
for (const value of values) {
|
||||||
|
for (const combination of recursiveCombinations(values, depth - 1)) {
|
||||||
|
combinations.push([value, ...combination])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return combinations
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue