added colorschemes

This commit is contained in:
Arlo Filley 2022-12-01 14:41:14 +00:00
parent 7d918b0995
commit 445344061c
23 changed files with 1247 additions and 125 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ Cargo.lock
/NEA_Screenshots
.DS_Store
.gitignore
/.database

View File

@ -5,6 +5,7 @@ edition = "2021"
[dependencies]
rusqlite = "0.28.0"
rand = "0.8.5"
[dependencies.rocket]
version = "0.5.0-rc.2"

View File

@ -20,6 +20,8 @@ use rocket::{
json::Json
}
};
use rand::Rng;
use std::{fs, vec};
// Imports for sql, see sql.rs for more information
pub mod sql;
@ -124,6 +126,27 @@ fn leaderboard() -> Json<Vec<LeaderBoardTest>> {
Json(leaderboard)
}
/// Returns an array of words as Json
/// Accessible from http://url/api/get_test
#[get("/get_test")]
fn get_test() -> Json<Vec<String>> {
let mut word_vec: Vec<&str> = vec![];
let words = fs::read_to_string("wordlist.txt").unwrap();
for word in words.split('\n') {
word_vec.push(word.clone());
}
let mut return_list: Vec<String> = vec![];
let mut rng = rand::thread_rng();
for _i in 0..100 {
let hi: u32 = rng.gen_range(0..999);
return_list.push(word_vec[hi as usize].to_string())
}
Json(return_list.clone())
}
/// The main function which builds and launches the
/// webserver with all appropriate routes and fileservers
#[launch]
@ -136,7 +159,7 @@ fn rocket() -> Rocket<Build> {
.mount("/api", routes![
create_database, create_user,
post_test, login, get_user_tests,
leaderboard
leaderboard, get_test
])
// hosts the fileserver
.mount("/typing", FileServer::from(relative!("website")))

View File

@ -111,7 +111,6 @@ pub fn create_user(
username: &str,
password: &str
) -> Result<()> {
println!("{} {}",username, password);
let connection = get_connection();
connection.execute(

View File

@ -81,9 +81,6 @@ class API {
const userId = Number(user.userId);
let test_content = screenManager.screen.textbox.getTestContent();
console.log(test);
console.log(test_content);
let string = "";
let inaccurateLetters = 0;
for (let letter = 0; letter < test.length; letter++) {
@ -218,7 +215,11 @@ class API {
);
xhr.onload = () => {
this.login(username,password);
if (xhr.status === 500) {
alert("Sorry, looks like your username isn't unique");
} else {
this.login(username,password);
}
};
}
@ -255,9 +256,14 @@ class API {
user.userId = 0;
user.tests = [];
localStorage.clear();
this.getTest();
}
getUserTests() {
if (user.userId === 0) {
user.tests = undefined;
return;
}
let xhr = new XMLHttpRequest();
let userId = Number(user.userId);
xhr.open('GET', `${this.url}get_user_tests/${userId}/`);
@ -278,7 +284,7 @@ class API {
getTest() {
let xhr = new XMLHttpRequest();
xhr.open('GET', `https://random-word-api.herokuapp.com/word?number=100`);
xhr.open('GET', `${this.url}get_test/`);
xhr.send();
xhr.onload = () => {
const effectiveWidth = (windowWidth - 200) / 13;

View File

@ -24,5 +24,24 @@ class User {
this.tests;
this.lastTest;
this.nextTest = `satisfy powerful pleasant bells disastrous mean kited is gusted romantic past taste immolate productive leak close show crabby awake handsails finicky betray long-term incompetent wander show manage toys convey hop constitute number send like off ice aboard well-made vast vacuous tramp seed force divergent flower porter fire untidy soggy fetch`;
this.colorScheme = {
background: "#eeeee4",
text: "#000",
timerBar: "#50C5B7",
timerText: "#000",
testGood: "#0A0",
testBad: "#A00",
buttonBG: "#000",
buttonText: "#fff",
buttonBorder: "#000",
buttonHoverBG: "#0f0",
buttonHoverText: "#000",
buttonHoverBorder: "#000"
}
}
}

View File

@ -16,8 +16,8 @@
<link rel="manifest" href="./assets/favicon/site.webmanifest">
<!-- Main Script Files -->
<!-- <script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script> -->
<script src="./lib/p5.js"></script>
<script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.min.js"></script>
<!-- <script src="./lib/p5.js"></script> -->
<script src="./index.js" type="text/javascript"></script>
<!-- Element Script Files -->

View File

@ -29,8 +29,8 @@ function setup() {
api = new API();
screenManager = new ScreenManager();
screenManager.setScreen(new StartScreen());
user = new User();
screenManager.setScreen(new StartScreen());
api.login();
api.getTest();
@ -44,6 +44,7 @@ function setup() {
* sure that the correct screen is being drawn
*/
function draw() {
background(user.colorScheme.background);
screenManager.draw();
}

View File

@ -22,35 +22,16 @@ class AccountScreen {
new Textbox(
120, 500, 500, 100, 0, true, "#000", false,
"000", "#000", false
"#000", "#000", false, false, true
)
]
this.buttons = [
new Button(
100, 300, 500, 100, 0, true, "#000", false,
"#000", "#fff", "", true, "#000", "#000", "#fff"
),
new Button(
100, 450, 500, 100, 0, true, "#000", false,
"#000", "#fff", "", true, "#000", "#000", "#fff"
),
new Button(
900, 300, 100, 50, 0, true, "#000", false,
"#000", "#00ff00", "Login"
),
new Button(
900, 400, 100, 50, 0, true, "#000", false,
"#000", "#00ff00", "Sign up"
),
new Button(
900, 500, 100, 50, 0, true, "#000", false,
"#000", "#00ff00", "Logout"
),
new Button(100, 300, 500, 100, "", false, true, "#000", "#000", "#fff", "#000", "#000", "#fff"),
new Button(100, 450, 500, 100, "", false, true, "#000", "#000", "#fff", "#000", "#000", "#fff"),
new Button(900, 300, 100, 50, "Login"),
new Button(900, 400, 100, 50, "Sign up"),
new Button(900, 500, 100, 50, "Logout"),
]
this.menu = new Menu();
@ -64,9 +45,8 @@ class AccountScreen {
* appropriate elements
*/
draw() {
background("#eeeee4");
textSize(100);
fill("#000");
fill(user.colorScheme.text);
text("Account", 300, 100);
for (let i = 0; i < this.buttons.length; i++) {
this.buttons[i].draw();
@ -105,6 +85,8 @@ class AccountScreen {
screenManager.setScreen(new StartScreen());
}
this.menu.draw();
fill(user.colorScheme.text);
text(`Logged in as ${user.username}`, windowWidth-150, 15);
}
/**

View File

@ -17,10 +17,9 @@ class EndScreen {
}
draw() {
background("#eeeee4");
textSize(100);
textAlign(CENTER, CENTER);
fill(0);
fill(user.colorScheme.text);
text("Test Complete", 0, 0, windowWidth - 100, windowHeight / 6);
textSize(30);

View File

@ -15,25 +15,76 @@
class LeaderboardScreen {
constructor() {
this.menu = new Menu();
api.getLeaderBoard()
api.getLeaderBoard();
this.testButtons;
this.buttons = [
new Button(1150, 270, 240, 120, "up"),
new Button(1150, 390, 240, 120, "down"),
]
this.offset = 0;
}
draw() {
background("#eeeee4");
textSize(100);
textAlign(CENTER, CENTER);
fill("#000");
fill(user.colorScheme.text);
text("Leaderboard", 0, 100, windowWidth, 120);
this.menu.draw();
textSize(20);
fill("#000");
fill(user.colorScheme.text);
if (user.leaderboard != undefined) {
for (let i = 0; i < user.leaderboard.length; i++) {
text(`#${i+1}: ${user.leaderboard[i].username} : ${user.leaderboard[i].wpm}wpm`, 0, i*30+300, windowWidth, 30);
if (this.testButtons === undefined) {
this.createTestButtons();
}
}
fill("#000");
text(`Logged in as ${user.username}`, windowWidth-400, 15);
if (this.testButtons !== undefined && this.testButtons.length > 1) {
for (let i = 0; i < this.testButtons.length; i++) {
this.testButtons[i][0].draw()
this.testButtons[i][1].draw()
this.testButtons[i][2].draw()
}
if (this.buttons[0].isPressed()) {
if (this.offset > 0) {
this.offset--;
}
this.createTestButtons(this.offset);
} else if (this.buttons[1].isPressed()) {
if (this.offset < user.leaderboard.length - 13) {
this.offset++;
}
this.createTestButtons(this.offset);
}
for (let i = 0; i < this.buttons.length; i++) {
this.buttons[i].draw();
}
} else {
fill(user.colorScheme.text);
text("Looks Like There Isn't A Leaderboard", windowWidth / 2, 300);
}
fill(user.colorScheme.text);
text(`Logged in as ${user.username}`, windowWidth-150, 15);
}
createTestButtons(offset = 0) {
this.testButtons = [[
new Button(400, 270, 100, 30, "ranking"), // test # button
new Button(500, 270, 400, 30, "username"), // wpm button
new Button(900, 270, 240, 30, "words per minute"), // accuracy button
]];
let j = 300;
for (let i = 0 + offset; i < user.leaderboard.length && i <= 12+offset; i++) {
console.log(i);
this.testButtons.push([
new Button(400, j, 100, 30, `${i+1}`, true, true, "#000", "#000", "#fff"), // test # button
new Button(500, j, 400, 30, `${user.leaderboard[i].username}`, true, true, "#000", "#000", "#fff"), // accuracy button
new Button(900, j, 240, 30, `${user.leaderboard[i].wpm}`, true, true, "#000", "#000", "#fff"), // wpm button
])
j+=30;
}
}
}

View File

@ -54,7 +54,6 @@ class LoginScreen {
* appropriate elements
*/
draw() {
background("#eeeee4");
for (let i = 0; i < this.buttons.length; i++) {
this.buttons[i].draw();
}

View File

@ -20,72 +20,73 @@ class ProfileScreen {
api.getUserTests();
this.testButtons;
this.buttons = [
new Button(950, 270, 240, 120, 0, true, "#fff", true, "#000", "#000", "up"),
new Button(950, 390, 240, 120, 0, true, "#fff", true, "#000", "#000", "down"),
new Button(950, 270, 240, 120, "up"),
new Button(950, 390, 240, 120, "down"),
]
this.offset = 0;
}
draw() {
background("#eeeee4");
textSize(100);
textAlign(CENTER, CENTER);
fill("#000");
fill(user.colorScheme.text);
text("Profile", 0, 100, windowWidth, 120);
this.menu.draw();
textSize(20);
fill("#000");
fill(user.colorScheme.text);
if (user.tests != undefined) {
if (this.testButtons === undefined) {
this.createTestButtons();
}
}
for (let i = 0; i < this.buttons.length; i++) {
this.buttons[i].draw();
}
if (this.testButtons !== undefined) {
if (this.testButtons !== undefined && this.testButtons.length > 1) {
for (let i = 0; i < this.testButtons.length; i++) {
this.testButtons[i][0].draw()
this.testButtons[i][1].draw()
this.testButtons[i][2].draw()
this.testButtons[i][3].draw()
}
if (this.buttons[0].isPressed()) {
if (this.offset > 0) {
this.offset--;
}
this.createTestButtons(this.offset);
} else if (this.buttons[1].isPressed()) {
if (user.tests.length - 13 - this.offset > 0) {
this.offset++;
}
this.createTestButtons(this.offset);
}
for (let i = 0; i < this.buttons.length; i++) {
this.buttons[i].draw();
}
} else {
fill(user.colorScheme.text);
text("Looks Like You Don't have any tests :(", windowWidth / 2, 300);
}
if (this.buttons[0].isPressed()) {
if (user.tests.length < 13 + this.offset) {
this.offset--;
}
this.createTestButtons(this.offset);
} else if (this.buttons[1].isPressed()) {
if (user.tests.length - 13 - this.offset > 0) {
this.offset++;
}
this.createTestButtons(this.offset);
}
fill("#000");
fill(user.colorScheme.text);
text(`Logged in as ${user.username}`, windowWidth-150, 15);
}
createTestButtons(offset = 0) {
this.testButtons = [[
new Button(400, 270, 100, 30, 0, true, "#fff", true, "#000", "#000", "test #"), // test # button
new Button(500, 270, 100, 30, 0, true, "#fff", true, "#000", "#000", "wpm"), // wpm button
new Button(600, 270, 100, 30, 0, true, "#fff", true, "#000", "#000", "accuracy"), // accuracy button
new Button(700, 270, 240, 30, 0, true, "#fff", true, "#000", "#000", "characters typed")
new Button(400, 270, 100, 30, "test #"), // test # button
new Button(500, 270, 100, 30, "wpm"), // wpm button
new Button(600, 270, 100, 30, "accuracy"), // accuracy button
new Button(700, 270, 240, 30, "characters typed")
]];
let j = 300;
for (let i = user.tests.length-1-offset; i >= user.tests.length-13-offset; i--) {
for (let i = user.tests.length-1-offset; i >= user.tests.length-13-offset && i >= 0; i--) {
this.testButtons.push([
new Button(400, j, 100, 30, 0, true, "#000", true, "#000", "#fff", `${i}`), // test # button
new Button(600, j, 100, 30, 0, true, "#000", true, "#000", "#fff", `${user.tests[i].accuracy}`), // accuracy button
new Button(500, j, 100, 30, 0, true, "#000", true, "#000", "#fff", `${user.tests[i].wpm}`), // wpm button
new Button(700, j, 240, 30, 0, true, "#000", true, "#000", "#fff", `${user.tests[i].test_length}`)
new Button(400, j, 100, 30, `${i+1}`, true, true , "#000", "#000", "#fff"), // test # button
new Button(500, j, 100, 30, `${user.tests[i].accuracy}`, true, true , "#000", "#000", "#fff"), // accuracy button
new Button(600, j, 100, 30, `${user.tests[i].wpm}`, true, true , "#000", "#000", "#fff"), // wpm button
new Button(700, j, 240, 30, `${user.tests[i].test_length}`, true, true , "#000", "#000", "#fff")
])
j+=30;
}

View File

@ -14,13 +14,14 @@ class settingsScreen {
draw() {
textAlign(CENTER, CENTER);
background("#eeeee4");
textSize(100);
fill("#000");
fill(user.colorScheme.text);
text("Test Settings", 450, 100);
this.menu.draw();
this.timeMenu.draw();
fill("#000");
text(`Logged in as ${user.username}`, windowWidth-150, 15);
}
}

View File

@ -53,7 +53,6 @@ class SignUpScreen {
* appropriate elements
*/
draw() {
background("#eeeee4");
for (let i = 0; i < this.buttons.length; i++) {
this.buttons[i].draw();
}
@ -62,7 +61,7 @@ class SignUpScreen {
this.textboxes[i].draw();
}
fill("#000");
fill(user.colorScheme.text);
text("Username", 110, 175);
text("Password", 110, 325);

View File

@ -13,16 +13,15 @@ class StartScreen {
}
draw() {
background("#eeeee4");
textSize(100);
textAlign(CENTER, CENTER);
fill("#000");
fill(user.colorScheme.text);
text("Press enter to start test", 0, 0, windowWidth - 100, windowHeight - 100);
this.menu.draw();
fill("#000");
text(`Logged in as ${user.username}`, windowWidth-400, 15);
fill(user.colorScheme.text);
text(`Logged in as ${user.username}`, windowWidth-150, 15);
}
letterTyped(key) {

View File

@ -16,17 +16,22 @@ class TestScreen {
constructor() {
this.textbox = new Textbox(100,100,windowWidth - 200,windowHeight,0,true,"#000", false, "#000", "#000", true, true);
this.timer = new Timer(0,0,windowWidth,50,0,true,"#fff", true, "#000", "#666", user.time, true);
this.timer.start();
this.timerStarted = false;
}
draw() {
background("#eeeee4");
this.textbox.draw();
this.timer.draw();
this.timer.tick();
if (this.timerStarted) {
this.timer.tick();
}
}
letterTyped(key) {
this.textbox.letterTyped(key);
if (!this.timerStarted) {
this.timer.start();
this.timerStarted = true;
}
}
}

View File

@ -31,13 +31,20 @@ class Button {
*/
constructor(pX = 100, pY = 100,
pWidth = 200, pHeight = 30,
pLayer = 0, pVisible = true,
pTextColor = "#fff",
pBorder = false, pBorderColor = "#000",
pBackgroundColor = "#000",
pLabel = "Default Button",
pHoverBorder = true, pHoverBorderColor = "#000",
pHoverTextColor = "#000", pHoverBackgroundColor = "#00ff00"
pBorder = false,
pHoverBorder = true,
pTextColor = user.colorScheme.buttonText,
pBorderColor = user.colorScheme.buttonBorder,
pBackgroundColor = user.colorScheme.buttonBG,
pHoverTextColor = user.colorScheme.buttonHoverText,
pHoverBorderColor = user.colorScheme.buttonHoverBorder,
pHoverBackgroundColor = user.colorScheme.buttonHoverBG,
pLayer = 0, pVisible = true,
) {
this.x = pX;
this.y = pY;

View File

@ -13,11 +13,11 @@
class Menu {
constructor() {
this.buttons = [
new Button(0, 0, 100, 30, 0, true, "#fff", false, "#000", "#000", "Account"),
new Button(101, 0, 130, 30, 0, true, "#fff", false, "#000", "#000", "Test Data"),
new Button(232, 0, 140, 30, 0, true, "#fff", false, "#000", "#000", "Start Test"),
new Button(373, 0, 140, 30, 0, true, "#fff", false, "#000", "#000", "Leaderboard"),
new Button(514, 0, 180, 30, 0, true, "#fff", false, "#000", "#000", "Test Settings")
new Button(0, 0, 100, 30, "Account"),
new Button(101, 0, 130, 30, "Test Data"),
new Button(232, 0, 140, 30, "Start Test"),
new Button(373, 0, 140, 30, "Leaderboard"),
new Button(514, 0, 180, 30, "Test Settings")
]
}

View File

@ -32,10 +32,11 @@ class Textbox {
pX, pY,
pWidth, pHeight,
pLayer, pVisible,
pTextColor,
pTextColor = user.colorScheme.text,
pBorder, pBorderColor,
pBackgroundColor,
pLine, pIsTest
pLine, pIsTest,
pIsPassword = false
) {
this.x = pX;
this.y = pY;
@ -52,7 +53,9 @@ class Textbox {
this.allowedLetters = [
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm','n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '\'', '"', ',', '.', ' '
'x', 'y', 'z',
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
'\'', '"', ',', '.', ' ', '!', '@', '$', '%', '^', '&', '*', '(', ')',
]
this.line = pLine;
@ -65,6 +68,11 @@ class Textbox {
} else {
this.words = "";
}
this.isPassword = pIsPassword;
this.goodColor = user.colorScheme.testGood;
this.badColor = user.colorScheme.testBad;
}
getX() {
@ -274,12 +282,12 @@ class Textbox {
for (let x = 0; x < this.testContent[this.currentLine].length; x++) {
if (x < this.words[this.currentLine].length) {
if (this.words[this.currentLine][x] === this.testContent[this.currentLine][x]) {
fill("#00AA00");
fill(this.goodColor);
} else {
fill("#AA0000");
fill(this.badColor);
}
} else {
fill("#000");
fill(this.textColor);
}
text(this.testContent[this.currentLine][x], i, j);
i += 13;
@ -288,12 +296,32 @@ class Textbox {
i = this.x;
j += 30;
fill("#000");
fill(this.textColor);
for (let x = this.currentLine + 1; x < this.testContent.length; x++) {
text(this.testContent[x], i, j);
j += 30;
}
} else if (this.isPassword) {
// these variables allow me to use the values of x and y while updating them
let i = this.x;
let j = this.y;
// currently this loop just prints out every letter in the array, including any enter characters
for (let x = 0; x < this.letters.length; x++) {
if (i > this.x + this.width) i = this.x, j += 30;
if (this.letters[x] === "Enter") {
i = this.x, j+= 30;
} else {
let char = "-";
text(char, i, j);
i += 13
}
if (this.letters.length > 0 && x == this.letters.length-1 && this.line) {
fill(this.textColor)
rect(i, j-15, 1, 30)
}
}
} else {
// these variables allow me to use the values of x and y while updating them
let i = this.x;
@ -309,7 +337,7 @@ class Textbox {
i += 13
}
if (this.letters.length > 0 && x == this.letters.length-1 && this.line) {
fill("black")
fill(this.textColor)
rect(i, j-15, 1, 30)
}
}

View File

@ -15,10 +15,10 @@
class TimeMenu {
constructor() {
this.buttons = [
new Button(100, 230, 100, 30, 0, true, "#fff", false, "#000", "#000", "15s"),
new Button(100, 260, 100, 30, 0, true, "#fff", false, "#000", "#000", "30s"),
new Button(100, 290, 100, 30, 0, true, "#fff", false, "#000", "#000", "45s"),
new Button(100, 320, 100, 30, 0, true, "#fff", false, "#000", "#000", "60s"),
new Button(100, 230, 100, 30, "15s"),
new Button(100, 260, 100, 30, "30s"),
new Button(100, 290, 100, 30, "45s"),
new Button(100, 320, 100, 30, "60s"),
];
this.topButton = this.buttons[0];
@ -33,19 +33,19 @@ class TimeMenu {
if (this.buttons[0].isPressed() && user.time != 15) {
user.time = 15;
this.topButton = new Button(100, 230, 100, 30, 0, true, "#fff", false, "#000", "#000", "15s");
this.topButton = new Button(100, 230, 100, 30, "15s");
this.dropdown = false;
} else if (this.buttons[1].isPressed()) {
user.time = 30;
this.topButton = new Button(100, 230, 100, 30, 0, true, "#fff", false, "#000", "#000", "30s");
this.topButton = new Button(100, 230, 100, 30, "30s");
this.dropdown = false;
} else if (this.buttons[2].isPressed()) {
user.time = 45;
this.topButton = new Button(100, 230, 100, 30, 0, true, "#fff", false, "#000", "#000", "45s");
this.topButton = new Button(100, 230, 100, 30, "45s");
this.dropdown = false;
} else if (this.buttons[3].isPressed()) {
user.time = 60;
this.topButton = new Button(100, 230, 100, 30, 0, true, "#fff", false, "#000", "#000", "60s");
this.topButton = new Button(100, 230, 100, 30, "60s");
this.dropdown = false;
}
} else {

View File

@ -148,7 +148,7 @@ class Timer {
* This method is called to start the timer
*/
start() {
this.startTime = frameCount;
this.startTime = millis();
// framecount is a special p5 value that counts the number of frames that have passed
// I am using the amount of frames passed to calculate the time, assuming that the website is running at 60q frames
// per second
@ -160,8 +160,10 @@ class Timer {
* it keeps track of the amount of time passed
*/
tick() {
this.timeElapsed = frameCount - this.startTime;
if (this.timeElapsed == this.time * 60) this.end();
this.timeElapsed = (millis() - this.startTime) / 1000;
if (this.timeElapsed >= this.time) {
this.end();
};
}
/**
@ -198,14 +200,13 @@ class Timer {
// draws a bar that move across the screen to show the time left
if (this.bar) {
fill(this.backgroundColor);
rect(this.y, this.x, windowWidth - windowWidth / (this.time * 60) * this.timeElapsed , this.height);
fill(user.colorScheme.timerBar);
rect(this.y, this.x, windowWidth - windowWidth * (this.timeElapsed / this.time), this.height);
}
// draws the text in the corner of the screen
noStroke();
fill(this.textColor);
let time = (this.time * 60 - this.timeElapsed) / 60
text(Math.ceil(time), this.x + this.width / 6, this.y + this.height / 2)
fill(user.colorScheme.timerText);
text(Math.ceil(this.time - this.timeElapsed), this.x + this.width / 6, this.y + this.height / 2)
}
}

1000
wordlist.txt Normal file

File diff suppressed because it is too large Load Diff