Merge remote-tracking branch 'UI/develop' into develop

This commit is contained in:
Luis Fernando Molina committed 2020-11-20 14:40:08 +01:00
commit ec6f397d7c
23 files changed
+4482

No files matched your search

+2
View File
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
+7
View File
@@ -0,0 +1,7 @@
.vs/*
obj/*
bin/*
node_modules/*
this.server.config.json
+3
View File
@@ -0,0 +1,3 @@
{
"editor.detectIndentation": false
}
+174
View File
@@ -0,0 +1,174 @@
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 {
/* 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++
let labelToPrint = key + ' ' + timeConsumed.toFixed(4)
UI.projects.superalgos.utilities.drawPrint.printLabel(labelToPrint, 10, 100 + row * 30, 1, 20, UI_COLOR.RED)
let percentage = timeConsumed * 100 / totalTimeConsumed
labelToPrint = key + ' ' + percentage.toFixed(1) + '%'
UI.projects.superalgos.utilities.drawPrint.printLabel(labelToPrint, 300, 100 + row * 30, 1, 20, UI_COLOR.RED)
}
/* Other Variables */
row++
UI.projects.superalgos.utilities.drawPrint.printLabel(DEBUG.variable1, 300, 100 + row * 30, 1, 20, UI_COLOR.RED)
row++
UI.projects.superalgos.utilities.drawPrint.printLabel(DEBUG.variable2, 300, 100 + row * 30, 1, 20, UI_COLOR.RED)
row++
UI.projects.superalgos.utilities.drawPrint.printLabel(DEBUG.variable3, 300, 100 + row * 30, 1, 20, UI_COLOR.RED)
row++
UI.projects.superalgos.utilities.drawPrint.printLabel(DEBUG.variable4, 300, 100 + row * 30, 1, 20, UI_COLOR.RED)
row++
UI.projects.superalgos.utilities.drawPrint.printLabel('Animation Frame Per Seconds: ' + ANIMATION_FRAME_PER_SECONDS, 300, 100 + row * 30, 1, 20, UI_COLOR.RED)
}
/* Video Recording */
videoRecorder.physics()
if (ARE_WE_RECORDING_A_VIDEO === true) {
videoRecorder.recordCanvas()
}
/* Panorama Recording */
if (ARE_WE_RECORDING_A_MARKET_PANORAMA === true) {
if (PANORAMA_WAS_PANNED === true) {
UI.projects.superalgos.utilities.download.addToMarketPanorama()
PANORAMA_WAS_PANNED = false
}
}
/* 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() {
if (CAN_SPACES_DRAW === false) { return }
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
browserCanvasContext.clearRect(0, 0, browserCanvas.width, browserCanvas.height)
}
}
+190
View File
@@ -0,0 +1,190 @@
let postLoader
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([
'Globals.js',
'Workspace.js',
'Files/SingleFile.js',
'Files/FileCloud.js',
'Files/MarketFiles.js',
'Files/DailyFiles.js',
'Files/FileCursor.js',
'Files/FileSequence.js',
'Files/FileStorage.js',
'EventsServerClient.js',
'LegacyPlotter.js',
'PlotterPanel.js',
'VideoRecorder.js',
'ProductStorage.js',
'Canvas.js',
'EventHandler.js',
'Frame.js',
'Animation.js',
'Container.js',
'Utilities.js',
'AppPostLoader.js'
])
modulesArray = modulesArray.concat(plotters)
functionLibraries()
function functionLibraries() {
let url = 'ListFunctionLibraries'
callWebServer(undefined, url, onResponse)
function onResponse(err, fileList) {
let urlArray = []
let fileArray = JSON.parse(fileList)
for (let i = 0; i < fileArray.length; i++) {
let item = fileArray[i]
project = item[0]
fileName = item[1]
urlArray.push('Projects' + '/' + project + '/' + 'Function-Libraries' + '/' + fileName)
}
modulesArray = modulesArray.concat(urlArray)
utilities()
}
}
function utilities() {
let url = 'ListUtilitiesFiles'
callWebServer(undefined, url, onResponse)
function onResponse(err, fileList) {
let urlArray = []
let fileArray = JSON.parse(fileList)
for (let i = 0; i < fileArray.length; i++) {
let item = fileArray[i]
project = item[0]
fileName = item[1]
urlArray.push('Projects' + '/' + project + '/' + 'Utilities' + '/' + fileName)
}
modulesArray = modulesArray.concat(urlArray)
globals()
}
}
function globals() {
let url = 'ListGlobalFiles'
callWebServer(undefined, url, onResponse)
function onResponse(err, fileList) {
let urlArray = []
let fileArray = JSON.parse(fileList)
for (let i = 0; i < fileArray.length; i++) {
let item = fileArray[i]
project = item[0]
fileName = item[1]
urlArray.push('Projects' + '/' + project + '/' + 'Globals' + '/' + fileName)
}
modulesArray = modulesArray.concat(urlArray)
spaces()
}
}
function spaces() {
let url = 'ListSpaceFiles'
callWebServer(undefined, url, onResponse)
function onResponse(err, fileList) {
let urlArray = []
let fileArray = JSON.parse(fileList)
for (let i = 0; i < fileArray.length; i++) {
let path = fileArray[i]
urlArray.push('Projects' + '/' + path)
}
modulesArray = modulesArray.concat(urlArray)
downloadIncludedFiles()
}
}
function downloadIncludedFiles() {
let downloadedCounter = 0
for (let i = 0; i < modulesArray.length; i++) {
let path = modulesArray[i]
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(() => {
postLoader = newAppPostLoader()
postLoader.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'
]
}
}
+147
View File
@@ -0,0 +1,147 @@
function newAppPostLoader() {
const MODULE_NAME = 'Post Loader'
const ERROR_LOG = true
const logger = newWebDebugLog()
logger.fileName = MODULE_NAME
let thisObject = {
start: start
}
return thisObject
function start() {
try {
/* Moving PROJECTS_ARRAY to the global variable */
PROJECTS_ARRAY = window.PROJECTS
window.PROJECTS = undefined
setBrowserEvents()
setupProjectsSchema()
function setupProjectsSchema() {
callWebServer(undefined, 'ProjectsSchema', onResponse)
function onResponse(err, file) {
PROJECTS_SCHEMA = JSON.parse(file)
setupSchemas()
}
}
function setupSchemas() {
let totalWebServerCalls = 0
let webServerResponses = 0
for (let i = 0; i < PROJECTS_ARRAY.length; i++) {
let project = PROJECTS_ARRAY[i]
let schemas = {
array: {
appSchema: [],
docSchema: [],
conceptSchema: []
},
map: {
appSchema: new Map(),
docSchema: new Map(),
conceptSchema: new Map()
}
}
SCHEMAS_BY_PROJECT.set(project, schemas)
totalWebServerCalls++
callWebServer(undefined, 'Schema/' + project + '/AppSchema', onResponseAppSchema)
function onResponseAppSchema(err, schema) {
try {
schemas.array.appSchema = JSON.parse(schema)
for (let j = 0; j < schemas.array.appSchema.length; j++) {
let nodeDefinition = schemas.array.appSchema[j]
let key = nodeDefinition.type
schemas.map.appSchema.set(key, nodeDefinition)
}
} catch (err) {
console.log(err.stack)
}
webServerResponses++
if (webServerResponses === totalWebServerCalls) { startCanvas() }
}
totalWebServerCalls++
callWebServer(undefined, 'Schema/' + project + '/DocSchema', onResponseDocSchema)
function onResponseDocSchema(err, schema) {
try {
schemas.array.docSchema = JSON.parse(schema)
for (let j = 0; j < schemas.array.docSchema.length; j++) {
let nodeDefinition = schemas.array.docSchema[j]
let key = nodeDefinition.type
schemas.map.docSchema.set(key, nodeDefinition)
}
} catch (err) {
console.log(err.stack)
}
webServerResponses++
if (webServerResponses === totalWebServerCalls) { startCanvas() }
}
totalWebServerCalls++
callWebServer(undefined, 'Schema/' + project + '/ConceptSchema', onResponseConceptSchema)
function onResponseConceptSchema(err, schema) {
try {
schemas.array.conceptSchema = JSON.parse(schema)
for (let j = 0; j < schemas.array.conceptSchema.length; j++) {
let nodeDefinition = schemas.array.conceptSchema[j]
let key = nodeDefinition.type
schemas.map.conceptSchema.set(key, nodeDefinition)
}
} catch (err) {
console.log(err.stack)
}
webServerResponses++
if (webServerResponses === totalWebServerCalls) { startCanvas() }
}
}
}
function startCanvas() {
/* If this method is executed for a second time, it should finalize the current execution structure */
if (canvas !== undefined) { canvas.finalize() }
canvas = newCanvas()
canvas.initialize()
}
} catch (err) {
if (ERROR_LOG === true) { logger.write('[ERROR] start -> err = ' + err.stack) }
}
}
function setBrowserEvents() {
window.onbeforeunload = saveWorkspace
/* handles backspace and refresh(F5) from keyboard */
window.manageBackRefresh = function (event) {
var tag = event.target.tagName.toLowerCase()
if (event.keyCode === 8 && tag !== 'input' && tag !== 'textarea') { // Backbutton pressed
saveWorkspace()
} else if (event.keyCode === 116) { // F5 pressed
saveWorkspace()
}
}
window.addEventListener('keydown', window.manageBackRefresh)
function saveWorkspace() {
UI.projects.superalgos.spaces.designSpace.workspace.save()
}
}
}
+158
View File
@@ -0,0 +1,158 @@
/* 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;
setupHTMLTextArea()
setupHTMLInput()
setupHTMLCanvas()
loadDebugModule()
function setupHTMLTextArea() {
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: ' + 600 + 'px;' +
'height: ' + 400 + 'px'
let textAreaDiv = document.getElementById('textAreaDiv');
textAreaDiv.appendChild(textArea);
textAreaDiv.style = 'position:fixed; top:' + -1500 + 'px; left:' + 500 + 'px; z-index:10; '
}
function setupHTMLInput() {
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);
}
function setupHTMLCanvas() {
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;
browserCanvas.style.border = "none";
browserCanvas.style.top = 0 + 'px';
}
function loadDebugModule() {
let path = "WebDebugLog.js";
REQUIREJS([path], onRequired);
function onRequired(pModule) {
if (INFO_LOG === true) { console.log(spacePad(MODULE_NAME, 50) + " : " + "[INFO] " + path + " downloaded."); }
setUpProjects();
}
}
function setUpProjects() {
let url = 'ProjectNames'
callWebServer(undefined, url, onResponse)
function onResponse(err, projects) {
window.PROJECTS = JSON.parse(projects)
loadModules()
}
}
/* And Finally, we start loading all the scripts we will inmediatelly need. */
function loadModules() {
let path = "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();
}
}
}
function callWebServer(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 })
}
}
}
+46
View File
@@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team using the online form in the contacts page of the superalgos.org website. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
+9
View File
@@ -0,0 +1,9 @@
# Contributing
We are thrilled you are interested in contributing to this repository. 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.
Please read the [Join the Dev Team]( https://superalgos.org/developers-join-dev-team.shtml) page in our website to learn more about how you may become a relevant member of the Community and even make a living out of contributing code to the project.
Contributions are deemed _voluntary work_, irrespective of the incentives that may be in place, and are subject to the conditions described in the LICENSE
+1082
View File
File diff suppressed because it is too large. Load diff
+262
View File
@@ -0,0 +1,262 @@
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)
}
}
}
+46
View File
@@ -0,0 +1,46 @@
function newEventHandler() {
let thisObject = {
name: undefined, // This is for debugging purposes only.
listenToEvent: listenToEvent,
stopListening: stopListening,
raiseEvent: raiseEvent,
finalize: finalize
}
let eventHandlers = [] // Here we store all the functions we will call when an event is raiseed.
return thisObject
function finalize() {
eventHandlers = []
}
function listenToEvent(eventType, handler, extraData) {
let eventSubscriptionId = newUniqueId()
eventHandlers.push([eventType, handler, extraData, eventSubscriptionId])
return eventSubscriptionId
}
function stopListening(pEventSubscriptionId) {
for (let i = 0; i < eventHandlers.length; i++) {
if (pEventSubscriptionId === eventHandlers[i][3]) {
eventHandlers.splice(i, 1)
return
}
}
}
function raiseEvent(eventType, event) {
for (var i = 0; i < eventHandlers.length; i++) {
/* We will execute all the functions listening to this event type. */
if (eventHandlers[i][0] === eventType) {
let handler = eventHandlers[i][1]
let extraData = eventHandlers[i][2]
handler(event, extraData)
}
}
}
}
+292
View File
@@ -0,0 +1,292 @@
function newEventsServerClient(networkNode) {
/* Web Sockets Connection */
const MODULE_NAME = 'System Event Handler'
const ERROR_LOG = true
const INFO_LOG = true
const logger = newWebDebugLog()
logger.fileName = MODULE_NAME
let WEB_SOCKETS_CONNECTION
let thisObject = {
isConnected: isConnected,
initialize: initialize,
finalize: finalize,
physics: physics,
createEventHandler: createEventHandler,
deleteEventHandler: deleteEventHandler,
listenToEvent: listenToEvent,
stopListening: stopListening,
raiseEvent: raiseEvent
}
let eventListeners = new Map()
let responseWaiters = new Map()
let commandsWaitingConfirmation = new Map()
let commandsSentByTimestamp = new Map()
let nonce = 0
let lastTryToReconnectDatetime
return thisObject
function initialize(callBackFunction) {
setuptWebSockets(callBackFunction)
}
function finalize() {
WEB_SOCKETS_CONNECTION.close()
WEB_SOCKETS_CONNECTION.onerror = undefined
WEB_SOCKETS_CONNECTION.onmessage = undefined
WEB_SOCKETS_CONNECTION.onopen = undefined
WEB_SOCKETS_CONNECTION = undefined
eventListeners = undefined
responseWaiters = undefined
commandsWaitingConfirmation = undefined
commandsSentByTimestamp = undefined
nonce = undefined
thisObject = undefined
}
function isConnected() {
if (WEB_SOCKETS_CONNECTION !== undefined) {
if (WEB_SOCKETS_CONNECTION.readyState === 1) {
return true
}
}
}
function sendCommand(command, responseCallBack, eventsCallBack) {
if (command.action === 'listenToEvent') {
let key
if (command.callerId !== undefined) {
key = command.eventHandlerName + '-' + command.eventType + '-' + command.callerId
} else {
key = command.eventHandlerName + '-' + command.eventType
}
eventListeners.set(key, eventsCallBack)
}
if (command.callerId && responseCallBack) {
responseWaiters.set(command.callerId, responseCallBack)
}
sendToWebSocketServer(command)
}
function sendToWebSocketServer(command) {
if (commandsWaitingConfirmation === undefined) {return} // object already finalized
nonce++
let stringNonce = nonce.toString()
let timestamp = (new Date()).valueOf()
commandsWaitingConfirmation.set(stringNonce, command)
commandsSentByTimestamp.set(stringNonce, timestamp)
let messageToWebSocketServer = 'Web Browser' + '|*|' + stringNonce + '|*|' + JSON.stringify(command)
if (WEB_SOCKETS_CONNECTION.readyState === 1) {
WEB_SOCKETS_CONNECTION.send(messageToWebSocketServer)
} else {
//console.log('WebSocket message could not be sent because the connection was not ready. Will retry soon. Message = ' + JSON.stringify(command))
}
}
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, eventSubscriptionId, callerId, responseCallBack) {
let eventCommand = {
action: 'stopListening',
eventHandlerName: eventHandlerName,
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)
}
function retryCommandsPhysics() {
commandsSentByTimestamp.forEach(checkTimestamp)
function checkTimestamp(timestamp, nonce) {
const MILISECONDS_TO_WAIT_FOR_RETRYING_A_COMMAND = 10000
let now = (new Date()).valueOf()
if ((now - timestamp) > MILISECONDS_TO_WAIT_FOR_RETRYING_A_COMMAND) {
let command = commandsWaitingConfirmation.get(nonce)
commandsWaitingConfirmation.delete(nonce)
commandsSentByTimestamp.delete(nonce)
sendToWebSocketServer(command)
}
}
}
function physics() {
if (WEB_SOCKETS_CONNECTION !== undefined) {
if (WEB_SOCKETS_CONNECTION.readyState === 3) {
/*
Connection closed. May happen after computer goes to sleep.
We will try to reconnect, but we will do it no more that once
a minute.
*/
if (lastTryToReconnectDatetime === undefined) {
setuptWebSockets(onOpen)
lastTryToReconnectDatetime = (new Date()).valueOf()
} else {
let now = (new Date()).valueOf()
if (now - lastTryToReconnectDatetime > 60000) {
setuptWebSockets(onOpen)
}
}
function onOpen() {
if (INFO_LOG === true) { logger.write('[INFO] setuptWebSockets -> Found Web Sockets Connection Closed. Reconnected to WebSockets Server.') }
}
}
} else {
/*
If there is a problem with the configuration then we go through
this path, retrying this until the configuration is fixed.
*/
setuptWebSockets(onOpen)
}
if (thisObject.isConnected() !== true ) {
if ( lastTryToReconnectDatetime !== undefined) {
if (networkNode !== undefined) {
if (networkNode.payload !== undefined) {
if (networkNode.payload.uiObject !== undefined) {
networkNode.payload.uiObject.setErrorMessage('Failed to Connect to Superalgos Backend via WebSockets. Retrying in 1 minute.')
}
}
}
}
} else {
if (networkNode !== undefined) {
if (networkNode.payload !== undefined) {
if (networkNode.payload.uiObject !== undefined) {
networkNode.payload.uiObject.setStatus('Connected to Superalgos Backend via WebSockets.')
retryCommandsPhysics()
}
}
}
}
DEBUG.variable4 = 'Commands Waiting For Confirmation from WS Server: ' + commandsWaitingConfirmation.size
}
function setuptWebSockets(callBackFunction) {
try {
let host
let port
/* At this point the node does not have the payload property yet, that is why we have to do this manually */
try {
let config = JSON.parse(networkNode.config)
host = config.host
port = config.webSocketsPort
/* Check if we really have to stablish the connection. */
if (config.autoConnect === false) {return}
} catch (err) {
networkNode.payload.uiObject.setErrorMessage('Bad configuration. Cannot know the host name or the webSocketsPort.')
return
}
if (host === undefined) {
networkNode.payload.uiObject.setErrorMessage('Bad configuration. You need to have a host property.')
return
}
if (port === undefined) {
networkNode.payload.uiObject.setErrorMessage('Bad configuration. You need to have a webSocketsPort property.')
return
}
const WEB_SOCKETS_URL = 'ws://' + host + ':' + port + ''
WEB_SOCKETS_CONNECTION = new WebSocket(WEB_SOCKETS_URL)
WEB_SOCKETS_CONNECTION.onerror = error => {
console.log('WebSocket error:' + JSON.stringify(error))
}
WEB_SOCKETS_CONNECTION.onopen = () => {
if (callBackFunction !== undefined) {
callBackFunction()
}
}
WEB_SOCKETS_CONNECTION.onmessage = e => {
// console.log('Websoked Message Received: ' + e.data)
let message = JSON.parse(e.data)
if (message.action === 'Event Raised') {
let key
if (message.callerId !== undefined) {
key = message.eventHandlerName + '-' + message.eventType + '-' + message.callerId
} else {
key = message.eventHandlerName + '-' + message.eventType
}
let handler = eventListeners.get(key)
if (handler) {
handler(message)
}
return
}
if (message.action === 'Event Server Response') {
let handler = responseWaiters.get(message.callerId)
if (handler) {
handler(message)
}
return
}
if (message.action === 'Acknowledge') {
commandsWaitingConfirmation.delete(message.nonce)
commandsSentByTimestamp.delete(message.nonce)
return
}
}
} catch (err) {
if (ERROR_LOG === true) { logger.write('[ERROR] setuptWebSockets -> err = ' + err.stack) }
}
}
}
+537
View File
@@ -0,0 +1,537 @@
function newFrame() {
const PANEL_CORNERS_RADIUS = 5
const TITLE_BAR_HEIGHT = 15 // this must be grater than radius
let thisObject = {
type: 'Rectangle',
containerName: '', // This is for debugging purposes only.
parentFrame: undefined, // Here we store the parent cointainer zoom object.
radius: 0,
offset: undefined,
position: undefined,
container: undefined,
width: browserCanvas.width,
height: browserCanvas.height,
getBodyHeight: getBodyHeight,
draw: draw,
fitIntoFrame: fitIntoFrame,
frameThisPoint: frameThisPoint, // This function changes the actual frame coordinate system to the screen coordinate system.
unframeThisPoint: unframeThisPoint,
isThisPointHere: isThisPointHere, // This function return true is the point received as parameter lives within this frame.
isThisScreenPointHere: isThisScreenPointHere,
isInViewPort: isInViewPort,
isCenterInViewPort: isCenterInViewPort,
initialize: initialize,
finalize: finalize
}
return thisObject
function finalize() {
thisObject.parentFrame = undefined
thisObject.position = undefined
thisObject.offset = undefined
}
function initialize(pType) {
if (pType !== undefined) { thisObject.type = pType }
thisObject.position = {
x: 0,
y: 0
}
thisObject.offset = {
x: 0,
y: 0
}
}
function getBodyHeight() {
return thisObject.height - TITLE_BAR_HEIGHT
}
function isInViewPort() {
/* This function is usefull to know if the object who has this frame is currently appearing at least in part at the UI.projects.superalgos.spaces.chartingSpace.viewport */
point1 = {
x: 0,
y: 0
}
point3 = {
x: thisObject.width,
y: thisObject.height
}
/* Now the transformations. */
point1 = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(point1, thisObject.container)
point3 = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(point3, thisObject.container)
if (point1.x < UI.projects.superalgos.spaces.chartingSpace.viewport.visibleArea.topRight.x && point1.y < UI.projects.superalgos.spaces.chartingSpace.viewport.visibleArea.bottomRight.y && point3.x > UI.projects.superalgos.spaces.chartingSpace.viewport.visibleArea.bottomLeft.x && point3.y > UI.projects.superalgos.spaces.chartingSpace.viewport.visibleArea.topLeft.y) {
return true
} else {
return false
}
}
function isCenterInViewPort() {
/* This function is usefull to know if the object who has this frame is currently appearing at least in part at the UI.projects.superalgos.spaces.chartingSpace.viewport */
point1 = {
x: thisObject.width * 40 / 100,
y: thisObject.height * 40 / 100
}
point3 = {
x: thisObject.width * 40 / 100,
y: thisObject.height * 40 / 100
}
/* Now the transformations. */
point1 = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(point1, thisObject.container)
point3 = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(point3, thisObject.container)
if (point1.x < UI.projects.superalgos.spaces.chartingSpace.viewport.visibleArea.topRight.x && point1.y < UI.projects.superalgos.spaces.chartingSpace.viewport.visibleArea.bottomRight.y && point3.x > UI.projects.superalgos.spaces.chartingSpace.viewport.visibleArea.bottomLeft.x && point3.y > UI.projects.superalgos.spaces.chartingSpace.viewport.visibleArea.topLeft.y) {
return true
} else {
return false
}
}
function frameThisPoint(point) {
/* We need not to modify the point received, so me make a copy of it. */
let checkPoint = {
x: point.x,
y: point.y
}
let parentPoint = {
x: 0,
y: 0
}
let returnPoint = {
x: 0,
y: 0
}
if (thisObject.parentFrame !== undefined) {
parentPoint = thisObject.parentFrame.frameThisPoint(checkPoint)
returnPoint.x = parentPoint.x + thisObject.position.x + thisObject.offset.x
returnPoint.y = parentPoint.y + thisObject.position.y + thisObject.offset.y
} else {
returnPoint.x = checkPoint.x + thisObject.position.x + thisObject.offset.x
returnPoint.y = checkPoint.y + thisObject.position.y + thisObject.offset.y
}
return returnPoint
}
function unframeThisPoint(point) {
/* We need not to modify the point received, so me make a copy of it. */
let checkPoint = {
x: point.x,
y: point.y
}
let parentPoint = {
x: 0,
y: 0
}
let returnPoint = {
x: 0,
y: 0
}
if (thisObject.parentFrame !== undefined) {
parentPoint = thisObject.parentFrame.unframeThisPoint(checkPoint)
returnPoint.x = parentPoint.x - thisObject.position.x
returnPoint.y = parentPoint.y - thisObject.position.y
} else {
returnPoint.x = checkPoint.x - thisObject.position.x
returnPoint.y = checkPoint.y - thisObject.position.y
}
return returnPoint
}
function fitIntoFrame(point) {
/* Here we check the boundaries of the resulting points, so they dont go out of the visible area. */
if (point.x > thisObject.width) {
point.x = thisObject.width
}
if (point.x < 0) {
point.x = 0
}
if (point.y > thisObject.height) {
point.y = thisObject.height
}
if (point.y < 0) {
point.y = 0
}
return point
}
function isThisPointHere(point, outsideViewPort, dontTransform, padding) {
// The second parameter is usefull when you want to check a point that you already know is outside the viewport.
// The padding is a distance to the borders of the container. Can be either negative (outside, to increase the cointainer size) or positive (inside to decrease the cointainer size)
if (padding === undefined) { padding = 0 }
/* We need not to modify the point received, so me make a copy of it. */
let checkPoint = {
x: point.x,
y: point.y
}
/* The point received is on the screen coordinates system, which already has zoom and displacement applied. We need to remove the zoom and displacement
in order to have the point on the containers coordinate system and be able to compare it with its dimmensions. */
if (dontTransform === false || dontTransform === undefined) {
if (outsideViewPort === true) {
checkPoint = thisObject.container.frame.unframeThisPoint(checkPoint)
} else {
checkPoint = UI.projects.superalgos.utilities.coordinateTransformations.unTransformThisPoint(checkPoint, thisObject.container)
}
}
/* Now we check if the resulting point is whin the current Frame. */
if (isNaN(checkPoint.x) || isNaN(checkPoint.y)) { return false }
if (thisObject.type === 'Circle') {
let distance = Math.sqrt(Math.pow(thisObject.position.x - checkPoint.x, 2) + Math.pow(thisObject.position.y - checkPoint.y, 2))
if (distance < thisObject.radius) {
return true
} else {
return false
}
}
if (thisObject.type === 'Rectangle') {
if (checkPoint.x < 0 + padding || checkPoint.y < 0 + padding || checkPoint.x > thisObject.width - padding || checkPoint.y > thisObject.height - padding) {
return false
} else {
return true
}
}
}
function isThisScreenPointHere(point) {
let checkPoint = {
x: point.x,
y: point.y
}
let thisPoint = {
x: thisObject.position.x,
y: thisObject.position.y
}
if (thisObject.parentFrame !== undefined) {
thisPoint = thisObject.parentFrame.frameThisPoint(thisPoint)
}
/* Now we check if the resulting point is whin the current Frame. */
if (thisObject.type === 'Circle') {
let distance = Math.sqrt(Math.pow(thisPoint.x - checkPoint.x, 2) + Math.pow(thisPoint.y - checkPoint.y, 2))
if (distance < thisObject.radius) {
return true
} else {
return false
}
}
if (thisObject.type === 'Rectangle') {
if (checkPoint.x < 0 || checkPoint.y < 0 || checkPoint.x > thisObject.width || checkPoint.y > thisObject.height) {
return false
} else {
return true
}
}
}
function draw(drawGrid, drawBorders, drawBackground, fitFunction, style) {
if (drawBorders === true) {
borders(fitFunction, style)
}
if (drawGrid === true) {
grid(fitFunction)
}
if (drawBackground === true) {
background(fitFunction)
}
}
function background(fitFunction) {
let params = {
cornerRadius: 5,
lineWidth: 0.1,
opacity: 0.75,
container: thisObject.container,
borderColor: UI_COLOR.DARK,
backgroundColor: UI_COLOR.WHITE,
fitFunction: fitFunction
}
UI.projects.superalgos.utilities.drawPrint.roundedCornersBackground(params)
titleBarPoint1 = {
x: 0,
y: TITLE_BAR_HEIGHT
}
titleBarPoint2 = {
x: thisObject.width,
y: TITLE_BAR_HEIGHT
}
/* Now the transformations. */
titleBarPoint1 = frameThisPoint(titleBarPoint1)
titleBarPoint2 = frameThisPoint(titleBarPoint2)
if (fitFunction !== undefined) {
titleBarPoint1 = fitFunction(titleBarPoint1)
titleBarPoint2 = fitFunction(titleBarPoint2)
}
/* We paint the title bar now */
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.DARK + ', 1)'
browserCanvasContext.beginPath()
browserCanvasContext.moveTo(titleBarPoint1.x, titleBarPoint1.y)
browserCanvasContext.lineTo(borderPoint1.x - PANEL_CORNERS_RADIUS, borderPoint1.y)
browserCanvasContext.arc(borderPoint1.x, borderPoint1.y, PANEL_CORNERS_RADIUS, 1.0 * Math.PI, 1.5 * Math.PI)
browserCanvasContext.lineTo(borderPoint2.x, borderPoint2.y - PANEL_CORNERS_RADIUS)
browserCanvasContext.arc(borderPoint2.x, borderPoint2.y, PANEL_CORNERS_RADIUS, 1.5 * Math.PI, 2.0 * Math.PI)
browserCanvasContext.lineTo(titleBarPoint2.x, titleBarPoint2.y)
browserCanvasContext.closePath()
browserCanvasContext.fill()
browserCanvasContext.lineWidth = 0.1
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.MANGANESE_PURPLE + ', 0.75)'
browserCanvasContext.setLineDash([0, 0])
browserCanvasContext.stroke()
/* print the title */
let labelPoint
let fontSize = 10
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
let label = thisObject.containerName
let xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO
let yOffset = (TITLE_BAR_HEIGHT - fontSize) / 2 + 2
labelPoint = {
x: thisObject.width / 2 - xOffset,
y: TITLE_BAR_HEIGHT - yOffset
}
labelPoint = thisObject.frameThisPoint(labelPoint)
if (fitFunction !== undefined) {
labelPoint = fitFunction(labelPoint)
}
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
}
function borders(fitFunction, style) {
/* Lest get the important points of the drawing so as to apply the needed transformations. */
let point1
let point2
let point3
let point4
point1 = {
x: 0,
y: 0
}
point2 = {
x: thisObject.width,
y: 0
}
point3 = {
x: thisObject.width,
y: thisObject.height
}
point4 = {
x: 0,
y: thisObject.height
}
/* Now the transformations. */
point1 = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(point1, thisObject.container)
point2 = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(point2, thisObject.container)
point3 = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(point3, thisObject.container)
point4 = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(point4, thisObject.container)
if (fitFunction !== undefined) {
point1 = fitFunction(point1)
point2 = fitFunction(point2)
point3 = fitFunction(point3)
point4 = fitFunction(point4)
}
/* Lets start the drawing. */
browserCanvasContext.beginPath()
browserCanvasContext.moveTo(point1.x, point1.y)
browserCanvasContext.lineTo(point2.x, point2.y)
browserCanvasContext.lineTo(point3.x, point3.y)
browserCanvasContext.lineTo(point4.x, point4.y)
browserCanvasContext.lineTo(point1.x, point1.y)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + style.color + ', ' + style.opacity + ')'
browserCanvasContext.lineWidth = style.lineWidth
browserCanvasContext.setLineDash(style.lineDash)
browserCanvasContext.stroke()
browserCanvasContext.closePath()
}
function grid(fitFunction, smallLines) {
if (smallLines === true) {
/* Small Lines */
let step = thisObject.width / 100
browserCanvasContext.beginPath()
for (let i = 0; i < thisObject.width; i = i + step) {
for (let j = 0; j < thisObject.height; j = j + step) {
let point1 = {
x: 0,
y: j
}
let point2 = {
x: thisObject.width,
y: j
}
point1 = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(point1, thisObject.container)
point2 = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(point2, thisObject.container)
if (fitFunction !== undefined) {
point1 = fitFunction(point1)
point2 = fitFunction(point2)
}
browserCanvasContext.moveTo(point1.x, point1.y)
browserCanvasContext.lineTo(point2.x, point2.y)
}
let point3 = {
x: thisObject.width,
y: thisObject.height
}
let point4 = {
x: 0,
y: thisObject.height
}
point3 = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(point3, thisObject.container)
point4 = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(point4, thisObject.container)
if (fitFunction !== undefined) {
point3 = fitFunction(point3)
point4 = fitFunction(point4)
}
browserCanvasContext.moveTo(point3.x, point3.y)
browserCanvasContext.lineTo(point4.x, point4.y)
}
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(150, 150, 150, 0.1)'
browserCanvasContext.lineWidth = 1
browserCanvasContext.setLineDash([0, 0])
browserCanvasContext.stroke()
}
/* Main Lines */
let step = thisObject.width / 20
browserCanvasContext.beginPath()
for (let i = 0; i < thisObject.width; i = i + step) {
for (let j = 0; j < thisObject.height; j = j + step) {
let point1 = {
x: 0,
y: j
}
let point2 = {
x: thisObject.width,
y: j
}
point1 = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(point1, thisObject.container)
point2 = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(point2, thisObject.container)
if (fitFunction !== undefined) {
point1 = fitFunction(point1)
point2 = fitFunction(point2)
}
browserCanvasContext.moveTo(point1.x, point1.y)
browserCanvasContext.lineTo(point2.x, point2.y)
}
let point3 = {
x: i,
y: 0
}
let point4 = {
x: i,
y: thisObject.height
}
point3 = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(point3, thisObject.container)
point4 = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(point4, thisObject.container)
if (fitFunction !== undefined) {
point3 = fitFunction(point3)
point4 = fitFunction(point4)
}
browserCanvasContext.moveTo(point3.x, point3.y)
browserCanvasContext.lineTo(point4.x, point4.y)
}
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(100, 100, 100, 0.2)'
browserCanvasContext.lineWidth = 1
browserCanvasContext.setLineDash([0, 0])
browserCanvasContext.stroke()
}
}
+230
View File
@@ -0,0 +1,230 @@
let canvas
let PROJECTS_ARRAY
let PROJECTS_SCHEMA
let SCHEMAS_BY_PROJECT = new Map()
/* New Root object*/
let UI = {
projects: {}
}
/* User Interface Colors */
const UI_COLOR = {
DARK: "48, 48, 54",
LIGHT: "234, 226, 222",
GREY: "150, 150, 150",
LIGHT_GREY: "247, 247, 247",
WHITE: "255, 255, 255",
BLACK: "0, 0, 0",
GOLDEN_ORANGE: "240, 162, 2",
RUSTED_RED: "204, 88, 53",
GREEN: "188, 214, 67",
RED: "223, 70, 60",
PATINATED_TURQUOISE: "27,153,139",
TITANIUM_YELLOW: "244,228,9",
MANGANESE_PURPLE: "91,80,122",
TURQUOISE: "74,207,217",
DARK_TURQUOISE: "2,149,170"
};
/* User Interface Fonts */
const UI_FONT = {
PRIMARY: "Saira Condensed",
SECONDARY: "Source Code Pro"
};
const MAC_AMOUNT_FACTOR = 5
const IS_MAC = navigator.platform.toUpperCase().indexOf('MAC') >= 0
const DEBUG = {}
let FONT_ASPECT_RATIO = 0.32;
let ANIMATION_FRAME_PER_SECONDS
let DISABLE_BROWSER_RESIZE_EVENT = false
const GET_CONTAINER_PURPOSE = {
MOUSE_OVER: 1,
MOUSE_WHEEL: 2,
MOUSE_CLICK: 3,
DRAGGING: 4
}
const ANGLE_TO_PARENT = {
NOT_FIXED: 0,
RANGE_360: 1,
RANGE_180: 2,
RANGE_90: 3,
RANGE_45: 4
}
const DISTANCE_TO_PARENT = {
NOT_FIXED: 0,
PARENT_025X: 1,
PARENT_050X: 2,
PARENT_100X: 3,
PARENT_150X: 4,
PARENT_200X: 5
}
const ARRANGEMENT_STYLE = {
CONCAVE: 0,
CONVEX: 1,
VERTICAL_RIGHT: 2,
VERTICAL_LEFT: 3,
HORIZONTAL_BOTTOM: 4,
HORIZONTAL_TOP: 5
}
/* User Interface Panels */
const UI_PANEL = {
WIDTH: {
SMALL: 100,
NORMAL: 150,
MEDIUM: 200,
LARGE: 250,
X_LARGE: 350
},
HEIGHT: {
SMALL: 65,
MEDIUM: 90,
NORMAL: 300,
LARGE: 450
}
};
let marketFilesPeriods =
'[' +
'[' + 24 * 60 * 60 * 1000 + ',' + '"24-hs"' + ']' + ',' +
'[' + 12 * 60 * 60 * 1000 + ',' + '"12-hs"' + ']' + ',' +
'[' + 8 * 60 * 60 * 1000 + ',' + '"08-hs"' + ']' + ',' +
'[' + 6 * 60 * 60 * 1000 + ',' + '"06-hs"' + ']' + ',' +
'[' + 4 * 60 * 60 * 1000 + ',' + '"04-hs"' + ']' + ',' +
'[' + 3 * 60 * 60 * 1000 + ',' + '"03-hs"' + ']' + ',' +
'[' + 2 * 60 * 60 * 1000 + ',' + '"02-hs"' + ']' + ',' +
'[' + 1 * 60 * 60 * 1000 + ',' + '"01-hs"' + ']' + ']';
marketFilesPeriods = JSON.parse(marketFilesPeriods);
let dailyFilePeriods =
'[' +
'[' + 45 * 60 * 1000 + ',' + '"45-min"' + ']' + ',' +
'[' + 40 * 60 * 1000 + ',' + '"40-min"' + ']' + ',' +
'[' + 30 * 60 * 1000 + ',' + '"30-min"' + ']' + ',' +
'[' + 20 * 60 * 1000 + ',' + '"20-min"' + ']' + ',' +
'[' + 15 * 60 * 1000 + ',' + '"15-min"' + ']' + ',' +
'[' + 10 * 60 * 1000 + ',' + '"10-min"' + ']' + ',' +
'[' + 05 * 60 * 1000 + ',' + '"05-min"' + ']' + ',' +
'[' + 04 * 60 * 1000 + ',' + '"04-min"' + ']' + ',' +
'[' + 03 * 60 * 1000 + ',' + '"03-min"' + ']' + ',' +
'[' + 02 * 60 * 1000 + ',' + '"02-min"' + ']' + ',' +
'[' + 01 * 60 * 1000 + ',' + '"01-min"' + ']' + ']';
dailyFilePeriods = JSON.parse(dailyFilePeriods);
let SHOW_ANIMATION_PERFORMACE = false;
let MENU_ITEM_ON_FOCUS
let EDITOR_ON_FOCUS
let testUser = window.localStorage.getItem("test_user")
let LOGGED_IN_USER_LOCAL_STORAGE_KEY
let LOGGED_IN_ACCESS_TOKEN_LOCAL_STORAGE_KEY
if (testUser !== null) {
LOGGED_IN_USER_LOCAL_STORAGE_KEY = "test_user"
LOGGED_IN_ACCESS_TOKEN_LOCAL_STORAGE_KEY = "test_access_token"
} else {
LOGGED_IN_USER_LOCAL_STORAGE_KEY = "user"
LOGGED_IN_ACCESS_TOKEN_LOCAL_STORAGE_KEY = "access_token"
}
const MAX_DEFAULT_RATE_SCALE_VALUE = 35000; // This is needed to know the scale of the market time line.
const WIDHTER_VOLUME_BAR_BASE_FACTOR = 2.5;
const LESS_WIDHTER_VOLUME_BAR_TOP_FACTOR = 1 / 4;
const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000;
const _12_HOURS_IN_MILISECONDS = 12 * 60 * 60 * 1000;
const _8_HOURS_IN_MILISECONDS = 8 * 60 * 60 * 1000;
const _6_HOURS_IN_MILISECONDS = 6 * 60 * 60 * 1000;
const _4_HOURS_IN_MILISECONDS = 4 * 60 * 60 * 1000;
const _3_HOURS_IN_MILISECONDS = 3 * 60 * 60 * 1000;
const _2_HOURS_IN_MILISECONDS = 2 * 60 * 60 * 1000;
const _1_HOUR_IN_MILISECONDS = 1 * 60 * 60 * 1000;
const _45_MINUTES_IN_MILISECONDS = 45 * 60 * 1000;
const _40_MINUTES_IN_MILISECONDS = 40 * 60 * 1000;
const _30_MINUTES_IN_MILISECONDS = 30 * 60 * 1000;
const _20_MINUTES_IN_MILISECONDS = 20 * 60 * 1000;
const _15_MINUTES_IN_MILISECONDS = 15 * 60 * 1000;
const _10_MINUTES_IN_MILISECONDS = 10 * 60 * 1000;
const _5_MINUTES_IN_MILISECONDS = 5 * 60 * 1000;
const _4_MINUTES_IN_MILISECONDS = 4 * 60 * 1000;
const _3_MINUTES_IN_MILISECONDS = 3 * 60 * 1000;
const _2_MINUTES_IN_MILISECONDS = 2 * 60 * 1000;
const _1_MINUTE_IN_MILISECONDS = 1 * 60 * 1000;
let NEW_SESSION_INITIAL_DATE = new Date(); // This value will be overwritten at the UI.projects.superalgos.spaces.chartingSpace.viewport.initialize if the user had a prevous session with this same browser.
let INITIAL_ZOOM_LEVEL = -28.25 // This is the zoom level at the view port in which the APP starts.
let INITIAL_TIME_PERIOD = ONE_DAY_IN_MILISECONDS // This value will be overwritten at the UI.projects.superalgos.spaces.chartingSpace.viewport.initialize if the user had a prevous session with this same browser.
let VERY_LARGE_NUMBER = 100000000000000
const TOP_MARGIN = 0
let CURRENT_TOP_MARGIN = TOP_MARGIN
let AT_FULL_SCREEN_MODE = false
let maxDate = new Date();
maxDate.setMilliseconds(0);
maxDate.setDate(maxDate.getDate() + 365 * 1); // We might have charts that projects data into the future.
const MIN_PLOTABLE_DATE = new Date(2015, 0, 1, 0, 0, 0);
const MAX_PLOTABLE_DATE = maxDate;
const TOP_SPACE_HEIGHT = 40
const COCKPIT_SPACE_HEIGHT = 40;
const SIDE_PANEL_WIDTH = 350
let COCKPIT_SPACE_POSITION = browserCanvas.height - COCKPIT_SPACE_HEIGHT
const LAYER_STATUS = {
ON: 'on',
LOADING: 'loading',
OFF: 'off'
};
let spawnPosition // this is used in several places.
/* Here we list the valid Time Periods: */
const PERIOD_24_HS = "24-hs";
const PERIOD_12_HS = "12-hs";
const PERIOD_06_HS = "06-hs";
const PERIOD_03_HS = "03-hs";
const PERIOD_01_HS = "01-hs";
const PERIOD_30_MIN = "30-min";
const PERIOD_10_MIN = "10-min";
const PERIOD_05_MIN = "05-min";
const PERIOD_01_MIN = "01-min";
/*
We define here the size of the chartingSpace. It has to bee enough big in order to accomodate all the charts we expect to display in this space.
*/
const TIME_MACHINE_WIDTH = 8;
const TIME_MACHINE_HEIGHT = 8;
let mediaRecorder // to downloadText canvas animation as a mediaRecorder
let marketPanoramaCanvas
let ARE_WE_RECORDING_A_VIDEO = false
let ARE_WE_RECORDING_A_MARKET_PANORAMA = false
let PANORAMA_WAS_PANNED = false
let CURRENT_PANORAMA_POSITION = 0
let CAN_SPACES_DRAW = false // This global variable regulates when spaces can or can not draw their contents.
function toRadians(angle) {
return angle * (Math.PI / 180);
}
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work plugins a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+147
View File
@@ -0,0 +1,147 @@
function newAppPostLoader() {
const MODULE_NAME = 'Post Loader'
const ERROR_LOG = true
const logger = newWebDebugLog()
logger.fileName = MODULE_NAME
let thisObject = {
start: start
}
return thisObject
function start() {
try {
/* Moving PROJECTS_ARRAY to the global variable */
PROJECTS_ARRAY = window.PROJECTS
window.PROJECTS = undefined
setBrowserEvents()
setupProjectsSchema()
function setupProjectsSchema() {
callWebServer(undefined, 'ProjectsSchema', onResponse)
function onResponse(err, file) {
PROJECTS_SCHEMA = JSON.parse(file)
setupSchemas()
}
}
function setupSchemas() {
let totalWebServerCalls = 0
let webServerResponses = 0
for (let i = 0; i < PROJECTS_ARRAY.length; i++) {
let project = PROJECTS_ARRAY[i]
let schemas = {
array: {
appSchema: [],
docSchema: [],
conceptSchema: []
},
map: {
appSchema: new Map(),
docSchema: new Map(),
conceptSchema: new Map()
}
}
SCHEMAS_BY_PROJECT.set(project, schemas)
totalWebServerCalls++
callWebServer(undefined, 'Schema/' + project + '/AppSchema', onResponseAppSchema)
function onResponseAppSchema(err, schema) {
try {
schemas.array.appSchema = JSON.parse(schema)
for (let j = 0; j < schemas.array.appSchema.length; j++) {
let nodeDefinition = schemas.array.appSchema[j]
let key = nodeDefinition.type
schemas.map.appSchema.set(key, nodeDefinition)
}
} catch (err) {
console.log(err.stack)
}
webServerResponses++
if (webServerResponses === totalWebServerCalls) { startCanvas() }
}
totalWebServerCalls++
callWebServer(undefined, 'Schema/' + project + '/DocSchema', onResponseDocSchema)
function onResponseDocSchema(err, schema) {
try {
schemas.array.docSchema = JSON.parse(schema)
for (let j = 0; j < schemas.array.docSchema.length; j++) {
let nodeDefinition = schemas.array.docSchema[j]
let key = nodeDefinition.type
schemas.map.docSchema.set(key, nodeDefinition)
}
} catch (err) {
console.log(err.stack)
}
webServerResponses++
if (webServerResponses === totalWebServerCalls) { startCanvas() }
}
totalWebServerCalls++
callWebServer(undefined, 'Schema/' + project + '/ConceptSchema', onResponseConceptSchema)
function onResponseConceptSchema(err, schema) {
try {
schemas.array.conceptSchema = JSON.parse(schema)
for (let j = 0; j < schemas.array.conceptSchema.length; j++) {
let nodeDefinition = schemas.array.conceptSchema[j]
let key = nodeDefinition.type
schemas.map.conceptSchema.set(key, nodeDefinition)
}
} catch (err) {
console.log(err.stack)
}
webServerResponses++
if (webServerResponses === totalWebServerCalls) { startCanvas() }
}
}
}
function startCanvas() {
/* If this method is executed for a second time, it should finalize the current execution structure */
if (canvas !== undefined) { canvas.finalize() }
canvas = newCanvas()
canvas.initialize()
}
} catch (err) {
if (ERROR_LOG === true) { logger.write('[ERROR] start -> err = ' + err.stack) }
}
}
function setBrowserEvents() {
window.onbeforeunload = saveWorkspace
/* handles backspace and refresh(F5) from keyboard */
window.manageBackRefresh = function (event) {
var tag = event.target.tagName.toLowerCase()
if (event.keyCode === 8 && tag !== 'input' && tag !== 'textarea') { // Backbutton pressed
saveWorkspace()
} else if (event.keyCode === 116) { // F5 pressed
saveWorkspace()
}
}
window.addEventListener('keydown', window.manageBackRefresh)
function saveWorkspace() {
UI.projects.superalgos.spaces.designSpace.workspace.save()
}
}
}
+333
View File
@@ -0,0 +1,333 @@
function newProductStorage(name) {
const MODULE_NAME = 'Product Storage'
const ERROR_LOG = true
const logger = newWebDebugLog()
logger.fileName = MODULE_NAME
/*
This object will initialize children objects that will end up loading the data of each set defined at each product of the bot received at initialization.
Once all the underlaying objects are fully initialized it will callback.
At the same time it will raise an event for each underlaying file being loaded, so that the UI can reflect the progress to the end user.
Product Storage
|
|-----> SingleFile
|
|-----> FileSequence
|
|-----> DailyFiles -----> FileCursor
|
|-----> MarketFiles
*/
let thisObject = {
eventHandler: undefined,
marketFiles: [],
dailyFiles: [],
singleFile: [],
fileSequences: [],
setDatetime: setDatetime,
setTimeFrame: setTimeFrame,
initialize: initialize,
finalize: finalize
}
thisObject.eventHandler = newEventHandler()
/* We name the event Handler to easy debugging. */
thisObject.eventHandler.name = 'Storage-' + name
let datetime
let timeFrame
return thisObject
function finalize() {
try {
for (let i = 0; i < thisObject.marketFiles.length; i++) {
let marketFile = thisObject.marketFiles[i]
marketFile.finalize()
}
thisObject.marketFiles = undefined
for (let i = 0; i < thisObject.dailyFiles.length; i++) {
let dailyFile = thisObject.dailyFiles[i]
dailyFile.finalize()
}
thisObject.dailyFiles = undefined
for (let i = 0; i < thisObject.fileSequences.length; i++) {
let fileSequence = thisObject.fileSequences[i]
fileSequence.finalize()
}
thisObject.fileSequences = undefined
} catch (err) {
if (ERROR_LOG === true) { logger.write('[ERROR] finalize -> err = ' + err.stack) }
}
}
function initialize(mine, bot, session, product, exchange, market, pDatetime, pTimeFrame, host, port, eventsServerClient, callBackFunction) {
try {
datetime = pDatetime
timeFrame = pTimeFrame
let dataSetsToLoad = 0
let dataSetsLoaded = 0
for (let i = 0; i < product.datasets.length; i++) {
let dataset = product.datasets[i]
switch (dataset.config.type) {
case 'Market Files': {
dataSetsToLoad++
let marketFiles = newMarketFiles()
marketFiles.initialize(mine, bot, session, product, dataset, exchange, market, host, port, eventsServerClient, onMarketFileReady)
thisObject.marketFiles.push(marketFiles)
}
break
case 'Daily Files': {
dataSetsToLoad++
let dailyFiles = newDailyFiles()
dailyFiles.initialize(mine, bot, session, product, dataset, exchange, market, pDatetime, pTimeFrame, host, port, eventsServerClient, onDailyFileReady)
thisObject.dailyFiles.push(dailyFiles)
}
break
case 'Single File': {
dataSetsToLoad++
let singleFile = newSingleFile()
singleFile.initialize(mine, bot, session, product, dataset, exchange, market, host, port, eventsServerClient, onSingleFileReady)
thisObject.singleFile.push(singleFile)
}
break
case 'File Sequence': {
dataSetsToLoad++
let fileSequences = newFileSequence()
fileSequences.initialize(mine, bot, session, product, dataset, exchange, market, host, port, eventsServerClient, onFileSequenceReady)
thisObject.fileSequences.push(fileSequences)
}
break
default:
if (ERROR_LOG === true) { logger.write('[WARN] initialize -> dataset with no type defined or type not supported -> dataset.config.type = ' + dataset.config.type) }
}
function onMarketFileReady(err, pCaller) {
try {
switch (err.result) {
case GLOBAL.DEFAULT_OK_RESPONSE.result: {
break
}
case GLOBAL.DEFAULT_FAIL_RESPONSE.result: {
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
return
}
}
let event = {
totalValue: pCaller.getExpectedFiles(),
currentValue: pCaller.getFilesLoaded(),
filesNotLoaded: pCaller.getFilesNotLoaded()
}
thisObject.eventHandler.raiseEvent('Market File Loaded', event)
if (event.filesNotLoaded === event.totalValue) {
dataSetsToLoad--
checkInitializeComplete()
return
}
if (event.currentValue + event.filesNotLoaded === event.totalValue) {
dataSetsLoaded++
checkInitializeComplete()
}
} catch (err) {
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
}
}
function onDailyFileReady(err, pCaller) {
try {
switch (err.result) {
case GLOBAL.DEFAULT_OK_RESPONSE.result: {
break
}
case GLOBAL.DEFAULT_FAIL_RESPONSE.result: {
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
return
}
case GLOBAL.CUSTOM_FAIL_RESPONSE.result: {
if (err.message === 'Dataset Unavailable.') {
dataSetsToLoad--
checkInitializeComplete()
return
} else {
callBackFunction(err)
return
}
}
default: {
callBackFunction(err)
return
}
}
let event = {
totalValue: pCaller.getExpectedFiles(),
currentValue: pCaller.getFilesLoaded()
}
thisObject.eventHandler.raiseEvent('Daily File Loaded', event)
if (event.currentValue === event.totalValue) {
dataSetsLoaded++
checkInitializeComplete()
}
} catch (err) {
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
}
}
function onSingleFileReady(err, pCaller) {
try {
switch (err.result) {
case GLOBAL.DEFAULT_OK_RESPONSE.result: {
break
}
case GLOBAL.DEFAULT_FAIL_RESPONSE.result: {
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
return
}
case GLOBAL.CUSTOM_FAIL_RESPONSE.result: {
callBackFunction(err)
return
}
default: {
callBackFunction(err)
return
}
}
let event = {
totalValue: 1,
currentValue: 1
}
thisObject.eventHandler.raiseEvent('Single File Loaded', event)
if (event.currentValue === event.totalValue) {
dataSetsLoaded++
checkInitializeComplete()
}
} catch (err) {
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
}
}
function onFileSequenceReady(err, pCaller) {
try {
switch (err.result) {
case GLOBAL.DEFAULT_OK_RESPONSE.result: {
break
}
case GLOBAL.DEFAULT_FAIL_RESPONSE.result: {
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
return
}
case GLOBAL.CUSTOM_FAIL_RESPONSE.result: {
callBackFunction(err)
return
}
default: {
callBackFunction(err)
return
}
}
let event
if (pCaller !== undefined) {
event = {
totalValue: pCaller.getExpectedFiles(),
currentValue: pCaller.getFilesLoaded()
}
} else { // When there are no data the reference to the caller wont arrive here.
event = {
totalValue: 1,
currentValue: 1
}
}
thisObject.eventHandler.raiseEvent('File Sequence Loaded', event)
if (event.currentValue === event.totalValue) {
dataSetsLoaded++
checkInitializeComplete()
}
} catch (err) {
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
}
}
function checkInitializeComplete() {
try {
if (dataSetsLoaded === dataSetsToLoad) {
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE)
}
} catch (err) {
if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> checkInitializeComplete -> err = ' + err.stack) }
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
}
}
}
} catch (err) {
if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> err = ' + err.stack) }
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
}
}
function setDatetime(pDatetime) {
/* If there is a change in the day, then we take some actions, otherwise, we dont. */
let currentDate = Math.trunc(datetime.valueOf() / ONE_DAY_IN_MILISECONDS)
let newDate = Math.trunc(pDatetime.valueOf() / ONE_DAY_IN_MILISECONDS)
datetime = new Date(pDatetime)
if (currentDate !== newDate) {
if (timeFrame <= _1_HOUR_IN_MILISECONDS) {
for (let i = 0; i < thisObject.dailyFiles.length; i++) {
thisObject.dailyFiles[i].setDatetime(pDatetime)
}
}
}
}
function setTimeFrame(pTimeFrame) {
/* We are going to filter out the cases in which the timeFrame received is the same that the one we already know. */
if (timeFrame !== pTimeFrame) {
timeFrame = pTimeFrame
if (timeFrame <= _1_HOUR_IN_MILISECONDS) {
for (let i = 0; i < thisObject.dailyFiles.length; i++) {
thisObject.dailyFiles[i].setTimeFrame(pTimeFrame, datetime)
}
}
}
}
}
+226
View File
@@ -0,0 +1,226 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<Name>Project</Name>
<RootNamespace>browser</RootNamespace>
<LastActiveSolutionConfig>Debug|Any CPU</LastActiveSolutionConfig>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>3ef11619-de26-4b8b-819d-a413df220b76</ProjectGuid>
<ProjectHome>
</ProjectHome>
<StartupFile>
</StartupFile>
<SearchPath>
</SearchPath>
<WorkingDirectory>.</WorkingDirectory>
<OutputPath>.</OutputPath>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<ProjectTypeGuids>{3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}</ProjectTypeGuids>
<NodejsPort>1337</NodejsPort>
<StartWebBrowser>true</StartWebBrowser>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<Compile Include="Animation.js" />
<Compile Include="CockpitSpace\DeleteTradingHistory.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="BreakpointsBar.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="CockpitSpace\ChartAspectRatio.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="CloudVM\CloudRequire.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="CloudVM\CloudVM.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="Exchange\ExchangeAPI.js" />
<Compile Include="Globals.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="TopSpace\Login.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="PlottersManager.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="Scales\RightScale.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="CloudVM\CloudSupport.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="CloudVM\WebFS.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="FloatingSpace\Note.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="FloatingSpace\NoteSets.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="FloatingSpace\FloatingObject.js" />
<Compile Include="CompetitionStorage.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="Files\FileSequence.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="FloatingSpace\FloatingLayer.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="ImageButton.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="Spaces\CockpitSpace.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="Spaces\TopSpace.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="TopSpace\CompanyLogo.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="TopSpace\CurrentBot.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="TopSpace\CurrentProcess.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="TopSpace\CurrentStartMode.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="TopSpace\CurrentEvent.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="TopSpace\dataMine.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="TopSpace\EndUser.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="CockpitSpace\PlayStopButton.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="WebDebugLog.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="FloatingSpace\ProfileBalls.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="FloatingSpace\ProfileBall.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="Spaces\PanelsSpace.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="Layer.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="Files\SingleFile.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="Files\FileCloud.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="Files\FileCursor.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="Files\DailyFiles.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="Candle.js" />
<Compile Include="Canvas.js" />
<Compile Include="Scales\ChartGrid.js" />
<Compile Include="Spaces\ChartingSpace.js" />
<Compile Include="ChartUtilities.js" />
<Compile Include="Container.js" />
<Compile Include="Dashboard.js" />
<Compile Include="Files\MarketFiles.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="Displace.js" />
<Compile Include="EventHandler.js" />
<Compile Include="Spaces\FloatingSpace.js" />
<Compile Include="Frame.js" />
<Compile Include="Panels\LayersPanel.js" />
<Compile Include="Panels\TimeControlPanel.js" />
<Compile Include="coordinateSystem.js" />
<SubType>Code</SubType>
</Compile>
<Compile Include="ProductStorage.js">
<SubType>Code</SubType>
</Compile>
<Compile Include="TextButton.js" />
<Compile Include="TimelineChart.js" />
<Compile Include="TimeMachine.js" />
<Compile Include="Utilities.js" />
<Compile Include="ViewPort.js" />
<Compile Include="VolumeBar.js" />
</ItemGroup>
<ItemGroup>
<Folder Include="CloudVM\" />
<Folder Include="Exchange\" />
<Folder Include="Files\" />
<Folder Include="FloatingSpace\" />
<Folder Include="CockpitSpace\" />
<Folder Include="Scales\" />
<Folder Include="TopSpace\" />
<Folder Include="Spaces\" />
<Folder Include="Panels\" />
</ItemGroup>
<!-- Do not delete the following Import Project. While this appears to do nothing it is a marker for setting TypeScript properties before our import that depends on them. -->
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets" Condition="False" />
<Import Project="$(VSToolsPath)\Node.js Tools\Microsoft.NodejsTools.targets" />
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>0</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:48022/</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>True</UseCustomServer>
<CustomServerUrl>http://localhost:1337</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}" User="">
<WebProjectProperties>
<StartPageUrl>
</StartPageUrl>
<StartAction>CurrentPage</StartAction>
<AspNetDebugging>True</AspNetDebugging>
<SilverlightDebugging>False</SilverlightDebugging>
<NativeDebugging>False</NativeDebugging>
<SQLDebugging>False</SQLDebugging>
<ExternalProgram>
</ExternalProgram>
<StartExternalURL>
</StartExternalURL>
<StartCmdLineArguments>
</StartCmdLineArguments>
<StartWorkingDirectory>
</StartWorkingDirectory>
<EnableENC>False</EnableENC>
<AlwaysStartWebServerOnDebug>False</AlwaysStartWebServerOnDebug>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>
+20
View File
@@ -0,0 +1,20 @@
# Web App UI
This repo is one of the repositories built into Superalgos. For more information [read the docs](https://docs.superalgos.org/) or check the [Readme](https://github.com/Superalgos/Superalgos/) at the main repository of the project.
## Copyright and License Notice
© Copyright 2020 Superalgos. Please see the [License](/LICENSE) for information on how you can use this software.
## Disclaimer
THE SOFTWARE AND ITS ASSOCIATED PRODUCTS AND SERVICES ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, SUITABILITY FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
IN NO EVENT WILL SUPERALGOS BE LIABLE TO ANY PARTY FOR ANY DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY USE OF THE SOFTWARE, OR ANY OTHER ASSOCIATED SERVICE OR WEB SITE, INCLUDING, WITHOUT LIMITATION, ANY LOST PROFITS, BUSINESS INTERRUPTION, LOSS OF FUNDS, PROGRAMS OR OTHER DATA OR OTHERWISE, EVEN IF WE ARE EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
# Maintainer
[![Luis-Fernando-Molina](https://avatars1.githubusercontent.com/u/9479367?s=130&amp;v=4)](https://github.com/Luis-Fernando-Molina) |
---|
[Luis-Fernando-Molina](https://github.com/Luis-Fernando-Molina) |
+131
View File
@@ -0,0 +1,131 @@
function getNodeDefinition(node, project) {
if (project === undefined) { project = node.project }
let APP_SCHEMA = SCHEMAS_BY_PROJECT.get(project)
if (APP_SCHEMA !== undefined) {
return SCHEMAS_BY_PROJECT.get(project).map.appSchema.get(node.type)
} else {
console.log('[Error] Could not get APP Scchema for project ' + node.project)
}
}
function dynamicDecimals(value, minDecimals) {
if (minDecimals === undefined) {
minDecimals = 0
}
let decimals = 0
if (value < 1) { decimals = 2 }
if (Math.abs(Math.trunc(value * 10)) < 1) { decimals = 4 }
if (Math.abs(Math.trunc(value * 100)) < 1) { decimals = 5 }
if (Math.abs(Math.trunc(value * 1000)) < 1) { decimals = 6 }
if (Math.abs(Math.trunc(value * 10000)) < 1) { decimals = 7 }
if (Math.abs(Math.trunc(value * 100000)) < 1) { decimals = 8 }
if (Math.abs(Math.trunc(value * 1000000)) < 1) { decimals = 9 }
if (Math.abs(Math.trunc(value * 10000000)) < 1) { decimals = 10 }
if (Math.abs(Math.trunc(value * 100000000000)) < 1) { value = 0; decimals = 0 }
if (decimals < minDecimals) { decimals = minDecimals }
let returnValue = Number(value).toFixed(decimals)
return returnValue
}
function convertTimeFrameToName(pTimeFrame) {
for (let i = 0; i < dailyFilePeriods.length; i++) {
let period = dailyFilePeriods[i]
if (period[0] === pTimeFrame) {
return period[1]
}
}
for (let i = 0; i < marketFilesPeriods.length; i++) {
let period = marketFilesPeriods[i]
if (period[0] === pTimeFrame) {
return period[1]
}
}
}
function nextPorwerOf10(number) {
for (let i = -10; i <= 10; i++) {
if (number < Math.pow(10, i)) {
return Math.pow(10, i)
}
}
}
function pad(str, max) {
str = str.toString()
return str.length < max ? pad('0' + str, max) : str
}
function moveToUserPosition(container, currentDate, currentRate, coordinateSystem, ignoreX, ignoreY, mousePosition, fitFunction) {
let targetPoint = {
x: currentDate.valueOf(),
y: currentRate
}
/* Put this point in the coordinate system of the UI.projects.superalgos.spaces.chartingSpace.viewport */
targetPoint = coordinateSystem.transformThisPoint(targetPoint)
targetPoint = UI.projects.superalgos.utilities.coordinateTransformations.transformThisPoint(targetPoint, container)
let displaceVector
let targetNoZoom = UI.projects.superalgos.spaces.chartingSpace.viewport.unTransformThisPoint(targetPoint)
let mouseNoZoom = UI.projects.superalgos.spaces.chartingSpace.viewport.unTransformThisPoint(mousePosition)
displaceVector = {
x: mouseNoZoom.x - targetNoZoom.x,
y: mouseNoZoom.y - targetNoZoom.y
}
if (ignoreX) { displaceVector.x = 0 }
if (ignoreY) { displaceVector.y = 0 }
container.displace(displaceVector)
}
function removeTime(datetime) {
if (datetime === undefined) { return }
let dateOnly = new Date(Math.trunc(datetime.valueOf() / ONE_DAY_IN_MILISECONDS) * ONE_DAY_IN_MILISECONDS)
return dateOnly
}
function newUniqueId() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8)
return v.toString(16)
})
}
function splitTextIntoPhrases(text, wordsPerLine) {
let splittedLabel = text.split(' ')
let phrases = []
let phrase = ''
let wordCount = 0
for (let i = 0; i < splittedLabel.length; i++) {
phrase = phrase + splittedLabel[i]
wordCount++
if (i < splittedLabel.length - 1 && wordCount < wordsPerLine) {
phrase = phrase + ' '
}
if (wordCount >= wordsPerLine) {
phrases.push(phrase)
phrase = ''
wordCount = 0
}
}
if (wordCount > 0) {
phrases.push(phrase)
}
return phrases
}
function getTextWidth(text) {
var metrics = browserCanvasContext.measureText(text);
return metrics.width;
}
+218
View File
@@ -0,0 +1,218 @@
function newVideoRecorder() {
let thisObject = {
recordCanvas: recordCanvas,
physics: physics
}
let lastAction
let wheelAnimationCounter = 0
let lastWheelPointerIcon
return thisObject
function physics() {
wheelAnimationCounter--
if (wheelAnimationCounter < 0) {
wheelAnimationCounter = 0
}
}
function recordCanvas() {
{
const DISTANCE_BETWEEN_ICONS = 35
const ICON_SIZES = 50
let mousePointerIcon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'mouse-pointer')
let draggingIcon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'hand-drag')
let leftClickIcon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'mouse-left-click')
let rightClickIcon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'mouse-right-click')
let wheelClickIcon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'mouse-wheel-click')
let imagePosition
let buttonPressedIcon
if (canvas.mouse.action === 'key down' && lastAction === 'dragging') {
canvas.mouse.action = 'dragging'
}
switch (canvas.mouse.action) {
case 'moving': {
pointerIcon = mousePointerIcon
break
}
case 'dragging': {
pointerIcon = draggingIcon
break
}
case 'wheel': {
wheelAnimationCounter = 25
if (canvas.mouse.event.delta > 0) {
pointerIcon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'mouse-wheel-up')
lastWheelPointerIcon = pointerIcon
} else {
pointerIcon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'mouse-wheel-down')
lastWheelPointerIcon = pointerIcon
}
break
}
case 'key down': {
if (wheelAnimationCounter > 0) {
pointerIcon = lastWheelPointerIcon
} else {
pointerIcon = mousePointerIcon
}
let key = canvas.mouse.event.key
if (key === undefined) { break }
switch (key.toLowerCase()) {
case 'escape':
{
pointerIcon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'key-m')
break
}
case 'm':
{
pointerIcon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'key-m')
break
}
case 'a':
{
pointerIcon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'key-a')
break
}
case 'r':
{
pointerIcon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'key-r')
break
}
case 'c':
{
pointerIcon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'key-r')
break
}
}
break
}
case 'key up': {
pointerIcon = mousePointerIcon
break
}
}
lastAction = canvas.mouse.action
imagePosition = {
x: canvas.mouse.position.x,
y: canvas.mouse.position.y
}
drawMousePointer(pointerIcon, imagePosition, ICON_SIZES)
switch (canvas.mouse.event.buttons) {
case 0: {
buttonPressedIcon = undefined
break
}
case 1: {
buttonPressedIcon = leftClickIcon
break
}
case 2: {
buttonPressedIcon = rightClickIcon
break
}
case 3: {
buttonPressedIcon = undefined
break
}
case 4: {
buttonPressedIcon = wheelClickIcon
break
}
}
let firstRow = DISTANCE_BETWEEN_ICONS * 1 + ICON_SIZES * 1
let secondRow = DISTANCE_BETWEEN_ICONS * 1 + ICON_SIZES * 2
let icon
imagePosition = {
x: canvas.mouse.position.x + DISTANCE_BETWEEN_ICONS * 2,
y: canvas.mouse.position.y
}
drawMousePointer(buttonPressedIcon, imagePosition, ICON_SIZES)
if (canvas.mouse.event.shiftKey === true) {
icon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'key-shift')
imagePosition = {
x: canvas.mouse.position.x - DISTANCE_BETWEEN_ICONS * 3,
y: canvas.mouse.position.y + firstRow
}
drawMousePointer(icon, imagePosition, ICON_SIZES)
}
if (canvas.mouse.event.ctrlKey === true || canvas.mouse.event.metaKey === true) {
icon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'key-ctrl')
imagePosition = {
x: canvas.mouse.position.x - DISTANCE_BETWEEN_ICONS * 3,
y: canvas.mouse.position.y + secondRow
}
drawMousePointer(icon, imagePosition, ICON_SIZES)
}
if (canvas.mouse.event.altKey === true) {
icon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'key-alt')
imagePosition = {
x: canvas.mouse.position.x + DISTANCE_BETWEEN_ICONS * 3 + ICON_SIZES * 0,
y: canvas.mouse.position.y + secondRow
}
drawMousePointer(icon, imagePosition, ICON_SIZES)
}
if (canvas.mouse.event.code === 'ArrowUp') {
icon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'key-up')
imagePosition = {
x: canvas.mouse.position.x - 0,
y: canvas.mouse.position.y + firstRow
}
drawMousePointer(icon, imagePosition, ICON_SIZES)
}
if (canvas.mouse.event.code === 'ArrowDown') {
icon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'key-down')
imagePosition = {
x: canvas.mouse.position.x - 0,
y: canvas.mouse.position.y + secondRow
}
drawMousePointer(icon, imagePosition, ICON_SIZES)
}
if (canvas.mouse.event.code === 'ArrowLeft') {
icon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'key-left')
imagePosition = {
x: canvas.mouse.position.x - DISTANCE_BETWEEN_ICONS * 0 - ICON_SIZES * 1,
y: canvas.mouse.position.y + secondRow
}
drawMousePointer(icon, imagePosition, ICON_SIZES)
}
if (canvas.mouse.event.code === 'ArrowRight') {
icon = UI.projects.superalgos.spaces.designSpace.getIconByProjectAndName( 'Superalgos', 'key-right')
imagePosition = {
x: canvas.mouse.position.x + DISTANCE_BETWEEN_ICONS * 0 + ICON_SIZES * 1,
y: canvas.mouse.position.y + secondRow
}
drawMousePointer(icon, imagePosition, ICON_SIZES)
}
function drawMousePointer(icon, imagePosition, imageSize) {
if (icon !== undefined) {
if (icon.canDrawIcon === true) {
browserCanvasContext.drawImage(
icon, imagePosition.x,
imagePosition.y,
imageSize,
imageSize)
}
}
}
mediaRecorder.capture(browserCanvas)
}
}
}
+21
View File
@@ -0,0 +1,21 @@
function newWebDebugLog() {
try {
let thisObject = {
write: write,
fileName: 'undefined'
}
return thisObject
function write(pText) {
console.log(spacePad(thisObject.fileName, 50) + ' : ' + pText)
function spacePad(str, max) {
str = str.toString()
return str.length < max ? spacePad(' ' + str, max) : str
}
}
} catch (err) {
console.log(spacePad(MODULE_NAME, 50) + ' : ' + '[ERROR] WebDebugLog --> err = ' + err.stack)
}
}