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;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
color: white;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import Root from './Root'
|
|||
import LogicGatePage from '../../logic-gates/components/LogicGatesPage'
|
||||
import { loadSubject } from '../subjects/loadedSubject'
|
||||
import { CustomRouter } from './CustomRouter'
|
||||
import LogicGateInfoPage from '../../logic-gate-info/components/LogicGateInfoPage'
|
||||
|
||||
const App = () => {
|
||||
useEffect(() => {
|
||||
|
@ -33,6 +34,7 @@ const App = () => {
|
|||
|
||||
<Route path="/" component={Root} exact />
|
||||
<Route path="/gates" component={LogicGatePage} />
|
||||
<Route path="/info/:name" component={LogicGateInfoPage} />
|
||||
</CustomRouter>
|
||||
</Theme>
|
||||
|
||||
|
|
|
@ -16,7 +16,11 @@ const CreateSimulationButton = () => {
|
|||
const translation = useTranslation()
|
||||
|
||||
return (
|
||||
<ListItem button className="contained" onClick={handleCreating}>
|
||||
<ListItem
|
||||
button
|
||||
className="contained create-simulation"
|
||||
onClick={handleCreating}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<Icon>note_add</Icon>
|
||||
</ListItemIcon>
|
||||
|
|
|
@ -9,16 +9,19 @@ import { useTranslation } from '../../internalisation/helpers/useLanguage'
|
|||
export interface CreateSimulationOption {
|
||||
mode: simulationMode
|
||||
icon: string
|
||||
id: string
|
||||
}
|
||||
|
||||
export const createSimulationOptions: CreateSimulationOption[] = [
|
||||
{
|
||||
mode: 'project',
|
||||
icon: 'gamepad'
|
||||
icon: 'gamepad',
|
||||
id: 'create-project'
|
||||
},
|
||||
{
|
||||
icon: 'memory',
|
||||
mode: 'ic'
|
||||
mode: 'ic',
|
||||
id: 'create-ic'
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -52,7 +55,10 @@ const CreateSimulation = () => {
|
|||
CreateSimulationStore.actions.next('submit')
|
||||
}}
|
||||
>
|
||||
<div className="create-option-icon">
|
||||
<div
|
||||
className={`create-option-icon ${option.id}`}
|
||||
id={option.id}
|
||||
>
|
||||
<Icon>{option.icon}</Icon>
|
||||
</div>
|
||||
<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 { LogicGateProps } from '../types/LogicGateProps'
|
||||
import { randomItem } from '../../internalisation/helpers/randomItem'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
const GateInfo = ({ template }: LogicGateProps) => {
|
||||
const info = template.info
|
||||
|
||||
if (info.length === 0) {
|
||||
return <></>
|
||||
} else {
|
||||
return (
|
||||
<div className="gate-info-icon">
|
||||
<a href={randomItem(info)} target="blank">
|
||||
<IconButton aria-label="info">
|
||||
<Icon>info</Icon>
|
||||
</IconButton>
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
const GateInfo = ({ name }: { name: string }) => {
|
||||
return (
|
||||
<div className="gate-info-icon">
|
||||
<Link to={`/info/${name}`}>
|
||||
<IconButton aria-label="info">
|
||||
<Icon>info</Icon>
|
||||
</IconButton>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
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 './GatePreview.scss';
|
||||
|
||||
$gate-margin: 1em;
|
||||
|
||||
.gate > section > .gate-preview > * {
|
||||
display: block;
|
||||
height: 10em;
|
||||
width: 10em;
|
||||
border-radius: 1em;
|
||||
|
||||
margin: $gate-margin;
|
||||
}
|
||||
|
||||
.gate:hover {
|
||||
border: 2px solid white !important;
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import './LogicGate.scss'
|
||||
import React from 'react'
|
||||
import GateInfo from './GateInfo'
|
||||
import GateSettings from './GateSettings'
|
||||
import AddGate from './AddGate'
|
||||
import { addGateFromTemplate } from '../helpers/addGateFromTemplate'
|
||||
import DeleteGateIcon from './DeleteGate'
|
||||
import GatePreview from './GatePreview'
|
||||
import { LogicGateProps } from '../types/LogicGateProps'
|
||||
import { firstCharUpperCase } from '../../../common/lang/strings/firstCharUpperCase'
|
||||
|
||||
const LogicGate = ({ template }: LogicGateProps) => {
|
||||
const rawName = template.metadata.name
|
||||
const name = `${rawName[0].toUpperCase()}${rawName.substr(1)}`
|
||||
const name = firstCharUpperCase(rawName)
|
||||
|
||||
return (
|
||||
<div className="gate">
|
||||
|
@ -27,8 +27,9 @@ const LogicGate = ({ template }: LogicGateProps) => {
|
|||
</section>
|
||||
<section>
|
||||
<div className="gate-icons">
|
||||
<GateInfo template={template} />
|
||||
{/* <GateSettings template={template} /> */}
|
||||
{!template.tags.includes('integrated') && (
|
||||
<GateInfo name={name} />
|
||||
)}
|
||||
<AddGate template={template} />
|
||||
<DeleteGateIcon template={template} />
|
||||
</div>
|
||||
|
|
|
@ -16,6 +16,9 @@ import halfAdderTemplate from './templates/halfAdder'
|
|||
import fullAdderTemplate from './templates/fullAdder'
|
||||
import _4bitEncoderTemplate from './templates/4bitEncoder'
|
||||
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 baseTemplates: DeepPartial<GateTemplate>[] = [
|
||||
|
@ -34,7 +37,10 @@ export const baseTemplates: DeepPartial<GateTemplate>[] = [
|
|||
halfAdderTemplate,
|
||||
fullAdderTemplate,
|
||||
_4bitEncoderTemplate,
|
||||
_4bitDecoderTemplate
|
||||
_4bitDecoderTemplate,
|
||||
comparatorTemplate,
|
||||
bitMergerTemplate,
|
||||
bitSplitterTemplate
|
||||
// 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
|
||||
}
|
||||
},
|
||||
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
|
||||
|
|
|
@ -24,7 +24,12 @@ const halfAdderTemplate: PartialTemplate = {
|
|||
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
|
||||
|
|
|
@ -22,13 +22,14 @@ const rgbLightTemplate: PartialTemplate = {
|
|||
},
|
||||
code: {
|
||||
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){
|
||||
context.color(context.colors.main)
|
||||
}
|
||||
|
||||
else{
|
||||
else {
|
||||
context.color(context.colors[color])
|
||||
}
|
||||
`
|
||||
|
|
|
@ -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