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.0.0 to 1.1.0

60

dist/hypertimer.js

@@ -8,4 +8,4 @@ /**

*
* @version 1.0.0
* @date 2014-07-17
* @version 1.1.0
* @date 2014-07-22
*

@@ -111,2 +111,5 @@ * @license

* event to event). By default, rate is 1.
* deterministic: boolean
* If true (default), simultaneous events
* are executed in a deterministic order.
*/

@@ -116,2 +119,3 @@ function hypertimer(options) {

var rate = 1; // number of milliseconds per milliseconds
var deterministic = true; // run simultaneous events in a deterministic order

@@ -141,2 +145,5 @@ // properties

* event to event). By default, rate is 1.
* deterministic: boolean
* If true (default), simultaneous events
* are executed in a deterministic order.
* @return {Object} Returns the applied configuration

@@ -155,2 +162,5 @@ */

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

@@ -163,3 +173,4 @@

return {
rate: rate
rate: rate,
deterministic: deterministic
};

@@ -500,2 +511,25 @@ };

/**
* Remove all timeouts occurring before or on the provided time from the
* queue and return them.
* @param {number} time A timestamp
* @returns {Array} returns an array containing all expired timeouts
* @private
*/
function _getExpiredTimeouts(time) {
var i = 0;
while (i < timeouts.length && ((timeouts[i].time <= time) || !isFinite(timeouts[i].time))) {
i++;
}
var expired = timeouts.splice(0, i);
if (deterministic == false) {
// the array with expired timeouts is in deterministic order
// shuffle them
util.shuffle(expired);
}
return expired;
}
/**
* Reschedule all queued timeouts

@@ -534,7 +568,3 @@ * @private

// grab all expired timeouts from the queue
var i = 0;
while (i < timeouts.length && ((timeouts[i].time <= time) || !isFinite(timeouts[i].time))) {
i++;
}
var expired = timeouts.splice(0, i);
var expired = _getExpiredTimeouts(time);
// note: expired.length can never be zero (on every change of the queue, we reschedule)

@@ -614,5 +644,19 @@

/**
* Shuffle an array
*
* + Jonas Raoni Soares Silva
* @ http://jsfromhell.com/array/shuffle [v1.0]
*
* @param {Array} o Array to be shuffled
* @returns {Array} Returns the shuffled array
*/
exports.shuffle = function (o){
for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
};
/***/ }
/******/ ])
})

6

dist/hypertimer.min.js

@@ -8,4 +8,4 @@ /**

*
* @version 1.0.0
* @date 2014-07-17
* @version 1.1.0
* @date 2014-07-22
*

@@ -27,3 +27,3 @@ * @license

*/
!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(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){function r(e){function t(e){if(s.length>0){for(var t=s.length-1;t>=0&&s[t].time>e.time;)t--;s.splice(t+1,0,e)}else s.push(e)}function n(e,n){function r(){e.type===o.INTERVAL&&m[e.id]&&(e.occurrence++,e.time=e.firstTime+e.occurrence*e.interval,t(e)),delete m[e.id],"function"==typeof n&&n()}m[e.id]=e;try{0==e.callback.length?(e.callback(),r()):e.callback(r)}catch(i){r()}}function r(){function e(){function e(){var t=o.shift();t?n(t,e):r()}a===u&&(l=i);for(var t=0;t<s.length&&(s[t].time<=i||!isFinite(s[t].time));)t++;var o=s.splice(0,t);a===u?e():(o.forEach(n),r())}if(!(a===u&&Object.keys(m).length>0)){var t=s[0];if(p&&(clearTimeout(p),p=null),c&&t){var i=t.time,o=i-b.now(),f=a===u?0:o/a;p=setTimeout(e,f)}}}var a=1,c=!1,f=null,l=null,s=[],m={},p=null,T=0,b={};return b.config=function(e){if(e&&"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"');l=b.now(),f=i.nowReal(),a=t}return r(),{rate:a}},b.setTime=function(e){if(e instanceof Date)l=e.valueOf();else{var t=Number(e);if(isNaN(t))throw new TypeError("time must be a Date or number");l=t}r()},b.now=function(){if(a===u)return l;if(c){var e=i.nowReal()-f,t=e*a;return l+t}return l},b["continue"]=function(){f=i.nowReal(),c=!0,r()},b.pause=function(){l=b.now(),f=null,c=!1,r()},b.getTime=function(){return new Date(b.now())},b.valueOf=b.getTime,b.toString=function(){return b.getTime().toString()},b.setTimeout=function(e,n){var i=T++,u=b.now()+n;if(isNaN(u))throw new TypeError("delay must be a number");return t({id:i,type:o.TIMEOUT,time:u,callback:e}),r(),i},b.setTrigger=function(e,n){var i=T++,u=Number(n);if(isNaN(u))throw new TypeError("time must be a Date or number");return t({id:i,type:o.TRIGGER,time:u,callback:e}),r(),i},b.setInterval=function(e,n,i){var u=T++,a=Number(n);if(isNaN(a))throw new TypeError("interval must be a number");(0>a||!isFinite(a))&&(a=0);var c;if(void 0!=i){if(c=Number(i),isNaN(c))throw new TypeError("firstTime must be a Date or number")}else c=b.now()+a;return t({id:u,type:o.INTERVAL,interval:a,time:c,firstTime:c,occurrence:0,callback:e}),r(),u},b.clearTimeout=function(e){if(m[e])return void delete m[e];for(var t=0;t<s.length;t++)if(s[t].id===e){s.splice(t,1),r();break}},b.clearTrigger=b.clearTimeout,b.clearInterval=b.clearTimeout,b.list=function(){return s.map(function(e){return e.id})},b.clear=function(){m={},s=[],r()},Object.defineProperty(b,"running",{get:function(){return c}}),b.config(e),b.setTime(i.nowReal()),b.continue(),b}var i=n(2),o={TIMEOUT:0,INTERVAL:1,TRIGGER:2},u="discrete";e.exports=r},function(e,t){t.nowReal="function"==typeof Date.now?function(){return Date.now()}:function(){return(new Date).valueOf()}}])});
!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(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){function r(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 n(e,n){function r(){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 n&&n()}d[e.id]=e;try{0==e.callback.length?(e.callback(),r()):e.callback(r)}catch(i){r()}}function r(e){for(var t=0;t<p.length&&(p[t].time<=e||!isFinite(p[t].time));)t++;var n=p.splice(0,t);return 0==f&&i.shuffle(n),n}function a(){function e(){function e(){var r=t.shift();r?n(r,e):a()}c===u&&(m=i);var t=r(i);c===u?e():(t.forEach(n),a())}if(!(c===u&&Object.keys(d).length>0)){var t=p[0];if(v&&(clearTimeout(v),v=null),l&&t){var i=t.time,o=i-b.now(),f=c===u?0:o/c;v=setTimeout(e,f)}}}var c=1,f=!0,l=!1,s=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(),s=i.nowReal(),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(l){var e=i.nowReal()-s,t=e*c;return m+t}return m},b["continue"]=function(){s=i.nowReal(),l=!0,a()},b.pause=function(){m=b.now(),s=null,l=!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,n){var r=T++,i=b.now()+n;if(isNaN(i))throw new TypeError("delay must be a number");return t({id:r,type:o.TIMEOUT,time:i,callback:e}),a(),r},b.setTrigger=function(e,n){var r=T++,i=Number(n);if(isNaN(i))throw new TypeError("time must be a Date or number");return t({id:r,type:o.TRIGGER,time:i,callback:e}),a(),r},b.setInterval=function(e,n,r){var i=T++,u=Number(n);if(isNaN(u))throw new TypeError("interval must be a number");(0>u||!isFinite(u))&&(u=0);var c;if(void 0!=r){if(c=Number(r),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 l}}),b.config(e),b.setTime(i.nowReal()),b.continue(),b}var i=n(2),o={TIMEOUT:0,INTERVAL:1,TRIGGER:2},u="discrete";e.exports=r},function(e,t){t.nowReal="function"==typeof Date.now?function(){return Date.now()}:function(){return(new Date).valueOf()},t.shuffle=function(e){for(var t,n,r=e.length;r;t=Math.floor(Math.random()*r),n=e[--r],e[r]=e[t],e[t]=n);return e}}])});
//# sourceMappingURL=hypertimer.map
# History
## 2014-07-22, version 1.1.0
- Added support for non-deterministic execution of events.
## 2014-07-17, version 1.0.0

@@ -5,0 +10,0 @@

@@ -22,2 +22,5 @@ var util = require('./util');

* event to event). By default, rate is 1.
* deterministic: boolean
* If true (default), simultaneous events
* are executed in a deterministic order.
*/

@@ -27,2 +30,3 @@ function hypertimer(options) {

var rate = 1; // number of milliseconds per milliseconds
var deterministic = true; // run simultaneous events in a deterministic order

@@ -52,2 +56,5 @@ // properties

* event to event). By default, rate is 1.
* deterministic: boolean
* If true (default), simultaneous events
* are executed in a deterministic order.
* @return {Object} Returns the applied configuration

@@ -66,2 +73,5 @@ */

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

@@ -74,3 +84,4 @@

return {
rate: rate
rate: rate,
deterministic: deterministic
};

@@ -411,2 +422,25 @@ };

/**
* Remove all timeouts occurring before or on the provided time from the
* queue and return them.
* @param {number} time A timestamp
* @returns {Array} returns an array containing all expired timeouts
* @private
*/
function _getExpiredTimeouts(time) {
var i = 0;
while (i < timeouts.length && ((timeouts[i].time <= time) || !isFinite(timeouts[i].time))) {
i++;
}
var expired = timeouts.splice(0, i);
if (deterministic == false) {
// the array with expired timeouts is in deterministic order
// shuffle them
util.shuffle(expired);
}
return expired;
}
/**
* Reschedule all queued timeouts

@@ -445,7 +479,3 @@ * @private

// grab all expired timeouts from the queue
var i = 0;
while (i < timeouts.length && ((timeouts[i].time <= time) || !isFinite(timeouts[i].time))) {
i++;
}
var expired = timeouts.splice(0, i);
var expired = _getExpiredTimeouts(time);
// note: expired.length can never be zero (on every change of the queue, we reschedule)

@@ -452,0 +482,0 @@

@@ -21,1 +21,15 @@

}
/**
* Shuffle an array
*
* + Jonas Raoni Soares Silva
* @ http://jsfromhell.com/array/shuffle [v1.0]
*
* @param {Array} o Array to be shuffled
* @returns {Array} Returns the shuffled array
*/
exports.shuffle = function (o){
for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
};
{
"name": "hypertimer",
"version": "1.0.0",
"version": "1.1.0",
"description": "Time control for simulations",

@@ -29,2 +29,3 @@ "author": "Jos de Jong <wjosdejong@gmail.com> (https://github.com/josdejong)",

"mocha": "^1.18.2",
"seed-random": "^2.2.0",
"uglify-js": "^2.4.15",

@@ -31,0 +32,0 @@ "uglifyjs": "^2.3.6",

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). In short, one needs to be able to run a simulation in [hypertime](http://en.wikipedia.org/wiki/Hypertime).
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)).

@@ -11,3 +11,3 @@ Hypertimer offers basic functionality to control time:

These functions are compatible with JavaScript's built-in functions `Date.now()`, `setTimeout()`, and `setInterval()`, but there is an important difference: they can run with a different current time and at a different rate.
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.

@@ -77,2 +77,5 @@ Hypertimer runs on node.js and on any modern browser (Chrome, FireFox, Opera, Safari, IE9+).

var timer3 = hypertimer({rate: 'discrete'});
// create a hypertimer running in discrete time and non-deterministic behavior
var timer4 = hypertimer({rate: 'discrete', deterministic: false});
```

@@ -193,3 +196,3 @@

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 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`.

@@ -247,5 +250,6 @@ ```js

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.
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.

@@ -280,4 +284,6 @@ Example:

- `rate: Number | 'discrete'`
- `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.

@@ -350,2 +356,3 @@ - **`continue()`**

- Implement support for non-deterministic behavior.
- Implement a scalable solution to synchronize hypertimers running in different processes.

@@ -352,0 +359,0 @@ - Use high precision timers and time functions.

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

var async = require('async');
var seed = require('seed-random');
var hypertimer = require('../lib/hypertimer');

@@ -39,3 +40,3 @@

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

@@ -1051,2 +1052,75 @@

describe('determinism', function () {
var originalRandom;
before(function () {
// replace the original Math.random with a reproducible one
// FIXME: for util.shuffle, we should replace Math.random with a reproducible one but this seems not to work.
originalRandom = Math.random;
Math.random = seed('key');
});
after(function () {
// restore the original random function
Math.random = originalRandom;
});
it('configure deterministic option', function () {
var timer = hypertimer({deterministic: true});
assert.equal(timer.config().deterministic, true);
timer.config({deterministic: false});
assert.equal(timer.config().deterministic, false);
timer.config({deterministic: true});
assert.equal(timer.config().deterministic, true);
});
it('should execute timeouts in deterministic order', function (done) {
var timer = hypertimer({rate: 'discrete', deterministic: true});
var ids = [];
var logs = [];
for (var i = 0; i < 1000; i++) {
(function () {
var id = timer.setTimeout(function () {
logs.push(id);
}, 1000);
ids.push(id);
})();
}
timer.setTimeout(function () {
// the timeouts should have been executed in the order they where added
assert.deepEqual(ids, logs);
done();
}, 2000);
});
it('should execute timeouts in non-deterministic order', function () {
var timer = hypertimer({rate: 'discrete', deterministic: false});
var ids = [];
var logs = [];
for (var i = 0; i < 1000; i++) {
(function () {
var id = timer.setTimeout(function () {
logs.push(id);
}, 1000);
ids.push(id);
})();
}
timer.setTimeout(function () {
// the timeouts should have been executed in the order they where added
assert.notDeepEqual(ids, logs);
done();
}, 2000);
});
});
// TODO: test with a numeric time instead of "real" Dates, timer.setTime(0), rate='discrete', and timeouts like timer.timeout(cb, 1)

@@ -1053,0 +1127,0 @@

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