Skip to content

Commit

Permalink
Merge pull request #73 from Capstone-Projects-2024-Spring/reizas-dev
Browse files Browse the repository at this point in the history
Added back changes from previous PR
  • Loading branch information
Dem0nMaxwell authored May 1, 2024
2 parents f28298b + cac8248 commit 34f7ab7
Show file tree
Hide file tree
Showing 8 changed files with 205 additions and 88 deletions.
157 changes: 107 additions & 50 deletions app.py

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion easy_words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2750,7 +2750,6 @@ milan
mild
mile
miles
milfs
milk
mill
miller
Expand Down
1 change: 0 additions & 1 deletion hard_words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1265,7 +1265,6 @@ metallica
metropolitan
microwave
migration
milfhunter
military
millennium
million
Expand Down
2 changes: 1 addition & 1 deletion static/js/content/Dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function Dashboard({ userSession }) {
{/* Winnings & Losses */}
<section className="dashItem userOverview">
<p className="center flexEven">
Total Playing Time: {userData.totalTime} minutes
Total Playing Time: {Math.floor(userData.totalTime)} minutes
</p>
<p className="center flexEven">
Accuracy: {userData.accuracy}%
Expand Down
60 changes: 43 additions & 17 deletions static/js/reusable/RobotOpponent.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
function RobotOpponent() {
const date = new Date();
let text = "Choose difficulty and click to start.";
let words = text.split(" ");
let avgEasyWordTxtLen;
Expand Down Expand Up @@ -123,22 +124,26 @@ function RobotOpponent() {
}
}

async function fetchRandomWordList(difficulty,msPerChar) {
let newText = "";
function getNumWords(difficulty,msPerChar){
let avgWordLen;
switch(difficulty){
case "Easy":
avgWordLen=avgEasyWordTxtLen;
break;
case "Medium":
avgWordLen=avgMedWordTxtLen;
break;
case "Hard":
avgWordLen=avgHardWordTxtLen;
break;
}
return Math.floor((60/(msPerChar*avgWordLen/1000)));
}

async function fetchRandomWordList(difficulty,numWords) {
let newText = "";
try {
switch(difficulty){
case "Easy":
avgWordLen=avgEasyWordTxtLen;
break;
case "Medium":
avgWordLen=avgMedWordTxtLen;
break;
case "Hard":
avgWordLen=avgHardWordTxtLen;
break;
}
const response = await fetch('/generate_text/?difficulty='+difficulty+'&form=words&amount='+Math.floor((60/(msPerChar*avgWordLen/1000))));
const response = await fetch('/generate_text/?difficulty='+difficulty+'&form=words&amount='+numWords);
if (!response.ok) {
throw new Error('Network response was not ok');
}
Expand All @@ -151,6 +156,24 @@ function RobotOpponent() {
}
}

async function postUserMetrics(wpm, accuracy, elapsedTime){
try{
const postData = {"wpm":wpm,"accuracy":accuracy,"mode":"Robot Opponent","elapsedTime":elapsedTime/60,"date":date.toISOString()}
const response = await fetch('/update_db',{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(postData)});
if(!response.ok){
throw new Error('Network response was not ok');
}
}
catch(error){
console.error('There was a problem with the fetch operation:', error);
}
}

function startTimer() {
currentWordIndex = 0; //initializes value for play again
currentCharIndex = 0;
Expand All @@ -168,10 +191,11 @@ function RobotOpponent() {

function startGame(){
var difficulty = getDifficulty();
var robotMsPerChar = getRobotMsPerChar(difficulty)
fetchRandomWordList(difficulty,robotMsPerChar);
robotType(robotMsPerChar);
var robotMsPerChar = getRobotMsPerChar(difficulty);
var numWords = getNumWords(difficulty,robotMsPerChar);
fetchRandomWordList(difficulty,numWords);
startTimer();
robotType(robotMsPerChar);
}

function getDifficulty(){
Expand Down Expand Up @@ -278,6 +302,7 @@ function RobotOpponent() {
document.getElementById("result").innerHTML = `Congratulations! You completed the game in ${elapsedTime.toFixed(2)} seconds. Your speed: ${wordsPerMinute} WPM. Accuracy: ${accuracy.toFixed(2)}%`;
document.getElementById("input-box").value = "";
document.getElementById("input-box").disabled = true;
postUserMetrics(wordsPerMinute,accuracy,elapsedTime);
}


Expand All @@ -289,6 +314,7 @@ function RobotOpponent() {
document.getElementById("result").innerHTML = `Sadly, Robot finished the game first in ${elapsedTime.toFixed(2)} seconds. Robot speed: ${wordsPerMinute} WPM.`;
document.getElementById("input-box").value = "";
document.getElementById("input-box").disabled = true;
postUserMetrics(Math.round((currentCharIndex/5 / elapsedTime) * 60),(correctCharsTyped / totalCharsTyped) * 100, elapsedTime);
}


Expand Down
29 changes: 27 additions & 2 deletions static/js/reusable/SinglePlayer.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
function ThrillTyperGame() {
const date = new Date();
let text = "Click start button to start!";
let words = text.split(" ");

Expand All @@ -8,6 +9,8 @@ function ThrillTyperGame() {
let startTime;
//let timerInterval;
let userInputCorrectText = "";
let correctCharsTyped = 0; // Track correct characters typed
let totalCharsTyped = 0; // Track total characters typed

const intervalRef = React.useRef(null);

Expand Down Expand Up @@ -42,6 +45,24 @@ function ThrillTyperGame() {
return newText;
}

async function postUserMetrics(wpm, accuracy, elapsedTime){
try{
const postData = {"wpm":wpm,"accuracy":accuracy,"mode":"Single Player","elapsedTime":elapsedTime/60,"date":date.toISOString()}
const response = await fetch('/update_db',{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(postData)});
if(!response.ok){
throw new Error('Network response was not ok');
}
}
catch(error){
console.error('There was a problem with the fetch operation:', error);
}
}

//update text color as user types text
//green text if user typed correctly
//red background text if user typed incorrectly
Expand Down Expand Up @@ -159,7 +180,9 @@ function ThrillTyperGame() {

if (userInputLastChar == text[currentCharIndex]) { //works but logic is bad
currentCharIndex++;
correctCharsTyped++;
}
totalCharsTyped++;

//submit input if last letter is typed
if (currentCharIndex >= text.length) {
Expand All @@ -172,10 +195,12 @@ function ThrillTyperGame() {
stopTimerInterval();
const endTime = new Date().getTime();
const elapsedTime = (endTime - startTime) / 1000;
const wordsPerMinute = Math.round((text.split(" ").length / elapsedTime) * 60);
document.getElementById("result").innerHTML = `Congratulations! You completed the game in ${elapsedTime.toFixed(2)} seconds. Your speed: ${wordsPerMinute} WPM.`;
const wordsPerMinute = Math.round((correctCharsTyped / 5 / elapsedTime) * 60);
const accuracy = (correctCharsTyped / totalCharsTyped) * 100;
document.getElementById("result").innerHTML = `Congratulations! You completed the game in ${elapsedTime.toFixed(2)} seconds. Your speed: ${wordsPerMinute} WPM. Your accuracy: ${accuracy.toFixed(2)}%`;
document.getElementById("input-box").value = "";
document.getElementById("input-box").disabled = true;
postUserMetrics(wordsPerMinute,accuracy,elapsedTime);
}

function stopTimer(){
Expand Down
41 changes: 27 additions & 14 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ def test_google_login(client):
def test_google_callback(monkeypatch, client):
"""
Test: That returned redirect requests are handled successfully, the passed in information is passed successfully and ultimately a response that indicates redirection to the home page is returned
Input monkeypatch : facilitates Google OAuth through mock token
Result: True if the returned response indicates a redirection to the home page
"""
mock_token = {
Expand Down Expand Up @@ -121,26 +122,38 @@ def test_logout(client):
assert response.request.path == "/"


def test_generate_text_sentences(client):
"""Test that the text generation endpoint is operational."""
# Make a GET request to the endpoint with expected parameters
response = client.get(
"/generate_text/?difficulty=easy&form=sentences&amount=6")

# Assert that the HTTP status code is 200 (OK), indicating success
assert response.status_code == 200, "Expected status code 200, but got {}".format(
response.status_code)


def test_generate_text_word_list(client):
"""Test generating text with word_list form."""
"""
Test: That the text generation endpoint generates text with word_list form
Result: True if the endpoint responds with success and generates the right amount of words separated by spaces
"""
response = client.get(
"/generate_text/?difficulty=hard&form=words&amount=10")
assert response.status_code == 200
content = response.data.decode('utf-8')
word_list = content.split(' ')
assert len(word_list) == 10

def test_generate_dynamic(client):
"""
Test: That dynamic text generation endpoint can take in WPM and accuracy and generate words using that data
Result: True if the endpoint responds with successful status code and responds with enough words to fill two lines
"""
response = client.get("/generate_dynamic/?wpm=53&accuracy=70")
assert response.status_code==200
word_lst = response.data.decode('utf-8').split(" ")
assert len(word_lst)>=10

def test_matchmaking(client):
"""
Test: That the matchmaking endpoint is responsive and can match players for a game
Result: True if the response status code indcates success and if the message indicates success or inability to find a match
"""
response = client.get("/matchmaking")
assert response.status_code==200
response_data = response.data.decode('utf-8')
assert response_data=="Matching successful." or response_data=="Match could not be found."

def test_socketio_connection(client):
"""Test SocketIO connection."""
sok = App.socketio
Expand Down Expand Up @@ -485,9 +498,9 @@ def test_get_txt_lst(self):
"""
assert type(Text_Generator.get_txt_list("words.txt")) == list

def test_get_average_word_len(self):
def test_get_average_txt_len(self):
"""
Test: Ensure that the average length of words in a list is calculated correctly
Test: Ensure that the average length of txt in a list is calculated correctly
Result: True if the average length is calculated correctly
"""
assert Text_Generator.get_avg_txt_len(
Expand Down
2 changes: 0 additions & 2 deletions words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5251,8 +5251,6 @@ mild
mile
mileage
miles
milfhunter
milfs
military
milk
mill
Expand Down

0 comments on commit 34f7ab7

Please sign in to comment.