Files
Superalgos/FloatingSpace/NoteSets.js
T

315 lines
16 KiB
JavaScript


function newNoteSets () {
/*
Different plotters will identify sets of notes whithin the data they are plotting. They will create with them arrays of Notes data.
On the other hand the floating space, and a floting layer in particular, manages Notes floating objects, which are visible entities
that floats on the screen. These entities are animated at a certain peace, and their life cycle differs from the life cycle of the
arrays of raw data plotters have.
The purpose of this module, is to provide a mechnism of syncronization between the raw data and the visible floating objects and a
data structure wheere to store these floating objects.
A NoteSet in this context is an array of Notes floating objects belonging to the same owner, which could be a certain bot for instance.
This module is capable of managing an array of NoteSets.
*/
const MODULE_NAME = 'Note Sets'
const INFO_LOG = false
const INFO_WARN = true
const ERROR_LOG = true
const logger = newWebDebugLog()
logger.fileName = MODULE_NAME
let thisObject = {
createNoteSet: createNoteSet,
destroyNoteSet: destroyNoteSet,
initialize: initialize,
finalize: finalize
}
let noteSets = []
let floatingLayer
return thisObject
function initialize (pFloatingLayer) {
floatingLayer = pFloatingLayer
}
function finalize () {
floatingLayer.finalize()
floatingLayer = undefined
}
function createNoteSet (pPayload, pEventHandler, callBackFunction) {
try {
/*
During the creating of a NoteSet, no floating objects are created yet. What we do here is to create the data structure which will allocate
the Notes floating objects, once we receive the array of notes raw data from the plotter. This array will come as an event raised by the
plotter everytime it's set of raw data changes. Remember that the plotter is not only filtering out notes based on how far they are from the
position the user gives to the viewport, but also, the plotter can be receiving actually new notes from its datasource.
*/
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> Entering function.') }
let noteSet = {
imageId: pPayload.profile.imageId,
floatingNotes: [],
payload: pPayload,
handle: Math.floor((Math.random() * 10000000) + 1)
}
noteSets.push(noteSet)
pEventHandler.listenToEvent('Notes Changed', onNotesChanged, noteSets.length - 1)
callBackFunction(GLOBAL.CUSTOM_OK_RESPONSE, noteSet.handle)
function onNotesChanged (pNewNotes, pNoteSetIndex) {
try {
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Entering function.') }
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> pNewNotes.length = ' + pNewNotes.length) }
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> pNoteSetIndex = ' + pNoteSetIndex) }
let noteSet = noteSets[pNoteSetIndex]
let found = false
let newFloatingNotes
/*
First we remove the old notes. This means that we are going to scan all the floating objects that we have, and see one by one if they
are still present on the raw data sent by the plotter. If it is not there, that means that the floating object must be discarded.
*/
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes.') }
newFloatingNotes = [] // We will create a new array of Floating Notes as a result of this operation.
/*
Here we scan the curren array of floating objects. We use the date + rate to create a unique key for each one, in order to be able to
compare it with the raw data. You will notice that instead of deleting from the current array what we actually do is to add the ones
that are still at the raw data array to a new array, and not adding the ones that are not.
*/
for (let j = 0; j < noteSet.floatingNotes.length; j++) {
found = false
let floatingNote = noteSet.floatingNotes[j]
let floatingNoteKey = floatingNote.date.toString() + floatingNote.rate.toString()
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> j = ' + j) }
let i
for (let i = 0; i < pNewNotes.length; i++) {
let plotterNote = pNewNotes[i]
let plotterNoteKey = plotterNote.date.toString() + plotterNote.rate.toString()
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> i = ' + i) }
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> floatingNoteKey = ' + floatingNoteKey) }
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> plotterNoteKey = ' + plotterNoteKey) }
if (plotterNoteKey === floatingNoteKey) {
found = true
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> found = ' + found) }
break
}
}
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> End of For i.') }
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> found = ' + found) }
if (found === false) {
/*
Each time we identify a floatingObject that is not at the raw data anymore, we request the floatinglayer to kill it.
*/
floatingLayer.removeFloatingObject(floatingNote.floatingHandle)
} else {
newFloatingNotes.push(floatingNote)
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> floatingNote.floatingHandle = ' + floatingNote.floatingHandle) }
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> Added to newFloatingNotes.') }
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> newFloatingNotes.length = ' + newFloatingNotes.length) }
/*
We set a property at each floatingObject of which is the index of the note at the raw data array, so that it can later evaluate its position or its visibility.
*/
let floatingObject = floatingLayer.getFloatingObject(floatingNote.floatingHandle)
floatingObject.payloadNoteIndex = i
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> floatingObject index updated.') }
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> floatingObject.payloadNoteIndex = ' + i) }
}
}
/*
We replace the current array, with the new one that only contains the surviving floating objects, meaning the ones that are still at the raw data received.
*/
noteSet.floatingNotes = newFloatingNotes
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> noteSet.floatingNotes.length = ' + noteSet.floatingNotes.length) }
/*
Second we add the new notes. There might be new notes at the raw data received that we didnt have before at the NodeSet array. To figure out which
ones are, we need to scan the raw data array and compare each element with the ones of the NodeSet array. Whenever we find one that is not there,
we add it.
*/
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes.') }
newFloatingNotes = [] // We will create a new array of Floating Notes as a result of this operation.
/*
We are using the date and rate as a unique key to identify each note. To prevent the cases of duplicate keys, we will check that at
least to consecutive records dont have the same key, and if they do, will ignore the second one.
*/
let lastPlotterKey = ''
for (let i = 0; i < pNewNotes.length; i++) {
found = false
let plotterNote = pNewNotes[i]
let plotterNoteKey = plotterNote.date.toString() + plotterNote.rate.toString()
let floatingNote
let floatingNoteKey
if (lastPlotterKey === plotterNoteKey) {
if (INFO_WARN === true) { logger.write('[WARN] createNoteSet -> onNotesChanged -> Add new Notes -> Duplicate record detected. Discarding it.') }
if (INFO_WARN === true) { logger.write('[WARN] createNoteSet -> onNotesChanged -> Add new Notes -> i = ' + i) }
continue
}
lastPlotterKey = plotterNoteKey
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> i = ' + i) }
for (let j = 0; j < noteSet.floatingNotes.length; j++) {
floatingNote = noteSet.floatingNotes[j]
floatingNoteKey = floatingNote.date.toString() + floatingNote.rate.toString()
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> j = ' + j) }
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> floatingNoteKey = ' + floatingNoteKey) }
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> plotterNoteKey = ' + plotterNoteKey) }
if (plotterNoteKey === floatingNoteKey) {
found = true
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> found = ' + found) }
break
}
}
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> End of For j.') }
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> found = ' + found) }
if (found === false) {
/*
Before adding a new item to the array, we need to create a floatingObject of type Note. Once we set its basic parameters
we can it to our array and to the floating layer.
*/
let floatingObject = newFloatingObject()
floatingObject.initialize('Note', '', floatingLayer)
floatingObject.payload = noteSet.payload
floatingObject.payloadNoteIndex = i
floatingObject.payloadImageId = noteSet.imageId
floatingObject.friction = 0.995
floatingObject.initializeMass(200)
// let bodyText = pNewNotes[i].body;
let radius
/*
if (bodyText.length < 100) {
radius = 100;
} else {
radius = bodyText.length;
}
*/
radius = 50
floatingObject.initializeRadius(radius)
floatingObject.initializeImageSize(15)
floatingObject.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 0.5)'
floatingObject.labelStrokeStyle = 'rgba(60, 60, 60, 0.50)'
floatingLayer.addFloatingObject(floatingObject)
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> New Note added to Layer.') }
plotterNote.floatingHandle = floatingObject.handle
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> plotterNote.floatingHandle = ' + plotterNote.floatingHandle) }
newFloatingNotes.push(plotterNote)
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> Added to newFloatingNotes.') }
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> newFloatingNotes.length = ' + newFloatingNotes.length) }
} else {
newFloatingNotes.push(floatingNote)
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> Old Note Kept.') }
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> floatingNote.floatingHandle = ' + floatingNote.floatingHandle) }
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> Added to newFloatingNotes.') }
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> newFloatingNotes.length = ' + newFloatingNotes.length) }
let floatingObject = floatingLayer.getFloatingObject(floatingNote.floatingHandle)
floatingObject.payloadNoteIndex = i
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> floatingObject index updated.') }
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> floatingObject.payloadNoteIndex = ' + i) }
}
}
noteSet.floatingNotes = newFloatingNotes
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> noteSet.floatingNotes.length = ' + noteSet.floatingNotes.length) }
} catch (err) {
if (ERROR_LOG === true) { logger.write('[ERROR] createNoteSet -> onNotesChanged -> err = ' + err.stack) }
}
}
} catch (err) {
if (ERROR_LOG === true) { logger.write('[ERROR] createNoteSet -> err = ' + err.stack) }
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
}
}
function destroyNoteSet (pHandle) {
try {
/*
Usually when a bot is disabled by the end user, or the zoom level changes to one where the notes must not be seen, this method
to destroy an entire NoteSet is executed. What we do in this situation is to localize the NoteSet to be destroyed and we need to
kill, one by one the floating objects in it. Finally we remove this NoteSet item from the NoteSets array.
*/
if (INFO_LOG === true) { logger.write('[INFO] destroyNoteSet -> Entering function.') }
for (let i = 0; i < noteSets.length; i++) {
let noteSet = noteSets[i]
if (noteSet.handle === pHandle) {
for (let j = 0; j < noteSet.floatingNotes.length; j++) {
let floatingNote = noteSet.floatingNotes[j]
floatingLayer.removeFloatingObject(floatingNote.floatingHandle)
}
noteSets.splice(i, 1) // Delete item from array.
return
}
}
} catch (err) {
if (ERROR_LOG === true) { logger.write('[ERROR] destroyNoteSet -> err = ' + err.stack) }
}
}
}