SetInterval depending on when i run it - setinterval

We have a side that has a server time. I want to check the server time every 1 ms and when it goes to a certain second and ms i want a button to be confirm. I do this with setInterval. The problem with this is that if I run my script via bookmarks 1 minute before the wanted time and 5 minutes before the wanted time, there is a difference on the time it confirms the button although the time I want is the exactly the same.
Any ideas will be appreciate!
The code i have made as far is this:
javascript:var currentTime=$("#serverTime").text().split(":");
var currentSec=currentTime[2];
var currentMs=new Date().getMilliseconds();
function checkTime(){
var currentTime=$("#serverTime").text().split(":");
var currentHours = currentTime[0];
var currentMins = currentTime[1];
var currentSec=currentTime[2];
var currentMs=new Date().getMilliseconds();
if((currentHours == 13)(currentMins == 30)&&(currentSec==00)&&(currentMs>0)&&(currentMs<15)){
document.forms[0].submit.click()
}
}
var confirm=setInterval("checkTime()",1);
So i want the form to be submited at 13:30:00 and 00 to 15 ms with this script that I run it on a website(with the form I want to submit) via bookmarks. The problem is that if I run it 2 hours before the time the form will be submited some ms or sec later than if I run the script 10 mins before 13:30:00.
Any ides?

Related

Why does my code does not update the number on the screen

what the function does is deviding the numertor with the denomirator and updates the app's text view accordingly after every second, the problem is that it doesn't update the screen its just simply shows the original number of the numerator that is 60.
what do I change in order to make this work?
fun division() {
val numerator = 60
var denominator = 4
repeat(4) {
Thread.sleep(1_000)
findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")
denominator--
}
}
Because you are setting (basically overwritting) the text everytime it loops through, you will only see the value of the last increment which would be 60/1 and that's why you are only seeing 60 value. Try like this:
fun division() {
val numerator = 60
var denominator = 4
repeat(4) {
Thread.sleep(1_000)
findViewById<TextView>(R.id.division_textview).append("${numerator / denominator}\n")
denominator--
}
}
setText() was overwriting the text with the new one but append() is gonna keep the previous text.
This is that dang Codelab again isn't it? I knew it looked familiar... I already answered a similar question here - but basically, when you run division on the main thread (which you must be since you're messing with UI components), you're freezing the app because you're blocking the thread with Thread.sleep
The display can't actually update until your code has finished running, i.e. after you exit the division function, because it's all running on the same thread, and the display update pass comes later. So this is what's actually happening:
freeze the app for 1 second
set the text as the result of 60 / 4 - it won't actually redraw until later, after your code has finished, so there's no visual change
freeze the app for 1 second
set the text as the result of 60 / 3 - again you won't see anything happen yet, but now it's going to show 60 / 3 instead of 60 / 4, because you just updated the state of that TextView
etc.
The last text you set is the result of 60 / 1, and then your code finishes, so the system can finally get around to updating the display. So the first thing you see after the app stops freezing is 60 - it's not just the numerator, it's the last calculation from your loop.
If you want something to update while the app is running, there are lots of solutions like coroutines, CountdownTimers, posting runnables that execute at a specific time, etc. The answer I linked shows how to create a separate thread to run basically the same code on, so you can block it as much as you like without affecting the running of the app. The one thing you don't do is block the main thread like that Codelab example does. It's a bad Codelab
You can use delay and then call from a coroutine:
private suspend fun division() {
val numerator = 60
var denominator = 4
repeat(4) {
delay(1000)
findViewById<TextView>(R.id.division_textview).text = "${numerator / denominator}"
denominator--
}
}
Then from your Activity/Fragment:
lifecycleScope.launch {
division()
}

Electron.JS is being very CPU intensive, I can't tell what's wrong with my code

I have written an application to show GPU/CPU/RAM loads in electron.js! It was all ok until I started implementing gauges to graphically display temperatures. This section is shown below, I have also included a screenshot of task manager showing hundreds of command and powershell windows!
function getGPUtempHome(){
let stinker = si.graphics();
stinker.then(function(tempGPU){
GPUtempHome = tempGPU.controllers[0].temperatureGpu;
console.log(GPUtempHome);
document.getElementById("GPUtemps").innerHTML = GPUtempHome+'°';
document.documentElement.style.setProperty('--GPUTEMP', GPUtempHome*1.8 + 'deg');
});
setInterval( function() {getGPUtempHome();}, 5000 );
}
function getRAMhome(){
let stinker3 = si.mem();
stinker3.then(function(RAM){
RAMUSAGE = Math.round(((RAM.used/RAM.total)*100));
console.log(RAMUSAGE);
document.getElementById("RAMloads").innerHTML = RAMUSAGE+'%';
document.documentElement.style.setProperty('--RAMLOAD', RAMUSAGE*1.8 + 'deg');
});
setInterval( function() {getRAMhome();}, 5000 );
}
The code above fetches RAM load or GPU temperature every 5 seconds, it then updates a HTML/CSS gauge.
If writing a program like this is unviable in electron.js are there any other better options out there, I am open to playing around with new languages/libraries.
Remember, setInterval() sets a recurring timer, so your code is basically saying "Every five seconds create another timer for every five seconds." After ten seconds you will have 2 timers. After 20 you now have 8. After 60 seconds you have 4,096 of them. Every 5 seconds the number of timers doubles.
That sounds like a problem, doesn't it?
What you want to do is set one timer, once, per function:
function getRAMhome(){
let stinker3 = si.mem();
stinker3.then(function(RAM){
RAMUSAGE = Math.round(((RAM.used/RAM.total)*100));
console.log(RAMUSAGE);
document.getElementById("RAMloads").innerHTML = RAMUSAGE+'%';
document.documentElement.style.setProperty('--RAMLOAD', RAMUSAGE*1.8 + 'deg');
});
}
// Set timer outside of the function
setInterval(getRAMhome, 5000);
It's a common problem to confuse setInterval() which sets a repeating timer with setTimeout() which sets a one-shot timer that needs to be re-engaged. You're treating the former like the latter, with disastrous consequences.

express app: where to place a closed loop temperature control

i am new in express.js, i´ve only built some small client/server apps.
Now i want to create a temperature-controller with a PID-component. I don´t understand the architecture of express.js enough to decide where to place what.
I have a router to get the targetvalue from my Web-Client - that works. And
I have a router to get the current temperature-value. And third have a router to control the heatingelement.
Now i need somewhat of a loop, in which for every some seconds i can compare this values and calculate my output-value and send that value to my heatingelement.
Where to place what?
Greets, Freisei.
In Javascript you don't use a loop for this kind of thing, you use an Interval, set up with setInterval().
function doTheControlOperation() {
const setPoint = //get the temp set point
const current = //get the most recent temperature reading
const diff = current - setPoint
if (diff < 0) // turn on the element
else // turn off the element
}
var howOften = 10000 //ten seconds in milliseconds
setInterval (doTheControlOperation, howOften)
This code calls doTheControlOperation() every ten seconds.
I'm sure you know this kind of control system usually contains some hysteresis and protection against short-cycling. My example doesn't do any of that, obviously.

Socket.io countdown synchronously? [duplicate]

This question already has answers here:
Sync JS time between multiple devices
(5 answers)
Closed 5 years ago.
On my server I call two emits at the same time, which looks like this.
if (songs.length > 0) {
socket.emit('data loaded', songs);
socket.broadcast.to(opponent).emit('data loaded', songs);
}
The one is for opponent and the other for himself.
Once the data is loaded a countdown should appear for both players on my android app. For me it is important that they see the same number at the same time on their screen. To be precise it should run synchronized. How can I do this?
As far as js timers are concerned the will be a small amount of difference. We can reduce the difference in time with reduce of latency time, with the difference between the request and response time from the server.
function syncTime() {
console.log("syncing time")
var currentTime = (new Date).getTime();
res.open('HEAD', document.location, false);
res.onreadystatechange = function()
{
var latency = (new Date).getTime() - currentTime;
var timestring = res.getResponseHeader("DATE");
systemtime = new Date(timestring);
systemtime.setMilliseconds(systemtime.getMilliseconds() + (latency / 2))
};
res.send(null);
}
Elapsed time between sending the request and getting back the response need to be calculated, divide that value by 2. That gives you a rough value of latency. If you add that to the time value from the server, you'll be closer to the true server time (The difference will be in microseconds)
Reference: http://ejohn.org/blog/accuracy-of-javascript-time/
Hope this helps.
I have made an application and I had the same problem. In That case I solved the problem leaving the time control to the server. The server send to the client and the client increases the time. Maybe in your case you could have problem with connection. If the problem exists you can leave clients to increase time by yourself and some times send a tick with correct time for sync.
I could give you something like bellow but I am not tested.
This solution have these steps:
Synchronize timers for client and server. all users have the same difference with server timer.
For the desired response/request get clients time and find the differences with server time.
Consider the smallest as first countdown which will be started.
For each response(socket) subtract the difference from smallest and let the client counter starts after waiting as much as this time.
The client that gets 0 in response data will start immediately.
and the main problem that you may will have is broadcast method which you can't use if you think this solution will be helpful.
This is a post may will help you.
Add time into emit message.
Let's say that songs is an object with {"time" : timeString, "songs" : songsList}.
If we consider devices time is correct You can calculate the time needed for information to travel and then just use server timer as a main calculator.
The client would get the time when countdown should start:
var start = false;
var startTime = 0;
var myTime = new Date().getMilliseconds();
var delay = 1000 - myTime;
setTimeout(function(){
intervalID = setInterval(function(){
myTime = new Date().getTime();
//console.log(myTime); to check if there is round number of milliseconds
if (startTime <= myTime && start = true) {startCountdown();}
}, 100); //put 1000 to check every second if second is round
//or put 100 or 200 is second is not round
}, delay);
socket.on('data loaded', data){
startTime = data.time;
start = true;
}
function startCountdown(){
//your time countdown
}
And that works fine when 2 clients are from same time region, therefore You will need "time converter" to check if time is good due to time difference if You strictly need same numbers.
After the countdown has ended You should clearInterval(intervalID);

How can I implement an anti-spamming technique on my IRC bot?

I run my bot in a public channel with hundreds of users. Yesterday a person came in and just abused it.
I would like to let anyone use the bot, but if they spam commands consecutively and if they aren't a bot "owner" like me when I debug then I would like to add them to an ignored list which expires in an hour or so.
One way I'm thinking would be to save all commands by all users, in a dictionary such as:
({
'meder#freenode': [{command:'.weather 20851', timestamp: 209323023 }],
'jack#efnet': [{command:'.seen john' }]
})
I would setup a cron job to flush this out every 24 hours, but I would basically determine if a person has made X number of commands in a duration of say, 15 seconds and add them to an ignore list.
Actually, as I'm writing this answer I thought of a better idea.. maybe instead of storing each users commands, just store the the bot's commands in a list and keep on pushing until it reaches a limit of say, 15.
lastCommands = [], limit = 5;
function handleCommand( timeObj, action ) {
if ( lastCommands.length < limit ) {
action();
} else {
// enumerate through lastCommands and compare the timestamps of all 5 commands
// if the user is the same for all 5 commands, and...
// if the timestamps are all within the vicinity of 20 seconds
// add the user to the ignoreList
}
}
watch_for('command', function() {
handleCommand({timestamp: 2093293032, user: user}, function(){ message.say('hello there!') })
});
I would appreciate any advice on the matter.
Here's a simple algorithm:
Every time a user sends a command to the bot, increment a number that's tied to that user. If this is a new user, create the number for them and set it to 1.
When a user's number is incremented to a certain value (say 15), set it to 100.
Every <period> seconds, run through the list and decrement all the numbers by 1. Zero means the user's number can be freed.
Before executing a command and after incrementing the user's counter, check to see if it exceeds your magic max value (15 above). If it does, exit before executing the command.
This lets you rate limit actions and forgive excesses after a while. Divide your desired ban length by the decrement period to find the number to set when a user exceeds your threshold (100 above). You can also add to the number if a particular user keeps sending commands after they've been banned.
Well Nathon has already offered a solution, but it's possible to reduce the code that's needed.
var user = {};
user.lastCommandTime = new Date().getTime(); // time the user send his last command
user.commandCount = 0; // command limit counter
user.maxCommandsPerSecond = 1; // commands allowed per second
function handleCommand(obj, action) {
var user = obj.user, now = new Date().getTime();
var timeDifference = now - user.lastCommandTime;
user.commandCount = Math.max(user.commandCount - (timeDifference / 1000 * user.maxCommandsPerSecond), 0) + 1;
user.lastCommandTime = now;
if (user.commandCount <= user.maxCommandsPerSecond) {
console.log('command!');
} else {
console.log('flooding');
}
}
var obj = {user: user};
var e = 0;
function foo() {
handleCommand(obj, 'foo');
e += 250;
setTimeout(foo, 400 + e);
}
foo();
In this implementation, there's no need for a list or some global callback every X seconds, instead we just reduce the commandCount every time there's a new message, based on time difference to the last command, it's also possible to allow different command rates for specific users.
All we need are 3 new properties on the user object :)
Redis
I would use the insanely fast advanced key-value store redis to write something like this, because:
It is insanely fast.
There is no need for cronjob because you can set expire on keys.
It has atomic operations to increment key
You could use redis-cli for prototyping.
I myself really like node_redis as redis client. It is a really fast redis client, which can easily be installed using npm.
Algorithme
I think my algorithme would look something like this:
For each user create a unique key which counts the commands consecutively executed. Also set expire to the time when you don't flag a user as spammer anymore. Let's assume the spammer has nickname x and the expire 15.
Inside redis-cli
incr x
expire x 15
When you do a get x after 15 seconds then the key does not exist anymore.
If value of key is bigger then threshold then flag user as spammer.
get x
These answers seem to be going the wrong way about this.
IRC Servers will disconnect your client regardless of whether you're "debugging" or not if the client or bot is flooding a channel or the server in general.
Make a blanket flood control, using the method #nmichaels has detailed, but on the bot's network connection to the server itself.

Resources