Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

hypertimer

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hypertimer - npm Package Compare versions

Comparing version 1.1.1 to 2.0.0

.travis.yml

186

dist/hypertimer.js

@@ -5,10 +5,11 @@ /**

*
* A timer running faster or slower than real-time, and in continuous or
* discrete time.
* Time control for simulations.
*
* @version 1.1.1
* @date 2014-10-21
* Run a timer at a faster or slower pace than real-time, or run discrete events.
*
* @version 2.0.0
* @date 2015-02-19
*
* @license
* Copyright (C) 2014 Almende B.V., http://almende.com
* Copyright (C) 2014-2015 Almende B.V., http://almende.com
*

@@ -99,31 +100,43 @@ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

var DISCRETE = 'discrete';
/**
* Create a new hypertimer
* @param {Object} [options] The following options are available:
* rate: number | 'discrete'
* The rate of speed of hyper time with
* respect to real-time in milliseconds
* per millisecond. Rate must be a
* positive number, or 'discrete' to
* run in discrete time (jumping from
* event to event). By default, rate is 1.
* deterministic: boolean
* If true (default), simultaneous events
* are executed in a deterministic order.
* paced: boolean
* Mode for pacing of time. When paced,
* the time proceeds at a continuous,
* configurable rate, useful for
* animation purposes. When unpaced, the
* time jumps immediately from scheduled
* event to the next scheduled event.
* rate: number
* The rate of progress of time with
* respect to real-time. Rate must be a
* positive number, and is 1 by default.
* For example when 2, the time of the
* hypertimer runs twice as fast as
* real-time.
* Only applicable when option paced=true.
* time: number | Date
* Set a simulation time. If not provided,
* The timer is instantiated with the
* current system time.
*/
function hypertimer(options) {
// options
var paced = true;
var rate = 1; // number of milliseconds per milliseconds
var deterministic = true; // run simultaneous events in a deterministic order
var configuredTime = null;
// properties
var running = false; // true when running
var realTime = null; // timestamp. the moment in real-time when hyperTime was set
var hyperTime = null; // timestamp. the start time in hyper-time
var timeouts = []; // array with all running timeouts
var current = {}; // the timeouts currently in progress (callback is being executed)
var timeoutId = null; // currently running timer
var idSeq = 0; // counter for unique timeout id's
var running = false; // true when running
var realTime = null; // timestamp. the moment in real-time when hyperTime was set
var hyperTime = util.systemNow(); // timestamp. the start time in hyper-time
var timeouts = []; // array with all running timeouts
var current = {}; // the timeouts currently in progress (callback is being executed)
var timeoutId = null; // currently running timer
var idSeq = 0; // counter for unique timeout id's

@@ -137,12 +150,22 @@ // exported timer object with public functions and variables

* @param {Object} [options] The following options are available:
* rate: number | 'discrete'
* The rate of speed of hyper time with
* respect to real-time in milliseconds
* per millisecond. Rate must be a
* positive number, or 'discrete' to
* run in discrete time (jumping from
* event to event). By default, rate is 1.
* deterministic: boolean
* If true (default), simultaneous events
* are executed in a deterministic order.
* paced: boolean
* Mode for pacing of time. When paced,
* the time proceeds at a continuous,
* configurable rate, useful for
* animation purposes. When unpaced, the
* time jumps immediately from scheduled
* event to the next scheduled event.
* rate: number
* The rate of progress of time with
* respect to real-time. Rate must be a
* positive number, and is 1 by default.
* For example when 2, the time of the
* hypertimer runs twice as fast as
* real-time.
* Only applicable when option paced=true.
* time: number | Date
* Set a simulation time.
* @return {Object} Returns the applied configuration

@@ -152,7 +175,31 @@ */

if (options) {
if ('deterministic' in options) {
deterministic = options.deterministic ? true : false;
}
if ('paced' in options) {
paced = options.paced ? true : false;
}
// important: apply time before rate
if ('time' in options) {
if (options.time instanceof Date) {
hyperTime = options.time.valueOf();
}
else {
var newTime = Number(options.time);
if (isNaN(newTime)) {
throw new TypeError('Invalid time ' + JSON.stringify(options.time) + '. Time must be a Date or number');
}
hyperTime = newTime;
}
configuredTime = options.time;
}
if ('rate' in options) {
var newRate = (options.rate === DISCRETE) ? DISCRETE : Number(options.rate);
if (newRate !== DISCRETE && (isNaN(newRate) || newRate <= 0)) {
throw new TypeError('rate must be a positive number or the string "discrete"');
var newRate = Number(options.rate);
if (isNaN(newRate) || newRate <= 0) {
throw new TypeError('Invalid rate ' + JSON.stringify(options.rate) + '. Rate must be a positive number');
}
hyperTime = timer.now();

@@ -162,5 +209,2 @@ realTime = util.systemNow();

}
if ('deterministic' in options) {
deterministic = options.deterministic ? true : false;
}
}

@@ -173,4 +217,6 @@

return {
paced: paced,
rate: rate,
deterministic: deterministic
deterministic: deterministic,
time: configuredTime
};

@@ -180,22 +226,2 @@ };

/**
* Set the time of the timer. To get the current time, use getTime() or now().
* @param {number | Date} time The time in hyper-time.
*/
timer.setTime = function (time) {
if (time instanceof Date) {
hyperTime = time.valueOf();
}
else {
var newTime = Number(time);
if (isNaN(newTime)) {
throw new TypeError('time must be a Date or number');
}
hyperTime = newTime;
}
// reschedule running timeouts
_schedule();
};
/**
* Returns the current time of the timer as a number.

@@ -206,6 +232,3 @@ * See also getTime().

timer.now = function () {
if (rate === DISCRETE) {
return hyperTime;
}
else {
if (paced) {
if (running) {

@@ -221,2 +244,5 @@ // TODO: implement performance.now() / process.hrtime(time) for high precision calculation of time interval

}
else {
return hyperTime;
}
};

@@ -252,3 +278,2 @@

*/
// rename to getTime
timer.getTime = function() {

@@ -495,3 +520,3 @@ return new Date(timer.now());

if (typeof callback === 'function') callback();
callback && callback();
}

@@ -544,5 +569,5 @@

// do not _schedule when there are timeouts in progress
// this can be the case with async timeouts in discrete time.
// this can be the case with async timeouts in non-paced mode.
// _schedule will be executed again when all async timeouts are finished.
if (rate === DISCRETE && Object.keys(current).length > 0) {
if (!paced && Object.keys(current).length > 0) {
return;

@@ -563,8 +588,8 @@ }

var delay = time - timer.now();
var realDelay = (rate === DISCRETE) ? 0 : delay / rate;
var realDelay = paced ? delay / rate : 0;
function onTimeout() {
// when running in discrete time, update the hyperTime to the time
// of the current event
if (rate === DISCRETE) {
// when running in non-paced mode, update the hyperTime to
// adjust the time of the current event
if (!paced) {
hyperTime = (time > hyperTime && isFinite(time)) ? time : hyperTime;

@@ -578,4 +603,12 @@ }

// execute all expired timeouts
if (rate === DISCRETE) {
// in discrete time, we execute all expired timeouts serially,
if (paced) {
// in paced mode, we fire all timeouts in parallel,
// and don't await their completion (they can do async operations)
expired.forEach(_execTimeout);
// schedule the next round
_schedule();
}
else {
// in non-paced mode, we execute all expired timeouts serially,
// and wait for their completion in order to guarantee deterministic

@@ -595,10 +628,2 @@ // order of execution

}
else {
// in continuous time, we fire all timeouts in parallel,
// and don't await their completion (they can do async operations)
expired.forEach(_execTimeout);
// schedule the next round
_schedule();
}
}

@@ -618,5 +643,4 @@

timer.config(options); // apply options
timer.setTime(util.systemNow()); // set time as current real time
timer.continue(); // start the timer
timer.config(options); // apply options
timer.continue(); // start the timer

@@ -671,2 +695,2 @@ return timer;

/******/ ])
})
});

@@ -5,10 +5,11 @@ /**

*
* A timer running faster or slower than real-time, and in continuous or
* discrete time.
* Time control for simulations.
*
* @version 1.1.1
* @date 2014-10-21
* Run a timer at a faster or slower pace than real-time, or run discrete events.
*
* @version 2.0.0
* @date 2015-02-19
*
* @license
* Copyright (C) 2014 Almende B.V., http://almende.com
* Copyright (C) 2014-2015 Almende B.V., http://almende.com
*

@@ -27,3 +28,3 @@ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

*/
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):"object"==typeof exports?exports.hypertimer=t():e.hypertimer=t()}(this,function(){return function(e){function t(n){if(r[n])return r[n].exports;var i=r[n]={exports:{},id:n,loaded:!1};return e[n].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var r={};return t.m=e,t.c=r,t.p="",t(0)}([function(e,t,r){e.exports=r(1)},function(e,t,r){function n(e){function t(e){if(p.length>0){for(var t=p.length-1;t>=0&&p[t].time>e.time;)t--;p.splice(t+1,0,e)}else p.push(e)}function r(e,r){function n(){e.type===o.INTERVAL&&d[e.id]&&(e.occurrence++,e.time=e.firstTime+e.occurrence*e.interval,t(e)),delete d[e.id],"function"==typeof r&&r()}d[e.id]=e;try{0==e.callback.length?(e.callback(),n()):e.callback(n)}catch(i){n()}}function n(e){for(var t=0;t<p.length&&(p[t].time<=e||!isFinite(p[t].time));)t++;var r=p.splice(0,t);return 0==f&&i.shuffle(r),r}function a(){function e(){function e(){var n=t.shift();n?r(n,e):a()}c===u&&(m=i>m&&isFinite(i)?i:m);var t=n(i);c===u?e():(t.forEach(r),a())}if(!(c===u&&Object.keys(d).length>0)){var t=p[0];if(v&&(clearTimeout(v),v=null),s&&t){var i=t.time,o=i-b.now(),f=c===u?0:o/c;v=setTimeout(e,Math.round(f))}}}var c=1,f=!0,s=!1,l=null,m=null,p=[],d={},v=null,T=0,b={};return b.config=function(e){if(e){if("rate"in e){var t=e.rate===u?u:Number(e.rate);if(t!==u&&(isNaN(t)||0>=t))throw new TypeError('rate must be a positive number or the string "discrete"');m=b.now(),l=i.systemNow(),c=t}"deterministic"in e&&(f=e.deterministic?!0:!1)}return a(),{rate:c,deterministic:f}},b.setTime=function(e){if(e instanceof Date)m=e.valueOf();else{var t=Number(e);if(isNaN(t))throw new TypeError("time must be a Date or number");m=t}a()},b.now=function(){if(c===u)return m;if(s){var e=i.systemNow()-l,t=e*c;return m+t}return m},b["continue"]=function(){l=i.systemNow(),s=!0,a()},b.pause=function(){m=b.now(),l=null,s=!1,a()},b.getTime=function(){return new Date(b.now())},b.valueOf=b.getTime,b.toString=function(){return b.getTime().toString()},b.setTimeout=function(e,r){var n=T++,i=b.now()+r;if(isNaN(i))throw new TypeError("delay must be a number");return t({id:n,type:o.TIMEOUT,time:i,callback:e}),a(),n},b.setTrigger=function(e,r){var n=T++,i=Number(r);if(isNaN(i))throw new TypeError("time must be a Date or number");return t({id:n,type:o.TRIGGER,time:i,callback:e}),a(),n},b.setInterval=function(e,r,n){var i=T++,u=Number(r);if(isNaN(u))throw new TypeError("interval must be a number");(0>u||!isFinite(u))&&(u=0);var c;if(void 0!=n){if(c=Number(n),isNaN(c))throw new TypeError("firstTime must be a Date or number")}else c=b.now()+u;return t({id:i,type:o.INTERVAL,interval:u,time:c,firstTime:c,occurrence:0,callback:e}),a(),i},b.clearTimeout=function(e){if(d[e])return void delete d[e];for(var t=0;t<p.length;t++)if(p[t].id===e){p.splice(t,1),a();break}},b.clearTrigger=b.clearTimeout,b.clearInterval=b.clearTimeout,b.list=function(){return p.map(function(e){return e.id})},b.clear=function(){d={},p=[],a()},Object.defineProperty(b,"running",{get:function(){return s}}),b.config(e),b.setTime(i.systemNow()),b.continue(),b}var i=r(2),o={TIMEOUT:0,INTERVAL:1,TRIGGER:2},u="discrete";e.exports=n},function(e,t){t.systemNow="function"==typeof Date.now?function(){return Date.now()}:function(){return(new Date).valueOf()},t.shuffle=function(e){for(var t,r,n=e.length;n;t=Math.floor(Math.random()*n),r=e[--n],e[n]=e[t],e[t]=r);return e}}])});
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):"object"==typeof exports?exports.hypertimer=t():e.hypertimer=t()}(this,function(){return function(e){function t(n){if(r[n])return r[n].exports;var i=r[n]={exports:{},id:n,loaded:!1};return e[n].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var r={};return t.m=e,t.c=r,t.p="",t(0)}([function(e,t,r){e.exports=r(1)},function(e,t,r){function n(e){function t(e){if(d.length>0){for(var t=d.length-1;t>=0&&d[t].time>e.time;)t--;d.splice(t+1,0,e)}else d.push(e)}function r(e,r){function n(){e.type===o.INTERVAL&&v[e.id]&&(e.occurrence++,e.time=e.firstTime+e.occurrence*e.interval,t(e)),delete v[e.id],r&&r()}v[e.id]=e;try{0==e.callback.length?(e.callback(),n()):e.callback(n)}catch(i){n()}}function n(e){for(var t=0;t<d.length&&(d[t].time<=e||!isFinite(d[t].time));)t++;var r=d.splice(0,t);return 0==f&&i.shuffle(r),r}function u(){function e(){function e(){var n=t.shift();n?r(n,e):u()}a||(p=i>p&&isFinite(i)?i:p);var t=n(i);a?(t.forEach(r),u()):e()}if(a||!(Object.keys(v).length>0)){var t=d[0];if(T&&(clearTimeout(T),T=null),m&&t){var i=t.time,o=i-w.now(),f=a?o/c:0;T=setTimeout(e,Math.round(f))}}}var a=!0,c=1,f=!0,l=null,m=!1,s=null,p=i.systemNow(),d=[],v={},T=null,b=0,w={};return w.config=function(e){if(e){if("deterministic"in e&&(f=e.deterministic?!0:!1),"paced"in e&&(a=e.paced?!0:!1),"time"in e){if(e.time instanceof Date)p=e.time.valueOf();else{var t=Number(e.time);if(isNaN(t))throw new TypeError("Invalid time "+JSON.stringify(e.time)+". Time must be a Date or number");p=t}l=e.time}if("rate"in e){var r=Number(e.rate);if(isNaN(r)||0>=r)throw new TypeError("Invalid rate "+JSON.stringify(e.rate)+". Rate must be a positive number");p=w.now(),s=i.systemNow(),c=r}}return u(),{paced:a,rate:c,deterministic:f,time:l}},w.now=function(){if(a){if(m){var e=i.systemNow()-s,t=e*c;return p+t}return p}return p},w["continue"]=function(){s=i.systemNow(),m=!0,u()},w.pause=function(){p=w.now(),s=null,m=!1,u()},w.getTime=function(){return new Date(w.now())},w.valueOf=w.getTime,w.toString=function(){return w.getTime().toString()},w.setTimeout=function(e,r){var n=b++,i=w.now()+r;if(isNaN(i))throw new TypeError("delay must be a number");return t({id:n,type:o.TIMEOUT,time:i,callback:e}),u(),n},w.setTrigger=function(e,r){var n=b++,i=Number(r);if(isNaN(i))throw new TypeError("time must be a Date or number");return t({id:n,type:o.TRIGGER,time:i,callback:e}),u(),n},w.setInterval=function(e,r,n){var i=b++,a=Number(r);if(isNaN(a))throw new TypeError("interval must be a number");(0>a||!isFinite(a))&&(a=0);var c;if(void 0!=n){if(c=Number(n),isNaN(c))throw new TypeError("firstTime must be a Date or number")}else c=w.now()+a;return t({id:i,type:o.INTERVAL,interval:a,time:c,firstTime:c,occurrence:0,callback:e}),u(),i},w.clearTimeout=function(e){if(v[e])return void delete v[e];for(var t=0;t<d.length;t++)if(d[t].id===e){d.splice(t,1),u();break}},w.clearTrigger=w.clearTimeout,w.clearInterval=w.clearTimeout,w.list=function(){return d.map(function(e){return e.id})},w.clear=function(){v={},d=[],u()},Object.defineProperty(w,"running",{get:function(){return m}}),w.config(e),w["continue"](),w}var i=r(2),o={TIMEOUT:0,INTERVAL:1,TRIGGER:2};e.exports=n},function(e,t){t.systemNow="function"==typeof Date.now?function(){return Date.now()}:function(){return(new Date).valueOf()},t.shuffle=function(e){for(var t,r,n=e.length;n;t=Math.floor(Math.random()*n),r=e[--n],e[n]=e[t],e[t]=r);return e}}])});
//# sourceMappingURL=hypertimer.map
var hypertimer = require('../index');
// create a hypertimer
var timer = hypertimer();
// create a hypertimer with the initial time at 14st of February 2015
var timer = hypertimer({
time: new Date(2015, 1, 14, 12, 0, 0)
});
// set the time at 1st of January 2050
timer.setTime(new Date(2050, 0, 1, 12, 0, 0));
// get the time as Date
console.log(timer.getTime()); // Returns a date, Sat Feb 14 2015 12:00:00 GMT+0100 (CET)
// change the time to the 1st of January 2050
timer.config({time: new Date(2050, 0, 1, 12, 0, 0)});
// get the time as Date

@@ -13,2 +18,2 @@ console.log(timer.getTime()); // Returns a date, Sat Jan 01 2050 12:00:00 GMT+0100 (CET)

// get the time as timestamp
console.log(timer.now()); // Returns a number, approximately 2524647600000
console.log(timer.now()); // Returns a number, 2524647600000
var hypertimer = require('../index');
// create a hypertimer running ten times faster than real-time
var timer = hypertimer({rate: 10});
// start the timer at 1st of January 2050
timer.setTime(new Date(2050, 0, 1, 12, 0, 0));
var timer = hypertimer({
rate: 10,
time: new Date(2050, 0, 1, 12, 0, 0)
});

@@ -35,2 +36,2 @@ console.log('start', timer.getTime()); // Sat Jan 01 2050 12:00:00 GMT+0100 (CET)

}
}, interval, firstTime);
}, interval, firstTime);
# History
## 2015-02-19, version 2.0.0
- Added a new option `paced: boolean` to distinguish running in paced mode
or in unpaced (as fast as possible) mode. Option `rate` can now only be
a number and is only applicable when `paced: true`.
- Removed method `setTime`, time can be configured on construction or with
the function `config({time: ...})`.
## 2014-10-21, version 1.1.1

@@ -5,0 +14,0 @@

@@ -5,5 +5,6 @@ /**

*
* A timer running faster or slower than real-time, and in continuous or
* discrete time.
* Time control for simulations.
*
* Run a timer at a faster or slower pace than real-time, or run discrete events.
*
* @version @@version

@@ -13,3 +14,3 @@ * @date @@date

* @license
* Copyright (C) 2014 Almende B.V., http://almende.com
* Copyright (C) 2014-2015 Almende B.V., http://almende.com
*

@@ -16,0 +17,0 @@ * Licensed under the Apache License, Version 2.0 (the "License"); you may not

@@ -10,31 +10,43 @@ var util = require('./util');

var DISCRETE = 'discrete';
/**
* Create a new hypertimer
* @param {Object} [options] The following options are available:
* rate: number | 'discrete'
* The rate of speed of hyper time with
* respect to real-time in milliseconds
* per millisecond. Rate must be a
* positive number, or 'discrete' to
* run in discrete time (jumping from
* event to event). By default, rate is 1.
* deterministic: boolean
* If true (default), simultaneous events
* are executed in a deterministic order.
* paced: boolean
* Mode for pacing of time. When paced,
* the time proceeds at a continuous,
* configurable rate, useful for
* animation purposes. When unpaced, the
* time jumps immediately from scheduled
* event to the next scheduled event.
* rate: number
* The rate of progress of time with
* respect to real-time. Rate must be a
* positive number, and is 1 by default.
* For example when 2, the time of the
* hypertimer runs twice as fast as
* real-time.
* Only applicable when option paced=true.
* time: number | Date
* Set a simulation time. If not provided,
* The timer is instantiated with the
* current system time.
*/
function hypertimer(options) {
// options
var paced = true;
var rate = 1; // number of milliseconds per milliseconds
var deterministic = true; // run simultaneous events in a deterministic order
var configuredTime = null;
// properties
var running = false; // true when running
var realTime = null; // timestamp. the moment in real-time when hyperTime was set
var hyperTime = null; // timestamp. the start time in hyper-time
var timeouts = []; // array with all running timeouts
var current = {}; // the timeouts currently in progress (callback is being executed)
var timeoutId = null; // currently running timer
var idSeq = 0; // counter for unique timeout id's
var running = false; // true when running
var realTime = null; // timestamp. the moment in real-time when hyperTime was set
var hyperTime = util.systemNow(); // timestamp. the start time in hyper-time
var timeouts = []; // array with all running timeouts
var current = {}; // the timeouts currently in progress (callback is being executed)
var timeoutId = null; // currently running timer
var idSeq = 0; // counter for unique timeout id's

@@ -48,12 +60,22 @@ // exported timer object with public functions and variables

* @param {Object} [options] The following options are available:
* rate: number | 'discrete'
* The rate of speed of hyper time with
* respect to real-time in milliseconds
* per millisecond. Rate must be a
* positive number, or 'discrete' to
* run in discrete time (jumping from
* event to event). By default, rate is 1.
* deterministic: boolean
* If true (default), simultaneous events
* are executed in a deterministic order.
* paced: boolean
* Mode for pacing of time. When paced,
* the time proceeds at a continuous,
* configurable rate, useful for
* animation purposes. When unpaced, the
* time jumps immediately from scheduled
* event to the next scheduled event.
* rate: number
* The rate of progress of time with
* respect to real-time. Rate must be a
* positive number, and is 1 by default.
* For example when 2, the time of the
* hypertimer runs twice as fast as
* real-time.
* Only applicable when option paced=true.
* time: number | Date
* Set a simulation time.
* @return {Object} Returns the applied configuration

@@ -63,7 +85,31 @@ */

if (options) {
if ('deterministic' in options) {
deterministic = options.deterministic ? true : false;
}
if ('paced' in options) {
paced = options.paced ? true : false;
}
// important: apply time before rate
if ('time' in options) {
if (options.time instanceof Date) {
hyperTime = options.time.valueOf();
}
else {
var newTime = Number(options.time);
if (isNaN(newTime)) {
throw new TypeError('Invalid time ' + JSON.stringify(options.time) + '. Time must be a Date or number');
}
hyperTime = newTime;
}
configuredTime = options.time;
}
if ('rate' in options) {
var newRate = (options.rate === DISCRETE) ? DISCRETE : Number(options.rate);
if (newRate !== DISCRETE && (isNaN(newRate) || newRate <= 0)) {
throw new TypeError('rate must be a positive number or the string "discrete"');
var newRate = Number(options.rate);
if (isNaN(newRate) || newRate <= 0) {
throw new TypeError('Invalid rate ' + JSON.stringify(options.rate) + '. Rate must be a positive number');
}
hyperTime = timer.now();

@@ -73,5 +119,2 @@ realTime = util.systemNow();

}
if ('deterministic' in options) {
deterministic = options.deterministic ? true : false;
}
}

@@ -84,4 +127,6 @@

return {
paced: paced,
rate: rate,
deterministic: deterministic
deterministic: deterministic,
time: configuredTime
};

@@ -91,22 +136,2 @@ };

/**
* Set the time of the timer. To get the current time, use getTime() or now().
* @param {number | Date} time The time in hyper-time.
*/
timer.setTime = function (time) {
if (time instanceof Date) {
hyperTime = time.valueOf();
}
else {
var newTime = Number(time);
if (isNaN(newTime)) {
throw new TypeError('time must be a Date or number');
}
hyperTime = newTime;
}
// reschedule running timeouts
_schedule();
};
/**
* Returns the current time of the timer as a number.

@@ -117,6 +142,3 @@ * See also getTime().

timer.now = function () {
if (rate === DISCRETE) {
return hyperTime;
}
else {
if (paced) {
if (running) {

@@ -132,2 +154,5 @@ // TODO: implement performance.now() / process.hrtime(time) for high precision calculation of time interval

}
else {
return hyperTime;
}
};

@@ -163,3 +188,2 @@

*/
// rename to getTime
timer.getTime = function() {

@@ -406,3 +430,3 @@ return new Date(timer.now());

if (typeof callback === 'function') callback();
callback && callback();
}

@@ -455,5 +479,5 @@

// do not _schedule when there are timeouts in progress
// this can be the case with async timeouts in discrete time.
// this can be the case with async timeouts in non-paced mode.
// _schedule will be executed again when all async timeouts are finished.
if (rate === DISCRETE && Object.keys(current).length > 0) {
if (!paced && Object.keys(current).length > 0) {
return;

@@ -474,8 +498,8 @@ }

var delay = time - timer.now();
var realDelay = (rate === DISCRETE) ? 0 : delay / rate;
var realDelay = paced ? delay / rate : 0;
function onTimeout() {
// when running in discrete time, update the hyperTime to the time
// of the current event
if (rate === DISCRETE) {
// when running in non-paced mode, update the hyperTime to
// adjust the time of the current event
if (!paced) {
hyperTime = (time > hyperTime && isFinite(time)) ? time : hyperTime;

@@ -489,4 +513,12 @@ }

// execute all expired timeouts
if (rate === DISCRETE) {
// in discrete time, we execute all expired timeouts serially,
if (paced) {
// in paced mode, we fire all timeouts in parallel,
// and don't await their completion (they can do async operations)
expired.forEach(_execTimeout);
// schedule the next round
_schedule();
}
else {
// in non-paced mode, we execute all expired timeouts serially,
// and wait for their completion in order to guarantee deterministic

@@ -506,10 +538,2 @@ // order of execution

}
else {
// in continuous time, we fire all timeouts in parallel,
// and don't await their completion (they can do async operations)
expired.forEach(_execTimeout);
// schedule the next round
_schedule();
}
}

@@ -529,5 +553,4 @@

timer.config(options); // apply options
timer.setTime(util.systemNow()); // set time as current real time
timer.continue(); // start the timer
timer.config(options); // apply options
timer.continue(); // start the timer

@@ -534,0 +557,0 @@ return timer;

{
"name": "hypertimer",
"version": "1.1.1",
"version": "2.0.0",
"description": "Time control for simulations",

@@ -23,12 +23,10 @@ "author": "Jos de Jong <wjosdejong@gmail.com> (https://github.com/josdejong)",

"devDependencies": {
"async": "^0.9.0",
"browserify": "^4.2.0",
"gulp": "^3.8.6",
"gulp-util": "^2.2.20",
"istanbul": "^0.2.6",
"mocha": "^1.18.2",
"browserify": "^8.1.3",
"gulp": "^3.8.11",
"gulp-util": "^3.0.3",
"istanbul": "^0.3.6",
"mocha": "^2.1.0",
"seed-random": "^2.2.0",
"uglify-js": "^2.4.15",
"uglifyjs": "^2.3.6",
"webpack": "^1.3.1-beta8"
"uglify-js": "^2.4.16",
"webpack": "^1.5.3"
},

@@ -35,0 +33,0 @@ "scripts": {

hypertimer
==========
Hypertimer offers time control for simulations. With simulations, it's important to be able to manipulate the time. Typically, simulations are run in discrete time, jumping from event to event in a deterministic manner. And afterwards, a simulation can be played back in continuous time at a faster or slower pace than real-time (depending on the time scale of the simulation). Hypertimer makes it possible to run in [hypertime](http://en.wikipedia.org/wiki/Hypertime) or in discrete time (a [discrete event simulation](http://en.wikipedia.org/wiki/Discrete_event_simulation)).
Hypertimer offers time control for simulations and animations. Hypertimer can be used to:
- Run in an unpaced mode for *simulations*: the time jumps from scheduled event to the next scheduled event, unrolling all events as fast as possible.
- Run in a paced mode for *animations* or *real-time* applications: the time proceeds at a continuous, configurable rate. Time can run at a faster or slower pace than real-time, and can run in the past, current, or future.
Hypertimer offers basic functionality to control time:
- Get and set the time using functions `getTime()`, `setTime()`, and `now()`.
- Configure pacing, rate, and time on construction or via the function `config()`.
- Get simulated time using functions `getTime()` or `now()`.
- Schedule events using functions `setTimeout()`, `setInterval()`, and `setTrigger()`.
These functions are compatible with JavaScript's built-in functions `Date.now()`, `setTimeout()`, and `setInterval()`, but there is an important difference: they can run at a different moment in time and at a different rate.
These functions are compatible with JavaScript's built-in functions `Date.now()`, `setTimeout()`, and `setInterval()`, with the difference that they use a simulated time rather than the system time.
Hypertimer enables writing code which can be used interchangeably in simulations as well as in real, online application. For example, a processs could predict its future state by running a simulation of itself, given a current state, its own behavior, and a model of the surrounding world.
Hypertimer enables writing code which can be used interchangeably in simulations as well as for real-time applications. For example, a process could predict its future state by running a simulation of itself, given a current state, its own behavior, and a model of the surrounding world.

@@ -35,4 +39,6 @@ Hypertimer runs on node.js and on any modern browser (Chrome, FireFox, Opera, Safari, IE9+).

var timer = hypertimer({rate: 1});
timer.setTime(new Date(2014, 0, 1));
var timer = hypertimer({
rate: 1,
time: new Date(2014, 0, 1)
});
```

@@ -50,4 +56,6 @@

<script>
var timer = hypertimer({rate: 1});
timer.setTime(new Date(2014, 0, 1));
var timer = hypertimer({
rate: 1,
time: new Date(2014, 0, 1)
});
</script>

@@ -62,4 +70,9 @@ </body>

A hypertimer can run in continuous or discrete time, and can run faster or slower than real-time. The speed of a hypertimer can be configured via the option `rate`, which can be a positive number (to run in continuous time) or the string `'discrete'` (to run in discrete time).
A hypertimer can run in two modes:
- paced: time proceeds at a continuous, configurable rate.
- unpaced: run as fast as possible, jumping from event to event.
Hypertimer as configuration options to set pacing, rate, time, and determinism of the timer.
```js

@@ -72,3 +85,3 @@ // create a hypertimer running ten times faster than real-time

// create a hypertimer with the default rate (1 by default)
// create a hypertimer with the default rate (1 by default, same speed as real-time)
var timer2 = hypertimer();

@@ -79,8 +92,8 @@

// create a hypertimer running in discrete time (time will jump
// from scheduled event to scheduled event)
var timer3 = hypertimer({rate: 'discrete'});
// create a hypertimer running discrete events as fast as possible (unpaced)
// (time will jump from scheduled event to scheduled event)
var timer3 = hypertimer({paced: false});
// create a hypertimer running in discrete time and non-deterministic behavior
var timer4 = hypertimer({rate: 'discrete', deterministic: false});
// create a hypertimer running discrete events with non-deterministic behavior
var timer4 = hypertimer({paced: false, deterministic: false});
```

@@ -93,6 +106,9 @@

```js
var timer = hypertimer();
// create a hypertimer with the initial time at 14st of February 2015
var timer = hypertimer({
time: new Date(2015, 1, 14, 12, 0, 0)
});
// set the time at 1st of January 2050
timer.setTime(new Date(2050, 0, 1, 12, 0, 0));
// change the time to the 1st of January 2050
timer.config({time: new Date(2050, 0, 1, 12, 0, 0)});

@@ -138,3 +154,3 @@ // get the time as Date

On creation, the trigger time of the events is calculated from the `delay`, `interval`, and/or `firstTime`, and the event is scheduled to occur at that moment in time. When the time of the hypertimer is changed via `setTime()`, trigger time of running timeouts will not be adjusted.
On creation, the trigger time of the events is calculated from the `delay`, `interval`, and/or `firstTime`, and the event is scheduled to occur at that moment in time. When the time of the hypertimer is changed via configuration, trigger time of running timeouts will not be adjusted.

@@ -144,7 +160,8 @@ The functions `setTimeout()`, `setTrigger()`, and `setInterval()` return a timeout id, which can be used to cancel a timeout using the functions `clearTimeout()`, `clearTrigger()`, and `clearInterval()` respectively. To cancel all scheduled events at once, the function `clear()` can be called.

```js
// create a hypertimer running ten times faster than real-time
var timer = hypertimer({rate: 10});
// create a hypertimer running ten times faster than real-time,
// start the timer at 1st of January 2050
timer.setTime(new Date(2050, 0, 1, 12, 0, 0));
var timer = hypertimer({
rate: 10,
time: new Date(2050, 0, 1, 12, 0, 0)
});

@@ -180,11 +197,13 @@ console.log('start', timer.getTime()); // start Sat Jan 01 2050 12:00:00 GMT+0100 (CET)

### Discrete time
### Pacing
When running in continuous time (rate is a positive number), scheduled events are triggered at their scheduled time (in hyper-time). When running a simulation, there is no need to wait and do nothing between scheduled events. It is much faster to jump from event to event in discrete time. To create a hypertimer running in discrete time, configure rate as `'discrete'`. Hypertimer ensures that all scheduled events are executed in a deterministic order.
When running in paced mode, time proceeds at a continuous, configurable rate. Between events, the timer is just waiting until the clock reaches the time of the next event. This is needed for animations, but for simulations this is just wasted time (assuming that the state of the system does not change between events). When running in unpaced mode, the timer will jump from event to the first next event, as fast as possible.
In the example below, the application will immediately output 'done!' and not after a delay of 10 seconds, because the timer is running in discrete time and immediately jumps to the first next event.
To run in unpaced mode, configure hypertimer with `paced: false`. Hypertimer ensures that all scheduled events are executed in a deterministic order by default. When non-deterministic order is desired, the configuration option `deterministic` can be set to `false`.
In the example below, the application will immediately output 'done!' and not after a delay of 10 seconds, because the timer is running in unpaced mode and immediately jumps to the first next event.
```js
// create a hypertimer running in discrete time,
var timer = hypertimer({rate: 'discrete'});
// create a hypertimer running discrete events
var timer = hypertimer({paced: false});

@@ -205,3 +224,3 @@ var delay = 10000;

When performing asynchronous tasks inside a timeout, one needs to create an asynchronous timeout, which calls `done()` when all asynchronous actions are finished. This is required in order to guarantee a deterministic order of execution. When non-deterministic order is desired, the configuration option `deterministic` can be set to `false`.
When performing asynchronous tasks inside a timeout, one needs to create an asynchronous timeout, which calls `done()` when all asynchronous actions are finished. This is required in order to guarantee a deterministic order of execution.

@@ -218,5 +237,5 @@ ```js

```js
// create a hypertimer running in discrete time,
// jumping from scheduled event to scheduled event.
var timer = hypertimer({rate: 'discrete'});
// create a hypertimer running discrete events,
// jumping from event to the next event.
var timer = hypertimer({paced: false});

@@ -234,3 +253,3 @@ // create an asynchronous timeout, having a callback parameter done

// once we are done with our asynchronous event, call done()
// so the hypertimer knows he can continue with a next event.
// so the hypertimer knows it can continue with the next event.
done();

@@ -261,6 +280,8 @@ });

Name | Type | Default | Description
------------- | -------------------- | ------- | -----------
rate | number or 'discrete' | 1 | The rate (in milliseconds per millisecond) at which the timer runs, with respect to real-time speed. Can be a positive number, or the string 'discrete' to run in discrete time.
deterministic | boolean | true | If true, (default) events taking place at the same time are executed in a deterministic order: in the same order they where created. If false, they are executed in a randomized order.
Name | Type | Default | Description
------------- | ----------------------------- | --------- | -----------
deterministic | boolean | `true` | If true, (default) events taking place at the same time are executed in a deterministic order: in the same order they where created. If false, they are executed in a randomized order.
paced | boolean | `true` | Mode for pacing of time. When paced, the time proceeds at a continuous, configurable rate, useful for animation purposes. When unpaced, the time jumps immediately from scheduled event to the next scheduled event.
rate | number | 1 | The rate of progress of time with respect to real-time. Rate must be a positive number. For example when 2, the time of the hypertimer runs twice as fast as real-time. Only applicable when option paced is true.
time | number or Date | `null` | Sets the simulation time. If not configured, a hypertimer is instantiated with the system time.

@@ -275,84 +296,116 @@ Example:

- `running`
True when the timer is running, false when paused. See also functions `pause()` and `continue()`.
- `running`
True when the timer is running, false when paused. See also functions `pause()` and `continue()`.
### Methods
- **`clear()`**
Clear all running timeouts.
- **`clear()`**
- **`clearTimeout(timeoutId: number)`**
Cancel a timeout.
Clear all running timeouts.
- **`clearInterval(intervalId: number)`**
Cancel an interval.
- **`clearTimeout(timeoutId: number)`**
- **`clearTrigger(triggerId: number)`**
Cancel a trigger.
Cancel a timeout.
- **`config([options: Object]): Object`**
Change the configuration options of the hypertimer, and/or retrieve the current configuration. Available options:
- **`clearInterval(intervalId: number)`**
- `rate: number | 'discrete'`
The rate (in milliseconds per millisecond) at which the timer runs, with respect to real-time speed. Can be a positive number, or 'discrete' to run in discrete time. By default, rate is 1.
- `deterministic: boolean`
If true (default), events taking place at the same time are executed in a deterministic order: in the same order they where created. If false, they are executed in a randomized order.
Cancel an interval.
- **`continue()`**
Continue the timer when paused. The state of the timer can be retrieved via the property `running`. See also `pause()`.
- **`clearTrigger(triggerId: number)`**
- **`getTime(): Date`**
Returns the current time of the timer as Date. See also `now()`.
The time can be set using `setTime(time)`.
Cancel a trigger.
- **`list()`**
Returns a list with the id's of all running timeouts.
- **`config([options: Object]): Object`**
Change the configuration options of the hypertimer, and/or retrieve the current configuration. Available options:
- `deterministic: boolean`
If true (default), events taking place at the same time are executed in a deterministic order: in the same order they where created. If false, they are executed in a randomized order.
- `paced: boolean`
Mode for pacing of time. When paced (default), the time proceeds at a continuous, configurable rate. When unpaced, the time jumps immediately from scheduled event to the next scheduled event.
- `rate: number`
The rate of progress of time with respect to real-time. Rate must be a positive number, and is 1 by default. For example when 2, the time of the hypertimer runs twice as fast as real-time. Only applicable when option paced is true.
- `time: number | Date`
Set a simulation time.
- **`continue()`**
Continue the timer when paused. The state of the timer can be retrieved via the property `running`. See also `pause()`.
- **`getTime(): Date`**
Returns the current time of the hypertimer as Date. See also `now()`.
The time can be set using `config({time: ...})`.
- **`list()`**
Returns a list with the id's of all running timeouts.
- **`now() : number`**
Returns the current time of the timer as a number. See also `getTime()`.
- **`now() : number`**
- **`pause()`**
Pause the timer. The state of the timer can be retrieved via the property `running`. See also `continue()`.
Returns the current time of the timer as a number. See also `getTime()`.
- **`setInterval(callback: Function, interval: number [, firstTime: Date | number])`**
Trigger a callback every interval. Optionally, a start date can be provided
to specify the first time the callback must be triggered. The function returns an intervalId which can be used to cancel the trigger using `clearInterval()`. See also `setTimeout` and `setTrigger`. Parameters:
- **`pause()`**
Pause the timer. The state of the timer can be retrieved via the property `running`. See also `continue()`.
- **`setInterval(callback: Function, interval: number [, firstTime: Date | number])`**
Trigger a callback every interval. Optionally, a start date can be provided
to specify the first time the callback must be triggered. The function returns an intervalId which can be used to cancel the trigger using `clearInterval()`. See also `setTimeout` and `setTrigger`. Parameters:
- `callback: Function`
Function executed when delay is exceeded.
- `interval: number`
Interval in milliseconds. When interval is smaller than zero or is infinity, the interval will be set to zero and triggered with a maximum rate.
- `[firstTime: Date | number]`
An optional absolute moment in time (Date) when the callback will be triggered the first time. By default, `firstTime = now() + interval`.
- `callback: Function`
- **`setTime(time: number | Date)`**
Set the current time of the timer. Can be a Date or a timestamp. To get the current time, use `getTime()` or `now()`.
Function executed when delay is exceeded.
- **`setTimeout(callback: Function, delay: number) : number`**
Set a timeout, which is triggered when the timeout occurs in hyper-time. See also `setTrigger` and `setInterval`. The function returns a timeoutId, which can be used to cancel the timeout using `clearTimeout(timeoutId)`. The parameters are:
- `interval: number`
Interval in milliseconds. When interval is smaller than zero or is infinity, the interval will be set to zero and triggered with a maximum rate.
- `[firstTime: Date | number]`
An optional absolute moment in time (Date) when the callback will be triggered the first time. By default, `firstTime = now() + interval`.
- **`setTimeout(callback: Function, delay: number) : number`**
Set a timeout, which is triggered when the timeout occurs in hyper-time. See also `setTrigger` and `setInterval`. The function returns a timeoutId, which can be used to cancel the timeout using `clearTimeout(timeoutId)`. The parameters are:
- `callback: Function`
Function executed when the delay is exceeded
- `delay: number`
The delay in milliseconds. When the delay is smaller or equal to zero, the callback is triggered immediately.
- `callback: Function`
- **`setTrigger(callback: Function, time: Date | number) : number`**
Set a trigger, which is triggered when the timeout occurs in hyper-time. See also `getTimeout`. The function returns a triggerId which can be used to cancel the trigger using `clearTrigger()`. The parameters are:
Function executed when the delay is exceeded
- `callback: Function`
Function executed when delay is exceeded.
- `delay: number`
The delay in milliseconds. When the delay is smaller or equal to zero, the callback is triggered immediately.
- **`setTrigger(callback: Function, time: Date | number) : number`**
Set a trigger, which is triggered when the timeout occurs in hyper-time. See also `getTimeout`. The function returns a triggerId which can be used to cancel the trigger using `clearTrigger()`. The parameters are:
- `callback: Function`
Function executed when delay is exceeded.
- `time: Date | number`
An absolute moment in time (Date) when the callback will be triggered. When the date is a Date in the past, the callback is triggered immediately.
- `time: Date | number`
An absolute moment in time (Date) when the callback will be triggered. When the date is a Date in the past, the callback is triggered immediately.
- **`toString() : String`**
Return a string representation of the current hyper-time, equal to `timer.getTime().toString()`.
- **`toString() : String`**
Return a string representation of the current hyper-time, equal to `timer.getTime().toString()`.
- **`valueOf() : Date`**
Get the value of the hypertimer, returns the current time of the timer as Date.
- **`valueOf() : Date`**
Get the value of the hypertimer, returns the current time of the timer as Date.
## Examples

@@ -416,3 +469,3 @@

Copyright (C) 2014 Almende B.V., http://almende.com
Copyright (C) 2014-2015 Almende B.V., http://almende.com

@@ -432,1 +485,2 @@ Licensed under the Apache License, Version 2.0 (the "License");

@@ -39,3 +39,3 @@ // NOTE: all timeouts should have time differences of at least 50ms to be

var timer = hypertimer();
assert.deepEqual(timer.config(), {rate: 1, deterministic: true});
assert.deepEqual(timer.config(), {paced: true, rate: 1, deterministic: true, time: null});
});

@@ -64,3 +64,3 @@

var timer = hypertimer({rate: 1});
timer.setTime(new Date(2050,0,1,12,0,0,0));
timer.config({time: new Date(2050,0,1,12,0,0,0)});
approx(timer.getTime(), new Date(2050,0,1,12,0,0,0));

@@ -76,3 +76,3 @@

hypertimer({rate: 'bla'});
}, /TypeError: rate must be a positive number/);
}, /TypeError: Invalid rate "bla". Rate must be a positive number/);
});

@@ -84,4 +84,6 @@

it ('should set the current hyper-time from a Date', function () {
var timer = hypertimer({rate: 1});
timer.setTime(new Date(2050, 0, 1));
var timer = hypertimer({
rate: 1,
time: new Date(2050, 0, 1)
});
approx(timer.getTime(), new Date(2050, 0, 1));

@@ -91,4 +93,6 @@ });

it ('should set the current hyper-time from a number', function () {
var timer = hypertimer({rate: 1});
timer.setTime(new Date(2050, 0, 1).valueOf());
var timer = hypertimer({
rate: 1,
time: new Date(2050, 0, 1).valueOf()
});
approx(timer.getTime(), new Date(2050, 0, 1));

@@ -99,4 +103,4 @@ });

var timer = hypertimer({rate: 1});
assert.throws(function () {timer.setTime('bla')}, /time must be a Date or number/);
assert.throws(function () {timer.setTime({})}, /time must be a Date or number/);
assert.throws(function () {timer.config({time:'bla'})}, /Invalid time "bla". Time must be a Date or number/);
assert.throws(function () {timer.config({time:{}})}, /Invalid time \{}. Time must be a Date or number/);
});

@@ -157,3 +161,3 @@

timer.setTime(d);
timer.config({time: d});
approx(timer.getTime(), d);

@@ -166,3 +170,3 @@ });

timer.setTime(d);
timer.config({time: d});
approx(timer.getTime(), d);

@@ -253,4 +257,2 @@

// TODO:
it('should continue scheduling when the first timeout is cancelled', function (done) {

@@ -303,4 +305,7 @@ var timer = hypertimer({rate: 1});

it('should pause a timeout when the timer is paused', function (done) {
var timer = hypertimer({rate: 1/2});
timer.setTime(new Date(2050,0,1,12,0,0,0));
var timer = hypertimer({
rate: 1/2,
time: new Date(2050,0,1,12,0,0,0)
});
var start = new Date();

@@ -335,7 +340,8 @@ var log = [];

it('should adjust a timeout when the timers time is adjusted', function (done) {
var timer = hypertimer({rate: 1});
var timer = hypertimer({
rate: 1,
time: new Date(2050,0,1,12,0,0,0)
});
var start = new Date();
timer.setTime(new Date(2050,0,1,12,0,0,0));
timer.setTimeout(function () {

@@ -347,12 +353,13 @@ approx(new Date(), new Date(start.valueOf() + 100));

timer.setTime(new Date(2050,0,1,12,0,0,100));
timer.config({time: new Date(2050,0,1,12,0,0,100)});
});
it('should adjust a timeout when the timers rate is adjusted', function (done) {
var timer = hypertimer({rate: 1/2});
var timer = hypertimer({
rate: 1/2,
time: new Date(2050,0,1,12,0,0,0)
});
var start = new Date();
var log = [];
timer.setTime(new Date(2050,0,1,12,0,0,0));
timer.setTimeout(function () {

@@ -376,7 +383,8 @@ assert.deepEqual(log, ['A']);

it('should cancel a timeout with clearTimeout', function (done) {
var timer = hypertimer({rate: 1});
var timer = hypertimer({
rate: 1,
time: new Date(2050,0,1,12,0,0,0)
});
var log = [];
timer.setTime(new Date(2050,0,1,12,0,0,0));
var timeout1 = timer.setTimeout(function () {

@@ -499,7 +507,6 @@ log.push('1');

it('should set a trigger with a start and end', function (done) {
var timer = hypertimer({rate: 2});
var start = new Date(2050,0,1,12,0,0,0);
var end = new Date(2050,0,1,12,0,0,200);
timer.setTime(start);
var timer = hypertimer({rate: 2, time: start});

@@ -514,7 +521,6 @@ var a = new Date();

it('should set a trigger with a start and an end in the past', function (done) {
var timer = hypertimer({rate: 2});
var start = new Date(2050,0,1,12,0,0,0);
var end = new Date(2050,0,1,11,0,0,0);
timer.setTime(start);
var timer = hypertimer({rate: 2, time: start});

@@ -529,7 +535,9 @@ var a = new Date();

it('should execute multiple triggers in the right order', function (done) {
var timer = hypertimer({rate: 1/2});
var start = new Date();
var log = [];
timer.setTime(new Date(2050,0,1,12,0,0,0));
var timer = hypertimer({
rate: 1/2,
time: new Date(2050,0,1,12,0,0,0)
});

@@ -563,4 +571,6 @@ var triggerB = timer.setTrigger(function () {

it('should pause a trigger when the timer is paused', function (done) {
var timer = hypertimer({rate: 1/2});
timer.setTime(new Date(2050,0,1,12,0,0,0));
var timer = hypertimer({
rate: 1/2,
time: new Date(2050,0,1,12,0,0,0)
});
var start = new Date();

@@ -595,7 +605,8 @@ var log = [];

it('should adjust a trigger when the timers time is adjusted', function (done) {
var timer = hypertimer({rate: 1});
var timer = hypertimer({
rate: 1,
time: new Date(2050,0,1,12,0,0,0)
});
var start = new Date();
timer.setTime(new Date(2050,0,1,12,0,0,0));
timer.setTrigger(function () {

@@ -607,12 +618,13 @@ approx(new Date(), new Date(start.valueOf() + 100));

timer.setTime(new Date(2050,0,1,12,0,0,100));
timer.config({time: new Date(2050,0,1,12,0,0,100)});
});
it('should adjust a trigger when the timers rate is adjusted', function (done) {
var timer = hypertimer({rate: 1/2});
var timer = hypertimer({
rate: 1/2,
time: new Date(2050,0,1,12,0,0,0)
});
var start = new Date();
var log = [];
timer.setTime(new Date(2050,0,1,12,0,0,0));
timer.setTrigger(function () {

@@ -636,7 +648,8 @@ assert.deepEqual(log, ['A']);

it('should cancel a trigger with clearTrigger', function (done) {
var timer = hypertimer({rate: 1});
var timer = hypertimer({
rate: 1,
time: new Date(2050,0,1,12,0,0,0)
});
var log = [];
timer.setTime(new Date(2050,0,1,12,0,0,0));
var trigger1 = timer.setTrigger(function () {

@@ -685,7 +698,8 @@ log.push('1');

it('should set an interval with firstTime', function (done) {
var timer = hypertimer({rate: 1});
var timer = hypertimer({
rate: 1,
time: new Date(2050,0,1,12,0,0,0)
});
var start = new Date();
timer.setTime(new Date(2050,0,1,12,0,0,0));
var firstTime = new Date(2050,0,1,12,0,0,300);

@@ -706,7 +720,8 @@ var occurrence = 0;

it('should set an interval with a number as firstTime', function (done) {
var timer = hypertimer({rate: 1});
var timer = hypertimer({
rate: 1,
time: new Date(2050,0,1,12,0,0,0)
});
var start = new Date();
timer.setTime(new Date(2050,0,1,12,0,0,0));
var firstTime = new Date(2050,0,1,12,0,0,300);

@@ -813,3 +828,2 @@ var occurrence = 0;

it('should set a negative interval with firstTime', function (done) {
var timer = hypertimer({rate: 1});
var timerStart = new Date(2050,0,1,12,0,0,0);

@@ -819,3 +833,3 @@ var realStart = new Date(new Date().valueOf() + 200);

timer.setTime(timerStart);
var timer = hypertimer({rate: 1, time: timerStart});

@@ -888,7 +902,8 @@ var occurrence = 0;

it('should correctly update interval when rate changes', function (done) {
var timer = hypertimer({rate: 1});
var timer = hypertimer({
rate: 1,
time: new Date(2050,0,1, 12,0,0, 0)
});
var start = new Date();
timer.setTime(new Date(2050,0,1, 12,0,0, 0));
var plans = {

@@ -924,11 +939,12 @@ '1': {realTime: new Date(start.valueOf() + 100), hyperTime: new Date(2050,0,1, 12,0,0, 100), newRate: 2},

describe('discrete', function () {
describe('discrete events', function () {
it('should run a series of events in discrete time', function (done) {
var timer = hypertimer({rate: 'discrete'});
it('should run a series of discrete events', function (done) {
var timer = hypertimer({
paced: false,
time: new Date(2050,0,1, 12,0,0, 0)
});
var start = new Date();
var logs = [];
timer.setTime(new Date(2050,0,1, 12,0,0));
timer.setTimeout(function () {

@@ -994,7 +1010,8 @@ logs.push('A');

it('should run an async timeout in discrete time', function (testDone) {
var timer = hypertimer({rate: 'discrete'});
it('should run an async timeout as discrete event', function (testDone) {
var timer = hypertimer({
paced: false,
time: new Date(2050,0,1, 12,0,0, 0)
});
timer.setTime(new Date(2050,0,1, 12,0,0));
timer.setTimeout(function (done) {

@@ -1031,7 +1048,9 @@ try {

// so the test would fail if A and B where executed in parallel
var timer = hypertimer({rate: 'discrete'});
var timer = hypertimer({
paced: false,
time: new Date(2050,0,1, 12,0,0, 0)
});
var logs = [];
timer.setTime(new Date(2050,0,1, 12,0,0));
timer.setTimeout(function (done) {

@@ -1077,7 +1096,8 @@ logs.push('A');

it('should handle adding a new setTimeout when all timeouts are finished', function (done) {
var timer = hypertimer({rate: 'discrete'});
var timer = hypertimer({
paced: false,
time: new Date(2050,0,1, 12,0,0, 0)
});
var logs = [];
timer.setTime(new Date(2050,0,1, 12,0,0));
timer.setTimeout(function () {

@@ -1103,7 +1123,8 @@ logs.push('A');

it('should handle adding a new setTrigger when all timeouts are finished', function (done) {
var timer = hypertimer({rate: 'discrete'});
var timer = hypertimer({
paced: false,
time: new Date(2050,0,1, 12,0,0, 0)
});
var logs = [];
timer.setTime(new Date(2050,0,1, 12,0,0));
timer.setTrigger(function () {

@@ -1129,6 +1150,7 @@ logs.push('A');

it('should handle adding a new setTimeout in the past', function (done) {
var timer = hypertimer({rate: 'discrete'});
var timer = hypertimer({
paced: false,
time: new Date(2050,0,1, 12,0,0, 0)
});
timer.setTime(new Date(2050,0,1, 12,0,0));
timer.setTimeout(function () {

@@ -1142,6 +1164,7 @@ assert.deepEqual(timer.getTime(), new Date(2050,0,1, 12,0,0));

it('should handle adding a new setTimeout with infinite delay', function (done) {
var timer = hypertimer({rate: 'discrete'});
var timer = hypertimer({
paced: false,
time: new Date(2050,0,1, 12,0,0, 0)
});
timer.setTime(new Date(2050,0,1, 12,0,0));
timer.setTimeout(function () {

@@ -1155,6 +1178,7 @@ assert.deepEqual(timer.getTime(), new Date(2050,0,1, 12,0,0));

it('should handle adding a new setTrigger in the past', function (done) {
var timer = hypertimer({rate: 'discrete'});
var timer = hypertimer({
paced: false,
time: new Date(2050,0,1, 12,0,0, 0)
});
timer.setTime(new Date(2050,0,1, 12,0,0));
timer.setTrigger(function () {

@@ -1168,6 +1192,7 @@ assert.deepEqual(timer.getTime(), new Date(2050,0,1, 12,0,0));

it('should handle adding a new setTrigger with infinite value', function (done) {
var timer = hypertimer({rate: 'discrete'});
var timer = hypertimer({
paced: false,
time: new Date(2050,0,1, 12,0,0, 0)
});
timer.setTime(new Date(2050,0,1, 12,0,0));
timer.setTrigger(function () {

@@ -1209,3 +1234,3 @@ assert.deepEqual(timer.getTime(), new Date(2050,0,1, 12,0,0));

it('should execute timeouts in deterministic order', function (done) {
var timer = hypertimer({rate: 'discrete', deterministic: true});
var timer = hypertimer({paced: false, deterministic: true});

@@ -1232,3 +1257,3 @@ var ids = [];

it('should execute timeouts in non-deterministic order', function () {
var timer = hypertimer({rate: 'discrete', deterministic: false});
var timer = hypertimer({paced: false, deterministic: false});

@@ -1255,3 +1280,3 @@ var ids = [];

it('should handle deep synchronous nesting', function (done) {
var timer = hypertimer({rate: 'discrete'});
var timer = hypertimer({paced: false});

@@ -1286,3 +1311,3 @@ timer.setTimeout(function () {

// TODO: test with a numeric time instead of "real" Dates, timer.setTime(0), rate='discrete', and timeouts like timer.timeout(cb, 1)
// TODO: test with a numeric time instead of "real" Dates, timer.config({time: 0}), paced: false, and timeouts like timer.timeout(cb, 1)

@@ -1289,0 +1314,0 @@ it('should get valueOf', function () {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc