简体   繁体   English

如何在测验中提出的每个问题上实施计时器?

[英]How do I implement a timer on each question asked in a quiz?

I was attempting to create a quiz and one of the criteria is to limit the time available to solve for each question in the quiz.我试图创建一个测验,其中一个标准是限制可用于解决测验中每个问题的时间。 I looked up certain tutorials but some require an input of x seconds for the timer to go off while others looked more like a stopwatch...我查找了某些教程,但有些教程需要输入 x 秒才能让计时器关闭,而其他教程看起来更像是秒表……

I was wondering how do I do like a background timer that ticks down as soon as the question is printed out and skips to the next question if, for example the 30-second period has ended?我想知道如何让后台计时器在问题打印出来后立即计时并跳到下一个问题,例如 30 秒时间段已经结束? I'm clueless in the timer function and was having problems to even try to implement them onto my codes.我对计时器功能一无所知,甚至在尝试将它们实现到我的代码中时遇到了问题。 Could someone give out a few pointers so I can sorta progress further in implementing a working timer?有人可以给出一些指示,以便我可以在实现工作计时器方面取得进一步进展吗?

Thank you!谢谢!

EDITED section below: The timer that I want to implement onto my coding:下面的编辑部分:我想在我的编码中实现的计时器:

import time
import threading

def atimer():
    print("Time's up.")

a_timer = threading.Timer(10.0, atimer)
a_timer.start()
print("")

This is the whole coding that I tried to implement the timer into.这是我尝试将计时器实现的整个编码。 I noticed that when I tried to define qtimer to just print 1 or 2 lines of statements the timer works but I want the timer to stop and go to second question or stop and give the user another attempt to retry the question, so I tried to attach a bunch of codes after the definition and it didn't work.我注意到,当我尝试将qtimer定义为仅打印 1 或 2 行语句时,计时器可以工作,但我希望计时器停止并转到第二个问题或停止并让用户再次尝试重试该问题,因此我尝试在定义后附上一堆代码,但它不起作用。 I know I'm most probably doing something wrong here since I'm not quite familiar with time or threading functions.我知道我很可能在这里做错了什么,因为我不太熟悉时间或线程函数。 Is there a workaround?有解决方法吗?

def qtimer():
    print("I'm sorry but your time is up for this question.")
    print("You may have another attempt if you wish to, with reduced marks allocated.")
    response1 = input("Type 'Yes' for another attempt, anything else to skip: ")
    if response1 == "Yes":
        Answ = input("Which option would you go for this time?: ")
        Answ = int(Answ)
        if possible[Answ - 1] == qaItem.corrAnsw:
            print("Your answer was correct.")
            corr += 1
            marks += 0.5 * qaItem.diff
        else:
            print("Your answer was wrong.")
            print("Correct answer was: " + qaItem.corrAnsw)
            print("Explanation: " + qaItem.expl)
            print("")
    else:
        print("Correct answer was: " + qaItem.corrAnsw)
        print("Explanation: " + qaItem.expl)
        print("")

class A:
  def __init__(self, question, correctAnswer, otherAnswers, difficulty, explanation):
    self.question = question
    self.corrAnsw = correctAnswer
    self.otherAnsw = otherAnswers
    self.diff = difficulty
    self.expl = explanation

qaList = [A("What is COVID-19?", "Coronavirus Disease 2019", ["Wuhan virus", "I don't understand...", "Coronavirus Disease v19"], 1, "Explanation 1"),
A("What describes COVID-19?", "A disease", ["A virus", "A parasite", "A bacteriophage"], 1, "Explanation 2"),
A("What causes COVID-19?", "SARS-CoV-2", ["Coronavirus", "Mimivirus", "Rubeola Virus"], 1, "Explanation 3"),
A("Which of the following is used in COVID-19 treatment?", "Lopinavir / Ritonavir ", ["Midazolam / Triazolam", "Amiodarone", "Phenytoin"], 2, "Explanation 4"),
A("Which of the following receptors is used by COVID-19 to infect human cells?", "ACE-2 Receptors", ["ApoE4 Receptors", "TCR Receptors", "CD28 Receptors"], 3, "Explanation 5")]

corr = 0
marks = 0
random.shuffle(qaList)
for qaItem in qaList:
    q_timer = threading.Timer(5.0, qtimer)
    q_timer.start()
    print(qaItem.question)
    print("Possible answers are:")
    possible = qaItem.otherAnsw + [qaItem.corrAnsw]
    random.shuffle(possible)
    count = 0
    while count < len(possible):
        print(str(count+1) + ": " + possible[count])
        count += 1
    print("Please enter the number of your answer:")
    Answ = input()
    Answ = str(Answ)
    while not Answ.isdigit():
        print("That was not a number. Please enter the number of your answer:")
        Answ = input()
        Answ = int(Answ)
    Answ = int(Answ)
    while Answ > 4 or Answ < 1:
        print("That number doesn't correspond to any answer. Please enter the number of your answer:")
        Answ = input()
        Answ = int(Answ)
    if possible[Answ-1] == qaItem.corrAnsw:
        print("Your answer was correct.")
        corr += 1
        marks += 1 * qaItem.diff
    else:
        print("Your answer was wrong.")
        response = input("Would you want to try again? If so, input 'Yes' to attempt it again, if not just input whatever!")
        if response == "Yes":
            Answ = input("Which option would you go for this time?: ")
            Answ = int(Answ)
            if possible[Answ - 1] == qaItem.corrAnsw:
                print("Your answer was correct.")
                corr += 1
                marks += 0.5 * qaItem.diff
            else:
                print("Your answer was wrong.")
                print("Correct answer was: " + qaItem.corrAnsw)
                print("Explanation: " + qaItem.expl)
                print("")
        else:
            print("Correct answer was: " + qaItem.corrAnsw)
            print("Explanation: " + qaItem.expl)
            print("")

print("You answered " + str(corr) + " of " + str(len(qaList)) + " questions correctly.")
print("You have achieved a total score of " + str(marks) + ".")

Even with a timer, the main thread can't proceed past waiting for the user to input a number;即使有定时器,主线程也不能继续等待用户输入数字; so if the user doesn't nothing, the timer function runs, and once it has finished the main thread is still waiting for input at所以如果用户什么都不做,定时器函数就会运行,一旦它完成,主线程仍然在等待输入

print("Please enter the number of your answer:")
Answ = input() 

You could have a global flag that the timer thread sets to tell the main thread to treat the input received as response1 in the timer code, and also have a flag to tell the timer that an answer was received, and so on, and it quickly becomes rather complicated.你可以有一个全局标志,定时器线程设置告诉主线程将接收到的输入视为定时器代码中的response1 ,还有一个标志来告诉定时器收到了一个答案,等等,它很快变得相当复杂。

So rather than trying to work around the blocking call to input by communicating between the timer and main thread, take the non-blocking input example from https://stackoverflow.com/a/22085679/1527 and stop the loop early if the time is up.因此,与其尝试通过计时器和主线程之间的通信来解决对input的阻塞调用,不如从https://stackoverflow.com/a/22085679/1527 中获取非阻塞输入示例,并在时间到时尽早停止循环起来了。

def timed_input(msg, timeout=10):
    kb = KBHit()

    print(msg)

    end_time = time.time() + timeout
    warn_time = 5

    result = None

    while True:

        if kb.kbhit():
            c = kb.getch()
            if '0' <= c <= '9':
                result = int(c)
                break                
            print(c)

        if time.time() > end_time:
            print('time is up')
            break

        if time.time() > end_time - warn_time:
            print(f'{warn_time}s left')
            warn_time = warn_time - 1

    kb.set_normal_term()

    return result


# Test    
if __name__ == "__main__":
    result = timed_input('Enter a number between 1 and 4')
    if result is None:
        print('be quicker next time')
    elif 1 <= result <= 4:
        print('ok')
    else: 
        print(f'{result} is not between 1 and 4')

Note also that breaking up into smaller functions helps make the code easier to follow, the logic of the test doesn't need to know about the logic of the timeout.还要注意,分解成更小的函数有助于使代码更容易理解,测试的逻辑不需要知道超时的逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM