0% found this document useful (0 votes)
5 views8 pages

Python (Multiplication

The document describes a console application called 'Multiplication Mastery' designed for practicing multiplication skills. It features a tables generator, practice quizzes with varying difficulty levels, score tracking, and the ability to save session results. The application is intended for educational purposes only.

Uploaded by

Kashmala Durrani
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views8 pages

Python (Multiplication

The document describes a console application called 'Multiplication Mastery' designed for practicing multiplication skills. It features a tables generator, practice quizzes with varying difficulty levels, score tracking, and the ability to save session results. The application is intended for educational purposes only.

Uploaded by

Kashmala Durrani
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

"""

Multiplication Mastery (Console App)


-----------------------------------
A full-featured multiplication practice tool:
- Tables generator
- Practice quiz (untimed or timed)
- Difficulty levels
- Score + accuracy tracking
- Mistake review
- Save session results to a file

Educational purpose only.


"""

from __future__ import annotations

import random
import time
from dataclasses import dataclass, asdict
from typing import List, Tuple, Optional
from pathlib import Path
import json

# -----------------------------
# Data Models
# -----------------------------

@dataclass
class Question:
a: int
b: int
user_answer: Optional[int] = None
correct_answer: Optional[int] = None
is_correct: Optional[bool] = None
time_taken_s: Optional[float] = None

def finalize(self, user_answer: int, time_taken_s: float) -> None:


self.user_answer = user_answer
self.correct_answer = self.a * self.b
self.is_correct = (user_answer == self.correct_answer)
self.time_taken_s = time_taken_s

@dataclass
class SessionResult:
started_at: float
ended_at: float
mode: str
difficulty: str
num_questions: int
correct: int
wrong: int
accuracy_percent: float
average_time_s: float
questions: List[Question]

# -----------------------------
# Utilities
# -----------------------------

def clear_screen() -> None:


# Simple clear (portable-ish)
print("\n" * 80)

def read_int(prompt: str, *, min_val: int | None = None, max_val: int | None = None) -> int:
while True:
raw = input(prompt).strip()
try:
value = int(raw)
except ValueError:
print("Please enter a valid integer.")
continue

if min_val is not None and value < min_val:


print(f"Value must be >= {min_val}.")
continue
if max_val is not None and value > max_val:
print(f"Value must be <= {max_val}.")
continue
return value

def read_choice(prompt: str, choices: List[str]) -> str:


choice_map = {[Link](): c for c in choices}
while True:
raw = input(prompt).strip().lower()
if raw in choice_map:
return choice_map[raw]
print(f"Choose one of: {', '.join(choices)}")

def format_seconds(s: float) -> str:


if s < 60:
return f"{s:.2f}s"
m = int(s // 60)
r = s % 60
return f"{m}m {r:.2f}s"

# -----------------------------
# Multiplication Tables
# -----------------------------

def show_table(n: int, upto: int = 12) -> None:


print(f"\nMultiplication Table for {n} (1 to {upto})")
print("-" * 34)
for i in range(1, upto + 1):
print(f"{n:>2} × {i:>2} = {n * i:>4}")
print("-" * 34)

def show_tables_range(start: int, end: int, upto: int = 12) -> None:
for n in range(start, end + 1):
show_table(n, upto=upto)

# -----------------------------
# Quiz Generation
# -----------------------------

def difficulty_ranges(difficulty: str) -> Tuple[Tuple[int, int], Tuple[int, int]]:


"""
Returns (range for a), (range for b).
"""
if difficulty == "easy":
return (0, 10), (0, 10)
if difficulty == "medium":
return (2, 15), (2, 15)
if difficulty == "hard":
return (5, 25), (5, 25)
if difficulty == "insane":
return (10, 50), (10, 50)
# fallback
return (0, 12), (0, 12)

def make_questions(num_questions: int, difficulty: str, *, avoid_repeats: bool = True) ->


List[Question]:
(a_min, a_max), (b_min, b_max) = difficulty_ranges(difficulty)

generated: List[Question] = []
seen: set[Tuple[int, int]] = set()

while len(generated) < num_questions:


a = [Link](a_min, a_max)
b = [Link](b_min, b_max)

key = (a, b)
if avoid_repeats and key in seen:
continue
[Link](key)

[Link](Question(a=a, b=b))
return generated

# -----------------------------
# Quiz Engine
# -----------------------------

def run_quiz(
*,
difficulty: str,
num_questions: int,
timed: bool,
time_limit_s: int,
) -> SessionResult:
mode = "timed" if timed else "practice"
started = [Link]()

questions = make_questions(num_questions, difficulty, avoid_repeats=True)

correct = 0
wrong = 0
total_time = 0.0

clear_screen()
print("Multiplication Quiz")
print("===================")
print(f"Mode: {mode} | Difficulty: {difficulty} | Questions: {num_questions}")
if timed:
print(f"Time limit per question: {time_limit_s}s")
print()

for idx, q in enumerate(questions, start=1):


print(f"Q{idx}/{num_questions}: {q.a} × {q.b} = ?")

t0 = [Link]()
user_answer: Optional[int] = None
# Basic timed input (soft timing): we measure how long they took.
# Note: true "interrupt input after X seconds" needs OS-specific tricks.
raw = input("Your answer: ").strip()
t1 = [Link]()

elapsed = t1 - t0
total_time += elapsed

if raw == "":
user_answer = 0
else:
try:
user_answer = int(raw)
except ValueError:
user_answer = 0

[Link](user_answer=user_answer, time_taken_s=elapsed)

# Evaluate timing (soft enforcement)

⏱️
if timed and elapsed > time_limit_s:
print(f" Too slow! You took {format_seconds(elapsed)} (limit {time_limit_s}s).")
if q.is_correct:
# even if correct, in timed mode mark as wrong if exceeded
q.is_correct = False
wrong += 1
print(f"Correct answer was: {q.a * q.b}\n")
continue


if q.is_correct:
print(" Correct!\n")
correct += 1


else:
print(f" Wrong. Correct answer: {q.a * q.b}\n")
wrong += 1

ended = [Link]()

accuracy = (correct / num_questions) * 100.0 if num_questions else 0.0


avg_time = total_time / num_questions if num_questions else 0.0

return SessionResult(
started_at=started,
ended_at=ended,
mode=mode,
difficulty=difficulty,
num_questions=num_questions,
correct=correct,
wrong=wrong,
accuracy_percent=accuracy,
average_time_s=avg_time,
questions=questions,
)

# -----------------------------
# Reporting + Saving
# -----------------------------

def print_summary(result: SessionResult) -> None:


duration = result.ended_at - result.started_at
print("\nSession Summary")
print("===============")
print(f"Mode: {[Link]}")
print(f"Difficulty: {[Link]}")
print(f"Questions: {result.num_questions}")
print(f"Correct: {[Link]}")
print(f"Wrong: {[Link]}")
print(f"Accuracy: {result.accuracy_percent:.2f}%")
print(f"Average time/question: {format_seconds(result.average_time_s)}")
print(f"Total duration: {format_seconds(duration)}")

def print_mistakes(result: SessionResult) -> None:


mistakes = [q for q in [Link] if q.is_correct is False]

🧠✅
if not mistakes:
print("\nNo mistakes — clean sweep ")
return

print("\nMistakes Review")
print("==============")
for i, q in enumerate(mistakes, start=1):
print(
f"{i:>2}. {q.a} × {q.b} = {q.a*q.b} | "
f"you said: {q.user_answer} | time: {format_seconds(q.time_taken_s or 0)}"
)

def save_result(result: SessionResult, filepath: str = "multiplication_session.json") -> Path:


path = Path(filepath)

payload = {
"started_at": result.started_at,
"ended_at": result.ended_at,
"mode": [Link],
"difficulty": [Link],
"num_questions": result.num_questions,
"correct": [Link],
"wrong": [Link],
"accuracy_percent": result.accuracy_percent,
"average_time_s": result.average_time_s,
"questions": [asdict(q) for q in [Link]],
}

path.write_text([Link](payload, indent=2), encoding="utf-8")


return path

# -----------------------------
# Main Menu
# -----------------------------

def menu() -> None:


while True:
print("\nMultiplication Mastery")
print("======================")
print("1) Show a multiplication table")
print("2) Show tables in a range")
print("3) Practice quiz (untimed)")
print("4) Timed quiz")
print("5) Exit")

choice = read_choice("Select (1/2/3/4/5): ", ["1", "2", "3", "4", "5"])

if choice == "1":
n = read_int("Which number table? (0-200): ", min_val=0, max_val=200)
upto = read_int("Up to which multiplier? (1-50): ", min_val=1, max_val=50)
clear_screen()
show_table(n, upto=upto)

elif choice == "2":


start = read_int("Start table (0-200): ", min_val=0, max_val=200)
end = read_int("End table (0-200): ", min_val=0, max_val=200)
if end < start:
start, end = end, start
upto = read_int("Up to which multiplier? (1-20): ", min_val=1, max_val=20)
clear_screen()
show_tables_range(start, end, upto=upto)

elif choice == "3":


difficulty = read_choice("Difficulty (easy/medium/hard/insane): ", ["easy", "medium",
"hard", "insane"])
num_q = read_int("Number of questions (1-100): ", min_val=1, max_val=100)
result = run_quiz(difficulty=difficulty, num_questions=num_q, timed=False,
time_limit_s=0)
print_summary(result)
print_mistakes(result)
if read_choice("Save results? (y/n): ", ["y", "n"]) == "y":
path = save_result(result)
print(f"Saved to: {[Link]()}")

elif choice == "4":


difficulty = read_choice("Difficulty (easy/medium/hard/insane): ", ["easy", "medium",
"hard", "insane"])
num_q = read_int("Number of questions (1-50): ", min_val=1, max_val=50)
limit = read_int("Time limit per question in seconds (2-60): ", min_val=2, max_val=60)
result = run_quiz(difficulty=difficulty, num_questions=num_q, timed=True,
time_limit_s=limit)
print_summary(result)
print_mistakes(result)
if read_choice("Save results? (y/n): ", ["y", "n"]) == "y":
path = save_result(result)
print(f"Saved to: {[Link]()}")

👋")
else:
print("Bye
return

if __name__ == "__main__":
[Link]() # system time seed
menu()

You might also like