Subtracting current hour’s value from previous hour’s value using javascript - javascript

I got my first touch with js yesterday and i got this small task to do a small script in bulding controller. I am reading values from certain location and calculating energy, and after 1 hour I should read the same values and subtract them to get get delta energy delta. The script should run constantly so Im using while(1) sleep(3,6 * 1000000)
Here is my code where I'm at
function summa() {
var E1 = (parseFloat(read("location1","value1")) *
parseFloat(read("location11","value11"))) / Math.pow(10,6)
executePropertyCommand("object1","Value","Write", E1)
var E2 = (parseFloat(read("location2","value2")) *
parseFloat(read("location22","value22"))) / Math.pow(10,6)
executePropertyCommand("object2","Value","Write", E2)
var IT_Sum = (E1 + E2)
return IT_Sum}
setTimeout(summa1,3.599 * 1000000);{
function summa1() {
var E1 = (parseFloat(read("location1","value1")) *
parseFloat(read("location1","value1"))) / Math.pow(10,6)
var E2 = (parseFloat(read("location2","value2")) *
parseFloat(read("location22","value2"))) / Math.pow(10,6)
var IT_Sum1 = (E1 + E2)
return IT_Sum1 }}
while(1) {
var sum1 = summa()
var sum2 = summa1()
var IT_delta = summa2 - summa1
sleep(3.6 * 1000000)}
I've tried to locate the settimeout in different locations like into the while loop but i cant seem to get the sum2 to wait for the delay.
Any ideas for better way to calculate the subtraction of same data in 1 hour loops?

You can add values to the array every hour and then calculate the difference of adjacent indexes.
To run code every hour use window.setTimeout and pass callback and time.
// array with values added each hour
var numbers = [];
function runHourly() {
var dateNow = new Date();
var mins = dateNow.getMinutes();
var secs = dateNow.getSeconds();
var interval = (60*(60-mins)+(60-secs))*1000;
if (interval > 0) {
window.setTimeout(runHourly, interval);
}
// your code for calculating delta goes here
numbers.push(summa());
if(numbers.length >= 2) {
var IT_delta = numbers[1] - numbers[0];
// do something with delta here
// shift array for getting delta in an hour for new values…
numbers.shift();
}
}

Related

Comparing current and next element of array and returning time difference

This is my array. Its length is about 9000. This is what a small bit of it looks like:
foreach_arr = ["21:07:01.535", "21:07:01.535", "21:07:26.113"]
There are a few occurences where the times diff is greater than a minute, and that is when I want to grab those times. And later use those times to get certain indices from another array. i.e "array"
I'm also using moment.js for time parsing.
Expected result: array = [8127, 9375, 13166, 14182]
Actual result: array = [8127, 13166]
Can't seem to find the issue here, I am getting 2 results when im supposed to be getting 4.
If the whole array is needed for troubleshooting, ill add it if I can.
var xx = foreach_arr.length - 1;
for(var z = 0; z < xx; z++) {
var current_row = foreach_arr[z];
var next_row = foreach_arr[z + 1];
var msElapsedTime = moment(next_row,"HH:mm:ss.SSS").diff(moment(current_row, "HH:mm:ss.SSS")) / 1000;
if(msElapsedTime > 60) {
attempt_indices.push(foreach_arr[z]);
}
}
for(var x = 0; x < attempt_indices.length; x++) {
array.push(newdata.indexOf(attempt_indices[x]));
}
Since the OP doesn't really need my code anymore, I'm posting it here to remove the downvote as much as anything else :)
const foreach_arr = ["21:07:01.535", "21:07:01.535", "21:07:26.113", '22:01:01.000'];
let processedForeach_arr = [];
let gtOneMinuteDiff = [];
foreach_arr.forEach((elem1, index1) => {
// elem1.split(':') turns foreach_arr[0] into ['21', '07', '01.535']
const splitElementArray = elem1.split(':');
let timeInMs = 0;
// this changes ['21', '07', '01.535'] into [75600000, 420000, 1535]
splitElementArray.forEach((elem2, index2) => {
if (index2 === 0) { // elem2 is hours. 3.6M ms per hour.
timeInMs += parseFloat(elem2) * 60 * 60 * 1000;
} else if (index2 === 1) { // elem2 is minutes. 60K ms per minute.
timeInMs += parseFloat(elem2) * 60 * 1000;
} else if (index2 === 2) { // elem2 is seconds. 1K ms per second.
timeInMs += parseFloat(elem2) * 1000;
} else {
throw `Expected array element formatted like HH:MM:SS.ms. Error on
element ${elem1}.`;
}
});
processedForeach_arr.push(timeInMs);
let timeDiff = processedForeach_arr[index1 - 1] - processedForeach_arr[index1];
if (Math.abs(timeDiff) > 60000) {
gtOneMinuteDiff.push(timeDiff);
}
});
To get the difference in milliseconds between foreach_arr[n] and foreach_arr[n+1], this code will
split each element of foreach_arr into 3 strings (hours, minutes, and seconds + milliseconds)
run parseFloat on each of those values to convert them to a number
convert all numbers to milliseconds and add them together
compare each consecutive value and return the difference.
Ok, I got this far and my son needs me. I'll finish out the code asap but you might beat me to it, hopefully the instructions above help.
turns out my code wasn't wrong. Just my idea of the whole proccess.
array = [8127, 13166]
is what I initialy get. With this, I use indexOf on my other array to eventually get my array as expected:
var another_test_arr = [];
for(var v = 0; v < array.length ; v++) {
var find = foreach_arr.indexOf(attempt_indices[v]);
another_test_arr.push(array[v], newdata.indexOf(foreach_arr[find + 1]));
}
Result: array = [8127, 9375, 13166, 14182]

Why is precomputing sin(x) *slower* than using Math.sin() in Javascript?

I've found what appears to be an interesting anomaly in JavaScript. Which centres upon my attempts to speed up trigonometric transformation calculations by precomputing sin(x) and cos(x), and simply referencing the precomputed values.
Intuitively, one would expect pre-computation to be faster than evaluating the Math.sin() and Math.cos() functions each time. Especially if your application design is going to use only a restricted set of values for the argument of the trig functions (in my case, integer degrees in the interval [0°, 360°), which is sufficient for my purposes here).
So, I ran a little test. After pre-computing the values of sin(x) and cos(x), storing them in 360-element arrays, I wrote a short test function, activated by a button in a simple test HTML page, to compare the speed of the two approaches. One loop simply multiplies a value by the pre-computed array element value, whilst the other loop multiplies a value by Math.sin().
My expectation was that the pre-computed loop would be noticeably faster than the loop involving a function call to a trig function. To my surprise, the pre-computed loop was slower.
Here's the test function I wrote:
function MyTest()
{
var ITERATION_COUNT = 1000000;
var angle = Math.floor(Math.random() * 360);
var test1 = 200 * sinArray[angle];
var test2 = 200 * cosArray[angle];
var ref = document.getElementById("Output1");
var outData = "Test 1 : " + test1.toString().trim() + "<br><br>";
outData += "Test 2 : "+test2.toString().trim() + "<br><br>";
var time1 = new Date(); //Time at the start of the test
for (var i=0; i<ITERATION_COUNT; i++)
{
var angle = Math.floor(Math.random() * 360);
var test3 = (200 * sinArray[angle]);
//End i loop
}
var time2 = new Date();
//This somewhat unwieldy procedure is how we find out the elapsed time ...
var msec1 = (time1.getUTCSeconds() * 1000) + time1.getUTCMilliseconds();
var msec2 = (time2.getUTCSeconds() * 1000) + time2.getUTCMilliseconds();
var elapsed1 = msec2 - msec1;
outData += "Test 3 : Elapsed time is " + elapsed1.toString().trim() + " milliseconds<br><br>";
//Now comparison test with the same number of sin() calls ...
var time1 = new Date();
for (var i=0; i<ITERATION_COUNT; i++)
{
var angle = Math.floor(Math.random() * 360);
var test3 = (200 * Math.sin((Math.PI * angle) / 180));
//End i loop
}
var time2 = new Date();
var msec1 = (time1.getUTCSeconds() * 1000) + time1.getUTCMilliseconds();
var msec2 = (time2.getUTCSeconds() * 1000) + time2.getUTCMilliseconds();
var elapsed2 = msec2 - msec1;
outData += "Test 4 : Elapsed time is " + elapsed2.toString().trim() + " milliseconds<br><br>";
ref.innerHTML = outData;
//End function
}
My motivation for the above, was that multiplying by a pre-computed value fetched from an array would be faster than invoking a function call to a trig function, but the results I obtain are interestingly anomalous.
Some sample runs yield the following results (Test 3 is the pre-computed elapsed time, Test 4 the Math.sin() elapsed time):
Run 1:
Test 3 : Elapsed time is 153 milliseconds
Test 4 : Elapsed time is 67 milliseconds
Run 2:
Test 3 : Elapsed time is 167 milliseconds
Test 4 : Elapsed time is 69 milliseconds
Run 3 :
Test 3 : Elapsed time is 265 milliseconds
Test 4 : Elapsed time is 107 milliseconds
Run 4:
Test 3 : Elapsed time is 162 milliseconds
Test 4 : Elapsed time is 69 milliseconds
Why is invoking a trig function twice as fast as referencing a precomputed value from an array, when the precomputed approach, intuitively at least, should be the faster by an appreciable margin? All the more so because I'm using integer arguments to index the array in the precomputed loop, whilst the function call loop also includes an extra calculation to convert from degrees to radians?
There's something interesting happening here, but at the moment, I'm not sure what. Usually, array accesses to precomputed data are a lot faster than calling intricate trig functions (or at least, they were back in the days when I coded similar code in assembler!), but JavaScript seems to turn this on its head. The only reason I can think of, is that JavaScript adds a lot of overhead to array accesses behind the scenes, but if this were so, this would impact upon a lot of other code, that appears to run at perfectly reasonable speed.
So, what exactly is going on here?
I'm running this code in Google Chrome:
Version 60.0.3112.101 (Official Build) (64-bit)
running on Windows 7 64-bit. I haven't yet tried it in Firefox, to see if the same anomalous results appear there, but that's next on the to-do list.
Anyone with a deep understanding of the inner workings of JavaScript engines, please help!
Optimiser has skewed the results.
Two identical test functions, well almost.
Run them in a benchmark and the results are surprising.
{
func : function (){
var i,a,b;
D2R = 180 / Math.PI
b = 0;
for (i = 0; i < count; i++ ) {
// single test start
a = (Math.random() * 360) | 0;
b += Math.sin(a * D2R);
// single test end
}
},
name : "summed",
},{
func : function (){
var i,a,b;
D2R = 180 / Math.PI;
b = 0;
for (i = 0; i < count; i++ ) {
// single test start
a = (Math.random() * 360) | 0;
b = Math.sin(a * D2R);
// single test end
}
},
name : "unsummed",
},
The results
=======================================
Performance test. : Optimiser check.
Use strict....... : false
Duplicates....... : 4
Samples per cycle : 100
Tests per Sample. : 10000
---------------------------------------------
Test : 'summed'
Calibrated Mean : 173µs ±1µs (*1) 11160 samples 57,803,468 TPS
---------------------------------------------
Test : 'unsummed'
Calibrated Mean : 0µs ±1µs (*1) 11063 samples Invalid TPS
----------------------------------------
Calibration zero : 140µs ±0µs (*)
(*) Error rate approximation does not represent the variance.
(*1) For calibrated results Error rate is Test Error + Calibration Error.
TPS is Tests per second as a calculated value not actual test per second.
The benchmarker barely picked up any time for the un-summed test (Had to force it to complete).
The optimiser knows that only the last result of the loop for the unsummed test is needed. It only does for the last iteration all the other results are not used so why do them.
Benchmarking in javascript is full of catches. Use a quality benchmarker, and know what the optimiser can do.
Sin and lookup test.
Testing array and sin. To be fair to sin I do not do a deg to radians conversion.
tests : [{
func : function (){
var i,a,b;
b=0;
for (i = 0; i < count; i++ ) {
a = (Math.random() * 360) | 0;
b += a;
}
},
name : "Calibration",
},{
func : function (){
var i,a,b;
b = 0;
for (i = 0; i < count; i++ ) {
a = (Math.random() * 360) | 0;
b += array[a];
}
},
name : "lookup",
},{
func : function (){
var i,a,b;
b = 0;
for (i = 0; i < count; i++ ) {
a = (Math.random() * 360) | 0;
b += Math.sin(a);
}
},
name : "Sin",
}
],
And the results
=======================================
Performance test. : Lookup compare to calculate sin.
Use strict....... : false
Data view........ : false
Duplicates....... : 4
Cycles........... : 1055
Samples per cycle : 100
Tests per Sample. : 10000
---------------------------------------------
Test : 'Calibration'
Calibrator Mean : 107µs ±1µs (*) 34921 samples
---------------------------------------------
Test : 'lookup'
Calibrated Mean : 6µs ±1µs (*1) 35342 samples 1,666,666,667TPS
---------------------------------------------
Test : 'Sin'
Calibrated Mean : 169µs ±1µs (*1) 35237 samples 59,171,598TPS
-All ----------------------------------------
Mean : 0.166ms Totals time : 17481.165ms 105500 samples
Calibration zero : 107µs ±1µs (*);
(*) Error rate approximation does not represent the variance.
(*1) For calibrated results Error rate is Test Error + Calibration Error.
TPS is Tests per second as a calculated value not actual test per second.
Again had the force completions as the lookup was too close to the error rate. But the calibrated lookup is almost a perfect match to the clock speed ??? coincidence.. I am not sure.
I believe this to be a benchmark issue on your side.
var countElement = document.getElementById('count');
var result1Element = document.getElementById('result1');
var result2Element = document.getElementById('result2');
var result3Element = document.getElementById('result3');
var floatArray = new Array(360);
var typedArray = new Float64Array(360);
var typedArray2 = new Float32Array(360);
function init() {
for (var i = 0; i < 360; i++) {
floatArray[i] = typedArray[i] = Math.sin(i * Math.PI / 180);
}
countElement.addEventListener('change', reset);
document.querySelector('form').addEventListener('submit', run);
}
function test1(count) {
var start = Date.now();
var sum = 0;
for (var i = 0; i < count; i++) {
for (var j = 0; j < 360; j++) {
sum += Math.sin(j * Math.PI / 180);
}
}
var end = Date.now();
var result1 = "sum=" + sum + "; time=" + (end - start);
result1Element.textContent = result1;
}
function test2(count) {
var start = Date.now();
var sum = 0;
for (var i = 0; i < count; i++) {
for (var j = 0; j < 360; j++) {
sum += floatArray[j];
}
}
var end = Date.now();
var result2 = "sum=" + sum + "; time=" + (end - start);
result2Element.textContent = result2;
}
function test3(count) {
var start = Date.now();
var sum = 0;
for (var i = 0; i < count; i++) {
for (var j = 0; j < 360; j++) {
sum += typedArray[j];
}
}
var end = Date.now();
var result3 = "sum=" + sum + "; time=" + (end - start);
result3Element.textContent = result3;
}
function reset() {
result1Element.textContent = '';
result2Element.textContent = '';
result3Element.textContent = '';
}
function run(ev) {
ev.preventDefault();
reset();
var count = countElement.valueAsNumber;
setTimeout(test1, 0, count);
setTimeout(test2, 0, count);
setTimeout(test3, 0, count);
}
init();
<form>
<input id="count" type="number" min="1" value="100000">
<input id="run" type="submit" value="Run">
</form>
<dl>
<dt><tt>Math.sin()</tt></dt>
<dd>Result: <span id="result1"></span></dd>
<dt><tt>Array()</tt></dt>
<dd>Result: <span id="result2"></span></dd>
<dt><tt>Float64Array()</tt></dt>
<dd>Result: <span id="result3"></span></dd>
</dl>
In my testing, an array is unquestionably faster than an uncached loop, and a typed array is marginally faster than that. Typed arrays avoid the need for boxing and unboxing the number between the array and the computation. The results I see are:
Math.sin(): 652ms
Array(): 41ms
Float64Array(): 37ms
Note that I am summing and including the results, to prevent the JIT from optimizing out the unused pure function. Also, Date.now() instead of creating seconds+millis yourself.
I agree with that the issue may be down to how you have initialised the pre-computed array
Jsbench shows the precomputed array to be 13% faster than using Math.sin()
Precomputed array: 86% (fastest 1480 ms)
Math.sin(): 100% (1718 ms)
Precomputed Typed Array: 87% (1493 ms)
Hope this helps!

Thousand separator in a JavaScript counter

I have this counter JavaScript snippet:
var START_DATE = new Date("October 24, 2015 11:00:00"); // start
var INTERVAL = 1; // sec
var START_VALUE = 0; // init value
var INCREMENT = 0.13; // value per sec
var count = 0;
window.onload = function()
{
var msInterval = INTERVAL * 1000;
var now = new Date();
count = parseInt((now - START_DATE)/msInterval,10) * INCREMENT + START_VALUE;
document.getElementById('count').innerHTML = count.toFixed(2);
setInterval("count += INCREMENT; document.getElementById('count').innerHTML = count.toFixed(2);", msInterval);
}
The counter may eventually display values in thousands and millions. My question is how to separate the thousands with a comma/blank space? I tried to achieve this via CSS, but apparently the options available here are not very practical. I was wondering on a possible solution in JavaScript. I found this on jsfiddle, but I am not sure how to apply it on the result of the counter?
function addCommas(n){
var rx= /(\d+)(\d{3})/;
return String(n).replace(/^\d+/, function(w){
while(rx.test(w)){
w= w.replace(rx, '$1,$2');
}
return w;
});
}
You can use javascript's built in toLocaleString function. Here is an example from MDN
var number = 3500;
console.log(number.toLocaleString()); // Displays "3,500" if in U.S. English locale
There are some additional options you can use with that function, but they are not all supported by various browsers. Basic use should work though.

Increment from zero to number in a set time

I am trying to increment from 0 to a number (can be any number from 2000 to 12345600000) within a certain duration (1000 ms, 5000 ms, etc). I have created the following:
http://jsfiddle.net/fmpeyton/c9u2sky8/
var counterElement = $(".lg-number");
var counterTotal = parseInt(counterElement.text()/*.replace(/,/g, "")*/);
var duration = 1000;
var animationInterval = duration/counterTotal;
counterElement.text("0");
var numberIncrementer = setInterval(function(){
var currentCounterNumber = parseInt(counterElement.text()/*.replace(/,/g, "")*/);
if (currentCounterNumber < counterTotal){
currentCounterNumber += Math.ceil(counterTotal/duration);
// convert number back to comma format
// currentCounterNumber = addCommas(currentCounterNumber);
counterElement.text(currentCounterNumber);
} else {
counterElement.text(counterTotal);
clearInterval(numberIncrementer);
}
console.log("run incrementer");
}, animationInterval);
function addCommas(number){
for (var i = number.length - 3; i > 0; i -= 3)
number = number.slice(0, i) + ',' + number.slice(i);
return number;
}
And this somewhat works, but it does not respect the duration. I.e. if you increase the number from 1000 to 1000000000, they both take different amounts of time to reach the destination number.
How can I increment from zero to a number in a specific time frame?
As #Mouser pointed out, the issue is that the animationInterval can't be too small (the actual minimum threshold will vary based on the browser and platform). Instead of varying the interval, vary the increment to the counter:
var counterElement = $(".lg-number");
var counterTotal = parseInt(counterElement.text()/*.replace(/,/g, "")*/);
var duration = 1000;
var animationInterval = 10;
var startTime = Date.now();
counterElement.text("0");
var numberIncrementer = setInterval(function(){
var elapsed = Date.now() - startTime;
var currentCounterNumber = Math.ceil(elapsed / duration * counterTotal);
if (currentCounterNumber < counterTotal){
counterElement.text(currentCounterNumber);
} else {
counterElement.text(counterTotal);
clearInterval(numberIncrementer);
}
console.log("run incrementer");
}, animationInterval);
I played around with your fiddle and found that the delay needs to be higher. At 8ms or 16ms, it is accurate enough to handle a second, but not accurate enough to handle half a second. From experimenting, it seems like a delay of 64ms is small enough to seem like it's incrementing smoothly, but big enough to have an accurate effect.
The difference is that the current number is calculated based on the process rather than directly manipulated.
var counterElement = $(".lg-number");
var counterTotal = parseInt(counterElement.data('total'));
var interval = 0;
var duration = parseInt(counterElement.data('duration'));;
var delay = 64
var numberIncrementer = setInterval(function(){
var currentCounterNumber = 0;
interval += delay;
if (interval <= duration){
var progress = interval / duration;
currentCounterNumber = Math.round(progress * counterTotal);
} else {
currentCounterNumber = counterTotal
clearInterval(numberIncrementer);
}
counterElement.text(currentCounterNumber);
}, delay);
http://jsfiddle.net/c9u2sky8/5/
Also: Javascript timers are not perfectly accurate. But this should be accurate enough for UI use cases.

Incrementing a number smoothly with a variable time period in JS

I have a really simple JS counter which I display on a dashboard like screen which does the following:
Every 5 minutes it makes an jsonp call and retrieves a "total" number
It then displays this number to the screen by incrementing the last total displayed till it is equal to the new total. (the number can only ever increase)
I'm having some trouble with making the number increment smoothly. What I would like to do is find a delta (i.e. New total - old total) and increment the number gradually over the 5 minutes till the next call so it looks like a nice smooth transition.
Any ideas on how I can do this?
Currently some of my code looks like this (This block get's called every 5mins. And yes, it's in dire need of a refactor...)
var LAST_NUMBER_OF_SESSIONS = null;
var five_minutes_in_seconds = 300;
var new_number_of_sessions;
$.getJSON('http://blah.com/live_stats/default_jsonp.aspx?callback=?', function(data) {
if(LAST_NUMBER_OF_SESSIONS === null){
LAST_NUMBER_OF_SESSIONS = data.total_sessions;
}
new_number_of_sessions = data.total_sessions;
var delta = Math.floor(new_number_of_sessions - LAST_NUMBER_OF_SESSIONS);
var time_interval = (five_minutes_in_seconds / delta) * 1000;
var old_value = LAST_NUMBER_OF_SESSIONS;
var new_value = null;
sessions_interval = setInterval(function (){
new_value = parseInt(old_value, 10) + 1;
$('#stats').text(new_value);
old_value = new_value;
if(new_value >= new_number_of_sessions){
clearInterval(sessions_interval);
}
}, time_interval);
LAST_NUMBER_OF_SESSIONS = new_value;
});
}
This code it seems to increment the number very quickly at the start of the 5min period and then stop so it's not exactly right...
Try this:
var total = 0,
delta = 0,
stats = $('#stats').text( total );
function increment() {
var v = +stats.text();
if ( v < total ) {
stats.text( v + 1 );
} else {
$.getJSON('http://...', function(data) { // added data here
delta = Math.floor( 300000 / ( data.total_sessions - total ) );
total = data.total_sessions;
});
}
setTimeout(increment, delta);
}
Update:
In order to test my code, I had to simulate the JSON reponse - I used an array of numbers. See here: http://jsfiddle.net/simevidas/MwQKM/
(In the demo, I use an interval of 5 seconds instead of 5 minutes.)
I am not exactly sure why your code doesn't work as expected, although I suspect that it has to do with line LAST_NUMBER_OF_SESSIONS = new_value;. I wrote something similar and it works fine. It's not that different from what you have, minus that last line of code.

Categories

Resources