From db244bad77e889a3e51cca83ecde4c99f9c40121 Mon Sep 17 00:00:00 2001 From: noahvolson Date: Tue, 15 Sep 2020 01:25:38 -0400 Subject: [PATCH 1/7] Basic server that echoes inputs --- .gitignore | 2 ++ package.json | 8 ++++---- public/favicon.ico | Bin 0 -> 15406 bytes public/index.html | 35 ++++++----------------------------- public/js/main.js | 31 +++++++++++++++++++++++++++++++ public/js/scripts.js | 3 --- server.improved.js | 15 ++++----------- 7 files changed, 47 insertions(+), 47 deletions(-) create mode 100644 public/favicon.ico create mode 100755 public/js/main.js delete mode 100755 public/js/scripts.js diff --git a/.gitignore b/.gitignore index 57195033..c64aa422 100755 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ *.DS_Store node_modules/ package-lock.json + +.idea/ diff --git a/package.json b/package.json index 988f135f..78f4cc59 100755 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "", - "version": "", - "description": "", - "author": "", + "name": "a2-noahvolson", + "version": "0.0.0", + "description": "Submission for Webware homework assignment A2", + "author": "Noah Olson", "scripts": { "start": "node server.improved.js" }, diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..84f7bc28dc2c8ac6541e2da0b8baf9d503c79af9 GIT binary patch literal 15406 zcmeHOYfM~46dqbk)cT+*@lm5B8tu;-AN{BGhbG2GBg>;HZNavJZ+~ek)}k?{{;1Yg ztnbzbmd8@Sr7bDc((+g!Eh-ijw^*PQR?4=#7Rs{h9?!YUta~qaAD87WL%NepX7AiN z^L^*sx#!NDnPn`7Eo5^daVrF3xyoGmg#*S_sd|m%`bf|$yzIZm2}o3Ki)qK&QauS8wS&@nVRJZ*zIR z+1wxhNIY+U*z={n-mo2-(sQL;y&@;5pQ&BB&D-9b@=?(C!R%n~I8Sa0S8;?uW$^qh@DOJyYSyYlN~*mMyoeBZf*FNsLtmoLeZ<|4kh z{I~A-K64q4>7I1)pSs(h&xJVP(4XDVQ+|?P>WW`+?`zUrii5c(oKSiHCTTv)>-4g} zF*X%!O{Y1GRG!+BFTLwDpXNy~{MMX84k48`^WR`xm>LoMss}fNYhu!iPjml6cfaEG zb9(CEd!QMH{yOKyrXMG>zVKp`ztj`o?fU=SB5dNL^x=Bq6DCiz?lIl++??Rk8ic;f zO5OFgKi9qETmS0~z3p%BJP#$;ty9%qZ~bZfRX-AV4m8{P*F5pQ^sMQ5S3mlWU%mNQ zII=w3+rIY6Z9&^}xoD{^&NLhLnpz9?%|>4{=>ze5C{{KT+1Zdm>}*^5)9F@49tPzBzT+cWlzTyvBb6byvzm6FcyjDrFEQno^R4< z0ZVMe_(leCChp&}#}*;)Px1bk);{N|J#xhuoZ%DF0d-0BTu0tdg`@uz=L{_C!|7)( zWs!R$jrY0a5Dqqudm-P|P<2B4>mHX4l}ohU{PI6DeO?q-I(XO1vRoRMp?N<2)6E-Y zeNdm}cf6pvAFXr`4RE7NdWPssfQvys31VeyYifriyP!Etd!NnN@Yoxka}OesF6W_waVbpEuT zs*E-HJ_up?FG!L0UVOQ#{T7u!#WqLUt!k8Ibt3ZLzi5pV`wTR0xDq1rZ%o@Iiz{=k zYWj%ApT-Tv`jv_HB>IlEDyxO^KQup3`&JNX%g%%F%d6iA%b&int?wFP(&3bGB)@NK zvOxLmSwLrelu4BFb7c9OFxoBOvn8$*!(*N^KIl(H<-h-$H86<#eQMv>_RlK8c*QDd zjw2%f;wx7}`{$L)VIk>qq4^&uzADW-KNF5W&CT%a9G!ntrqQl`IQsBbFL#<7ipIYz zemxAdbWR&LxhmTdci^gARcbeOr*;^fOKT)LdujFq>e^Yti>wax7vi)f+ z)zdjzJVQe~{bdpD?{ZGU>D`C@a`x3lH2!4w{<=0eaA#;SDAD*&42?nUQy&B!H~blh z#NX|5L;IIiP=xbJ&M#OwSNuDFtbxH(U9#L`Iss)jO#j9P(!rd%L)HiN*;9TZWc>s6 z9q3+ZTsoB9v|g4=u3f7cm*%R - CS4241 Assignment 2 + Noah Olson A2 + - +
- + +
- - + diff --git a/public/js/main.js b/public/js/main.js new file mode 100755 index 00000000..1aea08f4 --- /dev/null +++ b/public/js/main.js @@ -0,0 +1,31 @@ +// Add some Javascript code here, to run on the front end. + +function main() { + + const submit = function( e ) { + // prevent default form action from being carried out + e.preventDefault(); + + const username = document.querySelector( '#username' ); + const guess = document.querySelector( '#guess' ); + const json = { username: username.value, guess: guess.value } + const body = JSON.stringify( json ); + + fetch( '/submit', { + method:'POST', + body: body + }) + .then( function( response ) { + // do something with the reponse + return response.text(); + }) + .then( function ( txt ) { + console.log( JSON.parse(txt) ) + }) + + return false; + } + + const button = document.querySelector( 'button' ); + button.onclick = submit; +} diff --git a/public/js/scripts.js b/public/js/scripts.js deleted file mode 100755 index de052eae..00000000 --- a/public/js/scripts.js +++ /dev/null @@ -1,3 +0,0 @@ -// Add some Javascript code here, to run on the front end. - -console.log("Welcome to assignment 2!") \ No newline at end of file diff --git a/server.improved.js b/server.improved.js index 26673fc0..b5e4e58c 100644 --- a/server.improved.js +++ b/server.improved.js @@ -6,12 +6,6 @@ const http = require( 'http' ), 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 ) @@ -30,20 +24,19 @@ const handleGet = function( request, response ) { } } +let guesses = [] const handlePost = function( request, response ) { - let dataString = '' request.on( 'data', function( data ) { - dataString += data + guesses.push(JSON.parse(data)) }) request.on( 'end', function() { - console.log( JSON.parse( dataString ) ) + //console.log( JSON.parse( dataString ) ) // ... do something with the data here!!! - response.writeHead( 200, "OK", {'Content-Type': 'text/plain' }) - response.end() + response.end(JSON.stringify(guesses)) }) } From b71d6bad3990ca59dd2f0c3ceec8bebd0ab8136e Mon Sep 17 00:00:00 2001 From: noahvolson Date: Tue, 15 Sep 2020 02:23:53 -0400 Subject: [PATCH 2/7] Add update and delete functionality --- public/index.html | 8 ++++++-- public/js/main.js | 37 ++++++++++++++++++++++++++++++++++--- server.improved.js | 31 ++++++++++++++++++++++++++++--- 3 files changed, 68 insertions(+), 8 deletions(-) diff --git a/public/index.html b/public/index.html index 925fe326..f84bae43 100755 --- a/public/index.html +++ b/public/index.html @@ -9,10 +9,14 @@
- + +
- + + + +
Username----Guess----Status----Total Attempts----Most Recent Submission----
placeholder12Too High92109/15/2020
diff --git a/public/js/main.js b/public/js/main.js index 1aea08f4..7d0295ca 100755 --- a/public/js/main.js +++ b/public/js/main.js @@ -8,7 +8,11 @@ function main() { const username = document.querySelector( '#username' ); const guess = document.querySelector( '#guess' ); - const json = { username: username.value, guess: guess.value } + const json = { + username: username.value, + guess: guess.value, + remove: false + } const body = JSON.stringify( json ); fetch( '/submit', { @@ -26,6 +30,33 @@ function main() { return false; } - const button = document.querySelector( 'button' ); - button.onclick = submit; + const deleteUser = function( e ) { + // prevent default form action from being carried out + e.preventDefault(); + const username = document.querySelector( '#username' ); + const json = { + username: username.value, + remove: true + } + const body = JSON.stringify( json ); + + fetch( '/submit', { + method:'POST', + body: body + }) + .then( function( response ) { + // do something with the reponse + return response.text(); + }) + .then( function ( txt ) { + console.log( JSON.parse(txt) ) + }) + + return false; + } + + const submitButton = document.getElementById("submit"); + const deleteButton = document.getElementById("delete"); + submitButton.onclick = submit; + deleteButton.onclick = deleteUser; } diff --git a/server.improved.js b/server.improved.js index b5e4e58c..08c3eba0 100644 --- a/server.improved.js +++ b/server.improved.js @@ -28,13 +28,38 @@ let guesses = [] const handlePost = function( request, response ) { request.on( 'data', function( data ) { - guesses.push(JSON.parse(data)) + const dataObject = JSON.parse(data) + const totalItems = guesses.length + + for (let i = 0; i < guesses.length; i++) { + + if (dataObject.username === guesses[i].username) { + if (dataObject.remove) { + console.log("deleting entry") + guesses.splice(i, 1) + return + } + else { + guesses[i].guess = dataObject.guess + guesses[i].attempts++ + return + } + } + } + + let newStoredGuess = { + username: dataObject.username, + guess: dataObject.guess, + status: "", + attempts: 0, + date: "" + } + + guesses.push(newStoredGuess) }) 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(JSON.stringify(guesses)) }) From 1b8c292dc7581510de25c960a96beb6e721f8169 Mon Sep 17 00:00:00 2001 From: noahvolson Date: Tue, 15 Sep 2020 14:54:42 -0400 Subject: [PATCH 3/7] Completed all server functionality for guessing game --- public/index.html | 6 ++-- public/js/main.js | 53 +++++++++++++++++++++++++++---- server.improved.js | 77 +++++++++++++++++++++++++++++++++++----------- 3 files changed, 109 insertions(+), 27 deletions(-) diff --git a/public/index.html b/public/index.html index f84bae43..980f7703 100755 --- a/public/index.html +++ b/public/index.html @@ -13,9 +13,9 @@ - - - +
Username----Guess----Status----Total Attempts----Most Recent Submission----
placeholder12Too High92109/15/2020
+ +
Username----Guess----Status----Total Attempts----Most Recent Submission----
diff --git a/public/js/main.js b/public/js/main.js index 7d0295ca..1a4bdfec 100755 --- a/public/js/main.js +++ b/public/js/main.js @@ -2,17 +2,40 @@ function main() { + // On page load, pull any existing guesses from server + fetch ('/table', { + method: 'GET' + }) + .then( function( response ) { + return response.text(); + }) + .then( function ( txt ) { + updateTable( JSON.parse(txt) ); + }) + const submit = function( e ) { // prevent default form action from being carried out e.preventDefault(); + // code snippet for timestamp from: https://phoenixnap.com/kb/how-to-get-the-current-date-and-time-javascript + var today = new Date(); + var date = (today.getMonth()+1)+'/'+today.getDate()+'/'+today.getFullYear(); + var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds(); + var dateTime = date+' '+time; + const username = document.querySelector( '#username' ); + if (username.value === "") { + return false + } + const guess = document.querySelector( '#guess' ); const json = { username: username.value, guess: guess.value, + timestamp: dateTime, remove: false } + const body = JSON.stringify( json ); fetch( '/submit', { @@ -24,7 +47,8 @@ function main() { return response.text(); }) .then( function ( txt ) { - console.log( JSON.parse(txt) ) + const responseArray = JSON.parse(txt); + updateTable( responseArray ); }) return false; @@ -49,14 +73,31 @@ function main() { return response.text(); }) .then( function ( txt ) { - console.log( JSON.parse(txt) ) + const responseArray = JSON.parse(txt); + updateTable( responseArray ); }) return false; } - const submitButton = document.getElementById("submit"); - const deleteButton = document.getElementById("delete"); - submitButton.onclick = submit; - deleteButton.onclick = deleteUser; + function updateTable( responseArray ) { + const updatedTableBody = document.createElement("tbody"); + updatedTableBody.setAttribute("id", "activeUsersList"); + + for (let i = 0; i < responseArray.length; i++) { + let row = updatedTableBody.insertRow(i); + row.insertCell(0).innerText = responseArray[i].username; + row.insertCell(1).innerText = responseArray[i].guess; + row.insertCell(2).innerText = responseArray[i].status; + row.insertCell(3).innerText = responseArray[i].attempts; + row.insertCell(4).innerText = responseArray[i].timestamp; + } + const currentTable = document.getElementById("activeUsersTable"); + currentTable.replaceChild(updatedTableBody, document.getElementById("activeUsersList")); + } + + + document.getElementById("submit").onclick = submit; + document.getElementById("delete").onclick = deleteUser; + } diff --git a/server.improved.js b/server.improved.js index 08c3eba0..754cf1f3 100644 --- a/server.improved.js +++ b/server.improved.js @@ -14,57 +14,98 @@ const server = http.createServer( function( request,response ) { } }) +// List of users that have entered guesses +let activeUsers = [] +let magicNumber = Math.floor((Math.random() * 10000) + 1).toString(); +console.log(magicNumber) + const handleGet = function( request, response ) { const filename = dir + request.url.slice( 1 ) if( request.url === '/' ) { sendFile( response, 'public/index.html' ) - }else{ + } + else if (request.url === '/table') { + response.end(JSON.stringify(activeUsers)) + } + else{ sendFile( response, filename ) } } -let guesses = [] const handlePost = function( request, response ) { request.on( 'data', function( data ) { const dataObject = JSON.parse(data) - const totalItems = guesses.length - for (let i = 0; i < guesses.length; i++) { + for (let i = 0; i < activeUsers.length; i++) { + + if (dataObject.username === activeUsers[i].username) { + + if (activeUsers[i].win) { + return + } - if (dataObject.username === guesses[i].username) { if (dataObject.remove) { - console.log("deleting entry") - guesses.splice(i, 1) + activeUsers.splice(i, 1) return } else { - guesses[i].guess = dataObject.guess - guesses[i].attempts++ + let status = generateStatus(dataObject.guess) + + activeUsers[i].guess = dataObject.guess + activeUsers[i].status = status + activeUsers[i].attempts++ + activeUsers[i].timestamp = dataObject.timestamp + + if (status === "Winner!") { + activeUsers[i].win = true; + activeUsers[i].guess = "*****" //Hidden from other players + } return } } } - let newStoredGuess = { - username: dataObject.username, - guess: dataObject.guess, - status: "", - attempts: 0, - date: "" - } + if (!dataObject.remove) { - guesses.push(newStoredGuess) + let newStoredGuess = { + win: false, + username: dataObject.username, + guess: dataObject.guess, + status: generateStatus(dataObject.guess), + attempts: 1, + timestamp: dataObject.timestamp + } + + if (newStoredGuess.status === "Winner!") { + newStoredGuess.win = true; + newStoredGuess.guess = "*****" //Hidden from other players + } + + activeUsers.push(newStoredGuess) + } }) request.on( 'end', function() { response.writeHead( 200, "OK", {'Content-Type': 'text/plain' }) - response.end(JSON.stringify(guesses)) + response.end(JSON.stringify(activeUsers)) }) } +function generateStatus(guess) { + if (guess === magicNumber) { + return "Winner!" + } + if ( guess < magicNumber) { + return "Too Low" + } + if ( guess > magicNumber) { + return "Too High" + } +} + const sendFile = function( response, filename ) { const type = mime.getType( filename ) From a130b4ca05c351b7a76cf6a13203137d57226093 Mon Sep 17 00:00:00 2001 From: noahvolson Date: Wed, 16 Sep 2020 16:41:06 -0400 Subject: [PATCH 4/7] Added leaderboard --- public/index.html | 11 +++++++ public/js/main.js | 78 +++++++++++++++++++++++++++++++++++----------- server.improved.js | 11 ++++--- 3 files changed, 78 insertions(+), 22 deletions(-) diff --git a/public/index.html b/public/index.html index 980f7703..e51dd932 100755 --- a/public/index.html +++ b/public/index.html @@ -13,10 +13,21 @@ +

All Players

Username----Guess----Status----Total Attempts----Most Recent Submission----
+ +
+
+
+ +

Rankings

+ + + +
Rank----Username----Total Attempts----Time of Win----
diff --git a/public/js/main.js b/public/js/main.js index 1a4bdfec..d8779d26 100755 --- a/public/js/main.js +++ b/public/js/main.js @@ -10,7 +10,7 @@ function main() { return response.text(); }) .then( function ( txt ) { - updateTable( JSON.parse(txt) ); + updateTables( JSON.parse(txt) ); }) const submit = function( e ) { @@ -18,10 +18,10 @@ function main() { e.preventDefault(); // code snippet for timestamp from: https://phoenixnap.com/kb/how-to-get-the-current-date-and-time-javascript - var today = new Date(); - var date = (today.getMonth()+1)+'/'+today.getDate()+'/'+today.getFullYear(); - var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds(); - var dateTime = date+' '+time; + let today = new Date(); + let date = (today.getFullYear()+'/'+(today.getMonth()+1)+'/'+today.getDate()); + let time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds(); + let dateTime = date+' '+time; const username = document.querySelector( '#username' ); if (username.value === "") { @@ -48,7 +48,7 @@ function main() { }) .then( function ( txt ) { const responseArray = JSON.parse(txt); - updateTable( responseArray ); + updateTables( responseArray ); }) return false; @@ -74,26 +74,68 @@ function main() { }) .then( function ( txt ) { const responseArray = JSON.parse(txt); - updateTable( responseArray ); + updateTables( responseArray ); }) return false; } - function updateTable( responseArray ) { - const updatedTableBody = document.createElement("tbody"); - updatedTableBody.setAttribute("id", "activeUsersList"); + function updateTables( responseArray ) { + + const updatedUserList = document.createElement("tbody"); + updatedUserList.setAttribute("id", "activeUsersList"); + + const updatedRankingsList = document.createElement("tbody"); + updatedRankingsList.setAttribute("id", "rankingsList"); + + let rankings = [] for (let i = 0; i < responseArray.length; i++) { - let row = updatedTableBody.insertRow(i); - row.insertCell(0).innerText = responseArray[i].username; - row.insertCell(1).innerText = responseArray[i].guess; - row.insertCell(2).innerText = responseArray[i].status; - row.insertCell(3).innerText = responseArray[i].attempts; - row.insertCell(4).innerText = responseArray[i].timestamp; + let userRow = updatedUserList.insertRow(i); + userRow.insertCell(0).innerText = responseArray[i].username; + userRow.insertCell(1).innerText = responseArray[i].guess; + userRow.insertCell(2).innerText = responseArray[i].status; + userRow.insertCell(3).innerText = responseArray[i].attempts; + userRow.insertCell(4).innerText = responseArray[i].timestamp; + + if (responseArray[i].win){ + + let placed = false; + + for (let j = 0; j < rankings.length; j++) { + + // if attempts are equal, timestamp is tiebreaker + if (responseArray[i].attempts > rankings[j].attempts + || responseArray[i].attempts === rankings[j].attempts && + (new Date(responseArray[i].timestamp).getTime() > new Date(rankings[j].timestamp).getTime())) { + + rankings.splice(j, 0, responseArray[i]); + placed = true; + break; + } + } + + if (!placed) { + rankings.push(responseArray[i]); + } + } + } + + rankings.reverse(); + + for (let k = 0; k < rankings.length; k++) { + let rankingsRow = updatedRankingsList.insertRow(k); + rankingsRow.insertCell(0).innerText = (k + 1).toString(); + rankingsRow.insertCell(1).innerText = rankings[k].username; + rankingsRow.insertCell(2).innerText = rankings[k].attempts; + rankingsRow.insertCell(3).innerText = rankings[k].timestamp; } - const currentTable = document.getElementById("activeUsersTable"); - currentTable.replaceChild(updatedTableBody, document.getElementById("activeUsersList")); + + const currentUserTable = document.getElementById("activeUsersTable"); + currentUserTable.replaceChild(updatedUserList, document.getElementById("activeUsersList")); + + const currentRankingsTable = document.getElementById("rankingsTable"); + currentRankingsTable.replaceChild(updatedRankingsList, document.getElementById("rankingsList")); } diff --git a/server.improved.js b/server.improved.js index 754cf1f3..0010e839 100644 --- a/server.improved.js +++ b/server.improved.js @@ -16,7 +16,7 @@ const server = http.createServer( function( request,response ) { // List of users that have entered guesses let activeUsers = [] -let magicNumber = Math.floor((Math.random() * 10000) + 1).toString(); +let magicNumber = Math.floor((Math.random() * 10000) + 1); console.log(magicNumber) const handleGet = function( request, response ) { @@ -95,13 +95,16 @@ const handlePost = function( request, response ) { } function generateStatus(guess) { - if (guess === magicNumber) { + + let guessAsInt = parseInt(guess, 10) + + if (guessAsInt === magicNumber) { return "Winner!" } - if ( guess < magicNumber) { + if ( guessAsInt < magicNumber) { return "Too Low" } - if ( guess > magicNumber) { + if ( guessAsInt > magicNumber) { return "Too High" } } From 6070a5304b89e7a99feec4532f3cd7e86275326d Mon Sep 17 00:00:00 2001 From: noahvolson Date: Wed, 16 Sep 2020 21:06:44 -0400 Subject: [PATCH 5/7] Styled page with flexbox --- public/css/style.css | 90 +++++++++++++++++- public/index.html | 46 +++++---- public/js/main.js | 217 ++++++++++++++++++++++--------------------- 3 files changed, 229 insertions(+), 124 deletions(-) diff --git a/public/css/style.css b/public/css/style.css index d5f842ab..c909eb78 100755 --- a/public/css/style.css +++ b/public/css/style.css @@ -1 +1,89 @@ -/*Style your own assignment! This is fun! */ \ No newline at end of file +/*Style your own assignment! This is fun! */ +body { + display: flex; + flex-direction: column; + font-family: 'Oxygen', serif; + font-size: 18px; + background-color: #383240; + color: white; +} + +h3 { + text-align: center; +} + +th { + text-align: left; + padding-right: 40px; +} + +table { + display: table; + padding: 10px; + border: 1px solid white; + border-bottom: none; +} + +#inputForm { + align-self: center; + margin-bottom: 40px; +} + +#pageTitle { +text-align: center; +} + +#creditLine { + position: absolute; + bottom: 0; + align-self: center; + font-weight: lighter; + color: #bcbcbc; + opacity: 50%; +} + +#results { + display: flex; +} + +#activeUsersTable { + width: 775px; +} + +#rankingsTable { + width: 590px; +} + +#submit { + background-color: #6a11a4; +} +#delete { + background-color: #5d17b8; +} +#refresh { + background-color: #3c15b0; +} + +.shiftedLeft { + margin-left: 20px; +} + +.standardButton { + font-weight: bold; + color: white; + border: none; + text-decoration: none; + text-align: center; + padding: 5px 10px; + font-size: 16px; +} + +.standardButton:hover { + opacity: 70%; +} + +.inputLine { + font-size: 16px; + padding: 4px; + border: 1px solid gray; +} diff --git a/public/index.html b/public/index.html index e51dd932..29e81525 100755 --- a/public/index.html +++ b/public/index.html @@ -4,30 +4,38 @@ Noah Olson A2 + + -
- - - - + + +

Guess My Number!

+ + + + +
-

All Players

- - - -
Username----Guess----Status----Total Attempts----Most Recent Submission----
+
+
+

All Players

+ + + +
UsernameGuessStatusTotal AttemptsMost Recent Submission
+
- -
-
-
+
+

Rankings

+ + + +
RankUsernameTotal AttemptsTime of Win
+
+
-

Rankings

- - - -
Rank----Username----Total Attempts----Time of Win----
+
Created by Noah Olson for CS 4241 Webware Assignment A2
diff --git a/public/js/main.js b/public/js/main.js index d8779d26..7636e3e1 100755 --- a/public/js/main.js +++ b/public/js/main.js @@ -2,144 +2,153 @@ function main() { + refreshData(); + document.getElementById("submit").onclick = submit; + document.getElementById("delete").onclick = deleteUser; + document.getElementById("refresh").onclick = refreshButtonClicked; +} + +const refreshButtonClicked = function (e) { + // prevent default form action from being carried out + e.preventDefault(); + refreshData(); +} + +function refreshData() { // On page load, pull any existing guesses from server - fetch ('/table', { + fetch('/table', { method: 'GET' }) - .then( function( response ) { + .then(function (response) { return response.text(); }) - .then( function ( txt ) { - updateTables( JSON.parse(txt) ); + .then(function (txt) { + updateTables(JSON.parse(txt)); }) +} - const submit = function( e ) { - // prevent default form action from being carried out - e.preventDefault(); +const submit = function (e) { + // prevent default form action from being carried out + e.preventDefault(); - // code snippet for timestamp from: https://phoenixnap.com/kb/how-to-get-the-current-date-and-time-javascript - let today = new Date(); - let date = (today.getFullYear()+'/'+(today.getMonth()+1)+'/'+today.getDate()); - let time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds(); - let dateTime = date+' '+time; + // code snippet for timestamp from: https://phoenixnap.com/kb/how-to-get-the-current-date-and-time-javascript + let today = new Date(); + let date = (today.getFullYear() + '/' + (today.getMonth() + 1) + '/' + today.getDate()); + let time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds(); + let dateTime = date + ' ' + time; - const username = document.querySelector( '#username' ); - if (username.value === "") { - return false - } + const username = document.querySelector('#username'); + if (username.value === "") { + return false + } - const guess = document.querySelector( '#guess' ); - const json = { - username: username.value, - guess: guess.value, - timestamp: dateTime, - remove: false - } + const guess = document.querySelector('#guess'); + const json = { + username: username.value, + guess: guess.value, + timestamp: dateTime, + remove: false + } - const body = JSON.stringify( json ); + const body = JSON.stringify(json); - fetch( '/submit', { - method:'POST', - body: body + fetch('/submit', { + method: 'POST', + body: body + }) + .then(function (response) { + // do something with the reponse + return response.text(); + }) + .then(function (txt) { + const responseArray = JSON.parse(txt); + updateTables(responseArray); }) - .then( function( response ) { - // do something with the reponse - return response.text(); - }) - .then( function ( txt ) { - const responseArray = JSON.parse(txt); - updateTables( responseArray ); - }) - - return false; - } - const deleteUser = function( e ) { - // prevent default form action from being carried out - e.preventDefault(); - const username = document.querySelector( '#username' ); - const json = { - username: username.value, - remove: true - } - const body = JSON.stringify( json ); + return false; +} - fetch( '/submit', { - method:'POST', - body: body - }) - .then( function( response ) { - // do something with the reponse - return response.text(); - }) - .then( function ( txt ) { - const responseArray = JSON.parse(txt); - updateTables( responseArray ); - }) - - return false; +const deleteUser = function (e) { + // prevent default form action from being carried out + e.preventDefault(); + const username = document.querySelector('#username'); + const json = { + username: username.value, + remove: true } + const body = JSON.stringify(json); + + fetch('/submit', { + method: 'POST', + body: body + }) + .then(function (response) { + // do something with the reponse + return response.text(); + }) + .then(function (txt) { + const responseArray = JSON.parse(txt); + updateTables(responseArray); + }) - function updateTables( responseArray ) { + return false; +} - const updatedUserList = document.createElement("tbody"); - updatedUserList.setAttribute("id", "activeUsersList"); +function updateTables(responseArray) { - const updatedRankingsList = document.createElement("tbody"); - updatedRankingsList.setAttribute("id", "rankingsList"); + const updatedUserList = document.createElement("tbody"); + updatedUserList.setAttribute("id", "activeUsersList"); - let rankings = [] + const updatedRankingsList = document.createElement("tbody"); + updatedRankingsList.setAttribute("id", "rankingsList"); - for (let i = 0; i < responseArray.length; i++) { - let userRow = updatedUserList.insertRow(i); - userRow.insertCell(0).innerText = responseArray[i].username; - userRow.insertCell(1).innerText = responseArray[i].guess; - userRow.insertCell(2).innerText = responseArray[i].status; - userRow.insertCell(3).innerText = responseArray[i].attempts; - userRow.insertCell(4).innerText = responseArray[i].timestamp; + let rankings = [] - if (responseArray[i].win){ + for (let i = 0; i < responseArray.length; i++) { + let userRow = updatedUserList.insertRow(i); + userRow.insertCell(0).innerText = responseArray[i].username; + userRow.insertCell(1).innerText = responseArray[i].guess; + userRow.insertCell(2).innerText = responseArray[i].status; + userRow.insertCell(3).innerText = responseArray[i].attempts; + userRow.insertCell(4).innerText = responseArray[i].timestamp; - let placed = false; + if (responseArray[i].win) { - for (let j = 0; j < rankings.length; j++) { + let placed = false; - // if attempts are equal, timestamp is tiebreaker - if (responseArray[i].attempts > rankings[j].attempts - || responseArray[i].attempts === rankings[j].attempts && - (new Date(responseArray[i].timestamp).getTime() > new Date(rankings[j].timestamp).getTime())) { + for (let j = 0; j < rankings.length; j++) { - rankings.splice(j, 0, responseArray[i]); - placed = true; - break; - } - } + // if attempts are equal, timestamp is tiebreaker + if (responseArray[i].attempts > rankings[j].attempts + || responseArray[i].attempts === rankings[j].attempts && + (new Date(responseArray[i].timestamp).getTime() > new Date(rankings[j].timestamp).getTime())) { - if (!placed) { - rankings.push(responseArray[i]); + rankings.splice(j, 0, responseArray[i]); + placed = true; + break; } } - } - - rankings.reverse(); - for (let k = 0; k < rankings.length; k++) { - let rankingsRow = updatedRankingsList.insertRow(k); - rankingsRow.insertCell(0).innerText = (k + 1).toString(); - rankingsRow.insertCell(1).innerText = rankings[k].username; - rankingsRow.insertCell(2).innerText = rankings[k].attempts; - rankingsRow.insertCell(3).innerText = rankings[k].timestamp; + if (!placed) { + rankings.push(responseArray[i]); + } } + } - const currentUserTable = document.getElementById("activeUsersTable"); - currentUserTable.replaceChild(updatedUserList, document.getElementById("activeUsersList")); + rankings.reverse(); - const currentRankingsTable = document.getElementById("rankingsTable"); - currentRankingsTable.replaceChild(updatedRankingsList, document.getElementById("rankingsList")); + for (let k = 0; k < rankings.length; k++) { + let rankingsRow = updatedRankingsList.insertRow(k); + rankingsRow.insertCell(0).innerText = (k + 1).toString(); + rankingsRow.insertCell(1).innerText = rankings[k].username; + rankingsRow.insertCell(2).innerText = rankings[k].attempts; + rankingsRow.insertCell(3).innerText = rankings[k].timestamp; } + const currentUserTable = document.getElementById("activeUsersTable"); + currentUserTable.replaceChild(updatedUserList, document.getElementById("activeUsersList")); - document.getElementById("submit").onclick = submit; - document.getElementById("delete").onclick = deleteUser; - + const currentRankingsTable = document.getElementById("rankingsTable"); + currentRankingsTable.replaceChild(updatedRankingsList, document.getElementById("rankingsList")); } + From 0b9287a30b3596b9dfc73f186b7e5b24318fae4a Mon Sep 17 00:00:00 2001 From: noahvolson Date: Wed, 16 Sep 2020 21:44:45 -0400 Subject: [PATCH 6/7] Initial README edits, need glitch URL --- README.md | 113 ++++++++++++------------------------------------------ 1 file changed, 25 insertions(+), 88 deletions(-) diff --git a/README.md b/README.md index 3945c152..c309e754 100755 --- a/README.md +++ b/README.md @@ -1,93 +1,30 @@ -Assignment 2 - Short Stack: Basic Two-tier Web Application using HTML/CSS/JS and Node.js -=== +## CS 4241 Webware Assignment A2 +Noah Olson - nvolson@wpi.edu - noahvolson -Due: September 16th, by 11:59 PM. +Glitch URL: -This assignment aims to introduce you to the concepts and practice involved in creating a prototype (i.e. not deployment ready) two-tiered web application. The baseline aims of this assignment involve creating an application that demonstrates the use of several specific pieces of HTML, CSS, JavaScript, and Node.js functionality. +For this assignment, I have created an online multiplayer +number guessing game. To begin, enter a username and your +guess. The server will respond and tell you whether your +guess was higher or lower than its number. The fewer guesses +it takes to figure out the number, the higher your position +on the scoreboard! I hope to encourage users to "metagame" by +looking at each others answers. However, don't wait too long +as winning users will have their last guess obstructed from view! -Baseline Requirements ---- - -Note that there is a very large range of application areas and possibilities that meet these baseline requirements. 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 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 `
    ` could also work and might be simpler to work with. -- All pages should [validate](https://validator.w3.org) - -CSS: -- CSS styling of the primary visual elements in the application -- Various CSS Selector functionality must be demonstrated: - - Element selectors - - ID selectors - - Class selectors -- CSS positioning and styling of the primary visual elements in the application: - - Use of either a CSS grid or flexbox for layout - - Rules defining fonts for all text used; no default fonts! Be sure to use a web safe font or a font from a web service like [Google Fonts](http://fonts.google.com/) - -- CSS defined in a maintainable, readable form, in external stylesheets - -JavaScript: -- At minimum, a small amount of front-end JavaScript to get / fetch data from the server; a sample is provided in this repository. - -Node.js: -- An HTTP Server that delivers all necessary files and data for the application. A starting point is provided in this repository. - -Deliverables ---- - -Do the following to complete this assignment and acheive a base grade of 85%: - -1. Fork the starting project code (make sure to fork the 2020 repo!). This repo contains some starter code that may be used or discarded as needed. -2. Implement your project with the above requirements. -3. Test your project to make sure that when someone goes to your main page, it displays correctly. -4. Deploy your project to Glitch, and fill in the appropriate fields in your package.json file. -5. Ensure that your project has the proper naming scheme `a2-yourname` so we can find it. -6. Modify the README to the specifications below. -7. Create and submit a Pull Request to the original repo. Label the pull request as follows: a2-gitusername-firstname-lastname - -Acheivements ---- - -Below are suggested technical and design achievements. You can use these to help boost your grade up to an A and customize the assignment to your personal interests. These are recommended acheivements, but feel free to create/implement your own... just make sure you thoroughly describe what you did in your README and why it was challenging. ALL ACHIEVEMENTS MUST BE DESCRIBED IN YOUR README IN ORDER TO GET CREDIT FOR THEM. - -*Technical* -- (10 points) Create a single-page app that both provides a form for users to submit data and always shows the current state of the server-side data. To put it another way, when the user submits data, the server should respond sending back the updated data (including the derived field calculated on the server) and the client should then update its data display. - -*Design/UX* -- (5 points per person, with a max of 10 points) Test your user interface with other students in the class. Define a specific task for them to complete (ideally something short that takes <10 minutes), and then use the [think-aloud protocol](https://en.wikipedia.org/wiki/Think_aloud_protocol) to obtain feedback on your design (talk-aloud is also find). Important considerations when designing your study: - -1. Make sure you start the study by clearly stating the task that you expect your user to accomplish. -2. You shouldn't provide any verbal instructions on how to use your interface / accomplish the task you give them. Make sure that your interface is clear enough that users can figure it out without any instruction, or provide text instructions from within the interface itself. -3. If users get stuck to the point where they give up, you can then provde instruction so that the study can continue, but make sure to discuss this in your README. You won't lose any points for this... all feedback is good feedback! - -You'll need to use sometype of collaborative software that will enable you both to see the test subject's screen and listen to their voice as they describe their thoughts. After completing each study, briefly (one to two sentences for each question) address the following in your README: - -1. Provide the last name of each student you conduct the evaluation with. -2. What problems did the user have with your design? -3. What comments did they make that surprised you? -4. What would you change about the interface based on their feedback? - -*You do not need to actually make changes based on their feedback*. This acheivement is designed to help gain experience testing user interfaces. If you run two user studies, you should answer two sets of questions. - -Sample Readme (delete the above when you're ready to submit, and modify the below so with your links and descriptions) ---- - -## Your Web Application Title -Include a very brief summary of your project here. Be sure to include the CSS positioning technique you used, and any required instructions to use your application. +I used flexbox to position my elements. ## Technical Achievements -- **Tech Achievement 1**: Using a combination of... - -### Design/Evaluation Achievements -- **Design Achievement 1**: +- **Tech Achievement 1**: My application displays the current + state of server data (user info) + at all times. Additionally, I have added an easy-access + button to refresh all tables. + +- **Tech Achievement 1**: My application supports adding, updating, +and deleting of guesses. + - Adding is accomplished by clicking the submit + button after entering username and guess data. + - Updating is accomplished by clicking the submit button with + an existing username and new guess + - Deleting is accomplished by clicking the delete button with an + existing username in its respective field From f3282438606c3d847f734c70b8a376e153f26fd0 Mon Sep 17 00:00:00 2001 From: noahvolson Date: Wed, 16 Sep 2020 21:57:27 -0400 Subject: [PATCH 7/7] Added glitch URL and notes to README --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c309e754..55f79b63 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## CS 4241 Webware Assignment A2 Noah Olson - nvolson@wpi.edu - noahvolson -Glitch URL: +Glitch URL: https://a2-noaholson.glitch.me/ For this assignment, I have created an online multiplayer number guessing game. To begin, enter a username and your @@ -20,7 +20,7 @@ I used flexbox to position my elements. at all times. Additionally, I have added an easy-access button to refresh all tables. -- **Tech Achievement 1**: My application supports adding, updating, +- **Tech Achievement 2**: My application supports adding, updating, and deleting of guesses. - Adding is accomplished by clicking the submit button after entering username and guess data. @@ -28,3 +28,8 @@ and deleting of guesses. an existing username and new guess - Deleting is accomplished by clicking the delete button with an existing username in its respective field + +## Notes +- You cannot delete a user once they have won the game +- Code snippet was used from: https://phoenixnap.com/kb/how-to-get-the-current-date-and-time-javascript +for the current time and date