Merge pull request #1 from Superalgos/master

SYnc
This commit is contained in:
Luis Fernando authored and GitHub committed 2021-03-06 22:06:39 -03:00
commit 96f57d8555
6972 files changed
+1331035 -294283

No files matched your search

-37
View File
@@ -1,37 +0,0 @@
#PORT NUMBERS: If any of these ports are already in use by a different app, please pick a new number between 1 and 50000.
WEB_SERVER_PORT=34247
WEB_SOCKETS_SERVER_PORT=8080
# TASK MANAGER VARIABLES:
TASK_SERVER_PATH=./TaskServer
# TASK SERVER VARIABLES:
INTER_PROCESS_FILES_PATH=./Inter-Process-Files
STORAGE_PATH=./Data-Storage
PLOTTERS_PATH=./Legacy-Code
DATA_MINES_PATH=./Data-Mines
TRADING_SYSTEMS_PATH=./Trading-Systems
SUPER_SCRIPTS_PATH=./Super-Scripts
WRITE_LOGS_TO_FILES=true
BOTS_PATH=./Legacy-Code
LOG_PATH=./Log-Files
WEB_SERVER_URL=localhost
# WEB SERVER VARIABLES:
#Log options
CONSOLE_LOG=false
CONSOLE_ERROR_LOG=true
LOG_FILE_CONTENT=false
PATH_TO_CANVAS_APP=./CanvasApp
PATH_TO_FILES_COMPONENT=./Files-Component/src
PATH_TO_WEB_SERVER=./BackendServers/
APP_SCHEMA_PATH=./
WORKSPACE_PATH=./
+66
View File
@@ -0,0 +1,66 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
## Before you open an issue
There are two requirements to open an issue:
1. You must first follow the [Troubleshooting Guide](https://docs.superalgos.org/suite-how-to-troubleshoot-an-issue.html)
2. If your issue hasn't been resolved by following the Troubleshooting Guide, then follow the guide on [How to Report an Issue](https://docs.superalgos.org/suite-how-to-report-an-issue.html).
## Context
*Complete and adjust the contents leaving the information that fits your case and deleting the information that doesn't.*
**Operating System:** Windows | MacOs | Linux | Other (include the version on either case)
**Software version:** today's master branch | today's develop branch
**Workspace version:** default Workspace.json (Getting Started Guide) | Simple Workspace.json | Workspace - Binance - WHB - BBTB.json | My custom workspace
**Reproducible:** the issue may | may not be reproduced.
## Explain your issue
### 1. Explain what the problem seems to be.
Type your explanation here.
### 2. Clearly explain what you wish to accomplish.
Type your explanation here.
### 3. Explain, step by step, what you've done to achieve the goal. The Team will follow these steps to reproduce the issue, so be precise.
Type your explanation here.
### 4. Explain what is the result you expect from your actions.
Type your explanation here.
### 5. Explain what happens instead of the expected results.
Type your explanation here.
### 6. Explain what errors you have found on-screen, on the browser console application, or in the ```Log-Files``` folder.
Type your explanation here.
## Attach a video reproducing the issue
Attach video here.
## Attach relevant log files and error screenshots
Attach logs here.
## Attach you custom workspace if any
Attach custom workspace here.
+20
View File
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+5 -1
View File
@@ -1,2 +1,6 @@
Data-Storage
Log-Files
Log-Files
My-Workspaces
debug.log
*.db
+16
View File
@@ -0,0 +1,16 @@
{
"files.exclude": {
"**/Data-Storage": true,
"**/Documentation": true,
"**/Log-Files": true,
"**/node_modules": true,
"**/Deprecated-Code": true
},
"search.exclude": {
"**/Data-Storage": true,
"**/Documentation": true,
"**/Log-Files": true,
"**/Deprecated-Code": true
},
"search.maintainFileSearchCache": true
}
-6571
View File
File diff suppressed because it is too large. Load diff
-13
View File
@@ -1,13 +0,0 @@
INTER_PROCESS_FILES_PATH=../Inter-Process-Files
STORAGE_PATH=../Data-Storage
PLOTTERS_PATH=../Legacy-Code
USE_KEYVAULT=false
WRITE_LOGS_TO_FILES=true
BOTS_PATH=../Legacy-Code
LOG_PATH=../Log-Files
WEB_SOCKETS_SERVER_PORT=8080
WEB_SERVER_PORT=34247
WEB_SERVER_URL=localhost
-252
View File
@@ -1,252 +0,0 @@
let dashboard
function newAppLoader() {
const MODULE_NAME = 'App Loader'
const INFO_LOG = false
const ERROR_LOG = true
const logger = newWebDebugLog()
logger.fileName = MODULE_NAME
let thisObject = {
loadModules: loadModules
}
return thisObject
async function loadModules() {
try {
if (INFO_LOG === true) { logger.write('[INFO] loadModules -> Entering function.') }
let plotters
let modulesArray = []
plotters = defaultPlotters()
modulesArray = modulesArray.concat([
'ChartingSpace/Viewport.js',
'Globals.js',
'AppSchema.js',
'Workspace.js',
'ChartingSpace/EdgeEditor.js',
'ChartingSpace/ChartUtilities.js',
'ChartingSpace/PlottersManager.js',
'ChartingSpace/TimelineChart.js',
'ChartingSpace/TimeMachine.js',
'ChartingSpace/CoordinateSystem.js',
'DesignSpace/Workspace/Workspace.js',
'DesignSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js',
'DesignSpace/Workspace/FunctionLibraries/ChainAttachDetach.js',
'DesignSpace/Workspace/FunctionLibraries/ReferenceAttachDetach.js',
'DesignSpace/Workspace/FunctionLibraries/NodeDeleter.js',
'DesignSpace/Workspace/FunctionLibraries/ProtocolNode.js',
'DesignSpace/Workspace/FunctionLibraries/NodeCloning.js',
'DesignSpace/Workspace/FunctionLibraries/NodeChildren.js',
'DesignSpace/Workspace/FunctionLibraries/TaskFunctions.js',
'DesignSpace/Workspace/FunctionLibraries/SessionFunctions.js',
'DesignSpace/Workspace/FunctionLibraries/ShortcutKeys.js',
'DesignSpace/Workspace/FunctionLibraries/OnFocus.js',
'DesignSpace/Workspace/FunctionLibraries/SuperScripts.js',
'DesignSpace/Workspace/FunctionLibraries/CCXTFunctions.js',
'DesignSpace/Workspace/FunctionLibraries/WebhookFunctions.js',
'DesignSpace/Workspace/FunctionLibraries/DependenciesFilter.js',
'Utilities/RoundedCornersBackground.js',
'Panels/LayersPanel.js',
'Panels/UpDownButton.js',
'Panels/LeftRightButton.js',
'Panels/Layer.js',
'Panels/PlotterPanel.js',
'Panels/PanelsVisibleButton.js',
'ControlsToolBox/SidePanel.js',
'ControlsToolBox/SidePanelTab.js',
'Spaces/CockpitSpace.js',
'Spaces/TopSpace.js',
'Spaces/PanelsSpace.js',
'Spaces/ChartingSpace.js',
'Spaces/FloatingSpace.js',
'Spaces/DesignSpace.js',
'Files/SingleFile.js',
'Files/FileCloud.js',
'Files/MarketFiles.js',
'Files/DailyFiles.js',
'Files/FileCursor.js',
'Files/FileSequence.js',
'Files/FileStorage.js',
'FloatingSpace/FloatingObject.js',
'FloatingSpace/FloatingLayer.js',
'FloatingSpace/UiObjectConstructor.js',
'FloatingSpace/UiObject.js',
'FloatingSpace/UiObjectTitle.js',
'FloatingSpace/CircularMenu.js',
'FloatingSpace/CircularMenuItem.js',
'FloatingSpace/CircularProgressBar.js',
'FloatingSpace/BusyProgressBar.js',
'FloatingSpace/CodeEditor.js',
'FloatingSpace/ConfigEditor.js',
'FloatingSpace/ConditionEditor.js',
'FloatingSpace/FormulaEditor.js',
'FloatingSpace/Picker.js',
'Scales/RateScale.js',
'Scales/TimeScale.js',
'Scales/TimeFrameScale.js',
'Scales/Commons.js',
'Scales/AutoScaleButton.js',
'CockpitSpace/AssetBalances.js',
'CockpitSpace/Speedometer.js',
'CockpitSpace/FullScreen.js',
'EventsServerClient.js',
'VideoRecorder.js',
'Plotter.js',
'LegacyPlotter.js',
'PlotterPanel.js',
'ProductStorage.js',
'SplashScreen.js',
'Canvas.js',
'EventHandler.js',
'Frame.js',
'Animation.js',
'Container.js',
'Utilities.js',
'PostLoader.js'
])
modulesArray = modulesArray.concat(plotters)
let downloadedCounter = 0
let versionParam = window.canvasApp.version
if (versionParam === undefined) { versionParam = '' } else {
versionParam = '?' + versionParam
}
for (let i = 0; i < modulesArray.length; i++) {
let path = window.canvasApp.urlPrefix + modulesArray[i] + versionParam
REQUIREJS([path], onRequired)
if (INFO_LOG === true) { logger.write('[INFO] loadModules -> Module Requested.') }
if (INFO_LOG === true) { logger.write('[INFO] loadModules -> path = ' + path) }
if (INFO_LOG === true) { logger.write('[INFO] loadModules -> total requested = ' + (i + 1)) }
function onRequired(pModule) {
try {
if (INFO_LOG === true) { logger.write('[INFO] loadModules -> onRequired -> Entering function.') }
if (INFO_LOG === true) { logger.write('[INFO] loadModules -> onRequired -> Module Downloaded.') }
if (INFO_LOG === true) { logger.write('[INFO] loadModules -> onRequired -> path = ' + path) }
downloadedCounter++
if (INFO_LOG === true) { logger.write('[INFO] loadModules -> onRequired -> downloadedCounter = ' + downloadedCounter) }
if (downloadedCounter === modulesArray.length) {
if (INFO_LOG === true) { logger.write('[INFO] loadModules -> onRequired -> Starting Advanced Algos Platform.') }
setTimeout(() => {
dashboard = newDashboard()
dashboard.start()
}, 500)
}
} catch (err) {
if (ERROR_LOG === true) { logger.write('[ERROR] loadModules -> onRequired -> err = ' + err.stack) }
}
}
}
} catch (err) {
if (ERROR_LOG === true) { logger.write('[ERROR] loadModules -> err = ' + err.stack) }
}
}
function defaultPlotters() {
return [
'Plotters/Masters/Plotters-Candles-Volumes/Candles.js',
'Plotters/Masters/Plotters-Candles-Volumes/CandlePanel.js',
'Plotters/Masters/Plotters-Candles-Volumes/Volumes.js',
'Plotters/Masters/Plotters-Candles-Volumes/VolumePanel.js',
'Plotters/Masters/Plotters-Bollinger-Bands/BollingerBands.js',
'Plotters/Masters/Plotters-Bollinger-Bands/BollingerBandsPanel.js',
'Plotters/Masters/Plotters-Bollinger-Bands/PercentageBandwidth.js',
'Plotters/TradingEngines/Plotters-Trading-Simulation/TradingSimulation.js',
'Plotters/TradingEngines/Plotters-Trading-Simulation/TradingSimulationAssetBalancesPanel.js',
'Plotters/TradingEngines/Plotters-Trading-Simulation/TradingSimulationCurrentPositionPanel.js',
'Plotters/TradingEngines/Plotters-Trading-Simulation/TradingSimulationPartialResultsPanel.js',
'Plotters/TradingEngines/Plotters-Trading-Simulation/Conditions.js',
'Plotters/TradingEngines/Plotters-Trading-Simulation/Strategies.js',
'Plotters/TradingEngines/Plotters-Trading-Simulation/Trades.js',
'Plotters/TradingEngines/Plotters-Trading-Simulation/SimulationExecution.js',
'Plotters/TradingEngines/Plotters-Trading-Simulation/SimulationExecutionPanel.js'
]
}
function getPlotters(ecosystem) {
if (INFO_LOG === true) { console.log('[INFO] server -> onBrowserRequest -> onFileRead -> addPlotters -> Entering function.') }
let plotters = []
let dataMines = ecosystem.dataMines
let hosts = ecosystem.hosts
plotters = plotters.concat(addScript(dataMines))
plotters = plotters.concat(addScript(hosts))
return plotters
}
function addScript(pDataMinesOrHosts) {
if (INFO_LOG === true) { console.log('[INFO] server -> onBrowserRequest -> onFileRead -> addPlotters -> addScript -> Entering function.') }
const htmlLinePlotter = 'Plotters/@dataMine@/@repo@/@module@.js'
const htmlLinePlotterPanel = 'PlotterPanels/@dataMine@/@repo@/@module@.js'
let plotters = []
for (let i = 0; i < pDataMinesOrHosts.length; i++) {
let dataMine = pDataMinesOrHosts[i]
for (let j = 0; j < dataMine.plotters.length; j++) {
let plotter = dataMine.plotters[j]
if (plotter.modules !== undefined) {
for (let k = 0; k < plotter.modules.length; k++) {
let module = plotter.modules[k]
let htmlLineCopy = htmlLinePlotter
let stringToInsert
stringToInsert = htmlLineCopy.replace('@dataMine@', dataMine.codeName)
stringToInsert = stringToInsert.replace('@repo@', plotter.repo)
stringToInsert = stringToInsert.replace('@module@', module.moduleName)
plotters.push(stringToInsert)
if (module.panels !== undefined) {
for (let l = 0; l < module.panels.length; l++) {
let panel = module.panels[l]
let htmlLineCopy = htmlLinePlotterPanel
let stringToInsert
stringToInsert = htmlLineCopy.replace('@dataMine@', dataMine.codeName)
stringToInsert = stringToInsert.replace('@repo@', plotter.repo)
stringToInsert = stringToInsert.replace('@module@', panel.moduleName)
plotters.push(stringToInsert)
}
}
}
}
}
}
return plotters
}
}
-174
View File
@@ -1,174 +0,0 @@
/* Callbacks default responses. */
let GLOBAL = {};
GLOBAL.DEFAULT_OK_RESPONSE = {
result: "Ok",
message: "Operation Succeeded"
};
GLOBAL.DEFAULT_FAIL_RESPONSE = {
result: "Fail",
message: "Operation Failed"
};
GLOBAL.DEFAULT_RETRY_RESPONSE = {
result: "Retry",
message: "Retry Later"
};
GLOBAL.CUSTOM_OK_RESPONSE = {
result: "Ok, but check Message",
message: "Custom Message"
};
GLOBAL.CUSTOM_FAIL_RESPONSE = {
result: "Fail Because",
message: "Custom Message"
};
let browserCanvas; // This is the canvas object of the browser.
function spacePad(str, max) {
str = str.toString();
return str.length < max ? spacePad(" " + str, max) : str;
}
function loadSuperalgos() {
const MODULE_NAME = "App Pre-Loader";
const INFO_LOG = false;
const ERROR_LOG = true;
if (INFO_LOG === true) { console.log(spacePad(MODULE_NAME, 50) + " : " + "[INFO] loadSuperalgos -> Entering function."); }
/* The first thing to do here is to add the canvas where all the action is going to happen. */
let textArea = document.createElement('textarea');
textArea.id = "textArea";
textArea.spellcheck = false;
textArea.style = 'resize: none;' +
' border: none;' +
' outline: none;' +
'box-shadow: none;' +
'overflow:hidden;' +
'font-family: ' + 'Saira' + ';' +
'font-size: 12px;' +
'background-color: rgb(255, 255, 255);' +
'color:rgb(255, 255, 255);' +
'width: ' + 800 + 'px;' +
'height: ' + 600 + 'px'
let textAreaDiv = document.getElementById('textAreaDiv');
textAreaDiv.appendChild(textArea);
textAreaDiv.style = 'position:fixed; top:' + -1500 + 'px; left:' + 500 + 'px; z-index:10; '
let input = document.createElement('input');
input.id = "input";
input.spellcheck = false;
input.style = "border: none; outline: none; box-shadow: none; overflow:hidden; width: 0px; height: 0px;";
let inputDiv = document.getElementById('inputDiv');
inputDiv.appendChild(input);
let canvas = document.createElement('canvas');
canvas.id = "canvas";
canvas.width = 1400;
canvas.height = 600;
canvas.style.border = "0";
canvas.style = "position:absolute; top:0px; left:0px; z-index:1";
let canvasApp = document.getElementById('canvasApp');
canvasApp.appendChild(canvas);
browserCanvas = document.getElementById('canvas');
browserCanvas.width = window.innerWidth;
browserCanvas.height = window.innerHeight - window.canvasApp.topMargin;
browserCanvas.style.border = "none";
browserCanvas.style.top = window.canvasApp.topMargin + 'px';
loadDebugModule();
function loadDebugModule() {
try {
if (INFO_LOG === true) { console.log(spacePad(MODULE_NAME, 50) + " : " + "[INFO] loadDebugModule -> Entering function."); }
let path = window.canvasApp.urlPrefix + "WebDebugLog.js";
REQUIREJS([path], onRequired);
function onRequired(pModule) {
if (INFO_LOG === true) { console.log(spacePad(MODULE_NAME, 50) + " : " + "[INFO] " + path + " downloaded."); }
loadModules();
}
}
catch (err) {
console.log(spacePad(MODULE_NAME, 50) + " : " + "[ERROR] loadDebugModule --> " + path + " --> err = " + err.stack);
}
}
/* And Finally, we start loading all the scripts we will inmediatelly need. */
function loadModules() {
try {
if (INFO_LOG === true) { console.log(spacePad(MODULE_NAME, 50) + " : " + "[INFO] loadModules -> Entering function."); }
let path = window.canvasApp.urlPrefix + "WebServer/AppLoader.js";
REQUIREJS([path], onRequired);
function onRequired(pModule) {
if (INFO_LOG === true) { console.log(spacePad(MODULE_NAME, 50) + " : " + "[INFO] " + path + " downloaded."); }
let APP_LOADER_MODULE = newAppLoader();
APP_LOADER_MODULE.loadModules();
}
}
catch (err) {
console.log(spacePad(MODULE_NAME, 50) + " : " + "[ERROR] loadModules --> " + path + " --> err = " + err.stack);
}
}
}
function callServer(pContentToSend, pPath, callBackFunction) {
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200) {
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 })
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 809 KiB

-6
View File
@@ -1,6 +0,0 @@
function getNewPlotterPanel(pDataMineOrHost, pPlotter, pModule, pPanel) {
let functionName = pDataMineOrHost + pPlotter + pModule + pPanel;
functionName = functionName.replace(/-/g, "");
functionName = 'new' + functionName
return window[functionName]();
}
-69
View File
@@ -1,69 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Superalgos</title>
<meta name="description"
content="Crypto Trading on an Industrial Scale">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<link href="https://fonts.googleapis.com/css?family=Saira+Condensed:300,600|Saira:300,600&amp;subset=latin-ext,vietnamese"
rel="stylesheet">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css"
integrity="sha384-DNOHZ68U8hZfKXOrtjWvjxusGo9WQnrNx2sqG0tfsghAvtVlRW3tvkXWZh58N9jp" crossorigin="anonymous">
<link rel="shortcut icon" type="image/png/ico" href="Images/favicon.ico" />
<script type="text/javascript" src="WebServer/require.js"></script>
<script type="text/javascript" src="WebServer/AppPreLoader.js"></script>
<script src="externalScripts/CCapture.all.min.js"></script>
<script type="text/javascript">
function loadCanvas() {
if (window.canvasApp.visible === undefined) {
window.canvasApp = {
version: '', // This is used to avoid catching problems at the browser level.
sessionToken: '',
visible: true,
topMargin: 0,
urlPrefix: 'http://localhost:WEB_SERVER_PORT/',
graphQL: {
masterAppApiUrl: 'https://demo-api-dev.superalgos.org/graphql',
},
context: {}
};
try {
loadSuperalgos();
} catch (err) {
console.log("[ERROR] CanvasApp can not be started. Please check that WebServer is running.", err);
}
}
}
function onResize() {
try {
if (canvas === undefined) { return }
if (canvas.eventHandler === undefined) { return }
canvas.eventHandler.raiseEvent('Browser Resized')
} catch (err) {
}
}
</script>
</head>
<body id="body" onload="loadCanvas()"
style="overflow:hidden; background: url(Images/superalgos-platform.jpg); background-size: cover;"
onresize="onResize()">
<div id="masterApp"></div>
<div id="canvasApp"></div>
<div id="textAreaDiv"></div>
<div id="inputDiv" style="font-family:saira condensed;">&nbsp;</div>
</body>
</html>
-237
View File
@@ -1,237 +0,0 @@
exports.newEventsServer = function newEventsServer() {
const MODULE = "Events Server"
const LOG_INFO = false
let thisObject = {
initialize: initialize,
finalize: finalize,
run: run,
onMessage: onMessage
}
let eventHandlers = new Map()
let counter = 0
return thisObject
function finalize() {
}
function initialize() {
}
function onMessage(data, callbackFunction) {
try {
let command = JSON.parse(data)
switch (command.action) {
case "greetings": {
sendResponse(global.DEFAULT_OK_RESPONSE)
return
}
case "createEventHandler": {
let eventHandler = eventHandlers.get(command.eventHandlerName)
if (eventHandler === undefined) {
/*
We will only create event handlers which were not created before. Remember that someone trying to listen events
at an event handler that does not exist, will create that eventhandler, so it is possible that the emitter
when trying to create the event handler in fact was late and the event handler is already there if the listener
arrived here first. An event handler created with this method is not destroyed if there are no listeners or they
all leave.
*/
eventHandler = newEventHandler()
eventHandler.deleteWhenAllListenersAreGone = false
eventHandlers.set(command.eventHandlerName, eventHandler)
}
sendResponse(global.DEFAULT_OK_RESPONSE)
return
}
case "deleteEventHandler": {
let eventHandler = eventHandlers.get(command.eventHandlerName)
if (eventHandler !== undefined) {
/*
We will only delete event handlers which have noone listening, allowing a listener to continue listening even
when the event emitter is gone, asuming that it could come back at some point in time and resume emitting.
*/
if (eventHandler.listeners.length === 0) {
eventHandlers.delete(command.eventHandlerName)
} else {
eventHandler.deleteWhenAllListenersAreGone = true
}
}
sendResponse(global.DEFAULT_OK_RESPONSE)
return
}
case "listenToEvent": {
let eventHandler = eventHandlers.get(command.eventHandlerName)
if (eventHandler === undefined) {
/*
We will create event handlers which were not created before if a listener tries to listen to a handler that does not
exist before the emitter comes and create it. This is to aviod syncronization problems and also problems with emitters life
cycles with higher frecuency that the ones of listeners. Created in this way, event handlers are marked for deletion if
all listeners stop listening at one point in time.
*/
eventHandler = newEventHandler()
eventHandler.deleteWhenAllListenersAreGone = true
eventHandlers.set(command.eventHandlerName, eventHandler)
}
eventSubscriptionId = eventHandler.listenToEvent(command.eventHandlerName, command.eventType, command.callerId, handlerFunction, command.extraData)
function handlerFunction(event, extraData) {
let outputData = {
action: 'Event Raised',
eventHandlerName: command.eventHandlerName,
eventType: command.eventType,
event: event,
callerId: command.callerId,
extraData: extraData
}
callbackFunction(JSON.stringify(outputData))
}
let response = {
result: global.DEFAULT_OK_RESPONSE.result,
message: global.DEFAULT_OK_RESPONSE.message,
eventSubscriptionId: eventSubscriptionId
}
sendResponse(response)
return
}
case "stopListening": {
let eventHandler = eventHandlers.get(command.eventHandlerName)
if (eventHandler === undefined) {
/* If the event handler does not exist anymore, then there is no need to perform further actiions. */
sendResponse(global.DEFAULT_OK_RESPONSE)
return
}
eventHandler.stopListening(command.eventHandlerName, command.eventType, command.callerId, command.eventSubscriptionId)
/*
We check here if there are no more listeners and the event handler original emmiter is also gone, then we need to delete
this event handlers since chances are that is not needed anymore.
*/
if (eventHandler.listeners.length === 0 && eventHandler.deleteWhenAllListenersAreGone === true) {
eventHandlers.delete(command.eventHandlerName)
}
sendResponse(global.DEFAULT_OK_RESPONSE)
return
}
case "raiseEvent": {
let eventHandler = eventHandlers.get(command.eventHandlerName)
if (eventHandler === undefined) {
eventHandler = newEventHandler()
eventHandlers.set(command.eventHandlerName, eventHandler)
/* No matter if it is the listener or the emiter the one that acts first, if an event handler does not exist we just create it acan keep it there. */
}
//console.log("[INFO] BackendServers -> Events Server -> Raising Event " + command.eventHandlerName + " " + command.eventType)
eventHandler.raiseEvent(command.eventType, command.event)
sendResponse(global.DEFAULT_OK_RESPONSE)
return
}
}
console.log("[WARN] BackendServers -> Events Server -> onMessage -> Unknown Command Received:" + data)
function sendResponse(message) {
if (command.callerId !== undefined) {
message.callerId = command.callerId
}
message.action = 'Event Server Response'
callbackFunction(JSON.stringify(message))
}
} catch (err) {
console.log("[ERROR] BackendServers -> Events Server -> onMessage -> Bad Command Received:" + data)
console.log("[ERROR] BackendServers -> Events Server -> onMessage -> An Error Happened:" + err.stack)
}
}
function run() {
console.log('Events Server Started.')
}
function newEventHandler() {
let thisObject = {
name: undefined, // This is for debugging purposes only.
deleteWhenAllListenersAreGone: false,
listeners: [], // Here we store all the functions we will call when an event is raiseed.
listenToEvent: listenToEvent,
stopListening: stopListening,
raiseEvent: raiseEvent,
finalize: finalize
}
return thisObject
function finalize() {
thisObject.listeners = []
}
function listenToEvent(eventHandlerName, eventType, callerId, handler, extraData) {
let eventSubscriptionId = Math.trunc(Math.random() * 1000000)
/*
We can not allow to have the exact same listener more than once. In case that we find a listener trying to listen again, the first record will
be deleted and we are just going to consider the last one comming in.
*/
for (let i = 0; i < thisObject.listeners.length; i++) {
if (eventHandlerName === thisObject.listeners[i][0] && eventType === thisObject.listeners[i][1] && callerId === thisObject.listeners[i][2]) {
thisObject.listeners.splice(i, 1)
break
}
}
thisObject.listeners.push([eventHandlerName, eventType, callerId, handler, extraData, eventSubscriptionId])
return eventSubscriptionId
}
function stopListening(eventHandlerName, eventType, callerId, eventSubscriptionId) {
if (eventSubscriptionId !== undefined) {
for (let i = 0; i < thisObject.listeners.length; i++) {
if (eventSubscriptionId === thisObject.listeners[i][5]) {
thisObject.listeners.splice(i, 1)
return
}
}
}
if (eventHandlerName !== undefined && eventType !== undefined && callerId !== undefined) {
for (let i = 0; i < thisObject.listeners.length; i++) {
if (eventHandlerName === thisObject.listeners[i][0] && eventType === thisObject.listeners[i][1] && callerId === thisObject.listeners[i][2]) {
thisObject.listeners.splice(i, 1)
return
}
}
}
}
function raiseEvent(eventType, event) {
for (let i = 0; i < thisObject.listeners.length; i++) {
/* We will execute all the functions listening to this event type. */
if (thisObject.listeners[i][1] === eventType) {
let handler = thisObject.listeners[i][3]
let extraData = thisObject.listeners[i][4]
handler(event, extraData)
}
}
}
}
}
-11
View File
@@ -1,11 +0,0 @@
/* @flow */
(function () {
require('./lib/main').config(
Object.assign(
{},
require('./lib/env-options'),
require('./lib/cli-options')(process.argv)
)
)
})()
-13
View File
@@ -1,13 +0,0 @@
/* @flow */
const re = /^dotenv_config_(encoding|path|debug)=(.+)$/
module.exports = function optionMatcher (args /*: Array<string> */) {
return args.reduce(function (acc, cur) {
const matches = cur.match(re)
if (matches) {
acc[matches[1]] = matches[2]
}
return acc
}, {})
}
-18
View File
@@ -1,18 +0,0 @@
/* @flow */
// ../config.js accepts options via environment variables
const options = {}
if (process.env.DOTENV_CONFIG_ENCODING != null) {
options.encoding = process.env.DOTENV_CONFIG_ENCODING
}
if (process.env.DOTENV_CONFIG_PATH != null) {
options.path = process.env.DOTENV_CONFIG_PATH
}
if (process.env.DOTENV_CONFIG_DEBUG != null) {
options.debug = process.env.DOTENV_CONFIG_DEBUG
}
module.exports = options
-113
View File
@@ -1,113 +0,0 @@
/* @flow */
/*::
type DotenvParseOptions = {
debug?: boolean
}
// keys and values from src
type DotenvParseOutput = { [string]: string }
type DotenvConfigOptions = {
path?: string, // path to .env file
encoding?: string, // encoding of .env file
debug?: string // turn on logging for debugging purposes
}
type DotenvConfigOutput = {
parsed?: DotenvParseOutput,
error?: Error
}
*/
const fs = require('fs')
const path = require('path')
function log (message /*: string */) {
console.log(`[dotenv][DEBUG] ${message}`)
}
const NEWLINE = '\n'
const RE_INI_KEY_VAL = /^\s*([\w.-]+)\s*=\s*(.*)?\s*$/
const RE_NEWLINES = /\\n/g
const NEWLINES_MATCH = /\n|\r|\r\n/
// Parses src into an Object
function parse (src /*: string | Buffer */, options /*: ?DotenvParseOptions */) /*: DotenvParseOutput */ {
const debug = Boolean(options && options.debug)
const obj = {}
// convert Buffers before splitting into lines and processing
src.toString().split(NEWLINES_MATCH).forEach(function (line, idx) {
// matching "KEY' and 'VAL' in 'KEY=VAL'
const keyValueArr = line.match(RE_INI_KEY_VAL)
// matched?
if (keyValueArr != null) {
const key = keyValueArr[1]
// default undefined or missing values to empty string
let val = (keyValueArr[2] || '')
const end = val.length - 1
const isDoubleQuoted = val[0] === '"' && val[end] === '"'
const isSingleQuoted = val[0] === "'" && val[end] === "'"
// if single or double quoted, remove quotes
if (isSingleQuoted || isDoubleQuoted) {
val = val.substring(1, end)
// if double quoted, expand newlines
if (isDoubleQuoted) {
val = val.replace(RE_NEWLINES, NEWLINE)
}
} else {
// remove surrounding whitespace
val = val.trim()
}
obj[key] = val
} else if (debug) {
log(`did not match key and value when parsing line ${idx + 1}: ${line}`)
}
})
return obj
}
// Populates process.env from .env file
function config (options /*: ?DotenvConfigOptions */) /*: DotenvConfigOutput */ {
let dotenvPath = path.resolve(process.cwd(), '.env')
let encoding /*: string */ = 'utf8'
let debug = false
if (options) {
if (options.path != null) {
dotenvPath = options.path
}
if (options.encoding != null) {
encoding = options.encoding
}
if (options.debug != null) {
debug = true
}
}
try {
// specifying an encoding returns a string instead of a buffer
const parsed = parse(fs.readFileSync(dotenvPath, { encoding }), { debug })
Object.keys(parsed).forEach(function (key) {
if (!Object.prototype.hasOwnProperty.call(process.env, key)) {
process.env[key] = parsed[key]
} else if (debug) {
log(`"${key}" is already defined in \`process.env\` and will not be overwritten`)
}
})
return { parsed }
} catch (e) {
return { error: e }
}
}
module.exports.config = config
module.exports.parse = parse
-79
View File
@@ -1,79 +0,0 @@
{
"_from": "dotenv@^8.2.0",
"_id": "dotenv@8.2.0",
"_inBundle": false,
"_integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==",
"_location": "/dotenv",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "dotenv@^8.2.0",
"name": "dotenv",
"escapedName": "dotenv",
"rawSpec": "^8.2.0",
"saveSpec": null,
"fetchSpec": "^8.2.0"
},
"_requiredBy": [
"/"
],
"_resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
"_shasum": "97e619259ada750eea3e4ea3e26bceea5424b16a",
"_spec": "dotenv@^8.2.0",
"_where": "C:\\Users\\Luis\\source\\repos\\AAMasters\\BackendServers",
"bugs": {
"url": "https://github.com/motdotla/dotenv/issues"
},
"bundleDependencies": false,
"dependencies": {},
"deprecated": false,
"description": "Loads environment variables from .env file",
"devDependencies": {
"decache": "^4.5.1",
"dtslint": "^0.9.8",
"flow-bin": "^0.109.0",
"sinon": "^7.5.0",
"standard": "^13.1.0",
"standard-markdown": "^5.1.0",
"standard-version": "^7.0.0",
"tap": "^14.7.0"
},
"engines": {
"node": ">=8"
},
"homepage": "https://github.com/motdotla/dotenv#readme",
"keywords": [
"dotenv",
"env",
".env",
"environment",
"variables",
"config",
"settings"
],
"license": "BSD-2-Clause",
"main": "lib/main.js",
"name": "dotenv",
"repository": {
"type": "git",
"url": "git://github.com/motdotla/dotenv.git"
},
"scripts": {
"dtslint": "dtslint types",
"flow": "flow",
"lint": "standard",
"postlint": "standard-markdown",
"prerelease": "npm test",
"pretest": "npm run lint && npm run dtslint",
"release": "standard-version",
"test": "tap tests/*.js --100"
},
"standard": {
"ignore": [
"flow-typed/"
]
},
"types": "types",
"version": "8.2.0"
}
-15
View File
@@ -1,15 +0,0 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": ["es6"],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"noEmit": true,
"baseUrl": ".",
"paths": {
"dotenv": ["."]
}
}
}
-6
View File
@@ -1,6 +0,0 @@
{
"extends": "dtslint/dtslint.json",
"rules": {
"strict-export-declare-modifiers": false
}
}
-126
View File
@@ -1,126 +0,0 @@
{
"name": "backend-servers",
"version": "0.0.6",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "1.0.0",
"concat-map": "0.0.1"
}
},
"ccxt": {
"version": "1.26.45",
"resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.26.45.tgz",
"integrity": "sha512-/gmeUKUlNsroBR2/W7A3knZzCvPYzztb7VRwtWyqze7U/LZiXsXo1GBSC2goQIe2xL8FlAyk7ARjZrPdSWtExA=="
},
"child_process": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz",
"integrity": "sha1-sffn/HPSXn/R1FWtyU4UODAYK1o="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"dotenv": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"requires": {
"fs.realpath": "1.0.0",
"inflight": "1.0.6",
"inherits": "2.0.4",
"minimatch": "3.0.4",
"once": "1.4.0",
"path-is-absolute": "1.0.1"
}
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
"once": "1.4.0",
"wrappy": "1.0.2"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"is-wsl": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
"integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0="
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"brace-expansion": "1.1.11"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1.0.2"
}
},
"open": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz",
"integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==",
"requires": {
"is-wsl": "1.1.0"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"requires": {
"glob": "7.1.6"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"ws": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz",
"integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ=="
}
}
}
-17
View File
@@ -1,17 +0,0 @@
{
"name": "backend-servers",
"version": "0.0.6",
"description": "BackendServer",
"main": "server.js",
"author": {
"name": "Luis-Fernando-Molina"
},
"dependencies": {
"child_process": "^1.0.2",
"dotenv": "^8.2.0",
"ws": "^7.1.2",
"ccxt": "^1.23.67",
"open": "^6.4.0",
"rimraf": "^3.0.2"
}
}
-71
View File
@@ -1,71 +0,0 @@
process.on('uncaughtException', function (err) {
if (err.message.indexOf("EADDRINUSE") > 0) {
console.log("A Superalgos Backend Server cannot be started. Reason: the port " + port + " is already in use by another application.")
return
}
console.log('[ERROR] Backend Server -> server -> uncaughtException -> err.message = ' + err.message)
console.log('[ERROR] Backend Server -> server -> uncaughtException -> err.stack = ' + err.stack)
process.exit(1)
})
process.on('unhandledRejection', (reason, p) => {
console.log('[ERROR] Backend Server -> server -> unhandledRejection -> reason = ' + JSON.stringify(reason))
console.log('[ERROR] Backend Server -> server -> unhandledRejection -> p = ' + JSON.stringify(p))
process.exit(1)
})
/* Callbacks default responses. */
global.DEFAULT_OK_RESPONSE = {
result: "Ok",
message: "Operation Succeeded"
};
global.DEFAULT_FAIL_RESPONSE = {
result: "Fail",
message: "Operation Failed"
};
global.DEFAULT_RETRY_RESPONSE = {
result: 'Retry',
message: 'Retry Later'
}
global.CUSTOM_OK_RESPONSE = {
result: 'Ok, but check Message',
message: 'Custom Message'
}
global.CUSTOM_FAIL_RESPONSE = {
result: 'Fail Because',
message: 'Custom Message'
}
let EVENTS_SERVER = require('./eventsServer.js');
let WEB_SOCKETS_SERVER = require('./webSocketsServer.js');
let TASK_MANAGER_SERVER = require('./taskManagerServer.js');
let WEB_SERVER = require('./webServer.js');
try {
EVENTS_SERVER = EVENTS_SERVER.newEventsServer()
EVENTS_SERVER.initialize()
EVENTS_SERVER.run()
WEB_SOCKETS_SERVER = WEB_SOCKETS_SERVER.newWebSocketsServer(EVENTS_SERVER)
WEB_SOCKETS_SERVER.initialize()
WEB_SOCKETS_SERVER.run()
TASK_MANAGER_SERVER = TASK_MANAGER_SERVER.newTaskManagerServer(WEB_SOCKETS_SERVER, EVENTS_SERVER)
TASK_MANAGER_SERVER.initialize()
TASK_MANAGER_SERVER.run()
WEB_SERVER = WEB_SERVER.newWebServer(EVENTS_SERVER)
WEB_SERVER.initialize()
WEB_SERVER.run()
} catch (err) {
console.log('[ERROR] BackendServers -> Task Manager -> server -> Error = ' + err.stack)
}
-296
View File
@@ -1,296 +0,0 @@
exports.newTaskManagerServer = function newTaskManagerServer(WEB_SOCKETS_SERVER, EVENTS_SERVER) {
const MODULE = "Task Manager Server"
let thisObject = {
initialize: initialize,
finalize: finalize,
run: run
}
/*
This server creates and destroys Task Servers according to what is going on at the UI. Each of these created servers will do their own
work. The responsibility of this server is to manage those children processes in order to be in sync with what the end user want and is defining
at the user interface.
*/
const { fork } = require('child_process')
require('dotenv').config()
tasks = new Map()
return thisObject
function finalize() {
}
function initialize() {
}
function run() {
/*
Here we will create an Event Handler for this server. After that we will listen to events happening here. Elements of the UI will raise events here,
as a way to communicate what is going on with the user interacting with UI components. That is the way this server will know for example when a new
task needs to be created or destroyed.
*/
let eventsServerClient = newEventsServerClient()
eventsServerClient.createEventHandler('Task Manager')
eventsServerClient.listenToEvent('Task Manager', 'Run Task', undefined, undefined, undefined, runTask)
eventsServerClient.listenToEvent('Task Manager', 'Stop Task', undefined, undefined, undefined, stopTask)
console.log('Task Manager Server Started.')
function runTask(message) {
//console.log('[INFO] BackendServers -> Task Manager Server -> runTask -> Entering function.')
if (message.event === undefined) {
console.log('[WARN] BackendServers -> Task Manager Server -> runTask -> Message Received Without Event -> message = ' + JSON.stringify(message).substring(0, 1000))
return
}
if (message.event.taskId === undefined) {
console.log('[WARN] BackendServers -> Task Manager Server -> runTask -> Message Received Without taskId -> message = ' + JSON.stringify(message).substring(0, 1000))
return
}
if (message.event.taskDefinition === undefined) {
console.log('[WARN] BackendServers -> Task Manager Server -> runTask -> Message Received Without taskDefinition -> message = ' + JSON.stringify(message).substring(0, 1000))
return
}
if (tasks.get(message.event.taskId) !== undefined) {
let key = message.event.taskName + '-' + 'Task' + '-' + message.event.taskId
eventsServerClient.raiseEvent(key, 'Running') // Meaning Task Running
return
}
//console.log('[INFO] BackendServers -> Task Manager Server -> runTask -> Task Name = ' + message.event.taskName)
//console.log('[INFO] BackendServers -> Task Manager Server -> runTask -> Task Id = ' + message.event.taskId)
let path = process.env.TASK_SERVER_PATH + '/server.js'
/* Workarround to avoid having the same debug port at the forked process which makes it crash. */
for (let i = 0; i < process.execArgv.length; i++) {
let argument = process.execArgv[i]
if (argument.indexOf('--inspect') > -1) {
process.execArgv[i] = ''
}
}
/* Forking this process. */
let task = {
childProcess: fork(path, [message.event.taskId], { stdio: 'inherit' }),
id: message.event.taskId,
name: message.event.taskName
}
tasks.set(message.event.taskId, task)
task.childProcess.on('error', (err) => {
console.log('[ERROR] BackendServers -> Task Manager Server -> runTask -> Problem with Task Name = ' + task.name)
console.log('[ERROR] BackendServers -> Task Manager Server -> runTask -> Problem with Task Id = ' + task.id)
console.log(`[ERROR] BackendServers -> Task Manager Server -> runTask -> Task Manager exited with error ${err}`)
})
task.childProcess.on('close', (code, signal) => {
//console.log('[INFO] BackendServers -> Task Manager Server -> runTask -> Task Terminated. -> Task Name = ' + task.name)
//console.log('[INFO] BackendServers -> Task Manager Server -> runTask -> Task Terminated. -> Task Id = ' + task.id)
tasks.delete(task.id)
})
eventsServerClient.listenToEvent('Task Manager - ' + message.event.taskId, 'Nodejs Process Ready for Task', undefined, undefined, undefined, sendStartingEvent)
function sendStartingEvent() {
//console.log('[INFO] BackendServers -> Task Manager Server -> runTask -> Emitting Event -> key = ' + 'Task Server - ' + task.id)
eventsServerClient.raiseEvent('Task Server - ' + task.id, 'Run Task', message.event)
}
}
function stopTask(message) {
//console.log('[INFO] BackendServers -> Task Manager Server -> stopTask -> Entering function.')
if (message.event === undefined) {
console.log('[WARN] BackendServers -> Task Manager Server -> stopTask -> Message Received Without Event -> message = ' + JSON.stringify(message).substring(0, 1000))
return
}
if (message.event.taskId === undefined) {
console.log('[WARN] BackendServers -> Task Manager Server -> stopTask -> Message Received Without taskId -> message = ' + JSON.stringify(message).substring(0, 1000))
return
}
//console.log('[INFO] BackendServers -> Task Manager Server -> stopTask -> Task Name = ' + message.event.taskName)
//console.log('[INFO] BackendServers -> Task Manager Server -> stopTask -> Task Id = ' + message.event.taskId)
let task = tasks.get(message.event.taskId)
if (task) {
task.childProcess.send('Stop this Task');
//console.log('[INFO] BackendServers -> Task Manager Server -> stopTask -> Child Process instructed to finish.')
} else {
console.log('[WARN] BackendServers -> Task Manager Server -> stopTask -> Cannot delete Task that does not exist.')
}
}
}
function newEventsServerClient() {
let thisObject = {
initialize: initialize,
finalize: finalize,
createEventHandler: createEventHandler,
deleteEventHandler: deleteEventHandler,
listenToEvent: listenToEvent,
stopListening: stopListening,
raiseEvent: raiseEvent,
onMessage: onMessage
}
let eventListeners = new Map()
let responseWaiters = new Map()
return thisObject
function finalize() {
/* Before disconnecting we will forze all eventListeners to stop listening. */
const eventListenersArray = [...eventListeners.values()]
for (let i = 0; i < eventListenersArray.length; i++) {
let handler = eventListenersArray[i]
let eventCommand = {
action: 'stopListening',
eventHandlerName: handler.eventHandlerName,
eventType: handler.eventType,
callerId: handler.callerId
}
sendCommand(eventCommand)
}
}
function initialize() {
}
function onMessage(data) {
try {
let message = JSON.parse(data)
if (message.action === 'Event Raised') {
let key
if (message.callerId) {
key = message.eventHandlerName + '-' + message.eventType + '-' + message.callerId
} else {
key = message.eventHandlerName + '-' + message.eventType
}
let handler = eventListeners.get(key)
if (handler) {
handler.callBack(message)
} else {
console.log(key + ' not found so could not deliver event raised.')
console.log(' Message = ' + data)
}
return
}
if (message.action === 'Event Server Response') {
let handler = responseWaiters.get(message.callerId)
if (handler) {
handler(message)
}
return
}
} catch (err) {
console.log('[ERROR] BackendServers -> Task Manager Server -> onMessage -> Error Receiving Message from Events Server -> data = ' + JSON.stringify(data))
console.log('[ERROR] BackendServers -> Task Manager Server -> onMessage -> Error Receiving Message from Events Server -> error = ' + err.stack)
}
}
function sendCommand(command, responseCallBack, eventsCallBack) {
try {
if (command.action === 'listenToEvent') {
let key
if (command.callerId) {
key = command.eventHandlerName + '-' + command.eventType + '-' + command.callerId
} else {
key = command.eventHandlerName + '-' + command.eventType
}
let handler = {
eventHandlerName: command.eventHandlerName,
eventType: command.eventType,
callerId: command.callerId,
callBack: eventsCallBack
}
eventListeners.set(key, handler)
}
if (command.callerId && responseCallBack) {
responseWaiters.set(command.callerId, responseCallBack)
}
EVENTS_SERVER.onMessage(JSON.stringify(command), thisObject.onMessage)
} catch (err) {
console.log('[ERROR] BackendServers -> Task Manager Server -> sendCommand -> Error Sending Command to Events Server -> command = ' + JSON.stringify(command))
console.log('[ERROR] BackendServers -> Task Manager Server -> sendCommand -> Error Sending Command to Events Server -> error = ' + err.stack)
}
}
function createEventHandler(eventHandlerName, callerId, responseCallBack) {
let eventCommand = {
action: 'createEventHandler',
eventHandlerName: eventHandlerName,
callerId: callerId
}
sendCommand(eventCommand, responseCallBack)
}
function deleteEventHandler(eventHandlerName, callerId, responseCallBack) {
let eventCommand = {
action: 'deleteEventHandler',
eventHandlerName: eventHandlerName,
callerId: callerId
}
sendCommand(eventCommand, responseCallBack)
}
function listenToEvent(eventHandlerName, eventType, extraData, callerId, responseCallBack, eventsCallBack) {
let eventCommand = {
action: 'listenToEvent',
eventHandlerName: eventHandlerName,
eventType: eventType,
extraData: extraData,
callerId: callerId
}
sendCommand(eventCommand, responseCallBack, eventsCallBack)
}
function stopListening(eventHandlerName, eventType, eventSubscriptionId, callerId, responseCallBack) {
/* User either needs to specify a valid eventSubscriptionId OR the 3 params: eventHandlerName, eventType, callerId which were used when start listening to events. */
let eventCommand = {
action: 'stopListening',
eventHandlerName: eventHandlerName,
eventType: eventType,
eventSubscriptionId: eventSubscriptionId,
callerId: callerId
}
sendCommand(eventCommand, responseCallBack)
}
function raiseEvent(eventHandlerName, eventType, event, callerId, responseCallBack) {
let eventCommand = {
action: 'raiseEvent',
eventHandlerName: eventHandlerName,
eventType: eventType,
event: event,
callerId: callerId
}
sendCommand(eventCommand, responseCallBack)
}
}
}
-654
View File
@@ -1,654 +0,0 @@
exports.newWebServer = function newWebServer(EVENTS_SERVER) {
const MODULE = "Web Server"
let thisObject = {
initialize: initialize,
finalize: finalize,
run: run
}
require('dotenv').config()
const open = require('open')
CONSOLE_LOG = process.env.CONSOLE_LOG === 'true'
CONSOLE_ERROR_LOG = process.env.CONSOLE_ERROR_LOG === 'true'
LOG_FILE_CONTENT = process.env.LOG_FILE_CONTENT === 'true'
let port = process.env.WEB_SERVER_PORT
let http = require('http')
let isHttpServerStarted = false
let cloneExecutorChildProcess
let webhook = new Map()
return thisObject
function finalize() {
}
function initialize() {
}
function run() {
startHtttpServer()
}
function startHtttpServer() {
if (CONSOLE_LOG === true) { console.log('[INFO] webServer -> startHtttpServer -> Entering function.') }
try {
if (isHttpServerStarted === false) {
gWebServer = http.createServer(onBrowserRequest).listen(port)
isHttpServerStarted = true
open('http://localhost:' + port)
console.log('Web Server Started.')
}
} catch (err) {
console.log('[ERROR] webServer -> startHtttpServer -> Error = ' + err.stack)
}
}
function onBrowserRequest(request, response) {
if (CONSOLE_LOG === true && request.url.indexOf('NO-LOG') === -1) { console.log('[INFO] webServer -> onBrowserRequest -> request.url = ' + request.url) }
function getBody(callback) { // Gets the de body from a POST request to the web server
let body = ''
request.on('data', function (data) {
body += data
// Too much POST data
if (body.length > 1e6) {
request.connection.destroy()
}
})
request.on('end', function () {
callback(body)
})
}
let requestParameters = request.url.split('/')
if (requestParameters[1].indexOf('index.html') >= 0) {
/*
We use this to solve the problem when someone is arriving to the site with a sessionToken in the queryString. We extract here that
token, that will be sent later embedded into the HTML code, so that it can enter into the stardard circuit where any site can put
the sessionToken into their HTML code and from there the Browser app will log the user in.
*/
let queryString = requestParameters[1].split('?')
requestParameters[1] = ''
requestParameters[2] = queryString[1]
homePage()
return
}
requestParameters = request.url.split('?') // Remove version information
requestParameters = requestParameters[0].split('/')
switch (requestParameters[1]) {
case 'CCXT':
{
getBody(processRequest)
async function processRequest(body) {
try {
let params = JSON.parse(body)
const ccxt = require('ccxt')
switch (params.method) {
case 'fetchMarkets': {
const exchangeClass = ccxt[params.exchangeId]
const exchangeConstructorParams = {
'timeout': 30000,
'enableRateLimit': true,
verbose: false
}
let ccxtExchange = new exchangeClass(exchangeConstructorParams)
let ccxtMarkets = []
if (ccxtExchange.has.fetchMarkets === true) {
ccxtMarkets = await ccxtExchange.fetchMarkets()
}
respondWithContent(JSON.stringify(ccxtMarkets), response)
return
}
case 'listExchanges': {
let exchanges = []
for (let i = 0; i < ccxt.exchanges.length; i++) {
let exchangeId = ccxt.exchanges[i]
const exchangeClass = ccxt[exchangeId]
const exchangeConstructorParams = {
'timeout': 30000,
'enableRateLimit': true,
verbose: false
}
let ccxtExchange
try { ccxtExchange = new exchangeClass(exchangeConstructorParams) }
catch (err) { }
if (ccxtExchange === undefined) { continue }
if (ccxtExchange.has.fetchOHLCV === params.has.fetchOHLCV) {
if (ccxtExchange.has.fetchMarkets === params.has.fetchMarkets) {
if (ccxtExchange.timeframes['1m'] !== undefined) {
let exchange = {
name: ccxtExchange.name,
id: ccxtExchange.id
}
exchanges.push(exchange)
}
}
}
}
respondWithContent(JSON.stringify(exchanges), response)
return
}
}
let content = {
err: global.DEFAULT_FAIL_RESPONSE // method not supported
}
} catch (err) {
if (CONSOLE_LOG === true) { console.log('[INFO] webServer -> CCXT FetchMarkets -> Could not fetch markets.') }
let error = {
result: 'Fail Because',
message: err.message
}
respondWithContent(JSON.stringify(error), response)
}
}
break
}
case 'Webhook': {
switch (requestParameters[2]) { // switch by command
case 'Fetch-Messages': {
let exchange = requestParameters[3]
let market = requestParameters[4]
/* Some validations */
if (exchange === undefined) {
console.log('[WARN] webServer -> Webhook -> Fetch-Messages -> Message with no Exchange received -> messageReceived = ' + messageReceived)
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), response)
return
}
if (market === undefined) {
console.log('[WARN] webServer -> Webhook -> Fetch-Messages -> Message with no market received -> messageReceived = ' + messageReceived)
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), response)
return
}
let key = exchange + '-' + market
let webhookMessages = webhook.get(key)
if (webhookMessages === undefined) {
webhookMessages = []
}
respondWithContent(JSON.stringify(webhookMessages), response)
webhookMessages = []
webhook.set(key, webhookMessages)
break
}
case 'New-Message': {
getBody(processRequest)
function processRequest(messageReceived) {
let timestamp = (new Date()).valueOf()
let source = requestParameters[3]
let exchange = requestParameters[4]
let market = requestParameters[5]
/* Some validations */
if (source === undefined) {
console.log('[WARN] webServer -> Webhook -> New-Message -> Message with no Source received -> messageReceived = ' + messageReceived)
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), response)
return
}
if (exchange === undefined) {
console.log('[WARN] webServer -> Webhook -> New-Message -> Message with no Exchange received -> messageReceived = ' + messageReceived)
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), response)
return
}
if (market === undefined) {
console.log('[WARN] webServer -> Webhook -> New-Message -> Message with no market received -> messageReceived = ' + messageReceived)
respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), response)
return
}
let key = exchange + '-' + market
let webhookMessages = webhook.get(key)
if (webhookMessages === undefined) {
webhookMessages = []
}
webhookMessages.push([timestamp, source, messageReceived])
webhook.set(key, webhookMessages)
respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), response)
}
break
}
}
break
}
case 'ResetLogsAndData':
{
try {
let rimraf = require('rimraf')
rimraf.sync(process.env.STORAGE_PATH + '/Masters/Masters/AAJason.1.0')
rimraf.sync(process.env.LOG_PATH)
respondWithContent(JSON.stringify(global.DEFAULT_OK_RESPONSE), response)
} catch (err) {
if (CONSOLE_LOG === true) { console.log('[INFO] webServer -> ResetLogsAndData -> Could not delete Logs and Data.') }
let error = {
result: 'Fail Because',
message: err.message
}
respondWithContent(JSON.stringify(error), response)
}
break
}
case 'LegacyPlotter.js':
{
respondWithFile(process.env.PATH_TO_WEB_SERVER + 'WebServer/LegacyPlotter.js', response)
}
break
case 'PlotterPanel.js':
{
respondWithFile(process.env.PATH_TO_WEB_SERVER + 'WebServer/PlotterPanel.js', response)
}
break
case 'Images': // This means the Images folder.
{
let path = process.env.PATH_TO_WEB_SERVER + 'WebServer/Images/' + requestParameters[2]
if (requestParameters[3] !== undefined) {
path = path + '/' + requestParameters[3]
}
if (requestParameters[4] !== undefined) {
path = path + '/' + requestParameters[4]
}
if (requestParameters[5] !== undefined) {
path = path + '/' + requestParameters[5]
}
path = unescape(path)
respondWithImage(path, response)
}
break
case 'favicon.ico': // This means the Scripts folder.
{
respondWithImage(process.env.PATH_TO_WEB_SERVER + 'WebServer/Images/' + 'favicon.ico', response)
}
break
case 'CockpitSpace': // This means the CockpitSpace folder.
{
respondWithFile(process.env.PATH_TO_CANVAS_APP + '/CockpitSpace/' + requestParameters[2], response)
}
break
case 'TopSpace': // This means the TopSpace folder.
{
respondWithFile(process.env.PATH_TO_CANVAS_APP + '/TopSpace/' + requestParameters[2], response)
}
break
case 'DesignSpace': // This means the DesignSpace folder.
{
if (requestParameters[3] === undefined) {
respondWithFile(process.env.PATH_TO_CANVAS_APP + '/DesignSpace/' + requestParameters[2], response)
return
}
if (requestParameters[4] === undefined) {
respondWithFile(process.env.PATH_TO_CANVAS_APP + '/DesignSpace/' + requestParameters[2] + '/' + requestParameters[3], response)
return
}
if (requestParameters[5] === undefined) {
respondWithFile(process.env.PATH_TO_CANVAS_APP + '/DesignSpace/' + requestParameters[2] + '/' + requestParameters[3] + '/' + requestParameters[4], response)
return
}
}
break
case 'ControlsToolBox': // This means the DesignSpace folder.
{
respondWithFile(process.env.PATH_TO_CANVAS_APP + '/ControlsToolBox/' + requestParameters[2], response)
}
break
case 'Utilities': // This means the DesignSpace folder.
{
respondWithFile(process.env.PATH_TO_CANVAS_APP + '/Utilities/' + requestParameters[2], response)
}
break
case 'WebServer': // This means the WebServer folder.
{
respondWithFile(process.env.PATH_TO_WEB_SERVER + 'WebServer/' + requestParameters[2], response)
}
break
case 'externalScripts': // This means the WebServer folder.
{
respondWithFile(process.env.PATH_TO_WEB_SERVER + 'WebServer/externalScripts/' + requestParameters[2], response)
}
break
case 'Plotters': // This means the plotter folder, not to be confused with the Plotters script!
{
let dataMine = requestParameters[2]
let codeName = requestParameters[3]
let moduleName = requestParameters[4]
let filePath = process.env.PLOTTERS_PATH + '/' + dataMine + '/plotters/' + codeName + '/' + moduleName
respondWithFile(filePath, response)
}
break
case 'PlotterPanels': // This means the PlotterPanels folder, not to be confused with the Plotter Panels scripts!
{
let dataMine = requestParameters[2]
let codeName = requestParameters[3]
let moduleName = requestParameters[4]
let filePath = process.env.PLOTTERS_PATH + '/' + dataMine + '/plotters/' + codeName + '/' + moduleName
respondWithFile(filePath, response)
}
break
case 'Panels':
{
respondWithFile(process.env.PATH_TO_CANVAS_APP + '/' + requestParameters[1] + '/' + requestParameters[2], response)
}
break
case 'ChartLayers':
{
respondWithFile(process.env.PATH_TO_CANVAS_APP + '/' + requestParameters[1] + '/' + requestParameters[2], response)
}
break
case 'Spaces':
{
respondWithFile(process.env.PATH_TO_CANVAS_APP + '/' + requestParameters[1] + '/' + requestParameters[2], response)
}
break
case 'Scales':
{
respondWithFile(process.env.PATH_TO_CANVAS_APP + '/' + requestParameters[1] + '/' + requestParameters[2], response)
}
break
case 'Files':
{
respondWithFile(process.env.PATH_TO_FILES_COMPONENT + '/' + requestParameters[2], response)
}
break
case 'FloatingSpace':
{
respondWithFile(process.env.PATH_TO_CANVAS_APP + '/' + requestParameters[1] + '/' + requestParameters[2], response)
}
break
case 'ChartingSpace':
{
respondWithFile(process.env.PATH_TO_CANVAS_APP + '/' + requestParameters[1] + '/' + requestParameters[2], response)
}
break
case 'AppSchema.js':
{
let fs = require('fs')
try {
let filePath = process.env.APP_SCHEMA_PATH + 'AppSchema.json'
fs.readFile(filePath, onFileRead)
} catch (e) {
console.log('[ERROR] Error reading the App Schema.', e)
}
function onFileRead(err, appSchema) {
if (err) {
respondWithContent(undefined, response)
} else {
let responseContent = 'function getAppSchema(){ return ' + appSchema + '}'
respondWithContent(responseContent, response)
}
}
}
break
case 'Workspace.js':
{
let fs = require('fs')
try {
let filePath = process.env.WORKSPACE_PATH + 'Workspace.json'
fs.readFile(filePath, onFileRead)
} catch (e) {
console.log('[ERROR] Error reading the Workspace.', e)
}
function onFileRead(err, workspace) {
if (err) {
respondWithContent(undefined, response)
} else {
let responseContent = 'function getWorkspace(){ return ' + workspace + '}'
respondWithContent(responseContent, response)
}
}
}
break
case 'DataMines':
{
respondWithFile(process.env.DATA_MINES_PATH + '/' + requestParameters[2] + '.json', response)
}
break
case 'TradingSystems':
{
respondWithFile(process.env.TRADING_SYSTEMS_PATH + '/' + requestParameters[2] + '.json', response)
}
break
case 'SuperScripts':
{
respondWithFile(process.env.SUPER_SCRIPTS_PATH + '/' + requestParameters[2] + '.json', response)
}
break
case 'Storage':
{
respondWithFile(process.env.STORAGE_PATH + '/' + request.url.substring(9), response)
}
break
case 'GetDefinition':
{
respondWithFile(process.env.INTER_PROCESS_FILES_PATH + '/definition.json', response)
}
break
case 'SaveDefinition':
{
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.INTER_PROCESS_FILES_PATH + '/definition.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() {
if (requestParameters[1] === '') {
let fs = require('fs')
try {
let fileName = process.env.PATH_TO_WEB_SERVER + 'WebServer/index.html'
fs.readFile(fileName, onFileRead)
function onFileRead(err, file) {
if (CONSOLE_LOG === true) { console.log('[INFO] webServer -> onBrowserRequest -> onFileRead -> Entering function.') }
try {
let fileContent = file.toString()
fileContent = fileContent.replace('WEB_SERVER_PORT', process.env.WEB_SERVER_PORT)
respondWithContent(fileContent, response)
} catch (err) {
console.log('[ERROR] webServer -> onBrowserRequest -> File Not Found: ' + fileName + ' or Error = ' + err.stack)
}
}
} catch (err) {
console.log(err)
}
} else {
respondWithFile(process.env.PATH_TO_CANVAS_APP + '/' + requestParameters[1], response)
}
}
}
function respondWithFile(fileName, response) {
if (CONSOLE_LOG === true) { console.log('[INFO] webServer -> respondWithFile -> Entering function.') }
let fs = require('fs')
if (fileName.indexOf('undefined') > 0) {
console.log('[WRN] webServer -> 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] webServer -> 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] webServer -> respondWithContent -> Entering function.') }
try {
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.
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')
} catch (err) {
returnEmptyArray(response)
}
}
function respondWithImage(fileName, response) {
if (CONSOLE_LOG === true) { console.log('[INFO] webServer -> respondWithImage -> Entering function.') }
let fs = require('fs')
try {
fs.readFile(fileName, onFileRead)
function onFileRead(err, file) {
if (CONSOLE_LOG === true) { console.log('[INFO] webServer -> respondWithImage -> onFileRead -> Entering function.') }
try {
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': 'image/png' })
response.end(file, 'binary')
} catch (err) {
console.log('[ERROR] webServer -> respondWithImage -> onFileRead -> File Not Found: ' + fileName + ' or Error = ' + err.stack)
}
}
} catch (err) {
console.log('[ERROR] webServer -> respondWithImage -> err = ' + err.stack)
}
}
function returnEmptyArray(response) {
try {
if (CONSOLE_LOG === true) { console.log('[INFO] webServer -> respondWithFile -> returnEmptyArray -> Entering function.') }
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.writeHead(200, { 'Content-Type': 'text/html' })
response.write('[]')
response.end('\n')
} catch (err) {
console.log('[ERROR] webServer -> returnEmptyArray -> err.message ' + err.message)
}
}
}
-112
View File
@@ -1,112 +0,0 @@
exports.newWebSocketsServer = function newWebSocketsServer(EVENTS_SERVER) {
const MODULE = "Web Sockets Server"
const LOG_INFO = false
let thisObject = {
initialize: initialize,
finalize: finalize,
run: run
}
require('dotenv').config()
const WEB_SOCKET = require('ws')
let socketServer
let port = process.env.WEB_SOCKETS_SERVER_PORT
return thisObject
function finalize() {
}
function initialize() {
}
function run() {
setUpWebSocketServer()
}
function setUpWebSocketServer() {
try {
socketServer = new WEB_SOCKET.Server({ port: port })
socketServer.on('connection', onConnection)
function onConnection(socket) {
let lastNonce = -1
if (LOG_INFO === true) {
console.log('New Websocket Connection.')
}
socket.on('message', onMenssage)
function onMenssage(message){
try {
if (LOG_INFO === true) {
console.log('Message Received: ' + message.substring(0, 1000))
}
let messageArray = message.split('|*|')
let origin = messageArray[0]
let nonce = messageArray[1]
let messageToEventServer = messageArray[2]
if (origin === 'Web Browser') {
if (isNaN(nonce) || nonce === "") {
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Nonce is not a Number. message = ' + message.substring(0, 1000))
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Nonce is not a Number. nonce = ' + nonce)
return
}
if (nonce === "1") { // this happens once the browser is restarted, and the server is running since a previous session.
lastNonce = 0
}
if (Number(nonce) < Number(lastNonce)) {
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Nonce received is less than Last Nonce. message = ' + message.substring(0, 1000))
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Nonce received is less than Last Nonce. nonce = ' + nonce)
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Nonce received is less than Last Nonce. lastNonce = ' + lastNonce)
return
}
lastNonce = nonce
try {
let jsonCheck = JSON.parse(messageToEventServer)
} catch (err) {
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Message received from the browser is not a valid JSON. message = ' + message.substring(0, 1000))
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Message received from the browser is not a valid JSON. messageToEventServer = ' + messageToEventServer)
return
}
let acknowledgeMessage = {
action: 'Acknowledge',
nonce: nonce
}
socket.send(JSON.stringify(acknowledgeMessage))
}
EVENTS_SERVER.onMessage(messageToEventServer, onResponse)
function onResponse(message) {
socket.send(message)
}
} catch (err) {
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> Nonce received is less than Last Nonce. err = ' + err.stack)
}
}
}
console.log('Web Sockets Server Started.')
} catch (err) {
console.log('[ERROR] BackendServers -> Web Sockets Server -> run -> setUpWebSocketServer -> err.message = ' + err.message.substring(0, 1000))
}
}
}
+3 -19
View File
@@ -1,23 +1,7 @@
# Contributing
We are thrilled you are interested in contributing to this project. Your help may be essential to the project's success and we want you in!
We are thrilled you are interested in contributing to Superalgos. Your help may be essential to the project's success and we want you in!
Superalgos is a collective project, currently at a very early stage. We not only welcome contributions but may even choose to incentivize relevant contributions via the project's native crypto token, to be deployed in the near future.
[There is something you may do](https://docs.superalgos.org/contributing-to-superalgos.html) to help the project grow regardless of what your skill set may be.
Contributions are deemed _voluntary work_, irrespective of the incentives that may be in place, and are subject to the conditions described in the software [LICENSE](LICENSE).
## Getting Started
First step is to fork this repository and start using the app. The repository includes all source code which constitutes your development environment. The app runs uncompilled on the actual code.
* The priority at this moment is the stabilization of existing functionality. Your first contribution will be using, learning, and testing the app, and reporting any bugs you may find.
* You may debug and remove bugs yourself, and submit pull requests.
* Another top priority is building a robust base of indicators and technical studies. This is done from the UI, using the functionality managed by data mines.
As you engage with other developers and the Core Team, we will get to know you and develop a relationship, so that you may later participate in core development tasks.
Please join the [Superalgos Develop](https://t.me/superalgosdevelop) Telegram group, let us know about your progress and ask any questions you may have. Feel free to let us know about yourself and your personal interests.
Thank you!
-174
View File
@@ -1,174 +0,0 @@
function newAnimation () {
const MODULE_NAME = 'Animation'
const ERROR_LOG = true
const logger = newWebDebugLog()
logger.fileName = MODULE_NAME
/*
Essentially, what the animation object does, is to call several functions in order to draw the content of each frame.
To do that, it has an array of functions that need to be called, and it just goes one by one through them. His parent object
is responsible for providing more functions to call, or removing functions from its list when they are not longer needed.
*/
let animationLoopHandle // This is the handle to the animation loop. With this handle we can cancel the loop, for instance.
let callBackFunctions = new Map()
let thisObject = {
start: start,
stop: stop,
addCallBackFunction: addCallBackFunction,
removeCallBackFunction: removeCallBackFunction,
initialize: initialize,
finalize: finalize
}
let totalConsumption = 0
let totalCounter = 0
let pointerIcon
let videoRecorder
return thisObject
function finalize () {
thisObject.stop()
pointerIcon = undefined
videoRecorder = undefined
}
function initialize () {
videoRecorder = newVideoRecorder()
}
function start () {
animationLoop() // Inside this function the animation process is started, and at the same time it creates a loop.
}
function stop () {
window.cancelAnimationFrame(animationLoopHandle)
}
function addCallBackFunction (key, callBack) {
callBackFunctions.set(key, callBack)
}
function removeCallBackFunction (key) {
callBackFunctions.delete(key)
}
function animationLoop () {
try {
if (window.canvasApp.visible === true) {
/* We set the canvas to its normal width and height */
// browserCanvas.width = window.innerWidth
// browserCanvas.height = window.innerHeight - CURRENT_TOP_MARGIN
/* First thing is to clear the actual canvas */
clearBrowserCanvas()
/* We loop through the callback functions collections and execute them all. */
let performanceMap = new Map()
let totalTimeConsumed = 0
let totalElements = 0
let chanceToExecute
let randomNumber
let mustExecute
// console.clear()
let row = 0
for (const [key, callBackFunction] of callBackFunctions.entries()) {
row++
switch (key) {
case 'Floating Space Physics':
chanceToExecute = 50
randomNumber = Math.random() * 100 * chanceToExecute
if (randomNumber > 100 - chanceToExecute) { mustExecute = true } else { mustExecute = false }
break
default: {
mustExecute = true
}
}
let timeConsumed = 0
if (mustExecute === true) {
let t0 = performance.now()
callBackFunction()
let t1 = performance.now()
timeConsumed = t1 - t0
if (key === 'Charting Space Draw') {
if (Math.random() * 100 > 99) {
totalConsumption = 0
totalCounter = 0
}
totalConsumption = totalConsumption + timeConsumed
totalCounter = totalCounter + 1
}
performanceMap.set(key, timeConsumed)
totalTimeConsumed = totalTimeConsumed + timeConsumed
totalElements++
}
}
/* Frame per Seconds */
ANIMATION_FRAME_PER_SECONDS = Math.trunc(1000 / totalTimeConsumed)
/* Performance Check */
if (SHOW_ANIMATION_PERFORMACE === true) {
row = 0
for (const [key, timeConsumed] of performanceMap.entries()) {
row++
labelToPrint = key + ' ' + timeConsumed.toFixed(4)
printLabel(labelToPrint, 10, 100 + row * 30, 1, 20, UI_COLOR.RED)
let percentage = timeConsumed * 100 / totalTimeConsumed
labelToPrint = key + ' ' + percentage.toFixed(1) + '%'
printLabel(labelToPrint, 300, 100 + row * 30, 1, 20, UI_COLOR.RED)
}
/* Other Variables */
row++
printLabel(DEBUG.variable1, 300, 100 + row * 30, 1, 20, UI_COLOR.RED)
row++
printLabel(DEBUG.variable2, 300, 100 + row * 30, 1, 20, UI_COLOR.RED)
row++
printLabel(DEBUG.variable3, 300, 100 + row * 30, 1, 20, UI_COLOR.RED)
row++
printLabel(DEBUG.variable4, 300, 100 + row * 30, 1, 20, UI_COLOR.RED)
row++
printLabel('Animation Frame Per Seconds: ' + ANIMATION_FRAME_PER_SECONDS, 300, 100 + row * 30, 1, 20, UI_COLOR.TITANIUM_YELLOW)
}
} else {
browserCanvas.width = 1
browserCanvas.height = 1
}
/* Media Recording */
videoRecorder.physics()
if (areWeRecording === true) {
videoRecorder.recordCanvas()
}
/* We request the next frame to be drawn, and stablishing a loop */
/* Use this code for full animation speed. */
animationLoopHandle = window.requestAnimationFrame(animationLoop)
/* Use this code for max 10 frames per second animation speed, if the app is consumming too much of your CPU. */
/*
setTimeout(nextLoop, 100)
function nextLoop () {
animationLoopHandle = window.requestAnimationFrame(animationLoop)
}
*/
} catch (err) {
if (ERROR_LOG === true) { logger.write('[ERROR] animationLoop -> err = ' + err.stack) }
}
}
function clearBrowserCanvas () {
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
browserCanvasContext.clearRect(0, 0, browserCanvas.width, browserCanvas.height)
}
}
-1081
View File
File diff suppressed because it is too large. Load diff
-139
View File
@@ -1,139 +0,0 @@
function getSideDays (timeFrame) {
let daysOnSides
if (timeFrame < _1_HOUR_IN_MILISECONDS) {
daysOnSides = 1
}
if (timeFrame === _1_HOUR_IN_MILISECONDS) {
daysOnSides = 9
}
if (timeFrame === _2_HOURS_IN_MILISECONDS) {
daysOnSides = 10
}
if (timeFrame === _3_HOURS_IN_MILISECONDS) {
daysOnSides = 12
}
if (timeFrame === _4_HOURS_IN_MILISECONDS) {
daysOnSides = 20
}
if (timeFrame === _6_HOURS_IN_MILISECONDS) {
daysOnSides = 35
}
if (timeFrame === _8_HOURS_IN_MILISECONDS) {
daysOnSides = 44
}
if (timeFrame === _12_HOURS_IN_MILISECONDS) {
daysOnSides = 56
}
if (timeFrame === ONE_DAY_IN_MILISECONDS) {
daysOnSides = 154
}
return daysOnSides
}
function getCondenseFactor (timeFrame) {
switch (timeFrame) {
case _1_MINUTE_IN_MILISECONDS: return 1
case _5_MINUTES_IN_MILISECONDS: return 5
case _10_MINUTES_IN_MILISECONDS: return 10
case _30_MINUTES_IN_MILISECONDS: return 50
case _1_HOUR_IN_MILISECONDS: return 100
}
}
function getTransparenceFactor (timeFrame) {
switch (timeFrame) {
case _1_MINUTE_IN_MILISECONDS: return '0.12'
case _5_MINUTES_IN_MILISECONDS: return '0.10'
case _10_MINUTES_IN_MILISECONDS: return '0.08'
case _30_MINUTES_IN_MILISECONDS: return '0.06'
case _1_HOUR_IN_MILISECONDS: return '0.04'
}
}
function recalculatePeriod (zoomLevel) {
// console.log('NEW ZOOM LEVEL', zoomLevel)
if (zoomLevel > 400) {
return _1_MINUTE_IN_MILISECONDS
}
if (zoomLevel > 360) {
return _2_MINUTES_IN_MILISECONDS
}
if (zoomLevel > 330) {
return _3_MINUTES_IN_MILISECONDS
}
if (zoomLevel > 300) {
return _4_MINUTES_IN_MILISECONDS
}
if (zoomLevel > 270) {
return _5_MINUTES_IN_MILISECONDS
}
if (zoomLevel > 250) {
return _10_MINUTES_IN_MILISECONDS
}
if (zoomLevel > 230) {
return _15_MINUTES_IN_MILISECONDS
}
if (zoomLevel > 210) {
return _20_MINUTES_IN_MILISECONDS
}
if (zoomLevel > 190) {
return _30_MINUTES_IN_MILISECONDS
}
if (zoomLevel > 170) {
return _40_MINUTES_IN_MILISECONDS
}
if (zoomLevel > 150) {
return _45_MINUTES_IN_MILISECONDS
}
if (zoomLevel > 130) {
return _1_HOUR_IN_MILISECONDS
}
if (zoomLevel > 110) {
return _2_HOURS_IN_MILISECONDS
}
if (zoomLevel > 80) {
return _3_HOURS_IN_MILISECONDS
}
if (zoomLevel > 50) {
return _4_HOURS_IN_MILISECONDS
}
if (zoomLevel > 35) {
return _6_HOURS_IN_MILISECONDS
}
if (zoomLevel > 20) {
return _8_HOURS_IN_MILISECONDS
}
if (zoomLevel > 10) {
return _12_HOURS_IN_MILISECONDS
}
return ONE_DAY_IN_MILISECONDS
}
-371
View File
@@ -1,371 +0,0 @@
/*
This Object object is responsible for defining the coordinate system in a TimeLine.
The scale on the X axis depends on the time.
The scale on the Y axis depends on the data that wants to be plotted. Usually we need the Max amount on that data to generate a proper scale.
*/
function newCoordinateSystem () {
let thisObject = {
min: undefined,
max: undefined,
parentMin: undefined,
parentMax: undefined,
childrenMin: undefined,
childrenMax: undefined,
maxHeight: undefined,
maxWidth: undefined,
scale: undefined,
eventHandler: undefined,
autoMinXScale: true,
autoMaxXScale: true,
autoMinYScale: true,
autoMaxYScale: true,
HORIZONTAL_MARGIN_FACTOR: 0.80,
VERTICAL_MARGIN_FACTOR: 0.90,
HORIZONTAL_MARGIN_INVERSE_FACTOR: 0.20,
VERTICAL_MARGIN_INVERSE_FACTOR: 0.10,
physics: physics,
reportParentXValue: reportParentXValue,
reportParentYValue: reportParentYValue,
reportXValue: reportXValue,
reportYValue: reportYValue,
zoomX: zoomX,
zoomY: zoomY,
recalculateScale: recalculateScale,
transformThisPoint: transformThisPoint,
transformThisPoint2: transformThisPoint2,
unInverseTransform: unInverseTransform,
inverseTransformUncappedY: inverseTransformUncappedY,
initializeX: initializeX,
initializeY: initializeY,
initialize: initialize,
finalize: finalize
}
thisObject.min = {
x: 0,
y: 0
}
thisObject.max = {
x: 0,
y: 0
}
thisObject.parentMin = {
x: 0,
y: 0
}
thisObject.parentMax = {
x: 0,
y: 0
}
thisObject.childrenMin = {
x: 0,
y: 0
}
thisObject.childrenMax = {
x: 0,
y: 0
}
thisObject.scale = {
x: 0,
y: 0
}
thisObject.eventHandler = newEventHandler()
thisObject.eventHandler.name = 'Coordinate System'
let newXMax = -VERY_LARGE_NUMBER
let newXMin = VERY_LARGE_NUMBER
let newYMax = -VERY_LARGE_NUMBER
let newYMin = VERY_LARGE_NUMBER
let parentMinChanged = false
let parentMaxChanged = false
return thisObject
function finalize () {
thisObject.eventHandler.finalize()
thisObject.eventHandler = undefined
}
function initialize (minValue, maxValue, pMaxWidth, pMaxHeight) {
/* Defines the min and max value of rate that we are going to transport to the available screen at the center position. */
thisObject.min.x = minValue.x
thisObject.max.x = maxValue.x
thisObject.min.y = minValue.y
thisObject.max.y = maxValue.y
thisObject.maxWidth = pMaxWidth
thisObject.maxHeight = pMaxHeight
recalculateScale()
}
function reportXValue (value) {
if (thisObject.autoMinXScale === true) {
if (value < newXMin && value !== 0) {
newXMin = value
}
}
if (thisObject.autoMaxXScale === true) {
if (value > newXMax && value !== 0) {
newXMax = value
}
}
}
function reportYValue (value) {
if (thisObject.autoMinYScale === true) {
if (value < newYMin) {
newYMin = value
}
}
if (thisObject.autoMaxYScale === true) {
if (value > newYMax) {
newYMax = value
}
}
}
function reportParentXValue (min, max) {
if (thisObject.autoMinXScale === true) {
if (thisObject.parentMin.x !== min) {
thisObject.parentMin.x = min
}
}
if (thisObject.autoMaxXScale === true) {
if (thisObject.parentMax.x !== max) {
thisObject.parentMax.x = max
}
}
}
function reportParentYValue (min, max) {
if (thisObject.autoMinYScale === true) {
if (thisObject.parentMin.y !== min) {
thisObject.parentMin.y = min
}
}
if (thisObject.autoMaxYScale === true) {
if (thisObject.parentMax.y !== max) {
thisObject.parentMax.y = max
}
}
}
function physics () {
let mustRecalculate = false
if ((thisObject.autoMinXScale === true || thisObject.autoMaxXScale === true)) {
if (thisObject.autoMaxXScale === true && thisObject.childrenMax.x !== newXMax && newXMax !== -VERY_LARGE_NUMBER) {
thisObject.childrenMax.x = newXMax
}
if (thisObject.autoMaxXScale === true) {
newXMax = -VERY_LARGE_NUMBER
}
if (thisObject.autoMinXScale === true && thisObject.childrenMin.x !== newXMin && newXMin !== VERY_LARGE_NUMBER) {
thisObject.childrenMin.x = newXMin
newXMin = VERY_LARGE_NUMBER
}
if (thisObject.autoMinXScale === true) {
newXMin = VERY_LARGE_NUMBER
}
}
if ((thisObject.autoMinYScale === true || thisObject.autoMaxYScale === true)) {
if (thisObject.autoMaxYScale === true && thisObject.childrenMax.y !== newYMax && newYMax !== -VERY_LARGE_NUMBER) {
thisObject.childrenMax.y = newYMax
}
if (thisObject.autoMaxYScale === true) {
newYMax = -VERY_LARGE_NUMBER
}
if (thisObject.autoMinYScale === true && thisObject.childrenMin.y !== newYMin && newYMin !== VERY_LARGE_NUMBER) {
thisObject.childrenMin.y = newYMin
newYMin = VERY_LARGE_NUMBER
}
if (thisObject.autoMinYScale === true) {
newYMin = VERY_LARGE_NUMBER
}
}
/* Here we will see if any of the children or parent values modify the current status quo */
/* Min */
let minX = Math.min(thisObject.childrenMin.x, thisObject.parentMin.x)
let minY = Math.min(thisObject.childrenMin.y, thisObject.parentMin.y)
let maxX = Math.max(thisObject.childrenMax.x, thisObject.parentMax.x)
let maxY = Math.max(thisObject.childrenMax.y, thisObject.parentMax.y)
if (thisObject.parentMin.x === 0) {
minX = thisObject.childrenMin.x
}
if (thisObject.parentMin.y === 0) {
minY = thisObject.childrenMin.y
}
if (thisObject.parentMax.x === 0) {
maxX = thisObject.childrenMax.x
}
if (thisObject.parentMax.y === 0) {
maxY = thisObject.childrenMax.y
}
if (minX !== 0 && thisObject.min.x !== minX && thisObject.autoMinXScale === true) {
thisObject.min.x = minX
mustRecalculate = true
}
if (minY !== 0 && thisObject.min.y !== minY && thisObject.autoMinYScale === true) {
thisObject.min.y = minY
mustRecalculate = true
}
if (maxX !== 0 && thisObject.max.x !== maxX && thisObject.autoMaxXScale === true) {
thisObject.max.x = maxX
mustRecalculate = true
}
if (maxY !== 0 && thisObject.max.y !== maxY && thisObject.autoMaxYScale === true) {
thisObject.max.y = maxY
mustRecalculate = true
}
if (mustRecalculate === true) {
recalculateScale()
}
}
function recalculateScale (event) {
thisObject.scale.x = thisObject.maxWidth * thisObject.HORIZONTAL_MARGIN_FACTOR / (thisObject.max.x - thisObject.min.x)
thisObject.scale.y = thisObject.maxHeight * thisObject.VERTICAL_MARGIN_FACTOR / (thisObject.max.y - thisObject.min.y)
thisObject.eventHandler.raiseEvent('Scale Changed', event)
}
function zoomX (factor, mousePosition, container) {
let mouseAtCointainer = unTransformThisPoint(mousePosition, container)
let leftDistance = mouseAtCointainer.x
let rightDistance = container.frame.width - mouseAtCointainer.x
let diff = thisObject.max.x - thisObject.min.x
let min = thisObject.min.x + diff * factor * leftDistance / (container.frame.width / 2)
let max = thisObject.max.x - diff * factor * rightDistance / (container.frame.width / 2)
if (min < max) {
let mustRecalculate = false
if (thisObject.autoMinXScale === false) {
thisObject.min.x = min
mustRecalculate = true
}
if (thisObject.autoMaxXScale === false) {
thisObject.max.x = max
mustRecalculate = true
}
if (mustRecalculate === true) {
thisObject.recalculateScale()
}
}
}
function zoomY (factor, mousePosition, container) {
let mouseAtCointainer = unTransformThisPoint(mousePosition, container)
let topDistance = mouseAtCointainer.y
let bottomDistance = container.frame.height - mouseAtCointainer.y
let diff = thisObject.max.y - thisObject.min.y
let min = thisObject.min.y + diff * factor * bottomDistance / (container.frame.height / 2)
let max = thisObject.max.y - diff * factor * topDistance / (container.frame.height / 2)
if (min < max) {
let mustRecalculate = false
if (thisObject.autoMinYScale === false) {
thisObject.min.y = min
mustRecalculate = true
}
if (thisObject.autoMaxYScale === false) {
thisObject.max.y = max
mustRecalculate = true
}
if (mustRecalculate === true) {
thisObject.recalculateScale()
}
}
}
function initializeX (minValue, maxValue, maxWidth) {
thisObject.min.x = minValue.x // * 0.999; // 0.1% less
thisObject.max.x = maxValue.x // * 1.001; // 0.1% more
thisObject.scale.x = thisObject.maxWidth / (thisObject.max.x - thisObject.min.x)
}
function initializeY (minValue, maxValue, pMaxHeight) {
thisObject.min.y = minValue.y // * 0.999; // 0.1% less
thisObject.max.y = maxValue.y // * 1.001; // 0.1% more
thisObject.scale.y = pMaxHeight / (thisObject.max.y - thisObject.min.y)
thisObject.maxHeight = pMaxHeight
}
function transformThisPoint (point) {
/*
This is the straigh fordward transformation this object provides. The input is a point on the data set that wants to be plotted in a timeline.
The x value of the point must be a datetime.valueOf() and is going to be transformed into an x value on the coordinate system of the timeline.
The y value should be a value in the dataset at that moment in time. Depending on how this coordinate system was initialized then are the
possible values y can have. For sure it must be in the range between the min and max y declared at initialization. The y value has a special
treatment since the browser canvas object used, has a zero y value at the top, while the timeline we use has a zero y value at the botton,
for that reason y is flipped.
Besides this, what we do is to multiply by the scale, which in turn is calculated at initialization time depending on the values provided.
*/
point = {
x: (point.x - thisObject.min.x) * thisObject.scale.x + thisObject.maxWidth * thisObject.HORIZONTAL_MARGIN_INVERSE_FACTOR / 2,
y: thisObject.maxHeight - (point.y - thisObject.min.y) * thisObject.scale.y - thisObject.maxHeight * thisObject.VERTICAL_MARGIN_INVERSE_FACTOR / 2
}
return point
}
function transformThisPoint2 (point) {
point = {
x: (point.x - thisObject.min.x) * thisObject.scale.x + thisObject.maxWidth * thisObject.HORIZONTAL_MARGIN_INVERSE_FACTOR / 2,
y: (thisObject.maxHeight - point.y - thisObject.min.y) * thisObject.scale.y - thisObject.maxHeight * thisObject.VERTICAL_MARGIN_INVERSE_FACTOR / 2
}
return point
}
function unInverseTransform (point, inverseY) {
point = {
x: ((point.x - thisObject.maxWidth * thisObject.HORIZONTAL_MARGIN_INVERSE_FACTOR / 2) / thisObject.scale.x) + thisObject.min.x,
y: (inverseY * thisObject.VERTICAL_MARGIN_FACTOR - point.y + thisObject.maxHeight * thisObject.VERTICAL_MARGIN_INVERSE_FACTOR / 2) / thisObject.scale.y + thisObject.min.y
}
return point
}
function inverseTransformUncappedY (point, inverseY) {
point = {
x: (point.x - thisObject.min.x) * thisObject.scale.x + thisObject.maxWidth * thisObject.HORIZONTAL_MARGIN_INVERSE_FACTOR / 2,
y: (inverseY * thisObject.VERTICAL_MARGIN_FACTOR - point.y) * thisObject.scale.y - thisObject.maxHeight * thisObject.VERTICAL_MARGIN_INVERSE_FACTOR / 2
}
return point
}
}
-716
View File
@@ -1,716 +0,0 @@
function newEdgeEditor () {
const MODULE_NAME = 'Edge Editor'
let thisObject = {
container: undefined,
fitFunction: undefined,
isVisible: true,
isMouseOver: undefined,
resetAspectRatio: resetAspectRatio,
onKeyPressed: onKeyPressed,
physics: physics,
drawForeground: drawForeground,
getContainer: getContainer,
initialize: initialize,
finalize: finalize
}
const EDGE_SIZE = 6
thisObject.container = newContainer()
thisObject.container.initialize(MODULE_NAME)
thisObject.container.isDraggeable = true
thisObject.container.isClickeable = false
thisObject.container.isWheelable = false
thisObject.container.detectMouseOver = true
let whatHappened
let whereIsMouseOver = 'outside'
let coordinateSystem
let coordinateSystemWhenDragStarted
let onMouseOverEventSubscriptionId
let onMouseNotOverEventSubscriptionId
let onDragStartedEventSubscriptionId
let mouse = {
position: {
x: 0,
y: 0
}
}
mouseWhenDragStarted = {
position: {
x: 0,
y: 0
}
}
parentFrameWhenDragStarted = {
position: {
x: 0,
y: 0
},
width: 0,
height: 0
}
let doubleClickCounter = 0
return thisObject
function finalize () {
thisObject.container.eventHandler.stopListening(onMouseOverEventSubscriptionId)
thisObject.container.eventHandler.stopListening(onMouseNotOverEventSubscriptionId)
thisObject.container.eventHandler.stopListening(onDragStartedEventSubscriptionId)
thisObject.container.finalize()
thisObject.container = undefined
thisObject.fitFunction = undefined
mouse = undefined
mouseWhenDragStarted = undefined
parentFrameWhenDragStarted = undefined
coordinateSystem = undefined
if (coordinateSystemWhenDragStarted !== undefined) {
coordinateSystemWhenDragStarted.finalize()
}
coordinateSystemWhenDragStarted = undefined
}
function initialize (pCoordinateSystem) {
coordinateSystem = pCoordinateSystem
onMouseOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
onMouseNotOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
onDragStartedEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onDragStarted', onDragStarted)
}
function onMouseOver (event) {
thisObject.isMouseOver = true
mouse = {
position: {
x: event.x,
y: event.y
}
}
}
function onMouseNotOver () {
thisObject.isMouseOver = false
}
function resetAspectRatio () {
/* Resize the Time Machine to match the current screen aspect ration */
thisObject.container.parentContainer.frame.width = browserCanvas.width / TIME_MACHINE_WIDTH
thisObject.container.parentContainer.frame.height = (COCKPIT_SPACE_POSITION - TOP_SPACE_HEIGHT) / TIME_MACHINE_HEIGHT
coordinateSystem.maxHeight = thisObject.container.parentContainer.frame.height
coordinateSystem.maxWidth = thisObject.container.parentContainer.frame.width
coordinateSystem.recalculateScale()
thisObject.container.parentContainer.eventHandler.raiseEvent('Dimmensions Changed', event)
}
function onDoubleClick (event) {
doubleClickCounter = 0
if (canvas.chartingSpace.viewport.zoomLevel === DOUBLE_CLICK_ZOOM_OUT_LEVEL) {
canvas.chartingSpace.viewport.displaceToContainer(thisObject.container.parentContainer)
canvas.chartingSpace.viewport.zoomAtCenter(DOUBLE_CLICK_ZOOM_IN_LEVEL)
return
}
if (canvas.chartingSpace.viewport.zoomLevel === DOUBLE_CLICK_ZOOM_IN_LEVEL) {
canvas.chartingSpace.viewport.zoomAtCenter(DOUBLE_CLICK_ZOOM_IN_IN_LEVEL)
return
}
}
function onDragStarted (event) {
if (event.buttons === 1) {
if (doubleClickCounter > 0) {
onDoubleClick(event)
return
} else {
doubleClickCounter = 50
}
}
mouseWhenDragStarted = {
position: {
x: event.x,
y: event.y
}
}
parentFrameWhenDragStarted = {
position: {
x: thisObject.container.parentContainer.frame.position.x,
y: thisObject.container.parentContainer.frame.position.y
},
width: thisObject.container.parentContainer.frame.width,
height: thisObject.container.parentContainer.frame.height
}
coordinateSystemWhenDragStarted = newCoordinateSystem()
let minValue = {
x: coordinateSystem.min.x,
y: coordinateSystem.min.y
}
let maxValue = {
x: coordinateSystem.max.x,
y: coordinateSystem.max.y
}
coordinateSystemWhenDragStarted.initialize(minValue, maxValue, coordinateSystem.maxWidth, coordinateSystem.maxHeight)
switch (event.buttons) {
case 1: {
whatHappened = 'left mouse button'
if (event.shiftKey === true) {
whatHappened = 'left mouse button + SHIFT'
}
break
}
case 2: {
whatHappened = 'right mouse button' // this will never happen as of today
break
}
}
}
function onKeyPressed (event) {
const STEP = 10
if (event.shiftKey === false && event.ctrlKey === false && event.code === 'ArrowLeft') {
onDragStarted(event)
thisObject.container.frame.position.x = thisObject.container.frame.position.x + STEP
whatHappened = 'left or right arrow key pressed'
return
}
if (event.shiftKey === false && event.ctrlKey === false && event.code === 'ArrowRight') {
onDragStarted(event)
thisObject.container.frame.position.x = thisObject.container.frame.position.x - STEP
whatHappened = 'left or right arrow key pressed'
return
}
if (event.shiftKey === false && event.ctrlKey === false && event.code === 'ArrowUp') {
onDragStarted(event)
thisObject.container.frame.position.y = thisObject.container.frame.position.y + STEP
whatHappened = 'up or down arrow key pressed'
return
}
if (event.shiftKey === false && event.ctrlKey === false && event.code === 'ArrowDown') {
onDragStarted(event)
thisObject.container.frame.position.y = thisObject.container.frame.position.y - STEP
whatHappened = 'up or down arrow key pressed'
return
}
if (event.shiftKey === true && (event.ctrlKey === true || event.metaKey === true) && (event.key === 'A' || event.key === 'a')) {
resetAspectRatio()
return
}
}
function getContainer (event, purpose) {
if (thisObject.container.frame.isThisPointHere(event, undefined, undefined, -EDGE_SIZE) === true && event.buttons !== 2) {
let point = {
x: event.x,
y: event.y
}
point = unTransformThisPoint(point, thisObject.container)
if (point.x <= 0) {
whereIsMouseOver = 'left'
return thisObject.container
}
if (point.x >= thisObject.container.frame.width) {
whereIsMouseOver = 'right'
return thisObject.container
}
if (point.y <= 0) {
whereIsMouseOver = 'top'
return thisObject.container
}
if (point.y >= thisObject.container.frame.height) {
whereIsMouseOver = 'bottom'
return thisObject.container
}
whereIsMouseOver = 'center'
switch (purpose) {
case GET_CONTAINER_PURPOSE.MOUSE_OVER:
return // We will let the Time Machine to handle this situation.
break
case GET_CONTAINER_PURPOSE.DRAGGING:
return thisObject.container
break
}
}
}
function physics () {
draggingPhysics()
doubleClickPhysics()
}
function doubleClickPhysics () {
doubleClickCounter--
if (doubleClickCounter < 0) {
doubleClickCounter = 0
}
}
function draggingPhysics () {
if (coordinateSystemWhenDragStarted === undefined) { return }
if (thisObject.container.frame.position.x === 0 && thisObject.container.frame.position.y === 0) { return }
let mouseNoZoom = canvas.chartingSpace.viewport.unTransformThisPoint(mouse.position)
let mouseWhenDragStartedNoZoom = canvas.chartingSpace.viewport.unTransformThisPoint(mouseWhenDragStarted.position)
let dragVectorWhenDragStarted = {
x: mouseNoZoom.x - mouseWhenDragStartedNoZoom.x,
y: mouseNoZoom.y - mouseWhenDragStartedNoZoom.y
}
let dragVector = {
x: thisObject.container.frame.position.x,
y: thisObject.container.frame.position.y
}
thisObject.container.frame.position.x = 0
thisObject.container.frame.position.y = 0
const MIN_WIDTH = 200
const MIN_HEIGHT = 100
switch (whereIsMouseOver) {
case 'center': {
switch (whatHappened) {
case 'left mouse button + SHIFT': {
/* This is equivalent to drag the whole Time Machine, so we will apply the translation received onto the Time Machine container. */
thisObject.container.parentContainer.frame.position.x = parentFrameWhenDragStarted.position.x + dragVectorWhenDragStarted.x
thisObject.container.parentContainer.frame.position.y = parentFrameWhenDragStarted.position.y + dragVectorWhenDragStarted.y
snapPointToGrid(thisObject.container.parentContainer.frame.position)
thisObject.container.parentContainer.eventHandler.raiseEvent('onDisplace')
break
}
case 'left mouse button': {
let point = {
x: (-dragVectorWhenDragStarted.x),
y: (-dragVectorWhenDragStarted.y)
}
let newMinDate = getDateFromPointAtContainer(point, thisObject.container.parentContainer, coordinateSystemWhenDragStarted)
let newMaxRate = getRateFromPointAtContainer(point, thisObject.container.parentContainer, coordinateSystemWhenDragStarted)
let xDifferenceMaxMin = coordinateSystemWhenDragStarted.max.x - coordinateSystemWhenDragStarted.min.x
let yDifferenceMaxMin = coordinateSystemWhenDragStarted.max.y - coordinateSystemWhenDragStarted.min.y
coordinateSystem.min.x = newMinDate.valueOf()
coordinateSystem.max.x = newMinDate.valueOf() + xDifferenceMaxMin
coordinateSystem.min.y = newMaxRate - yDifferenceMaxMin
coordinateSystem.max.y = newMaxRate
let event = {
type: 'center dragged',
dragVector: dragVector
}
coordinateSystem.recalculateScale(event)
}
break
case 'left or right arrow key pressed': {
let point = {
x: -dragVector.x + thisObject.container.frame.width * coordinateSystem.HORIZONTAL_MARGIN_INVERSE_FACTOR / 2,
y: 0
}
let newMinDate = getDateFromPointAtContainer(point, thisObject.container.parentContainer, coordinateSystem)
let xDifferenceMaxMin = coordinateSystem.max.x - coordinateSystem.min.x
coordinateSystem.min.x = newMinDate.valueOf()
coordinateSystem.max.x = newMinDate.valueOf() + xDifferenceMaxMin
let event = {
type: 'center dragged',
dragVector: dragVector
}
coordinateSystem.recalculateScale(event)
}
break
case 'up or down arrow key pressed': {
let point = {
x: 0,
y: -dragVector.y + thisObject.container.frame.height * coordinateSystem.VERTICAL_MARGIN_INVERSE_FACTOR / 2
}
let newMaxRate = getRateFromPointAtContainer(point, thisObject.container.parentContainer, coordinateSystem)
let yDifferenceMaxMin = coordinateSystem.max.y - coordinateSystem.min.y
coordinateSystem.min.y = newMaxRate - yDifferenceMaxMin
coordinateSystem.max.y = newMaxRate
let event = {
type: 'center dragged',
dragVector: dragVector
}
coordinateSystem.recalculateScale(event)
}
break
}
thisObject.container.parentContainer.eventHandler.raiseEvent('onMouseOver', mouse.position)
break
}
case 'top' : {
dragVectorWhenDragStarted.x = 0
let newHight = parentFrameWhenDragStarted.height - dragVectorWhenDragStarted.y
if (newHight < MIN_HEIGHT && dragVectorWhenDragStarted.y > 0) {
dragVectorWhenDragStarted.y = parentFrameWhenDragStarted.height - MIN_HEIGHT
}
thisObject.container.parentContainer.frame.position.y = parentFrameWhenDragStarted.position.y + dragVectorWhenDragStarted.y
snapPointToGrid(thisObject.container.parentContainer.frame.position)
thisObject.container.parentContainer.frame.height = parentFrameWhenDragStarted.height + (parentFrameWhenDragStarted.position.y - thisObject.container.parentContainer.frame.position.y)
let point = {
x: 0,
y: (thisObject.container.parentContainer.frame.position.y - parentFrameWhenDragStarted.position.y)
}
/* This is equivalent to getRateFromPointAtContainer, but as we do not have a container anymore because we already change it, we do it like this. */
point = coordinateSystemWhenDragStarted.unInverseTransform(point, parentFrameWhenDragStarted.height)
let newMaxRate = point.y
switch (whatHappened) {
case 'left mouse button': {
coordinateSystem.max.y = newMaxRate
coordinateSystem.maxHeight = thisObject.container.parentContainer.frame.height
let event = {
type: 'top dragged',
dragVector: dragVector
}
coordinateSystem.recalculateScale(event)
break
}
case 'left mouse button + SHIFT': {
coordinateSystem.maxHeight = thisObject.container.parentContainer.frame.height
coordinateSystem.recalculateScale()
break
}
}
thisObject.container.parentContainer.eventHandler.raiseEvent('Dimmensions Changed', event)
break
}
case 'bottom' : {
dragVectorWhenDragStarted.x = 0
let newHight = dragVectorWhenDragStarted.y + parentFrameWhenDragStarted.height
if (newHight < MIN_HEIGHT && dragVectorWhenDragStarted.y < 0) {
dragVectorWhenDragStarted.y = MIN_HEIGHT - parentFrameWhenDragStarted.height
}
let point = {
x: 0,
y: dragVectorWhenDragStarted.y + parentFrameWhenDragStarted.height + parentFrameWhenDragStarted.position.y
}
snapPointToGrid(point)
point.y = point.y - parentFrameWhenDragStarted.position.y
thisObject.container.parentContainer.frame.height = point.y
/* This is equivalent to getRateFromPointAtContainer, but as we do not have a container anymore because we already change it, we do it like this. */
point = coordinateSystemWhenDragStarted.unInverseTransform(point, parentFrameWhenDragStarted.height)
let newMinRate = point.y
switch (whatHappened) {
case 'left mouse button': {
coordinateSystem.min.y = newMinRate
coordinateSystem.maxHeight = thisObject.container.parentContainer.frame.height
let event = {
type: 'bottom dragged',
dragVector: dragVector
}
coordinateSystem.recalculateScale(event)
break
}
case 'left mouse button + SHIFT': {
coordinateSystem.maxHeight = thisObject.container.parentContainer.frame.height
coordinateSystem.recalculateScale()
break
}
}
thisObject.container.parentContainer.eventHandler.raiseEvent('Dimmensions Changed', event)
break
}
case 'left' : {
dragVectorWhenDragStarted.y = 0
let newWidth = parentFrameWhenDragStarted.width - dragVectorWhenDragStarted.x
if (newWidth < MIN_WIDTH && dragVectorWhenDragStarted.x > 0) {
dragVectorWhenDragStarted.x = parentFrameWhenDragStarted.width - MIN_WIDTH
}
thisObject.container.parentContainer.frame.position.x = parentFrameWhenDragStarted.position.x + dragVectorWhenDragStarted.x
snapPointToGrid(thisObject.container.parentContainer.frame.position)
thisObject.container.parentContainer.frame.width = parentFrameWhenDragStarted.width + (parentFrameWhenDragStarted.position.x - thisObject.container.parentContainer.frame.position.x)
let point = {
x: (thisObject.container.parentContainer.frame.position.x - parentFrameWhenDragStarted.position.x),
y: 0
}
/* This is equivalent to getDateFromPointAtContainer, but as we do not have a container anymore because we already change it, we do it like this. */
point = coordinateSystemWhenDragStarted.unInverseTransform(point, parentFrameWhenDragStarted.width)
let newMinDate = point.x
switch (whatHappened) {
case 'left mouse button': {
coordinateSystem.min.x = newMinDate.valueOf()
coordinateSystem.maxWidth = thisObject.container.parentContainer.frame.width
coordinateSystem.recalculateScale()
break
}
case 'left mouse button + SHIFT': {
coordinateSystem.maxWidth = thisObject.container.parentContainer.frame.width
coordinateSystem.recalculateScale()
break
}
}
thisObject.container.parentContainer.eventHandler.raiseEvent('Dimmensions Changed', event)
break
}
case 'right' : {
dragVectorWhenDragStarted.y = 0
let newWidth = dragVectorWhenDragStarted.x + parentFrameWhenDragStarted.width
if (newWidth < MIN_WIDTH && dragVectorWhenDragStarted.x < 0) {
dragVectorWhenDragStarted.x = MIN_WIDTH - parentFrameWhenDragStarted.width
}
let point = {
x: dragVectorWhenDragStarted.x + parentFrameWhenDragStarted.width + parentFrameWhenDragStarted.position.x,
y: 0
}
snapPointToGrid(point)
point.x = point.x - parentFrameWhenDragStarted.position.x
thisObject.container.parentContainer.frame.width = point.x
/* This is equivalent to getRateFromPointAtContainer, but as we do not have a container anymore because we already change it, we do it like this. */
point = coordinateSystemWhenDragStarted.unInverseTransform(point, parentFrameWhenDragStarted.width)
let newMaxDate = point.x
switch (whatHappened) {
case 'left mouse button': {
coordinateSystem.max.x = newMaxDate.valueOf()
coordinateSystem.maxWidth = thisObject.container.parentContainer.frame.width
coordinateSystem.recalculateScale()
break
}
case 'left mouse button + SHIFT': {
coordinateSystem.maxWidth = thisObject.container.parentContainer.frame.width
coordinateSystem.recalculateScale()
break
}
}
thisObject.container.parentContainer.eventHandler.raiseEvent('Dimmensions Changed', event)
break
}
}
function snapPointToGrid (point) {
point.x = snapScalarToGrid(point.x)
point.y = snapScalarToGrid(point.y)
}
function snapScalarToGrid (scalar) {
let sign
if (scalar < 0) {
sign = -1
} else {
sign = 1
}
const GRID_SIZE = 10
return Math.trunc(scalar / GRID_SIZE) * GRID_SIZE + GRID_SIZE / 2 * sign
}
}
function drawForeground () {
let MARGIN = 1
let edgeSize
let lineWidth
if (whereIsMouseOver === 'outside' || thisObject.isMouseOver === false) {
edgeSize = 2
lineWidth = 0.1
} else {
edgeSize = EDGE_SIZE
lineWidth = 0.5
}
const OPACITY = 1
pointA1 = {
x: 0,
y: 0
}
pointA2 = {
x: thisObject.container.frame.width,
y: 0
}
pointA3 = {
x: thisObject.container.frame.width,
y: thisObject.container.frame.height
}
pointA4 = {
x: 0,
y: thisObject.container.frame.height
}
pointB1 = {
x: 0,
y: 0
}
pointB2 = {
x: thisObject.container.frame.width,
y: 0
}
pointB3 = {
x: thisObject.container.frame.width,
y: thisObject.container.frame.height
}
pointB4 = {
x: 0,
y: thisObject.container.frame.height
}
pointA1 = transformThisPoint(pointA1, thisObject.container)
pointA2 = transformThisPoint(pointA2, thisObject.container)
pointA3 = transformThisPoint(pointA3, thisObject.container)
pointA4 = transformThisPoint(pointA4, thisObject.container)
pointB1 = transformThisPoint(pointB1, thisObject.container)
pointB2 = transformThisPoint(pointB2, thisObject.container)
pointB3 = transformThisPoint(pointB3, thisObject.container)
pointB4 = transformThisPoint(pointB4, thisObject.container)
pointA1 = {
x: pointA1.x - MARGIN,
y: pointA1.y - MARGIN
}
pointA2 = {
x: pointA2.x + MARGIN,
y: pointA2.y - MARGIN
}
pointA3 = {
x: pointA3.x + MARGIN,
y: pointA3.y + MARGIN
}
pointA4 = {
x: pointA4.x - MARGIN,
y: pointA4.y + MARGIN
}
pointB1 = {
x: pointB1.x - edgeSize,
y: pointB1.y - edgeSize
}
pointB2 = {
x: pointB2.x + edgeSize,
y: pointB2.y - edgeSize
}
pointB3 = {
x: pointB3.x + edgeSize,
y: pointB3.y + edgeSize
}
pointB4 = {
x: pointB4.x - edgeSize,
y: pointB4.y + edgeSize
}
pointA1 = canvas.chartingSpace.viewport.fitIntoViewport(pointA1)
pointA2 = canvas.chartingSpace.viewport.fitIntoViewport(pointA2)
pointA3 = canvas.chartingSpace.viewport.fitIntoViewport(pointA3)
pointA4 = canvas.chartingSpace.viewport.fitIntoViewport(pointA4)
pointB1 = canvas.chartingSpace.viewport.fitIntoViewport(pointB1)
pointB2 = canvas.chartingSpace.viewport.fitIntoViewport(pointB2)
pointB3 = canvas.chartingSpace.viewport.fitIntoViewport(pointB3)
pointB4 = canvas.chartingSpace.viewport.fitIntoViewport(pointB4)
browserCanvasContext.setLineDash([0, 0])
browserCanvasContext.beginPath()
browserCanvasContext.moveTo(pointA1.x, pointA1.y)
browserCanvasContext.lineTo(pointA2.x, pointA2.y)
browserCanvasContext.lineTo(pointB2.x, pointB2.y)
browserCanvasContext.lineTo(pointB1.x, pointB1.y)
browserCanvasContext.lineTo(pointA1.x, pointA1.y)
browserCanvasContext.closePath()
drawEdge('top')
browserCanvasContext.beginPath()
browserCanvasContext.moveTo(pointA2.x, pointA2.y)
browserCanvasContext.lineTo(pointA3.x, pointA3.y)
browserCanvasContext.lineTo(pointB3.x, pointB3.y)
browserCanvasContext.lineTo(pointB2.x, pointB2.y)
browserCanvasContext.lineTo(pointA2.x, pointA2.y)
browserCanvasContext.closePath()
drawEdge('right')
browserCanvasContext.beginPath()
browserCanvasContext.moveTo(pointA3.x, pointA3.y)
browserCanvasContext.lineTo(pointA4.x, pointA4.y)
browserCanvasContext.lineTo(pointB4.x, pointB4.y)
browserCanvasContext.lineTo(pointB3.x, pointB3.y)
browserCanvasContext.lineTo(pointA3.x, pointA3.y)
browserCanvasContext.closePath()
drawEdge('bottom')
browserCanvasContext.beginPath()
browserCanvasContext.moveTo(pointA4.x, pointA4.y)
browserCanvasContext.lineTo(pointA1.x, pointA1.y)
browserCanvasContext.lineTo(pointB1.x, pointB1.y)
browserCanvasContext.lineTo(pointB4.x, pointB4.y)
browserCanvasContext.lineTo(pointA4.x, pointA4.y)
browserCanvasContext.closePath()
drawEdge('left')
function drawEdge (edgeType) {
if (whereIsMouseOver === edgeType && thisObject.isMouseOver === true) {
browserCanvasContext.lineWidth = lineWidth
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + OPACITY + ')'
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + OPACITY + ')'
} else {
browserCanvasContext.lineWidth = lineWidth
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + OPACITY + ')'
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.DARK_TURQUOISE + ', ' + OPACITY + ')'
}
browserCanvasContext.fill()
browserCanvasContext.stroke()
}
}
}
-326
View File
@@ -1,326 +0,0 @@
function newPlottersManager () {
const MODULE_NAME = 'Plotters Manager'
const ERROR_LOG = true
const logger = newWebDebugLog()
logger.fileName = MODULE_NAME
let timeFrame = INITIAL_TIME_PERIOD
let datetime = NEW_SESSION_INITIAL_DATE
let thisObject = {
fitFunction: undefined,
container: undefined,
payload: undefined,
connectors: [],
setDatetime: setDatetime,
setTimeFrame: setTimeFrame,
setCoordinateSystem: setCoordinateSystem,
draw: draw,
getContainer: getContainer,
initialize: initialize,
finalize: finalize
}
thisObject.connectors = []
let initializationReady = false
let layersPanel
let onLayerStatusChangedEventSuscriptionId
let coordinateSystem
setupContainer()
return thisObject
function setupContainer () {
thisObject.container = newContainer()
thisObject.container.initialize(MODULE_NAME)
}
function finalize () {
layersPanel.container.eventHandler.stopListening(onLayerStatusChangedEventSuscriptionId)
layersPanel = undefined
for (let i = 0; i < thisObject.connectors.length; i++) {
let connector = thisObject.connectors[i]
/* Then the panels. */
for (let j = 0; j < connector.panels.length; j++) {
canvas.panelsSpace.destroyPanel(connector.panels[j])
connector.panels[j] = undefined
}
connector.panels = undefined
/* Finalize the plotters */
if (connector.plotter.finalize !== undefined) {
connector.plotter.container.eventHandler.stopListening(connector.plotter.onRecordChangeEventsSubscriptionId)
connector.plotter.finalize()
}
connector.plotter = undefined
/* Finally the Storage Objects */
finalizeStorage(connector.storage)
connector.storage = undefined
connector = undefined
}
thisObject.connectors = []
coordinateSystem = undefined
thisObject.container.finalize()
thisObject.container = undefined
thisObject.payload = undefined
}
function finalizeStorage (storage) {
storage.eventHandler.stopListening(storage.onMarketFileLoadedLayerEventsSubscriptionId)
storage.eventHandler.stopListening(storage.onDailyFileLoadedLayerEventsSubscriptionId)
storage.eventHandler.stopListening(storage.onSingleFileLoadedLayerEventsSubscriptionId)
storage.eventHandler.stopListening(storage.onFileSequenceLoadedLayerEventsSubscriptionId)
storage.eventHandler.stopListening(storage.onDailyFileLoadedPlotterEventsSubscriptionId)
storage.finalize()
}
function initialize (pLayersPanel) {
/* Remember this */
layersPanel = pLayersPanel
/* Listen to the event of change of status */
onLayerStatusChangedEventSuscriptionId = layersPanel.container.eventHandler.listenToEvent('Layer Status Changed', onLayerStatusChanged)
}
function initializePlotter (layer) {
try {
/* Before Initializing a Plotter, we need the Storage it will use, loaded with the files it will initially need. */
let storage = newProductStorage(layer.payload.node.id)
/*
Before Initializing the Storage, we will put the Layer to listen to the events the storage will raise every time a file is loaded,
so that the UI can somehow show this. There are different types of events.
*/
for (let i = 0; i < layer.definition.referenceParent.referenceParent.datasets.length; i++) {
let dataset = layer.definition.referenceParent.referenceParent.datasets[i]
switch (dataset.code.type) {
case 'Market Files': {
storage.onMarketFileLoadedLayerEventsSubscriptionId = storage.eventHandler.listenToEvent('Market File Loaded', layer.onMarketFileLoaded)
}
break
case 'Daily Files': {
storage.onDailyFileLoadedLayerEventsSubscriptionId = storage.eventHandler.listenToEvent('Daily File Loaded', layer.onDailyFileLoaded)
}
break
case 'Single File': {
storage.onSingleFileLoadedLayerEventsSubscriptionId = storage.eventHandler.listenToEvent('Single File Loaded', layer.onSingleFileLoaded)
}
break
case 'File Sequence': {
storage.onFileSequenceLoadedLayerEventsSubscriptionId = storage.eventHandler.listenToEvent('File Sequence Loaded', layer.onFileSequenceLoaded)
}
break
default: {
if (ERROR_LOG === true) {
logger.write('[ERROR] initializePlotter -> Dataset Type Incorrect or Undefined -> dataset.type = ' + dataset.type)
}
return
}
}
}
let baseAsset = layer.definition.referenceParent.parentNode.referenceParent.baseAsset.referenceParent.code.codeName
let quotedAsset = layer.definition.referenceParent.parentNode.referenceParent.quotedAsset.referenceParent.code.codeName
let market = {
baseAsset: baseAsset,
quotedAsset: quotedAsset
}
let product = layer.definition.referenceParent.referenceParent
let bot = layer.definition.referenceParent.referenceParent.parentNode
let dataMine = layer.definition.referenceParent.referenceParent.parentNode.parentNode
let exchange = layer.definition.referenceParent.parentNode.referenceParent.parentNode.parentNode
let plotterModule = layer.definition.referenceParent.referenceParent.referenceParent
let session
if (layer.definition.referenceParent.parentNode.parentNode !== undefined) {
if (layer.definition.referenceParent.parentNode.parentNode.type === 'Session Reference') {
if (layer.definition.referenceParent.parentNode.parentNode.referenceParent !== undefined) {
session = layer.definition.referenceParent.parentNode.parentNode.referenceParent
}
}
}
let host = layer.networkNode.code.host
let webPort = layer.networkNode.code.webPort
if (host === undefined) { host = 'localhost' }
if (webPort === undefined) { webPort = window.location.port }
let eventsServerClient = canvas.designSpace.workspace.eventsServerClients.get(layer.networkNode.id)
storage.initialize(
dataMine,
bot,
session,
product,
exchange,
market,
datetime,
timeFrame,
host,
webPort,
eventsServerClient,
onProductStorageInitialized
)
function onProductStorageInitialized (err) {
try {
if (err.result === GLOBAL.DEFAULT_OK_RESPONSE.result) {
/* Now we have all the initial data loaded and ready to be delivered to the new instance of the plotter. */
let plotter
if (plotterModule.code.isLegacy !== true) {
plotter = newPlotter()
} else {
plotter = getNewPlotter(dataMine.code.codeName, plotterModule.parentNode.code.codeName, plotterModule.code.codeName)
}
plotter.container.connectToParent(thisObject.container, true, true, false, true, true, true, false, false, true)
plotter.container.frame.position.x = thisObject.container.frame.width / 2 - plotter.container.frame.width / 2
plotter.container.frame.position.y = thisObject.container.frame.height / 2 - plotter.container.frame.height / 2
plotter.fitFunction = thisObject.fitFunction
plotter.initialize(storage, datetime, timeFrame, coordinateSystem, onPlotterInizialized, product)
function onPlotterInizialized () {
try {
let connector = {
layer: layer,
plotter: plotter,
storage: storage
}
/* Let the Plotter listen to the event of Cursor Files loaded, so that it can react recalculating if needed. */
plotter.onDailyFileLoadedPlotterEventsSubscriptionId = storage.eventHandler.listenToEvent('Daily File Loaded', plotter.onDailyFileLoaded)
/* Lets load now this plotter panels. */
connector.panels = []
if (product !== undefined) {
for (let i = 0; i < plotterModule.panels.length; i++) {
let panel = plotterModule.panels[i]
let parameters = {
dataMine: dataMine.code.codeName,
plotterCodeName: plotterModule.parentNode.code.codeName,
moduleCodeName: plotterModule.code.codeName,
panelNode: panel
}
let owner = thisObject.payload.node.payload.parentNode.id // Panels are owned by the time machine.
let plotterPanelHandle = canvas.panelsSpace.createNewPanel('Plotter Panel', parameters, owner, layer.session)
let plotterPanel = canvas.panelsSpace.getPanel(plotterPanelHandle)
/* Connect Panel to the Plotter via an Event. */
connector.plotter.onRecordChangeEventsSubscriptionId = connector.plotter.container.eventHandler.listenToEvent('Current Record Changed', plotterPanel.onRecordChange)
connector.panels.push(plotterPanelHandle)
}
connector.layer.panels = connector.panels
}
thisObject.connectors.push(connector)
} catch (err) {
if (ERROR_LOG === true) { logger.write('[ERROR] initializePlotter -> onProductStorageInitialized -> onPlotterInizialized -> err = ' + err.stack) }
}
}
}
} catch (err) {
if (ERROR_LOG === true) { logger.write('[ERROR] initializePlotter -> onProductStorageInitialized -> err = ' + err.stack) }
}
}
} catch (err) {
if (ERROR_LOG === true) { logger.write('[ERROR] initializePlotter -> err = ' + err.stack) }
}
}
function onLayerStatusChanged (layer) {
if (layer.status === LAYER_STATUS.LOADING) {
/* Lets see if we can find the Plotter of this card on our Active Plotters list, other wise we will initialize it */
let found = false
for (let i = 0; i < thisObject.connectors.length; i++) {
let connector = thisObject.connectors[i]
if (connector.layer.payload.node.id === layer.payload.node.id) {
found = true
}
}
if (found === false) {
initializePlotter(layer, onProductPlotterInitialized)
function onProductPlotterInitialized (err) {
/* There is no policy yet of what to do if this fails. */
}
}
}
if (layer.status === LAYER_STATUS.OFF) {
/* If the plotter of this card is not on our Active Plotters list, then we remove it. */
for (let i = 0; i < thisObject.connectors.length; i++) {
let connector = thisObject.connectors[i]
if (connector.layer.payload.node.id === layer.payload.node.id) {
/* Then the panels. */
for (let j = 0; j < connector.panels.length; j++) {
canvas.panelsSpace.destroyPanel(connector.panels[j])
}
/* Finally the Storage Objects */
if (connector.plotter.finalize !== undefined) {
connector.plotter.container.eventHandler.stopListening(connector.plotter.onRecordChangeEventsSubscriptionId)
connector.plotter.container.finalize()
connector.plotter.finalize()
}
finalizeStorage(connector.storage)
thisObject.connectors.splice(i, 1) // Delete item from array.
return // We already found the product woth changes and processed it.
}
}
}
}
function setTimeFrame (pTimeFrame) {
timeFrame = pTimeFrame
for (let i = 0; i < thisObject.connectors.length; i++) {
let connector = thisObject.connectors[i]
connector.layer.setTimeFrame(timeFrame)
connector.storage.setTimeFrame(timeFrame)
connector.plotter.setTimeFrame(timeFrame)
}
}
function setDatetime (pDatetime) {
datetime = pDatetime
for (let i = 0; i < thisObject.connectors.length; i++) {
let connector = thisObject.connectors[i]
connector.layer.setDatetime(pDatetime)
connector.storage.setDatetime(pDatetime)
connector.plotter.setDatetime(pDatetime)
}
}
function setCoordinateSystem (pCoordinateSystem) {
coordinateSystem = pCoordinateSystem
for (let i = 0; i < thisObject.connectors.length; i++) {
let connector = thisObject.connectors[i]
connector.plotter.setCoordinateSystem(coordinateSystem)
}
}
function getContainer (point) {
}
function draw () {
if (thisObject.connectors === undefined) { return } // We need to wait
/* First the Product Plotters. */
let maxElementsPlotted = 0
for (let i = 0; i < thisObject.connectors.length; i++) {
let connector = thisObject.connectors[thisObject.connectors.length - i - 1]
let elementsPlotted = connector.plotter.draw()
if (elementsPlotted !== undefined) {
if (elementsPlotted > maxElementsPlotted) {
maxElementsPlotted = elementsPlotted
}
}
}
return maxElementsPlotted
}
}
-822
View File
@@ -1,822 +0,0 @@
/*
Markets are a function of time. When watching them, end users must be positioned at one particular point in time. The system currently allows users
to position themselves at any time they like.
In the future, it will be usefull to explore markets and compare them at different times simultaneously. Anticipating that future this module exists.
All the timelineCharts that depand on a datetime are children of this object Time Machine. In the future we will allow users to have more than one Time Machine,
each one with it own timelineCharts, and each one positioned at an especific point in titme.
*/
function newTimeMachine () {
const MODULE_NAME = 'Time Machine'
const logger = newWebDebugLog()
logger.fileName = MODULE_NAME
let timeFrame = INITIAL_TIME_PERIOD
let thisObject = {
container: undefined,
timeScale: undefined,
rateScale: undefined,
payload: undefined,
edgeEditor: undefined,
onFocus: undefined,
onKeyPressed: onKeyPressed,
timelineCharts: [],
fitFunction: fitFunction,
physics: physics,
draw: draw,
drawBackground: drawBackground,
drawForeground: drawForeground,
getContainer: getContainer, // returns the inner most container that holds the point received by parameter.
initialize: initialize,
finalize: finalize
}
let timeMachineCoordinateSystem = newCoordinateSystem()
timeMachineCoordinateSystem.name = 'TIME MACHINE'
let mouse = {
position: {
x: 0,
y: 0
}
}
let tabAnimation = 0
let tabAnimationStatus = 'Close'
let tabAnimationCounter = 0
let wasOnFocus = false
let drawScales = false
let syncWithDesignerLoop = 0
let timelineChartsMap = new Map()
let onMouseOverEventSuscriptionId
let onMouseNotOverEventSuscriptionId
let timeScaleMouseOverEventSuscriptionId
let rateScaleMouseOverEventSuscriptionId
let timeFrameScaleEventSuscriptionId
let timeFrameScaleMouseOverEventSuscriptionId
let onScaleChangedEventSubscriptionId
setupContainer()
return thisObject
function setupContainer () {
thisObject.container = newContainer()
thisObject.container.initialize(MODULE_NAME)
thisObject.container.fitFunction = thisObject.fitFunction
thisObject.container.isDraggeable = false
thisObject.container.insideViewport = true
thisObject.container.detectMouseOver = true
thisObject.container.frame.width = browserCanvas.width / TIME_MACHINE_WIDTH
thisObject.container.frame.height = (browserCanvas.height - TOP_SPACE_HEIGHT - COCKPIT_SPACE_HEIGHT) / TIME_MACHINE_HEIGHT
}
function finalize () {
timeMachineCoordinateSystem.eventHandler.stopListening(onScaleChangedEventSubscriptionId)
if (thisObject.timeScale !== undefined) {
finalizeTimeScale()
}
if (thisObject.rateScale !== undefined) {
finalizeRateScale()
}
if (thisObject.timeFrameScale !== undefined) {
finalizeTimeFrameScale()
}
thisObject.container.eventHandler.stopListening(onMouseOverEventSuscriptionId)
thisObject.container.eventHandler.stopListening(onMouseNotOverEventSuscriptionId)
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
let timelineChart = thisObject.timelineCharts[i]
timelineChart.container.eventHandler.stopListening(timelineChart.onChildrenMouseOverEventSuscriptionId)
timelineChart.finalize()
}
thisObject.timelineCharts = undefined
thisObject.fitFunction = undefined
thisObject.container.finalize()
thisObject.container = undefined
thisObject.payload = undefined
thisObject.edgeEditor = undefined
mouse = undefined
timelineChartsMap = undefined
timeMachineCoordinateSystem.finalize()
timeMachineCoordinateSystem = undefined
}
function finalizeTimeScale () {
if (thisObject.timeScale === undefined) { return }
thisObject.timeScale.container.eventHandler.stopListening(timeScaleMouseOverEventSuscriptionId)
thisObject.timeScale.finalize()
thisObject.timeScale = undefined
}
function finalizeRateScale () {
if (thisObject.rateScale === undefined) { return }
thisObject.rateScale.container.eventHandler.stopListening(rateScaleMouseOverEventSuscriptionId)
thisObject.rateScale.finalize()
thisObject.rateScale = undefined
}
function finalizeTimeFrameScale () {
if (thisObject.timeFrameScale === undefined) { return }
thisObject.timeFrameScale.container.eventHandler.stopListening(timeFrameScaleEventSuscriptionId)
thisObject.timeFrameScale.container.eventHandler.stopListening(timeFrameScaleMouseOverEventSuscriptionId)
thisObject.timeFrameScale.finalize()
thisObject.timeFrameScale = undefined
}
function initialize (callBackFunction) {
timeFrame = INITIAL_TIME_PERIOD
loadFrame(thisObject.payload, thisObject.container.frame)
saveFrame(thisObject.payload, thisObject.container.frame)
recalculateCoordinateSystem()
recalculateCurrentDatetime()
onMouseOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
onMouseNotOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
onScaleChangedEventSubscriptionId = timeMachineCoordinateSystem.eventHandler.listenToEvent('Scale Changed', onScaleChanged)
thisObject.edgeEditor = newEdgeEditor()
thisObject.edgeEditor.initialize(timeMachineCoordinateSystem)
thisObject.edgeEditor.container.connectToParent(thisObject.container, true, true, false, true, true, true)
callBackFunction()
}
function onKeyPressed (event) {
thisObject.edgeEditor.onKeyPressed(event)
}
function onMouseOver (event) {
drawScales = true
mouse.position.x = event.x
mouse.position.y = event.y
if (thisObject.timeScale !== undefined) {
thisObject.timeScale.onMouseOverSomeTimeMachineContainer(event)
}
if (thisObject.rateScale !== undefined) {
thisObject.rateScale.onMouseOverSomeTimeMachineContainer(event)
}
if (thisObject.timeFrameScale !== undefined) {
thisObject.timeFrameScale.onMouseOverSomeTimeMachineContainer(event)
}
}
function onMouseNotOver (event) {
drawScales = false
if (thisObject.timeScale !== undefined) {
thisObject.timeScale.visible = false
}
if (thisObject.rateScale !== undefined) {
thisObject.rateScale.visible = false
}
if (thisObject.timeFrameScale !== undefined) {
thisObject.timeFrameScale.visible = false
}
}
function initializeTimeScale () {
thisObject.timeScale = newTimeScale()
thisObject.timeScale.fitFunction = thisObject.fitFunction
thisObject.timeScale.payload = thisObject.payload.node.timeScale.payload
timeScaleMouseOverEventSuscriptionId = thisObject.timeScale.container.eventHandler.listenToEvent('onMouseOverScale', timeScaleMouseOver)
thisObject.timeScale.initialize(timeMachineCoordinateSystem, thisObject.container)
function timeScaleMouseOver (event) {
thisObject.container.eventHandler.raiseEvent('onMouseOver', event)
}
}
function initializeRateScale () {
thisObject.rateScale = newRateScale()
thisObject.rateScale.fitFunction = thisObject.fitFunction
thisObject.rateScale.payload = thisObject.payload.node.rateScale.payload
rateScaleMouseOverEventSuscriptionId = thisObject.rateScale.container.eventHandler.listenToEvent('onMouseOverScale', rateScaleMouseOver)
thisObject.rateScale.initialize(timeMachineCoordinateSystem, thisObject.container, thisObject.container)
function rateScaleMouseOver (event) {
thisObject.container.eventHandler.raiseEvent('onMouseOver', event)
}
}
function initializeTimeFrameScale () {
thisObject.timeFrameScale = newTimeFrameScale()
thisObject.timeFrameScale.fitFunction = thisObject.fitFunction
thisObject.timeFrameScale.payload = thisObject.payload.node.timeFrameScale.payload
timeFrameScaleEventSuscriptionId = thisObject.timeFrameScale.container.eventHandler.listenToEvent('Time Frame Value Changed', timeFrameScaleValueChanged)
timeFrameScaleMouseOverEventSuscriptionId = thisObject.timeFrameScale.container.eventHandler.listenToEvent('onMouseOverScale', timeFrameScaleMouseOver)
thisObject.timeFrameScale.initialize(thisObject.container)
function timeFrameScaleValueChanged (event) {
let currentTimeFrame = timeFrame
timeFrame = event.timeFrame
if (timeFrame !== currentTimeFrame) {
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
let timelineChart = thisObject.timelineCharts[i]
timelineChart.upstreamTimeFrame = timeFrame
if (timelineChart.timeFrameScale === undefined) {
timelineChart.setTimeFrame(timeFrame)
}
}
}
}
function timeFrameScaleMouseOver (event) {
thisObject.container.eventHandler.raiseEvent('onMouseOver', event)
}
}
function getContainer (point, purpose) {
let container
if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) {
container = thisObject.rateScale.getContainer(point, purpose)
if (container !== undefined) {
if (container.isForThisPurpose(purpose)) {
return container
} else {
if (purpose === GET_CONTAINER_PURPOSE.DRAGGING && container.isClickeable === true) {
return container
}
}
}
}
if (thisObject.timeScale !== undefined && thisObject.timeScale.isVisible === true) {
container = thisObject.timeScale.getContainer(point, purpose)
if (container !== undefined) {
if (container.isForThisPurpose(purpose)) {
return container
} else {
if (purpose === GET_CONTAINER_PURPOSE.DRAGGING && container.isClickeable === true) {
return container
}
}
}
}
if (thisObject.timeFrameScale !== undefined && thisObject.timeFrameScale.isVisible === true) {
container = thisObject.timeFrameScale.getContainer(point, purpose)
if (container !== undefined) {
if (container.isForThisPurpose(purpose)) {
return container
}
}
}
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
container = thisObject.timelineCharts[i].getContainer(point, purpose)
if (container !== undefined) {
if (container.isForThisPurpose(purpose)) {
if (thisObject.container.frame.isThisPointHere(point) === true) {
return container
}
} else {
if (purpose === GET_CONTAINER_PURPOSE.DRAGGING && container.isClickeable === true) {
if (thisObject.container.frame.isThisPointHere(point) === true) {
return container
}
}
}
}
}
container = thisObject.edgeEditor.getContainer(point, purpose)
if (container !== undefined) {
return container
} else {
if (thisObject.container.isForThisPurpose(purpose)) {
if (thisObject.container.frame.isThisPointHere(point) === true) {
return thisObject.container
}
}
}
}
function onScaleChanged () {
recalculateCurrentDatetime()
}
function recalculateCurrentDatetime () {
let center = {
x: thisObject.container.frame.width / 2,
y: thisObject.container.frame.height / 2
}
datetime = new Date(getDateFromPointAtContainer(center, thisObject.container, timeMachineCoordinateSystem))
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
let timelineChart = thisObject.timelineCharts[i]
timelineChart.setDatetime(datetime)
}
}
function fitFunction (point, fullVisible, margin, topMargin, bottomMargin) {
/* We prevent a point to be out of the container AND out of the Charting Space in general */
let returnPoint = {
x: point.x,
y: point.y
}
let upCorner = {
x: 0,
y: 0
}
let bottonCorner = {
x: thisObject.container.frame.width,
y: thisObject.container.frame.height
}
upCorner = transformThisPoint(upCorner, thisObject.container)
bottonCorner = transformThisPoint(bottonCorner, thisObject.container)
/* Checking against the container limits. */
if (margin === undefined) { margin = 0 }
if (topMargin === undefined) { topMargin = 0 }
if (bottomMargin === undefined) { bottomMargin = 0 }
if (returnPoint.x - margin < upCorner.x) { returnPoint.x = upCorner.x + margin }
if (returnPoint.x + margin > bottonCorner.x) { returnPoint.x = bottonCorner.x - margin }
if (returnPoint.y - margin - topMargin < upCorner.y) { returnPoint.y = upCorner.y + margin + topMargin }
if (returnPoint.y + margin + bottomMargin > bottonCorner.y) { returnPoint.y = bottonCorner.y - margin - bottomMargin }
returnPoint = canvas.chartingSpace.fitFunction(returnPoint, fullVisible)
return returnPoint
}
function physics () {
thisObject.edgeEditor.physics()
timeMachineCoordinateSystem.physics()
saveFrame(thisObject.payload, thisObject.container.frame)
if (thisObject.container.frame.isInViewPort()) {
childrenPhysics()
syncWithDesigner()
}
panelPhysics()
onFocusPhysics()
tabAnimationPhysics()
}
function tabAnimationPhysics () {
const MAX_COUNTER_VALUE = 40
const STEP = 10
if (wasOnFocus === true && thisObject.onFocus === false) {
tabAnimationStatus = 'Closing'
}
if (wasOnFocus === false && thisObject.onFocus === true) {
tabAnimationStatus = 'Opening'
}
if (tabAnimationStatus === 'Closing') {
tabAnimationCounter = tabAnimationCounter - STEP
if (tabAnimationCounter <= 0) {
tabAnimationCounter = 0
tabAnimationStatus = 'Closed'
}
}
if (tabAnimationStatus === 'Opening') {
tabAnimationCounter = tabAnimationCounter + STEP
if (tabAnimationCounter >= MAX_COUNTER_VALUE) {
tabAnimationCounter = MAX_COUNTER_VALUE
tabAnimationStatus = 'Open'
}
}
}
function onFocusPhysics () {
wasOnFocus = thisObject.onFocus
if (thisObject.edgeEditor.isMouseOver === true) {
thisObject.onFocus = true
} else {
thisObject.onFocus = false
}
}
function panelPhysics () {
if (
thisObject.container.frame.isInViewPort() &&
canvas.chartingSpace.viewport.zoomLevel >= ZOOM_OUT_THRESHOLD_FOR_NOT_HIDDING_PANELS) {
canvas.panelsSpace.unHide(thisObject.payload.node.id, 'Layers Panel')
canvas.panelsSpace.unHide(thisObject.payload.node.id, 'Plotter Panel')
return
}
if (
thisObject.container.frame.isCenterInViewPort() &&
canvas.chartingSpace.viewport.zoomLevel >= ZOOM_OUT_THRESHOLD_FOR_HIDDING_PANELS
) {
canvas.panelsSpace.unHide(thisObject.payload.node.id, 'Layers Panel')
canvas.panelsSpace.unHide(thisObject.payload.node.id, 'Plotter Panel')
} else {
canvas.panelsSpace.hide(thisObject.payload.node.id, 'Layers Panel')
canvas.panelsSpace.hide(thisObject.payload.node.id, 'Plotter Panel')
}
}
function syncWithDesigner () {
syncWithDesignerTimelineCharts()
syncWithDesignerScales()
}
function syncWithDesignerScales () {
if (thisObject.payload.node === undefined) {
finalizeTimeScale()
finalizeRateScale()
finalizeTimeFrameScale()
return
}
if (thisObject.payload.node.timeScale === undefined && thisObject.timeScale !== undefined) {
finalizeTimeScale()
}
if (thisObject.payload.node.timeScale !== undefined && thisObject.timeScale === undefined) {
initializeTimeScale()
}
if (thisObject.payload.node.rateScale === undefined && thisObject.rateScale !== undefined) {
finalizeRateScale()
}
if (thisObject.payload.node.rateScale !== undefined && thisObject.rateScale === undefined) {
initializeRateScale()
}
if (thisObject.payload.node.timeFrameScale === undefined && thisObject.timeFrameScale !== undefined) {
finalizeTimeFrameScale()
}
if (thisObject.payload.node.timeFrameScale !== undefined && thisObject.timeFrameScale === undefined) {
initializeTimeFrameScale()
}
}
function syncWithDesignerTimelineCharts () {
syncWithDesignerLoop = syncWithDesignerLoop + 0.00000000001
for (let j = 0; j < thisObject.payload.node.timelineCharts.length; j++) {
let node = thisObject.payload.node.timelineCharts[j]
let timelineChart = timelineChartsMap.get(node.id)
if (timelineChart === undefined) {
/* The timeline timelineChart node is new, thus we need to initialize a new timelineChart */
initializeTimelineChart(node, syncWithDesignerLoop)
} else {
/* The time machine already exists, we tag it as existing at the current loop. */
timelineChart.syncWithDesignerLoop = syncWithDesignerLoop
}
}
/* We check all the timeMachines we have to see if we need to remove any of them */
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
let timelineChart = thisObject.timelineCharts[i]
if (timelineChart.syncWithDesignerLoop < syncWithDesignerLoop) {
/* Must be removed */
timelineChart.container.eventHandler.stopListening(timelineChart.onChildrenMouseOverEventSuscriptionId)
timelineChart.finalize()
timelineChartsMap.delete(timelineChart.nodeId)
thisObject.timelineCharts.splice(i, 1)
/* We remove one at the time */
return
}
}
function initializeTimelineChart (node, syncWithDesignerLoop) {
let timelineChart = newTimelineChart()
timelineChart.syncWithDesignerLoop = syncWithDesignerLoop
timelineChart.payload = node.payload
timelineChart.nodeId = node.id
timelineChartsMap.set(node.id, timelineChart)
timelineChart.payload.uiObject.setValue('Loading...')
/* Setting up the new timeline timelineChart. */
timelineChart.container.connectToParent(thisObject.container, true, true, false, true, true, true, false, false, true)
timelineChart.container.fitFunction = thisObject.container.fitFunction
timelineChart.fitFunction = thisObject.fitFunction
timelineChart.container.frame.width = thisObject.container.frame.width
timelineChart.container.frame.height = thisObject.container.frame.height
timelineChart.container.frame.position.x = 0
timelineChart.container.frame.position.y = 0
timelineChart.initialize(timeMachineCoordinateSystem, timeFrame)
/* we will store the event suscription id as a property of the timelineChart, to avoid keeping it an a separate array */
timelineChart.onChildrenMouseOverEventSuscriptionId = timelineChart.container.eventHandler.listenToEvent('onChildrenMouseOver', onChildrenMouseOver)
thisObject.timelineCharts.push(timelineChart)
timelineChart.payload.uiObject.setValue('')
function onChildrenMouseOver (event) {
thisObject.container.eventHandler.raiseEvent('onMouseOver', event)
}
}
}
function childrenPhysics () {
if (thisObject.timeScale !== undefined) {
thisObject.timeScale.physics()
}
if (thisObject.rateScale !== undefined) {
thisObject.rateScale.physics()
}
if (thisObject.timeFrameScale !== undefined) {
thisObject.timeFrameScale.physics()
}
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
let timelineChart = thisObject.timelineCharts[i]
timelineChart.physics()
}
}
function drawBackground () {
drawChartsBackground()
if (thisObject.container.frame.isInViewPort()) {
if (drawScales === true) {
if (thisObject.timeScale !== undefined && thisObject.timeScale.isVisible === true) { thisObject.timeScale.drawBackground() }
if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) { thisObject.rateScale.drawBackground() }
}
let maxElementsPlotted = 0
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
let timelineChart = thisObject.timelineCharts[thisObject.timelineCharts.length - i - 1]
let elementsPlotted = timelineChart.drawBackground()
if (elementsPlotted !== undefined) {
if (elementsPlotted > maxElementsPlotted) {
maxElementsPlotted = elementsPlotted
}
}
}
if (thisObject.timeFrameScale !== undefined) {
thisObject.timeFrameScale.adjustTimeFrame(maxElementsPlotted)
}
}
}
function drawChartsBackground () {
drawContainerBackground(thisObject.container, UI_COLOR.WHITE, 0.5, thisObject.fitFunction)
}
function draw () {
if (thisObject.payload === undefined) { return }
if (thisObject.payload.node === undefined) { return }
if (thisObject.container.frame.isInViewPort()) {
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
let timelineChart = thisObject.timelineCharts[thisObject.timelineCharts.length - i - 1]
timelineChart.draw()
}
if (drawScales === true) {
if (thisObject.timeScale !== undefined && thisObject.timeScale.isVisible === true) { thisObject.timeScale.draw() }
if (thisObject.timeFrameScale !== undefined && thisObject.timeFrameScale.isVisible === true) { thisObject.timeFrameScale.draw() }
if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) { thisObject.rateScale.draw() }
}
} else {
if (canvas.chartingSpace.viewport.zoomTargetLevel < ZOOM_OUT_THRESHOLD_FOR_DISPLAYING_TIME_MACHINES_ICONIZED) {
let icon = canvas.designSpace.iconByUiObjectType.get(thisObject.payload.node.type)
if (icon !== undefined) {
if (icon.canDrawIcon === true) {
let imageSize = 40
let imagePosition = {
x: thisObject.container.frame.width / 2,
y: thisObject.container.frame.height / 2
}
imagePosition = transformThisPoint(imagePosition, thisObject.container)
imagePosition = thisObject.fitFunction(imagePosition, true)
browserCanvasContext.drawImage(
icon,
imagePosition.x - imageSize / 2,
imagePosition.y - imageSize / 2,
imageSize,
imageSize)
}
}
}
}
}
function drawForeground () {
if (thisObject.container.frame.isInViewPort()) {
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
let timelineChart = thisObject.timelineCharts[thisObject.timelineCharts.length - i - 1]
timelineChart.drawForeground()
}
if (drawScales === true) {
if (thisObject.timeScale !== undefined && thisObject.timeScale.isVisible === true) { thisObject.timeScale.drawForeground() }
if (thisObject.timeFrameScale !== undefined && thisObject.timeFrameScale.isVisible === true) { thisObject.timeFrameScale.drawForeground() }
if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) { thisObject.rateScale.drawForeground() }
}
drawLabel()
thisObject.edgeEditor.drawForeground()
}
}
function drawLabel () {
if (thisObject.payload.node === undefined) { return }
if (thisObject.payload === undefined) { return }
/* Draw Title Above the Container */
let position = {
x: 0,
y: 0
}
let imageSize = 13
let fontSize = 15
let opacity = 1
let icon = canvas.designSpace.iconByUiObjectType.get(thisObject.payload.node.type)
position = transformThisPoint(position, thisObject.container)
let label = thisObject.payload.node.name
let description = loadPropertyFromNodeConfig(thisObject.payload, 'description')
if (description !== undefined) {
label = description
}
printLabel(label, position.x + 20, position.y - 10, opacity, fontSize)
if (icon !== undefined) {
if (icon.canDrawIcon === true) {
browserCanvasContext.drawImage(
icon, position.x + 5,
position.y - 22,
imageSize,
imageSize)
}
}
imageSize = 13
fontSize = 15
let exchangeMarkets = new Map()
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
let timelinechart = thisObject.timelineCharts[i]
if (timelinechart.layersManager !== undefined) {
for (let j = 0; j < timelinechart.layersManager.layers.length; j++) {
let layer = timelinechart.layersManager.layers[j]
exchangeMarket = {
exchangeName: layer.exchange.name,
marketName: layer.market,
exchangeIcon: layer.exchangeIcon,
baseAssetIcon: layer.baseAssetIcon,
quotedAssetIcon: layer.quotedAssetIcon
}
exchangeMarkets.set(exchangeMarket.exchangeName + '-' + exchangeMarket.marketName, exchangeMarket)
}
}
}
drawTab(0, 0, exchangeMarkets.size * tabAnimationCounter, 90, thisObject.container)
const INTER_EXCHANGE_SPACE = 60
const INTER_MARKET_SPACE = -100
if (tabAnimationStatus === 'Open') {
drawMarketNames()
}
function drawMarketNames () {
exchangeMarkets.forEach((exchangeMarket, i) => {
browserCanvasContext.save()
browserCanvasContext.translate(position.x, position.y)
browserCanvasContext.rotate(-Math.PI / 2)
let xOffSet = -80
icon = exchangeMarket.exchangeIcon
if (icon !== undefined) {
if (icon.canDrawIcon === true) {
browserCanvasContext.drawImage(
icon,
-20 + xOffSet,
-43,
imageSize,
imageSize)
}
}
printLabel(exchangeMarket.exchangeName, -5 + xOffSet, -30, opacity, fontSize, UI_COLOR.GREY)
position.x = position.x + INTER_EXCHANGE_SPACE
icon = exchangeMarket.baseAssetIcon
if (icon !== undefined) {
if (icon.canDrawIcon === true) {
browserCanvasContext.drawImage(
icon,
-20 + xOffSet,
-22,
imageSize,
imageSize)
}
}
printLabel(exchangeMarket.marketName, -5 + xOffSet, -10, opacity, fontSize, UI_COLOR.GREY)
icon = exchangeMarket.quotedAssetIcon
if (icon !== undefined) {
if (icon.canDrawIcon === true) {
browserCanvasContext.drawImage(
icon,
+50 + xOffSet,
-22,
imageSize,
imageSize)
}
}
position.x = position.x + INTER_MARKET_SPACE
browserCanvasContext.restore()
})
}
function drawTab (x, y, width, height, container) {
const GRADIENT = 0
const X_OFFSET = -3
const Y_OFFSET = 13
const TAB_CORNERS_RADIUS = 5
let point = {
x: x,
y: y
}
point = transformThisPoint(point, container)
let point1 = {
x: point.x + X_OFFSET,
y: point.y + Y_OFFSET
}
let point2 = {
x: point.x + X_OFFSET,
y: point.y + height + Y_OFFSET
}
let point3 = {
x: point.x - width + X_OFFSET,
y: point.y + height - GRADIENT + Y_OFFSET
}
let point4 = {
x: point.x - width + X_OFFSET,
y: point.y + GRADIENT + Y_OFFSET
}
browserCanvasContext.beginPath()
browserCanvasContext.moveTo(point1.x, point1.y)
browserCanvasContext.lineTo(point2.x, point2.y)
browserCanvasContext.lineTo(point3.x, point3.y)
browserCanvasContext.arc(point3.x, point3.y - TAB_CORNERS_RADIUS, TAB_CORNERS_RADIUS, 0.5 * Math.PI, 1.0 * Math.PI)
// browserCanvasContext.lineTo(point4.x, point4.y)
browserCanvasContext.arc(point4.x, point4.y + TAB_CORNERS_RADIUS, TAB_CORNERS_RADIUS, 1.0 * Math.PI, 1.5 * Math.PI)
browserCanvasContext.closePath()
browserCanvasContext.lineWidth = 1
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + opacity + ''
browserCanvasContext.stroke()
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + opacity + ''
browserCanvasContext.fill()
}
}
function recalculateCoordinateSystem () {
let minValue = {
x: MIN_PLOTABLE_DATE.valueOf(),
y: 0
}
let maxValue = {
x: MAX_PLOTABLE_DATE.valueOf(),
y: nextPorwerOf10(MAX_DEFAULT_RATE_SCALE_VALUE) / 4
}
timeMachineCoordinateSystem.initialize(
minValue,
maxValue,
thisObject.container.frame.width,
thisObject.container.frame.height
)
}
}
-424
View File
@@ -1,424 +0,0 @@
function newTimelineChart () {
const MODULE_NAME = 'Timeline Chart'
const INFO_LOG = false
const INTENSIVE_LOG = false
const ERROR_LOG = true
let logger = newWebDebugLog()
logger.fileName = MODULE_NAME
let timeFrame = INITIAL_TIME_PERIOD
let datetime = NEW_SESSION_INITIAL_DATE
let thisObject = {
container: undefined,
fitFunction: undefined,
rateScale: undefined,
timeFrameScale: undefined,
payload: undefined,
layersManager: undefined,
plotterManager: undefined,
upstreamTimeFrame: undefined,
setDatetime: setDatetime,
setTimeFrame: setTimeFrame,
physics: physics,
draw: draw,
drawBackground: drawBackground,
drawForeground: drawForeground,
getContainer: getContainer,
initialize: initialize,
finalize: finalize
}
let timeMachineCoordinateSystem
let timelineChartCoordinateSystem = newCoordinateSystem()
timelineChartCoordinateSystem.name = 'TIMELINE CHART'
let coordinateSystem
let layersPanel
let layersPanelHandle
let onMouseOverEventSuscriptionId
let onMouseNotOverEventSuscriptionId
let rateScaleUpstreamEventSuscriptionId
let rateScaleMouseOverEventSuscriptionId
let timeFrameScaleEventSuscriptionId
let timeFrameScaleMouseOverEventSuscriptionId
let scaleChangedEventSubscriptionId
let drawScales = false
let mouse = {
position: {
x: 0,
y: 0
}
}
setupContainer()
return thisObject
function setupContainer () {
thisObject.container = newContainer()
thisObject.container.initialize(MODULE_NAME)
thisObject.container.detectMouseOver = true
}
function finalize () {
timeMachineCoordinateSystem.eventHandler.stopListening(scaleChangedEventSubscriptionId)
if (thisObject.layersManager !== undefined) {
finalizeLayersManager()
}
if (thisObject.rateScale !== undefined) {
finalizeRateScale()
}
if (thisObject.timeFrameScale !== undefined) {
finalizeTimeFrameScale()
}
thisObject.container.eventHandler.stopListening(onMouseOverEventSuscriptionId)
thisObject.container.eventHandler.stopListening(onMouseNotOverEventSuscriptionId)
thisObject.container.finalize()
thisObject.container = undefined
thisObject.payload = undefined
mouse = undefined
logger = undefined
timeMachineCoordinateSystem = undefined
timelineChartCoordinateSystem.finalize()
timelineChartCoordinateSystem = undefined
coordinateSystem = undefined
layersPanel = undefined
layersPanelHandle = undefined
}
function finalizeLayersManager () {
if (thisObject.plotterManager !== undefined) {
thisObject.plotterManager.finalize()
}
thisObject.plotterManager = undefined
thisObject.layersManager = undefined
canvas.panelsSpace.destroyPanel(layersPanelHandle)
}
function finalizeTimeFrameScale () {
if (thisObject.timeFrameScale === undefined) { return }
thisObject.timeFrameScale.container.eventHandler.stopListening(timeFrameScaleEventSuscriptionId)
thisObject.timeFrameScale.container.eventHandler.stopListening(timeFrameScaleMouseOverEventSuscriptionId)
thisObject.timeFrameScale.finalize()
thisObject.timeFrameScale = undefined
if (thisObject.upstreamTimeFrame !== undefined) {
timeFrame = thisObject.upstreamTimeFrame
if (thisObject.plotterManager !== undefined) {
thisObject.plotterManager.setTimeFrame(timeFrame)
}
}
}
function finalizeRateScale () {
if (thisObject.rateScale === undefined) { return }
thisObject.rateScale.container.eventHandler.stopListening(rateScaleMouseOverEventSuscriptionId)
thisObject.container.parentContainer.eventHandler.stopListening(rateScaleUpstreamEventSuscriptionId)
thisObject.rateScale.finalize()
thisObject.rateScale = undefined
/* Resets the local container with the dimessions of its parent, the Time Machine */
thisObject.container.frame.position.x = 0
thisObject.container.frame.position.y = 0
thisObject.container.frame.height = thisObject.container.parentContainer.frame.height
thisObject.container.frame.width = thisObject.container.parentContainer.frame.width
}
function initialize (pTimeMachineCoordinateSystem, pTimeFrame) {
/* We load the logow we will need for the background. */
timeMachineCoordinateSystem = pTimeMachineCoordinateSystem
coordinateSystem = timeMachineCoordinateSystem
initializeCoordinateSystem()
timeFrame = pTimeFrame
onMouseOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
onMouseNotOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
scaleChangedEventSubscriptionId = timeMachineCoordinateSystem.eventHandler.listenToEvent('Scale Changed', onScaleChanged)
}
function initializeCoordinateSystem () {
let minValue = {
x: timeMachineCoordinateSystem.min.x,
y: 0
}
let maxValue = {
x: timeMachineCoordinateSystem.max.x,
y: nextPorwerOf10(MAX_DEFAULT_RATE_SCALE_VALUE) / 4
}
if (thisObject.rateScale !== undefined) {
minValue.y = thisObject.rateScale.minValue
maxValue.y = thisObject.rateScale.maxValue
}
timelineChartCoordinateSystem.initialize(
minValue,
maxValue,
thisObject.container.frame.width,
thisObject.container.frame.height
)
}
function initializeLayersManager () {
let owner = thisObject.payload.node.payload.parentNode.id // The real owner is the Time Machine
layersPanelHandle = canvas.panelsSpace.createNewPanel('Layers Panel', undefined, owner)
thisObject.layersManager = canvas.panelsSpace.getPanel(layersPanelHandle)
thisObject.layersManager.payload = thisObject.payload.node.layersManager.payload
thisObject.layersManager.initialize()
/* Initialize the Plotter Manager */
thisObject.plotterManager = newPlottersManager()
thisObject.plotterManager.container.connectToParent(thisObject.container, true, true, false, true, true, true, false, false, true)
thisObject.plotterManager.container.frame.position.x = 0
thisObject.plotterManager.container.frame.position.y = 0
thisObject.plotterManager.fitFunction = thisObject.fitFunction
thisObject.plotterManager.payload = thisObject.payload
thisObject.plotterManager.initialize(thisObject.layersManager)
thisObject.plotterManager.setTimeFrame(timeFrame)
thisObject.plotterManager.setDatetime(datetime)
thisObject.plotterManager.setCoordinateSystem(coordinateSystem)
}
function initializeRateScale () {
thisObject.rateScale = newRateScale()
thisObject.rateScale.fitFunction = thisObject.fitFunction
thisObject.rateScale.payload = thisObject.payload.node.rateScale.payload
rateScaleMouseOverEventSuscriptionId = thisObject.rateScale.container.eventHandler.listenToEvent('onMouseOverScale', rateScaleMouseOver)
thisObject.rateScale.initialize(timelineChartCoordinateSystem, thisObject.container.parentContainer, thisObject.container)
function rateScaleMouseOver (event) {
thisObject.container.eventHandler.raiseEvent('onChildrenMouseOver', event)
}
}
function initializeTimeFrameScale () {
thisObject.timeFrameScale = newTimeFrameScale()
thisObject.timeFrameScale.fitFunction = thisObject.fitFunction
thisObject.timeFrameScale.payload = thisObject.payload.node.timeFrameScale.payload
timeFrameScaleEventSuscriptionId = thisObject.timeFrameScale.container.eventHandler.listenToEvent('Time Frame Value Changed', timeFrameScaleValueChanged)
timeFrameScaleMouseOverEventSuscriptionId = thisObject.timeFrameScale.container.eventHandler.listenToEvent('onMouseOverScale', timeFrameScaleMouseOver)
thisObject.timeFrameScale.initialize(thisObject.container.parentContainer)
function timeFrameScaleValueChanged (event) {
let currentTimeFrame = timeFrame
timeFrame = event.timeFrame
if (timeFrame !== currentTimeFrame) {
if (thisObject.plotterManager !== undefined) {
thisObject.plotterManager.setTimeFrame(timeFrame)
}
}
}
function timeFrameScaleMouseOver (event) {
thisObject.container.eventHandler.raiseEvent('onChildrenMouseOver', event)
}
}
function onScaleChanged (event) {
if (thisObject.rateScale !== undefined) {
thisObject.rateScale.onUpstreamScaleChanged(event)
}
timelineChartCoordinateSystem.min.x = timeMachineCoordinateSystem.min.x
timelineChartCoordinateSystem.max.x = timeMachineCoordinateSystem.max.x
timelineChartCoordinateSystem.maxHeight = timeMachineCoordinateSystem.maxHeight
timelineChartCoordinateSystem.maxWidth = timeMachineCoordinateSystem.maxWidth
timelineChartCoordinateSystem.autoMinXScale = timeMachineCoordinateSystem.autoMinXScale
timelineChartCoordinateSystem.autoMaxXScale = timeMachineCoordinateSystem.autoMaxXScale
timelineChartCoordinateSystem.recalculateScale()
}
function setTimeFrame (pTimeFrame) {
timeFrame = pTimeFrame
if (thisObject.plotterManager !== undefined) {
thisObject.plotterManager.setTimeFrame(timeFrame)
}
}
function setDatetime (pDatetime) {
datetime = pDatetime
if (thisObject.plotterManager !== undefined) {
thisObject.plotterManager.setDatetime(datetime)
}
}
function onMouseOver (event) {
/* This event gets to the timelinechart container because it inherits it from the time machine container, which is the one raising Mouse Over and Mouse not Over Events to its children. */
drawScales = true
if (thisObject.rateScale !== undefined) {
thisObject.rateScale.onMouseOverSomeTimeMachineContainer(event)
}
if (thisObject.timeFrameScale !== undefined) {
thisObject.timeFrameScale.onMouseOverSomeTimeMachineContainer(event)
}
mouse.position.x = event.x
mouse.position.y = event.y
}
function onMouseNotOver (event) {
/* This event is inherited from the Time Machine */
drawScales = false
if (thisObject.rateScale !== undefined) {
thisObject.rateScale.visible = false
}
if (thisObject.timeFrameScale !== undefined) {
thisObject.timeFrameScale.visible = false
}
}
function getContainer (point, purpose) {
let container
if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) {
container = thisObject.rateScale.getContainer(point, purpose)
if (container !== undefined) {
if (container.isForThisPurpose(purpose)) {
return container
}
}
}
if (thisObject.timeFrameScale !== undefined && thisObject.timeFrameScale.isVisible === true) {
container = thisObject.timeFrameScale.getContainer(point, purpose)
if (container !== undefined) {
if (container.isForThisPurpose(purpose)) {
return container
}
}
}
return container
}
function physics () {
thisObjectPhysics()
childrenPhysics()
syncWithDesignerScales()
syncWithDesignerLayersManager()
}
function thisObjectPhysics () {
/* Only if the plotter manager has some layer turned on, we will pass the min and max upstream. */
if (thisObject.plotterManager !== undefined && thisObject.plotterManager.connectors.length > 0) {
timelineChartCoordinateSystem.reportParentXValue(timeMachineCoordinateSystem.min.x, timeMachineCoordinateSystem.max.x)
timelineChartCoordinateSystem.physics()
timeMachineCoordinateSystem.reportXValue(timelineChartCoordinateSystem.childrenMin.x)
timeMachineCoordinateSystem.reportXValue(timelineChartCoordinateSystem.childrenMax.x)
}
}
function syncWithDesignerLayersManager () {
if (thisObject.payload.node === undefined) {
finalizeLayersManager()
return
}
if (thisObject.payload.node.layersManager === undefined && thisObject.layersManager !== undefined) {
finalizeLayersManager()
}
if (thisObject.payload.node.layersManager !== undefined && thisObject.layersManager === undefined) {
initializeLayersManager()
}
}
function syncWithDesignerScales () {
if (thisObject.payload.node === undefined) {
finalizeRateScale()
finalizeTimeFrameScale()
return
}
if (thisObject.payload.node.rateScale === undefined && thisObject.rateScale !== undefined) {
finalizeRateScale()
coordinateSystem = timeMachineCoordinateSystem
if (thisObject.plotterManager !== undefined) {
thisObject.plotterManager.setCoordinateSystem(coordinateSystem)
}
}
if (thisObject.payload.node.rateScale !== undefined && thisObject.rateScale === undefined) {
initializeRateScale()
coordinateSystem = timelineChartCoordinateSystem
if (thisObject.plotterManager !== undefined) {
thisObject.plotterManager.setCoordinateSystem(coordinateSystem)
}
}
if (thisObject.payload.node.timeFrameScale === undefined && thisObject.timeFrameScale !== undefined) {
finalizeTimeFrameScale()
}
if (thisObject.payload.node.timeFrameScale !== undefined && thisObject.timeFrameScale === undefined) {
initializeTimeFrameScale()
}
}
function childrenPhysics () {
if (thisObject.rateScale !== undefined) {
thisObject.rateScale.layersOn = thisObject.plotterManager.connectors.length
thisObject.rateScale.physics()
}
if (thisObject.timeFrameScale !== undefined) {
thisObject.timeFrameScale.layersOn = thisObject.plotterManager.connectors.length
thisObject.timeFrameScale.physics()
}
}
function drawBackground () {
if (thisObject.container.frame.isInViewPort()) {
if (drawScales === true) {
if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) { thisObject.rateScale.drawBackground() }
}
drawChartsBackground()
if (thisObject.plotterManager !== undefined) {
let elementsPlotted = thisObject.plotterManager.draw()
if (thisObject.timeFrameScale !== undefined) {
thisObject.timeFrameScale.adjustTimeFrame(elementsPlotted)
} else {
return elementsPlotted
}
}
}
}
function draw () {
if (thisObject.container.frame.isInViewPort()) {
if (drawScales === true) {
if (thisObject.timeFrameScale !== undefined && thisObject.timeFrameScale.isVisible === true) { thisObject.timeFrameScale.draw() }
if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) { thisObject.rateScale.draw() }
}
}
}
function drawForeground () {
if (thisObject.container.frame.isInViewPort()) {
if (drawScales === true) {
if (thisObject.timeFrameScale !== undefined && thisObject.timeFrameScale.isVisible === true) { thisObject.timeFrameScale.drawForeground() }
if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) { thisObject.rateScale.drawForeground() }
}
}
}
function drawChartsBackground () {
drawContainerBackground(thisObject.container, UI_COLOR.WHITE, 0, thisObject.fitFunction)
}
}
-421
View File
@@ -1,421 +0,0 @@
function newViewport () {
const MODULE_NAME = 'Viewport'
const MIN_ZOOM_LEVEL = 0
const MAX_ZOOM_LEVEL = 500
let ANIMATION_INCREMENT = 0.25
let ANIMATION_STEPS = 5
let TOP_MARGIN = 40 + TOP_SPACE_HEIGHT
let BOTTOM_MARGIN = 42 + COCKPIT_SPACE_HEIGHT
let LEFT_MARGIN = 0
let RIGHT_MARGIN = 0
let MARGINS = {
TOP: TOP_MARGIN,
BOTTOM: BOTTOM_MARGIN,
LEFT: LEFT_MARGIN,
RIGHT: RIGHT_MARGIN
}
let thisObject = {
visible: false,
visibleArea: undefined,
width: undefined,
height: undefined,
eventHandler: undefined,
zoomTargetLevel: undefined,
zoomLevel: undefined,
mousePosition: undefined,
margins: MARGINS,
payload: undefined,
zoomAtCenter: zoomAtCenter,
changeZoom: changeZoom,
onMouseWheel: onMouseWheel,
transformThisPoint: transformThisPoint,
unTransformThisPoint: unTransformThisPoint,
isThisPointVisible: isThisPointVisible,
isThisPointInViewport: isThisPointInViewport,
fitIntoVisibleArea: fitIntoVisibleArea,
fitIntoViewport: fitIntoViewport,
displace: displace,
displaceToContainer: displaceToContainer,
physics: physics,
raiseEvents: raiseEvents,
resize: resize,
initialize: initialize,
finalize: finalize
}
let increment = 0.035
let position = {
x: 0,
y: 0
}
thisObject.mousePosition = {
x: 0,
y: 0
}
thisObject.eventHandler = newEventHandler()
/* Initial default value */
thisObject.zoomLevel = MIN_ZOOM_LEVEL
thisObject.zoomTargetLevel = Math.round(MIN_ZOOM_LEVEL)
INITIAL_TIME_PERIOD = recalculatePeriod(thisObject.zoomLevel)
let overrideMousePositionCounter = 0
return thisObject
function finalize () {
thisObject.eventHandler.finalize()
thisObject.payload = undefined
thisObject = undefined
}
function initialize () {
if (thisObject.payload !== undefined) {
/* Read the position from the frame structure */
let frame = {
position: {
x: 0,
y: 0
}
}
loadFrame(thisObject.payload, frame)
if (!isNaN(frame.position.x)) {
position.x = frame.position.x
}
if (!isNaN(frame.position.y)) {
position.y = frame.position.y
}
}
resize()
readObjectState()
}
function resize () {
TOP_MARGIN = 40 + TOP_SPACE_HEIGHT
BOTTOM_MARGIN = 42 + browserCanvas.height - COCKPIT_SPACE_POSITION
LEFT_MARGIN = 0
RIGHT_MARGIN = 0
MARGINS = {
TOP: TOP_MARGIN,
BOTTOM: BOTTOM_MARGIN,
LEFT: LEFT_MARGIN,
RIGHT: RIGHT_MARGIN
}
thisObject.visibleArea = {
topLeft: { x: LEFT_MARGIN, y: TOP_MARGIN },
topRight: { x: browserCanvas.width - RIGHT_MARGIN, y: TOP_MARGIN },
bottomRight: { x: browserCanvas.width - RIGHT_MARGIN, y: browserCanvas.height - BOTTOM_MARGIN},
bottomLeft: { x: LEFT_MARGIN, y: browserCanvas.height - BOTTOM_MARGIN}
}
thisObject.width = thisObject.visibleArea.topRight.x - thisObject.visibleArea.topLeft.x
thisObject.height = thisObject.visibleArea.bottomRight.y - thisObject.visibleArea.topLeft.y
thisObject.center = {
x: LEFT_MARGIN + thisObject.width / 2,
y: TOP_MARGIN + thisObject.height / 2
}
}
function raiseEvents () {
if (thisObject.visible === false) { return }
let event = {
newPosition: position
}
thisObject.eventHandler.raiseEvent('Position Changed', event)
}
function displaceToContainer (container) {
let targetPoint = {
x: -container.frame.position.x - container.frame.width / 2,
y: -container.frame.position.y - container.frame.height / 2
}
position.x = targetPoint.x + browserCanvas.width / 2
position.y = targetPoint.y + (COCKPIT_SPACE_POSITION - TOP_SPACE_HEIGHT) / 2 + TOP_SPACE_HEIGHT
}
function zoomAtCenter (level) {
thisObject.zoomTargetLevel = Math.round(level)
overrideMousePositionCounter = 50
ANIMATION_INCREMENT = 0.5
}
function mousePositionPhysics () {
if (overrideMousePositionCounter > 0) {
thisObject.mousePosition.x = browserCanvas.width / 2
thisObject.mousePosition.y = (COCKPIT_SPACE_POSITION - TOP_SPACE_HEIGHT) / 2 + TOP_SPACE_HEIGHT
overrideMousePositionCounter--
if (overrideMousePositionCounter < 0) {
overrideMousePositionCounter = 0
}
}
}
function physics () {
if (thisObject.visible === false) { return }
mousePositionPhysics()
animationPhysics()
positioningPhysics()
readObjectState()
}
function positioningPhysics () {
if (thisObject.visible === false) { return }
if (thisObject.payload === undefined) { return }
/* Save the position at the frame lavel */
let frame = {}
frame.position = position
saveFrame(thisObject.payload, frame)
}
function animationPhysics () {
if (thisObject.zoomLevel < thisObject.zoomTargetLevel) {
if (thisObject.zoomTargetLevel - thisObject.zoomLevel < ANIMATION_INCREMENT) {
ANIMATION_INCREMENT = Math.round(Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel) * 100) / 100
}
thisObject.zoomLevel = Math.round((thisObject.zoomLevel + ANIMATION_INCREMENT) * 100) / 100
changeZoom(thisObject.zoomLevel - ANIMATION_INCREMENT, thisObject.zoomLevel)
}
if (thisObject.zoomLevel > thisObject.zoomTargetLevel) {
if (thisObject.zoomLevel - thisObject.zoomTargetLevel < ANIMATION_INCREMENT) {
ANIMATION_INCREMENT = Math.round(Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel) * 100) / 100
}
thisObject.zoomLevel = Math.round((thisObject.zoomLevel - ANIMATION_INCREMENT) * 100) / 100
changeZoom(thisObject.zoomLevel + ANIMATION_INCREMENT, thisObject.zoomLevel)
}
}
function onMouseWheel (event) {
if (thisObject.visible === false) { return }
if ((event.ctrlKey === true || event.metaKey === true)) { return }
let morePower = 1
if (IS_MAC) {
event.delta = event.delta * MAC_AMOUNT_FACTOR
}
let amount = event.delta
if (event.buttons === 4) { morePower = 2 } // Mouse wheel pressed.
/* We adjust the sensitivity for Mac Users */
if (thisObject.zoomTargetLevel > 10) {
amount = amount * 2
}
if (thisObject.zoomTargetLevel > 25) {
amount = amount * 3
}
if (thisObject.zoomTargetLevel > 50) {
amount = amount * 3.5
}
if (thisObject.zoomTargetLevel + amount * morePower > MAX_ZOOM_LEVEL) {
return false
}
if (thisObject.zoomTargetLevel + amount * morePower < MIN_ZOOM_LEVEL) {
return false
}
thisObject.zoomTargetLevel = Math.round(thisObject.zoomTargetLevel + amount * morePower)
ANIMATION_INCREMENT = Math.round(Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel) / ANIMATION_STEPS * 100) / 100
let newEvent = {
newLevel: thisObject.zoomTargetLevel,
newPosition: position,
type: undefined,
shiftKey: event.shiftKey
}
if (amount > 0) {
newEvent.type = 'Zoom In'
} else {
newEvent.type = 'Zoom Out'
}
thisObject.eventHandler.raiseEvent('Zoom Changed', newEvent)
return true
}
function fitIntoVisibleArea (point) {
let pointCopy = {
x: point.x,
y: point.y
}
/* Here we check the boundaries of the resulting points, so they dont go out of the visible area. */
if (pointCopy.x > thisObject.visibleArea.bottomRight.x + 1) {
pointCopy.x = thisObject.visibleArea.bottomRight.x + 1
}
if (pointCopy.x < thisObject.visibleArea.topLeft.x - 1) {
pointCopy.x = thisObject.visibleArea.topLeft.x - 1
}
if (pointCopy.y > thisObject.visibleArea.bottomRight.y + 1) {
pointCopy.y = thisObject.visibleArea.bottomRight.y + 1
}
if (pointCopy.y < thisObject.visibleArea.topLeft.y - 1) {
pointCopy.y = thisObject.visibleArea.topLeft.y - 1
}
return pointCopy
}
function fitIntoViewport (point) {
let pointCopy = {
x: point.x,
y: point.y
}
if (pointCopy.y > COCKPIT_SPACE_POSITION) {
pointCopy.y = COCKPIT_SPACE_POSITION
}
return pointCopy
}
function displace (displaceVector, recalculate) {
if (thisObject.visible === false) { return }
position.x = position.x + displaceVector.x
position.y = position.y + displaceVector.y
saveObjectState()
let event = {
newPosition: position,
recalculate: recalculate
}
thisObject.eventHandler.raiseEvent('Position Changed', event)
}
function changeZoom (oldLevel, newLevel) {
if (thisObject.visible === false) { return }
let oldMouse = unTransformThisPoint(thisObject.mousePosition, oldLevel)
let newMouse = transformThisPoint(oldMouse, newLevel)
position.x = position.x - newMouse.x + thisObject.mousePosition.x
position.y = position.y - newMouse.y + thisObject.mousePosition.y
saveObjectState()
thisObject.eventHandler.raiseEvent('Zoom Changed')
}
function transformThisPoint (point, level) {
if (thisObject.visible === false) { return }
let transformedPoint = {
x: 0,
y: 0
}
if (level === undefined) {
transformedPoint.x = point.x * (1 + thisObject.zoomLevel) + position.x
transformedPoint.y = point.y * (1 + thisObject.zoomLevel) + position.y
} else {
transformedPoint.x = point.x * (1 + level) + position.x
transformedPoint.y = point.y * (1 + level) + position.y
}
return transformedPoint
}
function unTransformThisPoint (point, level) {
let pointWithoutZoom = {
x: 0,
y: 0
}
if (level === undefined) {
pointWithoutZoom.x = (point.x - position.x) / (1 + thisObject.zoomLevel)
pointWithoutZoom.y = (point.y - position.y) / (1 + thisObject.zoomLevel)
} else {
pointWithoutZoom.x = (point.x - position.x) / (1 + level)
pointWithoutZoom.y = (point.y - position.y) / (1 + level)
}
return pointWithoutZoom
}
function isThisPointVisible (point) {
if (thisObject.visible === false) { return }
if (point.x < thisObject.visibleArea.topLeft.x || point.x > thisObject.visibleArea.bottomRight.x || point.y < thisObject.visibleArea.topLeft.y || point.y > thisObject.visibleArea.bottomRight.y) {
return false
} else {
return true
}
}
function isThisPointInViewport (point) {
if (thisObject.visible === false) { return }
if (point.y > COCKPIT_SPACE_POSITION) {
return false
} else {
return true
}
}
function saveObjectState () {
if (thisObject.payload === undefined) { return }
/* Save the zoom at the node config, so that the user can change it if he wishes to. */
try {
let code = JSON.parse(thisObject.payload.node.code)
code.zoom = (thisObject.zoomTargetLevel - MIN_ZOOM_LEVEL) / (MAX_ZOOM_LEVEL - MIN_ZOOM_LEVEL) * 100
code.zoom = code.zoom.toFixed(2)
thisObject.payload.node.code = JSON.stringify(code)
} catch (err) {
// we ignore errors here since most likely they will be parsing errors.
}
}
function readObjectState () {
if (thisObject.payload === undefined) { return }
/* Read the zoom level from the node config */
try {
let code = JSON.parse(thisObject.payload.node.code)
if (isNaN(code.zoom) || code.zoom === null || code.zoom === undefined) {
saveObjectState()
return
}
code.zoom = code.zoom / 100 * (MAX_ZOOM_LEVEL - MIN_ZOOM_LEVEL) + MIN_ZOOM_LEVEL
if (code.zoom < MIN_ZOOM_LEVEL) { code.zoom = MIN_ZOOM_LEVEL }
if (code.zoom > MAX_ZOOM_LEVEL) { code.zoom = MAX_ZOOM_LEVEL }
if (code.zoom.toFixed(2) !== thisObject.zoomTargetLevel.toFixed(2)) {
newZoomLevel(code.zoom)
} else {
saveObjectState()
}
} catch (err) {
// we ignore errors here since most likely they will be parsing errors.
}
function newZoomLevel (level) {
thisObject.zoomLevel = Math.round(level)
thisObject.zoomTargetLevel = Math.round(level)
INITIAL_TIME_PERIOD = recalculatePeriod(level)
saveObjectState()
ANIMATION_INCREMENT = 0
let event = {
newLevel: thisObject.zoomTargetLevel,
newPosition: position,
type: undefined
}
thisObject.eventHandler.raiseEvent('Zoom Changed', event)
return true
}
}
}
-123
View File
@@ -1,123 +0,0 @@
function newAssetalances () {
const MODULE_NAME = 'Asset Balances'
let thisObject = {
visible: true,
container: undefined,
paramsArray: undefined,
setParamsArray: setParamsArray,
physics: physics,
draw: draw,
speedometers: [],
getContainer: getContainer,
initialize: initialize,
finalize: finalize
}
thisObject.container = newContainer()
thisObject.container.initialize(MODULE_NAME)
thisObject.container.isDraggeable = false
thisObject.container.isWheelable = false
return thisObject
function finalize () {
for (let i = 0; i < thisObject.speedometers.length; i++) {
let speedometer = thisObject.speedometers[i]
speedometer.finalize()
}
thisObject.container.finalize()
thisObject.container = undefined
thisObject.paramsArray = undefined
}
function initialize () {
for (let i = 0; i < 2; i++) {
let speedometer = newSpeedometer()
speedometer.initialize()
speedometer.container.connectToParent(thisObject.container)
speedometer.container.frame.position.x = thisObject.container.frame.width / 2
speedometer.container.frame.position.y = thisObject.container.frame.height * (2 + i * 2) / 5
thisObject.speedometers.push(speedometer)
}
}
function getContainer (point, purpose) {
if (thisObject.visible !== true) { return }
let container
for (let i = 0; i < thisObject.speedometers.length; i++) {
container = thisObject.speedometers[i].getContainer(point, purpose)
if (container !== undefined) {
if (container.isForThisPurpose(purpose)) {
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
return container
}
}
}
}
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
return thisObject.container
} else {
return undefined
}
}
function setParamsArray (paramsArray) {
thisObject.paramsArray = paramsArray
for (let i = 0; i < thisObject.speedometers.length; i++) {
let speedometer = thisObject.speedometers[i]
speedometer.params = paramsArray[i]
}
}
function physics () {
}
function draw () {
if (thisObject.visible !== true) { return }
for (let i = 0; i < thisObject.speedometers.length; i++) {
let speedometer = thisObject.speedometers[i]
speedometer.draw()
}
drawQuotedAssetalances()
}
function drawQuotedAssetalances () {
if (thisObject.paramsArray === undefined) { return }
let fontSize
let label
let xOffset
let yOffset
const OPACITY = 1
/* We put the params.VALUE in the middle */
fontSize = 15
browserCanvasContext.font = 'bold ' + fontSize + 'px ' + UI_FONT.PRIMARY
label = 'ASSET BALANCES'
xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO
yOffset = -45 + 9
labelPoint = {
x: 0 - xOffset + (thisObject.paramsArray[1].LEFT_OFFSET - thisObject.paramsArray[0].LEFT_OFFSET) / 2 + thisObject.paramsArray[0].LEFT_OFFSET - 20,
y: COCKPIT_SPACE_POSITION - COCKPIT_SPACE_HEIGHT / 2 - yOffset
}
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + OPACITY + ')'
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
}
}
-169
View File
@@ -1,169 +0,0 @@
function newFullScreen () {
const MODULE_NAME = 'Fullscreen'
let thisObject = {
visible: true,
container: undefined,
status: undefined,
physics: physics,
draw: draw,
getContainer: getContainer,
initialize: initialize,
finalize: finalize
}
thisObject.container = newContainer()
thisObject.container.initialize(MODULE_NAME)
thisObject.container.isDraggeable = false
thisObject.container.isWheelable = false
thisObject.container.isClickeable = true
thisObject.container.detectMouseOver = true
let selfMouseOverEventSubscriptionId
let selfMouseClickEventSubscriptionId
let selfMouseNotOverEventSubscriptionId
let isMouseOver = false
let counterTillNextState = 0
let layersToTurnOn = []
return thisObject
function finalize () {
thisObject.container.eventHandler.stopListening(selfMouseOverEventSubscriptionId)
thisObject.container.eventHandler.stopListening(selfMouseClickEventSubscriptionId)
thisObject.container.eventHandler.stopListening(selfMouseNotOverEventSubscriptionId)
thisObject.container.finalize()
thisObject.container = undefined
}
function initialize () {
thisObject.container.frame.width = 50
thisObject.container.frame.height = COCKPIT_SPACE_HEIGHT - 12
selfMouseOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
selfMouseClickEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick)
selfMouseNotOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
thisObject.status = 'Ready'
}
function getContainer (point, purpose) {
if (thisObject.visible !== true) { return }
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
return thisObject.container
} else {
return undefined
}
}
function onMouseOver (point) {
if (thisObject.container.frame.isThisPointHere(point, true, false) === true) {
isMouseOver = true
} else {
isMouseOver = false
}
}
function onMouseNotOver (point) {
isMouseOver = false
}
function onMouseClick (event) {
if (thisObject.status !== 'On') {
thisObject.status = 'On'
goFullscreen()
CURRENT_TOP_MARGIN = 0
AT_FULL_SCREEN_MODE = true
} else {
thisObject.status = 'Off'
goOutFullscreen()
CURRENT_TOP_MARGIN = window.canvasApp.topMargin
AT_FULL_SCREEN_MODE = false
}
}
function goFullscreen () {
if (browserCanvas.requestFullscreen) {
browserCanvas.requestFullscreen()
} else if (browserCanvas.mozRequestFullScreen) {
browserCanvas.mozRequestFullScreen()
} else if (browserCanvas.webkitRequestFullscreen) {
browserCanvas.webkitRequestFullscreen()
} else if (browserCanvas.msRequestFullscreen) { browserCanvas.msRequestFullscreen() }
}
function goOutFullscreen () {
if (document.exitFullscreen) {
document.exitFullscreen()
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen()
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen()
} else if (document.msExitFullscreen) { document.msExitFullscreen() }
}
function physics () {
positionPhysics()
}
function positionPhysics () {
thisObject.container.frame.position.x = thisObject.container.parentContainer.frame.width - thisObject.container.frame.width
thisObject.container.frame.position.y = 6
}
function draw () {
if (thisObject.visible !== true) { return }
drawBackground()
drawText()
}
function drawBackground () {
let params = {
cornerRadius: 3,
lineWidth: 0.01,
container: thisObject.container,
borderColor: UI_COLOR.DARK,
castShadow: false,
opacity: 1
}
if (isMouseOver === true) {
params.backgroundColor = UI_COLOR.TURQUOISE
} else {
params.backgroundColor = UI_COLOR.DARK_TURQUOISE
}
roundedCornersBackground(params)
}
function drawText () {
let fontSize
let label
let xOffset
let yOffset
const OPACITY = 1
/* We put the params.VALUE in the middle */
fontSize = 15
browserCanvasContext.font = 'bold ' + fontSize + 'px ' + UI_FONT.PRIMARY
label = 'FS'
let labelPoint = {
x: thisObject.container.frame.width / 2 - label.length / 2 * fontSize * FONT_ASPECT_RATIO,
y: thisObject.container.frame.height - 9
}
labelPoint = thisObject.container.frame.frameThisPoint(labelPoint)
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + OPACITY + ')'
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
}
}
-261
View File
@@ -1,261 +0,0 @@
function newSpeedometer () {
const MODULE_NAME = 'Speedometer'
let thisObject = {
visible: true,
container: undefined,
params: undefined,
physics: physics,
draw: draw,
getContainer: getContainer,
initialize: initialize,
finalize: finalize
}
thisObject.container = newContainer()
thisObject.container.initialize(MODULE_NAME)
thisObject.container.isDraggeable = false
thisObject.container.isWheelable = false
return thisObject
function finalize () {
thisObject.container.finalize()
thisObject.container = undefined
thisObject.params = undefined
}
function initialize () {
}
function getContainer (point, purpose) {
if (thisObject.visible !== true) { return }
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
return thisObject.container
} else {
return undefined
}
}
function physics () {
}
function draw () {
if (thisObject.params === undefined) { return }
drawAssetCircle()
}
function drawAssetCircle () {
const RED_LINE_HIGHT = 2
const RADIUS = 50
const OPACITY = 1
let centerPoint = {
x: 0,
y: 0
}
centerPoint = thisObject.container.frame.frameThisPoint(centerPoint)
browserCanvasContext.beginPath()
browserCanvasContext.arc(centerPoint.x, centerPoint.y, RADIUS + RED_LINE_HIGHT, 0 * Math.PI, 2.0 * Math.PI)
browserCanvasContext.closePath()
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + OPACITY + ')'
browserCanvasContext.fill()
browserCanvasContext.beginPath()
browserCanvasContext.arc(centerPoint.x, centerPoint.y, RADIUS, 0.0 * Math.PI, 2.0 * Math.PI)
browserCanvasContext.closePath()
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.DARK_TURQUOISE + ', ' + OPACITY + ')'
browserCanvasContext.fill()
/* We draw the circle bar */
const DEFAULT_THICKNESS = 2
const VALUE_THICKNESS = 8
const VALUE_BG_THICKNESS = 1
const BAR_RADIUS = RADIUS * 0.85
let BAR_START_ANGLE = 0.85 * Math.PI
let BAR_END_ANGLE = 2.15 * Math.PI
let CURRENT_VALUE_ANGLE = thisObject.params.VALUE * (BAR_END_ANGLE - BAR_START_ANGLE) / thisObject.params.MAX_VALUE + BAR_START_ANGLE
let MIN_VALUE_ANGLE = thisObject.params.MIN_VALUE * (BAR_END_ANGLE - BAR_START_ANGLE) / thisObject.params.MAX_VALUE + BAR_START_ANGLE
let INIT_VALUE_ANGLE = thisObject.params.INIT_VALUE * (BAR_END_ANGLE - BAR_START_ANGLE) / thisObject.params.MAX_VALUE + BAR_START_ANGLE
let PROFIT_VALUE_ANGLE = CURRENT_VALUE_ANGLE
if (CURRENT_VALUE_ANGLE > INIT_VALUE_ANGLE) { CURRENT_VALUE_ANGLE = INIT_VALUE_ANGLE }
if (CURRENT_VALUE_ANGLE < MIN_VALUE_ANGLE) { CURRENT_VALUE_ANGLE = MIN_VALUE_ANGLE }
if (PROFIT_VALUE_ANGLE > BAR_END_ANGLE) { PROFIT_VALUE_ANGLE = BAR_END_ANGLE }
if (
thisObject.params.VALUE > 0 &&
thisObject.params.ASSET_NAME === thisObject.params.BASE_ASSET &&
thisObject.params.POSITION_TAKEN === false
) {
browserCanvasContext.setLineDash([0, 0])
browserCanvasContext.beginPath()
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIUS, BAR_START_ANGLE, MIN_VALUE_ANGLE)
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = VALUE_BG_THICKNESS
browserCanvasContext.stroke()
browserCanvasContext.closePath()
browserCanvasContext.beginPath()
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIUS, MIN_VALUE_ANGLE, CURRENT_VALUE_ANGLE)
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = VALUE_BG_THICKNESS
browserCanvasContext.stroke()
browserCanvasContext.closePath()
browserCanvasContext.beginPath()
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIUS, CURRENT_VALUE_ANGLE, INIT_VALUE_ANGLE)
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RED + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = VALUE_BG_THICKNESS
browserCanvasContext.stroke()
browserCanvasContext.closePath()
if (PROFIT_VALUE_ANGLE > INIT_VALUE_ANGLE) {
browserCanvasContext.beginPath()
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIUS, INIT_VALUE_ANGLE, PROFIT_VALUE_ANGLE)
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.GREEN + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = VALUE_BG_THICKNESS
browserCanvasContext.stroke()
browserCanvasContext.closePath()
}
browserCanvasContext.setLineDash([2, 3])
browserCanvasContext.beginPath()
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIUS, BAR_START_ANGLE, MIN_VALUE_ANGLE)
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = VALUE_THICKNESS
browserCanvasContext.stroke()
browserCanvasContext.closePath()
browserCanvasContext.beginPath()
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIUS, MIN_VALUE_ANGLE, CURRENT_VALUE_ANGLE)
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = VALUE_THICKNESS
browserCanvasContext.stroke()
browserCanvasContext.closePath()
browserCanvasContext.beginPath()
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIUS, CURRENT_VALUE_ANGLE, INIT_VALUE_ANGLE)
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RED + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = VALUE_THICKNESS
browserCanvasContext.stroke()
browserCanvasContext.closePath()
if (PROFIT_VALUE_ANGLE > INIT_VALUE_ANGLE) {
browserCanvasContext.beginPath()
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIUS, INIT_VALUE_ANGLE, PROFIT_VALUE_ANGLE)
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.GREEN + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = VALUE_THICKNESS
browserCanvasContext.stroke()
browserCanvasContext.closePath()
}
}
/* Common Variables */
let fontSize
let label
let xOffset
let yOffset
/* We put the thisObject.params.VALUE in the middle */
fontSize = 22
if (thisObject.params.VALUE > 999) {
fontSize = 18
}
if (thisObject.params.VALUE > 9999) {
fontSize = 14
}
if (thisObject.params.VALUE > 99999) {
fontSize = 10
}
browserCanvasContext.font = 'bold ' + fontSize + 'px ' + UI_FONT.PRIMARY
label = thisObject.params.VALUE
if (isNaN(label) === false) {
label = Number(label)
label = dynamicDecimals(label, 2)
if (label === 0) { label = label.toFixed(2) }
}
// label = label.substring(0, 6)
xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO + 7
labelPoint = {
x: centerPoint.x - xOffset,
y: centerPoint.y
}
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + OPACITY + ')'
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
/* We put the top label */
fontSize = 12
browserCanvasContext.font = 'bold ' + fontSize + 'px ' + UI_FONT.PRIMARY
label = thisObject.params.ASSET_LABEL
xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO + 3
yOffset = 22
labelPoint = {
x: centerPoint.x - xOffset,
y: centerPoint.y - yOffset
}
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + OPACITY + ')'
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
/* We put the bottom label */
fontSize = 12
browserCanvasContext.font = 'bold ' + fontSize + 'px ' + UI_FONT.PRIMARY
label = thisObject.params.ASSET_NAME + ' '
xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO + 3
yOffset = -15
labelPoint = {
x: centerPoint.x - xOffset,
y: centerPoint.y - yOffset
}
if (thisObject.params.ASSET_NAME === thisObject.params.BASE_ASSET) {
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + OPACITY + ')'
} else {
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + OPACITY + ')'
}
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
}
}
-262
View File
@@ -1,262 +0,0 @@
function newContainer () {
let thisObject = {
id: newUniqueId(),
type: 'Rectangle',
frame: undefined,
eventHandler: undefined,
parentContainer: undefined,
isDraggeable: true,
notDraggingOnX: false,
notDraggingOnY: false,
isClickeable: false,
isWheelable: false,
detectMouseOver: false,
name: undefined,
fitFunction: undefined,
isVisibleFunction: undefined,
displace: displace,
initialize: initialize,
finalize: finalize,
connectToParent: connectToParent,
isForThisPurpose: isForThisPurpose
}
let connectedToParentWidth = false
let connectedToParentHeight = false
let connectedToParentRadius = false
let onDimmensionsChangedParentEvent = false
let onMouseOverParentEvent = false
let onMouseNotOverParentEvent = false
let onFocusParentEvent = false
let onNotFocusParentEvent = false
let onDisplaceParentEvent = false
let onDragStartedParentEvent = false
let onDragFinishedParentEvent = false
let isConnectedToParent = false
let dimensionsChangedEventSubscriptionId
let onMouseOverEventSubscriptionId
let onMouseNotOverEventSubscriptionId
let onFocusEventSubscriptionId
let onNotFocusEventSubscriptionId
let onDisplaceEventSubscriptionId
let onDragStartedEventSubscriptionId
let onDragFinishedEventSubscriptionId
return thisObject
function finalize () {
if (isConnectedToParent === true) {
thisObject.parentContainer.eventHandler.stopListening(dimensionsChangedEventSubscriptionId)
thisObject.parentContainer.eventHandler.stopListening(onMouseOverEventSubscriptionId)
thisObject.parentContainer.eventHandler.stopListening(onMouseNotOverEventSubscriptionId)
thisObject.parentContainer.eventHandler.stopListening(onFocusEventSubscriptionId)
thisObject.parentContainer.eventHandler.stopListening(onNotFocusEventSubscriptionId)
thisObject.parentContainer.eventHandler.stopListening(onDisplaceEventSubscriptionId)
thisObject.parentContainer.eventHandler.stopListening(onDragStartedEventSubscriptionId)
thisObject.parentContainer.eventHandler.stopListening(onDragFinishedEventSubscriptionId)
thisObject.parentContainer = undefined
thisObject.eventHandler.finalize()
thisObject.frame.finalize()
}
}
function initialize (pName, pType) {
thisObject.name = pName
thisObject.type = pType
thisObject.frame = newFrame()
thisObject.frame.initialize(pType)
if (pName !== undefined) {
thisObject.frame.containerName = pName
}
thisObject.frame.container = thisObject
thisObject.eventHandler = newEventHandler()
thisObject.eventHandler.name = pName
}
function connectToParent (
parentContainer,
onWidth,
onHeight,
onRadius,
onDimmensionsChangedEvent,
onMouseOverEvent,
onMouseNotOverEvent,
onFocusEvent,
onNotFocusEvent,
onDisplaceEvent,
onDragStartedEvent,
onDragFinishedEvent
) {
connectedToParentWidth = onWidth
connectedToParentHeight = onHeight
connectedToParentRadius = onRadius
onDimmensionsChangedParentEvent = onDimmensionsChangedEvent
onMouseOverParentEvent = onMouseOverEvent
onMouseNotOverParentEvent = onMouseNotOverEvent
onFocusParentEvent = onFocusEvent
onNotFocusParentEvent = onNotFocusEvent
onDisplaceParentEvent = onDisplaceEvent
onDragStartedParentEvent = onDragStartedEvent
onDragFinishedParentEvent = onDragFinishedEvent
isConnectedToParent = true
thisObject.frame.parentFrame = parentContainer.frame
thisObject.parentContainer = parentContainer
if (onDimmensionsChangedParentEvent === true) {
dimensionsChangedEventSubscriptionId = thisObject.parentContainer.eventHandler.listenToEvent('Dimmensions Changed', onParentDimmensionsChanged)
}
if (onMouseOverParentEvent === true) {
onMouseOverEventSubscriptionId = thisObject.parentContainer.eventHandler.listenToEvent('onMouseOver', onMouseOver)
}
if (onMouseNotOverParentEvent === true) {
onMouseNotOverEventSubscriptionId = thisObject.parentContainer.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
}
if (onFocusParentEvent === true) {
onFocusEventSubscriptionId = thisObject.parentContainer.eventHandler.listenToEvent('onFocus', onFocus)
}
if (onNotFocusParentEvent === true) {
onNotFocusEventSubscriptionId = thisObject.parentContainer.eventHandler.listenToEvent('onNotFocus', onNotFocus)
}
if (onDisplaceParentEvent === true) {
onDisplaceEventSubscriptionId = thisObject.parentContainer.eventHandler.listenToEvent('onDisplace', onDisplace)
}
if (onDragStartedParentEvent === true) {
onDragStartedEventSubscriptionId = thisObject.parentContainer.eventHandler.listenToEvent('onDragStarted', onDragStarted)
}
if (onDragFinishedParentEvent === true) {
onDragFinishedEventSubscriptionId = thisObject.parentContainer.eventHandler.listenToEvent('onDragFinished', onDragFinished)
}
if (connectedToParentWidth) {
thisObject.frame.width = thisObject.parentContainer.frame.width
}
if (connectedToParentHeight) {
thisObject.frame.height = thisObject.parentContainer.frame.height
}
if (connectedToParentRadius) {
thisObject.frame.radius = thisObject.parentContainer.frame.radius
}
}
function onParentDimmensionsChanged (event) {
let dimmensionsChanged = false
if (connectedToParentWidth) {
thisObject.frame.width = thisObject.parentContainer.frame.width
dimmensionsChanged = true
}
if (connectedToParentHeight) {
thisObject.frame.height = thisObject.parentContainer.frame.height
dimmensionsChanged = true
}
if (connectedToParentRadius) {
thisObject.frame.radius = thisObject.parentContainer.frame.radius
dimmensionsChanged = true
}
if (dimmensionsChanged) {
thisObject.eventHandler.raiseEvent('Dimmensions Changed', event)
}
}
function onMouseOver (event) {
thisObject.eventHandler.raiseEvent('onMouseOver', event)
}
function onMouseNotOver (event) {
thisObject.eventHandler.raiseEvent('onMouseNotOver', event)
}
function onFocus (event) {
thisObject.eventHandler.raiseEvent('onFocus', event)
}
function onNotFocus (event) {
thisObject.eventHandler.raiseEvent('onNotFocus', event)
}
function onDisplace (event) {
thisObject.eventHandler.raiseEvent('onDisplace', event)
}
function onDragStarted (event) {
thisObject.eventHandler.raiseEvent('onDragStarted', event)
}
function onDragFinished (event) {
thisObject.eventHandler.raiseEvent('onDragFinished', event)
}
function isForThisPurpose (purpose) {
if (purpose !== undefined) {
switch (purpose) {
case GET_CONTAINER_PURPOSE.MOUSE_OVER:
if (thisObject.detectMouseOver === true) {
return true
}
break
case GET_CONTAINER_PURPOSE.MOUSE_WHEEL:
if (thisObject.isWheelable === true) {
return true
}
break
case GET_CONTAINER_PURPOSE.MOUSE_CLICK:
if (thisObject.isClickeable === true) {
return true
}
break
case GET_CONTAINER_PURPOSE.DRAGGING:
if (thisObject.isDraggeable === true) {
return true
}
break
default: { return false }
}
}
return false
}
function displace (point) {
/* This function will move the container according to the vector received. If it has a visible function will use it
to see if the container can be moved there or not. It wont if the center will not be visible.
Returns true if move was possible, false if not. */
let checkPoint = {}
if (thisObject.isVisibleFunction === undefined) {
drag()
return true
} else {
checkPoint.x = thisObject.frame.position.x + point.x + thisObject.frame.width / 2
checkPoint.y = thisObject.frame.position.y + point.y + thisObject.frame.height / 2
let isVisible = thisObject.isVisibleFunction(checkPoint)
if (isVisible === true) {
drag()
return true
} else {
return false
}
}
function drag () {
if (thisObject.notDraggingOnX === false) {
thisObject.frame.position.x = thisObject.frame.position.x + point.x
}
if (thisObject.notDraggingOnY === false) {
thisObject.frame.position.y = thisObject.frame.position.y + point.y
}
thisObject.eventHandler.raiseEvent('onDisplace', event)
}
}
}
Loaded 100 of 6972 files, more files were not shown because too many files have changed in this diff. Show more