Python Dates and Times in Python Let's Build a Timed Quiz App The Question Classes & the Plan

matthias papsdorf
PRO
matthias papsdorf
Pro Student 4,152 Points

My approach of the Quiz:

__author__ = 'matthias_papsdorf1'

class Question():
    answer = None
    text = None


class Add(Question):
    def __init__(self, num1, num2):
        self.text = "{} + {}".format(num1, num2)
        self.answer = num1 + num2


class Multiply(Question):
    def __init__(self, num1, num2):
        self.text = "{} x {}".format(num1, num2)
        self.answer = num1 * num2
__author__ = 'matthias_papsdorf1'

import datetime
import random
import os

from question import Add
from question import Multiply

class Quiz():
    questions = []
    answers = []

    def __init__(self):
        #generate 10 random questions [1 - 10]
        self.question_template = {"add" : "how much is {} + {}? ",
                                  "mul" : "how much is {} x {}? "}
        self.answered_questions = 0

        for k in range(0,10):
            #need to manually create a list out of dict.keys(), dict.keys() object is not indexable
            rkey = random.choice(list(self.question_template.keys()))
            num1 = random.randint(0, 10)
            num2 = random.randint(0, 10)
            self.questions.append([rkey, num1, num2])

    def take_quiz(self):
        self.start_time = datetime.datetime.now()
        for question in self.questions:
            q_time = self.ask(question)
            if q_time:
                total_time = datetime.datetime.now() - self.start_time
                print("The answer is right!\nTime used for question: {}\nTotal time: {}".format(q_time,total_time))
                del q_time
                self.answered_questions += 1
            else:
                print("Answer incorrect")
        self.end_time = datetime.datetime.now() - self.start_time
        self.summary()

    def ask(self, question):
        calculation = 0
        start = datetime.datetime.now()
        #print(question)
        if question[0] == "add":
            calculation = Add(question[1], question[2]).answer
        if question[0] == "mul":
            calculation = Multiply(question[1], question[2]).answer
        if int(input(self.question_template[question[0]].format(question[1], question[2]))) == calculation:
            return(datetime.datetime.now() - start)
        else:
            print("Wrong answer, should have been: {}".format(calculation))

    def summary(self):
        os.system("clear")
        print("Total time: {}\n"
              "Questions answered: {}\n"
              "questions not answered: {}".format(self.end_time, self.answered_questions, len(self.questions) - self.answered_questions))

if __name__ == "__main__":
    myquiz = Quiz()
    myquiz.take_quiz()
matthias papsdorf
matthias papsdorf
Pro Student 4,152 Points

For some reason it does not let my update my post further. I meant to say, please leave a bit of feedback.I tent to over complicate things sometime.

2 Answers

Iulia Maria Lungu
Iulia Maria Lungu
16,922 Points

My approach below. I did not check the teacher's one yet. So I am not sure if this is how the quiz was meant to be :P My solution implies questions about adding/multiplying a random set of operands (up to 10) I'm very open to improvement and comments!

import datetime
import random
from functools import reduce


def format_time_elapsed(delta):
    seconds = delta.seconds
    hours, remainder = divmod(seconds, 3600)
    minutes, seconds = divmod(remainder, 60)
    return '{:02}:{:02}:{:02}'.format(int(hours), int(minutes), int(seconds))


def format_time(date):
    return date.strftime("%H:%M:%S")


class Question:
    answer = None
    text = None


class Add(Question):
    def __init__(self, *args):
        self.text = (
            "{}" + " + {}" * (len(args) - 1)
        ).format(*args)  # => '7 + 8 + 9 + 1 + 4'
        self.answer = reduce((lambda x, y: x + y), args)


class Multiply(Question):
    def __init__(self, *args):
        self.text = (
            "{}" + " x {}" * (len(args) - 1)
        ).format(*args)  # => '7 x 8 x 9 x 1 x 4'
        self.answer = reduce((lambda x, y: x * y), args)


class Quiz:
    questions = []

    def __init__(self):
        # generate 10 random questions with numbers from 1 to 10
        for index in range(10):
            arguments = random.sample(
                range(1, 11), random.choice(range(2, 11)))
            # add these to questions list
            if index % 2 == 0:
                self.questions.append(Add(*arguments))
            else:
                self.questions.append(Multiply(*arguments))

    def take_quiz(self):
        correct = 0
        # log the start time
        start_time = datetime.datetime.now()
        print("Quiz started", format_time(start_time))
        # ask all of the questions
        for index, _ in enumerate(self.questions):
            response, time_elapsed = self.ask(index)
            # log if they got the question right
            print(
                "This is the right answer" if response else "Your math skills are not very good"
            )
            print(
                'It took you',
                format_time_elapsed(time_elapsed),
                'to answer'
            )
            if response:
                correct += 1

        # log the end time
        end_time = datetime.datetime.now()
        print("Quiz ended!", format_time(end_time))
        # show a summary
        return self.summary(correct, format_time_elapsed(end_time - start_time))

    def ask(self, question_number):
        question = self.questions[question_number]
        # log the start time
        start_time = datetime.datetime.now()
        # capture the answer
        answer = input(f"How much is {question.text}?\n")
        # log the end time
        end_time = datetime.datetime.now()
        time_delta = end_time - start_time

        # check the answer
        try:
            parsed_answer = int(answer)
        except ValueError:
            print('I need you to answer back a number')
            return False, time_delta
        else:
            if parsed_answer == question.answer:
                response = True
            else:
                response = False
        # also send back the time elapsed
        return response, time_delta

    def summary(self, result, time):
        # print the result: how many are correct from the total
        print('You got', result, 'correct out of', len(self.questions))
        # print the total time of the quiz
        print('Total quiz time', time)
        return

# run quiz

Quiz().take_quiz()