Files
P42_UI/test.js
T
2025-09-21 20:08:12 +00:00

118 lines
4.7 KiB
JavaScript

class SnapToBus{
constructor(config){
this._curBusConfig = []
this._stagedBusConfig = config // null Means nothing uncommitted
this.commitConfig()
}
get busConfig() { return this._stagedBusConfig }
get liveBusConfig() { return this._curBusConfig }
set busConfig(newConfig) { this._stagedBusConfig = newConfig }
async commitConfig(){
const chansToAdd = []
const chansToKeep = []
console.log('=======>_stagedBusConfig', this._stagedBusConfig)
for(const chanObj of this._stagedBusConfig){
console.log('staged chan:',chanObj.chan,' current ones:', this._curBusConfig.map(item => item.chan))
if(this._curBusConfig.map(item => item.chan).includes(chanObj.chan)) chansToKeep.push(chanObj)
else chansToAdd.push(chanObj)
}
const chansToDel = this._curBusConfig.filter(item => (!chansToKeep.map(c=>c.chan).includes(item.chan) && !chansToAdd.map(c=>c.chan).includes(item.chan)))
app.MessageBus.subscribe(chansToAdd.map(item => item.chan))
app.MessageBus.unSubscribe(chansToDel.map(item => item.chan))
// console.log('subscribe:', chansToAdd.map(item => item.chan))
// console.log('unSubscribe:', chansToDel)
const eventsToAdd = chansToAdd.flatMap(item => item.events.map(ev => ({ chan:item.chan, eventName:ev.eventName })))
let eventsToDel = []//= chansToDel.flatMap(item => item.events.map(ev => ({ chan:item.chan, eventName:ev.eventName })))
for(const oldChan of this._curBusConfig){
for(const oldEvent of oldChan.events){
for(const keepChan of chansToKeep){
if(!keepChan.events.map(item=>item.eventName).includes(oldEvent.eventName)) eventsToDel.push({chan: oldChan.chan, eventName: oldEvent.eventName})
}
}
}
// console.log('eventsToAdd:', eventsToAdd)
// console.log('eventsToDel:', eventsToDel)
for(const eventToAdd of eventsToAdd){
app.MessageBus.addBusListener(eventToAdd.eventName, [eventToAdd.chan], this.processBus.bind(this), 'snaptobus')
}
for(const eventToDel of eventsToDel){
app.MessageBus.removeBusListener(eventToDel.eventName, this.processBus.bind(this), 'snaptobus')
}
this._curBusConfig = this.deepClone(this._stagedBusConfig)
}
deepClone(obj) { // Needed because structuredClone doesn't take functions (and we have transformers)
if (obj === null || typeof obj !== 'object') {
return obj
}
if (Array.isArray(obj)) {
return obj.map((el => this.deepClone(el)))
}
const clone = {}
for (const key in obj) {
clone[key] = this.deepClone(obj[key])
}
return clone
}
}
const s2bConfig = [
{ chan: 'gps:agents', // What to subscribe to
events: [ // What to select on this chan
{ eventName: 'moving',
snaps: [
{
// selector will be used as css selector for a snap element / group,
// with LAST MINUTE template resolving of event properties (with eventual dots)
selector: '#${aid}',
assign: {
x: 'coords.x', // type string: event property, eventual dots to go down object
y: 'coords.y',
},
animate: true
}
]
},
{ eventName: 'rotating',
snaps: [
{
selector: '#${aid}',
assign: {
r: 'rotangle'
},
animate: true
}
]
},
]
},
{ chan: 'agent:*', // wildcards allowed
events: [
{ eventName: 'aging',
snaps: [
{
selector: '#{aid}',
assign: {
fill: { // transformer function
arguments: [ 'age' ], // What to give from the event as function's params
transformer: i => `rgb(${Math.round(255 * i / 10)},0,${Math.round(255 * (1 - i / 10))})`
},
},
}
]
},
]
},
]
t = new SnapToBus(s2bConfig)
console.log('----------------------------------------')
t.busConfig.splice(1, 1)
t.busConfig[0].events.splice(1, 1)
t.commitConfig()