Newer
Older
- scrape to manager,
- manager gogetter ... and then, hello click
- and then, nicely:
- also - link for flowcontrol when downstream non-conn ? the init-over-link question? a few states ...
- div structure ... ? open something up just barely, to test node and scraper
- beer 2 celly
- div structure: the div(div) scaling unfuckery
import {
Hunkify,
Input,
Output,
State
} from './hunks.js'
TSET, // typset
MK, // manager keys,
HK, // hunk keys,
MSGS // messaging
// yonder def, the ui mirror on hunks
import HunkDefinition from '../view/vdef.js'
// to file-organize view.js, a monster
import BezierTools from '../view/vbzt.js'
let verbose = true
let msgverbose = true
let msgsin = new Input('byteArray', 'msgs', this)
let msgsout = new Output('byteArray', 'msgs', this)
Jake Read
committed
this.inputs.push(msgsin)
this.outputs.push(msgsout)
// das UI globals
// our dom is the space we're allotted,
this.dom = {}
// the plane, one layer beneath, is where divs live
this.plane = {}
// we have a list of definitions,
let defs = new Array()
// tools to write dom-representations of hunks,
let dt = new DomTools(this)
// and tools for the links,
let bzt = new BezierTools(this)
// and for program (patch) management
let patchset = new PatchSet(this, msgbox)
/* --------------------------- ---------------------------- */
/* -------------------- INIT, LISTENERS ---------------------- */
/* --------------------------- ---------------------------- */
this.init = () => {
// in the case of UIs, we have the dom before init runs,
// so this is kind of like the 'window.onload' function
this.log('hello ui')
this.dom = $('<div>').addClass('view').get(0)
// for nested dom elements,
this.plane = $('<div>').addClass('plane').get(0)
// to log, type, etc
let dft = {
s: 1,
x: 0,
y: 0,
ox: 0,
oy: 0
dt.writeTransform(this.plane, dft)
dt.writeBackgroundTransform(this.dom, dft)
this.dom.addEventListener('wheel', mouseWheelListener)
this.dom.addEventListener('mousedown', (evt) => {
if ($(evt.target).is('.view')) {
evt.preventDefault()
evt.stopPropagation()
window.addEventListener('mousemove', canvasDragListener)
window.addEventListener('mouseup', canvasUpListener)
} else if ($(evt.target).is('input')) {
// no op
} else {
// prevents bubbling up outside of the view, potentially a bug farm ?
// evt.preventDefault()
// evt.stopPropagation()
}
})
// get the context menu on righ click
this.dom.addEventListener('contextmenu', onContextMenu)
// append
$(this.dom).append(this.plane)
// key listeners
// keys are global, so ... idk how to unfoof this yet, but
document.addEventListener('keydown', (evt) => {
//writeMessage('addhunk', 'link')
//writeMessage('addprogram', 'ntlink')
//writeMessage('addprogram', 'llink')
} else if (evt.keyCode === 27) {
// escapekey
$(this.plane).children('.contextmenu').remove()
Jake Read
committed
// also find floaters ...
// END INIT CODE
Jake Read
committed
this.refresh = () => {
// wipe ya docs, and ask yonder manager for a complete description
// everything is friggen jquery, so check it out
$(this.plane).children('.block').remove()
// and then say hello,
writeMessage([MK.REQDESCRIBESELF])
Jake Read
committed
// that's fine, we can wait for a response, but we have to track and setup the next move
}
if (!$(evt.target).is('.view') && !$(evt.target).is('#floater')) {
return false
}
evt.preventDefault()
evt.stopPropagation()
let ds
if (evt.deltaY > 0) {
ds = 0.025
} else {
ds = -0.025
}
let ct = dt.readTransform(this.plane)
ct.x += (ct.x - ox) * ds
ct.y += (ct.y - oy) * ds
dt.writeTransform(this.plane, ct)
dt.writeBackgroundTransform(this.dom, ct)
let canvasDragListener = (evt) => {
evt.preventDefault()
evt.stopPropagation()
let ct = dt.readTransform(this.plane)
dt.writeTransform(this.plane, ct)
dt.writeBackgroundTransform(this.dom, ct)
/*
this.pan.x += evt.movementX
this.pan.y += evt.movementY
this.plane.style.backgroundPosition = `${this.pan.x}px ${this.pan.y}px`
$(this.plane).children().each((index, div) => {
let tf = dt.readTransform(div)
dt.writeTransform(div, tf)
})
*/
}
let canvasUpListener = (evt) => {
window.removeEventListener('mousemove', canvasDragListener)
window.removeEventListener('mouseup', canvasUpListener)
}
// CONTEXT MENU
let onContextMenu = (evt) => {
//console.log(evt)
evt.preventDefault()
evt.stopPropagation()
Jake Read
committed
// more like
/*
-> add a hunk
-> load a program
-> save this program
-> reload this view
-> heartbeat checkin
*/
console.log('context...', evt)
// make the menu,
let menu = $('<div>').addClass('contextmenu').get(0)
// and place,
let pt = dt.readTransform(this.plane)
console.log('plane transform', pt)
// HERE: there's still some mess, not landing in the right place,
// (and there's compounding scale issues on dragging the canvas)
dt.writeTransform(menu, {
x: ((evt.clientX - pt.x) / pt.s), // (pt.s + -0.1 * (pt.s-1))),
// hmmm
this.changeContextTitle('you can... ')
// on of the options will ...
// add a hunk menu
this.addContextOption('add a hunk', (evt) => {
msgbox.write('requested a list of hunks...')
$(evt.target).text('requested a list of hunks...')
writeMessage([MK.REQLISTAVAIL])
})
this.addContextOption('load a patch', (evt) => {
Jake Read
committed
patchset.findPatches(evt)
})
this.addContextOption('save this patch', (evt) => {
patchset.saveCurrent(evt, true)
})
// writeMessage([MK.REQLISTAVAIL])
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
// takes 'under' argument
this.addContextOption = (text, click) => {
$(this.plane).find('.contextmenu').get(0).append($('<li>' + text + '</li>').click((click)).get(0))
}
this.changeContextTitle = (text) => {
// clear,
$(this.plane).find('.contextmenu').children().remove()
// overkill, but fun
let menu = $(this.plane).find('.contextmenu').get(0)
let title = $(`<div>${text}</div>`).addClass('contextTitle').get(0)
title.onmousedown = (evt) => {
evt.preventDefault()
evt.stopPropagation()
let domElemMouseMove = (evt) => {
// TRANSFORMS here to move div about on drag
evt.preventDefault()
evt.stopPropagation()
let ct = dt.readTransform(menu)
let pt = dt.readTransform(menu.parentElement) // think that's just this.plane ?
ct.x += evt.movementX / pt.s
ct.y += evt.movementY / pt.s
dt.writeTransform(menu, ct)
this.drawLinks()
}
function rmOnMouseUp(evt) {
document.removeEventListener('mousemove', domElemMouseMove)
document.removeEventListener('mouseup', rmOnMouseUp)
}
document.addEventListener('mousemove', domElemMouseMove)
document.addEventListener('mouseup', rmOnMouseUp)
/*
this.changeContextTitle('list of available:')
for(let item of list){
this.addContextOption(item, (evt) => {
let msg = [MK.REQADDHUNK]
MSGS.writeTo(msg, item, 'string')
Jake Read
committed
writeMessage(msg)
/* --------------------------- ---------------------------- */
/* ---------------------- 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 = []
// happens when items added, deleted (changing topology)
let updateForceLoop = () => {
// init and/or update
flsimrun = true
// start with two nodes
let positions = this.getAllHunkPositions()
index: i,
x: positions[i].x,
y: positions[i].y,
vx: 0,
.force('charge', d3.forceManyBody().strength(250))
.force('collide', d3.forceCollide((node, i, nodes) => {
return node.r
}))
.alphaMin(finAlpha)
.on('tick', flTick)
.on('end', flEnd)
// donot
} else {
// case for adding / rming from sim
if (positions.length > flnodes.length) {
let last = positions.length - 1
//console.log('to add new node like', positions[last])
index: last,
x: positions[last].x,
y: positions[last].y,
vx: 0,
// console.log('SIM adds now this', newNode.x, newNode.y)
} else {
}
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'
}
if ($(msgbox.zeCheckbox).prop('checked')) {
this.zoomExtents()
}
let flEnd = () => {
console.log('FIN DU SIM')
}
Jake Read
committed
let minxy = {
x: 0,
y: 0
}
let maxxy = {
x: 500,
y: 500
}
Jake Read
committed
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
Jake Read
committed
if (maxx > maxxy.x) {
Jake Read
committed
if (maxy > maxxy.y) {
Jake Read
committed
if (minx < minxy.x) {
Jake Read
committed
if (miny < minxy.y) {
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
Jake Read
committed
ct.x = -minxy.x * pfs
ct.y = -minxy.y * pfs
dt.writeTransform(this.plane, ct)
dt.writeBackgroundTransform(this.dom, ct)
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()
Jake Read
committed
for (let nd of nds) {
if ($(nd).attr('id') === "NROL39_0" || $(nd).attr('id') === "TLView") {
//console.log('skip')
} else {
// here is where you rm'd drawing & moving
this.drawLinks = () => {
// drawing from scratch every time ! could be faster, probably
// draw 'em all
for(let def of defs){
for(let output of def.outputs){
for(let input of output.connections){
bzt.drawLink(output, input)
}
if(output.hasFloater){
let head = bzt.getRightHandle(output.de)
let tail = bzt.getFloaterHandle(output.floater)
bzt.writeBezier(head, tail)
}
/* --------------------------- ---------------------------- */
/* -------------------- DEFS in the DOM ---------------------- */
/* --------------------------- ---------------------------- */
let deserializeNameType = (arr, bytes, i) => {
let nameresp = MSGS.readFrom(bytes, i, 'string')
let typeresp = MSGS.readFrom(bytes, i + nameresp.increment, 'string')
arr.push({
name: nameresp.item,
type: typeresp.item
})
return nameresp.increment + typeresp.increment
}
ind: null,
name: null
}
spec.inputs = new Array()
spec.outputs = new Array()
spec.states = new Array()
// hold,
let temp
// starting at 2, msgs[0] is 'hnkalive'
Jake Read
committed
let i = start
// lets write a goddang real structure an object (spec) with mirror type dom and access fn's ...
// this will make building better and better code mucho bueno
outer: while (i < bytes.length) {
switch (bytes[i]) {
case HK.IND:
temp = MSGS.readFrom(bytes, i, 'uint16')
i += temp.increment
break
case HK.NAME:
i += 1
temp = MSGS.readFrom(bytes, i, 'string')
i += temp.increment
break
case HK.INPUT:
i += 1
// expecting two strings here, name and then type
i += deserializeNameType(spec.states, bytes, i)
// ok, and the value should trail
// we don't *need* to know the type, could just read by the key, but,
temp = MSGS.readFrom(bytes, i, spec.states[spec.states.length - 1].type)
spec.states[spec.states.length - 1].value = temp.item
throw new Error(`unexpected key encountered during hunk deserialization at position ${i}: ${bytes[i]}`)
if (debug) console.log(`broke outer, len at ${bytes.length}, i at ${i}`)
// we should be able to kind of pick-thru and append based on,
if (debug) console.log('spec apres deserialize', spec)
/* --------------------------- ---------------------------- */
/* ------------------- SERIAL -> HOTMESSES ------------------- */
/* --------------------------- ---------------------------- */
let newDef = (spec) => {
// hmmm ok, we have checked that this is new, not an update,
if (verbose) console.log('ready write new spec to def', spec)
// do we have this id already? could be an update;
let def = new HunkDefinition(spec, this, dt, true)
// ...
Jake Read
committed
let mt = {}
let menu = $(this.plane).children('.contextmenu').get(0)
mt = dt.readTransform(menu)
$(menu).remove()
} else if (def.ind === 0 && def.name === 'manager') { // TEMPORARY until better management with force layout
} else if (def.ind === 1 && def.name === 'view') { // TEMPORARY until better management with force layout
} else { // also, initial placement should be determined by force layout
mt = {
s: 1,
x: Math.random() * 1000,
y: Math.random() * 800
}
// if it's in the ref-to-add *this is confusing*
let native = cuttlefishHunkRef.find((hunk) => {
return hunk.ind === def.ind
})
if (native !== undefined && native !== null) {
console.log("trying to add native hunk's dom: native:", native)
try { // try to add the dom element to the def's domelement
$(def.de).append($(native.dom).addClass('cuttlefishhunkdom'))
if ($(native.dom).is('.view')) {
de.style.height = '800px'
de.style.width = '1200px'
// leader on starting to reize these ...
/*
$(de).append($('<div>').addClass('rsHandle').on('mousedown', (evt) => {
console.log('rshandle down')
}))*/
} catch (err) {
msgbox.write(`native hunk attach fails ${err}`)
// ok, ready to place and append,
dt.writeTransform(def.de, mt)
// add the def's domelement to the view,
$(this.plane).append(def.de)
// i.e. we won't return it: it contains everything we need
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
let replaceDef = (spec) => {
// the old boy,
let od = defs[spec.ind]
// as a rule, when we replace defs, we unhook everything.
// the manager (in its wisdom) is responsible for following up by sending us
// links that are still alive,
console.log('the od', od)
// so first rm those links (this won't properly be tested until program loading, i'd bet)
for(let ip in od.inputs){
for(let op in od.inputs[ip].connections){
// a bit back asswards here ...
od.inputs[ip].connections[op].disconnect(od.inputs[ip])
}
}
// that was considerate of the others, but this whole thing is just going to get rm'd, so outputs don't matter
let mt = dt.readTransform(od.de)
// now we can *eliminate it*
$(od.de).remove()
defs[spec.ind] = null
// and replace it,
let nd = new HunkDefinition(spec, this, dt, true)
// write-over and cut all connections, we'll receive new ones
// ok, ready to place and append,
dt.writeTransform(nd.de, mt)
// add the def's domelement to the view,
$(this.plane).append(nd.de)
// and replace it in the list,
defs[spec.ind] = nd
// and re-render
this.drawLinks()
}
// for cuttlefish hunks,
let cuttlefishHunkRef = new Array()
this.take = (hunk) => {
cuttlefishHunkRef.push(hunk)
}
let removeDef = (index) => {
/* like ?
let def = defs[index]
if(!def) throw new Error('attempt to remove def that doth not exist')
*/
// get the inputs that we'll have to watch removal for
let inpts = $(this.plane).children('#' + id).children('.inputs').children('.input')
// remove the def / block
if ($(this.plane).children('#' + id).length === 0) throw new Error('trouble on remove, cannot find block with given id')
$(this.plane).children('#' + id).remove()
// we have to walk over the other outputs and disconnect them,
let otps = $(this.plane).find('.output')
for (let otp of otps) {
for (let inp of inpts) {
if (otp.connectedTo.includes('#' + inp.id)) {
otp.connectedTo.splice(otp.connectedTo.indexOf('#' + inp.id))
let putLink = (outInd, outputInd, inInd, inputInd) => {
let outputdef = defs[outInd].outputs[outputInd]
let inputdef = defs[inInd].inputs[inputInd]
outputdef.connect(inputdef)
} catch (err) {
console.log('ERR at putlink', err)
let cutLink = (outInd, outputInd, inInd, inputInd) => {
let outputdef = defs[outInd].outputs[outputInd]
let inputdef = defs[inInd].inputs[inputInd]
console.log('to disconn', outputdef, 'from', inputdef)
outputdef.disconnect(inputdef)
} catch (err) {
console.log('ERR at rmlink', err)
return true
}
return false
}
/* --------------------------- ---------------------------- */
/* ----------------- HOTMESSES -> SERIALMSGS ----------------- */
/* --------------------------- ---------------------------- */
Jake Read
committed
let helloTime = 0
this.sayHelloToManager = () => {
helloTime = performance.now()
msgbox.write(`said hello to manager at ${performance.now()}ms`)
writeMessage([MK.HELLO])
}
this.requestAddHunk = (name) => {
let msg = [MK.REQADDHUNK]
MSGS.writeTo(msg, name, 'string')
writeMessage(msg)
this.requestRemoveHunk = (ind) => {
let msg = [MK.REQRMHUNK]
MSGS.writeTo(msg, ind, 'uint16')
MSGS.writeTo(msg, output.parent.ind, 'uint16')
MSGS.writeTo(msg, output.ind, 'uint8')
MSGS.writeTo(msg, input.parent.ind, 'uint16')
MSGS.writeTo(msg, input.ind, 'uint8')
this.requestRemoveLink = (output, input) => {
MSGS.writeTo(msg, output.parent.ind, 'uint16')
MSGS.writeTo(msg, output.ind, 'uint8')
MSGS.writeTo(msg, input.parent.ind, 'uint16')
MSGS.writeTo(msg, input.ind, 'uint8')
// , numoot (number)
this.requestStateChange = (state, value) => {
// ok then, THISNOW
let msg = [MK.REQSTATECHANGE]
MSGS.writeTo(msg, state.parent.ind, 'uint16')
MSGS.writeTo(msg, state.ind, 'uint8')
// not unlikely mess here,
MSGS.writeTo(msg, value, state.type)
writeMessage(msg)
} catch (err) {
console.log('that type err:', err)
msgbox.write('err serializing state change request, see console for that type err')
}
}
/* --------------------------- ---------------------------- */
/* --------------------- MESSAGES OUTPUT --------------------- */
/* --------------------------- ---------------------------- */
Jake Read
committed
let writeMessage = (bytes) => {
if (!msgsout.io && outmsgbuffer.length < 1) {
if (msgverbose) this.log('msg out', bytes)
msgsout.put(bytes)
outmsgbuffer.push(bytes)
this.log('VIEW OUTBUFFER LEN', outmsgbuffer.length)
}
}
/* --------------------------- ---------------------------- */
/* ------------------ MESSAGES INPUT, LOOP ------------------- */
/* --------------------------- ---------------------------- */
// still looking for clear function naming / message naming
this.loop = () => {
// THE Q: is it trees or is it inputs / outputs ? ports ...
Jake Read
committed
if (msgsin.io) {
let msg = msgsin.get()
// at view, read in and deserialize list
if (msgverbose) console.log('VIEW RX MSG:', msg)
if (!Array.isArray(msg)) throw new Error(`view throwing object message, having header ${msg.header}`)
// for item, increment pulls
let temp
Jake Read
committed
case MK.ERR:
if (msgverbose) console.log('VIEW MSG is an error')
Jake Read
committed
break
Jake Read
committed
msgbox.write(`manager says hello, took ${performance.now() - helloTime}ms`)
break
case MK.BRIEF:
if (msgverbose) console.log('VIEW MSG is a manager brief')
// title, name of manager, lsit of unloaded hunks ?
msgbox.write('manger sends program brief, will begin loading...')
// serial -> js, by procedure du jakhey
let brief = {}
let bi = 1
// reading strings returns item, increment
temp = MSGS.readFrom(msg, bi, 'string')
bi += temp.increment
brief.interpreterName = temp.item
temp = MSGS.readFrom(msg, bi, 'string')
bi += temp.increment
brief.interpreterVersion = temp.item
temp = MSGS.readFrom(msg, bi, 'uint16')
bi += temp.increment
brief.numHunks = temp.item
brief.numLinks = MSGS.readFrom(msg, bi, 'uint16').item
// set local,
Jake Read
committed
this.interpreterName = brief.interpreterName
this.interpreterVersion = brief.interpreterVersion
// and write it down
if (msgverbose) console.log('VIEW MSG is a list of available items')
let stringlist = MSGS.readListFrom(msg, 1, 'string')
Jake Read
committed
this.changeContextTitle('available hunks:')
for (let item of stringlist) {
this.addContextOption(item, (evt) => {
let msg = [MK.REQADDHUNK]
MSGS.writeTo(msg, item, 'string')
writeMessage(msg)
$(evt.target).append(' > requested ... ')
})
}
// this can refer to new hunks, and modified hunk descriptions
// i.e. changing a list of outputs and inputs
if (msgverbose) console.log('VIEW MSG is a new hunk')
console.log('hunk alive, going to deserialize')
// so first we check for an existing hunk,
if(defs[spec.ind] === undefined){
newDef(spec)
msgbox.briefState.decrementHunks()
} else {
console.log('replacing hunk at', spec.ind)
replaceDef(spec)
}
Jake Read
committed
// bfstate should mixin to vptches
Jake Read
committed
case MK.HUNKSTATECHANGE:
if (msgverbose) console.log('VIEW MSG is a state change')
let stchHnkInd = MSGS.readFrom(msg, 1, 'uint16').item
let stchStInd = MSGS.readFrom(msg, 4, 'uint8').item
let stDef
try {
stDef = defs[stchHnkInd].states[stchStInd]
} catch (err) {
console.error('likely error from state change indexing', err)
}
let stValUpdate = MSGS.readFrom(msg, 6, stDef.type).item
stDef.set(stValUpdate)
Jake Read
committed
break
if (msgverbose) console.log('VIEW MSG is a hunk to remove')
let rmid = MSGS.readFrom(msg, 1, 'string').item
removeDef(rmid)
if (msgverbose) console.log('VIEW MSG is a link to put')
let addOutInd = MSGS.readFrom(msg, 1, 'uint16').item
let addOutputInt = MSGS.readFrom(msg, 4, 'uint8').item
let addInInd = MSGS.readFrom(msg, 6, 'uint16').item
let addInputInd = MSGS.readFrom(msg, 9, 'uint8').item
putLink(addOutInd, addOutputInt, addInInd, addInputInd)
//patchset.onLinkLoaded()
if (msgverbose) console.log('VIEW MSG is a link to cut')
let rmOutInd = MSGS.readFrom(msg, 1, 'uint16').item
let rmOutputInt = MSGS.readFrom(msg, 4, 'uint8').item
let rmInInd = MSGS.readFrom(msg, 6, 'uint16').item
let rmInputInd = MSGS.readFrom(msg, 9, 'uint8').item
cutLink(rmOutInd, rmOutputInt, rmInInd, rmInputInd)
throw new Error(`view receives message with no switch: ${msg[0]}`)
} // end msgs switch
} // end if-have-message
// MSGS output check,
if (outmsgbuffer.length > 0) {
let debug = true
if (!msgsout.io) {
if (debug) {
let msg = outmsgbuffer.shift()
if (msgverbose) this.log(`buffer release msg type: ${msg.header}`)
//console.log(msg.content)
msgsout.put(msg)
} else {
msgsout.put(outmsgbuffer.shift())
}
}
} // end msgs output check
} // end loop