diff --git a/README.md b/README.md index f7a5a120cf336de384ecf2e19475a39ebf46f95c..e4788a14578dc58922d956702926b814c5b881d2 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,12 @@ This project serves the developement environment / api we use to write and repre ## For MW - fundament + - the basic unit is a .js file having inputs, outputs, and state objects + - we can compose programs of these modules, being collections of them with connections + - we can represent these programs heirarchically, or in a flat manner ... heirarchy just requires an extra wrap, we do it later + - load / save programs (req. prgmem representation) + - rewrite ui & transfers to use this rep. - UI - title bar descr. how to operate - 'L' for load, 'M' for new module, type for module search ? @@ -39,7 +44,7 @@ Also Modules-that-represent-remote-computing also have Ports - that connect to + that connect to a Link To assemble a representation of these, we want to have a kind of 'netlist' that, for convenience, we'll treat like a JSON object. We want heirarchy, so consider the representation having 'top-level' outputs / inputs / state as well ? diff --git a/lib/inout.js b/lib/inout.js deleted file mode 100644 index f994d9e13e162ab0353ce458a469359d0df9970e..0000000000000000000000000000000000000000 --- a/lib/inout.js +++ /dev/null @@ -1,141 +0,0 @@ -// event system to include type-checking etc - -function Input(type, fn){ - var input = { - accepts: type, - fn: fn - } - - return input -} - -function Output(type){ - var output = { - emits: type - } - - output.calls = new Array() - - output.attach = function(input){ - this.calls.push(input) - } - - output.isLinked = function(input){ - // return true if already hooked up - if(this.calls.includes(input)){ - return true - } else { - return false - } - } - - output.remove = function(input){ - if(!this.isLinked(input)){ - console.log('attempt to rm input that is not attached') - return false - } else { - this.calls.splice(this.calls.indexOf(input), 1) - } - } - - output.emit = function(data){ - if(this.calls.length == 0){ - console.log('no inputs bound to this output') - } else { - for(index in this.calls){ - this.calls[index].fn(JSON.parse(JSON.stringify(data))) - } - } - } - - return output -} - -function State(){ - var state = { - } - - state.emitters = {} - - state.onChange = function(item, fn){ - this.emitters[item] = fn - //console.log('ADD STATE CHANGE EMITTER', this.emitters) - } - - state.emitChange = function(item){ - //console.log('EMIT CHANGE FOR', item) - if(this.emitters[item] != null){ - this.emitters[item]() - } - } - - return state -} - -// within state ... or not ? -function Button(label){ - var button = { - isButton: true, - isPressed: false, - label: label - } - - return button -} - -// now we're definitely writing a UI class -function MultiLine(label, rows){ - var ml = { - isMultiLine: true, - label: label, - rows: rows, - value: ' - ' - } - - return ml -} - -module.exports = { - Input: Input, - Output: Output, - State: State, - Button: Button, - MultiLine: MultiLine -} - -/* -prjRep = { - connectivity: [ - {id: 1, thisOutput: ['2:thisInput', '4:thatInput'], thatOutput: [etc]}, - {id: 2, thatOutput: ['2:thisInput', '4:thatInput']} - ], - states: [ - {id: 1, state: { - // - }} - }, - positions: [ - {id: 1, posX: 12, posY: 15} - ] -} -*/ - - -/* -more like - -modules = [ - Class { - state: object, - inputs: object, - outputs: object, // walk this for connectivity - how to set that up? - } -] - -reps = [ - object { - posX: num, - posY: num - } -] -*/ \ No newline at end of file diff --git a/lib/jsunit.js b/lib/jsunit.js new file mode 100644 index 0000000000000000000000000000000000000000..324ff7c5bb12702d084a7bb6bb07748ee2538956 --- /dev/null +++ b/lib/jsunit.js @@ -0,0 +1,104 @@ +// event system to include type-checking etc +// dataflow types for javascript objects ... + +function Input(type, fn) { + var input = { + accepts: type, + fn: fn + } + + return input +} + +function Output(type) { + var output = { + emits: type + } + + output.calls = new Array() + + output.attach = function(input) { + this.calls.push(input) + } + + output.isLinked = function(input) { + // return true if already hooked up + if (this.calls.includes(input)) { + return true + } else { + return false + } + } + + output.remove = function(input) { + if (!this.isLinked(input)) { + console.log('attempt to rm input that is not attached') + return false + } else { + this.calls.splice(this.calls.indexOf(input), 1) + } + } + + output.emit = function(data) { + if (this.calls.length == 0) { + console.log('no inputs bound to this output') + } else { + for (index in this.calls) { + this.calls[index].fn(JSON.parse(JSON.stringify(data))) + } + } + } + + return output +} + +function State() { + var state = {} + + state.emitters = {} + + state.onChange = function(item, fn) { + this.emitters[item] = fn + //console.log('ADD STATE CHANGE EMITTER', this.emitters) + } + + state.emitChange = function(item) { + //console.log('EMIT CHANGE FOR', item) + if (this.emitters[item] != null) { + this.emitters[item]() + } + } + + return state +} + +// within state ... or not ? +function Button(label) { + var button = { + isButton: true, + isPressed: false, + label: label + } + + return button +} + +// now we're definitely writing a UI class +function MultiLine(label, rows) { + var ml = { + isMultiLine: true, + label: label, + rows: rows, + value: ' - ' + } + + return ml +} + +module.exports = { + Input: Input, + Output: Output, + State: State, + Button: Button, + MultiLine: MultiLine +} \ No newline at end of file diff --git a/server.js b/nnc.js similarity index 62% rename from server.js rename to nnc.js index e5f901747a9f19482a7e29c089321e0fdb6ece00..9f25315978801c7002ed71f3b68107d6bda51261 100644 --- a/server.js +++ b/nnc.js @@ -1,5 +1,6 @@ // -// server.js +// nnc.js +// // // Jake Read at the Center for Bits and Atoms // (c) Massachusetts Institute of Technology 2018 @@ -134,129 +135,216 @@ PROGRAM AS API ------------------------------------------------------ */ -var modules = new Array() +// nodes are objects having inputs, outputs, and state +// nodes can be made up of other nodes +// a node originates somewhere, -// a program is a list of modules, -// modules have internal lists of modules that they call +// is it a JSON, or a txt .js file ? loadProgram and loadModule ... +// it wants to be an object that gets 'read' in ... -var prgmem = { - // we want to describe all of the nodes first, - // then we can add connections once we have hooks - // to each of them - modules: { - gate: { - path: './src/util/gate.js', - conn: { - - } - ui:{ - pos: [100, 100] - } - }, - delay: { - path: './src/util/delay.js', - state: { - ms: 500 - } - }, - log: { - path: './src/util.log.js' - } +var program = { + description: { + name: 'tstprgmem', }, - connections: ['gate.outputs.out', 'delay.inputs.thru'] + modules: new Array() } -function loadPrgmem(desc) { - console.log(desc) -} +// add things -loadPrgmem(prgmem) +var gate = addModuleToProgram(program, './src/util/gate.js') +var delay = addModuleToProgram(program, './src/util/delay.js') +var log = addModuleToProgram(program, './src/util/log.js') -/* ------------------------------------------------------- -LOST FUNCTION ------------------------------------------------------- -*/ +// hookup as usual + +gate.outputs.out.attach(delay.inputs.thru) +delay.outputs.out.attach(log.inputs.thru) +gate.outputs.out.attach(log.inputs.thru) + +saveProgram(program, 'save/onesave.json') + +program = null +delete gate +delete delay +delete log + +console.log('PROGRAM', program) + +var prgmem = openProgram('save/onesave.json') + +saveProgram(prgmem, 'save/twosave.json') -function setUiPos(module, left, top) { - if (module.ui == null) { - module.ui = {} - } - module.ui.left = left - module.ui.top = top -} /* ------------------------------------------------------ -PROGRAM WRITING +PROGRAM ASSEMBLY ------------------------------------------------------ */ -function addModule(path) { - // get and add to server system +function addModuleToProgram(program, path) { + // program is an object seeking heirarchy, has program.modules if (fs.existsSync(path)) { - var src = require(path) // get and return - var mod = new src() // make a new one - modules.push(mod) // add to the system - - // assign and id and remember from whence it came - mod.id = modules.length - 1 - mod.path = path - - // we need to add some top-level info to the inputs so that we can draw them - for (item in mod.inputs) { - mod.inputs[item].parentId = mod.id - mod.inputs[item].key = item + var src = require(path) + var mod = new src() + + // add to list + program.modules.push(mod) + // make unique name + mod.description.id = mod.description.name + '-' + program.modules.length + mod.description.path = path + + // input need references for later hookup + for (key in mod.inputs) { + mod.inputs[key].parentId = mod.description.id + mod.inputs[key].key = key } - for (item in mod.state) { - if (item == 'onChange' | item == 'emitChange' | item == 'emitters') { + // state updating, begs for update + for (key in mod.state) { + if (key == 'onChange' | key == 'emitChange' | key == 'emitters') { //console.log('rolling past change fn') } else { - mod.state['_' + item] = mod.state[item] - mod.state[item] = {} - writeStateObject(mod, item) + mod.state['_' + key] = mod.state[key] + mod.state[key] = {} + writeStateObject(mod, key) } } - console.log('ADDING MODULE', mod.description.name) + if (program.description.id == null) { + if (program.description.name == null) { + if (program.description == null) { + program.description = {} + } + program.description.name = 'unnamed program' + } + program.description.id = program.description.name + '-' + 0 + } - // now roll and return representable object - // first to UI - putRep(mod) - // also to fn call, in case writing program ? + console.log('ADDING', mod.description.id, 'to', program.description.id) + // also return it so that we can write programs without the UI return mod } else { - console.log('ERR no module found at', path) + console.log('ERR no module found at ', path) } } -function writeStateObject(mod, item) { - Object.defineProperty(mod.state, item, { +function writeStateObject(mod, key) { + Object.defineProperty(mod.state, key, { set: function(x) { // update internal value - this['_' + item] = x - //console.log('SET', item, this['_' + item]) + this['_' + key] = x + //console.log('SET', key, this['_' + key]) // push to internal state change handler - this.emitChange(item) + this.emitChange(key) // update server (or in some cases, a confirmation) putState(mod) } }) - Object.defineProperty(mod.state, item, { + Object.defineProperty(mod.state, key, { get: function() { - //console.log('GET', item, this['_' + item]) - return this['_' + item] + //console.log('GET', key, this['_' + key]) + return this['_' + key] } }) } +function makeRepFromModule(mdl) { + var rep = { + description: { + id: mdl.description.id, + name: mdl.description.name, + alt: mdl.description.alt, + path: mdl.description.path + } + } + + // TODO: making rep. of input / output should be a f'n of that object ... + // input, outputs, state objs should be known /sysobjects + // everything else is free play + rep.inputs = {} + for (key in mdl.inputs) { + rep.inputs[key] = {} + rep.inputs[key].accepts = mdl.inputs[key].accepts + } + + rep.outputs = {} + for (key in mdl.outputs) { + rep.outputs[key] = {} + rep.outputs[key].emits = mdl.outputs[key].emits + rep.outputs[key].calls = new Array() + mdl.outputs[key].calls.forEach(function(inp) { + var input = { + parentId: inp.parentId, + key: inp.key + } + rep.outputs[key].calls.push(input) + }) + } + + rep.state = {} + for(key in mdl.state){ + if(isStateKey(key)){ + rep.state[key] = mdl.state[key] + } + } + + return rep +} + +function saveProgram(prgmem, path) { + // ok, and we're interested in just copying the relevant things ... + var svprgmem = { + description: { + name: prgmem.description.name + }, + modules: new Array() + } + + var mdls = prgmem.modules + + mdls.forEach(function(mdl) { + // basically, going to run a diff on this + console.log('mdl unit', mdl) + // and + var og = makeRepFromModule(mdl) + console.log('rep uniiiit', og) + svprgmem.modules.push(og) + }) + + fs.writeFileSync(path, JSON.stringify(svprgmem, null, 2), 'utf8') +} + +function openProgram(path){ + var program = {} + + // get the .json file as an object + var prgRep = JSON.parse(fs.readFileSync(path, 'utf8')) + console.log('OPENING THIS REP', prgRep) + + program.description = { + name: prgRep.description.name, + id: prgRep.description.name + 1, + path: path + } + + program.modules = new Array() + + prgRep.modules.forEach(function(rep){ + addModuleToProgram(program, rep.description.path) + }) + + // once modules exist, link inputs / outputs / copy state ? + + return program +} + /* -PROGRAM UPDATING +PROGRAM REPRESENT */ + //console.log('modules at prgmem start', modules) function putReps() { var reps = new Array() @@ -341,6 +429,15 @@ function changeUi(data) { console.log('CHANGE UI', mod.id, mod.ui) } +function setUiPos(module, left, top) { + if (module.ui == null) { + module.ui = {} + } + module.ui.left = left + module.ui.top = top +} + + function isStateKey(key) { if (key.indexOf('_') == 0 || key == 'emitters' || key == 'onChange' || key == 'emitChange') { return false diff --git a/programs/instron.js b/programs/instron.js index 68dba0f823db30cfba9dce6728d957a14ff30de4..bf65736d862a1be3f33a7feb6bb0abbc86d33603 100644 --- a/programs/instron.js +++ b/programs/instron.js @@ -1,4 +1,5 @@ + var gate = addModule('./src/util/gate.js') var delay = addModule('./src/util/delay.js') var log = addModule('./src/util/log.js') diff --git a/programs/tstprgmem.js b/programs/tstprgmem.js new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/save/mdls.json b/save/mdls.json new file mode 100644 index 0000000000000000000000000000000000000000..167d4ffa273a3b01b6e3f6304b4f4952ac8872f2 --- /dev/null +++ b/save/mdls.json @@ -0,0 +1 @@ +[{"description":{"name":"gate","alt":"in ... out"},"state":{"emitters":{},"toggle":{"isButton":true,"isPressed":false,"label":"Open / Close"},"message":"closed","_toggle":{"isButton":true,"isPressed":false,"label":"Open / Close"},"_message":"closed"},"isOpen":false,"inputs":{"thru":{"accepts":"any","parentId":0,"key":"thru"}},"outputs":{"out":{"emits":"any","calls":[{"accepts":"any","parentId":1,"key":"thru"},{"accepts":"any","parentId":2,"key":"thru"},{"accepts":"any","parentId":3,"key":"reset"},{"accepts":"event","parentId":4,"key":"trigger"},{"accepts":"event","parentId":8,"key":"rmtrig"},{"accepts":"event","parentId":9,"key":"rmtrig"}]}},"id":0,"path":"./src/util/gate.js","ui":{"left":160,"top":130}},{"description":{"name":"delay!","alt":"in ... out"},"state":{"emitters":{},"ms":100,"_ms":100},"inputs":{"thru":{"accepts":"any","parentId":1,"key":"thru"}},"outputs":{"out":{"emits":"any","calls":[{"accepts":"any","parentId":3,"key":"A"}]}},"id":1,"path":"./src/util/delay.js","ui":{"left":160,"top":260}},{"description":{"name":"logger!","alt":"in ... out to console"},"state":{"emitters":{},"prefix":"LOGGER:","message":"---","_prefix":"LOGGER:","_message":"---"},"inputs":{"thru":{"accepts":"any","parentId":2,"key":"thru"}},"id":2,"path":"./src/util/log.js","ui":{"left":160,"top":400}},{"description":{"name":"andflow","alt":"in ... out"},"state":{"emitters":{},"toggle":{"isButton":true,"isPressed":false,"label":"Reset"},"A":0,"B":0,"_toggle":{"isButton":true,"isPressed":false,"label":"Reset"},"_A":0,"_B":0},"inputs":{"reset":{"accepts":"any","parentId":3,"key":"reset"},"A":{"accepts":"any","parentId":3,"key":"A"},"B":{"accepts":"any","parentId":3,"key":"B"}},"outputs":{"out":{"emits":"any","calls":[{"accepts":"any","parentId":0,"key":"thru"}]}},"id":3,"path":"./src/flowcontrol/and.js","ui":{"left":700,"top":300}},{"description":{"name":"CAMERA Request","alt":"webcam","isHardware":true},"state":{"emitters":{},"button":{"isButton":true,"isPressed":false,"label":"REQUEST IMAGE"},"counter":0,"_button":{"isButton":true,"isPressed":false,"label":"REQUEST IMAGE"},"_counter":0},"inputs":{"trigger":{"accepts":"event","parentId":4,"key":"trigger"}},"outputs":{"image":{"emits":"image","calls":[]},"callback":{"emits":"event","calls":[{"accepts":"any","parentId":3,"key":"B"}]}},"id":4,"path":"./src/hardware/webcam.js","ui":{"left":500,"top":700}},{"description":{"name":"Breadboard ADC Request","alt":"bbadc","isHardware":true},"state":{"emitters":{},"button":{"isButton":true,"isPressed":false,"label":"REQUEST CONVERSION"},"adcVal":0,"_button":{"isButton":true,"isPressed":false,"label":"REQUEST CONVERSION"},"_adcVal":0},"inputs":{"packet":{"accepts":"headless packet","parentId":5,"key":"packet"},"request":{"accepts":"event","parentId":5,"key":"request"}},"outputs":{"packet":{"emits":"number","calls":[{"accepts":"headless packet","parentId":7,"key":"B"}]}},"id":5,"path":"./src/hardware/adc.js","ui":{"left":1629,"top":180}},{"description":{"name":"Test Packet","alt":"net state","isHardware":true},"state":{"emitters":{},"button":{"isButton":true,"isPressed":false,"label":"TEST"},"message":"no test started","_button":{"isButton":true,"isPressed":false,"label":"TEST"},"_message":"no test started"},"inputs":{"packet":{"accepts":"headless packet","parentId":6,"key":"packet"},"trigger":{"accepts":"event","parentId":6,"key":"trigger"}},"outputs":{"packet":{"emits":"number","calls":[{"accepts":"headless packet","parentId":7,"key":"B"}]}},"id":6,"path":"./src/hardware/test.js","ui":{"left":1060,"top":918}},{"description":{"name":"ATK Hardware Bridge","alt":"talks over serialport","isHardware":true},"state":{"emitters":{},"rA":"0,0","rB":"0,1","rC":"0,2","rD":"0,3","rE":"0,4","rF":"0,5","rG":"0","findPort":{"isButton":true,"isPressed":false,"label":"click to find atk port"},"portName":"---","connect":{"isButton":true,"isPressed":false,"label":"click to connect"},"portStatus":"closed","terminal":"address | key:values","sendRawPacket":{"isButton":true,"isPressed":false,"label":"sendRaw"},"_rA":"0,0","_rB":"0,1","_rC":"0,2","_rD":"0,3","_rE":"0,4","_rF":"0,5","_rG":"0","_findPort":{"isButton":true,"isPressed":false,"label":"click to find atk port"},"_portName":"---","_connect":{"isButton":true,"isPressed":false,"label":"click to connect"},"_portStatus":"closed","_terminal":"address | key:values","_sendRawPacket":{"isButton":true,"isPressed":false,"label":"sendRaw"}},"inputs":{"A":{"accepts":"headless packet","parentId":7,"key":"A"},"B":{"accepts":"headless packet","parentId":7,"key":"B"},"C":{"accepts":"headless packet","parentId":7,"key":"C"},"D":{"accepts":"headless packet","parentId":7,"key":"D"},"E":{"accepts":"headless packet","parentId":7,"key":"E"},"F":{"accepts":"headless packet","parentId":7,"key":"F"},"G":{"accepts":"headless packet","parentId":7,"key":"G"}},"outputs":{"A":{"emits":"headless packet","calls":[{"accepts":"headless packet","parentId":8,"key":"packet"},{"accepts":"headless packet","parentId":10,"key":"packet"}]},"B":{"emits":"headless packet","calls":[{"accepts":"headless packet","parentId":5,"key":"packet"},{"accepts":"headless packet","parentId":6,"key":"packet"}]},"C":{"emits":"headless packet","calls":[]},"D":{"emits":"headless packet","calls":[]},"E":{"emits":"headless packet","calls":[]},"F":{"emits":"headless packet","calls":[{"accepts":"headless packet","parentId":9,"key":"packet"},{"accepts":"headless packet","parentId":11,"key":"packet"}]},"G":{"emits":"headless packet","calls":[]}},"pairs":{"A":{"route":"0,0","output":{"emits":"headless packet","calls":[{"accepts":"headless packet","parentId":8,"key":"packet"},{"accepts":"headless packet","parentId":10,"key":"packet"}]}},"B":{"route":"0,1","output":{"emits":"headless packet","calls":[{"accepts":"headless packet","parentId":5,"key":"packet"},{"accepts":"headless packet","parentId":6,"key":"packet"}]}},"C":{"route":"0,2","output":{"emits":"headless packet","calls":[]}},"D":{"route":"0,3","output":{"emits":"headless packet","calls":[]}},"E":{"route":"0,4","output":{"emits":"headless packet","calls":[]}}},"id":7,"path":"./src/hardware/bridge.js","ui":{"left":1629,"top":890}},{"description":{"name":"ATK Network Stepper Driver","alt":"software representation of stepper","isHardware":true},"state":{"emitters":{},"axis":"Y","spu":75,"rawMove":0.25,"makeMove":{"isButton":true,"isPressed":false,"label":"test move"},"lead":0,"position":0,"_axis":"Y","_spu":75,"_rawMove":0.25,"_makeMove":{"isButton":true,"isPressed":false,"label":"test move"},"_lead":0,"_position":0},"inputs":{"move":{"accepts":"move instruction","parentId":8,"key":"move"},"packet":{"accepts":"headless packet","parentId":8,"key":"packet"},"rmtrig":{"accepts":"event","parentId":8,"key":"rmtrig"}},"outputs":{"ack":{"emits":"move acknowledgement","calls":[]},"q":{"emits":"number","calls":[]},"packet":{"emits":"headless packet","calls":[{"accepts":"headless packet","parentId":7,"key":"A"}]}},"id":8,"path":"./src/hardware/stepper.js","ui":{"left":1629,"top":372}},{"description":{"name":"ATK Network Stepper Driver","alt":"software representation of stepper","isHardware":true},"state":{"emitters":{},"axis":"Y","spu":-75,"rawMove":0.25,"makeMove":{"isButton":true,"isPressed":false,"label":"test move"},"lead":0,"position":0,"_axis":"Y","_spu":-75,"_rawMove":0.25,"_makeMove":{"isButton":true,"isPressed":false,"label":"test move"},"_lead":0,"_position":0},"inputs":{"move":{"accepts":"move instruction","parentId":9,"key":"move"},"packet":{"accepts":"headless packet","parentId":9,"key":"packet"},"rmtrig":{"accepts":"event","parentId":9,"key":"rmtrig"}},"outputs":{"ack":{"emits":"move acknowledgement","calls":[]},"q":{"emits":"number","calls":[]},"packet":{"emits":"headless packet","calls":[{"accepts":"headless packet","parentId":7,"key":"F"}]}},"id":9,"path":"./src/hardware/stepper.js","ui":{"left":1629,"top":626}},{"description":{"name":"Test Packet","alt":"net state","isHardware":true},"state":{"emitters":{},"button":{"isButton":true,"isPressed":false,"label":"TEST"},"message":"no test started","_button":{"isButton":true,"isPressed":false,"label":"TEST"},"_message":"no test started"},"inputs":{"packet":{"accepts":"headless packet","parentId":10,"key":"packet"},"trigger":{"accepts":"event","parentId":10,"key":"trigger"}},"outputs":{"packet":{"emits":"number","calls":[{"accepts":"headless packet","parentId":7,"key":"A"}]}},"id":10,"path":"./src/hardware/test.js","ui":{"left":1060,"top":1050}},{"description":{"name":"Test Packet","alt":"net state","isHardware":true},"state":{"emitters":{},"button":{"isButton":true,"isPressed":false,"label":"TEST"},"message":"no test started","_button":{"isButton":true,"isPressed":false,"label":"TEST"},"_message":"no test started"},"inputs":{"packet":{"accepts":"headless packet","parentId":11,"key":"packet"},"trigger":{"accepts":"event","parentId":11,"key":"trigger"}},"outputs":{"packet":{"emits":"number","calls":[{"accepts":"headless packet","parentId":7,"key":"F"}]}},"id":11,"path":"./src/hardware/test.js","ui":{"left":1060,"top":1170}}] \ No newline at end of file diff --git a/save/onesave.json b/save/onesave.json new file mode 100644 index 0000000000000000000000000000000000000000..aa0f88040398157147534212ba8a81523a4361cc --- /dev/null +++ b/save/onesave.json @@ -0,0 +1,104 @@ +{ + "description": + { + "name": "tstprgmem" + }, + "modules": [ + { + "description": + { + "id": "gate-1", + "name": "gate", + "alt": "in ... out", + "path": "./src/util/gate.js" + }, + "inputs": + { + "thru": + { + "accepts": "any" + } + }, + "outputs": + { + "out": + { + "emits": "any", + "calls": [ + { + "parentId": "delay-2", + "key": "thru" + }, + { + "parentId": "logger-3", + "key": "thru" + }] + } + }, + "state": + { + "toggle": + { + "isButton": true, + "isPressed": false, + "label": "Open / Close" + }, + "message": "closed" + } + }, + { + "description": + { + "id": "delay-2", + "name": "delay", + "alt": "in ... out", + "path": "./src/util/delay.js" + }, + "inputs": + { + "thru": + { + "accepts": "any" + } + }, + "outputs": + { + "out": + { + "emits": "any", + "calls": [ + { + "parentId": "logger-3", + "key": "thru" + }] + } + }, + "state": + { + "ms": 100 + } + }, + { + "description": + { + "id": "logger-3", + "name": "logger", + "alt": "in ... out to console", + "path": "./src/util/log.js" + }, + "inputs": + { + "thru": + { + "accepts": "any" + } + }, + "outputs": + {}, + "state": + { + "prefix": "LOGGER:", + "message": "---" + } + }] +} \ No newline at end of file diff --git a/save/otms.json b/save/otms.json new file mode 100644 index 0000000000000000000000000000000000000000..aa0f88040398157147534212ba8a81523a4361cc --- /dev/null +++ b/save/otms.json @@ -0,0 +1,104 @@ +{ + "description": + { + "name": "tstprgmem" + }, + "modules": [ + { + "description": + { + "id": "gate-1", + "name": "gate", + "alt": "in ... out", + "path": "./src/util/gate.js" + }, + "inputs": + { + "thru": + { + "accepts": "any" + } + }, + "outputs": + { + "out": + { + "emits": "any", + "calls": [ + { + "parentId": "delay-2", + "key": "thru" + }, + { + "parentId": "logger-3", + "key": "thru" + }] + } + }, + "state": + { + "toggle": + { + "isButton": true, + "isPressed": false, + "label": "Open / Close" + }, + "message": "closed" + } + }, + { + "description": + { + "id": "delay-2", + "name": "delay", + "alt": "in ... out", + "path": "./src/util/delay.js" + }, + "inputs": + { + "thru": + { + "accepts": "any" + } + }, + "outputs": + { + "out": + { + "emits": "any", + "calls": [ + { + "parentId": "logger-3", + "key": "thru" + }] + } + }, + "state": + { + "ms": 100 + } + }, + { + "description": + { + "id": "logger-3", + "name": "logger", + "alt": "in ... out to console", + "path": "./src/util/log.js" + }, + "inputs": + { + "thru": + { + "accepts": "any" + } + }, + "outputs": + {}, + "state": + { + "prefix": "LOGGER:", + "message": "---" + } + }] +} \ No newline at end of file diff --git a/save/twosave.json b/save/twosave.json new file mode 100644 index 0000000000000000000000000000000000000000..fd9d0a530ebdbe79afbaaaafd342eea264b0bbc7 --- /dev/null +++ b/save/twosave.json @@ -0,0 +1,92 @@ +{ + "description": + { + "name": "tstprgmem" + }, + "modules": [ + { + "description": + { + "id": "gate-1", + "name": "gate", + "alt": "in ... out", + "path": "./src/util/gate.js" + }, + "inputs": + { + "thru": + { + "accepts": "any" + } + }, + "outputs": + { + "out": + { + "emits": "any", + "calls": [] + } + }, + "state": + { + "toggle": + { + "isButton": true, + "isPressed": false, + "label": "Open / Close" + }, + "message": "closed" + } + }, + { + "description": + { + "id": "delay-2", + "name": "delay", + "alt": "in ... out", + "path": "./src/util/delay.js" + }, + "inputs": + { + "thru": + { + "accepts": "any" + } + }, + "outputs": + { + "out": + { + "emits": "any", + "calls": [] + } + }, + "state": + { + "ms": 100 + } + }, + { + "description": + { + "id": "logger-3", + "name": "logger", + "alt": "in ... out to console", + "path": "./src/util/log.js" + }, + "inputs": + { + "thru": + { + "accepts": "any" + } + }, + "outputs": + {}, + "state": + { + "prefix": "LOGGER:", + "message": "---" + } + }] +} \ No newline at end of file diff --git a/scratch.js b/scratch.js deleted file mode 100644 index 3c9a5440974baa48640194368f9d97fd844522c0..0000000000000000000000000000000000000000 --- a/scratch.js +++ /dev/null @@ -1,14 +0,0 @@ - -function writeStateRep(rep, key){ - // ui including different input types ... + button to fire? - var li = document.createElement('li') - li.appendChild(document.createTextNode(key + ':')) - var input = document.createElement('input') - input.type = 'text' - input.size = 20 - li.appendChild(input) - input.addEventListener('change', function(){ - console.log('update', rep.state, key) - }) - return li -} \ No newline at end of file diff --git a/atkterminal.js b/scratch/atkterminal.js similarity index 100% rename from atkterminal.js rename to scratch/atkterminal.js diff --git a/run.js b/scratch/run.js similarity index 100% rename from run.js rename to scratch/run.js diff --git a/scratch/scratch.js b/scratch/scratch.js new file mode 100644 index 0000000000000000000000000000000000000000..5ba65416a7370c8de0d848539452ecd1f34d11ba --- /dev/null +++ b/scratch/scratch.js @@ -0,0 +1,81 @@ + +function writeStateRep(rep, key){ + // ui including different input types ... + button to fire? + var li = document.createElement('li') + li.appendChild(document.createTextNode(key + ':')) + var input = document.createElement('input') + input.type = 'text' + input.size = 20 + li.appendChild(input) + input.addEventListener('change', function(){ + console.log('update', rep.state, key) + }) + return li +} + + +function addModule(list, path) { + // get and add to server system + if (fs.existsSync(path)) { + var src = require(path) // get and return + var mod = new src() // make a new one + list.push(mod) + // assign and id and remember from whence it came + mod.id = list.length - 1 + mod.path = path + + // we need to add some top-level info to the inputs so that we can draw them + for (item in mod.inputs) { + mod.inputs[item].parentId = mod.id + mod.inputs[item].key = item + } + + for (item in mod.state) { + if (item == 'onChange' | item == 'emitChange' | item == 'emitters') { + //console.log('rolling past change fn') + } else { + mod.state['_' + item] = mod.state[item] + mod.state[item] = {} + writeStateObject(mod, item) + } + } + + console.log('ADDING MODULE', mod.description.name) + + // now roll and return representable object + // first to UI + + // putRep(mod) + + // also to fn call, in case writing program ? + return mod + } else { + console.log('ERR no module found at', path) + } +} + + +/* + +fs.writeFile('save/mdls.json', JSON.stringify(modules), 'utf8', function(err){ + if(err) throw err + console.log('wrote file') +}) + +*/ + +function loadPrgmem(desc) { + // a collection of modules + var modules = new Array() + + // go through once and load in memory + for (obj in desc.nodes) { + console.log(desc.nodes[obj].path) + addModule(modules, desc.nodes[obj].path) + } + for (obj in desc.nodes) { + var lst = desc.nodes[obj].connects + // 1st item is output, all others are inputs + console.log(lst) + } +} \ No newline at end of file diff --git a/terminalMachine.js b/scratch/terminalMachine.js similarity index 100% rename from terminalMachine.js rename to scratch/terminalMachine.js diff --git a/src/util/delay.js b/src/util/delay.js index 1d19c018da14a6ef4afc826762cada47838d74f4..21e43be4f5a3ef94edfa96e237b39262371ba469 100644 --- a/src/util/delay.js +++ b/src/util/delay.js @@ -1,8 +1,9 @@ // boilerplate atkapi header -const InOut = require('../../lib/inout.js') -let Input = InOut.Input -let Output = InOut.Output -let State = InOut.State +// boilerplate header +const JSUnit = require('../../lib/jsunit.js') +let Input = JSUnit.Input +let Output = JSUnit.Output +let State = JSUnit.State // a constructor, a fn, a javascript mess function Delay() { @@ -10,7 +11,7 @@ function Delay() { var delay = { // descriptions are used in UI description: { - name: 'delay!', + name: 'delay', alt: 'in ... out' } } diff --git a/src/util/gate.js b/src/util/gate.js index 7a3b012916d541bb50b1753e0cdf0a9a7af41686..e9b8fdd93336ad51179ffc3b326e04793faa89b7 100644 --- a/src/util/gate.js +++ b/src/util/gate.js @@ -1,9 +1,9 @@ -// boilerplate atkapi header -const InOut = require('../../lib/inout.js') -let Input = InOut.Input -let Output = InOut.Output -let State = InOut.State -let Button = InOut.Button +// boilerplate header +const JSUnit = require('../../lib/jsunit.js') +let Input = JSUnit.Input +let Output = JSUnit.Output +let State = JSUnit.State +let Button = JSUnit.Button // a constructor, a fn, a javascript mess function Gate() { diff --git a/src/util/log.js b/src/util/log.js index 60403c42985f0d6494b391bbecb83c2f823050e6..3af0f622663b53a656ee95d79d7ec03974d4c93a 100644 --- a/src/util/log.js +++ b/src/util/log.js @@ -1,8 +1,8 @@ -// boilerplate atkapi header -const InOut = require('../../lib/inout.js') -let Input = InOut.Input -let Output = InOut.Output -let State = InOut.State +// boilerplate header +const JSUnit = require('../../lib/jsunit.js') +let Input = JSUnit.Input +let Output = JSUnit.Output +let State = JSUnit.State // a constructor, a fn, a javascript mess function Logger() { @@ -10,7 +10,7 @@ function Logger() { var logger = { // descriptions are used in UI description: { - name: 'logger!', + name: 'logger', alt: 'in ... out to console' } }