Skip to content

Commit

Permalink
Merge pull request #94 from Capstone-Projects-2024-Spring/reizas-dev2
Browse files Browse the repository at this point in the history
Edited README and fixed some testing
  • Loading branch information
TU-Wenjie-Gao committed May 2, 2024
2 parents f47124d + 9a88b8a commit 5ffe22d
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 33 deletions.
39 changes: 33 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<div align="center">

# Project Name
ThrillTyper
[![Report Issue on Jira](https://img.shields.io/badge/Report%20Issues-Jira-0052CC?style=flat&logo=jira-software)](https://temple-cis-projects-in-cs.atlassian.net/jira/software/c/projects/DT/issues)
[![Deploy Docs](https://github.com/ApplebaumIan/tu-cis-4398-docs-template/actions/workflows/deploy.yml/badge.svg)](https://github.com/ApplebaumIan/tu-cis-4398-docs-template/actions/workflows/deploy.yml)
[![Documentation Website Link](https://img.shields.io/badge/-Documentation%20Website-brightgreen)](https://applebaumian.github.io/tu-cis-4398-docs-template/)
Expand All @@ -11,27 +12,46 @@

## Keywords

Section #, as well as any words that quickly give your peers insights into the application like programming language, development platform, type of application, etc.
Section 4
Python
React
Type Racing
Web Application

## Project Abstract

This document proposes a novel application of a text message (SMS or Email) read-out and hands-free call interacted between an Android Smartphone and an infotainment platform (headunit) in a car environment. When a phone receives an SMS or Email, the text message is transferred from the phone to the headunit through a Bluetooth connection. On the headunit, user can control which and when the received SMS or E-mail to be read out through the in-vehicle audio system. The user may press one button on the headunit to activate the hands-free feature to call back the SMS sender.
Welcome to the exciting world of ThrillTyper – a cutting-edge typing racer game that's here to make typing fun and competitive. This game is an online web application that offers various single player modes including a robot opponent mode, custom mode, and dynamic race mode, private online multiplayer, and public online multiplayer. In multiplayer each race is composed of up to ten racers, and in online multiplayer the host of the game shall have the option between two to ten competitors. Metrics for each race shall be logged to each user’s account including words-per-minute (wpm), time, and accuracy, however, if the player has no account they shall be playing as a guest with no saved data. Participants shall be able to register accounts, join typing races, and compete in real-time against each other. The game shall feature a user-friendly interface built with JavaScript, a backend powered by Flask, and WebSocket technology for seamless real-time communication. The game shall include user authentication, race creation, and a dynamic leaderboard to showcase the fastest typists.

## High Level Requirement

Describe the requirements – i.e., what the product does and how it does it from a user point of view – at a high level.
ThrillTyper is the ultimate typing challenge, offering players an array of modes to engage with. In robot opponent mode, users will see the robot’s progress typing against them and their own metrics. Custom mode will allows users to input texts, select genres, and select between words and sentences. Dynamic race mode will analyze the user’s last few sentences typed and their metrics to generate a few new lines based on that data and what AI deems best to generate. While online multiplayer provides the thrill of real-time competition with two to ten players hosted by a game master. Key metrics, such as words-per-minute (wpm), time, and accuracy, shall be shown in game and meticulously logged for each user, creating a personalized experience. Whether you're a registered user tracking your progress or a guest enjoying the rush, ThrillTyper ensures an exciting typing adventure for everyone.

## Conceptual Design

Describe the initial design concept: Hardware/software architecture, programming language, operating system, etc.
The initial design concept envisions a software architecture where the frontend, developed using JavaScript, provides a user-friendly interface for interaction. The backend is powered by Flask, a framework written in Python, serving as a robust foundation for text generation, multiplayer connection handling and user data handling. Real-time communication is facilitated through WebSocket technology, ensuring dynamic multiplayer experience. The software stack is designed for compatibility with standard web browsers, making it accessible across various operating systems. The development process adheres to industry best practices, utilizing Git for version control and collaborative development.

## Background

The background will contain a more detailed description of the product and a comparison to existing similar projects/products. A literature search should be conducted and the results listed. Proper citation of sources is required. If there are similar open-source products, you should state whether existing source will be used and to what extent. If there are similar closed-source/proprietary products, you should state how the proposed product will be similar and different.
ThrillTyper seeks to distinguish itself through the incorporation of real-time multiplayer capabilities, a dynamic leaderboard, and an emphasis on performance metrics tracking. Proprietary products like "TypeRacer" and "Nitro Type" were also scrutinized for their user engagement features and various capabilities. In crafting ThrillTyper, the aim is not only to offer a unique and thrilling game experience but also to strategically position the product by leveraging successful elements observed in existing projects while introducing innovative differentiators like Robot Opponent Mode and Dynamic Text Generation that cater to a broader user base.

## Required Resources

Discuss what you need to develop this project. This includes background information you will need to acquire, hardware resources, and software resources. If these are not part of the standard Computer Science Department lab resources, these must be identified early and discussed with the instructor.
This is a software-dominant project with zero outside hardware requirements. The Visual Studio Code IDE shall be the biggest requirement to program in JavaScript and Python. Experience with Python Flask and JavaScript shall be helpful. A computer or server provider shall be needed to act as a server to host the application.

## Implemented Features

Single Player - basic timed gameplay
Robot Opponent Mode - competing against a simulated opponent with difficulties of either easy, medium, or hard
Custom Mode - allows user to choose genre for words to type or input a blurb of their own to type
User Systems - accounts, logging in, dashboard, and leaderboard
Dynamic Mode - generates an easy blurb for the user to type initially and based on the WPM the users has for that it generates a new blurb, and this goes on until time runs out

## Known Bugs

### Release 1.0

1. Dynamic Text Generation does not allow the user to advance if they type two spaces in a row after finishing their last blurb
2. Multiplayer does not synchronize gameplay so that the match ends when one player has finished the race

## Collaborators

Expand Down Expand Up @@ -87,6 +107,13 @@ Discuss what you need to develop this project. This includes background informat
<sub><b>Allen Abraham</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/icycoldveins">
<img src="https://avatars.githubusercontent.com/u/81425589?v=4" width="100;" alt="tuk04440"/>
<br />
<sub><b>Allen Abraham</b></sub>
</a>
</td>
</tr>
</table>

Expand Down
10 changes: 5 additions & 5 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def test_valid_login(client):
response = client.post(
"/authentication", data={"username": username, "password": password})
print(response.status_code)
assert "/" == response.location
assert "/#/menu" == response.location


def test_continue_as_guest(client):
Expand Down Expand Up @@ -141,10 +141,10 @@ def test_generate_text_word_list(client):

def test_generate_dynamic(client):
"""
Test: That dynamic text generation endpoint can take in WPM and accuracy and generate words using that data
Test: That text generation endpoint can take in WPM 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")
response = client.get("/generate_text/?wpm=53")
assert response.status_code==200
word_lst = response.data.decode('utf-8').split(" ")
assert len(word_lst)>=10
Expand Down Expand Up @@ -543,7 +543,7 @@ def test_generate_text(self):
Test: Ensure that text is generate successfully given valid input
Result: True when: if given valid input, the invalid argument message is not returned, or if invalid input is given, then the invalid argument message is returned
"""
assert "Invalid arguments or missing arguments." not in Text_Generator.generate_text(
assert "An error occurred, check the file name and the parameters." not in Text_Generator.generate_text(
"hard", "words", 20)
assert "Invalid arguments or missing arguments." in Text_Generator.generate_text(
assert "An error occurred, check the file name and the parameters." in Text_Generator.generate_text(
"what", "no way buddy", 3)
38 changes: 16 additions & 22 deletions text_generator.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
from random import randint
LEN_OF_LONGEST_WORD = 22

LEFT_SIDE = "qwert|asdfg|zxcv"
LEFT_ROW2_START = LEFT_SIDE.find('|')
LEFT_ROW3_START = LEFT_SIDE.find('|', LEFT_ROW2_START+1)
RIGHT_SIDE = "poiuy|lkjh|mnb"
RIGHT_ROW2_START = RIGHT_SIDE.find('|')
RIGHT_ROW3_START = RIGHT_SIDE.find('|', RIGHT_ROW2_START+1)
PINKIE_CHARS = "qaz"

class Text_Generator:
"""
Responsible for generating text for a game to use and also separating words into different difficulties (the latter is done outside of run time)
"""
LEFT_SIDE = "qwert|asdfg|zxcv"
LEFT_ROW2_START = LEFT_SIDE.find('|')
LEFT_ROW3_START = LEFT_SIDE.find('|', LEFT_ROW2_START+1)
RIGHT_SIDE = "poiuy|lkjh|mnb"
RIGHT_ROW2_START = RIGHT_SIDE.find('|')
RIGHT_ROW3_START = RIGHT_SIDE.find('|', RIGHT_ROW2_START+1)
PINKIE_CHARS = "qaz"

def get_txt_list(file) -> list[str]:
"""
Expand Down Expand Up @@ -41,17 +40,17 @@ def score_word_typing_difficulty(self, word) -> int:
while i < len(word):
has_next_char = i+1 < len(word)
# checking edge chars
if word[i] in self.PINKIE_CHARS:
if word[i] in PINKIE_CHARS:
score += 0.25
if has_next_char and word[i+1] == word[i]:
i += 1
# checking direct verticals and consecutive side switches
has_next_char = i+1 < len(word)
if has_next_char:
curr_word_left_ind = self.LEFT_SIDE.find(word[i])
next_word_left_ind = self.LEFT_SIDE.find(word[i+1])
curr_word_right_ind = self.RIGHT_SIDE.find(word[i])
next_word_right_ind = self.RIGHT_SIDE.find(word[i+1])
curr_word_left_ind = LEFT_SIDE.find(word[i])
next_word_left_ind = LEFT_SIDE.find(word[i+1])
curr_word_right_ind = RIGHT_SIDE.find(word[i])
next_word_right_ind = RIGHT_SIDE.find(word[i+1])
if (curr_word_left_ind == -1 and next_word_left_ind != -1) or (curr_word_left_ind != -1 and next_word_left_ind == -1):
side_switches += 1
else:
Expand Down Expand Up @@ -79,11 +78,11 @@ def is_direct_vertical(self, curr_char_keyboard_pos, nxt_char_keyboard_pos, is_l
"""
if (curr_char_keyboard_pos != -1 and nxt_char_keyboard_pos != -1):
# standardize the rows
row2_start = self.RIGHT_ROW2_START
row3_start = self.RIGHT_ROW3_START
row2_start = RIGHT_ROW2_START
row3_start = RIGHT_ROW3_START
if is_left:
row2_start = self.LEFT_ROW2_START
row3_start = self.LEFT_ROW3_START
row2_start = LEFT_ROW2_START
row3_start = LEFT_ROW3_START
if curr_char_keyboard_pos > row3_start:
curr_char_keyboard_pos -= row3_start
elif curr_char_keyboard_pos > row2_start:
Expand Down Expand Up @@ -162,8 +161,3 @@ def generate_text(difficulty: str, form: str, amount: int, genre: str = None):
except Exception as e:
print(f"Error: {e}")
return "An error occurred, check the file name and the parameters."


if __name__ == "__main__":
tg = Text_Generator()
tg.sort_words_by_difficulty(tg.get_txt_list("words.txt"))

0 comments on commit 5ffe22d

Please sign in to comment.