Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python3
- import random
- import operator
- import json
- operators = {
- "+": operator.add,
- "/": operator.floordiv,
- "-": operator.sub,
- "*": operator.mul
- }
- def prompt_int(prompt):
- while True:
- try:
- return int(input(prompt).strip())
- except ValueError:
- print("Not a valid whole number, try again.")
- QUESTIONS = 10 # total question count
- MAX_DIVISION_VALUE = 12 # maximum answer for division questions
- MAX_GENERAL_VALUE = 50 # maximum size of operand for addition/subtraction
- MAX_MULTIPLICATION_VALUE = 24 # maximum size of operand for multiplication
- CLASSES = ["1", "2", "3"] # classes a student can be in
- def do_quiz():
- name = input("Name: ")
- while True:
- class_ = input("Class: ").lower().strip() # class is a reserved keyword in Python, so use class_ instead
- if class_ in CLASSES: break
- else: print("No such class", class_)
- score = 0
- for _ in range(QUESTIONS):
- # randomly pick one of division, subtraction, multiplication or addition
- operation = random.choice(list(operators.keys()))
- # pick questions which only require integer division
- if operation == "/":
- b = random.randint(2, MAX_DIVISION_VALUE)
- a = b * random.randint(2, MAX_DIVISION_VALUE)
- # generate smaller questions for multiplication
- elif operation == "*":
- a = random.randint(1, MAX_MULTIPLICATION_VALUE)
- b = random.randint(1, MAX_MULTIPLICATION_VALUE)
- else:
- a = random.randint(1, MAX_GENERAL_VALUE)
- b = random.randint(1, MAX_GENERAL_VALUE)
- # display question
- print(f"{a} {operation} {b}")
- # calculate answer and compare with input
- correct_answer = operators[operation](a, b)
- if prompt_int("Answer: ") == correct_answer:
- print("Correct!")
- score += 1
- else:
- print(f"Incorrect. The answer is {correct_answer}.")
- # print totals
- print(f"You got {score}/{QUESTIONS} right ({score / QUESTIONS * 100}%).")
- # write score to file (as newline-delimited JSON, to avoid possible escaping issues and for easy parsing, including by other tools)
- with open("scores.jsonl", "a") as file:
- json.dump({ "class": class_, "score": score, "student": name }, file)
- file.write("\n")
- def display_scores():
- with open("scores.jsonl", "r") as file:
- lines = [ line.strip() for line in file.readlines() ]
- scores_seen = {}
- best_scores = {}
- # read file backward to get latest scores first
- for line in reversed(lines):
- # parse JSON
- quiz_result = json.loads(line)
- name = quiz_result["student"]
- class_ = quiz_result["class"]
- score = quiz_result["score"]
- # uniquely identify student by their name and class
- student = (name, class_)
- # check if 3 scores for a student have already been processed
- times_seen = scores_seen.get(student, 0)
- if times_seen < 3:
- scores_seen[student] = times_seen + 1
- # check if score is better than current best
- best_score = best_scores.get(student, None)
- if best_score == None or score > best_score:
- best_scores[student] = score
- # sort student, best score tuples by student name
- alphabetical_scores = sorted(best_scores.items(), key=lambda student_and_score: student_and_score[0])
- for (name, class_), score in alphabetical_scores:
- print(f"{name} (class {class_}): {score}")
- if "y" in input("Display scores? ").lower():
- display_scores()
- else:
- do_quiz()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement