diff --git a/Plotters/AAMasters/plotters/Plotters-Bollinger-Bands b/Plotters/AAMasters/plotters/Plotters-Bollinger-Bands deleted file mode 160000 index b801eb222..000000000 --- a/Plotters/AAMasters/plotters/Plotters-Bollinger-Bands +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b801eb222c274bafd1cf5bcb2ce4f94ad1a5ee47 diff --git a/Plotters/AAMasters/plotters/Plotters-Bollinger-Channels b/Plotters/AAMasters/plotters/Plotters-Bollinger-Channels deleted file mode 160000 index f1466c8b4..000000000 --- a/Plotters/AAMasters/plotters/Plotters-Bollinger-Channels +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f1466c8b437ccce809b51771ba3ff8a2b68cec43 diff --git a/Plotters/AAMasters/plotters/Plotters-Candles-Volumes b/Plotters/AAMasters/plotters/Plotters-Candles-Volumes deleted file mode 160000 index f2254b9a2..000000000 --- a/Plotters/AAMasters/plotters/Plotters-Candles-Volumes +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f2254b9a21eeaa8efa559305f64cc681bc26ebf1 diff --git a/Plotters/AAMasters/plotters/Plotters-ROI/CombinedProfits.js b/Plotters/AAMasters/plotters/Plotters-ROI/CombinedProfits.js deleted file mode 100644 index 32d92f360..000000000 --- a/Plotters/AAMasters/plotters/Plotters-ROI/CombinedProfits.js +++ /dev/null @@ -1,711 +0,0 @@ -function newAAMastersPlottersROICombinedProfits() { - - const MODULE_NAME = "AAArena Plotters ROI Combined Profits"; - const ERROR_LOG = true; - const INTENSIVE_LOG = false; - const logger = newWebDebugLog(); - logger.fileName = MODULE_NAME; - - let thisObject = { - - // Main functions and properties. - - initialize: initialize, - container: undefined, - getContainer: getContainer, - setTimePeriod: setTimePeriod, - setDatetime: setDatetime, - recalculateScale: recalculateScale, - draw: draw, - payload: [] - }; - - /* this is part of the module template */ - - thisObject.container = newContainer() - thisObject.container.initialize(MODULE_NAME) - - 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 competition; - - let competitorsSequences; - - let updatedFilesEventsReceived = 0; - - let fileStyles = []; - - let offsetChangedEventSubscriptionId - let filesUpdatedEventSubscriptionId - let dimmensionsChangedEventSubscriptionId - - return thisObject; - - function finalize() { - try { - - /* Stop listening to the necesary events. */ - - viewPort.eventHandler.stopListening(offsetChangedEventSubscriptionId); - fileSequence.eventHandler.stopListening(filesUpdatedEventSubscriptionId); - thisObject.container.eventHandler.stopListening(dimmensionsChangedEventSubscriptionId) - - /* Destroyd References */ - - datetime = undefined; - timePeriod = undefined; - - fileSequence = undefined; - - } catch (err) { - - if (ERROR_LOG === true) { logger.write("[ERROR] finalize -> err = " + err.stack); } - } - } - - function initialize(pCompetition, pStorage, pDatetime, pTimePeriod, callBackFunction) { - - try { - - competition = pCompetition; - competitorsSequences = pStorage.competitorsSequences; - - datetime = pDatetime; - timePeriod = pTimePeriod; - - recalculate(); - recalculateScale(); - - offsetChangedEventSubscriptionId = viewPort.eventHandler.listenToEvent("Offset Changed", onOffsetChanged); - - /* Create the Payload structure */ - - for (let k = 0; k < competition.participants.length; k++) { - - let participant = competition.participants[k]; - - let payload = { - profile: { - position: { - x: 0, - y: 0 - }, - visible: false, - plot: true - } - } - - thisObject.payload.push(payload); - } - - for (let k = 0; k < competition.participants.length; k++) { - - let fileSequence = competitorsSequences[0][k]; // Only the first dataSet is considered for now. - - filesUpdatedEventSubscriptionId = fileSequence.eventHandler.listenToEvent("Files Updated", onFilesUpdated); // Only the first sequence is supported right now. - - } - - /* Here we will choose the colors of each participants path. */ - - for (let k = 0; k < competition.participants.length; k++) { - - let red = Math.trunc(Math.random() * 5) * 50; - let green = Math.trunc(Math.random() * 5) * 50; - let blue = Math.trunc(Math.random() * 5) * 50; - - let fillStyle = " " + red + "," + green + "," + blue; - - fileStyles.push(fillStyle); - - } - - dimmensionsChangedEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('Dimmensions Changed', function () { - recalculateScale() - recalculate(); - }) - - recalculate(); - recalculateScale(); - - callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE); - - } catch (err) { - - if (ERROR_LOG === true) { logger.write("[ERROR] initialize -> err = " + err.stack); } - - } - } - - function getContainer(point) { - - try { - - let container; - - /* First we check if this point is inside this space. */ - - if (thisObject.container.frame.isThisPointHere(point) === true) { - - return thisObject.container; - - } else { - - /* This point does not belong to this space. */ - - return undefined; - } - - } catch (err) { - - if (ERROR_LOG === true) { logger.write("[ERROR] getContainer -> err = " + err.stack); } - - } - } - - function onFilesUpdated() { - - try { - - updatedFilesEventsReceived++; - - if (updatedFilesEventsReceived === competition.participants.length) { - - recalculate(); - updatedFilesEventsReceived = 0; - } - - } catch (err) { - - if (ERROR_LOG === true) { logger.write("[ERROR] onFilesUpdated -> err = " + err.stack); } - - } - } - - function setTimePeriod(pTimePeriod) { - - try { - - timePeriod = pTimePeriod; - - recalculate(); - - } catch (err) { - - if (ERROR_LOG === true) { logger.write("[ERROR] setTimePeriod -> err = " + err.stack); } - - } - } - - function setDatetime(newDatetime) { - - try { - - datetime = newDatetime; - - } catch (err) { - - if (ERROR_LOG === true) { logger.write("[ERROR] setDatetime -> err = " + err.stack); } - - } - } - - function draw() { - - try { - return; // This plotter is currently disabled. - - if (INTENSIVE_LOG === true) { logger.write("[INFO] setDatetime -> Entering function."); } - - plotStartFinishLines(); - plotChart(); - - } catch (err) { - - if (ERROR_LOG === true) { logger.write("[ERROR] draw -> err = " + err.stack); } - - } - } - - function onOffsetChanged() { - - try { - - if (Math.random() * 100 > 95) { - - recalculate() - }; - - } catch (err) { - - if (ERROR_LOG === true) { logger.write("[ERROR] onOffsetChanged -> err = " + err.stack); } - - } - } - - function recalculate() { - - try { - - if (competitorsSequences === 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. - - */ - - for (let k = 0; k < competition.participants.length; k++) { - - let fileSequence = competitorsSequences[0][k]; // Only the first dataSet is considered for now. - - competition.participants[k].plotElements = []; - - let maxSequence = fileSequence.getFilesLoaded(); - - for (let j = 0; j < maxSequence; j++) { - - let file = fileSequence.getFile(j); - - /* First the small balls */ - - const ONE_MIN_IN_MILISECONDS = 60 * 1000; - let step = timePeriod / ONE_MIN_IN_MILISECONDS; - - 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] - }; - - competition.participants[k].plotElements.push(newHistoryRecord); - lastRecordPushed = i; - } - - /* 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] - }; - - competition.participants[k].plotElements.push(newHistoryRecord); - - } - } - } - - } catch (err) { - - if (ERROR_LOG === true) { logger.write("[ERROR] recalculate -> err = " + err.stack); } - - } - } - - function recalculateScale() { - - try { - - if (competitorsSequences === undefined) { return; } // We need the market file to be loaded to make the calculation. - - if (timeLineCoordinateSystem.maxValue > 0) { return; } // Already calculated. - - let minValue = { - x: MIN_PLOTABLE_DATE.valueOf(), - y: 0 - }; - - let maxValue = { - x: MAX_PLOTABLE_DATE.valueOf(), - y: 200 * 100 - }; - - - timeLineCoordinateSystem.initialize( - minValue, - maxValue, - thisObject.container.frame.width, - thisObject.container.frame.height - ); - - } catch (err) { - - if (ERROR_LOG === true) { logger.write("[ERROR] recalculateScale -> err = " + err.stack); } - - } - } - - function plotStartFinishLines() { - - try { - - let startDatetime = new Date(competition.startDatetime); - let finishDatetime = new Date(competition.finishDatetime); - - let startPointDown = { - x: startDatetime.valueOf(), - y: 0 - }; - - let startPointUp = { - x: startDatetime.valueOf(), - y: 0 - }; - - startPointDown = timeLineCoordinateSystem.transformThisPoint(startPointDown); - startPointDown = transformThisPoint(startPointDown, thisObject.container); - - startPointUp = timeLineCoordinateSystem.transformThisPoint(startPointUp); - startPointUp.y = startPointUp.y - thisObject.container.frame.height; - startPointUp = transformThisPoint(startPointUp, thisObject.container); - - if (startPointUp.x > viewPort.visibleArea.bottomLeft.x && startPointUp.x < viewPort.visibleArea.bottomRight.x) { - - startPointDown = viewPort.fitIntoVisibleArea(startPointDown); - startPointUp = viewPort.fitIntoVisibleArea(startPointUp); - - browserCanvasContext.beginPath(); - - browserCanvasContext.moveTo(startPointDown.x, startPointDown.y); - browserCanvasContext.lineTo(startPointUp.x, startPointUp.y); - - browserCanvasContext.closePath(); - - browserCanvasContext.strokeStyle = 'rgba(100, 10, 10, 0.5)'; - browserCanvasContext.lineWidth = 2; - browserCanvasContext.stroke(); - - } - - /* Here we draw the finish line. */ - - let SQUARE_SIDE_REDUCTION_FACTOR = 4; - - if (timePeriod <= _1_HOUR_IN_MILISECONDS) { SQUARE_SIDE_REDUCTION_FACTOR = 2; } - if (timePeriod <= _10_MINUTES_IN_MILISECONDS) { SQUARE_SIDE_REDUCTION_FACTOR = 1; } - if (timePeriod < _5_MINUTES_IN_MILISECONDS) { SQUARE_SIDE_REDUCTION_FACTOR = 0.5; } - - const TOTAL_SQUARES_TALL = ONE_DAY_IN_MILISECONDS / timePeriod * (timePeriod / _1_MINUTE_IN_MILISECONDS) / SQUARE_SIDE_REDUCTION_FACTOR; - const SQUARE_SIDE = thisObject.container.frame.height / TOTAL_SQUARES_TALL; - - let paintThis = true; - - for (i = 0; i < 3; i++) { - - for (j = 0; j < TOTAL_SQUARES_TALL; j++) { - - let finishPointDown = { - x: finishDatetime.valueOf(), - y: 0 - }; - - let finishPointUp = { - x: finishDatetime.valueOf(), - y: 0 - }; - - finishPointDown = timeLineCoordinateSystem.transformThisPoint(finishPointDown); - - finishPointDown.x = finishPointDown.x + SQUARE_SIDE * i; - finishPointDown.y = finishPointDown.y - SQUARE_SIDE * j; - - finishPointDown = transformThisPoint(finishPointDown, thisObject.container); - - finishPointUp = timeLineCoordinateSystem.transformThisPoint(finishPointUp); - - finishPointUp.x = finishPointUp.x + SQUARE_SIDE * i + SQUARE_SIDE; - finishPointUp.y = finishPointUp.y - SQUARE_SIDE * j - SQUARE_SIDE; - - finishPointUp = transformThisPoint(finishPointUp, thisObject.container); - - if (finishPointUp.x < viewPort.visibleArea.bottomLeft.x || finishPointDown.x > viewPort.visibleArea.bottomRight.x) { continue; } - - finishPointDown = viewPort.fitIntoVisibleArea(finishPointDown); - finishPointUp = viewPort.fitIntoVisibleArea(finishPointUp); - - browserCanvasContext.beginPath(); - - browserCanvasContext.moveTo(finishPointDown.x, finishPointDown.y); - browserCanvasContext.lineTo(finishPointUp.x, finishPointDown.y); - browserCanvasContext.lineTo(finishPointUp.x, finishPointUp.y); - browserCanvasContext.lineTo(finishPointDown.x, finishPointUp.y); - - browserCanvasContext.closePath(); - - /* - browserCanvasContext.strokeStyle = 'rgba(100, 100, 100, 1)'; - browserCanvasContext.lineWidth = 1; - browserCanvasContext.stroke(); - */ - - if (paintThis === true) { - - browserCanvasContext.fillStyle = 'rgba(100, 100, 100, ' + (0.6 - i / 5) + ')'; - browserCanvasContext.fill(); - - } - - if (paintThis === true) { paintThis = false; } else { paintThis = true; } - } - - if (paintThis === true) { paintThis = false; } else { paintThis = true; } - } - - } catch (err) { - - if (ERROR_LOG === true) { logger.write("[ERROR] plotStartFinishLines -> err = " + err.stack); } - - } - } - - function plotChart() { - - try { - - let userPosition = getUserPosition() - let userPositionDate = userPosition.point.x - - for (let k = 0; k < competition.participants.length; k++) { - - let point = { - x: 0, - y: 0 - }; - - let upLabel = ""; - - let participant = competition.participants[k]; - let plotElements = participant.plotElements; - - if (plotElements !== undefined) { - - let profileIntervalCounter = 0; - let previousPoint; - - for (let i = 0; i < plotElements.length; i++) { - - record = plotElements[i]; - - point = { - x: record.date, - y: record.combinedProfitsB * 100 - }; - - upLabel = "ROI: " + Math.trunc(record.combinedProfitsB * 10000) / 10000 + " %"; - - point = timeLineCoordinateSystem.transformThisPoint(point); - - point.y = point.y - thisObject.container.frame.height / 2; - - 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 (userPositionDate >= record.date - timePeriod / 2 && userPositionDate <= record.date + timePeriod / 2 - 1) { - isCurrentRecord = true; - } - - let opacity = '0.2'; - - let radius = 2; - - browserCanvasContext.lineWidth = 1; - - - /* Circles */ - - if (thisObject.payload[k].profile.plot === true) { - - browserCanvasContext.beginPath(); - - browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.DARK + ', ' + opacity + ')'; - - if (isCurrentRecord === false) { - browserCanvasContext.fillStyle = 'rgba(' + fileStyles[k] + ', ' + opacity + ')'; - } else { - browserCanvasContext.fillStyle = 'rgba(255, 233, 31, ' + 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(); - - } - - /* Since there is at least some point plotted, then the profile should be visible. */ - - thisObject.payload[k].profile.visible = true; - - /* Line */ - - if (previousPoint !== undefined && thisObject.payload[k].profile.plot === true) { - - - browserCanvasContext.strokeStyle = 'rgba(' + fileStyles[k] + ', ' + opacity + ')'; - browserCanvasContext.beginPath(); - - browserCanvasContext.moveTo(previousPoint.x, previousPoint.y); - browserCanvasContext.lineTo(point.x, point.y); - - browserCanvasContext.closePath(); - - browserCanvasContext.stroke(); - - } - - previousPoint = { - x: point.x, - y: point.y - }; - - /* Image */ - - if (thisObject.payload[k].profile.plot === true) { - - profileIntervalCounter++; - - if (profileIntervalCounter === 25) { - - profileIntervalCounter = 0; - - if (participant.profilePicture !== undefined) { - - let imageId = participant.devTeam + "." + participant.profilePicture; - imageSize = 15; - - if (imageId !== undefined) { - - let image = document.getElementById(imageId); - - if (image !== null) { - - let offset = imageSize * 1.5; - - if (point.y > viewPort.visibleArea.bottomLeft.y / 2) { offset = - offset; } - - /* The line */ - - browserCanvasContext.lineWidth = 0.3; - browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.DARK + ', ' + opacity + ')'; - browserCanvasContext.beginPath(); - - browserCanvasContext.moveTo(point.x, point.y + offset); - browserCanvasContext.lineTo(point.x, point.y); - - browserCanvasContext.closePath(); - - browserCanvasContext.stroke(); - - /* The Image */ - - browserCanvasContext.drawImage(image, point.x - imageSize / 2, point.y - imageSize / 2 + offset, imageSize, imageSize); - - /* Now the border */ - - browserCanvasContext.beginPath(); - - opacity = '0.5'; - - browserCanvasContext.lineWidth = 1; - browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.DARK + ', ' + opacity + ')'; - - let radius = imageSize / 2 + 2; - - browserCanvasContext.arc(point.x, point.y + offset, radius, 0, Math.PI * 2, true); - browserCanvasContext.closePath(); - - browserCanvasContext.stroke(); - - } - } - } - } - } - } - - /* - - 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[k].profile.position.x = point.x; - thisObject.payload[k].profile.position.y = point.y; - thisObject.payload[k].profile.upLabel = upLabel; - - } - } - - } catch (err) { - - if (ERROR_LOG === true) { logger.write("[ERROR] plotChart -> err = " + err.stack); } - - } - } - -} - diff --git a/Plotters/AAMasters/plotters/Plotters-ROI/this.plotter.config.json b/Plotters/AAMasters/plotters/Plotters-ROI/this.plotter.config.json deleted file mode 100644 index 79caf13c0..000000000 --- a/Plotters/AAMasters/plotters/Plotters-ROI/this.plotter.config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "displayName": "Plotters ROI", - "codeName": "PlottersROI", - "devTeam": "AAMasters", - "modules": [ - { - "codeName": "CombinedProfits", - "moduleName": "CombinedProfits", - "description": "Plots participants of a competition by the ROI each one had over time.", - "panels": [] - } - ] -} \ No newline at end of file diff --git a/Plotters/AAMasters/plotters/Plotters-Stairs-Patterns b/Plotters/AAMasters/plotters/Plotters-Stairs-Patterns deleted file mode 160000 index f2c3d2ad3..000000000 --- a/Plotters/AAMasters/plotters/Plotters-Stairs-Patterns +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f2c3d2ad3948d710785dd9da114ec57a0fe9124c diff --git a/Plotters/AAMasters/plotters/Plotters-Trading b/Plotters/AAMasters/plotters/Plotters-Trading deleted file mode 160000 index 316a2a847..000000000 --- a/Plotters/AAMasters/plotters/Plotters-Trading +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 316a2a8476eefd058bc2bd3baf3e88b36c12e6be diff --git a/Plotters/AAMasters/plotters/Plotters-Trading-Simulation b/Plotters/AAMasters/plotters/Plotters-Trading-Simulation deleted file mode 160000 index 54f9c8d64..000000000 --- a/Plotters/AAMasters/plotters/Plotters-Trading-Simulation +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 54f9c8d6474b2adbacf0dbf8340ed2b40d3ab442 diff --git a/Plotters/AAVikings/plotters/Plotters-Linear-Regression-Curve b/Plotters/AAVikings/plotters/Plotters-Linear-Regression-Curve deleted file mode 160000 index df092daaa..000000000 --- a/Plotters/AAVikings/plotters/Plotters-Linear-Regression-Curve +++ /dev/null @@ -1 +0,0 @@ -Subproject commit df092daaa2a67be49fdc90c9b91f2ddfc97e3871 diff --git a/package-lock.json b/package-lock.json index 3cfe4779f..cd57b0187 100644 --- a/package-lock.json +++ b/package-lock.json @@ -199,6 +199,11 @@ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.0.0.tgz", "integrity": "sha512-30xVGqjLjiUOArT4+M5q9sYdvuR4riM6yK9wMcas9Vbp6zZa+ocC9dp6QoftuhTPhFAiLK/0C5Ni2nou/Bk8lg==" }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" + }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -245,6 +250,20 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", @@ -305,6 +324,11 @@ } } }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -486,6 +510,11 @@ "p-defer": "^1.0.0" } }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" + }, "mem": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", @@ -683,6 +712,22 @@ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "requires": { + "through": "~2.3" + } + }, + "ps-tree": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", + "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", + "requires": { + "event-stream": "=3.3.4" + } + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -730,11 +775,27 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "requires": { + "through": "2" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "requires": { + "duplexer": "~0.1.1" + } + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -770,6 +831,11 @@ "has-flag": "^3.0.0" } }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", diff --git a/package.json b/package.json index a975ce5cc..9d13b35bf 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ }, "dependencies": { "@superalgos/mqservice": "0.0.12", + "axios": "0.19.0", "dotenv": "8.0.0", - "axios": "0.19.0" + "ps-tree": "^1.2.0" } } diff --git a/server.js b/server.js index cf3e48759..7d21eefb3 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,7 @@ -require('dotenv').config() +require('dotenv').config(); +const { spawn } = require('child_process'); +const psTree = require('ps-tree'); CONSOLE_LOG = process.env.CONSOLE_LOG === 'true' CONSOLE_ERROR_LOG = process.env.CONSOLE_ERROR_LOG === 'true' @@ -33,8 +35,10 @@ global.CUSTOM_FAIL_RESPONSE = { let http = require('http') let port = process.env.PORT || 1337 let isHttpServerStarted = false +let cloneExecutorChildProcess startHtttpServer() +startCloneExecutor() function startHtttpServer() { if (CONSOLE_LOG === true) { console.log('[INFO] server -> startHtttpServer -> Entering function.') } @@ -49,6 +53,49 @@ function startHtttpServer() { } } +function startCloneExecutor() { + if (CONSOLE_LOG === true) { console.log('[INFO] server -> startCloneExecutor -> Entering function.') }; + + let path = process.env.CLONE_EXECUTOR_PATH + '/run.js' + cloneExecutorChildProcess = spawn('node', [path], { shell: true, stdio: 'inherit' }); + + cloneExecutorChildProcess.on('error', (err) => { + console.log(`[ERROR] server -> startCloneExecutor -> Clone Executor exited with error ${err}`); + }); + cloneExecutorChildProcess.on('close', (code, signal) => { + console.log(`[INFO] CloneExecutor process terminated.`); + }); +} + +function stopCloneExecutor() { + if (CONSOLE_LOG === true) { console.log('[INFO] server -> stopCloneExecutor -> Entering function.') }; + + var kill = function (pid, signal, callback) { + signal = signal || 'SIGKILL'; + callback = callback || function () { }; + var killTree = true; + if (killTree) { + psTree(pid, function (err, children) { + [pid].concat( + children.map(function (p) { + return p.PID; + }) + ).forEach(function (tpid) { + try { process.kill(tpid, signal) } + catch (ex) { } + }); + callback(); + }); + } else { + try { process.kill(pid, signal) } + catch (ex) { } + callback(); + } + }; + + kill(cloneExecutorChildProcess.pid); +} + function onBrowserRequest(request, response) { if (CONSOLE_LOG === true && request.url.indexOf('NO-LOG') === -1) { console.log('[INFO] server -> onBrowserRequest -> request.url = ' + request.url) } @@ -75,6 +122,28 @@ function onBrowserRequest(request, response) { switch (requestParameters[1]) { + case 'RestartCloneExecutor': + { + try { + stopCloneExecutor(); + startCloneExecutor(); + respondWithContent('Restart Clone Executor ok.', response) + } catch (err) { + respondWithContent('There was an error restarting clone executor.', response) + } + + break + } + case 'StopCloneExecutor': + { + try { + stopCloneExecutor(); + respondWithContent('Stop Clone Executor ok.', response) + } catch (err) { + respondWithContent('There was an error stopping clone executor.', response) + } + break + } case 'MQService': { let filePath = './node_modules/@superalgos/mqservice/orderLifeCicle/webDependency.js'