var createReactClass = window.p5VendorJs.createReactClass; var h = window.p5VendorJs.React.createElement; var ReactDOM = window.p5VendorJs.ReactDOM; // var AsyncTypeahead = window.p5VendorJs.AsyncTypeahead; // var swal = window.swal; if (!HTML_ID) throw "Missing HTML_ID"; // if (!d3) throw "Missing d3 (https://d3js.org/d3.v5.min.js)"; var DBG = DBG || false; var DBG1 = true; // // // var DEFAULT_CONFIG = { ui_output_width: 800, ui_max_receptor_r: 12, ui_space_y: 30, config_read_speed: 500, config_charge_receptor_at_input: 1, config_max_receptor_charge: 1.5, config_discharge_per_tick: 0.1, config_discharge_max_in_new_neuron_from_one: 0.7, } var DEFAULT_NEURON = { value: '', charge: 0, maxCharge: DEFAULT_CONFIG.config_max_receptor_charge, uiShape: "circle", ui: { cx: 0, cy: 0 }, source: [], next: [], } function state__getInitial(state, letters) { function makeReceptor(letter, idx, arr) { var totalReceptors = arr.length; var cx = Math.ceil(state.ui_output_width / (totalReceptors + 1)); var r = Math.min(Math.ceil(state.ui_output_width / (totalReceptors + 10) / 2), state.ui_max_receptor_r); var xCenter = cx + cx * idx - r; return Object.assign({}, DEFAULT_NEURON, { value: letter, maxCharge: state.config_max_receptor_charge, uiShape: "circle", ui: { cx: xCenter, cy: 40, r: r, }, next: [], }) } return { receptor: letters.map(makeReceptor), } } function state__readFromInput(state, char) { // 1. charge receptor with letter `char` var listNeuron = state.neuron; var listReceptor = state.receptor; var mapLetterToReceptor = {} for (var i = 0, l = listReceptor.length; i < l; i++) { mapLetterToReceptor[listReceptor[i].value] = listReceptor[i]; } // var toChangeReceptor = getReceptor(listReceptor, char) var toChangeReceptor = mapLetterToReceptor[char] DBG && console.log("DBG:anim", { char, len: state.inputText.length, toChangeReceptor, mapLetterToReceptor: mapLetterToReceptor }); toChangeReceptor.charge += state.config_charge_receptor_at_input; // 2. check if any receptor is over charged if (toChangeReceptor.charge > state.config_max_receptor_charge) { var closestNodeWithCharge = findReceptorClosestNodeWithCharge(state, toChangeReceptor) DBG1 && console.log("DBG:overcharge.1:", { char, len: state.inputText.length, closestNodeWithCharge, receptor: state.receptor }); if (!closestNodeWithCharge) { { // TODO: export to funtion makeNeuronFromOneNode(state, listReceptor, listNeuron, toChangeReceptor) var neuron = makeNeuronFromOneNode(state, toChangeReceptor) // TODO: neuron may already exists? check neuron.source if already has defined next var alreadyExistNeuron = toChangeReceptor.next.filter(function (nextNeuron) { return (nextNeuron.source.length === 1); }) DBG1 && console.log("DBG:overcharge.2:", { alreadyExistNeuron }); if (alreadyExistNeuron.length) { alreadyExistNeuron[0].charge += toChangeReceptor.charge toChangeReceptor.charge = 0 } else { toChangeReceptor.next.push(neuron) listNeuron.push(neuron) toChangeReceptor.charge = 0 } } } else { // (closestNodeWithCharge) { // TODO: export to funtion makeNeuronFromTwoNodes(state, listReceptor, listNeuron, toChangeReceptor, closestNodeWithCharge) var neuron = makeNeuronFromTwoNodes(state, toChangeReceptor, closestNodeWithCharge) // TODO: neuron may already exists? check neuron.source if already has defined next var alreadyExistNeuron = toChangeReceptor.next.filter(function (nextNeuron) { return (nextNeuron.source.length === 2 && ( (nextNeuron.source[0].value === toChangeReceptor.value && nextNeuron.source[1].value === closestNodeWithCharge.value) || (nextNeuron.source[0].value === closestNodeWithCharge.value && nextNeuron.source[1].value === toChangeReceptor.value) )); }) DBG1 && console.log("DBG:overcharge.2:", { alreadyExistNeuron }); if (alreadyExistNeuron.length) { alreadyExistNeuron[0].charge += toChangeReceptor.charge + closestNodeWithCharge.charge toChangeReceptor.charge = 0 closestNodeWithCharge.charge = 0 } else { toChangeReceptor.next.push(neuron) closestNodeWithCharge.next.push(neuron) listNeuron.push(neuron) toChangeReceptor.charge = 0 closestNodeWithCharge.charge = 0 } } } // TODO: dont use last letter -- use findReceptorClosestNodeWithCharge // if no closest neuron with charge then create new neuron over receptor // if (null !== state.animLastLetter && state.animLastLetter !== toChangeReceptor.letter) { // DBG1 && console.log("DBG:check overcharged", { toChangeReceptor, closestNodeWithCharge: closestNodeWithCharge, last_letter: state.animLastLetter }); // listNeuron = makeNueron(listReceptor, listNeuron, toChangeReceptor.letter, state.animLastLetter); // // discharge receptors to 0 // var toDischarge = [toChangeReceptor.letter, state.animLastLetter]; // listReceptor = listReceptor.map(function (receptor) { // return (-1 !== toDischarge.indexOf(receptor.letter)) // ? Object.assign({}, receptor, { charge: 0 }) // : receptor // ; // }) // } } // 3. discharge all receptors and nodes by 0.1 (config_discharge_per_tick) var dischargeNode = makeDischargeNodeFun(state); return { receptor: listReceptor.map(dischargeNode), neuron: listNeuron.map(dischargeNode), } } function state__fromOverchargedNeurons(state, overchargedNeurons) { var listNeuron = state.neuron; var listReceptor = state.receptor; overchargedNeurons = overchargedNeurons.sort(sortNeuronByChargeCallback) DBG1 && console.log("DBG:state:overcharged", { overchargedNeurons }) if (overchargedNeurons.length === 1) { var toChangeReceptor = overchargedNeurons[0] { // TODO: export to funtion makeNeuronFromOneNode(state, listReceptor, listNeuron, toChangeReceptor) var neuron = makeNeuronFromOneNode(state, toChangeReceptor) // TODO: neuron may already exists? check neuron.source if already has defined next var alreadyExistNeuron = toChangeReceptor.next.filter(function (nextNeuron) { return (nextNeuron.source.length === 1); }) DBG1 && console.log("DBG:overcharge.2:", { alreadyExistNeuron }); if (alreadyExistNeuron.length) { alreadyExistNeuron[0].charge += toChangeReceptor.charge toChangeReceptor.charge = 0 } else { toChangeReceptor.next.push(neuron) listNeuron.push(neuron) toChangeReceptor.charge = 0 } } } else { var toChangeReceptor = overchargedNeurons[0] var closestNodeWithCharge = overchargedNeurons[1] { // TODO: export to funtion makeNeuronFromTwoNodes(state, listReceptor, listNeuron, toChangeReceptor, closestNodeWithCharge) var neuron = makeNeuronFromTwoNodes(state, toChangeReceptor, closestNodeWithCharge) // TODO: neuron may already exists? check neuron.source if already has defined next var alreadyExistNeuron = toChangeReceptor.next.filter(function (nextNeuron) { return (nextNeuron.source.length === 2 && ( (nextNeuron.source[0].value === toChangeReceptor.value && nextNeuron.source[1].value === closestNodeWithCharge.value) || (nextNeuron.source[0].value === closestNodeWithCharge.value && nextNeuron.source[1].value === toChangeReceptor.value) )); }) DBG1 && console.log("DBG:overcharge.2:", { alreadyExistNeuron }); if (alreadyExistNeuron.length) { alreadyExistNeuron[0].charge += toChangeReceptor.charge + closestNodeWithCharge.charge toChangeReceptor.charge = 0 closestNodeWithCharge.charge = 0 } else { toChangeReceptor.next.push(neuron) closestNodeWithCharge.next.push(neuron) listNeuron.push(neuron) toChangeReceptor.charge = 0 closestNodeWithCharge.charge = 0 } } } return { receptor: listReceptor, neuron: listNeuron, } } function sortNeuronByChargeCallback(n1, n2) { if (n1.charge > n2.charge) return 1; if (n1.charge < n2.charge) return -1; return 0; } function getReceptor(listReceptor, char) { var receptor = listReceptor.filter(function (receptor) { return (char == receptor.value); }); if (!receptor.length) throw "BUG: no input receptor found for char '" + char + "'"; // TODO: create on demand? return receptor[0]; } function findReceptorClosestNodeWithCharge(state, node) { var skipSelfValue = node.value; var maxChargedReceptor = state.receptor.reduce(function (ret, receptor) { if (receptor.value === skipSelfValue) return ret; if (0 === receptor.charge) return ret; if (!ret) return receptor; return (receptor.charge > ret.charge) ? receptor : ret; }, null) return maxChargedReceptor; } function makeNeuronFromOneNode(state, sourceNode) { return Object.assign({}, DEFAULT_NEURON, { value: '' + (state.neuron.length + 1), charge: 0, // sourceNode.charge, maxCharge: sourceNode.maxCharge * state.config_discharge_max_in_new_neuron_from_one, // maybe?: sourceNode.charge uiShape: "ellipse", ui: { cx: sourceNode.ui.cx, cy: sourceNode.ui.cy + 10 + state.ui_space_y, rx: 10, ry: 10, }, source: [sourceNode], }); } function makeNeuronFromTwoNodes(state, first, second) { var value = '' + first.value + second.value; return Object.assign({}, DEFAULT_NEURON, { value: value, charge: 0, // (first.charge + second.charge) / 2, maxCharge: ((first.maxCharge + second.maxCharge) / 2) * state.config_discharge_max_in_new_neuron_from_one, uiShape: "ellipse", ui: { cx: (first.ui.cx + second.ui.cx) / 2, cy: first.ui.cy + 10 + state.ui_space_y, rx: 10 * value.length, ry: 10, }, source: [first, second], }); } function getNeuron(listNeuron, value) { var neuron = listNeuron.filter(function (neuron) { return (value == neuron.letter); }); return (neuron.length) ? neuron[0] : null; } function makeDischargeNodeFun(state) { return function dischargeNode(neuron) { return (neuron.charge > 0) ? Object.assign({}, neuron, { charge: Math.max(0, neuron.charge - state.config_discharge_per_tick), }) : neuron ; } } function isNeuronOvercharged(neuron) { return (neuron.charge > neuron.maxCharge); } function LOG__render(listLogEntries) { return h('details', { open: false, style: { margin: "12px 0", border: "1px solid #aaa", borderRadius: "6px", padding: "12px", backgroundColor: "#eee", } }, [ h('summary', { style: { cursor: "pointer" } }, "Log"), h('div', { style: { border: "1px solid #eee", backgroundColor: "#fff" } }, [ h('table', { className: "table table-border" }, [ h('thead', {}, LOG__renderTheadLog(listLogEntries)), h('tbody', {}, LOG__renderTbodyLog(listLogEntries)), ]), ]), ]); } function LOG__renderTheadLog(listLogEntries) { if (!listLogEntries.length) return null; var lastLog = listLogEntries[listLogEntries.length - 1] var colsR = lastLog.receptor.map(function (node) { return node.value; }) var colsN = lastLog.neuron.map(function (node) { return node.value; }) return [ h('tr', {}, [h('th', {}, "Lp.")] .concat( colsR.map(function (label) { return h('th', {}, "R:'" + label + "'"); }) ) .concat( colsN.map(function (label) { return h('th', {}, "N:'" + label + "'"); }) ) ) ]; } function LOG__renderTbodyLog(listLogEntries) { if (!listLogEntries.length) return null; var lastLog = listLogEntries[listLogEntries.length - 1] var colsR = lastLog.receptor.map(function (node) { return node.value; }) var colsN = lastLog.neuron.map(function (node) { return node.value; }) return listLogEntries.map(function (log, lpLog) { var row = colsR.map(function (label, idx) { return log.receptor[idx].charge; }) .concat( colsN.map(function (label, idx) { return (log.neuron[idx]) ? log.neuron[idx].charge : null; }) ) return h('tr', {}, [h('th', { style: { color: "#ddd" } }, '' + (lpLog + 1) + '.')] .concat( row.map(LOG__renderCellNodeChargeLog) ) ) }) } function LOG__renderCellNodeChargeLog(charge) { if (null === charge) return null; return h('td', { style: { color: (charge > 0) ? "#000" : "#aaa", }, }, charge.toFixed(2)); } var NeuronView = createReactClass({ _input: null, _output: null, _animTimoutID: null, _log: [], getInitialState: function () { return Object.assign({}, DEFAULT_CONFIG, { inputText: this.props.initialData || '', // TODO: INITIAL_DATA receptor: [], neuron: [], doAnim: false, animPos: 0, animLastLetter: null, selectedReceptorIdx: null, }); }, handleChangeInput: function (event) { this.setState({ inputText: event.target.value, }) }, setInputRet: function (reactEl) { this._input = reactEl; }, setOutputRet: function (reactEl) { this._output = reactEl; }, componentDidMount: function () { this.startAnimation(); }, handleExec: function (event) { event.preventDefault(); DBG1 && console.log('DBG:handleExec...'); if (this._animTimoutID) clearTimeout(this._animTimoutID); this.setState({ neuron: [], receptor: [], }) setTimeout(this.startAnimation, this.state.config_read_speed * 2) }, handlePause: function (event) { event.preventDefault(); this.setState({ doAnim: false }) }, handleStart: function (event) { event.preventDefault(); this.forwardAnim(true) }, startAnimation: function (event) { var distinct = function (value, idx, self) { return (idx === self.indexOf(value)); }; // var foundLetters = this.state.inputText.split("\n").reduce(function (ret, line) { // return ret.concat( // line.split('').filter(distinct) // ).filter(distinct); // }, []); var foundLetters = this.state.inputText.split("").filter(distinct); DBG1 && console.warn('DBG:handleExec:foundLetters', { foundLetters }); this._log = [] this.setState(Object.assign( {}, state__getInitial(this.state, foundLetters), { animPos: 0, neuron: [], doAnim: true, } ), function () { console.warn({ receptor: this.state.receptor.map(function (n) { return n }), neuron: this.state.receptor.map(function (n) { return n }), }) }.bind(this)); setTimeout(this.forwardAnim, this.state.config_read_speed) }, getReceptor: function (char) { var receptor = this.state.receptor.filter(function (receptor) { return (char == receptor.value); }); if (!receptor.length) throw "BUG: no input receptor found for char '" + char + "'"; // TODO: create on demand? return receptor[0]; }, forwardAnim: function (forceUpdateDoAnim) { this._logState(this.state) var doAnim = (arguments.length > 0) ? forceUpdateDoAnim : this.state.doAnim; var animPos = this.state.animPos; var overchargedNeurons = this.state.neuron.filter(isNeuronOvercharged) if (overchargedNeurons.length === 0) { animPos += 1; } else { DBG1 && console.log("DBG:anim TODO: neuron overcharged", { overchargedNeurons }); } if (animPos >= this.state.inputText.length) { DBG1 && console.log("DBG:anim STOP - end of input", { inputLength: this.state.inputText.length, animPos: this.state.animPos }); return; } var char = this.state.inputText.charAt(animPos) DBG && console.log("DBG:anim", { animPos, char, len: this.state.inputText.length, doAnim }); this.setState(Object.assign( {}, (overchargedNeurons.length) ? state__fromOverchargedNeurons(this.state, overchargedNeurons) : state__readFromInput(this.state, char), { animLastLetter: char, animPos: animPos, doAnim: doAnim, } )); if (doAnim) { this._animTimoutID = setTimeout(this.forwardAnim, this.state.config_read_speed) } }, _logState: function (state) { function getNodeInfo(node) { return { value: node.value, charge: node.charge, } } this._log.push({ receptor: state.receptor.map(getNodeInfo), neuron: state.neuron.map(getNodeInfo), }) }, selectReceptor: function (receptorIdx) { this.setState({ selectedReceptorIdx: receptorIdx }) }, handleClickReceptor: function (event) { var data_receptor_idx = event.target.getAttribute('data_receptor_idx') DBG1 && console.log('DBG:handleClickReceptor', { data_receptor_idx, target: event.target }); this.selectReceptor(data_receptor_idx) }, renderConnections: function (neuron, idx) { DBG1 && console.log('DBG:renderConnections', { neuron, p1: neuron.source[0].ui, p2: (neuron.source.length > 1) ? neuron.source[1].ui : null }); return h('g', {}, [ h('line', { x1: neuron.source[0].ui.cx, y1: neuron.source[0].ui.cy, x2: neuron.ui.cx, y2: neuron.ui.cy, style: { stroke: "#46b8da", strokeWidth: "2" }, }), (neuron.source.length > 1) ? h('line', { x1: neuron.source[1].ui.cx, y1: neuron.source[1].ui.cy, x2: neuron.ui.cx, y2: neuron.ui.cy, style: { stroke: "#46b8da", strokeWidth: "2" }, }) : null, ]); }, renderNeuron: function (neuron, idx) { var chargePr = (100 * neuron.charge) / this.state.config_max_receptor_charge; var fontColor = (chargePr < 50) ? "#000" : "#fff"; return h('g', {}, [ h(neuron.uiShape, Object.assign({}, neuron.ui, { stroke: "#46b8da", strokeWidth: 1, fill: (chargePr > 100) ? "#f00" : "hsl(194, 67%, " + (100 - chargePr) + "%)", // data_neuron_idx: idx, // onClick: this.handleClickNeuron, style: { cursor: "pointer" }, }), [ h('title', {}, this.viewNeuronTitle(neuron.value)), ]), h('text', { x: neuron.ui.cx, y: neuron.ui.cy + 1, fill: fontColor, dominantBaseline: "middle", textAnchor: "middle", style: { fontSize: "10px", cursor: "pointer" }, // data_neuron_idx: idx, // onClick: this.handleClickNeuron, }, neuron.charge.toFixed(1)), ]); }, viewNeuronValue: function (value) { return value .replace(new RegExp("\n", "g"), "\\n") .replace(new RegExp("\t", "g"), "\\t") .replace(new RegExp(" ", "g"), "_") ; }, viewNeuronTitle: function (value) { return this.viewNeuronValue(value); }, renderReceptor: function (receptor, idx) { // orange: hsl(40, 100%, 50%) --> hsl(0, 100%, 50%) -> red (overcharged) // var totalReceptors = this.state.receptor.length; // var cx = Math.ceil(this.state.ui_output_width / ( totalReceptors + 1 )); // var r = Math.min(Math.ceil(this.state.ui_output_width / ( totalReceptors + 10 ) / 2), this.state.ui_max_receptor_r); // DBG && console.log('DBG:renderReceptor', { receptor, idx, totalReceptors, r }); // var xCenter = cx + cx * idx - r; var chargePr = (100 * receptor.charge) / this.state.config_max_receptor_charge; // var shapeColor = (chargePr > 100) ? "#f00" : "hsl(194, 67%, " + (100 - chargePr) + "%)"; // blue -> dark blue -> red var shapeColor = (chargePr > 100) ? "#f00" : "hsl(" + (40 - chargePr * 2 / 5).toFixed() + ", 100%, 50%)"; // orange -> dark orange -> red var fontColor = "#fff"; // (chargePr < 50) ? "#000" : "#fff"; // this.state.config_max_receptor_charge = 100% // receptor.charge = x% (max 100) return h('g', {}, [ h(receptor.uiShape, Object.assign({}, receptor.ui, { stroke: "#46b8da", strokeWidth: 1, fill: shapeColor, data_receptor_idx: idx, onClick: this.handleClickReceptor, style: { cursor: "pointer" }, }), [ h('title', {}, this.viewReceptorTitle(receptor.value)), ]), h('text', { x: receptor.ui.cx, y: receptor.ui.cy + 1, fill: fontColor, dominantBaseline: "middle", textAnchor: "middle", style: { fontSize: "10px", cursor: "pointer" }, data_receptor_idx: idx, onClick: this.handleClickReceptor, }, receptor.charge.toFixed(1)), h('text', { x: receptor.ui.cx, y: receptor.ui.cy - 20, fill: "#000", dominantBaseline: "middle", textAnchor: "middle", style: { fontSize: "10px", cursor: "pointer" }, data_receptor_idx: idx, onClick: this.handleClickReceptor, }, this.viewReceptorLetter(receptor.value)), ]); }, viewReceptorLetter: function (letter) { switch (letter) { case "\t": return "\\t"; case " ": return "_"; case "\n": return "\\n"; default: return letter; } }, viewReceptorTitle: function (letter) { switch (letter) { case "\t": return "tab"; case " ": return "space"; case "\n": return "new line"; default: return letter; } }, renderReceptorInfo: function () { if (null === this.state.selectedReceptorIdx) return null; var receptor = this.state.receptor[this.state.selectedReceptorIdx]; return h('div', {}, [ "Receptor: '" + this.viewReceptorTitle(receptor.value) + "' charge('" + receptor.charge.toFixed(2) + "')", ]); }, renderAllReceptorInfo: function () { return h('div', {}, this.state.receptor.map(this.renderAllReceptorInfo_item)); }, renderAllReceptorInfo_item: function (receptor) { return h('div', {}, ["Receptor: '" + this.viewReceptorTitle(receptor.value) + "' charge('" + receptor.charge.toFixed(2) + "')"]); }, renderAllNeuronInfo: function () { return h('div', {}, this.state.neuron.map(this.renderAllNeuronInfo_item)); }, renderAllNeuronInfo_item: function (neuron) { return h('div', {}, ["Neuron: '" + neuron.value + "' charge('" + neuron.charge.toFixed(2) + "')"]); }, renderInput: function () { return h('details', { open: true, style: { margin: "12px 0", border: "1px solid #aaa", borderRadius: "6px", padding: "12px", backgroundColor: "#eee", } }, [ h('summary', { style: { cursor: "pointer" } }, "Input"), h('textarea', { ref: this.setInputRet, onChange: this.handleChangeInput, value: this.state.inputText, rows: 10, style: { width: "100%", padding: "12px", marginTop: "6px", backgroundColor: "#fff", }, }), ]); }, renderConfig: function () { return h('details', { open: true, style: { margin: "12px 0", border: "1px solid #aaa", borderRadius: "6px", padding: "12px", backgroundColor: "#eee", } }, [ h('summary', { style: { cursor: "pointer" } }, "Config"), h('div', { style: { padding: "12px", backgroundColor: "#fff", } }, [ h('div', {}, "Read speed:"), h('input', { className: "form-control input-sm", type: "number", value: this.state.config_read_speed, name: "config_read_speed", onChange: this.handleChangeConfig, }), h('div', { style: { marginTop: "12px" } }), h('div', {}, "Charge receptor at input:"), h('input', { className: "form-control input-sm", type: "number", value: this.state.config_charge_receptor_at_input, name: "config_charge_receptor_at_input", onChange: this.handleChangeConfig, }), h('div', { style: { marginTop: "12px" } }), h('div', {}, "Max receptor charge:"), h('input', { className: "form-control input-sm", type: "number", value: this.state.config_max_receptor_charge, name: "config_max_receptor_charge", onChange: this.handleChangeConfig, }), h('div', { style: { marginTop: "12px" } }), h('div', {}, "Discharge per tick:"), h('input', { className: "form-control input-sm", type: "number", step: "0.1", value: this.state.config_discharge_per_tick, name: "config_discharge_per_tick", onChange: this.handleChangeConfig, }), ]), ]); }, handleChangeConfig: function (event) { var value = event.target.value; var name = event.target.getAttribute('name'); var state = this.state; state[name] = value; this.setState(state); }, renderLog: function () { return LOG__render(this._log) }, handleRefreshLog: function () { if (!this._log.length) return; var lastLog = this._log[this._log.length - 1] console.table( [ lastLog.receptor.map(function (node) { return "R:'" + node.value + "'"; }) .concat( lastLog.neuron.map(function (node) { return "N:'" + node.value + "'"; }) ) ].concat( this._log.map(function (log) { return log.receptor.map(function (node) { return node.charge }) .concat( log.neuron.map(function (node) { return node.charge }) ) }) ) ) }, render: function () { DBG1 && console.log("DBG:render", { state: this.state }); return h('div', {}, [ h('table', { className: "table table-border", p5_node_id: "p5-neuron-output-table" }, [ h('tbody', {}, [ h('tr', {}, [ h('td', { style: { width: this.state.ui_output_width + 20 } }, [ h('svg', { ref: this.setOutputRet, height: 300, width: this.state.ui_output_width, style: { border: "1px solid #eee" } }, [ this.state.neuron.map(this.renderConnections), this.state.receptor.map(this.renderReceptor), this.state.neuron.map(this.renderNeuron), ]), ]), h('td', { style: { verticalAlign: "top" } }, [ this.renderReceptorInfo(), this.renderAllReceptorInfo(), this.renderAllNeuronInfo(), ]), ]), ]), ]), h('div', {}, [ h('button', { className: "btn btn-primary", onClick: this.handleExec }, "Uruchom"), " ", this.state.doAnim ? h('button', { className: "btn btn-default", onClick: this.handlePause }, [h('i', { className: "glyphicon glyphicon-pause" }), "Stop"]) : h('button', { className: "btn btn-default", onClick: this.handleStart }, [h('i', { className: "glyphicon glyphicon-play" }), "Start"]) , h('button', { className: "btn btn-default", onClick: this.handleRefreshLog }, [h('i', { className: "glyphicon glyphicon-refresh" }), " ", "Log"]) ]), this.renderLog(), h('table', { className: "table table-border" }, [ h('tbody', {}, [ h('tr', {}, [ h('td', { style: { width: "50%" } }, [ this.renderInput(), ]), h('td', { style: { width: "50%" } }, [ this.renderConfig(), ]), ]), ]), ]), h('div', {}, [ "TODO: receptory...", ]), ]); } }); ReactDOM.render(h(NeuronView, { initialData: INITIAL_DATA || "", }), document.getElementById(HTML_ID))