diff --git a/README.md b/README.md index f229958..d5b265d 100644 --- a/README.md +++ b/README.md @@ -1,98 +1,13 @@ -Assignment 2 - Short Stack: Basic Two-tier Web Application using HTML/CSS/JS and Node.js -=== +Jack McEvoy -Due: September 8th, by 11:59 AM. +https://a2-linkd-aether.glitch.me/ -This assignment aims to introduce you to creating a prototype two-tiered web application. -Your application will include the use of HTML, CSS, JavaScript, and Node.js functionality, with active communication between the client and the server over the life of a user session. +## Instant Data Cruncher +This simple web tool allows users to find various measures of average of a group of numbers. Type a number of at most 10 digits into the text field, press enter or the "Add to List" button. The number will be added to the list below and the measures of average will be calculated automatically. To delete an entry in the list, click on the number. -Baseline Requirements ---- +This page uses CSS Flexbox. -There is a large range of application areas and possibilities that meet these baseline requirements. -Try to make your application do something useful! A todo list, storing / retrieving high scores for a very simple game... have a little fun with it. - -Your application is required to implement the following functionalities: - -- a `Server` which not only serves files, but also maintains a tabular dataset with 3 or more fields related to your application -- a `Results` functionality which shows the entire dataset residing in the server's memory -- a `Form/Entry` functionality which allows a user to add, modify, or delete (complete at least two) data items residing in the server's memory -- a `Server Logic` which, upon receiving new or modified "incoming" data, includes and uses a function that adds at least one additional derived field to this incoming data before integrating it with the existing dataset -- the `Derived field` for a new row of data must be computed based on fields already existing in the row. -For example, a `todo` dataset with `task`, `priority`, and `creation_date` may generate a new field `deadline` by looking at `creation_date` and `priority` - -Your application is required to demonstrate the use of the following concepts: - -HTML: -- One or more [HTML Forms](https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms), with any combination of form tags appropriate for the user input portion of the application -- A results page displaying all data currently available on the server. You will most likely use a `` tag for this, but `
'; + for (let i = 0; i < numArr.length; i++) { + numTable += + ""; + } + numTable += "
" + numArr[i] + "
"; + document.getElementById("num-table").innerHTML = numTable; + + document.getElementById("count").innerText = response.stats.entries; + document.getElementById("mean").innerText = response.stats.mean; + document.getElementById("median").innerText = response.stats.median; + document.getElementById("mode").innerText = response.stats.mode; +} diff --git a/server.improved.js b/server.improved.js index 26673fc..15c5c59 100644 --- a/server.improved.js +++ b/server.improved.js @@ -1,72 +1,133 @@ -const http = require( 'http' ), - fs = require( 'fs' ), - // IMPORTANT: you must run `npm install` in the directory for this assignment - // to install the mime library used in the following line of code - mime = require( 'mime' ), - dir = 'public/', - port = 3000 - -const appdata = [ - { 'model': 'toyota', 'year': 1999, 'mpg': 23 }, - { 'model': 'honda', 'year': 2004, 'mpg': 30 }, - { 'model': 'ford', 'year': 1987, 'mpg': 14} -] - -const server = http.createServer( function( request,response ) { - if( request.method === 'GET' ) { - handleGet( request, response ) - }else if( request.method === 'POST' ){ - handlePost( request, response ) +console.log("S: Welcome to assignment 2!"); + +const http = require("http"), + fs = require("fs"), + // IMPORTANT: you must run `npm install` in the directory for this assignment + // to install the mime library used in the following line of code + mime = require("mime"), + dir = "public/", + port = 3000; + +const appdata = { + stats: { entries: 0, mean: null, median: null, mode: [] }, + data: [], +}; + +const server = http.createServer(function (request, response) { + console.log("S: Request received: " + request.method); + if (request.method === "GET") { + handleGet(request, response); + } else if (request.method === "POST") { + handlePost(request, response); } -}) - -const handleGet = function( request, response ) { - const filename = dir + request.url.slice( 1 ) - - if( request.url === '/' ) { - sendFile( response, 'public/index.html' ) - }else{ - sendFile( response, filename ) +}); + +const handleGet = function (request, response) { + const filename = dir + request.url.slice(1); + + if (request.url === "/") { + sendFile(response, "public/index.html"); + } else if (request.url === "/request") { + response.writeHead(200, "OK", { "Content-Type": "text/plain" }); + response.end(JSON.stringify(appdata)); + } else { + sendFile(response, filename); + } +}; + +const handlePost = function (request, response) { + console.log("S: Post received"); + let dataString = ""; + + request.on("data", function (data) { + dataString += data; + }); + + request.on("end", function () { + let parsed = JSON.parse(dataString); + let url = request.url; + + if (url === "/submit") { + console.log("S: Added " + parsed.num + " to List " + appdata.data); + appdata.data[appdata.data.length] = parsed.num; + } else if (url === "/remove") { + console.log( + "S: Deleted # with index " + parsed.index + " from List " + appdata.data + ); + let data = appdata.data; + data.splice(parsed.index, 1); + appdata.data = data; + } + + appdata.stats = mathUpdateHelper(appdata); + + console.log("S: Final returned JSON: " + JSON.stringify(appdata)); + + response.writeHead(200, "OK", { "Content-Type": "text/plain" }); + response.end(JSON.stringify(appdata)); + }); +}; + +function mathUpdateHelper(appdata) { + console.log("S: Recalculating Stats"); + let numbers = appdata.data.sort(function (a, b) { + return a - b; + }); + let total = 0, + count = numbers.length, + median = 0, + modes = [], + counts = [], + modeNum, + maxIndex = 0; + + for (let i in numbers) { + total += parseFloat(numbers[i]); + modeNum = numbers[i]; + counts[modeNum] = (counts[modeNum] || 0) + 1; + if (counts[modeNum] > maxIndex) { + maxIndex = counts[modeNum]; + } } -} - -const handlePost = function( request, response ) { - let dataString = '' - - request.on( 'data', function( data ) { - dataString += data - }) - - request.on( 'end', function() { - console.log( JSON.parse( dataString ) ) - - // ... do something with the data here!!! - - response.writeHead( 200, "OK", {'Content-Type': 'text/plain' }) - response.end() - }) -} - -const sendFile = function( response, filename ) { - const type = mime.getType( filename ) - - fs.readFile( filename, function( err, content ) { - - // if the error = null, then we've loaded the file successfully - if( err === null ) { - - // status code: https://httpstatuses.com - response.writeHeader( 200, { 'Content-Type': type }) - response.end( content ) - - }else{ - - // file not found, error code 404 - response.writeHeader( 404 ) - response.end( '404 Error: File Not Found' ) - } - }) + for (let i in counts) + if (counts.hasOwnProperty(i)) { + if (counts[i] === maxIndex) { + modes[modes.length] = i; + } + } + + if (count % 2 == 0) + median = + (parseFloat(numbers[count / 2 - 1]) + parseFloat(numbers[count / 2])) / 2; + else median = numbers[(count - 1) / 2]; + + const stats = { + entries: count, + total: total, + mean: Math.round((total / count) * 1000) / 1000, + median: Math.round(median * 1000) / 1000, + mode: modes, + }; + + return stats; } -server.listen( process.env.PORT || port ) +const sendFile = function (response, filename) { + const type = mime.getType(filename); + + fs.readFile(filename, function (err, content) { + // if the error = null, then we've loaded the file successfully + if (err === null) { + // status code: https://httpstatuses.com + response.writeHeader(200, { "Content-Type": type }); + response.end(content); + } else { + // file not found, error code 404 + response.writeHeader(404); + response.end("404 Error: File Not Found"); + } + }); +}; + +server.listen(process.env.PORT || port);