MWSE/script/index.html

714 lines
26 KiB
HTML

<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Network meter</title>
</head>
<body style="background-color: #333333;">
<div id="container">
<div class="speed-container">
</div>
</div>
<style>
html,body,#container{
height: 100%;
margin: 0;
}
#container{
display: flex;
flex-direction: column;
}
.speed-container{
display: flex;
flex-direction: row;
max-width: 1200px;
flex-wrap: wrap;
margin: auto;
}
.speed-container > div{
flex: 1 1 25%;
max-width: 100%;
overflow: auto;
margin-bottom: 50px;
}
.speed-container > div canvas{
max-width: 100%;
overflow: auto;
}
.speed-container > div .text{
display: flex;
color: white;
vertical-align: middle;
}
.speed-container > div .mwse{
display: flex;
justify-content: space-evenly;
color: white;
text-align: center;
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
.speed-container > div .text > .text1{
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 2em;
text-align: center;
vertical-align: middle;
flex: 1;
display: flex;
justify-content: center;
}
.speed-container > div .text > .text2{
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 2em;
text-align: center;
vertical-align: middle;
flex: 1;
display: flex;
justify-content: center;
}
.speed-container > div .text1::after{
content:' FLOW';
font-size: 0.4em;
margin: auto 0 auto 5px;
}
.speed-container > div .text2::after{
content:' PRESSURE';
font-size: 0.4em;
margin: auto 0 auto 5px;
}
</style>
<script>
function CreateMeter()
{
var iCurrentSpeed = 0,
iTargetSpeed = 0,
bDecrement = null,
job = null;
function degToRad(angle) {
// Degrees to radians
return ((angle * Math.PI) / 180);
}
function radToDeg(angle) {
// Radians to degree
return ((angle * 180) / Math.PI);
}
function drawLine(options, line) {
// Draw a line using the line object passed in
options.ctx.beginPath();
// Set attributes of open
options.ctx.globalAlpha = line.alpha;
options.ctx.lineWidth = line.lineWidth;
options.ctx.fillStyle = line.fillStyle;
options.ctx.strokeStyle = line.fillStyle;
options.ctx.moveTo(line.from.X,
line.from.Y);
// Plot the line
options.ctx.lineTo(
line.to.X,
line.to.Y
);
options.ctx.stroke();
}
function createLine(fromX, fromY, toX, toY, fillStyle, lineWidth, alpha) {
// Create a line object using Javascript object notation
return {
from: {
X: fromX,
Y: fromY
},
to: {
X: toX,
Y: toY
},
fillStyle: fillStyle,
lineWidth: lineWidth,
alpha: alpha
};
}
function drawOuterMetallicArc(options) {
/* Draw the metallic border of the speedometer
* Outer grey area
*/
options.ctx.beginPath();
// Nice shade of grey
options.ctx.fillStyle = "rgb(127,127,127)";
// Draw the outer circle
options.ctx.arc(options.center.X,
options.center.Y,
options.radius,
0,
Math.PI,
true);
// Fill the last object
options.ctx.fill();
/* */
}
function drawInnerMetallicArc(options) {
/* Draw the metallic border of the speedometer
* Inner white area
*/
options.ctx.beginPath();
// White
options.ctx.fillStyle = "rgb(255,255,255)";
// Outer circle (subtle edge in the grey)
options.ctx.arc(options.center.X,
options.center.Y,
(options.radius / 100) * 90,
0,
Math.PI,
true);
options.ctx.fill();
/* */
}
function drawMetallicArc(options) {
/* Draw the metallic border of the speedometer
* by drawing two semi-circles, one over lapping
* the other with a bot of alpha transparency
*/
drawOuterMetallicArc(options);
drawInnerMetallicArc(options);
}
function drawBackground(options) {
/* Black background with alphs transparency to
* blend the edges of the metallic edge and
* black background
*/
var i = 0;
options.ctx.globalAlpha = 0.2;
options.ctx.fillStyle = "rgb(0,0,0)";
// Draw semi-transparent circles
for (i = 170; i < 180; i++) {
options.ctx.beginPath();
options.ctx.arc(options.center.X,
options.center.Y,
i,
0,
Math.PI,
true);
options.ctx.fill();
}
}
function applyDefaultContextSettings(options) {
/* Helper function to revert to gauges
* default settings
*/
options.ctx.lineWidth = 2;
options.ctx.globalAlpha = 0.5;
options.ctx.strokeStyle = "rgb(255, 255, 255)";
options.ctx.fillStyle = 'rgb(255,255,255)';
}
function drawSmallTickMarks(options) {
/* The small tick marks against the coloured
* arc drawn every 5 mph from 10 degrees to
* 170 degrees.
*/
var tickvalue = options.levelRadius - 8,
iTick = 0,
gaugeOptions = options.gaugeOptions,
iTickRad = 0,
onArchX,
onArchY,
innerTickX,
innerTickY,
fromX,
fromY,
line,
toX,
toY;
applyDefaultContextSettings(options);
// Tick every 20 degrees (small ticks)
for (iTick = 10; iTick < 180; iTick += 10) {
iTickRad = degToRad(iTick);
/* Calculate the X and Y of both ends of the
* line I need to draw at angle represented at Tick.
* The aim is to draw the a line starting on the
* coloured arc and continueing towards the outer edge
* in the direction from the center of the gauge.
*/
onArchX = gaugeOptions.radius - (Math.cos(iTickRad) * tickvalue);
onArchY = gaugeOptions.radius - (Math.sin(iTickRad) * tickvalue);
innerTickX = gaugeOptions.radius - (Math.cos(iTickRad) * gaugeOptions.radius);
innerTickY = gaugeOptions.radius - (Math.sin(iTickRad) * gaugeOptions.radius);
fromX = (options.center.X - gaugeOptions.radius) + onArchX;
fromY = (gaugeOptions.center.Y - gaugeOptions.radius) + onArchY;
toX = (options.center.X - gaugeOptions.radius) + innerTickX;
toY = (gaugeOptions.center.Y - gaugeOptions.radius) + innerTickY;
// Create a line expressed in JSON
line = createLine(fromX, fromY, toX, toY, "rgb(127,127,127)", 3, 0.6);
// Draw the line
drawLine(options, line);
}
}
function drawLargeTickMarks(options) {
/* The large tick marks against the coloured
* arc drawn every 10 mph from 10 degrees to
* 170 degrees.
*/
var tickvalue = options.levelRadius - 8,
iTick = 0,
gaugeOptions = options.gaugeOptions,
iTickRad = 0,
innerTickY,
innerTickX,
onArchX,
onArchY,
fromX,
fromY,
toX,
toY,
line;
applyDefaultContextSettings(options);
tickvalue = options.levelRadius - 2;
// 10 units (major ticks)
for (iTick = 20; iTick < 180; iTick += 20) {
iTickRad = degToRad(iTick);
/* Calculate the X and Y of both ends of the
* line I need to draw at angle represented at Tick.
* The aim is to draw the a line starting on the
* coloured arc and continueing towards the outer edge
* in the direction from the center of the gauge.
*/
onArchX = gaugeOptions.radius - (Math.cos(iTickRad) * tickvalue);
onArchY = gaugeOptions.radius - (Math.sin(iTickRad) * tickvalue);
innerTickX = gaugeOptions.radius - (Math.cos(iTickRad) * gaugeOptions.radius);
innerTickY = gaugeOptions.radius - (Math.sin(iTickRad) * gaugeOptions.radius);
fromX = (options.center.X - gaugeOptions.radius) + onArchX;
fromY = (gaugeOptions.center.Y - gaugeOptions.radius) + onArchY;
toX = (options.center.X - gaugeOptions.radius) + innerTickX;
toY = (gaugeOptions.center.Y - gaugeOptions.radius) + innerTickY;
// Create a line expressed in JSON
line = createLine(fromX, fromY, toX, toY, "rgb(127,127,127)", 3, 0.6);
// Draw the line
drawLine(options, line);
}
}
function drawTicks(options) {
/* Two tick in the coloured arc!
* Small ticks every 5
* Large ticks every 10
*/
drawSmallTickMarks(options);
drawLargeTickMarks(options);
}
function drawTextMarkers(options) {
/* The text labels marks above the coloured
* arc drawn every 10 mph from 10 degrees to
* 170 degrees.
*/
var innerTickX = 0,
innerTickY = 0,
iTick = 0,
gaugeOptions = options.gaugeOptions,
iTickToPrint = 00;
applyDefaultContextSettings(options);
// Font styling
options.ctx.font = 'italic 10px sans-serif';
options.ctx.textBaseline = 'top';
options.ctx.beginPath();
// Tick every 20 (small ticks)
for (iTick = 10; iTick < 160; iTick += 20) {
innerTickX = gaugeOptions.radius - (Math.cos(degToRad(iTick)) * gaugeOptions.radius);
innerTickY = gaugeOptions.radius - (Math.sin(degToRad(iTick)) * gaugeOptions.radius);
// Some cludging to center the values (TODO: Improve)
if (iTick <= 10) {
options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX,
(gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY + 5);
} else if (iTick < 50) {
options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX - 5,
(gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY + 5);
} else if (iTick < 90) {
options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX,
(gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY);
} else if (iTick === 90) {
options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX + 4,
(gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY);
} else if (iTick < 145) {
options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX + 10,
(gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY);
} else {
options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX + 15,
(gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY + 5);
}
// MPH increase by 10 every 20 degrees
//iTickToPrint += Math.round(2160 / 9);
iTickToPrint += 30;
}
options.ctx.stroke();
}
function drawSpeedometerPart(options, alphaValue, strokeStyle, startPos) {
/* Draw part of the arc that represents
* the colour speedometer arc
*/
options.ctx.beginPath();
options.ctx.globalAlpha = alphaValue;
options.ctx.lineWidth = 5;
options.ctx.strokeStyle = strokeStyle;
options.ctx.arc(options.center.X,
options.center.Y,
options.levelRadius,
Math.PI + (Math.PI / 360 * startPos),
0 - (Math.PI / 360 * 10),
false);
options.ctx.stroke();
}
function drawSpeedometerColourArc(options) {
/* Draws the colour arc. Three different colours
* used here; thus, same arc drawn 3 times with
* different colours.
* TODO: Gradient possible?
*/
drawSpeedometerPart(options, 1.0, "rgb(255,255,255)", 10);
drawSpeedometerPart(options, 0.9, "rgb(0,255,0)", 80);
drawSpeedometerPart(options, 0.9, "rgb(255,128,0)", 250);
drawSpeedometerPart(options, 0.9, "rgb(255,0,0)", 300);
}
function drawNeedleDial(options, alphaValue, strokeStyle, fillStyle) {
/* Draws the metallic dial that covers the base of the
* needle.
*/
var i = 0;
options.ctx.globalAlpha = alphaValue;
options.ctx.lineWidth = 3;
options.ctx.strokeStyle = strokeStyle;
options.ctx.fillStyle = fillStyle;
// Draw several transparent circles with alpha
for (i = 0; i < 30; i++) {
options.ctx.beginPath();
options.ctx.arc(options.center.X,
options.center.Y,
i,
0,
Math.PI,
true);
options.ctx.fill();
options.ctx.stroke();
}
}
function drawNeedle(options) {
/* Draw the needle in a nice read colour at the
* angle that represents the options.speed value.
*/
var iSpeedAsAngle = convertSpeedToAngle(options),
iSpeedAsAngleRad = degToRad(iSpeedAsAngle),
gaugeOptions = options.gaugeOptions,
innerTickX = gaugeOptions.radius - (Math.cos(iSpeedAsAngleRad) * 20),
innerTickY = gaugeOptions.radius - (Math.sin(iSpeedAsAngleRad) * 20),
fromX = (options.center.X - gaugeOptions.radius) + innerTickX,
fromY = (gaugeOptions.center.Y - gaugeOptions.radius) + innerTickY,
endNeedleX = gaugeOptions.radius - (Math.cos(iSpeedAsAngleRad) * gaugeOptions.radius),
endNeedleY = gaugeOptions.radius - (Math.sin(iSpeedAsAngleRad) * gaugeOptions.radius),
toX = (options.center.X - gaugeOptions.radius) + endNeedleX,
toY = (gaugeOptions.center.Y - gaugeOptions.radius) + endNeedleY,
line = createLine(fromX, fromY, toX, toY, "rgb(255, 0, 0)", 5, 0.6);
drawLine(options, line);
// Two circle to draw the dial at the base (give its a nice effect?)
drawNeedleDial(options, 0.6, "rgb(127, 127, 127)", "rgb(255,255,255)");
drawNeedleDial(options, 0.2, "rgb(127, 127, 127)", "rgb(127,127,127)");
}
function buildOptionsAsJSON(canvas, iSpeed) {
/* Setting for the speedometer
* Alter these to modify its look and feel
*/
var centerX = 210,
centerY = 210,
radius = 150,
outerRadius = 200;
// Create a speedometer object using Javascript object notation
return {
ctx: canvas.getContext('2d'),
speed: iSpeed,
center: {
X: centerX,
Y: centerY
},
levelRadius: radius - 10,
gaugeOptions: {
center: {
X: centerX,
Y: centerY
},
radius: radius
},
radius: outerRadius
};
}
function clearCanvas(options) {
options.ctx.clearRect(0, 0, 800, 600);
applyDefaultContextSettings(options);
}
function draw() {
/* Main entry point for drawing the speedometer
* If canvas is not support alert the user.
*/
var canvas = createCanvas.value,
options = null;
// Canvas good?
if (canvas !== null && canvas.getContext) {
options = buildOptionsAsJSON(canvas, iCurrentSpeed);
// Clear canvas
clearCanvas(options);
// Draw the metallic styled edge
drawMetallicArc(options);
// Draw thw background
drawBackground(options);
// Draw tick marks
drawTicks(options);
// Draw labels on markers
drawTextMarkers(options);
// Draw speeometer colour arc
drawSpeedometerColourArc(options);
// Draw the needle and base
drawNeedle(options);
} else {
alert("Canvas not supported by your browser!");
};
if(iTargetSpeed == iCurrentSpeed) {
cancelAnimationFrame(job);
return;
} else if(iTargetSpeed < iCurrentSpeed) {
bDecrement = true;
} else if(iTargetSpeed > iCurrentSpeed) {
bDecrement = false;
}
console.log(iTargetSpeed,bDecrement)
if(bDecrement) {
iCurrentSpeed = iCurrentSpeed - 1;
} else {
iCurrentSpeed = iCurrentSpeed + 1;
}
job = requestAnimationFrame(draw);
};
function createCanvas()
{
let container = document.createElement("div");
container.classList.add("boxmodel")
let canvas = document.createElement("canvas");
let text = document.createElement("div");
let text1 = document.createElement("div");
let text2 = document.createElement("div");
text.classList.add("text")
text1.classList.add("text1")
text2.classList.add("text2")
let mwse = document.createElement("div");
let text3 = document.createElement("span");
let text4 = document.createElement("span");
mwse.classList.add("mwse")
text3.classList.add("text3")
text4.classList.add("text4")
text.append(text1);
text.append(text2);
mwse.append(text3);
mwse.append(text4);
canvas.setAttribute("width", "440px");
canvas.setAttribute("height", "220px");
container.append(canvas);
container.append(text);
container.append(mwse);
createCanvas.value = canvas;
createCanvas.container = container;
createCanvas.ps = text1;
createCanvas.pw = text2;
createCanvas.rooms = text3;
createCanvas.clients = text4;
return container;
};
function update(value, pressure, rooms, clients)
{
iTargetSpeed = value;
createCanvas.ps.innerText = value;
createCanvas.pw.innerText = pressure + '%';
createCanvas.rooms.innerText = rooms;
createCanvas.clients.innerText = clients;
draw()
}
function convertSpeedToAngle(options) {
/* Helper function to convert a speed to the
* equivelant angle.
*/
let m = 150;
let value = (m/10) + Math.min(
Math.max(
options.speed,
0
),
240
);
iSpeedAsAngle = (
(100 / m) * value
);
// Ensure the angle is within range
if (iSpeedAsAngle > 180) {
iSpeedAsAngle = iSpeedAsAngle - 180;
} else if (iSpeedAsAngle < 0) {
iSpeedAsAngle = iSpeedAsAngle + 180;
}
return iSpeedAsAngle;
}
return {
createCanvas,
update
}
}
/*
let elem = document.querySelector(".speed-container");
for(let e = 0; e < 8; e++)
{
let meter = CreateMeter();
let container = meter.createCanvas();
elem.appendChild(container);
meter.update(54,25)
}
*/
let elem = document.querySelector(".speed-container");
let meters = new Map();
async function reloadData()
{
while(1)
{
await fetchData();
await new Promise(ok => {
setTimeout(() => ok(), 3000)
})
}
};
let isFirst = true;
async function fetchData()
{
let response = await fetch("/stats",{
method: "post",
credentials: "same-origin",
cache: "no-cache",
mode:"no-cors"
}).then(e => e.json());
for (const {
ws_total_packs,
core,
mwse_rooms,
mwse_clients
} of response) {
if(!meters.has(core))
{
let meter = CreateMeter();
let container = meter.createCanvas();
elem.appendChild(container);
meters.set(core, meter)
};
let _meter = meters.get(core);
_meter.update(
ws_total_packs,
ws_total_packs < 30 ? 0 : ws_total_packs < 60 ? 1 : ws_total_packs < 90 ? 2 : 3,
"RM: "+mwse_rooms,
"CL: "+mwse_clients
);
}
}
reloadData();
</script>
</body>
</html>