Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a countdown timer in Rails that resets on the backend

I am currently creating a Rails quiz application with a timer that counts down the seconds left to answer the question.

In my first version, I did this a simple way: creating a variable for the timer, an instance for seconds, and then making it part of the quiz's Javascript, like so:

Quiz = function() {
  this.quizCurrent = 0;
  this.score = 0;
  this.seconds = 10;
  this.timing = this.seconds;
  this.container = $('#trivia');
  this.participationId = null;
 }

 Quiz.prototype.init = function() {
  $('#trivia').on('click', '.btn.btn-primary-questions', this.checkAnswer.bind(this));
  $('div.timer strong').text(this.seconds)

  this.start();
 }

I would now like to move this to the backend using Rails. A previous question references the countdown gem, but that seems to present two issues:

1) I will need to repeatedly call the date/time and validate for each question (which I don't think I can do with countdown), and;

2) I ideally could then pass this value into the Javascript as a variable.

In the documentation for that gem, it shows how you can pass the countdown time into the view directly. However, I am using the countdown value (in other words, when it hits zero) to force the user to the next question while recording a wrong answer, like below, as part of my validation:

Quiz.prototype.timer = function() {
 var that = this;

 this.timing--;
   $('div.timer strong').text(this.timing);
   if (this.timing <= 0) {
     self.stop(); 
  $.getJSON('/api/skip_question/' + this.participationId, function() {
    that.nextQuestion();
   })
  }}

Any ideas on how I can "check" the time on the backend while still having the quiz check to make sure time hasn't run out?

like image 629
darkginger Avatar asked Jan 29 '16 07:01

darkginger


1 Answers

I don't know anything about the countdown gem, but a simple solution comes to mind.

Lets say you keep a timestamp on the backend and when your js quiz starts it lets the back end know that the quiz has started.

$.getJSON('/api/start_quiz/', function() {
    //do whatever javascript starts the quiz.
})

on the backend, lets assume you have a QuizAttempt model with corresponding database value 'attempt_timestamp':

def start_quiz
  QuizAttempt.create(user_id: current_user.id, attempt_timestamp: Time.now)
end

Then you could have a before filter that determines if time has run out on your skip_question and answer_question endpoints. (in my example there's an 8 minute time limit.

before_filter :check_time, only: [:skip_question, :answer_question]

def check_time
  #get last attempt
  last_attempt = QuizAttempt.where(user_id: current_user.id).last
  if (last_attempt.attempt_timestamp + 8.minutes) < Time.now
    #time is up
    return false
  end
end

Side Idea: you could also add an endpoint that responds with the recorded timestamp for the purpose of syncronizing the js clock with the timestamp in the db.

Edit: another possible place to keep said timestamp might be in the session rather than the database.

like image 179
denodster Avatar answered Oct 23 '22 20:10

denodster