From 9ad43f73e29dfc00473ae911f2e38bc7f0eaea02 Mon Sep 17 00:00:00 2001 From: seansta18 Date: Tue, 27 Sep 2022 12:55:50 -0400 Subject: [PATCH 01/64] Proposal updated --- Proposal.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Proposal.md diff --git a/Proposal.md b/Proposal.md new file mode 100644 index 000000000..0802f2dee --- /dev/null +++ b/Proposal.md @@ -0,0 +1,6 @@ +# Final Project Proposal (due 9/27) +# By Sean McMillan, Liliana Foucault, JR Kim, and Jacob Van Steyn + +For our project, we are planning on creating a webpage with three seperate clicking games. There will be a main page with a login option along with buttons to move to different games. The three games we are planning on creating are a clicks per second test, reaction time test, and a mouse accuracy test. The clicks per second test will have a single button that the user will click for 10 seconds. During this time, we will record the number of clicks to calculate their clicks per second. For the reaction time test, three buttons will show up with only one of them being green. The overall score for this test will be calculated by overall time plus extra time for clicking the wrong button. And for the mouse accuracy test, a button will randomly appear somewhere on a screen and, once it is clicked, another will appear in a different location. This games score will be calculated by overall time it takes to click 10 buttons. Along with these games, there will be a leaderboard with the best scored from each of the games which users can be added to once logged in. + +We plan on using a few different libraries and technologies for this project. For authentication and the leaderboard, we plan on using MongoDB to keep consistent data across different clients. We also plan on using React for some of the games like placing buttons randomly on the screen. We also plan on using express along with express middleware packages for the server. \ No newline at end of file From 5face1c7bd319ff3ae19ce5c3bcca1b34c181ac2 Mon Sep 17 00:00:00 2001 From: jrkim-wpi <46631460+jrkim-wpi@users.noreply.github.com> Date: Wed, 28 Sep 2022 21:27:04 -0400 Subject: [PATCH 02/64] Update Proposal.md --- Proposal.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Proposal.md b/Proposal.md index 0802f2dee..9def002d2 100644 --- a/Proposal.md +++ b/Proposal.md @@ -1,6 +1,6 @@ # Final Project Proposal (due 9/27) -# By Sean McMillan, Liliana Foucault, JR Kim, and Jacob Van Steyn +# By Sean McMillan, Liliana Foucault, Jin Ryoul Kim, and Jacob Van Steyn For our project, we are planning on creating a webpage with three seperate clicking games. There will be a main page with a login option along with buttons to move to different games. The three games we are planning on creating are a clicks per second test, reaction time test, and a mouse accuracy test. The clicks per second test will have a single button that the user will click for 10 seconds. During this time, we will record the number of clicks to calculate their clicks per second. For the reaction time test, three buttons will show up with only one of them being green. The overall score for this test will be calculated by overall time plus extra time for clicking the wrong button. And for the mouse accuracy test, a button will randomly appear somewhere on a screen and, once it is clicked, another will appear in a different location. This games score will be calculated by overall time it takes to click 10 buttons. Along with these games, there will be a leaderboard with the best scored from each of the games which users can be added to once logged in. -We plan on using a few different libraries and technologies for this project. For authentication and the leaderboard, we plan on using MongoDB to keep consistent data across different clients. We also plan on using React for some of the games like placing buttons randomly on the screen. We also plan on using express along with express middleware packages for the server. \ No newline at end of file +We plan on using a few different libraries and technologies for this project. For authentication and the leaderboard, we plan on using MongoDB to keep consistent data across different clients. We also plan on using React for some of the games like placing buttons randomly on the screen. We also plan on using express along with express middleware packages for the server. From 48b46626b98e9f961d678326e626ce874a8ddcd0 Mon Sep 17 00:00:00 2001 From: seansta18 Date: Tue, 4 Oct 2022 12:53:32 -0400 Subject: [PATCH 03/64] Set up main html as well as different folders for the project --- README.md | 49 ------------------------------------------------ public/main.html | 25 ++++++++++++++++++++++++ server.js | 0 3 files changed, 25 insertions(+), 49 deletions(-) create mode 100644 public/main.html create mode 100644 server.js diff --git a/README.md b/README.md index e5b5ca55b..e69de29bb 100644 --- a/README.md +++ b/README.md @@ -1,49 +0,0 @@ -# Final Project -*Due before the start of class, October 13th (final day of the term)* - -For your final project, you'll implement a web application that exhibits understanding of the course materials. -This project should provide an opportunity to both be creative and to pursue individual research and learning goals. - -## General description -Your project should consist of a complete Web application, exhibiting facets of the three main sections of the course material: - -- Static web page content and design. You should have a project that is accessible, easily navigable, and features significant content. -- Dynamic behavior implemented with JavaScript (TypeScript is also allowed if your group wants to explore it). -- Server-side programming *using Node.js*. Typically this will take the form of some sort of persistent data (database), authentication, and possibly server-side computation. -- A video (less than five minutes) where each group member explains some aspect of the project. An easy way to produce this video is for you all the groups members to join a Zoom call that is recorded; each member can share their screen when they discuss the project or one member can "drive" the interface while other members narrate (this second option will probably work better.) The video should be posted on YouTube or some other accessible video hosting service. Make sure your video is less than five minutes, but long enough to successfully explain your project and show it in action. There is no minimum video length. - -## Project ideation -Excellent projects typically serve someone/some group; for this assignment you need to define your users and stakeholders. I encourage you to identify projects that will have impact, either artistically, politically, or in terms of productivity. - -### Deliverables - -#### Form Team (due 9/25) -Students are will work in teams of 3-5 students for the project; teams of two can be approved with the permission of the instructor. Working in teams should help enable you to build a good project in a limited amount of time. Use the `#project-logistics` channel in Discord to pitch ideas for final projects and/or find fellow team members as needed. - -Teams must be in place by end of day on Sunday, September 25th. If you have not identified a team at this point, you will be assigned a team. You will be given some class time on Monday to work on your proposal, but please plan on reserving additional time outside of class as needed. - -#### Proposal (due 9/27) -Provide an outline of your project direction and the names of associated team members. -The outline should have enough detail so that staff can determine if it meets the minimum expectations, or if it goes too far to be reasonable by the deadline. Please include a general description of a project, and list of key technologies/libraries you plan on using (e.g. React, Three.js, Svelte, TypeScript etc.). Two to four paragraps should provide enough level of detail. Name the file proposal.md and submit a pull request by Tuesday, September 27th at 11:59 PM (end of day). Only one pull request is required per team. - -There are no other scheduled checkpoints for your project. - -#### Turning in Your Project -Submit a second PR on the final project repo to turn in your app and code. Again, only one pull request per team. - -Deploy your app, in the form of a webpage, to Glitch/Heroku/Digital Ocean or some other service; it is critical that the application functions correctly wherever you post it. - -The README for your second pull request doesn’t need to be a formal report, but it should contain: - -1. A brief description of what you created, and a link to the project itself (two paragraphs of text) -2. Any additional instructions that might be needed to fully use your project (login information etc.) -3. An outline of the technologies you used and how you used them. -4. What challenges you faced in completing the project. -5. What each group member was responsible for designing / developing. -6. A link to your project video. - -Think of 1,3, and 4 in particular in a similar vein to the design / tech achievements for A1—A4… make a case for why what you did was challenging and why your implementation deserves a grade of 100%. - -## FAQs - -- **Can I use XYZ framework?** You can use any web-based frameworks or tools available, but for your server programming you need to use Node.js. Your client-side scripting language should be either JavaScript or TypeScript. diff --git a/public/main.html b/public/main.html new file mode 100644 index 000000000..9aaac6133 --- /dev/null +++ b/public/main.html @@ -0,0 +1,25 @@ + + + + CS4241 Final Project + + +

+ Final Project By Sean, Liliana, Jacob, and JR +

+ +

+ To read more about the project, visit the README.md file. For our project we created a few different + clicking tests. The first is clicks per second to see how many clicks the user can do in 10 seconds. The second is + a reaction time test. There will be three buttons that pop up with only one of them being green. This score will be determined by + how fast the user can get 5 correct. Finally the last test is a mouse accuracy test. Buttons will pop up randomly on the screen in different locations + and the user must move their cursor to press 5 of them. We also have a leaderboard page as well to see logged in users best scores. +

+ + + + + + + + \ No newline at end of file diff --git a/server.js b/server.js new file mode 100644 index 000000000..e69de29bb From 34a80fe09174f53cb9fa5376a0ae6f5213b34a56 Mon Sep 17 00:00:00 2001 From: Jacob van Steyn Date: Fri, 7 Oct 2022 14:18:34 -0400 Subject: [PATCH 04/64] add files & begin implementing games --- .gitignore | 61 + app.js | 74 ++ bin/www | 90 ++ models/Results.js | 34 + models/User.js | 22 + package-lock.json | 2165 +++++++++++++++++++++++++++++++++ package.json | 24 + public/javascripts/scripts.js | 6 + public/main.html | 25 - public/stylesheets/style.css | 8 + routes/auth.js | 58 + routes/games.js | 26 + routes/index.js | 46 + server.js | 0 views/accuracy.ejs | 3 + views/cps.ejs | 3 + views/error.ejs | 3 + views/footer.ejs | 49 + views/header.ejs | 59 + views/index.ejs | 70 ++ views/leaderboard.ejs | 3 + views/reaction.ejs | 3 + 22 files changed, 2807 insertions(+), 25 deletions(-) create mode 100644 .gitignore create mode 100644 app.js create mode 100755 bin/www create mode 100644 models/Results.js create mode 100644 models/User.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/javascripts/scripts.js delete mode 100644 public/main.html create mode 100644 public/stylesheets/style.css create mode 100644 routes/auth.js create mode 100644 routes/games.js create mode 100644 routes/index.js delete mode 100644 server.js create mode 100644 views/accuracy.ejs create mode 100644 views/cps.ejs create mode 100644 views/error.ejs create mode 100644 views/footer.ejs create mode 100644 views/header.ejs create mode 100644 views/index.ejs create mode 100644 views/leaderboard.ejs create mode 100644 views/reaction.ejs diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..d1bed128f --- /dev/null +++ b/.gitignore @@ -0,0 +1,61 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# next.js build output +.next diff --git a/app.js b/app.js new file mode 100644 index 000000000..1624f71fd --- /dev/null +++ b/app.js @@ -0,0 +1,74 @@ +require('dotenv').config(); + +const createError = require('http-errors'); +const express = require('express'); +const path = require('path'); +const cookieParser = require('cookie-parser'); +const session = require('express-session'); +const csrf = require('csurf'); +const passport = require('passport'); +const logger = require('morgan'); +const mongoose = require('mongoose'); + + +var indexRouter = require('./routes/index'); +var authRouter = require('./routes/auth'); + +var app = express(); + +mongoose.Promise = global.Promise; +mongoose.connect(process.env['URI']) + .then(() => console.log('Connected to MongoDB')) + .catch((err) => console.error(err)); + + +// view engine setup +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'ejs'); + +app.use(logger('common')); +app.use(cookieParser()); +app.use(express.json()); +app.use(express.urlencoded({ extended: false })); +app.use(express.static(path.join(__dirname, 'public'))); +app.use(session({ + secret: 'secRet!', + resave: true, + saveUninitialized: false +})); +app.use(passport.initialize()); +app.use(passport.session()) +app.use(csrf()); +//app.use(passport.authenticate('session')); +app.use(function(req, res, next) { + var msgs = req.session.messages || []; + res.locals.messages = msgs; + res.locals.hasMessages = !! msgs.length; + req.session.messages = []; + next(); +}); +app.use(function(req, res, next) { + res.locals.csrfToken = req.csrfToken(); + next(); +}); + +app.use('/', indexRouter); +app.use('/', authRouter); + +// catch 404 and forward to error handler +app.use(function(req, res, next) { + next(createError(404)); +}); + +// error handler +app.use(function(err, req, res, next) { + // set locals, only providing error in development + res.locals.message = err.message; + res.locals.error = req.app.get('env') === 'development' ? err : {}; + + // render the error page + res.status(err.status || 500); + res.render('error'); +}); + +module.exports = app; diff --git a/bin/www b/bin/www new file mode 100755 index 000000000..e36999f87 --- /dev/null +++ b/bin/www @@ -0,0 +1,90 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var app = require('../app'); +var debug = require('debug')('final-project:server'); +var http = require('http'); + +/** + * Get port from environment and store in Express. + */ + +var port = normalizePort(process.env.PORT || '3000'); +app.set('port', port); + +/** + * Create HTTP server. + */ + +var server = http.createServer(app); + +/** + * Listen on provided port, on all network interfaces. + */ + +server.listen(port); +server.on('error', onError); +server.on('listening', onListening); + +/** + * Normalize a port into a number, string, or false. + */ + +function normalizePort(val) { + var port = parseInt(val, 10); + + if (isNaN(port)) { + // named pipe + return val; + } + + if (port >= 0) { + // port number + return port; + } + + return false; +} + +/** + * Event listener for HTTP server "error" event. + */ + +function onError(error) { + if (error.syscall !== 'listen') { + throw error; + } + + var bind = typeof port === 'string' + ? 'Pipe ' + port + : 'Port ' + port; + + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + console.error(bind + ' requires elevated privileges'); + process.exit(1); + break; + case 'EADDRINUSE': + console.error(bind + ' is already in use'); + process.exit(1); + break; + default: + throw error; + } +} + +/** + * Event listener for HTTP server "listening" event. + */ + +function onListening() { + var addr = server.address(); + var bind = typeof addr === 'string' + ? 'pipe ' + addr + : 'port ' + addr.port; + debug('Listening on ' + bind); +} diff --git a/models/Results.js b/models/Results.js new file mode 100644 index 000000000..3772de7be --- /dev/null +++ b/models/Results.js @@ -0,0 +1,34 @@ +const mongoose = require("mongoose"); +let Schema = mongoose.Schema; + +let ResultsSchema = new Schema( + { + owner_id: {type: String, required: true}, + game_type: {type: String, required: true, enum: ["cps", "accuracy", "reaction"]}, + score: { + type: Number, + required: [true, "A score is required!"]}, + time: {type: Date, default: new Date()} + }, + { timestamps: true } +); + +ResultsSchema.index({ game_type: 1, score: 1 }); + +ResultsSchema.statics.findOrCreate = require("find-or-create"); + +ResultsSchema.statics.getAllResultsForGame = function(game) { + return this.find({game_type: game}) +} + +ResultsSchema.statics.getResultsForUserId = function(user_id) { + return this.find({owner_id: user_id}) +} + +ResultsSchema.statics.getRankforScore = function(game, score) { + + var numGreaterThan = this.distinct({game_type: game, score: { $gt: score}}).count(); + return null; +} + +module.exports = mongoose.model("results", ResultsSchema, "results"); \ No newline at end of file diff --git a/models/User.js b/models/User.js new file mode 100644 index 000000000..f0753530f --- /dev/null +++ b/models/User.js @@ -0,0 +1,22 @@ +const mongoose = require("mongoose"); +let Schema = mongoose.Schema; + +let UserSchema = new Schema( + { + id: { type: String, sparse: true}, + email: { + type: String, + required: [true, "Email is required!"], + unique: [true, "Email already registered"], + sparse: true }, + username: {type: String, required: true}, + displayName: String, + profilePhoto: String, + lastVisited: { type: Date, default: new Date() }, + }, + { timestamps: true } +); + +UserSchema.statics.findOrCreate = require("find-or-create"); + +module.exports = mongoose.model("user", UserSchema, "users"); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..4e18e41cf --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2165 @@ +{ + "name": "final-project", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "final-project", + "version": "0.0.0", + "dependencies": { + "cookie-parser": "~1.4.4", + "csurf": "^1.11.0", + "debug": "~2.6.9", + "dotenv": "^16.0.2", + "ejs": "^3.1.8", + "express": "~4.16.1", + "express-session": "^1.17.3", + "find-or-create": "^2.0.0", + "http-errors": "~1.6.3", + "mongodb": "^4.9.1", + "mongoose": "^6.6.0", + "morgan": "~1.9.1", + "passport": "^0.6.0", + "passport-github": "^1.1.0" + } + }, + "node_modules/@types/node": { + "version": "18.8.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.2.tgz", + "integrity": "sha512-cRMwIgdDN43GO4xMWAfJAecYn8wV4JbsOGHNfNUIDiuYkUYAR5ec4Rj7IO2SAhFPEfpPtLtUTbbny/TCT7aDwA==" + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" + }, + "node_modules/@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "dependencies": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha512-YQyoqQG3sO8iCmf8+hyVpgHHOv0/hCEFiS4zTGUwTA1HjAFX66wRcNQrVCeJq9pgESMRvUAOvSil5MJlmccuKQ==", + "dependencies": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/bson": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.0.tgz", + "integrity": "sha512-VrlEE4vuiO1WTpfof4VmaVolCVYkYTgB9iWgYNOrVlnifpME/06fhFRmONgBhClD5pFC1t9ZWqFUQEQAzY43bA==", + "dependencies": { + "buffer": "^5.6.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/csrf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.1.0.tgz", + "integrity": "sha512-uTqEnCvWRk042asU6JtapDTcJeeailFy4ydOQS28bj1hcLnYRiqi8SsD2jS412AY1I/4qdOwWZun774iqywf9w==", + "dependencies": { + "rndm": "1.2.0", + "tsscmp": "1.0.6", + "uid-safe": "2.1.5" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/csurf": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.11.0.tgz", + "integrity": "sha512-UCtehyEExKTxgiu8UHdGvHj4tnpE/Qctue03Giq5gPgMQ9cg/ciod5blZQ5a4uCEenNQjxyGuzygLdKUmee/bQ==", + "deprecated": "Please use another csrf package", + "dependencies": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "csrf": "3.1.0", + "http-errors": "~1.7.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/csurf/node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/csurf/node_modules/http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/csurf/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/csurf/node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/csurf/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==" + }, + "node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "dependencies": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.3", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-session": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "dependencies": { + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-session/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express-session/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/express/node_modules/cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha512-+IJOX0OqlHCszo2mBUq+SrEbCj6w7Kpffqx60zYbPTFaO4+yYgRjHwcZNpWvaTylDHaV7PPmBHzSecZiMhtPgw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-or-create": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-or-create/-/find-or-create-2.0.0.tgz", + "integrity": "sha512-XOFTRwmFTkT+/PplVsteHw+i/acxSXT8kijOR2RBeBO6Gj4jwaBMEtVMSMNQPfKq2x/pgot75JFuacXA0BCj1Q==", + "deprecated": "Unmaintained" + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/kareem": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.4.1.tgz", + "integrity": "sha512-aJ9opVoXroQUPfovYP5kaj2lM7Jn02Gw13bL0lg9v0V7SaUc0qavPs0Eue7d2DcC3NjqI6QAUElXNsuZSeM+EA==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "bin": { + "mime": "cli.js" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mongodb": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.10.0.tgz", + "integrity": "sha512-My2QxLTw0Cc1O9gih0mz4mqo145Jq4rLAQx0Glk/Ha9iYBzYpt4I2QFNRIh35uNFNfe8KFQcdwY1/HKxXBkinw==", + "dependencies": { + "bson": "^4.7.0", + "denque": "^2.1.0", + "mongodb-connection-string-url": "^2.5.3", + "socks": "^2.7.0" + }, + "engines": { + "node": ">=12.9.0" + }, + "optionalDependencies": { + "saslprep": "^1.0.3" + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.4.tgz", + "integrity": "sha512-SeAxuWs0ez3iI3vvmLk/j2y+zHwigTDKQhtdxTgt5ZCOQQS5+HW4g45/Xw5vzzbn7oQXCNQ24Z40AkJsizEy7w==", + "dependencies": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, + "node_modules/mongoose": { + "version": "6.6.5", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.6.5.tgz", + "integrity": "sha512-iA/oDpWOc+K2QYzA4Eq7Z1oUBQOz9FGDmUwPLgw872Bfs/qizA5Db+gJorAn+TnnGu3VoCK8iP4Y+TECUelwjA==", + "dependencies": { + "bson": "^4.6.5", + "kareem": "2.4.1", + "mongodb": "4.9.1", + "mpath": "0.9.0", + "mquery": "4.0.3", + "ms": "2.1.3", + "sift": "16.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/mongodb": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.9.1.tgz", + "integrity": "sha512-ZhgI/qBf84fD7sI4waZBoLBNJYPQN5IOC++SBCiPiyhzpNKOxN/fi0tBHvH2dEC42HXtNEbFB0zmNz4+oVtorQ==", + "dependencies": { + "bson": "^4.7.0", + "denque": "^2.1.0", + "mongodb-connection-string-url": "^2.5.3", + "socks": "^2.7.0" + }, + "engines": { + "node": ">=12.9.0" + }, + "optionalDependencies": { + "saslprep": "^1.0.3" + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/morgan": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", + "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==", + "dependencies": { + "basic-auth": "~2.0.0", + "debug": "2.6.9", + "depd": "~1.1.2", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-4.0.3.tgz", + "integrity": "sha512-J5heI+P08I6VJ2Ky3+33IpCdAvlYGTSUjwTPxkAr8i8EoduPMBX2OY/wa3IKZIQl7MU4SbFk8ndgSKyB/cl1zA==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/mquery/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mquery/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/passport": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-github": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/passport-github/-/passport-github-1.1.0.tgz", + "integrity": "sha512-XARXJycE6fFh/dxF+Uut8OjlwbFEXgbPVj/+V+K7cvriRK7VcAOm+NgBmbiLM9Qv3SSxEAV+V6fIk89nYHXa8A==", + "dependencies": { + "passport-oauth2": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-oauth2": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.6.1.tgz", + "integrity": "sha512-ZbV43Hq9d/SBSYQ22GOiglFsjsD1YY/qdiptA+8ej+9C1dL1TVB+mBE5kDH/D4AJo50+2i8f4bx0vg4/yDDZCQ==", + "dependencies": { + "base64url": "3.x.x", + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "dependencies": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rndm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", + "integrity": "sha512-fJhQQI5tLrQvYIYFpOnFinzv9dwmR7hRnUz1XqP3OJ1jIweTNOd6aTO4jwQSgcBSFUB+/KHJxuGneime+FdzOw==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "dependencies": { + "sparse-bitfield": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "node_modules/sift": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.0.tgz", + "integrity": "sha512-ILTjdP2Mv9V1kIxWMXeMTIRbOBrqKc4JAXmFMnFq3fKeyQ2Qwa3Dw1ubcye3vR+Y6ofA0b9gNDr/y2t6eUeIzQ==" + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "optional": true, + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "engines": { + "node": ">=0.6.x" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + } + }, + "dependencies": { + "@types/node": { + "version": "18.8.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.2.tgz", + "integrity": "sha512-cRMwIgdDN43GO4xMWAfJAecYn8wV4JbsOGHNfNUIDiuYkUYAR5ec4Rj7IO2SAhFPEfpPtLtUTbbny/TCT7aDwA==" + }, + "@types/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" + }, + "@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "requires": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha512-YQyoqQG3sO8iCmf8+hyVpgHHOv0/hCEFiS4zTGUwTA1HjAFX66wRcNQrVCeJq9pgESMRvUAOvSil5MJlmccuKQ==", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "bson": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.0.tgz", + "integrity": "sha512-VrlEE4vuiO1WTpfof4VmaVolCVYkYTgB9iWgYNOrVlnifpME/06fhFRmONgBhClD5pFC1t9ZWqFUQEQAzY43bA==", + "requires": { + "buffer": "^5.6.0" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + }, + "cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "requires": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + } + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "csrf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.1.0.tgz", + "integrity": "sha512-uTqEnCvWRk042asU6JtapDTcJeeailFy4ydOQS28bj1hcLnYRiqi8SsD2jS412AY1I/4qdOwWZun774iqywf9w==", + "requires": { + "rndm": "1.2.0", + "tsscmp": "1.0.6", + "uid-safe": "2.1.5" + } + }, + "csurf": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.11.0.tgz", + "integrity": "sha512-UCtehyEExKTxgiu8UHdGvHj4tnpE/Qctue03Giq5gPgMQ9cg/ciod5blZQ5a4uCEenNQjxyGuzygLdKUmee/bQ==", + "requires": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "csrf": "3.1.0", + "http-errors": "~1.7.3" + }, + "dependencies": { + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==" + }, + "dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "requires": { + "jake": "^10.8.5" + } + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "express": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.3", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha512-+IJOX0OqlHCszo2mBUq+SrEbCj6w7Kpffqx60zYbPTFaO4+yYgRjHwcZNpWvaTylDHaV7PPmBHzSecZiMhtPgw==" + } + } + }, + "express-session": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "requires": { + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "dependencies": { + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } + } + }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + } + }, + "find-or-create": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-or-create/-/find-or-create-2.0.0.tgz", + "integrity": "sha512-XOFTRwmFTkT+/PplVsteHw+i/acxSXT8kijOR2RBeBO6Gj4jwaBMEtVMSMNQPfKq2x/pgot75JFuacXA0BCj1Q==" + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "requires": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + } + }, + "kareem": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.4.1.tgz", + "integrity": "sha512-aJ9opVoXroQUPfovYP5kaj2lM7Jn02Gw13bL0lg9v0V7SaUc0qavPs0Eue7d2DcC3NjqI6QAUElXNsuZSeM+EA==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "mongodb": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.10.0.tgz", + "integrity": "sha512-My2QxLTw0Cc1O9gih0mz4mqo145Jq4rLAQx0Glk/Ha9iYBzYpt4I2QFNRIh35uNFNfe8KFQcdwY1/HKxXBkinw==", + "requires": { + "bson": "^4.7.0", + "denque": "^2.1.0", + "mongodb-connection-string-url": "^2.5.3", + "saslprep": "^1.0.3", + "socks": "^2.7.0" + } + }, + "mongodb-connection-string-url": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.4.tgz", + "integrity": "sha512-SeAxuWs0ez3iI3vvmLk/j2y+zHwigTDKQhtdxTgt5ZCOQQS5+HW4g45/Xw5vzzbn7oQXCNQ24Z40AkJsizEy7w==", + "requires": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, + "mongoose": { + "version": "6.6.5", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.6.5.tgz", + "integrity": "sha512-iA/oDpWOc+K2QYzA4Eq7Z1oUBQOz9FGDmUwPLgw872Bfs/qizA5Db+gJorAn+TnnGu3VoCK8iP4Y+TECUelwjA==", + "requires": { + "bson": "^4.6.5", + "kareem": "2.4.1", + "mongodb": "4.9.1", + "mpath": "0.9.0", + "mquery": "4.0.3", + "ms": "2.1.3", + "sift": "16.0.0" + }, + "dependencies": { + "mongodb": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.9.1.tgz", + "integrity": "sha512-ZhgI/qBf84fD7sI4waZBoLBNJYPQN5IOC++SBCiPiyhzpNKOxN/fi0tBHvH2dEC42HXtNEbFB0zmNz4+oVtorQ==", + "requires": { + "bson": "^4.7.0", + "denque": "^2.1.0", + "mongodb-connection-string-url": "^2.5.3", + "saslprep": "^1.0.3", + "socks": "^2.7.0" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "morgan": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", + "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==", + "requires": { + "basic-auth": "~2.0.0", + "debug": "2.6.9", + "depd": "~1.1.2", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" + } + }, + "mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==" + }, + "mquery": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-4.0.3.tgz", + "integrity": "sha512-J5heI+P08I6VJ2Ky3+33IpCdAvlYGTSUjwTPxkAr8i8EoduPMBX2OY/wa3IKZIQl7MU4SbFk8ndgSKyB/cl1zA==", + "requires": { + "debug": "4.x" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "passport": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", + "requires": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + } + }, + "passport-github": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/passport-github/-/passport-github-1.1.0.tgz", + "integrity": "sha512-XARXJycE6fFh/dxF+Uut8OjlwbFEXgbPVj/+V+K7cvriRK7VcAOm+NgBmbiLM9Qv3SSxEAV+V6fIk89nYHXa8A==", + "requires": { + "passport-oauth2": "1.x.x" + } + }, + "passport-oauth2": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.6.1.tgz", + "integrity": "sha512-ZbV43Hq9d/SBSYQ22GOiglFsjsD1YY/qdiptA+8ej+9C1dL1TVB+mBE5kDH/D4AJo50+2i8f4bx0vg4/yDDZCQ==", + "requires": { + "base64url": "3.x.x", + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + } + }, + "passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "rndm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", + "integrity": "sha512-fJhQQI5tLrQvYIYFpOnFinzv9dwmR7hRnUz1XqP3OJ1jIweTNOd6aTO4jwQSgcBSFUB+/KHJxuGneime+FdzOw==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "sift": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.0.tgz", + "integrity": "sha512-ILTjdP2Mv9V1kIxWMXeMTIRbOBrqKc4JAXmFMnFq3fKeyQ2Qwa3Dw1ubcye3vR+Y6ofA0b9gNDr/y2t6eUeIzQ==" + }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" + }, + "socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "requires": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + } + }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "optional": true, + "requires": { + "memory-pager": "^1.0.2" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "requires": { + "punycode": "^2.1.1" + } + }, + "tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "requires": { + "random-bytes": "~1.0.0" + } + }, + "uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + }, + "whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "requires": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..0784c70d6 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "final-project", + "version": "0.0.0", + "private": true, + "scripts": { + "start": "node ./bin/www" + }, + "dependencies": { + "cookie-parser": "~1.4.4", + "csurf": "^1.11.0", + "debug": "~2.6.9", + "dotenv": "^16.0.2", + "ejs": "^3.1.8", + "express": "~4.16.1", + "express-session": "^1.17.3", + "find-or-create": "^2.0.0", + "http-errors": "~1.6.3", + "mongodb": "^4.9.1", + "mongoose": "^6.6.0", + "morgan": "~1.9.1", + "passport": "^0.6.0", + "passport-github": "^1.1.0" + } +} diff --git a/public/javascripts/scripts.js b/public/javascripts/scripts.js new file mode 100644 index 000000000..2a91bacf6 --- /dev/null +++ b/public/javascripts/scripts.js @@ -0,0 +1,6 @@ +let csrf = null + +window.onload = function() { + csrf = document.getElementById("csrf").getAttribute('value') + console.log("Window loaded") +} diff --git a/public/main.html b/public/main.html deleted file mode 100644 index 9aaac6133..000000000 --- a/public/main.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - CS4241 Final Project - - -

- Final Project By Sean, Liliana, Jacob, and JR -

- -

- To read more about the project, visit the README.md file. For our project we created a few different - clicking tests. The first is clicks per second to see how many clicks the user can do in 10 seconds. The second is - a reaction time test. There will be three buttons that pop up with only one of them being green. This score will be determined by - how fast the user can get 5 correct. Finally the last test is a mouse accuracy test. Buttons will pop up randomly on the screen in different locations - and the user must move their cursor to press 5 of them. We also have a leaderboard page as well to see logged in users best scores. -

- - - - - - - - \ No newline at end of file diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css new file mode 100644 index 000000000..9453385b9 --- /dev/null +++ b/public/stylesheets/style.css @@ -0,0 +1,8 @@ +body { + padding: 50px; + font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; +} + +a { + color: #00B7FF; +} diff --git a/routes/auth.js b/routes/auth.js new file mode 100644 index 000000000..7a8007bad --- /dev/null +++ b/routes/auth.js @@ -0,0 +1,58 @@ +const express = require('express'); +const router = express.Router(); +const passport = require('passport'); +const User = require("../models/User"); + +const GitHubStrategy = require('passport-github').Strategy; + +passport.use( + new GitHubStrategy({ + authorizationURL: "https://github.com/login/oauth/authorize?prompt=login", + clientID: process.env['GITHUB_CLIENT_ID'], + clientSecret: process.env['GITHUB_CLIENT_SECRET'], + callbackURL: process.env['GITHUB_CALLBACK_URL'] + }, + function(accessToken, refreshToken, profile, cb) { + console.log("User check: \n%s", profile) + User.findOrCreate({ id: profile.id}, {username: profile.username, displayName: profile.displayName, profilePhoto: `https://avatars.githubusercontent.com/u/${profile.id}?v=4`}, function (err, user) { + console.log("User Logged in (new=%s): %s", user.isNew, user.doc); + return cb(err, user); + }); + } +)); + +passport.serializeUser(function(user, cb) { + process.nextTick(function() { + //cb(null, user._id) + user = user.doc + cb(null, { + id: user.id, + username: user.username, + displayName: user.displayName, + email: user.email, + profilePhoto: user.profilePhoto + }); + }); +}); + +passport.deserializeUser(function(user, cb) { + process.nextTick(function() { + cb(null, user) + }); +}); + +router.get('/login/federated/github', passport.authenticate('github')); + +router.get('/auth/github/callback', passport.authenticate('github', { + successRedirect: '/', + failureRedirect: '/login' +})); + +router.post('/logout', function(req, res, next) { + req.logout(function(err) { + if (err) { return next(err); } + res.redirect('/'); + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/routes/games.js b/routes/games.js new file mode 100644 index 000000000..da5871924 --- /dev/null +++ b/routes/games.js @@ -0,0 +1,26 @@ +var express = require('express'); +var router = express.Router(); +const Results = require("../models/Results"); + +router.get('/accuracy', function(req, res, next) { + res.render('accuracy', { title: 'ReactionTests', user : req.user}); +}) +router.get('/cps', function(req, res, next) { + res.render('cps', { title: 'ReactionTests', user : req.user}); +}) +router.get('/reaction', function(req, res, next) { + res.render('reaction', { title: 'ReactionTests', user : req.user}); +}) + +router.post('/addResult', function (req, res, next) { + console.log("AddResult: %s", req.body) + Results.create({owner_id: req.body.owner_id, game_type: req.body.game_type, score: req.body.score}, () => { + Note.find({owner_id: req.body.owner_id}).lean().exec(function (err, notes) { + console.log("Found notes: %s", notes); + res.json(notes) + }) + }) + +}); + +module.exports = router; \ No newline at end of file diff --git a/routes/index.js b/routes/index.js new file mode 100644 index 000000000..dcba1e315 --- /dev/null +++ b/routes/index.js @@ -0,0 +1,46 @@ +var express = require('express'); +var router = express.Router(); +const Note = require("../models/Note"); +const mongodb = require("mongodb"); + +/* GET home page. */ +router.get('/', function(req, res, next) { + res.render('index', { title: 'ReactionTests', user : req.user}); +}); + + + +router.post('/edit', function (req, res, next) { + console.log("Edit: %s", req.body) + Note.updateOne({_id: new mongodb.ObjectID(req.body._id)}, {note: req.body.note}, {}, () => { + Note.find({owner_id: req.body.owner_id}).lean().exec(function (err, notes) { + console.log("Found notes: %s", notes); + res.json(notes) + }) + }) +}); + +router.post('/delete', function (req, res, next) { + console.log("Delete: %s", req.body) + Note.deleteOne({_id: new mongodb.ObjectID(req.body._id)}, {}, (err, doc, result) => { + console.log(err); + console.log(doc); + console.log(result); + Note.find({owner_id: req.body.owner_id}).lean().exec(function (err, notes) { + console.log("Found notes: %s", notes); + res.json(notes) + }) + }) +}); + +router.post('/getNotes', function (req, res, next) { + Note.find({owner_id: req.body.owner_id}).lean().exec(function (err, notes) { + console.log("Found notes: %s", notes); + res.json(notes) + }) +}) + + + + +module.exports = router; diff --git a/server.js b/server.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/views/accuracy.ejs b/views/accuracy.ejs new file mode 100644 index 000000000..8f1f6b323 --- /dev/null +++ b/views/accuracy.ejs @@ -0,0 +1,3 @@ +<%- include('header', { title: 'ReactionTests' }) -%> +

ACCURACY

+<%- include('footer') -%> \ No newline at end of file diff --git a/views/cps.ejs b/views/cps.ejs new file mode 100644 index 000000000..9838147d3 --- /dev/null +++ b/views/cps.ejs @@ -0,0 +1,3 @@ +<%- include('header', { title: 'ReactionTests' }) -%> +

CPS

+<%- include('footer') -%> \ No newline at end of file diff --git a/views/error.ejs b/views/error.ejs new file mode 100644 index 000000000..7cf94edf1 --- /dev/null +++ b/views/error.ejs @@ -0,0 +1,3 @@ +

<%= message %>

+

<%= error.status %>

+
<%= error.stack %>
diff --git a/views/footer.ejs b/views/footer.ejs new file mode 100644 index 000000000..14ac40f5d --- /dev/null +++ b/views/footer.ejs @@ -0,0 +1,49 @@ + +
+
+
+
+
About
+

+ To read more about the project, visit the README.md file. For our project we created a few different + clicking tests. The first is clicks per second to see how many clicks the user can do in 10 seconds. The second is + a reaction time test. There will be three buttons that pop up with only one of them being green. This score will be determined by + how fast the user can get 5 correct. Finally the last test is a mouse accuracy test. Buttons will pop up randomly on the screen in different locations + and the user must move their cursor to press 5 of them. We also have a leaderboard page as well to see logged in users best scores. +

+
+ +
+
Quick Links
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + +
+ + \ No newline at end of file diff --git a/views/header.ejs b/views/header.ejs new file mode 100644 index 000000000..72d7211f0 --- /dev/null +++ b/views/header.ejs @@ -0,0 +1,59 @@ + + + + <%= title %> + + + + + + + + + +
+
+
+ + <%= title %> + + + + + + + + <%if (user) {%> + + <% } else { %> + Github Login + <% } %> +
+
+
+ \ No newline at end of file diff --git a/views/index.ejs b/views/index.ejs new file mode 100644 index 000000000..3b31a0d4e --- /dev/null +++ b/views/index.ejs @@ -0,0 +1,70 @@ +<%- include('header', { title: 'ReactionTests' }) -%> +
+ +

myNotes

+
+

Take your notes here! Simply enter anything on your mind below!

+
+ <%if (user) {%> +
+
+ + + +
+ +
+
+ +
+
+ + + + + + + + + + + + + +
#NoteActions
+

No Data!

+
+
+ <% } else { %> +
+
+

Please Log in above!

+
+
+ <% } %> + +
+ + +
+ +<%- include('footer') -%> + diff --git a/views/leaderboard.ejs b/views/leaderboard.ejs new file mode 100644 index 000000000..0e071a8e5 --- /dev/null +++ b/views/leaderboard.ejs @@ -0,0 +1,3 @@ +<%- include('header', { title: 'ReactionTests' }) -%> +

LEADERBOARD

+<%- include('footer') -%> \ No newline at end of file diff --git a/views/reaction.ejs b/views/reaction.ejs new file mode 100644 index 000000000..f2ac16e42 --- /dev/null +++ b/views/reaction.ejs @@ -0,0 +1,3 @@ +<%- include('header', { title: 'ReactionTests' }) -%> +

REACTION

+<%- include('footer') -%> \ No newline at end of file From 2051c48cfc52d5008fdd63b7bdc20752d653f70e Mon Sep 17 00:00:00 2001 From: Jacob van Steyn Date: Fri, 7 Oct 2022 15:16:31 -0400 Subject: [PATCH 05/64] Fix styles and remove old code --- models/Results.js | 1 - public/stylesheets/style.css | 67 +++++++++++++++++++++- routes/index.js | 60 ++++++++++---------- views/accuracy.ejs | 4 +- views/cps.ejs | 4 +- views/footer.ejs | 6 +- views/header.ejs | 15 ++--- views/index.ejs | 107 ++++++++++++++--------------------- views/leaderboard.ejs | 4 +- views/reaction.ejs | 4 +- 10 files changed, 163 insertions(+), 109 deletions(-) diff --git a/models/Results.js b/models/Results.js index 3772de7be..1e5703ae9 100644 --- a/models/Results.js +++ b/models/Results.js @@ -26,7 +26,6 @@ ResultsSchema.statics.getResultsForUserId = function(user_id) { } ResultsSchema.statics.getRankforScore = function(game, score) { - var numGreaterThan = this.distinct({game_type: game, score: { $gt: score}}).count(); return null; } diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index 9453385b9..11e2f77e0 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -1,8 +1,73 @@ body { - padding: 50px; + padding: 0px; + margin: 0; font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; + min-height: 100vh; + display: flex; + flex-direction: column; } a { color: #00B7FF; } + +.main-content { + flex-grow: 1; +} + +.site-footer +{ + background-color: rgb(1, 1, 1); + padding:45px 0 20px; + font-size:12px; + line-height:24px; + color:#737373; +} +.site-footer hr +{ + border-top-color:#bbb; + opacity:0.5 +} +.site-footer hr.small +{ + margin:20px 0 +} +.site-footer h6 +{ + color:#fff; + font-size:16px; + text-transform:uppercase; + margin-top:5px; + letter-spacing:2px +} +.site-footer a +{ + color:#737373; +} +.site-footer a:hover +{ + color:#3366cc; + text-decoration:none; +} +.footer-links +{ + padding-left:0; + list-style:none +} +.footer-links li +{ + display:block +} +.footer-links a +{ + color:#737373 +} +.footer-links a:active,.footer-links a:focus,.footer-links a:hover +{ + color:#3366cc; + text-decoration:none; +} +.footer-links.inline li +{ + display:inline-block +} \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index dcba1e315..203f582a4 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,6 +1,6 @@ var express = require('express'); var router = express.Router(); -const Note = require("../models/Note"); +//const Note = require("../models/Note"); const mongodb = require("mongodb"); /* GET home page. */ @@ -10,35 +10,35 @@ router.get('/', function(req, res, next) { -router.post('/edit', function (req, res, next) { - console.log("Edit: %s", req.body) - Note.updateOne({_id: new mongodb.ObjectID(req.body._id)}, {note: req.body.note}, {}, () => { - Note.find({owner_id: req.body.owner_id}).lean().exec(function (err, notes) { - console.log("Found notes: %s", notes); - res.json(notes) - }) - }) -}); - -router.post('/delete', function (req, res, next) { - console.log("Delete: %s", req.body) - Note.deleteOne({_id: new mongodb.ObjectID(req.body._id)}, {}, (err, doc, result) => { - console.log(err); - console.log(doc); - console.log(result); - Note.find({owner_id: req.body.owner_id}).lean().exec(function (err, notes) { - console.log("Found notes: %s", notes); - res.json(notes) - }) - }) -}); - -router.post('/getNotes', function (req, res, next) { - Note.find({owner_id: req.body.owner_id}).lean().exec(function (err, notes) { - console.log("Found notes: %s", notes); - res.json(notes) - }) -}) +// router.post('/edit', function (req, res, next) { +// console.log("Edit: %s", req.body) +// Note.updateOne({_id: new mongodb.ObjectID(req.body._id)}, {note: req.body.note}, {}, () => { +// Note.find({owner_id: req.body.owner_id}).lean().exec(function (err, notes) { +// console.log("Found notes: %s", notes); +// res.json(notes) +// }) +// }) +// }); +// +// router.post('/delete', function (req, res, next) { +// console.log("Delete: %s", req.body) +// Note.deleteOne({_id: new mongodb.ObjectID(req.body._id)}, {}, (err, doc, result) => { +// console.log(err); +// console.log(doc); +// console.log(result); +// Note.find({owner_id: req.body.owner_id}).lean().exec(function (err, notes) { +// console.log("Found notes: %s", notes); +// res.json(notes) +// }) +// }) +// }); +// +// router.post('/getNotes', function (req, res, next) { +// Note.find({owner_id: req.body.owner_id}).lean().exec(function (err, notes) { +// console.log("Found notes: %s", notes); +// res.json(notes) +// }) +// }) diff --git a/views/accuracy.ejs b/views/accuracy.ejs index 8f1f6b323..b1602dd31 100644 --- a/views/accuracy.ejs +++ b/views/accuracy.ejs @@ -1,3 +1,5 @@ <%- include('header', { title: 'ReactionTests' }) -%> -

ACCURACY

+
+

ACCURACY

+
<%- include('footer') -%> \ No newline at end of file diff --git a/views/cps.ejs b/views/cps.ejs index 9838147d3..abec562f0 100644 --- a/views/cps.ejs +++ b/views/cps.ejs @@ -1,3 +1,5 @@ <%- include('header', { title: 'ReactionTests' }) -%> -

CPS

+
+

CPS

+
<%- include('footer') -%> \ No newline at end of file diff --git a/views/footer.ejs b/views/footer.ejs index 14ac40f5d..451d5b936 100644 --- a/views/footer.ejs +++ b/views/footer.ejs @@ -1,8 +1,8 @@
-
-
+
+
About

To read more about the project, visit the README.md file. For our project we created a few different @@ -13,7 +13,7 @@

-
+
Quick Links
- + + <%- include('scores') -%>
diff --git a/views/scores.ejs b/views/scores.ejs new file mode 100644 index 000000000..6f36fa144 --- /dev/null +++ b/views/scores.ejs @@ -0,0 +1,108 @@ +
+ +
+
+ +
+ \ No newline at end of file From 2b426f15ca7ccae0e94eae8618a8be012fb49340 Mon Sep 17 00:00:00 2001 From: jrkim-wpi Date: Sun, 9 Oct 2022 17:38:59 -0400 Subject: [PATCH 16/64] feat: random hidden btn in acc --- public/javascripts/accuracy.js | 27 +++++++++++++++++++++++++++ public/stylesheets/style.css | 8 +++++++- views/accuracy.ejs | 20 ++++++++++++++++++-- 3 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 public/javascripts/accuracy.js diff --git a/public/javascripts/accuracy.js b/public/javascripts/accuracy.js new file mode 100644 index 000000000..ddbc1884c --- /dev/null +++ b/public/javascripts/accuracy.js @@ -0,0 +1,27 @@ +window.onload = function() { + + const randBtn = document.getElementsByClassName('randBtn'); + const btnCont = document.getElementById('btnContainer'); + const winWidth = btnCont.offsetWidth + const winHeight = btnCont.offsetHeight; + + function getRandomNumber(min, max) { + return Math.random() * (max - min - 120) + min; + } + + for( let i = 0; i < randBtn.length; i++) { + let currBtn = randBtn[i]; + const randomTop = getRandomNumber(0, winHeight); + const randomLeft = getRandomNumber(0, winWidth); + + currBtn.style.top = randomTop +"px"; + currBtn.style.left = randomLeft +"px"; + } + + const statusText = document.getElementById("statusText") + const reactionBtn1 = document.getElementById("reactionBtn1") + const reactionBtn2 = document.getElementById("reactionBtn2") + const reactionBtn3 = document.getElementById("reactionBtn3"); + const reactionBtn4 = document.getElementById("reactionBtn4"); + const reactionBtn5 = document.getElementById("reactionBtn5"); +} diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index 11e2f77e0..57e899d63 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -70,4 +70,10 @@ a { .footer-links.inline li { display:inline-block -} \ No newline at end of file +} +.randBtn { + position: relative; + top: 1; + left: 1; + visibility: hidden; +} diff --git a/views/accuracy.ejs b/views/accuracy.ejs index b1602dd31..5e56b397f 100644 --- a/views/accuracy.ejs +++ b/views/accuracy.ejs @@ -1,5 +1,21 @@ <%- include('header', { title: 'ReactionTests' }) -%>
-

ACCURACY

-
+
+

Accuracy

+
+

Click all five of the buttons as fast as possible when it appears on the screen.

+ +

+
+
+
+
+
+
+
+
+
+
+
+ <%- include('footer') -%> \ No newline at end of file From 606ffa4eff4014b3b48bdcab04a45b57781baf90 Mon Sep 17 00:00:00 2001 From: Jacob van Steyn Date: Sun, 9 Oct 2022 17:50:47 -0400 Subject: [PATCH 17/64] Add aim training & merge versions together --- public/javascripts/accuracy.js | 104 ++++++++++++++++++++++++------ public/javascripts/aimtraining.js | 27 ++++++++ public/javascripts/reaction.js | 93 -------------------------- public/stylesheets/style.css | 2 +- routes/games.js | 3 + views/accuracy.ejs | 26 +++++--- views/aimtraining.ejs | 21 ++++++ views/footer.ejs | 1 + views/header.ejs | 3 + views/reaction.ejs | 12 ++-- 10 files changed, 162 insertions(+), 130 deletions(-) create mode 100644 public/javascripts/aimtraining.js create mode 100644 views/aimtraining.ejs diff --git a/public/javascripts/accuracy.js b/public/javascripts/accuracy.js index ddbc1884c..3c654138a 100644 --- a/public/javascripts/accuracy.js +++ b/public/javascripts/accuracy.js @@ -1,27 +1,93 @@ window.onload = function() { - - const randBtn = document.getElementsByClassName('randBtn'); - const btnCont = document.getElementById('btnContainer'); - const winWidth = btnCont.offsetWidth - const winHeight = btnCont.offsetHeight; - - function getRandomNumber(min, max) { - return Math.random() * (max - min - 120) + min; - } - - for( let i = 0; i < randBtn.length; i++) { - let currBtn = randBtn[i]; - const randomTop = getRandomNumber(0, winHeight); - const randomLeft = getRandomNumber(0, winWidth); - - currBtn.style.top = randomTop +"px"; - currBtn.style.left = randomLeft +"px"; - } - + const statusText = document.getElementById("statusText") const reactionBtn1 = document.getElementById("reactionBtn1") const reactionBtn2 = document.getElementById("reactionBtn2") const reactionBtn3 = document.getElementById("reactionBtn3"); const reactionBtn4 = document.getElementById("reactionBtn4"); const reactionBtn5 = document.getElementById("reactionBtn5"); + const reactionBtn6 = document.getElementById("reactionBtn6"); + + var btns = [reactionBtn1, reactionBtn2, reactionBtn3, reactionBtn4, reactionBtn5, reactionBtn6] + var clicks = [] + var startTime = null + var chosenBtn = null + + const average = array => array.reduce((a, b) => a + b) / array.length; + + const startBtn = document.getElementById("startBtn"); + startBtn.addEventListener('click', function () { + startBtn.disabled = true; + statusText.innerText = "Starting in 3..."; + setTimeout(function() {countdown(2)}, 1100) + }) + + function countdown(i){ + if (i !== 0){ + statusText.innerText = (i == 2) ? "Starting in 3... 2..." : (i == 1) ? "Starting in 3... 2.. 1..." : "NAAA" + i -= 1 + console.log(i) + setTimeout(function() {countdown(i)}, 1100) + } + else{ + statusText.innerText = "Wait for green!" + playGame() + } + } + + function playGame(){ + if (clicks.length < 5){ + var delay = Math.random() * 2000 + 1500 // 1.5-3 seconds + setTimeout(setBtn, delay) + } + else { + var avg = average(clicks).toFixed(3) + statusText.innerText = `Avg Reaction Time: ${avg}` + + var result = { + owner_id: user, + game_type: game, + score: avg + } + + fetch( '/addResult', { + method:'POST', + headers: {"X-CSRF-TOKEN": csrf, "Content-Type": "application/json"}, + body: JSON.stringify(result) + }) + .then(async function( response ) { + var data = await response.json() + console.log( data ) + console.log("response ^") + const evt = new CustomEvent("updateData", {detail: {data: data}, bubbles: true, composed: false, cancelable: false}) + document.dispatchEvent(evt) + }) + + clicks = [] + startBtn.disabled = false + } + // while (iteration < 5){ + // var delay = Math.random() * 2000 // 0-2 seconds + // setTimeout(setBtn, delay) + // + // } + } + + function setBtn() { + chosenBtn = btns[Math.floor(Math.random() * btns.length)] + startTime = Date.now() + chosenBtn.addEventListener('click', handleClick) + + chosenBtn.style.backgroundColor = "lightgreen" + } + + function handleClick(){ + var reactionTime = (Date.now() - startTime)/1000 + console.log("Btn clicked!") + clicks.push(reactionTime) + statusText.innerText = `Reaction Time: ${reactionTime}` + chosenBtn.removeEventListener('click', handleClick) + chosenBtn.style.backgroundColor = "lightslategrey" + playGame() + } } diff --git a/public/javascripts/aimtraining.js b/public/javascripts/aimtraining.js new file mode 100644 index 000000000..ddbc1884c --- /dev/null +++ b/public/javascripts/aimtraining.js @@ -0,0 +1,27 @@ +window.onload = function() { + + const randBtn = document.getElementsByClassName('randBtn'); + const btnCont = document.getElementById('btnContainer'); + const winWidth = btnCont.offsetWidth + const winHeight = btnCont.offsetHeight; + + function getRandomNumber(min, max) { + return Math.random() * (max - min - 120) + min; + } + + for( let i = 0; i < randBtn.length; i++) { + let currBtn = randBtn[i]; + const randomTop = getRandomNumber(0, winHeight); + const randomLeft = getRandomNumber(0, winWidth); + + currBtn.style.top = randomTop +"px"; + currBtn.style.left = randomLeft +"px"; + } + + const statusText = document.getElementById("statusText") + const reactionBtn1 = document.getElementById("reactionBtn1") + const reactionBtn2 = document.getElementById("reactionBtn2") + const reactionBtn3 = document.getElementById("reactionBtn3"); + const reactionBtn4 = document.getElementById("reactionBtn4"); + const reactionBtn5 = document.getElementById("reactionBtn5"); +} diff --git a/public/javascripts/reaction.js b/public/javascripts/reaction.js index 3c654138a..e69de29bb 100644 --- a/public/javascripts/reaction.js +++ b/public/javascripts/reaction.js @@ -1,93 +0,0 @@ -window.onload = function() { - - const statusText = document.getElementById("statusText") - const reactionBtn1 = document.getElementById("reactionBtn1") - const reactionBtn2 = document.getElementById("reactionBtn2") - const reactionBtn3 = document.getElementById("reactionBtn3"); - const reactionBtn4 = document.getElementById("reactionBtn4"); - const reactionBtn5 = document.getElementById("reactionBtn5"); - const reactionBtn6 = document.getElementById("reactionBtn6"); - - var btns = [reactionBtn1, reactionBtn2, reactionBtn3, reactionBtn4, reactionBtn5, reactionBtn6] - var clicks = [] - var startTime = null - var chosenBtn = null - - const average = array => array.reduce((a, b) => a + b) / array.length; - - const startBtn = document.getElementById("startBtn"); - startBtn.addEventListener('click', function () { - startBtn.disabled = true; - statusText.innerText = "Starting in 3..."; - setTimeout(function() {countdown(2)}, 1100) - }) - - function countdown(i){ - if (i !== 0){ - statusText.innerText = (i == 2) ? "Starting in 3... 2..." : (i == 1) ? "Starting in 3... 2.. 1..." : "NAAA" - i -= 1 - console.log(i) - setTimeout(function() {countdown(i)}, 1100) - } - else{ - statusText.innerText = "Wait for green!" - playGame() - } - } - - function playGame(){ - if (clicks.length < 5){ - var delay = Math.random() * 2000 + 1500 // 1.5-3 seconds - setTimeout(setBtn, delay) - } - else { - var avg = average(clicks).toFixed(3) - statusText.innerText = `Avg Reaction Time: ${avg}` - - var result = { - owner_id: user, - game_type: game, - score: avg - } - - fetch( '/addResult', { - method:'POST', - headers: {"X-CSRF-TOKEN": csrf, "Content-Type": "application/json"}, - body: JSON.stringify(result) - }) - .then(async function( response ) { - var data = await response.json() - console.log( data ) - console.log("response ^") - const evt = new CustomEvent("updateData", {detail: {data: data}, bubbles: true, composed: false, cancelable: false}) - document.dispatchEvent(evt) - }) - - clicks = [] - startBtn.disabled = false - } - // while (iteration < 5){ - // var delay = Math.random() * 2000 // 0-2 seconds - // setTimeout(setBtn, delay) - // - // } - } - - function setBtn() { - chosenBtn = btns[Math.floor(Math.random() * btns.length)] - startTime = Date.now() - chosenBtn.addEventListener('click', handleClick) - - chosenBtn.style.backgroundColor = "lightgreen" - } - - function handleClick(){ - var reactionTime = (Date.now() - startTime)/1000 - console.log("Btn clicked!") - clicks.push(reactionTime) - statusText.innerText = `Reaction Time: ${reactionTime}` - chosenBtn.removeEventListener('click', handleClick) - chosenBtn.style.backgroundColor = "lightslategrey" - playGame() - } -} diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index 57e899d63..e86266895 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -75,5 +75,5 @@ a { position: relative; top: 1; left: 1; - visibility: hidden; + /*visibility: hidden;*/ } diff --git a/routes/games.js b/routes/games.js index dade1cb2e..c4c9e1627 100644 --- a/routes/games.js +++ b/routes/games.js @@ -10,5 +10,8 @@ router.get('/cps', function(req, res, next) { router.get('/reaction', function(req, res, next) { res.render('reaction', { title: 'ReactionTests', user : req.user, game_type: "reaction"}); }) +router.get('/aimtraining', function(req, res, next) { + res.render('aimtraining', { title: 'ReactionTests', user : req.user, game_type: "aimtraining"}); +}) module.exports = router; \ No newline at end of file diff --git a/views/accuracy.ejs b/views/accuracy.ejs index 5e56b397f..f30a3a147 100644 --- a/views/accuracy.ejs +++ b/views/accuracy.ejs @@ -1,21 +1,27 @@ <%- include('header', { title: 'ReactionTests' }) -%>
+

Accuracy

-

Click all five of the buttons as fast as possible when it appears on the screen.

+

Click on the correct button as fast as possible when it turns green.
Your score is determined from the average reaction time of 5 clicks.

-
-
-
-
-
-
-
+ +
+
+
+
+
+
+
+
+
+
+
-
- +
+ <%- include('footer') -%> \ No newline at end of file diff --git a/views/aimtraining.ejs b/views/aimtraining.ejs new file mode 100644 index 000000000..a07afa946 --- /dev/null +++ b/views/aimtraining.ejs @@ -0,0 +1,21 @@ +<%- include('header', { title: 'ReactionTests' }) -%> +
+
+

Aim Training

+
+

Click all five of the buttons as fast as possible when it appears on the screen.

+ +

+
+
+
+
+
+
+
+
+
+
+
+ +<%- include('footer') -%> \ No newline at end of file diff --git a/views/footer.ejs b/views/footer.ejs index 451d5b936..4673497f9 100644 --- a/views/footer.ejs +++ b/views/footer.ejs @@ -20,6 +20,7 @@
  • Reaction Time
  • Clicks Per Second
  • Accuracy
  • +
  • Aim Training
  • Leaderboard
  • diff --git a/views/header.ejs b/views/header.ejs index b4a306c05..7b3a9369c 100644 --- a/views/header.ejs +++ b/views/header.ejs @@ -28,6 +28,9 @@ + diff --git a/views/reaction.ejs b/views/reaction.ejs index c202a9e02..fd25a1e36 100644 --- a/views/reaction.ejs +++ b/views/reaction.ejs @@ -3,11 +3,11 @@

    Reaction Time

    -
    -

    Click on the correct button as fast as possible when it turns green.
    Your score is determined from the average reaction time of 5 clicks.

    - -

    -
    + + + + +
    @@ -21,8 +21,6 @@
    - - <%- include('scores') -%>
    From 4dfd92f166cdcc26b3175da9b70110bfa3a3627c Mon Sep 17 00:00:00 2001 From: Jacob van Steyn Date: Sun, 9 Oct 2022 18:03:00 -0400 Subject: [PATCH 18/64] Add support for putting data in db --- public/javascripts/accuracy.js | 11 ++++------- public/javascripts/aimtraining.js | 20 ++++++++++++++++++++ public/javascripts/cps.js | 17 +++++++++++++++++ public/javascripts/reaction.js | 19 +++++++++++++++++++ views/scores.ejs | 7 +++++-- 5 files changed, 65 insertions(+), 9 deletions(-) diff --git a/public/javascripts/accuracy.js b/public/javascripts/accuracy.js index 3c654138a..a1a867af5 100644 --- a/public/javascripts/accuracy.js +++ b/public/javascripts/accuracy.js @@ -54,14 +54,11 @@ window.onload = function() { method:'POST', headers: {"X-CSRF-TOKEN": csrf, "Content-Type": "application/json"}, body: JSON.stringify(result) + }).then(async function( response ) { + var data = await response.json() + console.log( data ) + console.log("response ^") }) - .then(async function( response ) { - var data = await response.json() - console.log( data ) - console.log("response ^") - const evt = new CustomEvent("updateData", {detail: {data: data}, bubbles: true, composed: false, cancelable: false}) - document.dispatchEvent(evt) - }) clicks = [] startBtn.disabled = false diff --git a/public/javascripts/aimtraining.js b/public/javascripts/aimtraining.js index ddbc1884c..aae2703d3 100644 --- a/public/javascripts/aimtraining.js +++ b/public/javascripts/aimtraining.js @@ -24,4 +24,24 @@ window.onload = function() { const reactionBtn3 = document.getElementById("reactionBtn3"); const reactionBtn4 = document.getElementById("reactionBtn4"); const reactionBtn5 = document.getElementById("reactionBtn5"); + + + function endGame() { + + var result = { + owner_id: user, + game_type: game, + score: 0 + } + + fetch( '/addResult', { + method:'POST', + headers: {"X-CSRF-TOKEN": csrf, "Content-Type": "application/json"}, + body: JSON.stringify(result) + }).then(async function( response ) { + var data = await response.json() + console.log( data ) + console.log("response ^") + }) + } } diff --git a/public/javascripts/cps.js b/public/javascripts/cps.js index 39f0bfba7..1198c8dad 100644 --- a/public/javascripts/cps.js +++ b/public/javascripts/cps.js @@ -50,6 +50,23 @@ window.onload = function() { statusText.innerText = `You performed ${numClicks} in 10 seconds!` clickWindow.style.backgroundColor = "lightslategrey" clickWindow.removeEventListener('click', handleClick) + + var result = { + owner_id: user, + game_type: game, + score: numClicks + } + + fetch( '/addResult', { + method:'POST', + headers: {"X-CSRF-TOKEN": csrf, "Content-Type": "application/json"}, + body: JSON.stringify(result) + }).then(async function( response ) { + var data = await response.json() + console.log( data ) + console.log("response ^") + }) + startBtn.disabled = false } diff --git a/public/javascripts/reaction.js b/public/javascripts/reaction.js index e69de29bb..34cfd81a6 100644 --- a/public/javascripts/reaction.js +++ b/public/javascripts/reaction.js @@ -0,0 +1,19 @@ +window.onload = function () { + + var result = { + owner_id: user, + game_type: game, + score: 0 + } + + fetch( '/addResult', { + method:'POST', + headers: {"X-CSRF-TOKEN": csrf, "Content-Type": "application/json"}, + body: JSON.stringify(result) + }).then(async function( response ) { + var data = await response.json() + console.log( data ) + console.log("response ^") + }) + +} \ No newline at end of file diff --git a/views/scores.ejs b/views/scores.ejs index 6f36fa144..81229437a 100644 --- a/views/scores.ejs +++ b/views/scores.ejs @@ -1,3 +1,4 @@ +
    @@ -7,8 +8,10 @@ <%- include('footer') -%> \ No newline at end of file diff --git a/views/scores.ejs b/views/scores.ejs index 81229437a..d0a1c8932 100644 --- a/views/scores.ejs +++ b/views/scores.ejs @@ -1,40 +1,49 @@ - -
    - -
    -
    - + - <%- include('footer') -%> \ No newline at end of file diff --git a/views/aimtraining.ejs b/views/aimtraining.ejs index a07afa946..71e6ad184 100644 --- a/views/aimtraining.ejs +++ b/views/aimtraining.ejs @@ -17,5 +17,7 @@
    + <%- include('scores') -%> + <%- include('footer') -%> \ No newline at end of file diff --git a/views/reaction.ejs b/views/reaction.ejs index fd25a1e36..3b0aa6998 100644 --- a/views/reaction.ejs +++ b/views/reaction.ejs @@ -22,6 +22,7 @@ + <%- include('scores') -%> <%- include('footer') -%> \ No newline at end of file diff --git a/views/scores.ejs b/views/scores.ejs index d0a1c8932..a929d034c 100644 --- a/views/scores.ejs +++ b/views/scores.ejs @@ -1,4 +1,4 @@ - + <%- include('footer') -%> \ No newline at end of file From 05ae21940c7825be36e8e34acb06e13e255e63ea Mon Sep 17 00:00:00 2001 From: seansta18 Date: Mon, 10 Oct 2022 17:03:03 -0400 Subject: [PATCH 24/64] Set up GET requests on the client side --- public/javascripts/leaderboard.js | 105 ++++++++++++++++++------------ 1 file changed, 63 insertions(+), 42 deletions(-) diff --git a/public/javascripts/leaderboard.js b/public/javascripts/leaderboard.js index b22459a98..5f6922488 100644 --- a/public/javascripts/leaderboard.js +++ b/public/javascripts/leaderboard.js @@ -5,53 +5,74 @@ window.onload = function() { const table = document.getElementById("leaderboard-table"); cpsBtn.addEventListener('click', function () { - //GET Table to update - while(table.rows.length !== 0) - { - table.deleteRow(0); - } - - var row = table.insertRow(0); - var userCell = row.insertCell(0); - var scoreCell = row.insertCell(1); - - userCell.innerHTML = "Username"; - userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; - scoreCell.innerHTML = "Clicks Per Second"; - scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + fetch('/cpsScores',{ + method: 'GET' + }) + .then( function (response ) { + return response.json(); + }) + .then( function (response){ + while(table.rows.length !== 0) + { + table.deleteRow(0); + } + + var row = table.insertRow(0); + var userCell = row.insertCell(0); + var scoreCell = row.insertCell(1); + + userCell.innerHTML = "Username"; + userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + scoreCell.innerHTML = "Clicks Per Second"; + scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + }) }) reactionBtn.addEventListener('click', function () { - //GET Table to update - while(table.rows.length !== 0) - { - table.deleteRow(0); - } - - var row = table.insertRow(0); - var userCell = row.insertCell(0); - var scoreCell = row.insertCell(1); - - userCell.innerHTML = "Username"; - userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; - scoreCell.innerHTML = "Average Time"; - scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + fetch('/reactionScores',{ + method: 'GET' + }) + .then( function (response ) { + return response.json(); + }) + .then( function (response){ + while(table.rows.length !== 0) + { + table.deleteRow(0); + } + + var row = table.insertRow(0); + var userCell = row.insertCell(0); + var scoreCell = row.insertCell(1); + + userCell.innerHTML = "Username"; + userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + scoreCell.innerHTML = "Average Time"; + scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + }) }) accuracyBtn.addEventListener('click', function () { - //GET Table to update - while(table.rows.length !== 0) - { - table.deleteRow(0); - } - - var row = table.insertRow(0); - var userCell = row.insertCell(0); - var scoreCell = row.insertCell(1); - - userCell.innerHTML = "Username"; - userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; - scoreCell.innerHTML = "Time"; - scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + fetch('/accuracyScores',{ + method: 'GET' + }) + .then( function (response ) { + return response.json(); + }) + .then( function (response){ + while(table.rows.length !== 0) + { + table.deleteRow(0); + } + + var row = table.insertRow(0); + var userCell = row.insertCell(0); + var scoreCell = row.insertCell(1); + + userCell.innerHTML = "Username"; + userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + scoreCell.innerHTML = "Time"; + scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + }) }) } \ No newline at end of file From b33dcc63f2567ca0cf8ed550736b488a2853c7d2 Mon Sep 17 00:00:00 2001 From: seansta18 Date: Mon, 10 Oct 2022 17:24:15 -0400 Subject: [PATCH 25/64] Set up skeleton GET requests --- app.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/app.js b/app.js index d827d79b6..a8354e9c5 100644 --- a/app.js +++ b/app.js @@ -54,6 +54,24 @@ app.use(function(req, res, next) { next(); }); +app.get('/cpsScores', function(req, res) { + // collection.find({ username: req.session.username}).toArray().then(result => { + // res.end(JSON.stringify(result)); + // }); +}) + +app.get('/reactionScores', function(req, res) { + // collection.find({ username: req.session.username}).toArray().then(result => { + // res.end(JSON.stringify(result)); + // }); +}) + +app.get('/accuracyScores', function(req, res) { + // collection.find({ username: req.session.username}).toArray().then(result => { + // res.end(JSON.stringify(result)); + // }); +}) + app.use('/', indexRouter); app.use('/', authRouter); app.use('/', gamesRouter); From 992ba71d9f55bae4af532c95981fbec11f28bd9d Mon Sep 17 00:00:00 2001 From: baihui23 Date: Mon, 10 Oct 2022 19:30:18 -0400 Subject: [PATCH 26/64] fixed aim training --- public/javascripts/aimtraining.js | 75 ++++++++++++++++++++++++------- views/aimtraining.ejs | 14 +++--- 2 files changed, 66 insertions(+), 23 deletions(-) diff --git a/public/javascripts/aimtraining.js b/public/javascripts/aimtraining.js index 3e2c54ca6..0f88dcc36 100644 --- a/public/javascripts/aimtraining.js +++ b/public/javascripts/aimtraining.js @@ -1,38 +1,81 @@ window.onload = function() { + let startTs = null + let numClicks = 0 const randBtn = document.getElementsByClassName('randBtn'); const btnCont = document.getElementById('btnContainer'); + const statusText = document.getElementById("statusText") const winWidth = btnCont.offsetWidth const winHeight = btnCont.offsetHeight; + const startBtn = document.getElementById("startBtn"); + startBtn.addEventListener('click', function () { + startBtn.disabled = true; + statusText.innerText = "Starting in 3..."; + setTimeout(function() {countdown(2)}, 1100) + }) + + function countdown(i){ + if (i !== 0){ + statusText.innerText = (i == 2) ? "Starting in 3... 2..." : (i == 1) ? "Starting in 3... 2.. 1..." : "NAAA" + i -= 1 + // console.log(i) + setTimeout(function() {countdown(i)}, 1100) + } + else{ + statusText.innerText = "" + startGame() + } + } + function getRandomNumber(min, max) { return Math.random() * (max - min - 120) + min; } + + function startGame() { + startTs = Date.now() + numClicks = 0 + + for( let i = 0; i < randBtn.length; i++) { + let currBtn = randBtn[i]; + const randomTop = getRandomNumber(0, winHeight); + const randomLeft = getRandomNumber(0, winWidth); + + currBtn.style.position = 'absolute' + currBtn.style.width = '2em' + currBtn.style.height = '2em' + currBtn.style.top = randomTop +"px"; + currBtn.style.left = randomLeft +"px"; - for( let i = 0; i < randBtn.length; i++) { - let currBtn = randBtn[i]; - const randomTop = getRandomNumber(0, winHeight); - const randomLeft = getRandomNumber(0, winWidth); - - currBtn.style.top = randomTop +"px"; - currBtn.style.left = randomLeft +"px"; + currBtn.addEventListener('click', handleClick) + } } - const statusText = document.getElementById("statusText") - const reactionBtn1 = document.getElementById("reactionBtn1") - const reactionBtn2 = document.getElementById("reactionBtn2") - const reactionBtn3 = document.getElementById("reactionBtn3"); - const reactionBtn4 = document.getElementById("reactionBtn4"); - const reactionBtn5 = document.getElementById("reactionBtn5"); - + function handleClick(evt) { + evt.target.style.width = '0px' + evt.target.style.height = '0px' + + numClicks += 1 + + if (numClicks === 5) { + endGame() + } + } function endGame() { - + score = (Date.now() - startTs) / 1000 + statusText.innerText = `Nice work! Total time: ${score} sec` + + numClicks = 0 + startTs = 0 + startBtn.disabled = false + var result = { owner_id: user, game_type: game, - score: 0 + score: score } + console.log(result) fetch( '/addResult', { method:'POST', diff --git a/views/aimtraining.ejs b/views/aimtraining.ejs index 71e6ad184..fb30974a0 100644 --- a/views/aimtraining.ejs +++ b/views/aimtraining.ejs @@ -7,13 +7,13 @@

    -
    -
    -
    -
    -
    -
    -
    +
    +
    +
    +
    +
    +
    +
    From b409310a4e476f6ba01e63eda3131c59ed1a98ab Mon Sep 17 00:00:00 2001 From: baihui23 Date: Mon, 10 Oct 2022 20:23:10 -0400 Subject: [PATCH 27/64] reaction test fixed. needs color change --- public/javascripts/accuracy.js | 2 +- public/javascripts/aimtraining.js | 2 +- public/javascripts/reaction.js | 77 +++++++++++++++++++++++++------ views/reaction.ejs | 24 +++++----- 4 files changed, 76 insertions(+), 29 deletions(-) diff --git a/public/javascripts/accuracy.js b/public/javascripts/accuracy.js index 2f541ca23..483867256 100644 --- a/public/javascripts/accuracy.js +++ b/public/javascripts/accuracy.js @@ -24,7 +24,7 @@ window.onload = function() { function countdown(i){ if (i !== 0){ - statusText.innerText = (i == 2) ? "Starting in 3... 2..." : (i == 1) ? "Starting in 3... 2.. 1..." : "NAAA" + statusText.innerText = (i == 2) ? "Starting in 3... 2..." : (i == 1) ? "Starting in 3... 2... 1..." : "NAAA" i -= 1 console.log(i) setTimeout(function() {countdown(i)}, 1100) diff --git a/public/javascripts/aimtraining.js b/public/javascripts/aimtraining.js index 0f88dcc36..239f8792d 100644 --- a/public/javascripts/aimtraining.js +++ b/public/javascripts/aimtraining.js @@ -17,7 +17,7 @@ window.onload = function() { function countdown(i){ if (i !== 0){ - statusText.innerText = (i == 2) ? "Starting in 3... 2..." : (i == 1) ? "Starting in 3... 2.. 1..." : "NAAA" + statusText.innerText = (i == 2) ? "Starting in 3... 2..." : (i == 1) ? "Starting in 3... 2... 1..." : "NAAA" i -= 1 // console.log(i) setTimeout(function() {countdown(i)}, 1100) diff --git a/public/javascripts/reaction.js b/public/javascripts/reaction.js index 03bfb827a..5558bff5b 100644 --- a/public/javascripts/reaction.js +++ b/public/javascripts/reaction.js @@ -1,21 +1,70 @@ window.onload = function () { + let startTs = null - var result = { - owner_id: user, - game_type: game, - score: 0 + const gameWindow = document.getElementById('gameWindow') + const statusText = document.getElementById('statusText') + const activeStatus = document.getElementById('activeStatus') + + const startBtn = document.getElementById("startBtn"); + startBtn.addEventListener('click', function () { + startBtn.disabled = true; + statusText.innerText = "Starting in 3..."; + setTimeout(function() {countdown(2)}, 1100) + }) + + function countdown(i){ + if (i !== 0){ + statusText.innerText = (i == 2) ? "Starting in 3... 2..." : (i == 1) ? "Starting in 3... 2... 1..." : "NAAA" + i -= 1 + setTimeout(function() {countdown(i)}, 1100) + } + else{ + statusText.innerText = "Click when the area is green." + playGame() + } } - fetch( '/addResult', { - method:'POST', - headers: {"X-CSRF-TOKEN": csrf, "Content-Type": "application/json"}, - body: JSON.stringify(result) - }).then(async function( response ) { - var data = await response.json() - console.log( data ) - console.log("response ^") + function playGame() { + // delay between 0 and 2 sec + let randDelay = Math.random() * 2000 + setTimeout(function () { + gameWindow.addEventListener('click', endGame) + gameWindow.style.backgroundColor = 'lightgreen' // doesnt work? + activeStatus.innerText = "CLICK ME!" + startTs = Date.now() + + }, + randDelay) - window.dispatchEvent(new CustomEvent("updateData", {detail: {data: data}})) - }) + } + + function endGame () { + score = (Date.now() - startTs) / 1000 + startTs = null + gameWindow.removeEventListener('click', endGame) + + startBtn.disabled = false + activeStatus.innerText = '' + statusText.innerText = `Reaction time: ${score} sec` + + var result = { + owner_id: user, + game_type: game, + score: score + } + console.log(result) + + fetch( '/addResult', { + method:'POST', + headers: {"X-CSRF-TOKEN": csrf, "Content-Type": "application/json"}, + body: JSON.stringify(result) + }).then(async function( response ) { + var data = await response.json() + console.log( data ) + console.log("response ^") + + window.dispatchEvent(new CustomEvent("updateData", {detail: {data: data}})) + }) + } } \ No newline at end of file diff --git a/views/reaction.ejs b/views/reaction.ejs index 3b0aa6998..84466e336 100644 --- a/views/reaction.ejs +++ b/views/reaction.ejs @@ -3,21 +3,19 @@

    Reaction Time

    - - - - - - -
    +
    +

    + There will be a random delay after the starting countdown.
    + Click on the game canvas as fast as possible when it turns green. +

    + +

    +
    +
    -
    -
    -
    -
    -
    -
    +

    +
    From 2af7b68ea4b630d0943c5e108fae16c68c11428c Mon Sep 17 00:00:00 2001 From: seansta18 Date: Tue, 11 Oct 2022 18:00:15 -0400 Subject: [PATCH 28/64] Added functionality to update table with all scores --- app.js | 20 +------------------- public/javascripts/leaderboard.js | 19 ++++++++++++++++--- routes/scores.js | 24 ++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/app.js b/app.js index a8354e9c5..442a249cb 100644 --- a/app.js +++ b/app.js @@ -15,6 +15,7 @@ var indexRouter = require('./routes/index'); var authRouter = require('./routes/auth'); var gamesRouter = require('./routes/games'); var scoresRouter = require('./routes/scores'); +const { Timestamp, Int32 } = require('mongodb'); var app = express(); @@ -23,7 +24,6 @@ mongoose.connect(process.env['URI']) .then(() => console.log('Connected to MongoDB')) .catch((err) => console.error(err)); - // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); @@ -54,24 +54,6 @@ app.use(function(req, res, next) { next(); }); -app.get('/cpsScores', function(req, res) { - // collection.find({ username: req.session.username}).toArray().then(result => { - // res.end(JSON.stringify(result)); - // }); -}) - -app.get('/reactionScores', function(req, res) { - // collection.find({ username: req.session.username}).toArray().then(result => { - // res.end(JSON.stringify(result)); - // }); -}) - -app.get('/accuracyScores', function(req, res) { - // collection.find({ username: req.session.username}).toArray().then(result => { - // res.end(JSON.stringify(result)); - // }); -}) - app.use('/', indexRouter); app.use('/', authRouter); app.use('/', gamesRouter); diff --git a/public/javascripts/leaderboard.js b/public/javascripts/leaderboard.js index 5f6922488..7fe45345e 100644 --- a/public/javascripts/leaderboard.js +++ b/public/javascripts/leaderboard.js @@ -5,13 +5,14 @@ window.onload = function() { const table = document.getElementById("leaderboard-table"); cpsBtn.addEventListener('click', function () { - fetch('/cpsScores',{ + fetch('/GetCPSScores',{ method: 'GET' }) .then( function (response ) { return response.json(); }) .then( function (response){ + console.log(response) while(table.rows.length !== 0) { table.deleteRow(0); @@ -25,11 +26,23 @@ window.onload = function() { userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; scoreCell.innerHTML = "Clicks Per Second"; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + + for(let i = 0; i < response.length; i++) + { + var row = table.insertRow(1); + var userCell = row.insertCell(0); + var scoreCell = row.insertCell(1); + + userCell.innerHTML = response[i].owner_id; + userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + scoreCell.innerHTML = response[i].score; + scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + } }) }) reactionBtn.addEventListener('click', function () { - fetch('/reactionScores',{ + fetch('/GetReactionScores',{ method: 'GET' }) .then( function (response ) { @@ -53,7 +66,7 @@ window.onload = function() { }) accuracyBtn.addEventListener('click', function () { - fetch('/accuracyScores',{ + fetch('/GetAccuracyScores',{ method: 'GET' }) .then( function (response ) { diff --git a/routes/scores.js b/routes/scores.js index 329145565..276d94238 100644 --- a/routes/scores.js +++ b/routes/scores.js @@ -32,4 +32,28 @@ router.post('/addResult', function (req, res, next) { }) }); +router.get("/getCPSScores", function(req, res, next) { + console.log("Getting scores for CPS: %s", req.body) + Results.find({game_type: "cps"}).lean().exec(function(err, documents) { + console.log("Found scores: %s", documents) + res.json(documents) + }) +}) + +router.get("/GetReactionScores", function(req, res, next) { + console.log("Getting scores for Reaction: %s", req.body) + Results.find({game_type: "reaction"}).lean().exec(function(err, documents) { + console.log("Found scores: %s", documents) + res.json(documents) + }) +}) + +router.get("/GetAccuracyScores", function(req, res, next) { + console.log("Getting scores for Accuracy: %s", req.body) + Results.find({game_type: "accuracy"}).lean().exec(function(err, documents) { + console.log("Found scores: %s", documents) + res.json(documents) + }) +}) + module.exports = router; \ No newline at end of file From fde9a35ff64a525fa932679fc493059126977dac Mon Sep 17 00:00:00 2001 From: seansta18 Date: Tue, 11 Oct 2022 18:03:13 -0400 Subject: [PATCH 29/64] updated all buttons to work --- public/javascripts/leaderboard.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/public/javascripts/leaderboard.js b/public/javascripts/leaderboard.js index 7fe45345e..e716daf27 100644 --- a/public/javascripts/leaderboard.js +++ b/public/javascripts/leaderboard.js @@ -62,6 +62,18 @@ window.onload = function() { userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; scoreCell.innerHTML = "Average Time"; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + + for(let i = 0; i < response.length; i++) + { + var row = table.insertRow(1); + var userCell = row.insertCell(0); + var scoreCell = row.insertCell(1); + + userCell.innerHTML = response[i].owner_id; + userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + scoreCell.innerHTML = response[i].score; + scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + } }) }) @@ -86,6 +98,18 @@ window.onload = function() { userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; scoreCell.innerHTML = "Time"; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + + for(let i = 0; i < response.length; i++) + { + var row = table.insertRow(1); + var userCell = row.insertCell(0); + var scoreCell = row.insertCell(1); + + userCell.innerHTML = response[i].owner_id; + userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + scoreCell.innerHTML = response[i].score; + scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + } }) }) } \ No newline at end of file From e6883faf5a59455bb4997ba31ab8f310970dc0aa Mon Sep 17 00:00:00 2001 From: seansta18 Date: Wed, 12 Oct 2022 11:01:37 -0400 Subject: [PATCH 30/64] Displays usernames with their scores on the leaderboard --- public/javascripts/leaderboard.js | 68 ++++++++++++++++++++++++++++++- routes/scores.js | 9 ++++ 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/public/javascripts/leaderboard.js b/public/javascripts/leaderboard.js index e716daf27..c2d3a4b27 100644 --- a/public/javascripts/leaderboard.js +++ b/public/javascripts/leaderboard.js @@ -38,7 +38,29 @@ window.onload = function() { scoreCell.innerHTML = response[i].score; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; } - }) + + fetch('/GetUsers',{ + method: 'GET' + }) + .then( function (res ) { + return res.json(); + }) + .then( function (res){ + console.log(res); + for(let i = 1; i < table.rows.length; i++) + { + var username = ""; + for(let j = 0; j < res.length; j++) + { + if(res[j].id === table.rows[i].cells[0].innerHTML) + { + username = res[j].username; + } + } + table.rows[i].cells[0].innerHTML = username; + } + }) + }) }) reactionBtn.addEventListener('click', function () { @@ -74,6 +96,27 @@ window.onload = function() { scoreCell.innerHTML = response[i].score; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; } + fetch('/GetUsers',{ + method: 'GET' + }) + .then( function (res ) { + return res.json(); + }) + .then( function (res){ + console.log(res); + for(let i = 1; i < table.rows.length; i++) + { + var username = ""; + for(let j = 0; j < res.length; j++) + { + if(res[j].id === table.rows[i].cells[0].innerHTML) + { + username = res[j].username; + } + } + table.rows[i].cells[0].innerHTML = username; + } + }) }) }) @@ -104,12 +147,33 @@ window.onload = function() { var row = table.insertRow(1); var userCell = row.insertCell(0); var scoreCell = row.insertCell(1); - + userCell.innerHTML = response[i].owner_id; userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; scoreCell.innerHTML = response[i].score; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; } + fetch('/GetUsers',{ + method: 'GET' + }) + .then( function (res ) { + return res.json(); + }) + .then( function (res){ + console.log(res); + for(let i = 1; i < table.rows.length; i++) + { + var username = ""; + for(let j = 0; j < res.length; j++) + { + if(res[j].id === table.rows[i].cells[0].innerHTML) + { + username = res[j].username; + } + } + table.rows[i].cells[0].innerHTML = username; + } + }) }) }) } \ No newline at end of file diff --git a/routes/scores.js b/routes/scores.js index 276d94238..5172d577e 100644 --- a/routes/scores.js +++ b/routes/scores.js @@ -1,6 +1,7 @@ var express = require('express'); var router = express.Router(); const Results = require("../models/Results"); +const Users = require ("../models/User"); router.get('/leaderboard', function (req, res, next) { res.render('leaderboard', { title: 'ReactionTests', user : req.user}); @@ -56,4 +57,12 @@ router.get("/GetAccuracyScores", function(req, res, next) { }) }) +router.get("/GetUsers", function(req, res, next) { + console.log("Getting Users: %s", req.body) + Users.find({ }).exec(function(err, documents) { + console.log("Found Users: %s", documents) + res.json(documents) + }) +}) + module.exports = router; \ No newline at end of file From c1a1d65900a5da2404f71f0e0b1e8f9bc5e51a91 Mon Sep 17 00:00:00 2001 From: seansta18 Date: Wed, 12 Oct 2022 18:25:22 -0400 Subject: [PATCH 31/64] Bug fixes --- public/javascripts/leaderboard.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/public/javascripts/leaderboard.js b/public/javascripts/leaderboard.js index c2d3a4b27..424b96fce 100644 --- a/public/javascripts/leaderboard.js +++ b/public/javascripts/leaderboard.js @@ -27,7 +27,13 @@ window.onload = function() { scoreCell.innerHTML = "Clicks Per Second"; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; - for(let i = 0; i < response.length; i++) + // var length = 10; + // if(response.length < 10) + // { + // length = response.length; + // } + + for(let i = 0; i < length; i++) { var row = table.insertRow(1); var userCell = row.insertCell(0); From a5ad2cdff592d8a10fb3ba679d1aa705bd19fca0 Mon Sep 17 00:00:00 2001 From: seansta18 Date: Wed, 12 Oct 2022 18:31:15 -0400 Subject: [PATCH 32/64] bugs --- public/javascripts/leaderboard.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/public/javascripts/leaderboard.js b/public/javascripts/leaderboard.js index 424b96fce..bb4824311 100644 --- a/public/javascripts/leaderboard.js +++ b/public/javascripts/leaderboard.js @@ -91,6 +91,12 @@ window.onload = function() { scoreCell.innerHTML = "Average Time"; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + // var length = 10; + // if(response.length < 10) + // { + // length = response.length; + // } + for(let i = 0; i < response.length; i++) { var row = table.insertRow(1); @@ -148,6 +154,12 @@ window.onload = function() { scoreCell.innerHTML = "Time"; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + // var length = 10; + // if(response.length < 10) + // { + // length = response.length; + // } + for(let i = 0; i < response.length; i++) { var row = table.insertRow(1); From 2fbd0d9fac556c963b147882f1baddb4bf0e3889 Mon Sep 17 00:00:00 2001 From: seansta18 Date: Wed, 12 Oct 2022 18:44:22 -0400 Subject: [PATCH 33/64] Bug fixes --- models/Results.js | 4 ++++ public/javascripts/leaderboard.js | 18 ++++++++---------- routes/scores.js | 6 +++--- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/models/Results.js b/models/Results.js index 1e5703ae9..6efafc638 100644 --- a/models/Results.js +++ b/models/Results.js @@ -21,6 +21,10 @@ ResultsSchema.statics.getAllResultsForGame = function(game) { return this.find({game_type: game}) } +ResultsSchema.statics.getTopResultsForGame = function(game_type, n_scores) { + return this.find({game_type: game_type}).sort({score: "desc"}).limit(n_scores) +} + ResultsSchema.statics.getResultsForUserId = function(user_id) { return this.find({owner_id: user_id}) } diff --git a/public/javascripts/leaderboard.js b/public/javascripts/leaderboard.js index bb4824311..a57d729e0 100644 --- a/public/javascripts/leaderboard.js +++ b/public/javascripts/leaderboard.js @@ -5,14 +5,13 @@ window.onload = function() { const table = document.getElementById("leaderboard-table"); cpsBtn.addEventListener('click', function () { - fetch('/GetCPSScores',{ + fetch('/getCPSScores',{ method: 'GET' }) .then( function (response ) { return response.json(); }) .then( function (response){ - console.log(response) while(table.rows.length !== 0) { table.deleteRow(0); @@ -24,7 +23,7 @@ window.onload = function() { userCell.innerHTML = "Username"; userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; - scoreCell.innerHTML = "Clicks Per Second"; + scoreCell.innerHTML = "Number Clicks"; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; // var length = 10; @@ -32,10 +31,10 @@ window.onload = function() { // { // length = response.length; // } - - for(let i = 0; i < length; i++) + + for(let i = 0; i < response.length; i++) { - var row = table.insertRow(1); + var row = table.insertRow(i+1); var userCell = row.insertCell(0); var scoreCell = row.insertCell(1); @@ -44,7 +43,6 @@ window.onload = function() { scoreCell.innerHTML = response[i].score; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; } - fetch('/GetUsers',{ method: 'GET' }) @@ -66,7 +64,7 @@ window.onload = function() { table.rows[i].cells[0].innerHTML = username; } }) - }) + }) }) reactionBtn.addEventListener('click', function () { @@ -99,7 +97,7 @@ window.onload = function() { for(let i = 0; i < response.length; i++) { - var row = table.insertRow(1); + var row = table.insertRow(i+1); var userCell = row.insertCell(0); var scoreCell = row.insertCell(1); @@ -162,7 +160,7 @@ window.onload = function() { for(let i = 0; i < response.length; i++) { - var row = table.insertRow(1); + var row = table.insertRow(i+1); var userCell = row.insertCell(0); var scoreCell = row.insertCell(1); diff --git a/routes/scores.js b/routes/scores.js index 5172d577e..8debe872b 100644 --- a/routes/scores.js +++ b/routes/scores.js @@ -35,7 +35,7 @@ router.post('/addResult', function (req, res, next) { router.get("/getCPSScores", function(req, res, next) { console.log("Getting scores for CPS: %s", req.body) - Results.find({game_type: "cps"}).lean().exec(function(err, documents) { + Results.getTopResultsForGame("cps", 10).exec(function(err, documents) { console.log("Found scores: %s", documents) res.json(documents) }) @@ -43,7 +43,7 @@ router.get("/getCPSScores", function(req, res, next) { router.get("/GetReactionScores", function(req, res, next) { console.log("Getting scores for Reaction: %s", req.body) - Results.find({game_type: "reaction"}).lean().exec(function(err, documents) { + Results.getTopResultsForGame("reaction", 10).exec(function(err, documents) { console.log("Found scores: %s", documents) res.json(documents) }) @@ -51,7 +51,7 @@ router.get("/GetReactionScores", function(req, res, next) { router.get("/GetAccuracyScores", function(req, res, next) { console.log("Getting scores for Accuracy: %s", req.body) - Results.find({game_type: "accuracy"}).lean().exec(function(err, documents) { + Results.getTopResultsForGame("accuracy", 10).exec(function(err, documents) { console.log("Found scores: %s", documents) res.json(documents) }) From e347012960acd53783b37ea05709fd45013814de Mon Sep 17 00:00:00 2001 From: Jacob van Steyn Date: Wed, 12 Oct 2022 18:45:05 -0400 Subject: [PATCH 34/64] Fix timing --- public/javascripts/cps.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/javascripts/cps.js b/public/javascripts/cps.js index 8d4d48508..ccec48b87 100644 --- a/public/javascripts/cps.js +++ b/public/javascripts/cps.js @@ -41,7 +41,7 @@ window.onload = function() { numClicks = 0 clickWindow.addEventListener('click', handleClick) - count = 10; // 10 Seconds + count = 100; // 10 Seconds counter = setInterval(timeLeft, 100); //10 will run it every 100th of a second } From c92b30f235cc7bf623db2124eabb2699e2e47b87 Mon Sep 17 00:00:00 2001 From: Jacob van Steyn Date: Wed, 12 Oct 2022 18:49:54 -0400 Subject: [PATCH 35/64] make text non-selectable --- views/reaction.ejs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/reaction.ejs b/views/reaction.ejs index 84466e336..5203125ca 100644 --- a/views/reaction.ejs +++ b/views/reaction.ejs @@ -14,7 +14,7 @@
    -

    +

    From 5e2d1410b50f2b05c236aefe6839de76ec1dbe29 Mon Sep 17 00:00:00 2001 From: seansta18 Date: Wed, 12 Oct 2022 19:00:27 -0400 Subject: [PATCH 36/64] Added Aim to Leaderboard and fixed timing order --- models/Results.js | 4 ++ public/javascripts/leaderboard.js | 75 ++++++++++++++++++++++++------- routes/scores.js | 12 ++++- views/leaderboard.ejs | 1 + 4 files changed, 74 insertions(+), 18 deletions(-) diff --git a/models/Results.js b/models/Results.js index 6efafc638..75181573b 100644 --- a/models/Results.js +++ b/models/Results.js @@ -25,6 +25,10 @@ ResultsSchema.statics.getTopResultsForGame = function(game_type, n_scores) { return this.find({game_type: game_type}).sort({score: "desc"}).limit(n_scores) } +ResultsSchema.statics.getTopResultsForTimeGame = function(game_type, n_scores) { + return this.find({game_type: game_type}).sort({score: "asc"}).limit(n_scores) +} + ResultsSchema.statics.getResultsForUserId = function(user_id) { return this.find({owner_id: user_id}) } diff --git a/public/javascripts/leaderboard.js b/public/javascripts/leaderboard.js index a57d729e0..ff0f6849a 100644 --- a/public/javascripts/leaderboard.js +++ b/public/javascripts/leaderboard.js @@ -2,6 +2,7 @@ window.onload = function() { const cpsBtn = document.getElementById("cpsBoardBtn"); const reactionBtn = document.getElementById("reactionBoardBtn"); const accuracyBtn = document.getElementById("accuracyBoardBtn"); + const aimBtn = document.getElementById("aimBoardBtn"); const table = document.getElementById("leaderboard-table"); cpsBtn.addEventListener('click', function () { @@ -26,11 +27,6 @@ window.onload = function() { scoreCell.innerHTML = "Number Clicks"; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; - // var length = 10; - // if(response.length < 10) - // { - // length = response.length; - // } for(let i = 0; i < response.length; i++) { @@ -89,12 +85,6 @@ window.onload = function() { scoreCell.innerHTML = "Average Time"; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; - // var length = 10; - // if(response.length < 10) - // { - // length = response.length; - // } - for(let i = 0; i < response.length; i++) { var row = table.insertRow(i+1); @@ -152,11 +142,64 @@ window.onload = function() { scoreCell.innerHTML = "Time"; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; - // var length = 10; - // if(response.length < 10) - // { - // length = response.length; - // } + + for(let i = 0; i < response.length; i++) + { + var row = table.insertRow(i+1); + var userCell = row.insertCell(0); + var scoreCell = row.insertCell(1); + + userCell.innerHTML = response[i].owner_id; + userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + scoreCell.innerHTML = response[i].score; + scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + } + fetch('/GetUsers',{ + method: 'GET' + }) + .then( function (res ) { + return res.json(); + }) + .then( function (res){ + console.log(res); + for(let i = 1; i < table.rows.length; i++) + { + var username = ""; + for(let j = 0; j < res.length; j++) + { + if(res[j].id === table.rows[i].cells[0].innerHTML) + { + username = res[j].username; + } + } + table.rows[i].cells[0].innerHTML = username; + } + }) + }) + }) + + aimBtn.addEventListener('click', function () { + fetch('/GetAimScores',{ + method: 'GET' + }) + .then( function (response ) { + return response.json(); + }) + .then( function (response){ + while(table.rows.length !== 0) + { + table.deleteRow(0); + } + + var row = table.insertRow(0); + var userCell = row.insertCell(0); + var scoreCell = row.insertCell(1); + + userCell.innerHTML = "Username"; + userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + scoreCell.innerHTML = "Time"; + scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + for(let i = 0; i < response.length; i++) { diff --git a/routes/scores.js b/routes/scores.js index 8debe872b..209647571 100644 --- a/routes/scores.js +++ b/routes/scores.js @@ -43,7 +43,7 @@ router.get("/getCPSScores", function(req, res, next) { router.get("/GetReactionScores", function(req, res, next) { console.log("Getting scores for Reaction: %s", req.body) - Results.getTopResultsForGame("reaction", 10).exec(function(err, documents) { + Results.getTopResultsForTimeGame("reaction", 10).exec(function(err, documents) { console.log("Found scores: %s", documents) res.json(documents) }) @@ -51,7 +51,15 @@ router.get("/GetReactionScores", function(req, res, next) { router.get("/GetAccuracyScores", function(req, res, next) { console.log("Getting scores for Accuracy: %s", req.body) - Results.getTopResultsForGame("accuracy", 10).exec(function(err, documents) { + Results.getTopResultsForTimeGame("accuracy", 10).exec(function(err, documents) { + console.log("Found scores: %s", documents) + res.json(documents) + }) +}) + +router.get("/GetAimScores", function(req, res, next) { + console.log("Getting scores for Accuracy: %s", req.body) + Results.getTopResultsForTimeGame("aimtraining", 10).exec(function(err, documents) { console.log("Found scores: %s", documents) res.json(documents) }) diff --git a/views/leaderboard.ejs b/views/leaderboard.ejs index aa3a8bd30..44a6fc6d7 100644 --- a/views/leaderboard.ejs +++ b/views/leaderboard.ejs @@ -8,6 +8,7 @@ +

    From b45bb46bfe596ae3fec7326ae29f7bff13409b21 Mon Sep 17 00:00:00 2001 From: seansta18 Date: Wed, 12 Oct 2022 19:02:13 -0400 Subject: [PATCH 37/64] bug fixes --- public/javascripts/leaderboard.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/javascripts/leaderboard.js b/public/javascripts/leaderboard.js index ff0f6849a..8c0f8ab45 100644 --- a/public/javascripts/leaderboard.js +++ b/public/javascripts/leaderboard.js @@ -139,7 +139,7 @@ window.onload = function() { userCell.innerHTML = "Username"; userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; - scoreCell.innerHTML = "Time"; + scoreCell.innerHTML = "Total Time"; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; @@ -197,7 +197,7 @@ window.onload = function() { userCell.innerHTML = "Username"; userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; - scoreCell.innerHTML = "Time"; + scoreCell.innerHTML = "Total Time"; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; From 199c20884b3652fd75131e4b70a7cefee6b8ec09 Mon Sep 17 00:00:00 2001 From: seansta18 Date: Wed, 12 Oct 2022 19:03:07 -0400 Subject: [PATCH 38/64] bugs --- public/javascripts/leaderboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/javascripts/leaderboard.js b/public/javascripts/leaderboard.js index 8c0f8ab45..90ee97619 100644 --- a/public/javascripts/leaderboard.js +++ b/public/javascripts/leaderboard.js @@ -139,7 +139,7 @@ window.onload = function() { userCell.innerHTML = "Username"; userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; - scoreCell.innerHTML = "Total Time"; + scoreCell.innerHTML = "Average Time"; scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; From 1f232ad0c2ab586da68b99a3d9b171514d121f7f Mon Sep 17 00:00:00 2001 From: jrkim-wpi Date: Wed, 12 Oct 2022 19:13:47 -0400 Subject: [PATCH 39/64] aim training result --- models/Results.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/Results.js b/models/Results.js index 6efafc638..03aebaaf9 100644 --- a/models/Results.js +++ b/models/Results.js @@ -4,7 +4,7 @@ let Schema = mongoose.Schema; let ResultsSchema = new Schema( { owner_id: {type: String, required: true}, - game_type: {type: String, required: true, enum: ["cps", "accuracy", "reaction"]}, + game_type: {type: String, required: true, enum: ["cps", "accuracy", "reaction", "aimtraining"]}, score: { type: Number, required: [true, "A score is required!"]}, From 20314b2b91655bf8b01317aa404741d63383bb40 Mon Sep 17 00:00:00 2001 From: seansta18 Date: Wed, 12 Oct 2022 19:17:46 -0400 Subject: [PATCH 40/64] changed to bootstrap table with hovering --- public/javascripts/leaderboard.js | 32 +++++++++++++++---------------- views/leaderboard.ejs | 14 ++++++-------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/public/javascripts/leaderboard.js b/public/javascripts/leaderboard.js index 90ee97619..e49c921e6 100644 --- a/public/javascripts/leaderboard.js +++ b/public/javascripts/leaderboard.js @@ -23,9 +23,9 @@ window.onload = function() { var scoreCell = row.insertCell(1); userCell.innerHTML = "Username"; - userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + userCell.style = "scope=\"col\"; font-weight=bold"; scoreCell.innerHTML = "Number Clicks"; - scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + scoreCell.style = "scope=\"col\"; font-weight=bold"; for(let i = 0; i < response.length; i++) @@ -35,9 +35,9 @@ window.onload = function() { var scoreCell = row.insertCell(1); userCell.innerHTML = response[i].owner_id; - userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + userCell.style = "scope=\"row\""; scoreCell.innerHTML = response[i].score; - scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + scoreCell.style = "scope=\"row\""; } fetch('/GetUsers',{ method: 'GET' @@ -81,9 +81,9 @@ window.onload = function() { var scoreCell = row.insertCell(1); userCell.innerHTML = "Username"; - userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + userCell.style = "scope=\"col\"; font-weight=bold"; scoreCell.innerHTML = "Average Time"; - scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + scoreCell.style = "scope=\"col\"; font-weight=bold"; for(let i = 0; i < response.length; i++) { @@ -92,9 +92,9 @@ window.onload = function() { var scoreCell = row.insertCell(1); userCell.innerHTML = response[i].owner_id; - userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + userCell.style = "scope=\"row\""; scoreCell.innerHTML = response[i].score; - scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + scoreCell.style = "scope=\"row\""; } fetch('/GetUsers',{ method: 'GET' @@ -138,9 +138,9 @@ window.onload = function() { var scoreCell = row.insertCell(1); userCell.innerHTML = "Username"; - userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + userCell.style = "scope=\"col\"; font-weight=bold"; scoreCell.innerHTML = "Average Time"; - scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + scoreCell.style = "scope=\"col\"; font-weight=bold"; for(let i = 0; i < response.length; i++) @@ -150,9 +150,9 @@ window.onload = function() { var scoreCell = row.insertCell(1); userCell.innerHTML = response[i].owner_id; - userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + userCell.style = "scope=\"row\""; scoreCell.innerHTML = response[i].score; - scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + scoreCell.style = "scope=\"row\""; } fetch('/GetUsers',{ method: 'GET' @@ -196,9 +196,9 @@ window.onload = function() { var scoreCell = row.insertCell(1); userCell.innerHTML = "Username"; - userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + userCell.style = "scope=\"col\"; font-weight=bold"; scoreCell.innerHTML = "Total Time"; - scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + scoreCell.style = "scope=\"col\"; font-weight=bold"; for(let i = 0; i < response.length; i++) @@ -208,9 +208,9 @@ window.onload = function() { var scoreCell = row.insertCell(1); userCell.innerHTML = response[i].owner_id; - userCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + userCell.style = "scope=\"row\""; scoreCell.innerHTML = response[i].score; - scoreCell.style = "padding-left: 30px;padding-right: 40px;font-weight: bold;"; + scoreCell.style = "scope=\"row\""; } fetch('/GetUsers',{ method: 'GET' diff --git a/views/leaderboard.ejs b/views/leaderboard.ejs index 44a6fc6d7..7dff350d6 100644 --- a/views/leaderboard.ejs +++ b/views/leaderboard.ejs @@ -12,14 +12,12 @@

    -
    -
    - - - -
    -
    -
    + + + + +
    + <%- include('footer') -%> \ No newline at end of file From 5efb38e4515209acc7aa33948d6585033c22f5d6 Mon Sep 17 00:00:00 2001 From: seansta18 Date: Wed, 12 Oct 2022 19:33:48 -0400 Subject: [PATCH 41/64] Personal Scores Page --- public/javascripts/personalScores.js | 173 +++++++++++++++++++++++++++ routes/scores.js | 32 +++++ views/personalScores.ejs | 23 ++++ 3 files changed, 228 insertions(+) create mode 100644 public/javascripts/personalScores.js create mode 100644 views/personalScores.ejs diff --git a/public/javascripts/personalScores.js b/public/javascripts/personalScores.js new file mode 100644 index 000000000..4cafffdd0 --- /dev/null +++ b/public/javascripts/personalScores.js @@ -0,0 +1,173 @@ +window.onload = function() { + const cpsBtn = document.getElementById("cpsBoardBtn"); + const reactionBtn = document.getElementById("reactionBoardBtn"); + const accuracyBtn = document.getElementById("accuracyBoardBtn"); + const aimBtn = document.getElementById("aimBoardBtn"); + const table = document.getElementById("leaderboard-table"); + + cpsBtn.addEventListener('click', function () { + if(user !== null) + { + var body = JSON.stringify(user); + fetch('/getPersonalCPSScores',{ + method: 'GET', + body + }) + .then( function (response ) { + return response.json(); + }) + .then( function (response){ + while(table.rows.length !== 0) + { + table.deleteRow(0); + } + + var row = table.insertRow(0); + var userCell = row.insertCell(0); + var scoreCell = row.insertCell(1); + + userCell.innerHTML = "Date"; + userCell.style = "scope=\"col\"; font-weight=bold"; + scoreCell.innerHTML = "Number Clicks"; + scoreCell.style = "scope=\"col\"; font-weight=bold"; + + + for(let i = 0; i < response.length; i++) + { + var row = table.insertRow(i+1); + var userCell = row.insertCell(0); + var scoreCell = row.insertCell(1); + + userCell.innerHTML = response[i].time; + userCell.style = "scope=\"row\""; + scoreCell.innerHTML = response[i].score; + scoreCell.style = "scope=\"row\""; + } + }) + } + }) + + reactionBtn.addEventListener('click', function () { + if(user !== null) + { + var body = JSON.stringify(user); + fetch('/GetPersonalReactionScores',{ + method: 'GET', + body + }) + .then( function (response ) { + return response.json(); + }) + .then( function (response){ + while(table.rows.length !== 0) + { + table.deleteRow(0); + } + + var row = table.insertRow(0); + var userCell = row.insertCell(0); + var scoreCell = row.insertCell(1); + + userCell.innerHTML = "Date"; + userCell.style = "scope=\"col\"; font-weight=bold"; + scoreCell.innerHTML = "Average Time"; + scoreCell.style = "scope=\"col\"; font-weight=bold"; + + for(let i = 0; i < response.length; i++) + { + var row = table.insertRow(i+1); + var userCell = row.insertCell(0); + var scoreCell = row.insertCell(1); + + userCell.innerHTML = response[i].time; + userCell.style = "scope=\"row\""; + scoreCell.innerHTML = response[i].score; + scoreCell.style = "scope=\"row\""; + } + }) + } + }) + + accuracyBtn.addEventListener('click', function () { + if(user !== null) + { + var body = JSON.stringify(user); + fetch('/GetPersonalAccuracyScores',{ + method: 'GET', + body + }) + .then( function (response ) { + return response.json(); + }) + .then( function (response){ + while(table.rows.length !== 0) + { + table.deleteRow(0); + } + + var row = table.insertRow(0); + var userCell = row.insertCell(0); + var scoreCell = row.insertCell(1); + + userCell.innerHTML = "Date"; + userCell.style = "scope=\"col\"; font-weight=bold"; + scoreCell.innerHTML = "Average Time"; + scoreCell.style = "scope=\"col\"; font-weight=bold"; + + + for(let i = 0; i < response.length; i++) + { + var row = table.insertRow(i+1); + var userCell = row.insertCell(0); + var scoreCell = row.insertCell(1); + + userCell.innerHTML = response[i].time; + userCell.style = "scope=\"row\""; + scoreCell.innerHTML = response[i].score; + scoreCell.style = "scope=\"row\""; + } + }) + } + }) + + aimBtn.addEventListener('click', function () { + if(user !== null) + { + var body = JSON.stringify(user); + fetch('/GetPersonalAimScores',{ + method: 'GET' + }) + .then( function (response ) { + return response.json(); + }) + .then( function (response){ + while(table.rows.length !== 0) + { + table.deleteRow(0); + } + + var row = table.insertRow(0); + var userCell = row.insertCell(0); + var scoreCell = row.insertCell(1); + + userCell.innerHTML = "Date"; + userCell.style = "scope=\"col\"; font-weight=bold"; + scoreCell.innerHTML = "Total Time"; + scoreCell.style = "scope=\"col\"; font-weight=bold"; + + + for(let i = 0; i < response.length; i++) + { + var row = table.insertRow(i+1); + var userCell = row.insertCell(0); + var scoreCell = row.insertCell(1); + + userCell.innerHTML = response[i].time; + userCell.style = "scope=\"row\""; + scoreCell.innerHTML = response[i].score; + scoreCell.style = "scope=\"row\""; + } + }) + } + }) +} \ No newline at end of file diff --git a/routes/scores.js b/routes/scores.js index 209647571..d9008e9a4 100644 --- a/routes/scores.js +++ b/routes/scores.js @@ -73,4 +73,36 @@ router.get("/GetUsers", function(req, res, next) { }) }) +router.get("/getPersonalCPSScores", function(req, res, next) { + console.log("Getting scores for CPS: %s", req.body) + Results.getResultsForUserId(req.body.owner_id).exec(function(err, documents) { + console.log("Found scores: %s", documents) + res.json(documents) + }) +}) + +router.get("/GetPersonalReactionScores", function(req, res, next) { + console.log("Getting scores for Reaction: %s", req.body) + Results.getResultsForUserId(req.body.owner_id).exec(function(err, documents) { + console.log("Found scores: %s", documents) + res.json(documents) + }) +}) + +router.get("/GetPersonalAccuracyScores", function(req, res, next) { + console.log("Getting scores for Accuracy: %s", req.body) + Results.getResultsForUserId(req.body.owner_id).exec(function(err, documents) { + console.log("Found scores: %s", documents) + res.json(documents) + }) +}) + +router.get("/GetPersonalAimScores", function(req, res, next) { + console.log("Getting scores for Accuracy: %s", req.body) + Results.getResultsForUserId(req.body.owner_id).exec(function(err, documents) { + console.log("Found scores: %s", documents) + res.json(documents) + }) +}) + module.exports = router; \ No newline at end of file diff --git a/views/personalScores.ejs b/views/personalScores.ejs new file mode 100644 index 000000000..e96dc56fe --- /dev/null +++ b/views/personalScores.ejs @@ -0,0 +1,23 @@ +<%- include('header', { title: 'ReactionTests' }) -%> +
    +
    + +

    Personal Scores

    +
    +

    Click on the button you wish to view

    + + + + +

    +
    +
    + + + + +
    + +
    + +<%- include('footer') -%> \ No newline at end of file From 87da949f602280ffb9b8ddcb2d07d39f1b633d73 Mon Sep 17 00:00:00 2001 From: baihui23 Date: Wed, 12 Oct 2022 19:47:45 -0400 Subject: [PATCH 42/64] fixed 100 accessibility lighthouse score --- public/stylesheets/style.css | 2 +- views/accuracy.ejs | 4 ++-- views/aimtraining.ejs | 4 ++-- views/cps.ejs | 4 ++-- views/footer.ejs | 24 +++--------------------- views/header.ejs | 12 ++++++------ views/index.ejs | 6 +++--- views/leaderboard.ejs | 4 ++-- views/reaction.ejs | 4 ++-- 9 files changed, 23 insertions(+), 41 deletions(-) diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index e86266895..64964aba1 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -60,7 +60,7 @@ a { } .footer-links a { - color:#737373 + color:#cccccc } .footer-links a:active,.footer-links a:focus,.footer-links a:hover { diff --git a/views/accuracy.ejs b/views/accuracy.ejs index 2b2839782..7cd399ef1 100644 --- a/views/accuracy.ejs +++ b/views/accuracy.ejs @@ -4,9 +4,9 @@

    Accuracy

    -

    Click on the correct button as fast as possible when it turns green.
    Your score is determined from the average reaction time of 5 clicks.

    +

    Click on the correct button as fast as possible when it turns green.
    Your score is determined from the average reaction time of 5 clicks.

    -

    +

    diff --git a/views/aimtraining.ejs b/views/aimtraining.ejs index fb30974a0..4ea3265a4 100644 --- a/views/aimtraining.ejs +++ b/views/aimtraining.ejs @@ -3,9 +3,9 @@

    Aim Training

    -

    Click all five of the buttons as fast as possible when it appears on the screen.

    +

    Click all five of the buttons as fast as possible when it appears on the screen.

    -

    +

    diff --git a/views/cps.ejs b/views/cps.ejs index 3fffef6d6..38c2a60ab 100644 --- a/views/cps.ejs +++ b/views/cps.ejs @@ -4,9 +4,9 @@

    Clicks Per Second

    -

    Start the test below and after a 3 second countdown you'll have 10 seconds to perform as many clicks as possible!

    +

    Start the test below and after a 3 second countdown you'll have 10 seconds to perform as many clicks as possible!

    -

    +

    diff --git a/views/footer.ejs b/views/footer.ejs index 4673497f9..3a561d712 100644 --- a/views/footer.ejs +++ b/views/footer.ejs @@ -3,8 +3,8 @@
    -
    About
    -

    +

    ABOUT

    +

    To read more about the project, visit the README.md file. For our project we created a few different clicking tests. The first is clicks per second to see how many clicks the user can do in 10 seconds. The second is a reaction time test. There will be three buttons that pop up with only one of them being green. This score will be determined by @@ -14,7 +14,7 @@

    -
    Quick Links
    +

    Quick Links


    - - - - - - - - - - - - - - - - - -
    \ No newline at end of file diff --git a/views/header.ejs b/views/header.ejs index 7b3a9369c..b3cb812a9 100644 --- a/views/header.ejs +++ b/views/header.ejs @@ -20,25 +20,25 @@ <%if (user) {%>