Advertisement
osmarks

task 1

Feb 11th, 2021
855
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.68 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. import random
  4. import operator
  5. import json
  6.  
  7. operators = {
  8.     "+": operator.add,
  9.     "/": operator.floordiv,
  10.     "-": operator.sub,
  11.     "*": operator.mul
  12. }
  13.  
  14. def prompt_int(prompt):
  15.     while True:
  16.         try:
  17.             return int(input(prompt).strip())
  18.         except ValueError:
  19.             print("Not a valid whole number, try again.")
  20.  
  21. QUESTIONS = 10 # total question count
  22. MAX_DIVISION_VALUE = 12 # maximum answer for division questions
  23. MAX_GENERAL_VALUE = 50 # maximum size of operand for addition/subtraction
  24. MAX_MULTIPLICATION_VALUE = 24 # maximum size of operand for multiplication
  25. CLASSES = ["1", "2", "3"] # classes a student can be in
  26.  
  27. def do_quiz():
  28.     name = input("Name: ")
  29.     while True:
  30.         class_ = input("Class: ").lower().strip() # class is a reserved keyword in Python, so use class_ instead
  31.         if class_ in CLASSES: break
  32.         else: print("No such class", class_)
  33.  
  34.     score = 0
  35.     for _ in range(QUESTIONS):
  36.         # randomly pick one of division, subtraction, multiplication or addition
  37.         operation = random.choice(list(operators.keys()))
  38.        
  39.         # pick questions which only require integer division
  40.         if operation == "/":
  41.             b = random.randint(2, MAX_DIVISION_VALUE)
  42.             a = b * random.randint(2, MAX_DIVISION_VALUE)
  43.         # generate smaller questions for multiplication
  44.         elif operation == "*":
  45.             a = random.randint(1, MAX_MULTIPLICATION_VALUE)
  46.             b = random.randint(1, MAX_MULTIPLICATION_VALUE)
  47.         else:
  48.             a = random.randint(1, MAX_GENERAL_VALUE)
  49.             b = random.randint(1, MAX_GENERAL_VALUE)
  50.  
  51.         # display question
  52.         print(f"{a} {operation} {b}")
  53.         # calculate answer and compare with input
  54.         correct_answer = operators[operation](a, b)
  55.         if prompt_int("Answer: ") == correct_answer:
  56.             print("Correct!")
  57.             score += 1
  58.         else:
  59.             print(f"Incorrect. The answer is {correct_answer}.")
  60.  
  61.     # print totals
  62.     print(f"You got {score}/{QUESTIONS} right ({score / QUESTIONS * 100}%).")
  63.  
  64.     # write score to file (as newline-delimited JSON, to avoid possible escaping issues and for easy parsing, including by other tools)
  65.     with open("scores.jsonl", "a") as file:
  66.         json.dump({ "class": class_, "score": score, "student": name }, file)
  67.         file.write("\n")
  68.  
  69. def display_scores():
  70.     with open("scores.jsonl", "r") as file:
  71.         lines = [ line.strip() for line in file.readlines() ]
  72.    
  73.     scores_seen = {}
  74.     best_scores = {}
  75.     # read file backward to get latest scores first
  76.     for line in reversed(lines):
  77.         # parse JSON
  78.         quiz_result = json.loads(line)
  79.         name = quiz_result["student"]
  80.         class_ = quiz_result["class"]
  81.         score = quiz_result["score"]
  82.         # uniquely identify student by their name and class
  83.         student = (name, class_)
  84.         # check if 3 scores for a student have already been processed
  85.         times_seen = scores_seen.get(student, 0)
  86.         if times_seen < 3:
  87.             scores_seen[student] = times_seen + 1
  88.             # check if score is better than current best
  89.             best_score = best_scores.get(student, None)
  90.             if best_score == None or score > best_score:
  91.                 best_scores[student] = score
  92.  
  93.     # sort student, best score tuples by student name
  94.     alphabetical_scores = sorted(best_scores.items(), key=lambda student_and_score: student_and_score[0])
  95.     for (name, class_), score in alphabetical_scores:
  96.         print(f"{name} (class {class_}): {score}")
  97.  
  98. if "y" in input("Display scores? ").lower():
  99.     display_scores()
  100. else:
  101.     do_quiz()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement