I'm learning Ruby and as part of the practice, I have implemented a simple quiz app. Its pseudocode is like this
for i in 0..questions.length - 1 do
puts questions[i]
$answer = gets.chomp
if $answer == answers[i]
correct = 1
end
end
timer_thread = Thread.new do
while $answer == nil
(1..5).each do |number|
sleep(1)
number
if number == 5
puts "Timer out"
end
break if ($answer != nil)
end
end
end
What I want is to add a timer of let's say 30 seconds, it should move to the next question and that question should be considered incorrect. I came to know about Time.now but am not sure how I can go about adding it to my program.
Any pointers, please?
CodePudding user response:
I think that using threads is overhead here
You can use Timeout
As I see you use two arrays for questions and answers, you can zip it with Array#zip
In Ruby we don't like for loop. We use Array#each. BTW for uses each under the hood
Using global variables in the code can lead to a shot in the foot. Use them only when you are absolutely sure that they are needed
So I would suggest refactoring the code like this:
require "timeout"
correct_answers_count = 0
TIMEOUT = 30
questions.zip(answers).each do |question, right_answer|
puts question
user_answer = nil
Timeout::timeout(TIMEOUT) { user_answer = gets.strip }
if user_answer&.downcase == right_answer&.downcase
correct_answers_count = 1
puts "Right!"
else
puts "Wrong!"
end
rescue Timeout::Error
puts "Time is out"
end
puts "Right answers: #{correct_answers_count}"
CodePudding user response:
You can use timeout. Set your desired timeout in seconds by changing time_to_answer, in this example it is set to 5.
require 'timeout'
questions = [
"2 2 = ?",
"Who is Amazons CEO?",
]
answers = [
"4",
"Jeff Bezos",
]
def ask_question(question, answer, time_to_answer)
puts "\n=== NEW QUESTION ==="
puts question
result = Timeout::timeout(time_to_answer) do
user_action = gets.chomp
return user_action === answer
end
rescue Timeout::Error
puts " 