0

I am creating a website for students which will be used to assign exams and I am having difficulties with the timer. The one I am using is made on the frontend in javascript and whenever the page is refreshed the timer startsover. Tried to store the start and end date by converting to epoch and back to datetime but I cannot think of a way to get the timer to the frontend and start counting. The idea is to count 60 minutes and call the submit button as well as to show the countdown without the option to restart the counter.

This is how I store the start and end time in nodejs.

var myDate = new Date();
var startTimeEpoch = myDate.getTime()/1000.0;
var endTimeEpoch = startTimeEpoch + 5400 // Adding 90 minutes to the timer
var startTimeBackToDate = new Date(startTimeEpoch *1000)
var endTimeBackToDate = new Date(endTimeEpoch *1000)

This is the javascript timer I am using and I am wondering if I should use one in the first place.

    function startTimer(duration, display) {
        var start = Date.now(),
            diff,
            minutes,
            seconds;
        function timer() {
            diff = duration - (((Date.now() - start) / 1000) | 0);
    
            minutes = (diff / 60) | 0;
            seconds = (diff % 60) | 0;
    
            minutes = minutes < 10 ? "0" + minutes : minutes;
            seconds = seconds < 10 ? "0" + seconds : seconds;
    
            display.textContent = minutes + ":" + seconds; 
    
            if (diff <= 0) {
                start = Date.now() + 1000;
            }
        }
        timer();
        setInterval(timer, 1000);
    }
    
    window.onload = function () {
        var fiveMinutes = "<%= scenario.time %>" * 60,
            display = document.querySelector('#time');
        startTimer(fiveMinutes, display);
    }
7h3blu3
  • 3
  • 1
  • 2

2 Answers2

0

I don't think a timer that a student with Javascript knowledge can modify should be used for serious tests, but for anything more light-hearted it should be fine.

The best system I can think of for this would be to have the test length stored in the mongodb and when a signed-in user starts the test, have the current time logged for that user. That way, you can calculate time remaining using user.testStart + test.length - Date.now().

LaytonGB
  • 1,384
  • 1
  • 6
  • 20
  • Thanks for the answer, I am wondering if I should use setInterval() in some way to create a timer in nodejs instead of javascript, do you have a suggestion ? – 7h3blu3 May 04 '21 at 13:32
  • @7h3blu3 i don't get why you need a "timer" in node, you know that the setInterval function basis in Javascript is to execute a function every intervals, why do you want that ? – mxncson May 04 '21 at 13:47
  • Hello, my idea was that using setInterval I can show the timer to the user, but not having much experience just felt wrong using it on the frontend. I am having difficulties with the timer being shown and from here I have the confusion on whether I should use JS or Nodejs. I am open to suggestions. – 7h3blu3 May 04 '21 at 14:03
  • @7h3blu3 What do you use for your frontend ? Any type of javascript framework or is this server side rendered ? – mxncson May 04 '21 at 14:09
  • I am not using any framework for the timer and it is plain javascript. I however use nodejs with express and ejs for my pages(Not sure if this information helps). – 7h3blu3 May 04 '21 at 14:37
0

As a general response and with the additional information provided, i could propose a solution to make this work.

If your students all have a specific exam entity attached to them, when they register/start an exam, you could retrieve the start date of this exam(add a mongo createdAt Date field) and use it as the starting date. If each exam has a time limit, then you could simply do the math to know how much time is left. Something that will look like this:

const getExamRemainingTime = (exam) => {
  // assuming that start is a js date object
  // and timeLimit is an number representing the duration hours of your exam
  const { start, timeLimit } = exam;

  let end = (start.getHours() + timeLimit);
  end = end.setHours(end);
  const remainingTime = (+end) - (+start)

  if (remainingTime > 0) {
    // duration not finished, exam still in progress
    return new Date(remainingTime);
  } else {
    // exam finished
   return 0;
  }
}

Then in your frontend, if it's plain javascript, you need to refresh your timer component, use setInterval in last ressort because it's very heavy on performance and format the date you got the way you want to show it.

Ref: casting js Date object to timestamp - How do you get a timestamp in JavaScript?.

Dharman
  • 30,962
  • 25
  • 85
  • 135
mxncson
  • 178
  • 1
  • 11