diff --git a/.env.matias b/.env.matias new file mode 100644 index 000000000..cd2da81a5 --- /dev/null +++ b/.env.matias @@ -0,0 +1,20 @@ +NODE_ENV=production +PORT=4101 + +VIRTUAL_HOST=charts-dev.superalgos.org +LETSENCRYPT_HOST=charts-dev.superalgos.org +LETSENCRYPT_EMAIL=ssl-certificates@advancedalgos.org +VIRTUAL_PORT=4101 + +#Log options +CONSOLE_LOG=true +CONSOLE_ERROR_LOG=true +LOG_FILE_CONTENT=false + +# Server commands +PATH_TO_CANVAS_APP=./dependency/CanvasApp +PATH_TO_FILES_COMPONENT=./dependency/Files-Component/src + +# GATEWAY_ENDPOINT=https://platform-api-dev.superalgos.org/graphql +GATEWAY_ENDPOINT=http://localhost:4100/graphql + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..7e1eb1e2d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,36 @@ +[submodule "Plotters/AAMasters/plotters/Plotters-Trading-Simulation"] + path = Plotters/AAMasters/plotters/Plotters-Trading-Simulation + url = https://github.com/AAMasters/Plotters-Trading-Simulation.git + branch = develop +[submodule "Plotters/AAMasters/plotters/Plotters-Candles-Volumes"] + path = Plotters/AAMasters/plotters/Plotters-Candles-Volumes + url = https://github.com/AAMasters/Plotters-Candles-Volumes.git + branch = develop +[submodule "Plotters/AAMasters/plotters/Plotters-Bollinger-Channels"] + path = Plotters/AAMasters/plotters/Plotters-Bollinger-Channels + url = https://github.com/AAMasters/Plotters-Bollinger-Channels.git + branch = develop +[submodule "Plotters/AAMasters/plotters/Plotters-Bollinger-Bands"] + path = Plotters/AAMasters/plotters/Plotters-Bollinger-Bands + url = https://github.com/AAMasters/Plotters-Bollinger-Bands.git + branch = develop +[submodule "Plotters/AAMasters/plotters/Plotters-Stairs-Patterns"] + path = Plotters/AAMasters/plotters/Plotters-Stairs-Patterns + url = https://github.com/AAMasters/Plotters-Stairs-Patterns.git + branch = develop +[submodule "Plotters/AAMasters/plotters/Plotters-Trading"] + path = Plotters/AAMasters/plotters/Plotters-Trading + url = https://github.com/AAMasters/Plotters-Trading.git + branch = develop +[submodule "Plotters/AAVikings/plotters/Plotters-Linear-Regression-Curve"] + path = Plotters/AAVikings/plotters/Plotters-Linear-Regression-Curve + url = https://github.com/AAVikings/Plotters-Linear-Regression-Curve.git + branch = master +[submodule "Files-Component"] + path = Files-Component + url = https://github.com/Superalgos/Files-Component.git + branch = develop +[submodule "CanvasApp"] + path = CanvasApp + url = https://github.com/Superalgos/CanvasApp.git + branch = develop \ No newline at end of file diff --git a/CanvasApp b/CanvasApp new file mode 160000 index 000000000..bdd9dce6a --- /dev/null +++ b/CanvasApp @@ -0,0 +1 @@ +Subproject commit bdd9dce6a40fdbbf5e551579eb9a369d2a2bae19 diff --git a/Ecosystem.js b/Ecosystem.js index 961085e1f..5a06cdc8c 100644 --- a/Ecosystem.js +++ b/Ecosystem.js @@ -18,6 +18,9 @@ function newEcosystem() { } let ECOSYSTEM = JSON.parse(window.localStorage.getItem('ecosystem')); + if (ECOSYSTEM === null || ECOSYSTEM === undefined) { + ECOSYSTEM = getUserEcosystem() + } return thisObject; diff --git a/Files-Component b/Files-Component new file mode 160000 index 000000000..df6c6050c --- /dev/null +++ b/Files-Component @@ -0,0 +1 @@ +Subproject commit df6c6050c7c2dd2db3801237fbeb7f074a1f6fcd diff --git a/Images/superalgos-platform.jpg b/Images/superalgos-platform.jpg new file mode 100644 index 000000000..709e0ba60 Binary files /dev/null and b/Images/superalgos-platform.jpg differ diff --git a/Plotters/AAMasters/plotters/Plotters-Bollinger-Bands b/Plotters/AAMasters/plotters/Plotters-Bollinger-Bands new file mode 160000 index 000000000..b801eb222 --- /dev/null +++ b/Plotters/AAMasters/plotters/Plotters-Bollinger-Bands @@ -0,0 +1 @@ +Subproject commit b801eb222c274bafd1cf5bcb2ce4f94ad1a5ee47 diff --git a/Plotters/AAMasters/plotters/Plotters-Bollinger-Channels b/Plotters/AAMasters/plotters/Plotters-Bollinger-Channels new file mode 160000 index 000000000..f1466c8b4 --- /dev/null +++ b/Plotters/AAMasters/plotters/Plotters-Bollinger-Channels @@ -0,0 +1 @@ +Subproject commit f1466c8b437ccce809b51771ba3ff8a2b68cec43 diff --git a/Plotters/AAMasters/plotters/Plotters-Candles-Volumes b/Plotters/AAMasters/plotters/Plotters-Candles-Volumes new file mode 160000 index 000000000..f2254b9a2 --- /dev/null +++ b/Plotters/AAMasters/plotters/Plotters-Candles-Volumes @@ -0,0 +1 @@ +Subproject commit f2254b9a21eeaa8efa559305f64cc681bc26ebf1 diff --git a/Plotters/AAMasters/plotters/Plotters-ROI/CombinedProfits.js b/Plotters/AAMasters/plotters/Plotters-ROI/CombinedProfits.js new file mode 100644 index 000000000..32d92f360 --- /dev/null +++ b/Plotters/AAMasters/plotters/Plotters-ROI/CombinedProfits.js @@ -0,0 +1,711 @@ +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 new file mode 100644 index 000000000..79caf13c0 --- /dev/null +++ b/Plotters/AAMasters/plotters/Plotters-ROI/this.plotter.config.json @@ -0,0 +1,13 @@ +{ + "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 new file mode 160000 index 000000000..f2c3d2ad3 --- /dev/null +++ b/Plotters/AAMasters/plotters/Plotters-Stairs-Patterns @@ -0,0 +1 @@ +Subproject commit f2c3d2ad3948d710785dd9da114ec57a0fe9124c diff --git a/Plotters/AAMasters/plotters/Plotters-Trading b/Plotters/AAMasters/plotters/Plotters-Trading new file mode 160000 index 000000000..316a2a847 --- /dev/null +++ b/Plotters/AAMasters/plotters/Plotters-Trading @@ -0,0 +1 @@ +Subproject commit 316a2a8476eefd058bc2bd3baf3e88b36c12e6be diff --git a/Plotters/AAMasters/plotters/Plotters-Trading-Simulation b/Plotters/AAMasters/plotters/Plotters-Trading-Simulation new file mode 160000 index 000000000..54f9c8d64 --- /dev/null +++ b/Plotters/AAMasters/plotters/Plotters-Trading-Simulation @@ -0,0 +1 @@ +Subproject commit 54f9c8d6474b2adbacf0dbf8340ed2b40d3ab442 diff --git a/Plotters/AAVikings/plotters/Plotters-Linear-Regression-Curve b/Plotters/AAVikings/plotters/Plotters-Linear-Regression-Curve new file mode 160000 index 000000000..df092daaa --- /dev/null +++ b/Plotters/AAVikings/plotters/Plotters-Linear-Regression-Curve @@ -0,0 +1 @@ +Subproject commit df092daaa2a67be49fdc90c9b91f2ddfc97e3871 diff --git a/Scripts/AppLoader.js b/Scripts/AppLoader.js index a9d2b4da1..f69ba2157 100644 --- a/Scripts/AppLoader.js +++ b/Scripts/AppLoader.js @@ -17,11 +17,20 @@ function newAppLoader() { try { if (INFO_LOG === true) { logger.write('[INFO] loadModules -> Entering function.') } - let ecosystem = await loadEcosystem() - window.localStorage.setItem('ecosystem', JSON.stringify(ecosystem)) - let plotters = getPlotters(ecosystem) + window.localStorage.removeItem('ecosystem') - let modulesArray = [ + let plotters, modulesArray + let ecosystem = await loadEcosystem() + if (ecosystem) { + window.localStorage.setItem('ecosystem', JSON.stringify(ecosystem)) + plotters = getPlotters(ecosystem) + } else { + plotters = defaultPlotters() + modulesArray = ['UserEcosystem.js'] + } + + modulesArray = modulesArray.concat([ + 'ChartsSpace/ViewPort.js', 'Globals.js', 'Ecosystem.js', @@ -31,7 +40,6 @@ function newAppLoader() { 'ChartsSpace/PlottersManager.js', 'ChartsSpace/TimelineChart.js', 'ChartsSpace/TimeMachine.js', - 'ChartsSpace/ViewPort.js', 'ChartsSpace/TimeLineCoordinateSystem.js', 'TopSpace/CurrentEvent.js', @@ -114,7 +122,7 @@ function newAppLoader() { 'Utilities.js', 'Dashboard.js' - ] + ]) modulesArray = modulesArray.concat(plotters) @@ -145,10 +153,11 @@ function newAppLoader() { if (downloadedCounter === modulesArray.length) { if (INFO_LOG === true) { logger.write('[INFO] loadModules -> onRequired -> Starting Advanced Algos Platform.') } + setTimeout(() => { + dashboard = newDashboard() + dashboard.start() + }, 500) - dashboard = newDashboard() - - dashboard.start() } } catch (err) { if (ERROR_LOG === true) { logger.write('[ERROR] loadModules -> onRequired -> err = ' + err.stack) } @@ -163,19 +172,13 @@ function newAppLoader() { async function loadEcosystem() { if (INFO_LOG === true) { logger.write('[INFO] loadEcosystem -> Entering function.') } - let headers let accessToken = window.localStorage.getItem('access_token') if (accessToken !== null) { - headers = { - authorization: 'Bearer ' + accessToken - } - } - - let response = await axios({ - url: window.canvasApp.graphQL.masterAppApiUrl, - method: 'post', - data: { - query: ` + let response = await axios({ + url: window.canvasApp.graphQL.masterAppApiUrl, + method: 'post', + data: { + query: ` query { web_GetEcosystem { id @@ -295,22 +298,54 @@ function newAppLoader() { } } ` - }, - headers: headers - }) + }, + headers: { + authorization: 'Bearer ' + accessToken + } + }) - if (response.data.errors) { - if (ERROR_LOG === true) { console.log(spacePad(MODULE_NAME, 50) + ' : ' + '[ERROR] AppPreLoader -> loadEcosystem -> response.text = ' + JSON.stringify(res.data.errors)) } - throw error + if (response.data.errors) { + if (ERROR_LOG === true) { console.log(spacePad(MODULE_NAME, 50) + ' : ' + '[ERROR] AppPreLoader -> loadEcosystem -> response.text = ' + JSON.stringify(response.data.errors)) } + throw error + } + + return response.data.data.web_GetEcosystem } + } - return response.data.data.web_GetEcosystem + function defaultPlotters() { + return [ + 'Plotters/AAMasters/Plotters-Candles-Volumes/Candles.js', + 'PlotterPanels/AAMasters/Plotters-Candles-Volumes/CandlePanel.js', + 'Plotters/AAMasters/Plotters-Candles-Volumes/Volumes.js', + 'PlotterPanels/AAMasters/Plotters-Candles-Volumes/VolumePanel.js', + 'Plotters/AAMasters/Plotters-Stairs-Patterns/CandleStairs.js', + 'Plotters/AAMasters/Plotters-Stairs-Patterns/VolumeStairs.js', + 'Plotters/AAMasters/Plotters-Trading/Details.js', + 'Plotters/AAMasters/Plotters-Trading/History.js', + 'Plotters/AAMasters/Plotters-Bollinger-Bands/BollingerBands.js', + 'PlotterPanels/AAMasters/Plotters-Bollinger-Bands/BollingerBandsPanel.js', + 'Plotters/AAMasters/Plotters-Bollinger-Bands/PercentageBandwidth.js', + 'Plotters/AAMasters/Plotters-Trading-Simulation/TradingSimulation.js', + 'PlotterPanels/AAMasters/Plotters-Trading-Simulation/TradingSimulationPanel.js', + 'Plotters/AAMasters/Plotters-Trading-Simulation/Conditions.js', + 'Plotters/AAMasters/Plotters-Trading-Simulation/Strategies.js', + 'Plotters/AAMasters/Plotters-Trading-Simulation/Trades.js', + 'Plotters/AAMasters/Plotters-Trading-Simulation/SimulationExecution.js', + 'PlotterPanels/AAMasters/Plotters-Trading-Simulation/SimulationExecutionPanel.js', + 'Plotters/AAMasters/Plotters-Bollinger-Channels/BollingerChannels.js', + 'PlotterPanels/AAMasters/Plotters-Bollinger-Channels/ChannelPanel.js', + 'Plotters/AAMasters/Plotters-Bollinger-Channels/BollingerSubChannels.js', + 'PlotterPanels/AAMasters/Plotters-Bollinger-Channels/SubChannelPanel.js', + 'Plotters/AAVikings/Plotters-Linear-Regression-Curve/LRC.js', + 'PlotterPanels/AAVikings/Plotters-Linear-Regression-Curve/ChannelPanel.js', + 'Plotters/AAMasters/Plotters-ROI/CombinedProfits.js' + ] } function getPlotters(ecosystem) { if (INFO_LOG === true) { console.log('[INFO] server -> onBrowserRequest -> onFileRead -> addPlotters -> Entering function.') } - let plotters = [] let devTeams = ecosystem.devTeams let hosts = ecosystem.hosts diff --git a/Scripts/AppPreLoader.js b/Scripts/AppPreLoader.js index 16f924c16..d17254d3b 100644 --- a/Scripts/AppPreLoader.js +++ b/Scripts/AppPreLoader.js @@ -26,9 +26,9 @@ GLOBAL.CUSTOM_OK_RESPONSE = { GLOBAL.CUSTOM_FAIL_RESPONSE = { result: "Fail Because", message: "Custom Message" -}; +}; -let browserCanvas; // This is the canvas object of the browser. +let browserCanvas; // This is the canvas object of the browser. function spacePad(str, max) { str = str.toString(); @@ -136,39 +136,28 @@ function loadAdvancedAlgosPlatform() { } function callServer(pContentToSend, pPath, callBackFunction) { - let xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function () { if (this.readyState === 4 && this.status === 200) { - - callBackFunction(xhttp.responseText); - + callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE, xhttp.responseText); + return; + } else if (this.readyState === 4 && this.status === 404) { + callBackFunction({ result: "Fail", message: xhttp.responseText.trim(), code: xhttp.responseText.trim() }); + return; } }; if (pContentToSend === undefined) { - xhttp.open("GET", pPath, true); xhttp.send(); - } else { - try { - let blob = new Blob([pContentToSend], { type: 'text/plain' }); - xhttp.open("POST", pPath, true); xhttp.send(blob); - } catch (err) { - if (ERROR_LOG === true) { console.log(spacePad(MODULE_NAME, 50) + " : " + "[ERROR] callServer -> err.message = " & err.message); } - + callBackFunction({ result: "Fail", message: err.message }) } } } - - - - - diff --git a/Server/FileCloud.js b/Server/FileCloud.js deleted file mode 100644 index 4cbb6e709..000000000 --- a/Server/FileCloud.js +++ /dev/null @@ -1,57 +0,0 @@ -exports.newFileCloud = function newFileCloud() { - const MODULE_NAME = 'File Cloud' - const INFO_LOG = false - const ERROR_LOG = true - const axios = require('axios') - - let thisObject = { - getBlobToText: getBlobToText - } - - return thisObject - - function getBlobToText(container, filePath, host, callBackFunction) { - try { - if (INFO_LOG === true) { console.log('[INFO] getBlobToText -> Entering function.' + filePath) } - - let headers - - axios({ - url: process.env.GATEWAY_ENDPOINT, - method: 'post', - data: { - query: ` - query web_PlotterCode($file: web_FileInput){ - web_PlotterCode(file: $file) - } - `, - variables: { - file: { - container: container.toLowerCase(), - filePath: filePath, - storage: '', - accessKey: '' - } - } - }, - headers: headers - }).then(res => { - if (res.data.errors) { - if (ERROR_LOG === true) { console.log(MODULE_NAME + ' : ' + '[ERROR] FileCloud -> getBlobToText -> response.text = ' + JSON.stringify(res.data.errors)) } - callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE, '', '') - } - let response = res.data.data.web_PlotterCode - if (response) - callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE, response, '') - else - callBackFunction(GLOBAL.CUSTOM_FAIL_RESPONSE) - }).catch(error => { - if (ERROR_LOG === true) { console.log(MODULE_NAME + ' : ' + '[ERROR] FileCloud -> getBlobToText -> Invalid JSON received: ' + error.message, error.stack) } - callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE, '', '') - }) - - } catch (err) { - if (ERROR_LOG === true) { console.log('[ERROR] FileCloud -> getBlobToText -> err = ' + err.message, err.stack) } - } - } -} diff --git a/ecosystem.json b/ecosystem.json new file mode 100644 index 000000000..449426410 --- /dev/null +++ b/ecosystem.json @@ -0,0 +1,1258 @@ +{ + "devTeams": [ + { + "codeName": "AAMasters", + "displayName": "Masters", + "host": { + "url": "https://demo-api-dev.superalgos.org/", + "storage": "localStorage", + "container": "aamasters", + "accessKey": "09e890b76767ede3e10f0526b5036600a6b8d3faac540336e12b493fdb2aa9ed46f86094c34652f99fb6322e5f09806412f17725807f85e4dc4169bd22dd59f0b23aba5251f5544478a1aabf5a2dea5260e6eb0c29af3a788208af85025a02f94950437d501b91fd55b9d97b3d6ac3af4e1161321f78b73ca0fda524dc3a5d03" + }, + "bots": [ + { + "codeName": "AAOlivia", + "displayName": "Olivia", + "type": "Indicator", + "profilePicture": "Olivia.png", + "repo": "AAOlivia-Indicator-Bot", + "configFile": "this.bot.config.json", + "products": [ + { + "codeName": "Candles", + "displayName": "Candles", + "description": "Two sets of files per period that contains candles.", + "dataSets": [ + { + "codeName": "Multi-Period-Market", + "type": "Market Files", + "validPeriods": [ + "24-hs", + "12-hs", + "08-hs", + "06-hs", + "04-hs", + "03-hs", + "02-hs", + "01-hs" + ], + "filePath": "AAMasters/AAOlivia.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candles/Multi-Period-Market/@Period", + "fileName": "@AssetA_@AssetB.json" + }, + { + "codeName": "Multi-Period-Daily", + "type": "Daily Files", + "validPeriods": [ + "45-min", + "40-min", + "30-min", + "20-min", + "15-min", + "10-min", + "05-min", + "04-min", + "03-min", + "02-min", + "01-min" + ], + "filePath": "AAMasters/AAOlivia.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candles/Multi-Period-Daily/@Period/@Year/@Month/@Day", + "fileName": "@AssetA_@AssetB.json", + "dataRange": { + "filePath": "AAMasters/AAOlivia.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candles/Multi-Period-Daily", + "fileName": "Data.Range.@AssetA_@AssetB.json" + } + } + ], + "exchangeList": [ + { + "name": "Poloniex" + }, + { + "name": "Coss" + } + ], + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersCandlesVolumes", + "moduleName": "Candles" + } + }, + { + "codeName": "Volumes", + "displayName": "Buy and Sell Volumes", + "description": "Two sets of files per period that contains buy and sell volumes.", + "dataSets": [ + { + "codeName": "Multi-Period-Market", + "type": "Market Files", + "validPeriods": [ + "24-hs", + "12-hs", + "08-hs", + "06-hs", + "04-hs", + "03-hs", + "02-hs", + "01-hs" + ], + "filePath": "AAMasters/AAOlivia.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volumes/Multi-Period-Market/@Period", + "fileName": "@AssetA_@AssetB.json" + }, + { + "codeName": "Multi-Period-Daily", + "type": "Daily Files", + "validPeriods": [ + "45-min", + "40-min", + "30-min", + "20-min", + "15-min", + "10-min", + "05-min", + "04-min", + "03-min", + "02-min", + "01-min" + ], + "filePath": "AAMasters/AAOlivia.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volumes/Multi-Period-Daily/@Period/@Year/@Month/@Day", + "fileName": "@AssetA_@AssetB.json", + "dataRange": { + "filePath": "AAMasters/AAOlivia.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volumes/Multi-Period-Daily", + "fileName": "Data.Range.@AssetA_@AssetB.json" + } + } + ], + "exchangeList": [ + { + "name": "Poloniex" + }, + { + "name": "Coss" + } + ], + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersCandlesVolumes", + "moduleName": "Volumes" + } + } + ] + }, + { + "codeName": "AATom", + "displayName": "Tom", + "type": "Indicator", + "profilePicture": "Tom.png", + "repo": "AATom-Indicator-Bot", + "configFile": "this.bot.config.json", + "products": [ + { + "codeName": "Candle-Stairs", + "displayName": "Candle-Stairs Patters", + "description": "Two sets of files per period that contains candle-stairs patterns.", + "dataSets": [ + { + "codeName": "Multi-Period-Market", + "type": "Market Files", + "validPeriods": [ + "24-hs", + "12-hs", + "08-hs", + "06-hs", + "04-hs", + "03-hs", + "02-hs", + "01-hs" + ], + "filePath": "AAMasters/AATom.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candle-Stairs/Multi-Period-Market/@Period", + "fileName": "@AssetA_@AssetB.json" + }, + { + "codeName": "Multi-Period-Daily", + "type": "Daily Files", + "validPeriods": [ + "45-min", + "40-min", + "30-min", + "20-min", + "15-min", + "10-min", + "05-min", + "04-min", + "03-min", + "02-min", + "01-min" + ], + "filePath": "AAMasters/AATom.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candle-Stairs/Multi-Period-Daily/@Period/@Year/@Month/@Day", + "fileName": "@AssetA_@AssetB.json", + "dataRange": { + "filePath": "AAMasters/AATom.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Candle-Stairs/Multi-Period-Daily", + "fileName": "Data.Range.@AssetA_@AssetB.json" + } + } + ], + "exchangeList": [ + { + "name": "Poloniex" + }, + { + "name": "Coss" + } + ], + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersStairsPatterns", + "moduleName": "CandleStairs" + } + }, + { + "codeName": "Volume-Stairs", + "displayName": "Volume-Stairs Patters", + "description": "Two sets of files per period that contains volume-stairs patterns.", + "dataSets": [ + { + "codeName": "Multi-Period-Market", + "type": "Market Files", + "validPeriods": [ + "24-hs", + "12-hs", + "08-hs", + "06-hs", + "04-hs", + "03-hs", + "02-hs", + "01-hs" + ], + "filePath": "AAMasters/AATom.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volume-Stairs/Multi-Period-Market/@Period", + "fileName": "@AssetA_@AssetB.json" + }, + { + "codeName": "Multi-Period-Daily", + "type": "Daily Files", + "validPeriods": [ + "45-min", + "40-min", + "30-min", + "20-min", + "15-min", + "10-min", + "05-min", + "04-min", + "03-min", + "02-min", + "01-min" + ], + "filePath": "AAMasters/AATom.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volume-Stairs/Multi-Period-Daily/@Period/@Year/@Month/@Day", + "fileName": "@AssetA_@AssetB.json", + "dataRange": { + "filePath": "AAMasters/AATom.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Volume-Stairs/Multi-Period-Daily", + "fileName": "Data.Range.@AssetA_@AssetB.json" + } + } + ], + "exchangeList": [ + { + "name": "Poloniex" + }, + { + "name": "Coss" + } + ], + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersStairsPatterns", + "moduleName": "VolumeStairs" + } + } + ] + }, + { + "codeName": "AAChris", + "displayName": "Chris", + "type": "Indicator", + "profilePicture": "Chris.png", + "repo": "AAChris-Indicator-Bot", + "configFile": "this.bot.config.json", + "products": [ + { + "codeName": "Bollinger-Bands", + "displayName": "Bollinger Bands", + "description": "Bollinger Bands", + "dataSets": [ + { + "codeName": "Multi-Period-Market", + "type": "Market Files", + "validPeriods": [ + "24-hs", + "12-hs", + "08-hs", + "06-hs", + "04-hs", + "03-hs", + "02-hs", + "01-hs" + ], + "filePath": "AAMasters/AAChris.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Bands/Multi-Period-Market/@Period", + "fileName": "@AssetA_@AssetB.json" + }, + { + "codeName": "Multi-Period-Daily", + "type": "Daily Files", + "validPeriods": [ + "45-min", + "40-min", + "30-min", + "20-min", + "15-min", + "10-min", + "05-min", + "04-min", + "03-min", + "02-min", + "01-min" + ], + "filePath": "AAMasters/AAChris.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Bands/Multi-Period-Daily/@Period/@Year/@Month/@Day", + "fileName": "@AssetA_@AssetB.json", + "dataRange": { + "filePath": "AAMasters/AAChris.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Bands/Multi-Period-Daily", + "fileName": "Data.Range.@AssetA_@AssetB.json" + } + } + ], + "exchangeList": [ + { + "name": "Poloniex" + }, + { + "name": "Coss" + } + ], + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersBollingerBands", + "moduleName": "BollingerBands" + } + }, + { + "codeName": "Percentage-Bandwidth", + "displayName": "Percentage Bandwidth", + "description": "Percentage Bandwidth", + "dataSets": [ + { + "codeName": "Multi-Period-Market", + "type": "Market Files", + "validPeriods": [ + "24-hs", + "12-hs", + "08-hs", + "06-hs", + "04-hs", + "03-hs", + "02-hs", + "01-hs" + ], + "filePath": "AAMasters/AAChris.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Percentage-Bandwidth/Multi-Period-Market/@Period", + "fileName": "@AssetA_@AssetB.json" + }, + { + "codeName": "Multi-Period-Daily", + "type": "Daily Files", + "validPeriods": [ + "45-min", + "40-min", + "30-min", + "20-min", + "15-min", + "10-min", + "05-min", + "04-min", + "03-min", + "02-min", + "01-min" + ], + "filePath": "AAMasters/AAChris.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Percentage-Bandwidth/Multi-Period-Daily/@Period/@Year/@Month/@Day", + "fileName": "@AssetA_@AssetB.json", + "dataRange": { + "filePath": "AAMasters/AAChris.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Percentage-Bandwidth/Multi-Period-Daily", + "fileName": "Data.Range.@AssetA_@AssetB.json" + } + } + ], + "exchangeList": [ + { + "name": "Poloniex" + }, + { + "name": "Coss" + } + ], + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersBollingerBands", + "moduleName": "PercentageBandwidth" + } + } + ] + }, + { + "codeName": "AAPaula", + "displayName": "Paula", + "type": "Indicator", + "profilePicture": "Paula.png", + "repo": "AAPaula-Indicator-Bot", + "configFile": "this.bot.config.json", + "products": [ + { + "codeName": "Bollinger-Channels", + "displayName": "Bollinger-Channels", + "description": "Two sets of files per period that contains band-channel patterns.", + "dataSets": [ + { + "codeName": "Multi-Period-Market", + "type": "Market Files", + "validPeriods": [ + "24-hs", + "12-hs", + "08-hs", + "06-hs", + "04-hs", + "03-hs", + "02-hs", + "01-hs" + ], + "filePath": "AAMasters/AAPaula.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Channels/Multi-Period-Market/@Period", + "fileName": "@AssetA_@AssetB.json" + }, + { + "codeName": "Multi-Period-Daily", + "type": "Daily Files", + "validPeriods": [ + "45-min", + "40-min", + "30-min", + "20-min", + "15-min", + "10-min", + "05-min", + "04-min", + "03-min", + "02-min", + "01-min" + ], + "filePath": "AAMasters/AAPaula.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Channels/Multi-Period-Daily/@Period/@Year/@Month/@Day", + "fileName": "@AssetA_@AssetB.json", + "dataRange": { + "filePath": "AAMasters/AAPaula.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Channels/Multi-Period-Daily", + "fileName": "Data.Range.@AssetA_@AssetB.json" + } + } + ], + "exchangeList": [ + { + "name": "Poloniex" + }, + { + "name": "Coss" + } + ], + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersBollingerChannels", + "moduleName": "BollingerChannels" + } + }, + { + "codeName": "Bollinger-Sub-Channels", + "displayName": "Bollinger-Sub-Channels", + "description": "Bollinger Sub Channels with slope.", + "dataSets": [ + { + "codeName": "Multi-Period-Market", + "type": "Market Files", + "validPeriods": [ + "24-hs", + "12-hs", + "08-hs", + "06-hs", + "04-hs", + "03-hs", + "02-hs", + "01-hs" + ], + "filePath": "AAMasters/AAPaula.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Sub-Channels/Multi-Period-Market/@Period", + "fileName": "@AssetA_@AssetB.json" + }, + { + "codeName": "Multi-Period-Daily", + "type": "Daily Files", + "validPeriods": [ + "45-min", + "40-min", + "30-min", + "20-min", + "15-min", + "10-min", + "05-min", + "04-min", + "03-min", + "02-min", + "01-min" + ], + "filePath": "AAMasters/AAPaula.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Sub-Channels/Multi-Period-Daily/@Period/@Year/@Month/@Day", + "fileName": "@AssetA_@AssetB.json", + "dataRange": { + "filePath": "AAMasters/AAPaula.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Sub-Channels/Multi-Period-Daily", + "fileName": "Data.Range.@AssetA_@AssetB.json" + } + } + ], + "exchangeList": [ + { + "name": "Poloniex" + }, + { + "name": "Coss" + } + ], + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersBollingerChannels", + "moduleName": "BollingerSubChannels" + } + } + ] + } + ], + "plotters": [ + { + "displayName": "Plotters Candles & Volumes", + "codeName": "PlottersCandlesVolumes", + "devTeam": "AAMasters", + "modules": [ + { + "codeName": "Candles", + "moduleName": "Candles", + "description": "Plots traditional red and green candles.", + "profilePicture": "Candles.png", + "panels": [ + { + "codeName": "CandlePanel", + "moduleName": "CandlePanel", + "event": "Current Candle Changed" + } + ] + }, + { + "codeName": "Volumes", + "description": "Plots volumes separated in buy and sell.", + "moduleName": "Volumes", + "profilePicture": "Volumes.png", + "panels": [ + { + "codeName": "VolumePanel", + "moduleName": "VolumePanel", + "event": "Current Volume Changed" + } + ] + } + ], + "repo": "Plotters-Candles-Volumes", + "configFile": "this.plotter.config.json" + }, + { + "displayName": "Plotters Stairs Patterns", + "codeName": "PlottersStairsPatterns", + "devTeam": "AAMasters", + "modules": [ + { + "codeName": "CandleStairs", + "moduleName": "CandleStairs", + "description": "Plots Candle Stairs patterns.", + "profilePicture": "CandleStairs.png", + "panels": [] + }, + { + "codeName": "VolumeStairs", + "description": "Plots Volume Stairs patterns.", + "moduleName": "VolumeStairs", + "profilePicture": "VolumeStairs.png", + "panels": [] + } + ], + "repo": "Plotters-Stairs-Patterns", + "configFile": "this.plotter.config.json" + }, + { + "displayName": "Plotters Trading", + "codeName": "PlottersTrading", + "devTeam": "AAMasters", + "modules": [ + { + "codeName": "Details", + "moduleName": "Details", + "description": "Plots trading decitions in an easy to understand way.", + "panels": [] + }, + { + "codeName": "History", + "moduleName": "History", + "description": "Plots trading history.", + "profilePicture": "History.png", + "panels": [] + } + ], + "repo": "Plotters-Trading", + "configFile": "this.plotter.config.json" + }, + { + "displayName": "Plotters Bollinger Bands", + "codeName": "PlottersBollingerBands", + "devTeam": "AAMasters", + "modules": [ + { + "codeName": "BollingerBands", + "moduleName": "BollingerBands", + "description": "Plots Bollinger Bands.", + "profilePicture": "BollingerBands.png", + "panels": [ + { + "codeName": "BollingerBandsPanel", + "moduleName": "BollingerBandsPanel", + "event": "Current Band Changed" + } + ] + }, + { + "codeName": "PercentageBandwidth", + "moduleName": "PercentageBandwidth", + "description": "Plots Bollinger Bands.", + "profilePicture": "PercentageBandwidth.png", + "panels": [] + } + ], + "repo": "Plotters-Bollinger-Bands", + "configFile": "this.plotter.config.json" + }, + { + "displayName": "Plotters Trading Simulation", + "codeName": "PlottersTradingSimulation", + "devTeam": "AAMasters", + "modules": [ + { + "codeName": "TradingSimulation", + "moduleName": "TradingSimulation", + "description": "Plots Bollinger Records.", + "profilePicture": "TradingSimulation.png", + "panels": [ + { + "codeName": "TradingSimulationPanel", + "moduleName": "TradingSimulationPanel", + "event": "Current Record Changed" + } + ] + }, + { + "codeName": "Conditions", + "moduleName": "Conditions", + "description": "Plots Simulation Conditions.", + "profilePicture": "Conditions.png", + "panels": [] + }, + { + "codeName": "Strategies", + "moduleName": "Strategies", + "description": "Plots Strategies.", + "profilePicture": "Strategies.png", + "panels": [] + }, + { + "codeName": "Trades", + "moduleName": "Trades", + "description": "Plots Trades.", + "profilePicture": "Trades.png", + "panels": [] + }, + { + "codeName": "SimulationExecution", + "moduleName": "SimulationExecution", + "description": "Plots Simulation Execution.", + "profilePicture": "SimulationExecution.png", + "panels": [ + { + "codeName": "SimulationExecutionPanel", + "moduleName": "SimulationExecutionPanel", + "event": "Current Record Changed" + } + ] + } + ], + "repo": "Plotters-Trading-Simulation", + "configFile": "this.plotter.config.json" + }, + { + "displayName": "Plotters Bollinger Channels", + "codeName": "PlottersBollingerChannels", + "devTeam": "AAMasters", + "modules": [ + { + "codeName": "BollingerChannels", + "moduleName": "BollingerChannels", + "description": "Plots Bollinger Channels.", + "profilePicture": "BollingerChannels.png", + "panels": [ + { + "codeName": "ChannelPanel", + "moduleName": "ChannelPanel", + "event": "Current Channel Changed" + } + ] + }, + { + "codeName": "BollingerSubChannels", + "moduleName": "BollingerSubChannels", + "description": "Plots Bollinger Sub-Channels.", + "profilePicture": "BollingerSubChannels.png", + "panels": [ + { + "codeName": "SubChannelPanel", + "moduleName": "SubChannelPanel", + "event": "Current Sub-Channel Changed" + } + ] + } + ], + "repo": "Plotters-Bollinger-Channels", + "configFile": "this.plotter.config.json" + } + ] + }, + { + "codeName": "AAVikings", + "displayName": "Vikings", + "host": { + "url": "https://demo-api-dev.superalgos.org/", + "container": "aavikings", + "storage": "localStorage", + "accessKey": "0f38fea438be5adfc5873228f503c55353fb334406128b16a958851b8e47c118a08f0105dd8985d5479758fc4cc3f56c2e2364c2d7c3d0fdffba8d7e9356056a34629e3b926b1ebb940122d973db30b04fc18fab542cbc1afdc032dccf64b0fe308ee6bbc74f82bd350aaebf723428a50d8a699fa2b4b96d58716986ed24069f" + }, + "bots": [ + { + "codeName": "AAGauss", + "displayName": "Gauss", + "type": "Indicator", + "profilePicture": "Gauss.png", + "repo": "AAGauss-Indicator-Bot", + "configFile": "this.bot.config.json", + "products": [ + { + "codeName": "LRCPoints", + "displayName": "LRCPoints", + "description": "Two sets of files per period that contains LRC points.", + "dataSets": [ + { + "codeName": "Multi-Period-Market", + "type": "Market Files", + "validPeriods": [ + "24-hs", + "12-hs", + "08-hs", + "06-hs", + "04-hs", + "03-hs", + "02-hs", + "01-hs" + ], + "filePath": "AAVikings/AAGauss.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/LRC-Points/Multi-Period-Market/@Period", + "fileName": "@AssetA_@AssetB.json" + }, + { + "codeName": "Multi-Period-Daily", + "type": "Daily Files", + "validPeriods": [ + "45-min", + "40-min", + "30-min", + "20-min", + "15-min", + "10-min", + "05-min", + "04-min", + "03-min", + "02-min", + "01-min" + ], + "filePath": "AAVikings/AAGauss.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/LRC-Points/Multi-Period-Daily/@Period/@Year/@Month/@Day", + "fileName": "@AssetA_@AssetB.json", + "dataRange": { + "filePath": "AAVikings/AAGauss.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/LRC-Points/Multi-Period-Daily", + "fileName": "Data.Range.@AssetA_@AssetB.json" + } + } + ], + "exchangeList": [ + { + "name": "Poloniex" + }, + { + "name": "Coss" + } + ], + "plotter": { + "devTeam": "AAVikings", + "codeName": "PlotterLinearRegressionCurve", + "moduleName": "LRC" + } + } + ] + } + ], + "plotters": [ + { + "displayName": "Plotter LRC", + "codeName": "PlotterLinearRegressionCurve", + "devTeam": "AAVikings", + "modules": [ + { + "codeName": "LRC", + "moduleName": "LRC", + "description": "Plots the linear regression curve.", + "profilePicture": "LRC.png", + "panels": [ + { + "codeName": "ChannelPanel", + "moduleName": "ChannelPanel", + "event": "Current LRC Changed" + } + ] + } + ], + "repo": "Plotters-Linear-Regression-Curve", + "configFile": "this.plotter.config.json" + } + ] + }, + { + "codeName": "user", + "displayName": "user", + "bots": [ + { + "displayName": "Simulator bot-user", + "codeName": "simulator-bot-user", + "type": "Indicator", + "profilePicture": "simulator-bot-user.png", + "products": [ + { + "codeName": "Trading-Simulation", + "displayName": "Trading Simulation", + "description": "Trading Simulation", + "dataSets": [ + { + "validPeriods": [ + "24-hs", + "12-hs", + "08-hs", + "06-hs", + "04-hs", + "03-hs", + "02-hs", + "01-hs" + ], + "codeName": "Multi-Period-Market", + "type": "Market Files", + "filePath": "user/simulator-bot-user.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Trading-Simulation/Multi-Period-Market/@Period", + "fileName": "@AssetA_@AssetB.json" + }, + { + "validPeriods": [ + "15-min", + "10-min", + "05-min" + ], + "codeName": "Multi-Period-Daily", + "type": "Daily Files", + "filePath": "user/simulator-bot-user.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Trading-Simulation/Multi-Period-Daily/@Period/@Year/@Month/@Day", + "fileName": "@AssetA_@AssetB.json", + "dataRange": { + "filePath": "user/simulator-bot-user.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Trading-Simulation/Multi-Period-Daily", + "fileName": "Data.Range.@AssetA_@AssetB.json" + } + } + ], + "exchangeList": [ + { + "name": "Poloniex" + }, + { + "name": "Coss" + } + ], + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersTradingSimulation", + "moduleName": "TradingSimulation" + } + }, + { + "codeName": "Simulation-Conditions", + "displayName": "Simulation Conditions", + "description": "Simulation Conditions", + "dataSets": [ + { + "validPeriods": [ + "24-hs", + "12-hs", + "08-hs", + "06-hs", + "04-hs", + "03-hs", + "02-hs", + "01-hs" + ], + "codeName": "Multi-Period-Market", + "type": "Market Files", + "filePath": "user/simulator-bot-user.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Simulation-Conditions/Multi-Period-Market/@Period", + "fileName": "@AssetA_@AssetB.json" + }, + { + "validPeriods": [ + "15-min", + "10-min", + "05-min" + ], + "codeName": "Multi-Period-Daily", + "type": "Daily Files", + "filePath": "user/simulator-bot-user.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Simulation-Conditions/Multi-Period-Daily/@Period/@Year/@Month/@Day", + "fileName": "@AssetA_@AssetB.json", + "dataRange": { + "filePath": "user/simulator-bot-user.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Simulation-Conditions/Multi-Period-Daily", + "fileName": "Data.Range.@AssetA_@AssetB.json" + } + } + ], + "exchangeList": [ + { + "name": "Poloniex" + }, + { + "name": "Coss" + } + ], + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersTradingSimulation", + "moduleName": "Conditions" + } + }, + { + "codeName": "Simulation-Strategies", + "displayName": "Simulation Strategies", + "description": "Simulation Strategies", + "dataSets": [ + { + "validPeriods": [ + "24-hs", + "12-hs", + "08-hs", + "06-hs", + "04-hs", + "03-hs", + "02-hs", + "01-hs" + ], + "codeName": "Multi-Period-Market", + "type": "Market Files", + "filePath": "user/simulator-bot-user.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Simulation-Strategies/Multi-Period-Market/@Period", + "fileName": "@AssetA_@AssetB.json" + }, + { + "validPeriods": [ + "15-min", + "10-min", + "05-min" + ], + "codeName": "Multi-Period-Daily", + "type": "Daily Files", + "filePath": "user/simulator-bot-user.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Simulation-Strategies/Multi-Period-Daily/@Period/@Year/@Month/@Day", + "fileName": "@AssetA_@AssetB.json", + "dataRange": { + "filePath": "user/simulator-bot-user.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Simulation-Strategies/Multi-Period-Daily", + "fileName": "Data.Range.@AssetA_@AssetB.json" + } + } + ], + "exchangeList": [ + { + "name": "Poloniex" + }, + { + "name": "Coss" + } + ], + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersTradingSimulation", + "moduleName": "Strategies" + } + }, + { + "codeName": "Simulation-Trades", + "displayName": "Simulation Trades", + "description": "Simulation Trades", + "dataSets": [ + { + "validPeriods": [ + "24-hs", + "12-hs", + "08-hs", + "06-hs", + "04-hs", + "03-hs", + "02-hs", + "01-hs" + ], + "codeName": "Multi-Period-Market", + "type": "Market Files", + "filePath": "user/simulator-bot-user.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Simulation-Trades/Multi-Period-Market/@Period", + "fileName": "@AssetA_@AssetB.json" + }, + { + "validPeriods": [ + "15-min", + "10-min", + "05-min" + ], + "codeName": "Multi-Period-Daily", + "type": "Daily Files", + "filePath": "user/simulator-bot-user.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Simulation-Trades/Multi-Period-Daily/@Period/@Year/@Month/@Day", + "fileName": "@AssetA_@AssetB.json", + "dataRange": { + "filePath": "user/simulator-bot-user.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Simulation-Trades/Multi-Period-Daily", + "fileName": "Data.Range.@AssetA_@AssetB.json" + } + } + ], + "exchangeList": [ + { + "name": "Poloniex" + }, + { + "name": "Coss" + } + ], + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersTradingSimulation", + "moduleName": "Trades" + } + } + ] + }, + { + "displayName": "bot-user", + "codeName": "bot-user", + "type": "Trading", + "cloneId":"1", + "profilePicture": "bot-user.png", + "products": [ + { + "codeName": "Live Trading History", + "displayName": "Live Trading History", + "description": "General information about trading history.", + "dataSets": [ + { + "validPeriods": [ + "24-hs", + "12-hs", + "08-hs", + "06-hs", + "04-hs", + "03-hs", + "02-hs", + "01-hs", + "45-min", + "40-min", + "30-min", + "20-min", + "15-min", + "10-min", + "05-min", + "04-min", + "03-min", + "02-min", + "01-min" + ], + "codeName": "Oficial History", + "type": "File Sequence", + "filePath": "@DevTeam/@Bot.1.0/AACloud.1.1/Poloniex/dataSet.V1/Output/Trading-Process", + "fileName": "Execution.History.Live.@Sequence.json" + } + ], + "exchangeList": [ + { + "name": "Poloniex" + } + ], + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersTradingSimulation", + "moduleName": "SimulationExecution" + } + }, + { + "codeName": "Backtest Trading History", + "displayName": "Backtest Trading History", + "description": "General information about backtest trading history.", + "dataSets": [ + { + "validPeriods": [ + "24-hs", + "12-hs", + "08-hs", + "06-hs", + "04-hs", + "03-hs", + "02-hs", + "01-hs", + "45-min", + "40-min", + "30-min", + "20-min", + "15-min", + "10-min", + "05-min", + "04-min", + "03-min", + "02-min", + "01-min" + ], + "codeName": "Backtest History", + "type": "File Sequence", + "filePath": "@DevTeam/@Bot.1.0/AACloud.1.1/Poloniex/dataSet.V1/Output/Trading-Process", + "fileName": "Execution.History.Backtest.@Sequence.json" + } + ], + "exchangeList": [ + { + "name": "Poloniex" + } + ], + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersTradingSimulation", + "moduleName": "SimulationExecution" + } + }, + { + "codeName": "Competition Trading History", + "displayName": "Competition Trading History", + "description": "General information about competition trading history.", + "dataSets": [ + { + "validPeriods": [ + "24-hs", + "12-hs", + "08-hs", + "06-hs", + "04-hs", + "03-hs", + "02-hs", + "01-hs", + "45-min", + "40-min", + "30-min", + "20-min", + "15-min", + "10-min", + "05-min", + "04-min", + "03-min", + "02-min", + "01-min" + ], + "codeName": "Competition History", + "type": "File Sequence", + "filePath": "@DevTeam/@Bot.1.0/AACloud.1.1/Poloniex/dataSet.V1/Output/Trading-Process", + "fileName": "Execution.History.Competition.@Sequence.json" + } + ], + "exchangeList": [ + { + "name": "Poloniex" + } + ], + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersTradingSimulation", + "moduleName": "SimulationExecution" + } + } + ] + } + ], + "host": { + "url": "localhost", + "storage": "localStorage", + "container": "user", + "accessKey": "", + "ownerKey": "" + }, + "plotters": [] + } + ], + "hosts": [ + { + "codeName": "AAMasters", + "displayName": "AA Arena", + "host": { + "url": "https://demo-api-dev.superalgos.org/", + "storage": "localStorage", + "container": "aamasters", + "accessKey": "09e890b76767ede3e10f0526b5036600a6b8d3faac540336e12b493fdb2aa9ed46f86094c34652f99fb6322e5f09806412f17725807f85e4dc4169bd22dd59f0b23aba5251f5544478a1aabf5a2dea5260e6eb0c29af3a788208af85025a02f94950437d501b91fd55b9d97b3d6ac3af4e1161321f78b73ca0fda524dc3a5d03" + }, + "competitions": [ + { + "codeName": "Weekend-Deathmatch", + "description": "First AA Internal Competition. Bots will be trading during 3 days at the USDT/BTC market of Poloniex to see who can make the gratest return over investment (ROI).", + "displayName": "AA Internal Challenge", + "startDatetime": "2018-01-01T16:00:00.000Z", + "finishDatetime": "2018-01-02T16:00:00.000Z", + "formula": "ROI", + "plotter": { + "devTeam": "AAMasters", + "codeName": "PlottersROI", + "host": { + "url": "https://demo-api-dev.superalgos.org/", + "storage": "localStorage", + "container": "aamasters", + "accessKey": "" + }, + "moduleName": "CombinedProfits", + "repo": "Plotters-ROI" + }, + "rules": [], + "prizes": [], + "participants": [], + "repo": "Weekend-Deathmatch", + "configFile": "this.competition.config.json" + } + ], + "plotters": [ + { + "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": [] + } + ], + "repo": "Plotters-ROI", + "configFile": "this.plotter.config.json" + } + ] + } + ] +} diff --git a/index.html b/index.html index d3e1678bf..50fe33b25 100644 --- a/index.html +++ b/index.html @@ -1,42 +1,67 @@ - + + - - - - - Superalgos + + Superalgos Platform + + + + + + + + - - - - - - + + + + + + + - - -
-
-
-
- + +
+
+
+
+ diff --git a/server.js b/server.js index bf9b8bd69..7ba53980e 100644 --- a/server.js +++ b/server.js @@ -34,12 +34,9 @@ let http = require('http') let port = process.env.PORT || 1337 let isHttpServerStarted = false -const FILE_CLOUD = require('./Server/FileCloud') -let fileCloud = FILE_CLOUD.newFileCloud() - startHtttpServer() -function startHtttpServer () { +function startHtttpServer() { if (CONSOLE_LOG === true) { console.log('[INFO] server -> startHtttpServer -> Entering function.') } try { @@ -52,7 +49,7 @@ function startHtttpServer () { } } -function onBrowserRequest (request, response) { +function onBrowserRequest(request, response) { if (CONSOLE_LOG === true && request.url.indexOf('NO-LOG') === -1) { console.log('[INFO] server -> onBrowserRequest -> request.url = ' + request.url) } let requestParameters = request.url.split('/') @@ -148,15 +145,15 @@ function onBrowserRequest (request, response) { { if (requestParameters[3] === undefined) { - respondWithFile(process.env.PATH_TO_CANVAS_APP + '/StrategySpace/' + requestParameters[2], response) + respondWithFile(process.env.PATH_TO_CANVAS_APP + '/StrategySpace/' + requestParameters[2], response) return } if (requestParameters[4] === undefined) { - respondWithFile(process.env.PATH_TO_CANVAS_APP + '/StrategySpace/' + requestParameters[2] + '/' + requestParameters[3], response) + respondWithFile(process.env.PATH_TO_CANVAS_APP + '/StrategySpace/' + requestParameters[2] + '/' + requestParameters[3], response) return } if (requestParameters[5] === undefined) { - respondWithFile(process.env.PATH_TO_CANVAS_APP + '/StrategySpace/' + requestParameters[2] + '/' + requestParameters[3] + '/' + requestParameters[4], response) + respondWithFile(process.env.PATH_TO_CANVAS_APP + '/StrategySpace/' + requestParameters[2] + '/' + requestParameters[3] + '/' + requestParameters[4], response) return } } @@ -182,13 +179,21 @@ function onBrowserRequest (request, response) { case 'Plotters': // This means the plotter folder, not to be confused with the Plotters script! { - respondWithSourceCode(requestParameters, response) + let devTeam = requestParameters[2] + let codeName = requestParameters[3] + let moduleName = requestParameters[4] + let filePath = './Plotters/' + devTeam + '/plotters/' + codeName + '/' + moduleName + respondWithFile(filePath, response) } break case 'PlotterPanels': // This means the PlotterPanels folder, not to be confused with the Plotter Panels scripts! { - respondWithSourceCode(requestParameters, response) + let devTeam = requestParameters[2] + let codeName = requestParameters[3] + let moduleName = requestParameters[4] + let filePath = './Plotters/' + devTeam + '/plotters/' + codeName + '/' + moduleName + respondWithFile(filePath, response) } break case 'Panels': @@ -233,20 +238,87 @@ function onBrowserRequest (request, response) { } break + case 'UserEcosystem.js': + { + let fs = require('fs') + + try { + let filePath = process.env.CONFIG_PATH + '/ecosystem.json' + fs.readFile(filePath, onFileRead) + } catch (e) { + console.log('[ERROR] Error reading the user ecosystem.', e) + } + + function onFileRead(err, userEcosystem) { + if (err) { + respondWithContent(undefined, response) + } else { + let responseContent = 'function getUserEcosystem(){ return ' + userEcosystem + '}' + respondWithContent(responseContent, response) + } + } + } + break + + case 'Storage': + { + respondWithFile(process.env.STORAGE_PATH + '/' + request.url.substring(9), response) + } + break + + case 'ReadUserConfig': + { + respondWithFile(process.env.CONFIG_PATH + '/userConfig.json', response) + } + break + + case 'WriteUserConfig': + { + let fs = require('fs') + let body = ''; + + request.on('data', function (data) { + body += data; + // Too much POST data + if (body.length > 1e6) + request.connection.destroy(); + }); + + request.on('end', function () { + try { + let filePath = process.env.CONFIG_PATH + '/userConfig.json' + fs.writeFile(filePath, body, onFileWrite) + } catch (e) { + console.log('[ERROR] Error writing user config.', e) + respondWithContent(undefined, response) + } + + function onFileWrite(err) { + if (err) { + respondWithContent(undefined, response) + } else { + let responseContent = 'User config updated.' + respondWithContent(responseContent, response) + } + } + }); + } + break + default: { homePage() } } - function homePage () { + function homePage() { if (requestParameters[1] === '') { let fs = require('fs') try { let fileName = 'index.html' fs.readFile(fileName, onFileRead) - function onFileRead (err, file) { + function onFileRead(err, file) { if (CONSOLE_LOG === true) { console.log('[INFO] server -> onBrowserRequest -> onFileRead -> Entering function.') } try { @@ -272,7 +344,32 @@ function onBrowserRequest (request, response) { } } -function respondWithContent (content, response) { +function respondWithFile(fileName, response) { + if (CONSOLE_LOG === true) { console.log('[INFO] server -> respondWithFile -> Entering function.') } + + let fs = require('fs') + if (fileName.indexOf('undefined') > 0) { + console.log('[WRN] server -> respondWithFile -> Received request for undefined file. ') + respondWithContent(undefined, response) + } else { + try { + fs.readFile(fileName, onFileRead) + + function onFileRead(err, file) { + if (CONSOLE_LOG === true) { console.log('[INFO] server -> respondWithFile -> onFileRead -> Entering function.') } + if (!err) { + respondWithContent(file.toString(), response) + } else { + respondWithContent(undefined, response) + } + } + } catch (err) { + returnEmptyArray() + } + } +} + +function respondWithContent(content, response) { if (CONSOLE_LOG === true) { console.log('[INFO] server -> respondWithContent -> Entering function.') } try { @@ -281,61 +378,27 @@ function respondWithContent (content, response) { response.setHeader('Expires', '0') // Proxies. response.setHeader('Access-Control-Allow-Origin', '*') // Allows to access data from other domains. - response.writeHead(200, { 'Content-Type': 'text/html' }) - response.write(content) + if (content !== undefined) { + response.writeHead(200, { 'Content-Type': 'text/html' }) + response.write(content) + } else { + response.writeHead(404, { 'Content-Type': 'text/html' }); + response.write('The specified key does not exist.') + } response.end('\n') - // console.log("Content Sent: " + content); } catch (err) { returnEmptyArray(response) } } -function respondWithFile (fileName, response) { - if (CONSOLE_LOG === true) { console.log('[INFO] server -> respondWithFile -> Entering function.') } - - let fs = require('fs') - try { - if (fileName.indexOf('undefined') > 0) { - console.log('[WRN] server -> respondWithFile -> Received request for undefined file. ') - return - } - - fs.readFile(fileName, onFileRead) - - function onFileRead (err, file) { - if (CONSOLE_LOG === true) { console.log('[INFO] server -> respondWithFile -> onFileRead -> Entering function.') } - - try { - let htmlResponse = file.toString() - - response.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate') // HTTP 1.1. - response.setHeader('Pragma', 'no-cache') // HTTP 1.0. - response.setHeader('Expires', '0') // Proxies. - response.setHeader('Access-Control-Allow-Origin', '*') // Allows to access data from other domains. - - // response.writeHead(200, { 'Content-Type': 'text/html' }); - response.write(htmlResponse) - response.end('\n') - // console.log("File Sent: " + fileName); - // - } catch (err) { - console.log('[ERROR] server -> respondWithFile -> onFileRead -> File Not Found: ' + fileName + ' or Error = ' + err.stack) - returnEmptyArray() - } - } - } catch (err) { - returnEmptyArray() - } -} - -function respondWithImage (fileName, response) { +function respondWithImage(fileName, response) { if (CONSOLE_LOG === true) { console.log('[INFO] server -> respondWithImage -> Entering function.') } let fs = require('fs') try { fs.readFile(fileName, onFileRead) - function onFileRead (err, file) { + function onFileRead(err, file) { if (CONSOLE_LOG === true) { console.log('[INFO] server -> respondWithImage -> onFileRead -> Entering function.') } try { @@ -355,7 +418,7 @@ function respondWithImage (fileName, response) { } } -function returnEmptyArray (response) { +function returnEmptyArray(response) { try { if (CONSOLE_LOG === true) { console.log('[INFO] server -> respondWithFile -> returnEmptyArray -> Entering function.') } @@ -370,21 +433,3 @@ function returnEmptyArray (response) { console.log('[ERROR] server -> returnEmptyArray -> err.message ' + err.message) } } - -function respondWithSourceCode (requestParameters, response) { - let devTeam = requestParameters[2] - let codeName = requestParameters[3] - let moduleName = requestParameters[4] - - let filePath = devTeam + '/plotters/' + codeName + '/' + moduleName - - fileCloud.getBlobToText(devTeam.toLowerCase(), filePath, null, onDataArrived) - - function onDataArrived (err, pData) { - if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - console.log('[ERROR] server -> onBrowserRequest -> respondWithSourceCode -> Could not read a file -> err.message = ' + err.message, err.stack) - pData = '' - } - respondWithContent(pData, response) - } -}