Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions Typing-Speed-Test/ReadMe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
## What it does

A terminal-based typing speed test built with Python's `curses` library.
A random sentence is loaded from a text file and displayed on screen.
As the user types, each character turns green for correct and red for
incorrect in real time. Words per minute is calculated and displayed
live throughout the test. The user can play multiple rounds or exit
with ESC at any time.

## Setting Up This Project

### What is `requirements.txt`?

A `requirements.txt` file is a list of external packages your code needs to run, written in a plain text file. Instead of installing each package one by one, anyone can install everything in one command.

### Step 1 — Clone the repository

```bash
git clone https://github.com/Grow-with-Open-Source/Python-Projects.git
cd Python-Projects/typing-speed-test
```

### Step 2 — Create a virtual environment (recommended)

A virtual environment keeps this project's packages separate from everything else on your computer.

```bash
# Create it
python -m venv venv

# Activate it — Windows
venv\Scripts\activate

# Activate it — Mac/Linux
source venv/bin/activate
```

### Step 3 — Install the requirements

```bash
pip install -r requirements.txt
```

This reads `requirements.txt` and installs everything listed inside it automatically.

### Step 4 — Run the program

```bash
python typing_test.py
```

### A note on this project

The `curses` library comes built into Python automatically on Mac and Linux. On Windows it does not, so `requirements.txt` only installs `windows-curses` if you are on Windows — that is what the `; platform_system == "Windows"` condition means. Pip handles this automatically based on your operating system, so you do not need to do anything different.
1 change: 1 addition & 0 deletions Typing-Speed-Test/requirement.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
windows-curses; platform_system == "Windows"
4 changes: 4 additions & 0 deletions Typing-Speed-Test/text.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
The quick brown fox jumps over the lazy dog.
Python is an amazing programming language.
Practice makes perfect.
Coding is a skill built through consistency.
99 changes: 99 additions & 0 deletions Typing-Speed-Test/wpm_typing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import curses
from curses import wrapper
import random
import time


def get_sentence():
# ENTER THE RELATIVE PATH OF TEXT.TXT
with open("ENTER THE RELATIVE PATH OF TEXT.TXT", "r") as file:
sentences = file.readlines()

return random.choice(sentences).strip()


def show_intro(screen):
screen.clear()
screen.addstr("⚡ Typing Speed Challenge")
screen.addstr("\n\nPress any key to start...")
screen.refresh()
screen.getch()


def draw_interface(screen, sentence, typed_chars, speed):
screen.addstr(0, 0, sentence)
screen.addstr(2, 0, f"Words Per Minute: {speed}")

for position, letter in enumerate(typed_chars):
color = curses.color_pair(1)

if letter != sentence[position]:
color = curses.color_pair(2)

screen.addstr(0, position, letter, color)


def typing_game(screen):
phrase = get_sentence()
user_input = []

start = time.time()

screen.nodelay(True)

while True:
elapsed = max(time.time() - start, 1)

speed = round((len(user_input) / 5) / (elapsed / 60))

screen.clear()
draw_interface(screen, phrase, user_input, speed)
screen.refresh()

if "".join(user_input) == phrase:
screen.nodelay(False)
break

try:
pressed_key = screen.getkey()
except:
continue

if ord(pressed_key) == 27:
return False

if pressed_key in ("KEY_BACKSPACE", "\b", "\x7f"):
if user_input:
user_input.pop()

elif len(user_input) < len(phrase):
user_input.append(pressed_key)

return True


def run_program(screen):
curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK)
curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK)

show_intro(screen)

while True:
finished = typing_game(screen)

if not finished:
break

screen.addstr(
4,
0,
"Great job! Press any key for another round or ESC to quit."
)

key = screen.getkey()

if ord(key) == 27:
break


wrapper(run_program)
Loading