v0.1.1 - Enable complete REST calls (#5)

Good implementation for parsing data from CSV into plotly. Reviewed-on: #5
Co-authored-by: Blizzard Finnegan <blizzardfinnegan@gmail.com>
Co-committed-by: Blizzard Finnegan <blizzardfinnegan@gmail.com>
This commit is contained in:
Blizzard Finnegan 2024-04-19 09:49:29 -04:00 committed by Isaacsouthwell
parent 21c688e961
commit 89e6c8e424
8 changed files with 149 additions and 107 deletions

3
app.js
View file

@ -3,6 +3,8 @@ var express = require('express');
var path = require('path'); var path = require('path');
var cookieParser = require('cookie-parser'); var cookieParser = require('cookie-parser');
var logger = require('morgan'); var logger = require('morgan');
var cors = require('cors');
var http = require('http');
var indexRouter = require('./routes/index'); var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users'); var usersRouter = require('./routes/users');
@ -13,6 +15,7 @@ var app = express();
app.set('views', path.join(__dirname, 'views')); app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade'); app.set('view engine', 'jade');
app.use(cors());
app.use(logger('dev')); app.use(logger('dev'));
app.use(express.json()); app.use(express.json());
app.use(express.urlencoded({ extended: false })); app.use(express.urlencoded({ extended: false }));

27
package-lock.json generated
View file

@ -9,8 +9,10 @@
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"cookie-parser": "~1.4.4", "cookie-parser": "~1.4.4",
"cors": "^2.8.5",
"debug": "~2.6.9", "debug": "~2.6.9",
"express": "~4.16.1", "express": "~4.16.1",
"http": "^0.0.1-security",
"http-errors": "~1.6.3", "http-errors": "~1.6.3",
"jade": "~1.11.0", "jade": "~1.11.0",
"morgan": "~1.9.1", "morgan": "~1.9.1",
@ -237,6 +239,18 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
}, },
"node_modules/cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"dependencies": {
"object-assign": "^4",
"vary": "^1"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/css": { "node_modules/css": {
"version": "1.0.8", "version": "1.0.8",
"resolved": "https://registry.npmjs.org/css/-/css-1.0.8.tgz", "resolved": "https://registry.npmjs.org/css/-/css-1.0.8.tgz",
@ -397,6 +411,11 @@
"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
"integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==" "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w=="
}, },
"node_modules/http": {
"version": "0.0.1-security",
"resolved": "https://registry.npmjs.org/http/-/http-0.0.1-security.tgz",
"integrity": "sha512-RnDvP10Ty9FxqOtPZuxtebw1j4L/WiqNMDtuc1YMH1XQm5TgDRaR1G9u8upL6KD1bXHSp9eSXo/ED+8Q7FAr+g=="
},
"node_modules/http-errors": { "node_modules/http-errors": {
"version": "1.6.3", "version": "1.6.3",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
@ -597,6 +616,14 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/on-finished": { "node_modules/on-finished": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",

View file

@ -7,8 +7,10 @@
}, },
"dependencies": { "dependencies": {
"cookie-parser": "~1.4.4", "cookie-parser": "~1.4.4",
"cors": "^2.8.5",
"debug": "~2.6.9", "debug": "~2.6.9",
"express": "~4.16.1", "express": "~4.16.1",
"http": "^0.0.1-security",
"http-errors": "~1.6.3", "http-errors": "~1.6.3",
"jade": "~1.11.0", "jade": "~1.11.0",
"morgan": "~1.9.1", "morgan": "~1.9.1",

View file

@ -1,121 +1,108 @@
TESTER = document.getElementById("test"); //Create delay function
const delay = ms => new Promise(res => setTimeout(res, ms));
var pointCount = 15; //Tennis court coordinates
var i, r; //Y: [-5.02m, 5.02m] X: [-11.88m, 11.88m] no Z height
var x = [-11.88, 11.88, 11.88, -11.88]
var y = [-5.02, -5.02, 5.02, 5.02]
//Shift the court slightly up so its not interfering with the grid
var z = [0.01, 0.01, 0.01, 0.01]
var x = []; //Face is made up of 2 triangles, both need to be set to the same colour
var y = []; var facecolor = [ 'rgb(30, 175, 0)', 'rgb(30, 175, 0)', ]
var z = [];
for(i = -pointCount; i < pointCount; i++) var court = { name:"Court", x, y, z, facecolor, type: 'mesh3d', }
{
r = i * (pointCount - i);
x.push(r * Math.cos(i / 30));
y.push(r * Math.sin(i / 30));
z.push(i);
}
var x2 = []; var x_val =new Array();
var y2 = []; var y_val =new Array();
var z2 = []; var z_val =new Array();
i = 0;
r = 0;
for(i=-pointCount; i < pointCount; i++){
r= 10 * Math.cos(i/10);
x2.push(r*Math.cos(i)+100);
y2.push(r*Math.sin(i)+60);
z2.push(i);
}
var trace2 = { var trajectory = {
name: "Line and points", name: "Trajectory",
type: 'scatter3d', type: 'scatter3d',
mode: 'lines+markers', mode: 'lines+markers',
x:x2, x: x_val,
y:y2, y: y_val,
z:z2, z: z_val,
opacity: 0.4,
line: { line: {
width:6, width: 4,
color: '#800000', color: '#ff0000',
}, },
marker: { marker: {
color: '#ffffff', color: '#0000ff',
size: 4, size: 2,
symbol: 'circle', symbol: 'circle',
line: {
color: 'rgb(0,0,0)',
width: 1,
}
}, },
}; };
var trace1 = { var layout = {
name: "Line", title: 'Tennis Ball Trajectory Plot',
type: 'scatter3d', autosize: true,
mode: 'lines+markers', margin: { autoexpand: true, },
opacity: 0.5, scene:{
x: x, xaxis:{ range:[-18,18], gridcolor: "#a0a0a0", zerolinecolor: "#a0a0a0", },
y: y, yaxis:{ range:[-10,10], gridcolor: "#a0a0a0", zerolinecolor: "#a0a0a0", },
z: z, zaxis:{ range:[ 0, 2], gridcolor: "#a0a0a0", zerolinecolor: "#a0a0a0", },
line: {
width: 8,
color: '#008000',
},
marker: {
color: '#000080',
size: 4,
symbol: 'circle',
line: {
color: 'rgb(0,0,0)',
width: 1,
} }
};
//Init plot
Plotly.newPlot("secondplot", [trajectory,court] , layout, {responsive: true} );
//Update plot with info from GET call
function poll(filename) {
var jqueryRequest = $.get("http://192.168.0.90:8000/serve/" + filename)
.done(function(data) {
Papa.parse(data, {
dynamicTyping: true,
delimiter: " ",
//Only include if the input contains a header row; i.e. the first row is labels.
//header: true,
worker: true,
complete: function(results){
results.data.forEach((element) => {
x_val.push(element[2]);
y_val.push(element[0]);
//Compensate for court offset
z_val.push(element[1]+0.01);
});
Plotly.update("secondplot", [trajectory,court], layout, {responsive: true});
}, },
}; });
}).fail(function(errorData){
console.error("Backend Request failed! Is the backend running?");
});
}
var x = [-100, -100, 120, 120, -100, -100, 120, 120] //Get the button from the HTML file
var y = [-75, 90, 90, -75, -75, 90, 90, -75] var button = document.getElementById("sendPost");
var z = [-10, -10, -10, -10, 10, 10, 10, 10]
var i = [7, 0, 0, 0, 4, 4, 2, 6, 4, 0, 3, 7]
var j = [3, 4, 1, 2, 5, 6, 5, 5, 0, 1, 2, 2]
var k = [0, 7, 2, 3, 6, 7, 1, 2, 5, 5, 7, 6]
var facecolor = [ //Get the input field from the HTML file
'rgb(50, 200, 200)', var input_field = document.getElementById("csvSelector");
'rgb(100, 200, 255)',
'rgb(150, 200, 115)', //If the user presses "enter" on the input field, call to press the button, as this is expected behaviour
'rgb(200, 200, 50)', input_field.addEventListener("keypress",function(event){
'rgb(230, 200, 10)', if (event.key === "Enter"){
'rgb(255, 140, 0)' event.preventDefault();
] button.click();
facecolor2 = new Array(facecolor.length * 2); }
facecolor.forEach(function(x, i) {
facecolor2[i * 2 + 1] = facecolor2[i * 2] = x;
}); });
var mesh = { //On button click...
x: x, button.addEventListener("click",function(e){
y: y, //Get the file name from the text input
z: z, var file_name = input_field.value;
i: i, //Send the text input to the web server
j: j, $.post("http://192.168.0.90:8000/serve", { file_name })
k: k, //Once the POST response comes back
opacity: 0.4, .done(function(){
legend: true, //Wait 2s for image processing to run
facecolor: facecolor2, delay(2000);
type: 'mesh3d' //Clear current values to graph the new file
} x_val.length = 0;
y_val.length = 0;
var data = [trace1,trace2,mesh]; z_val.length = 0;
var layout = { //Run a GET call, with the given file name
title: '3D Line and Point Plot', poll(file_name);
autosize: true, });
margin: { },false);
autoexpand: true,
l: 0,
r: 0,
b: 0,
t: 65
}
};
Plotly.newPlot('test', data, layout, {responsive: true} );

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -6,3 +6,13 @@ body {
a { a {
color: #00B7FF; color: #00B7FF;
} }
button {
background-color: #4caf50;
border: none;
color: white;
padding: 10px 20px;
text-align: center;
display: inline-block;
font-size: 15px;
}

View file

@ -2,8 +2,12 @@ extends layout
block content block content
h1= "Detect Inc. Tennis Ball Path Plotting" h1= "Detect Inc. Tennis Ball Path Plotting"
p WIP: Currently using sample data to demonstrate capabilities. label(for="csvSelector") Input the serve input data to use:
div(id="test" style="height:700px;") input(id="csvSelector")
p
button(id="sendPost") Start serve
div(id="secondplot" style="height:700px")
script(src="/javascripts/plotly-2.30.0.min.js") script(src="/javascripts/plotly-2.30.0.min.js")
script(src="/javascripts/graph.js") script(src="/javascripts/papaparse-5.4.1.min.js")
script(src="/javascripts/jquery-3.7.1.min.js")
script(type="module" src="/javascripts/graph.js")