added widgets

This commit is contained in:
Nico Melone
2022-07-21 13:58:09 -05:00
parent 23069ff5f1
commit c28194c00f
9 changed files with 576 additions and 517 deletions

BIN
Widgets/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,157 @@
self.onInit = function () {
//self.onResize();
//self.draw();
};
self.onDataUpdated = function () {
//self.draw();
};
//function for scaling a canvas
function fitToContainer(canvas) {
canvas.style.width = "100%";
canvas.style.height = "100%";
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
}
class Node {
constructor(id, x, y, radius, data) {
this.id = id;
this.x = x;
this.y = y;
this.radius = Math.min(radius, 25);
this.lineLength = 25;
this.data = data;
}
draw() {
this.node = new Path2D();
this.node.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
self.ctx.canvas.textAlign = "center";
self.ctx.canvas.textBaseline = "middle";
self.ctx.canvas.strokeText(this.data, this.x, this.y);
self.ctx.canvas.fillStyle = "White";
self.ctx.canvas.stroke(this.node);
self.ctx.canvas.fill(this.node);
}
setX(x) {
this.x = x;
}
setY(y) {
this.y = y;
}
setRadius(radius) {
this.radius = radius;
}
}
class Edge {
constructor(source, target) {
this.source = source;
this.target = target;
//this.draw();
}
draw() {
self.ctx.canvas.moveTo(self.nodes[this.source].x, self.nodes[this.source].y);
self.ctx.canvas.lineTo(self.nodes[this.target].x, self.nodes[this.target].y);
self.ctx.canvas.stroke();
}
}
function getDepth(edges) {
var depth = 1;
console.log(edges);
if (Object.keys(edges).length > 0) {
Object.keys(edges).forEach((target) => {
console.log("Target: " + target);
Object.keys(edges).forEach((nTarget) => {
edges[nTarget].forEach((edge) => {
console.log("Source: " + edge.source);
if (edge.source == target) {
console.log("recurse");
var slice = Object.fromEntries(Object.entries(edges).slice(0, Object.keys(edges).indexOf(target)) + Object.entries(edges).slice(Object.keys(edges).indexOf(target)) + 1);
depth = depth + getDepth(slice);
}
});
});
});
}
console.log("Depth: " + depth);
return depth;
}
function placeNodes() {
var numSourceNodes = Object.keys(self.nodes).length - Object.keys(self.edges).length;
var depth = getDepth(self.edges);
console.log(depth);
if (Object.keys(self.nodes).length == 1) {
self.nodes[Object.keys(self.nodes)[0]].setX(self.canvas.width / 2);
self.nodes[Object.keys(self.nodes)[0]].setY(self.canvas.height / 2);
self.nodes[Object.keys(self.nodes)[0]].setRadius(self.canvas.height * 0.1);
} else {
var counter = 0;
Object.keys(self.edges).forEach((target) => {
self.edges[target].forEach((edge) => {
self.nodes[edge.source].setX(self.canvas.width * (1 / (Object.keys(self.edges).length + 2)));
self.nodes[edge.source].setY(self.canvas.height * ((counter + 1) / (numSourceNodes + 1)));
self.nodes[edge.source].setRadius(self.canvas.height * (1 / (2 * (Object.keys(self.nodes).length + 1))));
self.nodes[edge.target].setX(self.canvas.width * (2 / (Object.keys(self.edges).length + 2)));
self.nodes[edge.target].setY(self.canvas.height * ((Object.keys(self.edges).indexOf(target) + 1) / (Object.keys(self.edges).length + 1)));
self.nodes[edge.target].setRadius(self.canvas.height * (1 / (2 * (Object.keys(self.nodes).length + 1))));
counter++;
});
});
}
}
self.draw = function () {
self.canvas = document.getElementById("topology");
self.ctx.canvas = self.canvas.getContext("2d");
fitToContainer(self.canvas);
self.ctx.canvas.globalCompositeOperation = "destination-over";
var collapse = false;
self.nodes = {};
let numNodes = 9;
//var centerNode = new Node(100, self.canvas.width * 0.11, self.canvas.height * 0.5, self.canvas.height * (1 / (2 * (numNodes + 1))), 1);
for (let i = 0; i < numNodes; i++) {
self.nodes[i] = new Node(i, 0, 0, 0, i);
//self.nodes[i] = new Node(i, self.canvas.width * 0.11, self.canvas.height * ((i + 1) / (numNodes + 1)), self.canvas.height * (1 / (2 * (numNodes + 1))), (Math.random() * 10).toFixed(2));
//self.nodes[i].draw();
}
self.edges = { 0: [new Edge(3, 0), new Edge(4, 0), new Edge(5, 0), new Edge(6, 0)], 8: [new Edge(0, 8)], 7: [new Edge(8, 7)], 2: [new Edge(1, 2)] };
placeNodes();
Object.keys(self.nodes).forEach((key) => {
self.nodes[key].draw();
});
Object.keys(self.edges).forEach((target) => {
self.edges[target].forEach((edge) => {
edge.draw();
});
});
//self.edges.push(new Edge(0,0));
/*let rNodes = Math.round(numNodes * 0.5);
for (let i = 0; i < rNodes; i++) {
self.nodes[i + numNodes] = new Node(i + numNodes, self.canvas.width * 0.89, self.canvas.height * ((i + 1) / (rNodes + 1)), self.canvas.height * (1 / (2 * (rNodes + 1))), (Math.random() * 20).toFixed(2));
self.nodes[i + numNodes].draw();
}
//self.nodes["hidden1"] = new Node("hidden1", self.canvas.width * 0.3, self.canvas.height * 0.5, 0, "");
//self.nodes["hidden2"] = new Node("hidden2", self.canvas.width * 0.6, self.canvas.height * 0.5, 0, "");
for (i = 0; i < numNodes; i++) {
new Edge(i, "hidden1");
}
new Edge("hidden1", "hidden2");
for (i = numNodes; i < numNodes + rNodes; i++) {
new Edge("hidden2", i);
}
*/
};
self.onResize = function () {
self.draw();
};
self.onDestroy = function () {};

205
Widgets/vessels/vessels.js Normal file
View File

@@ -0,0 +1,205 @@
self.onInit = function () {
volume = 0;
fluidLevel = 0;
self.ctx.$container.append(
"<div><canvas id='vessel" + self.ctx.defaultSubscription.id + "'></canvas></div>"
);
};
self.onResize = function () {
self.draw();
};
//function for scaling a canvas
function fitToContainer(canvas) {
canvas.style.width = "100%";
canvas.style.height = "100%";
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
}
self.onDataUpdated = function () {
self.ctx.detectChanges();
//setup variables
self.volume = 0;
self.fluidLevel = 0;
for (let i = 0; i < self.ctx.defaultSubscription.data.length; i++) {
if (self.ctx.defaultSubscription.data[i].dataKey.name === self.ctx.settings.vessels[0].volumeKey) {
self.volume = typeof self.ctx.defaultSubscription.data[i].data[0] !== "undefined" ? self.ctx.defaultSubscription.data[i].data[0][1] : 0;
} else if (self.ctx.defaultSubscription.data[i].dataKey.name === self.ctx.settings.vessels[0].fluidLevelKey) {
self.fluidLevel = typeof self.ctx.defaultSubscription.data[i].data[0] !== "undefined" ? self.ctx.defaultSubscription.data[i].data[0][1] : 0;
}
}
self.maxHeight = typeof self.ctx.settings.maxHeight !== "undefined" ? self.ctx.settings.maxHeight : 10;
self.fluidLevelPercent = self.fluidLevel / self.maxHeight;
//draw a new canvas
self.draw();
};
self.drawTank = function (ctx, compartmentWidth, compartmentHeight) {
ctx.moveTo(compartmentWidth * 0.05, compartmentHeight * 0.05);
ctx.lineTo(compartmentWidth * 0.05, compartmentHeight * 0.95);
ctx.ellipse(compartmentWidth / 2, compartmentHeight * 0.95, compartmentWidth / 2 - compartmentWidth * 0.05, compartmentHeight * 0.025, 0, Math.PI, 0, true);
ctx.lineTo(compartmentWidth * 0.95, compartmentHeight * 0.05);
ctx.ellipse(compartmentWidth / 2, compartmentHeight * 0.05, compartmentWidth / 2 - compartmentWidth * 0.05, compartmentHeight * 0.025, 0, 0, 2 * Math.PI);
};
self.drawPond = function (ctx, compartmentWidth, compartmentHeight) {
ctx.moveTo(compartmentWidth * 0.05, compartmentHeight * 0.05);
ctx.lineTo(compartmentWidth * 0.15, compartmentHeight * 0.95);
ctx.lineTo(compartmentWidth * 0.85, compartmentHeight * 0.95);
ctx.lineTo(compartmentWidth * 0.95, compartmentHeight * 0.05);
};
self.drawVessels = function (ctx, canvas, numVessels, cols, rows) {
if (numVessels <= cols * rows) {
//vessel
ctx.beginPath();
for (let i = 1; i <= numVessels; i++) {
for (let j = 0; j < self.ctx.defaultSubscription.data.length; j++) {
//console.log(self.ctx.settings.vessels[i - 1].volumeKey);
//console.log(self.ctx.settings.vessels[i - 1].fluidLevelKey);
if (self.ctx.defaultSubscription.data[j].dataKey.name === self.ctx.settings.vessels[i - 1].volumeKey) {
self.volume = typeof self.ctx.defaultSubscription.data[j].data[0] !== "undefined" ? self.ctx.defaultSubscription.data[j].data[0][1] : 0;
} else if (self.ctx.defaultSubscription.data[j].dataKey.name === self.ctx.settings.vessels[i - 1].fluidLevelKey) {
self.fluidLevel = typeof self.ctx.defaultSubscription.data[j].data[0] !== "undefined" ? self.ctx.defaultSubscription.data[j].data[0][1] : 0;
}
//console.log(self.volume);
//console.log(self.fluidLevel);
}
self.maxHeight = typeof self.ctx.settings.vessels[i - 1].maxHeight !== "undefined" ? self.ctx.settings.vessels[i - 1].maxHeight : 10;
self.fluidLevelPercent = self.fluidLevel / self.maxHeight;
var vesselType = typeof self.ctx.settings.vessels[i - 1].vesselType !== "undefined" ? self.ctx.settings.vessels[i - 1].vesselType : "Tank";
var fluidColor = typeof self.ctx.settings.vessels[i - 1].fluidColor !== "undefined" ? self.ctx.settings.vessels[i - 1].fluidColor : "Water";
var compartmentWidth = canvas.width / cols;
var compartmentHeight = canvas.height / rows;
//gradient used as water
const grad = ctx.createLinearGradient(0, compartmentHeight * 0.05, 0, compartmentHeight * 0.95);
switch(fluidColor){
case "Water": grad.addColorStop(0, "rgba(70,220,210,0.75)");grad.addColorStop(0.4, "rgba(0,120,240,0.75)");break;
case "Produced Water": grad.addColorStop(0, "rgba(170, 100, 30,1)");grad.addColorStop(0.4, "rgba(85, 50, 15,1");break;
case "Oil": grad.addColorStop(0,"rgba(100,100,100,0.75)");grad.addColorStop(0.3, "rgba(25,25,25, 0.85");break;
default: grad.addColorStop(0,fluidColor);break;
}
grad.addColorStop(1, "rgba(0,0,0, 0.8)");
//draw the vessel
switch (vesselType) {
case "Pond":
self.drawPond(ctx, compartmentWidth, compartmentHeight);
break;
case "Tank":
self.drawTank(ctx, compartmentWidth, compartmentHeight);
break;
}
//draw
ctx.stroke();
ctx.save();
//setup clip area of container
ctx.clip();
ctx.save();
//set fill style for water to gradient
ctx.fillStyle = grad;
//move grid for animation
if (self.fluidLevelPercent > 1) {
ctx.translate(0, compartmentHeight - (compartmentHeight * 0.95 - compartmentHeight * 0.05) * 1 - compartmentHeight * 0.1);
} else {
ctx.translate(0, compartmentHeight - (compartmentHeight * 0.95 - compartmentHeight * 0.05) * self.fluidLevelPercent - compartmentHeight * 0.1);
}
ctx.fillRect(0, compartmentHeight * 0.05, compartmentWidth, compartmentHeight * 0.95);
ctx.restore();
ctx.restore();
self.drawTicks(ctx, compartmentWidth, compartmentHeight);
self.drawText(ctx, compartmentWidth, compartmentHeight);
if (i % cols === 0) {
ctx.translate(-(cols - 1) * compartmentWidth, compartmentHeight);
} else {
ctx.translate(compartmentWidth, 0);
}
}
} else {
console.error("Not enough space for Vessels");
}
};
self.drawText = function (ctx, compartmentWidth, compartmentHeight) {
fl = typeof self.fluidLevel === 'number' ? self.fluidLevel.toFixed(2) : "0.00";
vl = typeof self.volume === 'number' ? self.volume.toFixed(2) : "0.00";
ctx.textAlign = "left";
ctx.fillStyle = "rgba(0,0,0,1)";
var padding = Math.max(Math.sqrt(compartmentWidth), Math.sqrt(compartmentHeight));
ctx.fillText(`${(self.fluidLevelPercent * 100).toFixed(2)} %`, compartmentWidth / 4 - padding, compartmentHeight / 2);
ctx.fillText(`${fl} Ft`, compartmentWidth / 4 - padding, compartmentHeight / 2 + padding);
ctx.fillText(`${vl} BBLs`, compartmentWidth / 4 - padding, compartmentHeight / 2 + 2 * padding);
};
self.drawTicks = function (ctx, compartmentWidth, compartmentHeight, guageAlignment) {
ctx.fillStyle = "rgba(0,0,0,1)";
ctx.textBaseline = "middle";
var widthOffset;
switch (guageAlignment) {
case "center":
widthOffset = compartmentWidth * 0.5;
break;
case "left":
widthOffset = compartmentWidth * 0.05;
break;
case "right":
widthOffset = compartmentWidth * 0.95;
break;
default:
widthOffset = compartmentWidth * 0.5;
}
var heightOffset = compartmentHeight * 0.05;
var heightRange = compartmentHeight * 0.9;
var numTicks = Math.min(Math.round(compartmentHeight / 40), 10);
ctx.moveTo(widthOffset, compartmentHeight - heightOffset);
ctx.lineTo(widthOffset, heightOffset);
for (let i = 0; i < numTicks; i++) {
if (i % 2) {
ctx.moveTo(widthOffset - ctx.lineWidth / 2, heightOffset + (i * heightRange) / numTicks);
ctx.lineTo(widthOffset + 10 + ctx.lineWidth / 2, heightOffset + (i * heightRange) / numTicks);
ctx.textAlign = "left";
ctx.fillText((self.maxHeight * ((numTicks - i) / numTicks)).toFixed(2), widthOffset + 15, heightOffset + (i * heightRange) / numTicks);
} else {
ctx.moveTo(widthOffset + ctx.lineWidth / 2, heightOffset + (i * heightRange) / numTicks);
ctx.lineTo(widthOffset - (10 + ctx.lineWidth / 2), heightOffset + (i * heightRange) / numTicks);
ctx.textAlign = "right";
ctx.fillText((self.maxHeight * ((numTicks - i) / numTicks)).toFixed(2), widthOffset - 15, heightOffset + (i * heightRange) / numTicks);
}
}
ctx.stroke();
};
self.draw = function () {
//self.fluidLevel = typeof self.ctx.defaultSubscription.data[0].data[0] !== "undefined" ? self.ctx.defaultSubscription.data[0].data[0][1] : 0;
var numVessels = typeof self.ctx.settings.vessels !== "undefined" ? self.ctx.settings.vessels.length : 1;
var vesselType = typeof self.ctx.settings.vessels[0].vesselType !== "undefined" ? self.ctx.settings.vessels[0].vesselType : "Tank";
var fluidColor = typeof self.ctx.settings.vessels[0].color !== "undefined" ? self.ctx.settings.vessels[0].color : "Water";
var numCols = typeof self.ctx.settings.numCols !== "undefined" ? self.ctx.settings.numCols : 1;
var numRows = typeof self.ctx.settings.numRows !== "undefined" ? self.ctx.settings.numRows : 1;
const canvas = document.getElementById("vessel" + self.ctx.defaultSubscription.id);
if (canvas.getContext) {
const ctx = canvas.getContext("2d");
fitToContainer(canvas);
//clear frame
ctx.clearRect(0, 0, canvas.width, canvas.height);
//line style
ctx.lineWidth = Math.max((canvas.width * 0.005) / numCols, (canvas.height * 0.005) / numRows);
ctx.lineJoin = "round";
ctx.strokeStyle = "black";
//text style
ctx.font = `${Math.min(Math.sqrt(canvas.width / numCols), Math.sqrt(canvas.height / numRows))}px Times New Roman`;
self.drawVessels(ctx, canvas, numVessels, numCols, numRows);
}
};
self.onDestroy = function () {};