node.js setInterval vs real time - javascript

I am working on a tool that require to measure certain amount of time (for example 2 minutes) since user interaction with a tool, this time also needs to be displayed for the user.
I started simple server loop for this reason:
setInterval(function() {
measure.time();
}, 10);
i created a code for to calculate:
this.reset = 0;
this.step = 100 // 10 ms server loop, adds 1 to reset === 100 is 1 second
this.time = function() {
if(this.reset === this.step) {
console.log('SPAWN', new Date());
this.reset = 0;
}
this.reset++;
};
this is the result of my approach:
The idea is to show clock for the user and update it every second, but it skips seconds rather often, what am i doing wrong?

Related

How do I make a div click without the mouse moving?

I'm trying to make a JavaScript code that injects into cpstest.org and when you click the start button, it automatically starts auto-clicking. I tried to make a script for it, but it just didn't work.
The start button has id start but I don't know the element to click. Viewing source code or using dev tools would be helpful, but those are blocked on my computer.
let i = 1;
document.querySelector('#start').addEventListener('click', function() {
i = 0;
});
function repeat() {
if (i == 0) {
document.querySelector(unknownId).click()};
requestAnimationFrame(repeat)
}
};
repeat();
Here's a solution:
// speed - how many CPS you want
// duration - how long the test is (in seconds)
const rapidClick = (speed, duration) => {
const startButton = document.querySelector('button#start');
const clickArea = document.querySelector('div#clickarea');
// Start the test
startButton.click()
// Click the clickArea on an interval based on the "speed" provided
const interval = setInterval(() => clickArea.click(), 1e3 / speed);
// Clear the interval after the duration has passed
setTimeout(() => clearInterval(interval), duration * 1e3);
}
// Do 100 CPS for 5 seconds
rapidClick(100, 5)
I noticed that even when setting the speed parameter to something insane like 1000 CPS, the test says only 133-139 clicks per second. Seems like it caps off at 139. Hope this helps.

Making Discord bot do things automatically on a daily routine

I am new to java script and discord programming and I want a bot at my discord server to do a channel purge at 5o'clock in the morning.
However, I want to run it on a dedicated server and don't know how to properly set up the time trigger mechanic.
Will
if (date.getHours()==5){
//do stuff
}
work?
You can use client.setInterval() to have timed functions.
For example: client.setInterval(() => purgeChannel(), 300000); will run the function purgeChannel every 5 minutes (300000 is 5 minutes in milliseconds).
The easiest way I could see you doing this, was an Object with each action saved to a time. I choose to use <HOUR><MINUTE> to store each value. So a 4:12PM time would be: 1612. Then a setInterval to run every minute and check if it needs todo a new action.
function hello() {
console.log('Hello');
}
let actions = {
"0630": function() {
console.log('Its 6:30');
},
"1200": hello, //NOON
"1400": hello, //2:00 PM
"0000": function() {
console.log('New Day / Midnight');
},
};
let codeStartTime = new Date();
function checkActions() {
let date = new Date();
let action = actions[`${date.getHours() >= 10 ? "" : "0"}${date.getHours()}${date.getMinutes() >= 9 ? "" : "0"}${date.getMinutes()}`];
if (typeof action === "function") action(); //If an action exists for this time, run it.
}
setTimeout(function() {
checkActions();
setInterval(checkActions, 60000); //Run the function every minute. Can increase/decrease this number
}, ((60 - codeStartTime.getSeconds()) * 1000) - codeStartTime.getMilliseconds()); // Start the interval at the EXACT time it starts at a new minute
/** CODE for the Stack Overflow Snippet **/
console.log(`Starting first interval in ${((60 - codeStartTime.getSeconds()))} seconds.`);
console.log(`Adding in StackOverflow function, set to run at: ${codeStartTime.getHours() >= 10 ? "" : "0"}${codeStartTime.getHours()}${codeStartTime.getMinutes() >= 9 ? "" : "0"}${codeStartTime.getMinutes() + 1}`);
actions[`${codeStartTime.getHours() >= 10 ? "" : "0"}${codeStartTime.getHours()}${codeStartTime.getMinutes() >= 9 ? "" : "0"}${codeStartTime.getMinutes() + 1}`] = function() {
console.log('Ran the StackOverflow Function');
};
If you choose to, you can wait for the any of my example times in the actions Object just to prove it works. But the StackOverflow code just adds a sample time to your current time +1 minute in the actions Object just to make it easier to see it in action.
setInterval is used here just to be simple, but not really recommended if this will run all day. Reason Why.
To have a more exact time, I suggest replacing the setInterval to a setTimeout and just re-define the setTimeout everytime it's ran.

wavesurfer get elapsed time in real time

I'm using katspaugh's waveSurfer library for playing sound files.
I wrote code to show 'elapsed time / total time' in this way.
waveSurfer.on('play', function() {
$scope.getCurrentDuration();
});
$scope.getCurrentDuration() is a function to transform floating-type variable to string-type variable, like below:
$scope.getDuration = function() {
if ($scope.waveSurferReady) {
var time = waveSurfer.getDuration(); // get duration(float) in second
var minute = Math.floor(time / 60); // get minute(integer) from time
var tmp = Math.round(time - (minute * 60)); // get second(integer) from time
var second = (tmp < 10 ? '0' : '') + tmp; // make two-figured integer if less than 10
return String(minute + ':' + second); // combine minute and second in string
}
else {
return 'not ready yet'; // waveSurfer is not ready yet
}
};
But the problem is,
in this part:
waveSurfer.on('play', function() ...)
the callback function execute only once.
I expect the callback function called periodically, but it executes only once, so as the result, elapsed time is shown only at the start time.
How can I solve this?
Looking into the source, I've found the audioprocess event paired with html5 timeupdate event.
Try it out.
waveSurfer.on('audioprocess', function() {
// do stuff here
});

Using requestAnimationFrame as a Timer

This is a multi-player "guess the word" turn-based game I am working on.
I have a page that is supposed to count down from a given number. If a word-guess is submitted before the time limit, a SignalR hub method is called. If 0 is reached, a different SignalR hub method is called. In both cases, the hub method sends a message back out to all relevant clients (in a group).
Someone recommended, instead of a JS timer, I can use requestAnimationFrame which updates every 17 milliseconds.
So here is what requestAnimationFrame code I have in the Play.aspx file...
function turnTimerOn() { //called by server code as a startup script
var timerStep = '<%=Application(Session("GameID") & "_TimeLimit")%>';
timerStep = Number(timerStep);
var startT = Date.now();
var timedifference = 0;
var countdown = document.getElementById('SecondsLeft');
requestAnimationFrame(function anim() {
requestAnimationFrame(anim);
startT = startT || Date.now();
countdown.innerHTML = timerStep - ((Date.now() - startT) / 1000 | 0);
timedifference = (Date.now() - startT) / 1000 | 0;
if (timedifference >= timerStep) {
startT = Date.now();
timedifference = 0;
countdown.innerHTML = "";
TomatoHubProxy.invoke('NextPlayer', '<%=Session("username")%>', '<%=Session("GameID")%>');
}
});
}
The return message from the SignalR hub causes execution of turnTimerOn() again, and this is meant to start the countdown again for the current player.
The count down seems to work but has a bug where it reaches a low number like 3 or 4 and then either resets the count down or invokes the Hub method (it's hard to tell what is happening). It is supposed to invoke the Hub method when the count down reaches 0 (so that the game can move to the next player)
I should also mention the Play.aspx page is never re-loaded. All updates happen automatically (thanks to SignalR)
Please help.

Gmail-like countdown timer not working

I've been trying to recreate a countdown timer similar to the one gmail uses that when you get disconnected from internet. The ajax request fails then it begin a short countdown then makes another ajax request and if it fails again then begin a longer countdown and so forth. Once a determined countdown value is reached (lets say 1 minute), the countdown is maintained at 1 minute until the internet connection is recovered or the servers comes back.
I don't want to use a plugin because this code will be embedded in a micro-controller that has limited space and also prefer not to place it as external file for practical reasons, even though jQuery library will already be external.
Everything should trigger onload, and continue automatically (i.e. no control inputs will be used).
So far I've developed code that does what I want if the ajax request succeeds or fails immediately but if there is a latency on the ajax request status (as for example having the server down) the browser won't produce an immediate result and my code fails.
I know what I stated above because I actually took the server down and was been help by firebug on Mozilla Firefox to see that the ajax result (success or failure) wasn't triggered immediately but keep waiting for several seconds.
Help please!
html code:
<div id='tempFail' ></div>
jQuery code:
$(document).ready(function()
{
//do when DOM ready - http://api.jquery.com/ready/
var timerSpeed = [1000, 5000, 10000, 20000, 30000, 60000];
// current time in ms since 1/1/1970, plus the initial reload interval
var end = (new Date).getTime() + timerSpeed[1];
var n=0;
var m=0;
setInterval(function()
{
var now = (new Date).getTime();
// Current time left to re-load in seconds, sometimes it goes to negative values, see below
var secLeft = Math.floor(( end - now ) / 1000);
// if secLeft is negative multiply by zero...equal to secLeft=0, this will produce an error of one second approximately
var timeToload = (secLeft < 0) ? secLeft * 0 : secLeft;
if (n!=0)
{
//check for failed or delayed request\n\
$('#tempFail').html('Failed or delayed response. Will auto load in: '+timeToload+ ' seconds!');
}
if( (secLeft)<=0)// if reload time is reached do
{
if (m==0)//used to prevent multiple continue reloads when ajax request status is not yet defined
{
m=1;
$.getScript('script_vars.js').done(function (data)
{
//if request succeeded
m=0;
n = 0;
end = (new Date).getTime() + timerSpeed[1];
// Time to load after the initial interval set above
$('#tempFail').html('');
//other code on success here
})
.fail(function()
{
//if request failed
m=0;
n ++;
if(n==6) n=5;
switch(n){ //timer delay for failed request\n\
case 1:
end = (new Date).getTime() + timerSpeed[1];
break;
case 2:
end = (new Date).getTime() + timerSpeed[2];
break;
case 3:
end = (new Date).getTime() + timerSpeed[3];
break;
case 4:
end = (new Date).getTime() + timerSpeed[4];
break;
case 5:
end = (new Date).getTime() + timerSpeed[5];
break;
}
});
}
}
}, 1000);
});
You asked for an example so I've written the following, you may want to wrap the contents of the function within another function so you can repeat it/don't have to worry about namespaces/etc. Didn't test so don't expect bug free!
Using window.setTimeout for every action, separated each stage into it's own function so code paths can more easily be followed.
$(document).ready(function () { // http://api.jquery.com/ready/
var $tempFail = $('#tempFail'),
delay = [1000, 5000, 10000, 20000, 30000, 60000],
delay_index = 0,
delay_ends = 0,
inform_user_ref = null,
inform_user = function inform_user() {
var now = (new Date).getTime(),
delta; // for difference, calculate later
if (delay_ends > now) { // if we're waiting for a retry
delta = Math.floor((delay_ends - now ) / 1000); // calculate time to wait
$tempFail.html('Failed or delayed response. Will auto load in: '+delta+ ' seconds!'); // let people know
window.setTimeout(inform_user, 200); // loop countdown timer
// can fast refresh this as it's just a countdown
}
},
get_success = function () {
$tempFail.html('');
// .. code on success
},
get_fail = function () {
delay_index < 5 && ++delay_index; // increment delay_index
get_initialise(); // retry
window.clearTimeout(inform_user_ref); // remove any old countdown timer
inform_user_ref = inform_user(); // and display new countdown
},
get_try = function () {
$.getScript('script_vars.js')
.done(get_success)
.fail(get_fail);
},
get_initialise = function () {
delay_ends = (new Date).getTime() + delay[delay_index];
window.setTimeout(get_try, delay[delay_index]); // retry
};
get_initialise(); // initial
});
Wow! Mr Paul S. your code was crazy good. I just made a couple of adjustments to have it perfectly working as I need it.
Added the following on ajax success:
delay_index = 0; //reset delay_index
get_initialise(); // retry
so I keep the code running every 5 seconds if everything goes ok.
2.
Added two new variables: let_cntDwn_end and ajax_rqst_status to avoid countdown number jumping (to let countdown finish before beginning the next one ) and to display a message while the ajax request haven't given any result respectively.
Here is the new code:
$(document).ready(function(){ //do when DOM ready - http://api.jquery.com/ready/
var $tempFail = $('#tempFail'),
delay = [5000, 5000, 10000, 20000, 30000, 60000],
delay_index = 0,
delay_ends = 0,
inform_user_ref = null,
let_cntDwn_end = 0,
ajax_rqst_status = 0, //ajax success or failure triggered
inform_user = function inform_user() {
var now = (new Date).getTime(),
delta; // for difference, calculated later
if (delay_ends > now) { // if we're waiting for a retry
let_cntDwn_end = 1;
delta = Math.floor((delay_ends - now ) / 1000); // calculate time to wait
if (ajax_rqst_status==0){
$tempFail.html('Failed response. Will auto load in: '+delta+ ' seconds!'); // let people know
window.setTimeout(inform_user, 900); // loop countdown timer
// can fast refresh this as it's just a countdown
}
}
else {let_cntDwn_end = 0; get_try();}
},
get_success = function () {
ajax_rqst_status =0;
$tempFail.html('');
// .. code on success
delay_index = 0; //reset delay_index
get_initialise(); // retry
},
get_fail = function () {
ajax_rqst_status =0;
delay_index < 5 && ++delay_index; // increment delay_index
get_initialise(); // retry
window.clearTimeout(inform_user_ref); // remove any old countdown timer
inform_user_ref = inform_user(); // and display new countdown
},
get_try = function () {
if (let_cntDwn_end == 0){
ajax_rqst_status=1;
$tempFail.html('Waiting for Ajax request success or failure'); // let people know
$.getScript('script_vars.js')
.done(get_success)
.fail(get_fail);
}
},
get_initialise = function () {
delay_ends = (new Date).getTime() + delay[delay_index];
window.setTimeout(get_try, delay[delay_index]); // retry
};
get_initialise(); // initial
});
There's also JS lib which handles this for you by monitoring ajax requests.
https://github.com/HubSpot/offline

Categories

Resources