Countdown timer inaccurate - losing time!?!

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Christine

    #1

    Countdown timer inaccurate - losing time!?!

    I've implemented a countdown timer for a tutorial web page that should
    give the user 45 minutes to complete the test, only to find that the
    timer is slowly 'losing' time. On average, it actually takes an extra
    35 seconds, but has taken an extra 2.5 minutes in some cases. Any
    ideas what might be the cause? And more importantly - the fix? Code
    snippet below...

    Thanks,
    Christine

    var gTimer=null;
    var gTimerCount = 2700; //45 minutes

    function CallTimer(num){ //this function is called when the page
    is loaded
    gTimerCount=num ;
    Timer();}

    function Timer() {
    window.status=" ";
    gTimerCount--;
    if (gTimerCount > 0)
    {
    if (gTimerCount == 300) TimeWarning();
    window.status = "Time Remaining: " +
    ConvertNum(gTim erCount) + " CT " + timeValue + " CTsecs " + ((hours *
    3600)+(minutes * 60)+seconds);
    gTimer=window.s etTimeout("Time r()",1000);
    }
    else{
    //OpenWin.close() ;
    window.document .forms[0].submit.click() ;}
    }

    function ConvertNum(nums ecs) { return (Math.floor(num secs/60)) +
    ":" + AdjustNum(numse cs % 60); }

    function AdjustNum(numse cs) {
    if (numsecs < 10) return "0"+ numsecs;
    else return numsecs;
    }
  • Lasse Reichstein Nielsen

    #2
    Re: Countdown timer inaccurate - losing time!?!

    wilson_work@yah oo.com (Christine) writes:
    [color=blue]
    > I've implemented a countdown timer for a tutorial web page that should
    > give the user 45 minutes to complete the test, only to find that the
    > timer is slowly 'losing' time. On average, it actually takes an extra
    > 35 seconds, but has taken an extra 2.5 minutes in some cases. Any
    > ideas what might be the cause?[/color]

    Each step in the countdown is triggered by (and triggers)
    gTimer=window.s etTimeout("Time r()",1000);
    That is, when Timer is called, first it performs its own computations,
    which takes some time, and then it schedules a new call one second
    after that.

    That means that the time between calls to Timer is not one second,
    but one second + the time to execute the call to Timer().

    You could probably get around that by using
    setInterval(Tim er, 1000)
    However, on top of that, the timer might not be exact. It can only
    perfectly match numbers that are a multiplum of the computer/OS's
    internal timer frequency. If 1000 isn't that, it might round it
    to 1024 or something. That is also a problem for long stretches
    of short intervals.

    My suggestion is to keep track of the time yourself:
    ---
    function countdown(endAc tion, totalSecs, stepAction, stepFreq) {
    var timeout = new Date();
    timeout.setSeco nds(timeout.get Seconds() + totalSecs);
    function countdownStep() {
    var now = new Date();
    var timeLeft = timeout - now;
    if (timeLeft <= 0) {
    clearInterval(i d);
    endAction();
    } else {
    stepAction(time Left);
    }
    }
    var id = setInterval(cou ntdownStep, stepFreq);
    }
    ---
    Then you can call it as:
    ---
    countdown(
    function() {
    document.forms[0].submit.click() ; // if you didn't call the button
    // submit, you could just do
    // .forms[0].submit()
    },
    2700,
    function (timeLeft) {
    window.status = "time left: " + timeLeft + "ms"; // or whatever
    },
    500);
    ---
    The first function is called when the countdown ends.
    The second argument is the seconds before that happens.
    The third argument is the function that is called for each "tick".
    The fourth argument is the milliseconds between ticks.

    This should not be off by more than the tick-size.

    Good luck.
    /L
    --
    Lasse Reichstein Nielsen - lrn@hotpop.com
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleD OM.html>
    'Faith without judgement merely degrades the spirit divine.'

    Comment

    • Dr John Stockton

      #3
      Re: Countdown timer inaccurate - losing time!?!

      JRS: In article <26c240b.040725 0456.40616e4f@p osting.google.c om>, dated
      Sun, 25 Jul 2004 05:56:04, seen in news:comp.lang. javascript, Christine
      <wilson_work@ya hoo.com> posted :
      [color=blue]
      >I've implemented a countdown timer for a tutorial web page that should
      >give the user 45 minutes to complete the test, only to find that the
      >timer is slowly 'losing' time. On average, it actually takes an extra
      >35 seconds, but has taken an extra 2.5 minutes in some cases. Any
      >ideas what might be the cause? And more importantly - the fix?[/color]

      Had you read the FAQ, you should have been led to the answer.

      An error of 2.5 in 45 is about 1 in 18. I imagine those are Win98-class
      systems, where the clock runs at 18.2 Hz.

      An error of 35 in 45*60 is about 1 in 80. I imagine those are WinNT-
      class systems, where the clock runs at 100 Hz.


      Note that, as well as the overheads in your program, the Timer must wait
      till the next clock tick before it fires.



      If you want something to happen once per computer second, you need a
      lesser timeout, automatically compensating for delays - something like

      setTimeout( S, 1010 - (new Date().getTime( ))%1000 )

      That can possibly miss a tick if the computer is otherwise engaged for a
      whole second; you might prefer to count in minutes.


      If you want something to happen when the computer clock reaches a
      certain time, you could loop waiting for that time. In order not to hog
      the machine, you should use setTimeout to look only once per second,
      checking new Date().getTime( ) against the proper value (for efficiency).


      Those are conceptually different, and the difference can be significant
      if clock-adjusting software is run (but, coded properly, the start and
      finish of Summer Time will not cause error).


      See below; js-date1.htm#TaI

      --
      © John Stockton, Surrey, UK. ?@merlyn.demon. co.uk Turnpike v4.00 IE 4 ©
      <URL:http://jibbering.com/faq/> JL / RC : FAQ for news:comp.lang. javascript
      <URL:http://www.merlyn.demo n.co.uk/js-index.htm> jscr maths, dates, sources.
      <URL:http://www.merlyn.demo n.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.

      Comment

      • Christine

        #4
        Re: Countdown timer inaccurate - losing time!?!

        Lasse,
        Thanks - I tailored your suggestion and I've got it working now. I
        appreciate the help.
        Just one other question about the code you posted...
        Why do you have to specify "function" in the function call below? Are
        you defining a function and why don't they have names?
        [color=blue]
        > countdown(
        > function() {
        > document.forms[0].submit.click() ; // if you didn't call the button
        > // submit, you could just do
        > // .forms[0].submit()
        > },
        > 2700,
        > function (timeLeft) {
        > window.status = "time left: " + timeLeft + "ms"; // or whatever
        > },
        > 500);[/color]


        Lasse Reichstein Nielsen <lrn@hotpop.com > wrote in message news:<1xj09qgs. fsf@hotpop.com> ...[color=blue]
        > wilson_work@yah oo.com (Christine) writes:
        >[color=green]
        > > I've implemented a countdown timer for a tutorial web page that should
        > > give the user 45 minutes to complete the test, only to find that the
        > > timer is slowly 'losing' time. On average, it actually takes an extra
        > > 35 seconds, but has taken an extra 2.5 minutes in some cases. Any
        > > ideas what might be the cause?[/color]
        >
        > Each step in the countdown is triggered by (and triggers)
        > gTimer=window.s etTimeout("Time r()",1000);
        > That is, when Timer is called, first it performs its own computations,
        > which takes some time, and then it schedules a new call one second
        > after that.
        >
        > That means that the time between calls to Timer is not one second,
        > but one second + the time to execute the call to Timer().
        >
        > You could probably get around that by using
        > setInterval(Tim er, 1000)
        > However, on top of that, the timer might not be exact. It can only
        > perfectly match numbers that are a multiplum of the computer/OS's
        > internal timer frequency. If 1000 isn't that, it might round it
        > to 1024 or something. That is also a problem for long stretches
        > of short intervals.
        >
        > My suggestion is to keep track of the time yourself:
        > ---
        > function countdown(endAc tion, totalSecs, stepAction, stepFreq) {
        > var timeout = new Date();
        > timeout.setSeco nds(timeout.get Seconds() + totalSecs);
        > function countdownStep() {
        > var now = new Date();
        > var timeLeft = timeout - now;
        > if (timeLeft <= 0) {
        > clearInterval(i d);
        > endAction();
        > } else {
        > stepAction(time Left);
        > }
        > }
        > var id = setInterval(cou ntdownStep, stepFreq);
        > }
        > ---
        > Then you can call it as:
        > ---
        > countdown(
        > function() {
        > document.forms[0].submit.click() ; // if you didn't call the button
        > // submit, you could just do
        > // .forms[0].submit()
        > },
        > 2700,
        > function (timeLeft) {
        > window.status = "time left: " + timeLeft + "ms"; // or whatever
        > },
        > 500);
        > ---
        > The first function is called when the countdown ends.
        > The second argument is the seconds before that happens.
        > The third argument is the function that is called for each "tick".
        > The fourth argument is the milliseconds between ticks.
        >
        > This should not be off by more than the tick-size.
        >
        > Good luck.
        > /L[/color]

        Comment

        • Lasse Reichstein Nielsen

          #5
          Re: Countdown timer inaccurate - losing time!?!

          wilson_work@yah oo.com (Christine) writes:
          [color=blue]
          > Just one other question about the code you posted...
          > Why do you have to specify "function" in the function call below? Are
          > you defining a function and why don't they have names?[/color]

          I am defining a function, and it is a so-called anonymous function.
          [color=blue][color=green]
          >> countdown([/color][/color]

          I'm calling "countdown" , and the first argument is:
          [color=blue][color=green]
          >> function() {
          >> document.forms[0].submit.click() ; // if you didn't call the button
          >> // submit, you could just do
          >> // .forms[0].submit()
          >> },[/color][/color]

          .... this function.
          This is a function *expression* (as opposed to a function *declaration*).
          It defines a function, but doesn't bind it to a name.

          A function declaration is written in the same places as statements.
          They both define the function and declare its name in the surrounding
          scope. A function expression is written in the same places as
          expressions. It only define the function, but doesn't declare a name.

          Example:
          ---
          function foo(f) {
          f(function() { return 42;});
          }
          function bar(x) { return x + 37; }

          alert(foo(bar)) ;
          ---
          In this example we have two function declarations, for the functions
          "foo" and "bar". We use the value of "bar" as an argument to "foo".
          Inside "foo", the variable "f" refers to the argument function (here
          only "bar"). We call that with a third function, defined by a
          function expression (the constant function that always returns 42).

          Executing this will alert 79.



          Good luck
          /L
          --
          Lasse Reichstein Nielsen - lrn@hotpop.com
          DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleD OM.html>
          'Faith without judgement merely degrades the spirit divine.'

          Comment

          Working...