From f0fc58433729b14356356840343a527f25de67d7 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Sun, 31 Mar 2019 09:29:00 +0200 Subject: [PATCH] Work in progress on the Simulation Executor --- Project.njsproj | 3 + SimulationExecution.js | 955 +++++++++++++++++++++++++++++++++++++++ this.plotter.config.json | 8 + 3 files changed, 966 insertions(+) create mode 100644 SimulationExecution.js diff --git a/Project.njsproj b/Project.njsproj index 22f4dcca1..f3ac2708b 100644 --- a/Project.njsproj +++ b/Project.njsproj @@ -23,6 +23,9 @@ Code + + Code + diff --git a/SimulationExecution.js b/SimulationExecution.js new file mode 100644 index 000000000..d912be97b --- /dev/null +++ b/SimulationExecution.js @@ -0,0 +1,955 @@ +function newAAMastersPlottersTradingSimulationSimulationExecution() { + + const MODULE_NAME = "Simulation Execution Plotter"; + const INFO_LOG = false; + const INTENSIVE_LOG = false; + const ERROR_LOG = true; + const logger = newWebDebugLog(); + logger.fileName = MODULE_NAME; + + let thisObject = { + + // Main functions and properties. + + initialize: initialize, + finalize: finalize, + container: undefined, + getContainer: getContainer, + setTimePeriod: setTimePeriod, + setDatetime: setDatetime, + recalculateScale: recalculateScale, + draw: draw, + payload: { + profile: { + position: { + x: 0, + y: 0 + }, + visible: false + }, + notes: [] + } + }; + + /* this is part of the module template */ + + let container = newContainer(); // Do not touch this 3 lines, they are just needed. + container.initialize(); + thisObject.container = container; + + let timeLineCoordinateSystem = newTimeLineCoordinateSystem(); // Needed to be able to plot on the timeline, otherwise not. + + let timePeriod; // This will hold the current Time Period the user is at. + let datetime; // This will hold the current Datetime the user is at. + + /* these are module specific variables: */ + + let fileSequence; + let plotElements = []; // This is where the elements to be plotted are stored before plotting. + let plotLines = []; // Here we store the lines of open positions. + let notes = []; // Here we store the notes with messages from the bot. + + let notesChangedEventRaised = true; // This controls when to raise the event that notes changed. + + let previousNotesSetKey; + let currentNotesSetKey; + + return thisObject; + + function finalize() { + try { + + if (INFO_LOG === true) { logger.write("[INFO] finalize -> Entering function."); } + + /* Stop listening to the necesary events. */ + + viewPort.eventHandler.stopListening("Offset Changed", onOffsetChanged); + fileSequence.eventHandler.stopListening("Files Updated", onFilesUpdated); + + /* Destroyd References */ + + datetime = undefined; + timePeriod = undefined; + + fileSequence = undefined; + plotElements = undefined; + plotLines = undefined; + notes = undefined; + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] finalize -> err.message = " + err.message); } + } + } + + function initialize(pStorage, pExchange, pMarket, pDatetime, pTimePeriod, callBackFunction) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] initialize -> Entering function."); } + + datetime = pDatetime; + timePeriod = pTimePeriod; + + fileSequence = pStorage.fileSequences[0]; + + recalculate(callBackFunction); + recalculateScale(callBackFunction); + + fileSequence.eventHandler.listenToEvent("Files Updated", onFilesUpdated); // Only the first sequence is supported right now. + viewPort.eventHandler.listenToEvent("Offset Changed", onOffsetChanged); + + callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] initialize -> err = " + err); } + callBackFunction(GLOBAL.CUSTOM_FAIL_RESPONSE); + } + } + + function getContainer(point) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] getContainer -> Entering function."); } + + let container; + + /* First we check if this point is inside this space. */ + + if (this.container.frame.isThisPointHere(point) === true) { + + return this.container; + + } else { + + /* This point does not belong to this space. */ + + return undefined; + } + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] initialize -> err = " + err); } + } + } + + function onFilesUpdated() { + + recalculate(); + + } + + function setTimePeriod(pTimePeriod) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] setTimePeriod -> Entering function."); } + + timePeriod = pTimePeriod; + + recalculate(); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] setTimePeriod -> err = " + err); } + } + } + + function setDatetime(newDatetime) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] setDatetime -> Entering function."); } + + datetime = newDatetime; + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] setTimePeriod -> err = " + err); } + } + } + + function onOffsetChanged() { + + if (Math.random() * 100 > 95) { + + recalculate() + }; + + } + + function recalculate(callBackFunction) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] recalculate -> Entering function."); } + + if (fileSequence === undefined) { return; } + + /* + + We are going to filter the records depending on the Time Period. We want that for a 1 min time peroid all the records appears on screen, + but for higher periods, we will filter out some records, so that they do not overlap ever. + + */ + + plotElements = []; + plotLines = []; + notes = []; + + let lastSellRate; + let lastSellDate; + let sellExecRate; + + let lastBuyRate; + let lastBuyDate; + let buyExecRate; + + let maxSequence = fileSequence.getFilesLoaded(); + + for (let j = 0; j < maxSequence; j++) { + + let file = fileSequence.getFile(j); + + let history = []; + let lines = []; + + /* First the small balls */ + + const ONE_MIN_IN_MILISECONDS = 60 * 1000; + let step = timePeriod / ONE_MIN_IN_MILISECONDS; + let step = 1; // For now we dont discard records depending on the zoom level. + + let i = 0; + let lastRecordPushed = 0; + + for (i = 0; i < file.length; i = i + step) { + + let newHistoryRecord = { + + date: Math.trunc(file[i][0] / 60000) * 60000 + 30000, + buyAvgRate: file[i][1], + sellAvgRate: file[i][2], + + lastSellRate: file[i][3], + sellExecRate: file[i][4], + lastBuyRate: file[i][5], + buyExecRate: file[i][6], + + marketRate: file[i][7], + newPositions: file[i][8], + newTrades: file[i][9], + movedPositions: file[i][10], + profitsAssetA: file[i][11], + profitsAssetB: file[i][12], + combinedProfitsA: file[i][13], + combinedProfitsB: file[i][14], + + messageRelevance: file[i][15], + messageTitle: file[i][16], + messageBody: file[i][17], + + mqServiceMessages: file[i][18] + }; + + /* + + Now we are going to inflate the mqService Messages in order to use them during the plotting. + + */ + + if (newHistoryRecord.mqServiceMessages !== undefined) { + for (let i = 0; i < newHistoryRecord.mqServiceMessages.length; i++) { + let mqMessage = mqServiceMessages[i]; + } + } + + /* Finally we add this History Record to the Array */ + + history.push(newHistoryRecord); + lastRecordPushed = i; + + /* Here we build the lines. */ + + if (timePeriod <= 1 * 60 * 1000) { + + if (newHistoryRecord.lastSellRate > 0) { + + lastSellRate = newHistoryRecord.lastSellRate; + lastSellDate = newHistoryRecord.date; + + } + + if (newHistoryRecord.sellExecRate > 0) { + + let newLine = { + type: "sell", + x1: lastSellDate, + y1: lastSellRate, + x2: newHistoryRecord.date, + y2: newHistoryRecord.sellExecRate + }; + + lines.push(newLine); + + } + + if (newHistoryRecord.lastBuyRate > 0) { + + lastBuyRate = newHistoryRecord.lastBuyRate; + lastBuyDate = newHistoryRecord.date; + + } + + if (newHistoryRecord.buyExecRate > 0) { + + let newLine = { + type: "buy", + x1: lastBuyDate, + y1: lastBuyRate, + x2: newHistoryRecord.date, + y2: newHistoryRecord.buyExecRate + }; + + lines.push(newLine); + + } + } + + } + + /* We allways want to put the last record of the file on the filterd dataset, so as to allways show the latest advance of the bot. */ + + i = file.length - 1; + + if (lastRecordPushed !== i) { + + let newHistoryRecord = { + + date: Math.trunc(file[i][0] / 60000) * 60000 + 30000, + buyAvgRate: file[i][1], + sellAvgRate: file[i][2], + + lastSellRate: file[i][3], + sellExecRate: file[i][4], + lastBuyRate: file[i][5], + buyExecRate: file[i][6], + + marketRate: file[i][7], + newPositions: file[i][8], + newTrades: file[i][9], + movedPositions: file[i][10], + profitsAssetA: file[i][11], + profitsAssetB: file[i][12], + combinedProfitsA: file[i][13], + combinedProfitsB: file[i][14], + + messageRelevance: file[i][15], + messageTitle: file[i][16], + messageBody: file[i][17], + + mqServiceMessages: file[i][18] + }; + + history.push(newHistoryRecord); + + } + + + /* Second we process the text */ + + for (let i = 0; i < file.length; i++) { + + let newHistoryRecord = { + + date: Math.trunc(file[i][0] / 60000) * 60000 + 30000, + buyAvgRate: file[i][1], + sellAvgRate: file[i][2], + + lastSellRate: file[i][3], + sellExecRate: file[i][4], + lastBuyRate: file[i][5], + buyExecRate: file[i][6], + + marketRate: file[i][7], + newPositions: file[i][8], + newTrades: file[i][9], + movedPositions: file[i][10], + profitsAssetA: file[i][11], + profitsAssetB: file[i][12], + combinedProfitsA: file[i][13], + combinedProfitsB: file[i][14], + + messageRelevance: file[i][15], + messageTitle: file[i][16], + messageBody: file[i][17] + }; + + if (newHistoryRecord.messageTitle !== "" && newHistoryRecord.messageBody !== "") { + + if (newHistoryRecord.messageRelevance >= 0 && newHistoryRecord.messageRelevance <= 10) { + + let relevanceTimePeriod = (dailyFilePeriods[10 - newHistoryRecord.messageRelevance][0]); + + if (timePeriod <= relevanceTimePeriod) { + + let note = { + title: newHistoryRecord.messageTitle, + body: newHistoryRecord.messageBody, + date: newHistoryRecord.date, + rate: newHistoryRecord.marketRate, + position: { + x: 0, + y: 0 + }, + visible: false + }; + + notes.push(note); + } + } + } + } + + plotElements.push(history); + plotLines.push(lines); + + } + + notesChangedEventRaised = false; + + thisObject.container.eventHandler.raiseEvent("History Changed", history); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] recalculate -> err = " + err); } + callBackFunction(GLOBAL.CUSTOM_FAIL_RESPONSE); + } + } + + function recalculateScale(callBackFunction) { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] recalculateScale -> Entering function."); } + + if (fileSequence === undefined) { return; } // We need the market file to be loaded to make the calculation. + + if (timeLineCoordinateSystem.maxValue > 0) { return; } // Already calculated. + + let minValue = { + x: EARLIEST_DATE.valueOf(), + y: 0 + }; + + let maxValue = { + x: MAX_PLOTABLE_DATE.valueOf(), + y: nextPorwerOf10(USDT_BTC_HTH) / 4 // TODO: This 4 is temporary + }; + + + timeLineCoordinateSystem.initialize( + minValue, + maxValue, + thisObject.container.frame.width, + thisObject.container.frame.height + ); + + function getMaxRate() { + + try { + + if (INFO_LOG === true) { logger.write("[INFO] recalculateScale -> getMaxRate > Entering function."); } + + let maxValue = 0; + + let maxSequence = fileSequence.getFilesLoaded(); + + for (let j = 0; j < maxSequence; j++) { + + let file = fileSequence.getFile(j); + + for (let i = 0; i < file.length; i++) { + + let currentMax = file[i][1] + file[i][2]; // 1 = rates. + + if (maxValue < currentMax) { + maxValue = currentMax; + } + } + } + + return maxValue; + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] recalculateScale -> getMaxRate -> err = " + err); } + callBackFunction(GLOBAL.CUSTOM_FAIL_RESPONSE); + } + } + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] recalculateScale -> err = " + err); } + callBackFunction(GLOBAL.CUSTOM_FAIL_RESPONSE); + } + } + + function draw() { + + try { + + if (INTENSIVE_LOG === true) { logger.write("[INFO] draw -> Entering function."); } + + plotChart(); + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] draw -> err = " + err); } + } + } + + function plotChart() { + + try { + + if (INTENSIVE_LOG === true) { logger.write("[INFO] plotChart -> Entering function."); } + + let point = { + x: 0, + y: 0 + }; + + let history; + + for (let j = 0; j < plotElements.length; j++) { + + let history = plotElements[j]; + + for (let i = 0; i < history.length; i++) { + + record = history[i]; + + let timestamp = Math.trunc(record.date / timePeriod) * timePeriod + timePeriod / 2; + + point = { + x: timestamp, + y: record.marketRate + }; + + point = timeLineCoordinateSystem.transformThisPoint(point); + point = transformThisPoint(point, thisObject.container); + + if (point.x < viewPort.visibleArea.bottomLeft.x || point.x > viewPort.visibleArea.bottomRight.x) { continue; } + + point = viewPort.fitIntoVisibleArea(point); + + let isCurrentRecord = false; + + if (datetime !== undefined) { + let dateValue = datetime.valueOf(); + if (dateValue >= record.date - timePeriod / 2 && dateValue <= record.date + timePeriod / 2 - 1) { + isCurrentRecord = true; + } + } + + let radius = 3; + + let opacity = '0.2'; + + browserCanvasContext.lineWidth = 1; + + /* Outer Circle */ + + browserCanvasContext.beginPath(); + + browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.DARK + ', ' + opacity + ')'; + + if (isCurrentRecord === false) { + browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.LIGHT + ', ' + opacity + ')'; + } else { + browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + opacity + ')'; /* highlight the current record */ + } + + browserCanvasContext.arc(point.x, point.y, radius, 0, Math.PI * 2, true); + browserCanvasContext.closePath(); + + if (point.x < viewPort.visibleArea.topLeft.x + 50 || point.x > viewPort.visibleArea.bottomRight.x - 50) {/*we leave this history without fill. */ } else { + browserCanvasContext.fill(); + } + + browserCanvasContext.stroke(); + + /* Draw a red inverted triangle on exec sell */ + + if (record.sellExecRate > 0) { + + opacity = '0.5'; + + let point1 = { + x: record.date, + y: record.sellExecRate + }; + + let point2 = { + x: record.date + timePeriod / 7 * 2, + y: record.sellExecRate + }; + + let point3 = { + x: record.date - timePeriod / 7 * 2, + y: record.sellExecRate + }; + + point1 = timeLineCoordinateSystem.transformThisPoint(point1); + point1 = transformThisPoint(point1, thisObject.container); + point1 = viewPort.fitIntoVisibleArea(point1); + + point2 = timeLineCoordinateSystem.transformThisPoint(point2); + point2 = transformThisPoint(point2, thisObject.container); + point2 = viewPort.fitIntoVisibleArea(point2); + + point3 = timeLineCoordinateSystem.transformThisPoint(point3); + point3 = transformThisPoint(point3, thisObject.container); + point3 = viewPort.fitIntoVisibleArea(point3); + + let diff = point2.x - point3.x; + point2.y = point2.y - diff; + point3.y = point3.y - diff; + + point2 = viewPort.fitIntoVisibleArea(point2); + point3 = viewPort.fitIntoVisibleArea(point3); + + browserCanvasContext.beginPath(); + + browserCanvasContext.moveTo(point1.x, point1.y); + browserCanvasContext.lineTo(point2.x, point2.y); + browserCanvasContext.lineTo(point3.x, point3.y); + browserCanvasContext.lineTo(point1.x, point1.y); + + browserCanvasContext.closePath(); + + if (isCurrentRecord === false) { + browserCanvasContext.fillStyle = 'rgba(219, 18, 18, ' + opacity + ')'; + } else { + browserCanvasContext.fillStyle = 'rgba(255, 233, 31, ' + opacity + ')'; /* highlight the current record */ + } + + browserCanvasContext.fill(); + + browserCanvasContext.strokeStyle = 'rgba(130, 9, 9, ' + opacity + ')'; + browserCanvasContext.stroke(); + + } + + /* Draw a green triangle on exec buy */ + + if (record.buyExecRate > 0) { + + opacity = '0.5'; + + let point1 = { + x: record.date, + y: record.buyExecRate + }; + + let point2 = { + x: record.date + timePeriod / 7 * 2, + y: record.buyExecRate + }; + + let point3 = { + x: record.date - timePeriod / 7 * 2, + y: record.buyExecRate + }; + + point1 = timeLineCoordinateSystem.transformThisPoint(point1); + point1 = transformThisPoint(point1, thisObject.container); + point1 = viewPort.fitIntoVisibleArea(point1); + + point2 = timeLineCoordinateSystem.transformThisPoint(point2); + point2 = transformThisPoint(point2, thisObject.container); + point2 = viewPort.fitIntoVisibleArea(point2); + + point3 = timeLineCoordinateSystem.transformThisPoint(point3); + point3 = transformThisPoint(point3, thisObject.container); + point3 = viewPort.fitIntoVisibleArea(point3); + + let diff = point2.x - point3.x; + point2.y = point2.y + diff; + point3.y = point3.y + diff; + + point2 = viewPort.fitIntoVisibleArea(point2); + point3 = viewPort.fitIntoVisibleArea(point3); + + browserCanvasContext.beginPath(); + + browserCanvasContext.moveTo(point1.x, point1.y); + browserCanvasContext.lineTo(point2.x, point2.y); + browserCanvasContext.lineTo(point3.x, point3.y); + browserCanvasContext.lineTo(point1.x, point1.y); + + browserCanvasContext.closePath(); + + if (isCurrentRecord === false) { + browserCanvasContext.fillStyle = 'rgba(64, 217, 26, ' + opacity + ')'; + } else { + browserCanvasContext.fillStyle = 'rgba(255, 233, 31, ' + opacity + ')'; /* highlight the current record */ + } + + browserCanvasContext.fill(); + + browserCanvasContext.strokeStyle = 'rgba(27, 105, 7, ' + opacity + ')'; + browserCanvasContext.stroke(); + + } + + /* Draw a red inverted triangle on sell */ + + if (record.lastSellRate > 0) { + + opacity = '0.5'; + + let point1 = { + x: record.date, + y: record.lastSellRate + }; + + let point2 = { + x: record.date + timePeriod / 7 * 2, + y: record.lastSellRate + }; + + let point3 = { + x: record.date - timePeriod / 7 * 2, + y: record.lastSellRate + }; + + point1 = timeLineCoordinateSystem.transformThisPoint(point1); + point1 = transformThisPoint(point1, thisObject.container); + point1 = viewPort.fitIntoVisibleArea(point1); + + point2 = timeLineCoordinateSystem.transformThisPoint(point2); + point2 = transformThisPoint(point2, thisObject.container); + point2 = viewPort.fitIntoVisibleArea(point2); + + point3 = timeLineCoordinateSystem.transformThisPoint(point3); + point3 = transformThisPoint(point3, thisObject.container); + point3 = viewPort.fitIntoVisibleArea(point3); + + let diff = point2.x - point3.x; + point2.y = point2.y - diff; + point3.y = point3.y - diff; + + point2 = viewPort.fitIntoVisibleArea(point2); + point3 = viewPort.fitIntoVisibleArea(point3); + + browserCanvasContext.beginPath(); + + browserCanvasContext.moveTo(point1.x, point1.y); + browserCanvasContext.lineTo(point2.x, point2.y); + browserCanvasContext.lineTo(point3.x, point3.y); + browserCanvasContext.lineTo(point1.x, point1.y); + + browserCanvasContext.closePath(); + + if (isCurrentRecord === false) { + browserCanvasContext.fillStyle = 'rgba(255, 255, 255, ' + opacity + ')'; + } else { + browserCanvasContext.fillStyle = 'rgba(255, 233, 31, ' + opacity + ')'; /* highlight the current record */ + } + + browserCanvasContext.fill(); + + browserCanvasContext.strokeStyle = 'rgba(130, 9, 9, ' + opacity + ')'; + browserCanvasContext.stroke(); + + } + + /* Draw a green triangle on buy */ + + if (record.lastBuyRate > 0) { + + opacity = '0.5'; + + let point1 = { + x: record.date, + y: record.lastBuyRate + }; + + let point2 = { + x: record.date + timePeriod / 7 * 2, + y: record.lastBuyRate + }; + + let point3 = { + x: record.date - timePeriod / 7 * 2, + y: record.lastBuyRate + }; + + point1 = timeLineCoordinateSystem.transformThisPoint(point1); + point1 = transformThisPoint(point1, thisObject.container); + point1 = viewPort.fitIntoVisibleArea(point1); + + point2 = timeLineCoordinateSystem.transformThisPoint(point2); + point2 = transformThisPoint(point2, thisObject.container); + point2 = viewPort.fitIntoVisibleArea(point2); + + point3 = timeLineCoordinateSystem.transformThisPoint(point3); + point3 = transformThisPoint(point3, thisObject.container); + point3 = viewPort.fitIntoVisibleArea(point3); + + let diff = point2.x - point3.x; + point2.y = point2.y + diff; + point3.y = point3.y + diff; + + point2 = viewPort.fitIntoVisibleArea(point2); + point3 = viewPort.fitIntoVisibleArea(point3); + + browserCanvasContext.beginPath(); + + browserCanvasContext.moveTo(point1.x, point1.y); + browserCanvasContext.lineTo(point2.x, point2.y); + browserCanvasContext.lineTo(point3.x, point3.y); + browserCanvasContext.lineTo(point1.x, point1.y); + + browserCanvasContext.closePath(); + + if (isCurrentRecord === false) { + browserCanvasContext.fillStyle = 'rgba(255, 255, 255, ' + opacity + ')'; + } else { + browserCanvasContext.fillStyle = 'rgba(255, 233, 31, ' + opacity + ')'; /* highlight the current record */ + } + + browserCanvasContext.fill(); + + browserCanvasContext.strokeStyle = 'rgba(27, 105, 7, ' + opacity + ')'; + browserCanvasContext.stroke(); + + } + + + /* Since there is at least some point plotted, then the profile should be visible. */ + + thisObject.payload.profile.visible = true; + } + + /* Draw the lines connecting plot elements. */ + + let lines = plotLines[j]; + + for (let i = 0; i < lines.length; i++) { + + let line = lines[i]; + + opacity = '0.2'; + + let point1 = { + x: line.x1, + y: line.y1 + }; + + let point2 = { + x: line.x2, + y: line.y2 + }; + + point1 = timeLineCoordinateSystem.transformThisPoint(point1); + point1 = transformThisPoint(point1, thisObject.container); + point1 = viewPort.fitIntoVisibleArea(point1); + + point2 = timeLineCoordinateSystem.transformThisPoint(point2); + point2 = transformThisPoint(point2, thisObject.container); + point2 = viewPort.fitIntoVisibleArea(point2); + + browserCanvasContext.beginPath(); + + browserCanvasContext.moveTo(point1.x, point1.y); + browserCanvasContext.lineTo(point2.x, point2.y); + + browserCanvasContext.closePath(); + + if (line.type === "sell") { + + browserCanvasContext.strokeStyle = 'rgba(130, 9, 9, ' + opacity + ')'; + + } else { + + browserCanvasContext.strokeStyle = 'rgba(27, 105, 7, ' + opacity + ')'; + + } + + browserCanvasContext.stroke(); + + } + + /* Now we calculate the anchor position of notes. */ + + currentNotesSetKey = ""; + + for (let i = 0; i < notes.length; i++) { + + let note = notes[i]; + + opacity = '0.2'; + + note.position = { + x: note.date, + y: note.rate + }; + + note.position = timeLineCoordinateSystem.transformThisPoint(note.position); + note.position = transformThisPoint(note.position, thisObject.container); + + if (note.position.x < (viewPort.visibleArea.bottomRight.x / 2) * (-1) || note.position.x > (viewPort.visibleArea.bottomRight.x) * (1.5)) { + note.visible = false; + currentNotesSetKey = currentNotesSetKey + "0"; + } else { + note.visible = true; + currentNotesSetKey = currentNotesSetKey + "1"; + } + } + + if (notesChangedEventRaised === false) { + + /* In this case the event is raised because we might have a different set of notes. */ + + thisObject.container.eventHandler.raiseEvent("Notes Changed", notes); + thisObject.payload.notes = notes; + + notesChangedEventRaised = true; + + } else { + + if (currentNotesSetKey !== previousNotesSetKey) { + + /* In this case the event is raised because the visibility of some of the notes changed. */ + + thisObject.container.eventHandler.raiseEvent("Notes Changed", notes); + thisObject.payload.notes = notes; + + previousNotesSetKey = currentNotesSetKey; + } + } + + } + + /* + + We replace the coordinate of the profile point so that whoever has a reference to it, gets the new position. + We will use the last point plotted on screen as the profilePoint. + + */ + + thisObject.payload.profile.position.x = point.x; + thisObject.payload.profile.position.y = point.y; + + } catch (err) { + + if (ERROR_LOG === true) { logger.write("[ERROR] plotChart -> err = " + err); } + } + } +} + diff --git a/this.plotter.config.json b/this.plotter.config.json index 1976dcda4..38e54024c 100644 --- a/this.plotter.config.json +++ b/this.plotter.config.json @@ -28,6 +28,14 @@ "event": "Current Condition Record Changed" } ] + }, + { + "codeName": "SimulationExecution", + "moduleName": "SimulationExecution", + "description": "Plots Simulation Execution.", + "profilePicture": "SimulationExecution.png", + "panels": [ + ] } ] } \ No newline at end of file