diff --git a/hunks/manager.js b/hunks/manager.js index eb78d842b4a662410691121be1e927b0c4f868cb..7465ae541511c97ccdfddf738fec874e7e7e99a8 100644 --- a/hunks/manager.js +++ b/hunks/manager.js @@ -409,12 +409,21 @@ function Manager() { this.log(`manager hello`) } + // just a tiny helper + let idSafeReply = (msgid, bytes) => { + if(msgid){ + bytes = [MK.MSGID, msgid].concat(bytes) + } + writeMessage(bytes) + } + this.loop = () => { // getting messages if (msgsin.io) { let msg = msgsin.get() if (msgverbose) console.log('MGR RX MSG:', msg) if (!Array.isArray(msg)) throw new Error(`manager throwing object message, having header ${msg.header}`) + this.isConnectedTo = true // once let resp = new Array() let inc = 0 @@ -428,38 +437,28 @@ function Manager() { switch (msg[inc]) { case MK.HELLO: if (msgverbose) console.log('MGR MSG is hello') - this.isConnectedTo = true - if(msgid){ - writeMessage([MK.MSGID, msgid, MK.HELLO]) - } else { - writeMessage([MK.HELLO]) - } + idSafeReply(msgid, [MK.HELLO]) break - case MK.REQDESCRIBESELF: - if (msgverbose) console.log('MGR MSG is a brief request') - this.isConnectedTo = true - // with ids, this is ok - resp.push(MK.BRIEF) - MSGS.writeTo(resp, gg.interpreterName, 'string') - MSGS.writeTo(resp, gg.interpreterVersion, 'string') - MSGS.writeTo(resp, hunks.length, 'uint16') - MSGS.writeTo(resp, writeLinkList().length, 'uint16') - writeMessage(resp) - // now start sending hunks, - for (let hnk of hunks) { - let serhunk = [MK.HUNKALIVE] - serializeHunk(hnk, serhunk) - writeMessage(serhunk) - } - // and links, - let links = writeLinkList() - for (let lnk of links) { - let serlink = [MK.LINKALIVE] - MSGS.writeTo(serlink, lnk.outInd, 'uint16') - MSGS.writeTo(serlink, lnk.outputInd, 'uint8') - MSGS.writeTo(serlink, lnk.inInd, 'uint16') - MSGS.writeTo(serlink, lnk.inputInd, 'uint8') - writeMessage(serlink) + case MK.QUERY: + // do we have an index ? + if (msg.length > inc + 1){ + let queryIndex = MSGS.readFrom(msg, inc + 1, 'uint16') + if (msgverbose) console.log(`MGR MSG is a hunk query for ${queryIndex}`) + if(hunks[queryIndex] === undefined){ + // write and return an error + idSafeReply(msgid, someNewErrMsg) + } else { + serializeHunk(hnk, serhunk) + idSafeReply(msgid, serhunk) + } + } else { + if (msgverbose) console.log('MGR MSG is a top level query') + // with ids, this is ok + resp.push(MK.BRIEF) + MSGS.writeTo(resp, gg.interpreterName, 'string') + MSGS.writeTo(resp, gg.interpreterVersion, 'string') + MSGS.writeTo(resp, hunks.length, 'uint16') + idSafeReply(msgid, resp) } break case MK.REQLISTAVAIL: diff --git a/hunks/view.js b/hunks/view.js index adc8ded3ea4b32c5832c0404187c9d1c939128d0..445cb8a73976ce8c4a34a81a5ca762c0e7db7514 100644 --- a/hunks/view.js +++ b/hunks/view.js @@ -140,20 +140,6 @@ function View() { } // END INIT CODE - this.refresh = () => { - // wipe ya docs, and ask yonder manager for a complete description - // everything is friggen jquery, so check it out - console.log("REFRESHING THE VIEW") - $(this.plane).children('.def').remove() - // also, - defs.length = 0 - // hello first, - this.sayHelloToManager().then(() => { - console.log('hello, as promised') - writeMessage([MK.REQDESCRIBESELF]) - }) - } - let mouseWheelListener = (evt) => { if (!$(evt.target).is('.view') && !$(evt.target).is('#floater')) { return false @@ -251,213 +237,9 @@ function View() { } /* --------------------------- ---------------------------- */ - /* ---------------------- FORCE LAYOUT ----------------------- */ + /* ----------------------- REDRAWING ------------------------- */ /* --------------------------- ---------------------------- */ - // ok, my thoughts on this - /* - - when you're up with big programs, spend a day / a handful, just making the UI sing - - https://bl.ocks.org/mbostock/3750558 - - at the moment this is kind of 'fine' - - starting condition is mostly random (and elsewhere) - maybe some graph analysis - - for who-is-generally-downstream-of-whomst - - this is nice code golf for boring times when you have lots of graphs - - still not looking at links for layout force: do that first - - want to connect this notion with the 'design patterns' ides ... - - (links) find (comm/*) connected, arrange in a stack - - (view) finds (link) connected, also stackup ... - - the links / split through views -> this is actually a lot of the work, - - and it's not unimportant - - */ - - let blocks = new Array() - let flsimrun = false - let flsim = {} - let flnodes = [] - - let finAlpha = 0.1 - let sizemultiple = 0.5 - - // happens when items added, deleted (changing topology) - let updateForceLoop = () => { - // init and/or update - if (!flsimrun && blocks.length > 3) { - // Case for starting sim - msgbox.write('starting force sim') - flsimrun = true - // start with two nodes - let positions = this.getAllHunkPositions() - let sizes = this.getAllHunkSizes() - for (let i in positions) { - let nd = { - index: i, - x: positions[i].x, - y: positions[i].y, - vx: 0, - vy: 0, - r: sizes[i].width * sizemultiple - } - flnodes.push(nd) - } - flsim = d3.forceSimulation(flnodes) - .force('charge', d3.forceManyBody().strength(250)) - .force('center', d3.forceCenter(600, 600)) - .force('collide', d3.forceCollide((node, i, nodes) => { - return node.r - })) - .alphaMin(finAlpha) - .on('tick', flTick) - .on('end', flEnd) - } else if (blocks.length <= 3) { - // donot - } else { - // case for adding / rming from sim - msgbox.write('UPD8 Force Sim') - let positions = this.getAllHunkPositions() - let sizes = this.getAllHunkSizes() - if (positions.length > flnodes.length) { - let last = positions.length - 1 - //console.log('to add new node like', positions[last]) - let nd = { - index: last, - x: positions[last].x, - y: positions[last].y, - vx: 0, - vy: 0, - r: sizes[last].width * sizemultiple - } - flnodes.push(nd) - // console.log('SIM adds now this', newNode.x, newNode.y) - } else { - //msgbox.write("SIM DELETE CASE NOT WRITTEN") - } - flsim.nodes(flnodes) - flsim.alpha(1) - .alphaMin(finAlpha) - .restart() - } - } - - // happens when things perterbed in existing state (i.e. drags) - let kickForceLoop = () => { - // hmm... but fix the one you're dragging, say? - flsim.alpha(1).restart() - } - - let flTick = () => { - // called on sim update - let blks = $(this.plane).children('.block').not('#NROL39_0').not('#TLView') - if (blks.length !== flnodes.length) { - console.log('FLOOP NODES MISMATCH', blks.length, flnodes.length) - } else { - for (let i = 0; i < blks.length; i++) { - blks[i].style.left = flnodes[i].x + 'px' - blks[i].style.top = flnodes[i].y + 'px' - } - } - this.drawLinks() - if ($(msgbox.zeCheckbox).prop('checked')) { - this.zoomExtents() - } - } - - let flEnd = () => { - console.log('FIN DU SIM') - } - - this.zoomExtents = () => { - // to zoom-extends - let psns = this.getAllHunkPositions() - let sizes = this.getAllHunkSizes() - // bless up, these are all in 0,0 relative space - let minxy = { - x: 0, - y: 0 - } - let maxxy = { - x: 500, - y: 500 - } - let maxx, minx, maxy, miny - for (let ind in psns) { - maxx = psns[ind].x + sizes[ind].width - minx = psns[ind].x - maxy = psns[ind].y + sizes[ind].height - miny = psns[ind].y - // max cases - if (maxx > maxxy.x) { - maxxy.x = maxx - } - if (maxy > maxxy.y) { - maxxy.y = maxy - } - // min cases - if (minx < minxy.x) { - minxy.x = minx - } - if (miny < minxy.y) { - minxy.y = miny - } - } - // margin - let margin = 100 - minxy.x -= margin - minxy.y -= margin - maxxy.x += margin - maxxy.y += margin - // ok, compare bounding box to current frustrum ? - let ct = dt.readTransform(this.plane) - let wd = this.dom.clientWidth - let ht = this.dom.clientHeight - // to find scale, do - let pfsx = (wd) / (maxxy.x - minxy.x) - let pfsy = (ht) / (maxxy.y - minxy.y) - let pfs = Math.min(pfsx, pfsy) - // write em - ct.s = pfs - ct.x = -minxy.x * pfs - ct.y = -minxy.y * pfs - dt.writeTransform(this.plane, ct) - dt.writeBackgroundTransform(this.dom, ct) - } - - this.getAllHunkPositions = () => { - // returns positions as numbers, - let nds = $(this.plane).children('.block') - let positions = new Array() - for (let nd of nds) { - if ($(nd).attr('id') === "NROL39_0" || $(nd).attr('id') === "TLView") { - //console.log('skip') - } else { - let pos = dt.readXY(nd) - pos.id = nd.id - positions.push(pos) - } - } - return positions - // should do transform here ? - } - - this.getAllHunkSizes = () => { - let nds = $(this.plane).children('.block') - let sizes = new Array() - for (let nd of nds) { - if ($(nd).attr('id') === "NROL39_0" || $(nd).attr('id') === "TLView") { - //console.log('skip') - } else { - let sz = dt.readSize(nd) - sz.id = nd.id - sizes.push(sz) - } - } - return sizes - } - - // here is where you rm'd drawing & moving - this.drawLinks = () => { // drawing from scratch every time ! could be faster, probably bzt.clear(this.plane) @@ -726,7 +508,9 @@ function View() { /* ----------------- HOTMESSES -> SERIALMSGS ----------------- */ /* --------------------------- ---------------------------- */ - // mostly, this is an experiment for returning promises + // herein lay each of our unit requests, as promises, + + // hello is a ping, this.sayHelloToManager = () => { return new Promise((resolve, reject) => { let helloTime = performance.now() @@ -734,13 +518,35 @@ function View() { promiseThis([MK.HELLO], () => { msgbox.write(`manager says hello, took ${performance.now() - helloTime}ms`) resolve() - }, () => { - // 2nd callback for error cases ? - reject() + }, (errmsg) => { + reject(errmsg) }) }) } + this.queryManager = (ind) => { + return new Promise((resolve, reject) => { + if (ind) { + msgbox.write(`querying manager for hunk at ${ind}`) + let req = [MK.QUERY] + MSGS.writeTo(req, ind, 'uint16') + promiseThis(req, (def) => { + resolve(def) + }, (errmsg) => { + reject(errmsg) + }) + } else { + msgbox.write(`querying top level of manager`) + promiseThis([MK.QUERY], (brief) => { + msgbox.write(``) + resolve(brief) + }, (errmsg) => { + reject(errmsg) + }) + } + }) + } + this.requestAddHunk = (name, states) => { let msg = [MK.REQADDHUNK] MSGS.writeTo(msg, name, 'string') @@ -803,6 +609,27 @@ function View() { } } + /* --------------------------- ---------------------------- */ + /* ------------------------ RECEPIES ------------------------- */ + /* --------------------------- ---------------------------- */ + + this.refresh = () => { + // wipe ya docs, and ask yonder manager for a complete description + // everything is friggen jquery, so check it out + console.log("REFRESHING THE VIEW") + $(this.plane).children('.def').remove() + // also, + defs.length = 0 + // hello first, + this.sayHelloToManager().then(() => { + console.log('hello, so ready to refresh') + this.queryManager().then((brief) => { + // should have a list then, do that brief then ? + console.log('promise brief', brief) + }) + }) + } + /* --------------------------- ---------------------------- */ /* --------------------- MESSAGES OUTPUT --------------------- */ /* --------------------------- ---------------------------- */ @@ -825,7 +652,7 @@ function View() { let callbackSets = new Array() let cbid = 0 - let promiseThis = (bytes, callback) => { + let promiseThis = (bytes, callback, errback) => { cbid++ if (cbid > 254) { cbid = 0 @@ -834,7 +661,8 @@ function View() { callbackSets.push({ key: bytes[0], id: cbid, - callback: callback + callback: callback, + errback: errback }) // so our header is like - we don't explicitly type the id, it's a byte let head = [MK.MSGID, cbid] @@ -860,7 +688,7 @@ function View() { let inc = 0 // track the msg id response, and that callback let msgid, cbd - if(msg[0] === MK.MSGID){ + if (msg[0] === MK.MSGID) { msgid = msg[1] inc = 2 // and find the callback we registered @@ -873,12 +701,16 @@ function View() { switch (msg[inc]) { case MK.ERR: if (msgverbose) console.log('VIEW MSG is an error') - msgbox.write(MSGS.readFrom(msg, inc + 1, 'string').item) + let errmsg = MSGS.readFrom(msg, inc + 1, 'string').item + console.error('view caught err from manager') + console.error(errmsg) + msgbox.write(errmsg) + if (cbd) cbd.errback(errmsg) break case MK.HELLO: if (msgverbose) console.log('VIEW MSG is hello') // that callback baybiiiie - if(cbd){ + if (cbd) { cbd.callback() } else { msgbox.write(`manager says hello!`) @@ -890,7 +722,7 @@ function View() { msgbox.write('manger sends program brief, will begin loading...') // serial -> js, by procedure du jakhey let brief = {} - inc ++ + inc++ // reading strings returns item, increment temp = MSGS.readFrom(msg, inc, 'string') inc += temp.increment @@ -901,12 +733,12 @@ function View() { temp = MSGS.readFrom(msg, inc, 'uint16') inc += temp.increment brief.numHunks = temp.item - brief.numLinks = MSGS.readFrom(msg, inc, 'uint16').item // set local, this.interpreterName = brief.interpreterName this.interpreterVersion = brief.interpreterVersion // and write it down msgbox.briefState.setFromBrief(brief) + if (cbd) cbd.callback(brief) break case MK.LISTOFAVAIL: if (msgverbose) console.log('VIEW MSG is a list of available items') diff --git a/typeset.js b/typeset.js index 8d2cd7e480957d4068502e49fa665241d76c74bd..ad72239ca72d8c9a93118d9ab622a0a73769d40e 100644 --- a/typeset.js +++ b/typeset.js @@ -355,7 +355,7 @@ const MK = { // heartbeats, wakeup HELLO: 253, // (eom) // request a top-level description - REQDESCRIBESELF: 251, // (eom) + QUERY: 251, // (eom) BRIEF: 250, // (str) name of interpreter, # hunks, # links (and then begin firing list back) // please show what is available REQLISTAVAIL: 249, // (eom) diff --git a/view/vfloop.js b/view/vfloop.js new file mode 100644 index 0000000000000000000000000000000000000000..21bdb7858ccec0c616e73ea8b4c3581799f185d8 --- /dev/null +++ b/view/vfloop.js @@ -0,0 +1,209 @@ +// view force layout, + + /* --------------------------- ---------------------------- */ + /* ---------------------- FORCE LAYOUT ----------------------- */ + /* --------------------------- ---------------------------- */ + + // ok, my thoughts on this + /* + + when you're up with big programs, spend a day / a handful, just making the UI sing + - https://bl.ocks.org/mbostock/3750558 + + at the moment this is kind of 'fine' + - starting condition is mostly random (and elsewhere) - maybe some graph analysis + - for who-is-generally-downstream-of-whomst + - this is nice code golf for boring times when you have lots of graphs + - still not looking at links for layout force: do that first + - want to connect this notion with the 'design patterns' ides ... + - (links) find (comm/*) connected, arrange in a stack + - (view) finds (link) connected, also stackup ... + - the links / split through views -> this is actually a lot of the work, + - and it's not unimportant + + */ + + let blocks = new Array() + let flsimrun = false + let flsim = {} + let flnodes = [] + + let finAlpha = 0.1 + let sizemultiple = 0.5 + + // happens when items added, deleted (changing topology) + let updateForceLoop = () => { + // init and/or update + if (!flsimrun && blocks.length > 3) { + // Case for starting sim + msgbox.write('starting force sim') + flsimrun = true + // start with two nodes + let positions = this.getAllHunkPositions() + let sizes = this.getAllHunkSizes() + for (let i in positions) { + let nd = { + index: i, + x: positions[i].x, + y: positions[i].y, + vx: 0, + vy: 0, + r: sizes[i].width * sizemultiple + } + flnodes.push(nd) + } + flsim = d3.forceSimulation(flnodes) + .force('charge', d3.forceManyBody().strength(250)) + .force('center', d3.forceCenter(600, 600)) + .force('collide', d3.forceCollide((node, i, nodes) => { + return node.r + })) + .alphaMin(finAlpha) + .on('tick', flTick) + .on('end', flEnd) + } else if (blocks.length <= 3) { + // donot + } else { + // case for adding / rming from sim + msgbox.write('UPD8 Force Sim') + let positions = this.getAllHunkPositions() + let sizes = this.getAllHunkSizes() + if (positions.length > flnodes.length) { + let last = positions.length - 1 + //console.log('to add new node like', positions[last]) + let nd = { + index: last, + x: positions[last].x, + y: positions[last].y, + vx: 0, + vy: 0, + r: sizes[last].width * sizemultiple + } + flnodes.push(nd) + // console.log('SIM adds now this', newNode.x, newNode.y) + } else { + //msgbox.write("SIM DELETE CASE NOT WRITTEN") + } + flsim.nodes(flnodes) + flsim.alpha(1) + .alphaMin(finAlpha) + .restart() + } + } + + // happens when things perterbed in existing state (i.e. drags) + let kickForceLoop = () => { + // hmm... but fix the one you're dragging, say? + flsim.alpha(1).restart() + } + + let flTick = () => { + // called on sim update + let blks = $(this.plane).children('.block').not('#NROL39_0').not('#TLView') + if (blks.length !== flnodes.length) { + console.log('FLOOP NODES MISMATCH', blks.length, flnodes.length) + } else { + for (let i = 0; i < blks.length; i++) { + blks[i].style.left = flnodes[i].x + 'px' + blks[i].style.top = flnodes[i].y + 'px' + } + } + this.drawLinks() + if ($(msgbox.zeCheckbox).prop('checked')) { + this.zoomExtents() + } + } + + let flEnd = () => { + console.log('FIN DU SIM') + } + + this.zoomExtents = () => { + // to zoom-extends + let psns = this.getAllHunkPositions() + let sizes = this.getAllHunkSizes() + // bless up, these are all in 0,0 relative space + let minxy = { + x: 0, + y: 0 + } + let maxxy = { + x: 500, + y: 500 + } + let maxx, minx, maxy, miny + for (let ind in psns) { + maxx = psns[ind].x + sizes[ind].width + minx = psns[ind].x + maxy = psns[ind].y + sizes[ind].height + miny = psns[ind].y + // max cases + if (maxx > maxxy.x) { + maxxy.x = maxx + } + if (maxy > maxxy.y) { + maxxy.y = maxy + } + // min cases + if (minx < minxy.x) { + minxy.x = minx + } + if (miny < minxy.y) { + minxy.y = miny + } + } + // margin + let margin = 100 + minxy.x -= margin + minxy.y -= margin + maxxy.x += margin + maxxy.y += margin + // ok, compare bounding box to current frustrum ? + let ct = dt.readTransform(this.plane) + let wd = this.dom.clientWidth + let ht = this.dom.clientHeight + // to find scale, do + let pfsx = (wd) / (maxxy.x - minxy.x) + let pfsy = (ht) / (maxxy.y - minxy.y) + let pfs = Math.min(pfsx, pfsy) + // write em + ct.s = pfs + ct.x = -minxy.x * pfs + ct.y = -minxy.y * pfs + dt.writeTransform(this.plane, ct) + dt.writeBackgroundTransform(this.dom, ct) + } + + this.getAllHunkPositions = () => { + // returns positions as numbers, + let nds = $(this.plane).children('.block') + let positions = new Array() + for (let nd of nds) { + if ($(nd).attr('id') === "NROL39_0" || $(nd).attr('id') === "TLView") { + //console.log('skip') + } else { + let pos = dt.readXY(nd) + pos.id = nd.id + positions.push(pos) + } + } + return positions + // should do transform here ? + } + + this.getAllHunkSizes = () => { + let nds = $(this.plane).children('.block') + let sizes = new Array() + for (let nd of nds) { + if ($(nd).attr('id') === "NROL39_0" || $(nd).attr('id') === "TLView") { + //console.log('skip') + } else { + let sz = dt.readSize(nd) + sz.id = nd.id + sizes.push(sz) + } + } + return sizes + } + + // here is where you rm'd drawing & moving