JS for loop not showing correct result - javascript

The question:
At exactly 10:25:21 , car speed is at 6.
11 mins later which is 10:36:21, car speed increased by 1, so is 7.
After 10:46:21 until 12:00:00, for every min, car speed increase steadily by 1, so is 8 onwards.
<script>
var date = new Date();
date.setHours(10);
date.setMinutes(25);
date.setSeconds(21);
var speed;
for (let i = 0; i < 95; i++) {
if (i < 35) {
speed = 6;
}
//increase speed by 1 after 10:36:21
else if (i < 45)
{ speed = 7;
}
// speed continously increase by 1 after 10:46:21
else
{ speed++;
}
date.setMinutes(25+i);
document.write(date + ":" + speed + "m/s <br><br>");
}
</script>
The result is showing me 6 till 10:59:21 instead of 10:36:21
And when the speed increased to 7, the hours and minutes increased too.
Any help is appreciated. I apologized if i'm a newbie here.

The logic in the code is weird, to say the least.
Rather than use a counter to manually work through each minute, why not simply create dates that start and end the trip, and mark the two places where the speed increases:
var startTime = new Date();
startTime.setHours(10);
startTime.setMinutes(25);
startTime.setSeconds(21);
var endTime = new Date();
endTime.setHours(12);
endTime.setMinutes(0);
endTime.setSeconds(0);
var time1 = new Date();
time1.setHours(10);
time1.setMinutes(36);
time1.setSeconds(21);
var time2 = new Date();
time2.setHours(10);
time2.setMinutes(46);
time2.setSeconds(21);
var thisTime = startTime;
var speed = 0;
while (thisTime < endTime) {
if (thisTime < time1) {
speed = 6;
} else if (thisTime < time2) {
speed = 7;
} else {
speed++;
}
document.write(thisTime + ":" + speed + "\n<br>");
thisTime.setMinutes(thisTime.getMinutes() + 1);
}
Using thisTime as the current time in the route, we just update that by 1 minute for each iteration. This is a while loop that runs from the start time to the end time, so as soon as thisTime is greater than endTime it ends the loop.

With
for (let i = 0; i < 95; i++) {
you are iterating over i which holds the amount of minutes - 25, because you started with 25 minutes.
if (i < 35) {
will be true until the 35th loop (including).
You could just subtract your start value:
if (i < 10) {
speed = 6;
}
//increase speed by 1 after 10:36:21
else if (i < 20)
{ speed = 7;
}

I think you have a problem with the amounts you are using, besides, here you have another idea:
var date = new Date();
date.setHours(10);
date.setMinutes(25);
date.setSeconds(21);
var speed;
var dateToShow;
function addMinutes(date, minutes) {
return new Date(date.getTime() + minutes*60000);
}
for (let i = 1; i < 96; i++) {
if (i < 11) {
speed = 6;
}
//increase speed by 1 after 10:36:21
else if (i < 22)
{ speed = 7;
}
// speed continously increase by 1 after 10:46:21
else
{ speed++;
}
dateToShow = addMinutes(date, i);
document.write(dateToShow + ":" + speed + "m/s <br></br>")
}
I think this solves your problem.
I have added an extra function to add the minutes to a new date so you won't have more problems

Before you start coding anything, you need to establish a few things first: Objects, Facts, Variables, States and Output
Objects:
1 What objects provide something that you need to use in your code?
2 What objects do you need to create in your code?
3 What objects do you need to manipulate in your code?
4 What objects are completely irrelevant to your code?
5 What will you do with any object used in your code?
Facts:
What are the known, static, facts?
What value or values will never change during the execution of the code but are required in the code?
Variables:
What are the unknowns?
What value or values will, or could, change during the execution of the code?
States:
1 What is the starting state of any object(s) or variable(s)?
2 What is desired/required final state of any object(s) or variable(s)?
Output:
1 Do you need to provide any "printed" output - eg, to the screen or the console?
2 Do you need to return anything - eg, is this a function that returns one or more values?
So, with this in mind, if we look at your question:
Objects:
There are two:
Car - completely irrelevant as nothing in the question is based on the type of vehicle, so we can ignore this object
Clock - required to determine the elapse of time in minutes. But, there is no need to create this as an object, a variable will handle this as we only actually need to know the time the clock would show. Presumbably, the car's clock or the driver's watch, for example, would be used to determine the time, but we are not looking at either as we have our own method of determining the time.
We could create a custom object for the car and its speed. However, the only value we would maintain on that object would be the speed. If, however, we needed to run the code for multiple vehicles, using different times, we could create an object for each. That is not required here as there is only one car. Likewise, the clock's value could be added to a car object, but, again, we only really need to know the time, not the fact that it is shown on a clock or that the clock/watch actually exists.
Facts:
There are six:
1 Start time
2 Speed change 1 time
3 Speed change 2 time
4 End time
5 We are checking the speed every minute
6 The speed is dependant on the time
The four times are static values, so we can create variables to hold these values and nothing in the code will change these values. Often, these are created using const but I've used var in my code example.
The fact that we are checking/changing the speed every minute just provides us with a reason to pinpoint particular times between the start and end times. A variable is required to handle this as the current time value will change during the running of the code.
States:
There are two initial states:
1 The time starts at 10:25:21
2 We start driving at 6mph
There is one final state:
The time stops at 12:00:00
Note that the speed will be whatever the code has calculated, so has an unknown final state
Output:
In this case, the output is written into the document. When testing, it is more usual to output to the console, using console.log(...)
Given all that, we can look at what code is required.
1 Create the static variables - the four points in time
2 Create the other variables - the speed and the current time
3 Create a loop that will move us through time from the "Start time" to the "End time", one minute at a time, using the current time variable to keep track of where we are
4 Create if/else tests to determine what the current time is in relation to the static times
5 Determine what speed the car should be going at that time
6 Output the time and speed - as we are not in a function, we output to either the page or the console as desired as we are not returning a value to other code
7 End the loop once "End time" is reached.
There are three types of loops we could use:
1 a for loop - this is normally used to iterate over collections, by referencing the collection's items by index number, or to provide a counter that can be used within the loop. As we don't need a counter and don't have a collection, we won't use this
2 a while loop - this is not dependant on counters, it simply tests a condition statement before starting an iteration of the loop. If the test fails, the condition is not met and the loop doesn't run.
3 a do/while loop - similar to a while loop except that the condition is checked AFTER the first iteration, so will run at least once. If the condition is met, the loop starts again. We could use this as we know that the loop needs to run at least once. However, if the current time was already after the end time, we would not want the loop to run, so I have avoided this loop
There are other types of loops available, such as for/in, for/of and forEach but these are generally used for objects and collections, so are not relevant here.
Thus, the best loop to use is the while loop as the requirement is to "...do something until..."
So, now we know all we need to know to construct the code.
// Create the static time variables
// Start time
var startTime = new Date();
startTime.setHours(10);
startTime.setMinutes(25);
startTime.setSeconds(21);
// Speed change 1 time
var endTime = new Date();
endTime.setHours(12);
endTime.setMinutes(0);
endTime.setSeconds(0);
// Speed change 2 time
var time1 = new Date();
time1.setHours(10);
time1.setMinutes(36);
time1.setSeconds(21);
// End time
var time2 = new Date();
time2.setHours(10);
time2.setMinutes(46);
time2.setSeconds(21);
// Create the other variables
// "thisTime" is initially set to "startTime" but will be incremented by the loop code
var thisTime = startTime;
// A variable to hold the current speed through the loops
// This could be set to 6, but if the loops don't run (ie, the condition is not met), we would not want the speed to be 6
var speed = 0;
// Start a loop - check that the current time (thisTime) is less than the endTime
while (thisTime < endTime) {
// If it is, check if we have reached the first speed change time - "time1"
if (thisTime < time1) {
// If we haven't, keep the speed at 6
speed = 6;
// If we have, check if we have reached the second speed change time - "time2"
} else if (thisTime < time2) {
// If we haven't, the speed is 7
speed = 7;
// If we have, we can now increase the speed 1mph for each minute (ie, for all further iterations of the loop)
} else {
speed++;
}
// Output the time and speed
document.write(thisTime + ":" + speed + "\n<br>");
// Add one minute to the thisTime variable which will be tested at the start of the next iteration of the loop
thisTime.setMinutes(thisTime.getMinutes() + 1);
}
And, to convert this all back into English:
Given these four points in time and checking my speed every minute, I start driving at the first time point. If I've not reached the second time point, I'm doing 6mph. But, if I have reached that, but haven't yet reached the third time point, I'm doing 7mph. But if I've reached that, I keep increasing my speed by 1mph for every minute. I stop driving at the final time point. Throughout, I'm making a note of the time and my speed.

Related

Speeding up an object in JS game after every 10 points

I am trying to speed up an object in JS game x2 every 10 points.
In the game at the same time I use
let game = setInterval(draw,100);
Which technique should I try? I have been searching for a really long time yet trying to do it with changing the setInterval didn't work as it should (it accelerated over and over).
Would be really grateful for any advice (not looking for a ready code, just saying!).
You just need to hang onto the game value returned from setInterval. You can use that to stop the current interval timer with clearInterval() and then start a new one with your new rate. Since you didn't post much code here's a contrived example that counts to 100 speeding up every 10 numbers:
let i = 0
let speed = 1
let basespeed = 1000
function play() {
console.log("play", i++)
if (i % 10 == 0) {
speed *= 2
clearInterval(int)
if (i >= 100) return
int = setInterval(play,basespeed/speed)
}
}
let int = setInterval(play, basespeed)

How to make a loop do something during a certain time frame in JS

I'm pretty new to JavaScript so please keep that in mind when answering my question.
I'm trying to make something where it asks the user questions during a certain time frame. Questions are asked using the window.prompt() method. I have a do while loop going on in a function called askquestions() as you can see:
var randomNo1;
var randomNo2;
var time;
do {
randomNo1 = Math.random() * 9;
randomNo1 = Math.round(randomNo1);
randomNo2 = Math.random() * 9;
randomNo2 = Math.round(randomNo2);
window.prompt("What is " + randomNo1 + " + " + randomNo2 + "?")
} while (time == 0);
How can I make it that time = 1 after 30 seconds?
Thanks in advance for your help.
You can use:
document.setTimeout("str js code/func name call",millisec);
document.setTimeout("time=1;",30000);
to execute some js code once with delay
And for your specification the following method may be needed for other timing purposes:
document.setInterval("js code /func name call",millisec);
to execute at an interval
Besides,it is strongly not recommended to have a "waiting while" in your js code to provide some timing service, which may cause browser to take this thread as a not-responding thread
You could get the milliseconds since Jan 1 1970 using
date = new Date();
mil = date.getTime();
You do that at the beginning of your code for comparison, then get a more current one in the loop. If the time between the two is greater than some number of milliseconds, you can exit the loop (while(curDate.getTime()-mil<30000) would be 30 seconds)

Create a scheduled Greasemonkey script

I need to create a special kind of script.
I want to show a message at certain times of the day. I've tested the code in Firebug Console and it works. The code is:
//Getting the hour minute and seconds of current time
var nowHours = new Date().getHours() + '';
var nowMinutes = new Date().getMinutes() + '';
var nowSeconds = new Date().getSeconds() + '';
var this_event = nowHours + nowMinutes + nowSeconds;
//172735 = 4PM 25 Minutes 30 Seconds. Just checked if now is the time
if (this_event == "162530") {
window.alert("Its Time!");
}
I feel that the Script is not running every second. For this to work effectively, the script has to be able to check the hour minutes and second "Every Second". I'm not worried about the performance, I just have to be accurate about the timing (to the second).
How do I do this?
Of course the script isn't running each second, GM-scripts run once when the document has been loaded.
Calculate the difference between the current time and the target-time and use a timeout based on the difference:
var now=new Date(),
then=new Date(),
diff;
then.setHours(16);
then.setMinutes(15);
then.setSeconds(30);
diff=then.getTime()-now.getTime();
//when time already has been reached
if(diff<=0){
window.alert('you\'re late');
}
//start a timer
else{
window.setTimeout(function(){window.alert('it\'s time');},diff);
}
Javascript doesn't guarantee your timeouts and other such events fire exactly on-time.
You should compare two Date objects using >= and remove the timeout or what ever other method you're using for tracking the time inside the matching if (and then reset it if necessary).
For more details see: https://stackoverflow.com/a/19252674/1470607
Alternatively you can use string comparison (but with caveats): https://stackoverflow.com/a/6212411/1470607

HTML Canvas Interval vs RequestAnimationFrame

So, maybe total brainfart here. The syntax for setInterval() is pretty clear. Do something every x miliseconds. How is this best translated to using the requestAnimationFrame() ?
I have about 300 objects and each is supposed to perform an animation sequence at a certain interval (every 8, 6, 2, etc seconds)? How can I best accomplish this using requestAnimationFrame() which gets called ~60 times a second? There is probably an easy answer, I just, for the life of me, can't figure it out.
To force requestAnimationFrame to stick to a specific FPS you can use both at once!
var fps = 15;
function draw() {
setTimeout(function() {
requestAnimationFrame(draw);
// Drawing code goes here
}, 1000 / fps);
}
A little weird, but noth the most confusing thing in the world.
You can also use requestAnimationFrame not with FPS but with elapsed time in order to draw objects that need to be updated based on the time difference since the last call:
var time;
function draw() {
requestAnimationFrame(draw);
var now = new Date().getTime(),
dt = now - (time || now);
time = now;
// Drawing code goes here... for example updating an 'x' position:
this.x += 10 * dt; // Increase 'x' by 10 units per millisecond
}
These two snippets are from this fine article, which contains additional details.
Good question by the way! I don't think I've seen this answered on SO either (and I'm here way too much)
requestAnimationFrame is pretty low level, it just does what you already said: roughly gets called at 60fps (assuming the browser can keep up with that pace). So typically you would need to build something on top of that, much like a game engine that has a game loop.
In my game engine, I have this (paraphased/simplified here):
window.requestAnimationFrame(this._doFrame);
...
_doFrame: function(timestamp) {
var delta = timestamp - (this._lastTimestamp || timestamp);
for(var i = 0, len = this.elements.length; i < len; ++i) {
this.elements[i].update(delta);
}
this._lastTimestamp = timestamp;
// I used underscore.js's 'bindAll' to make _doFrame always
// get called against my game engine object
window.requestAnimationFrame(this._doFrame);
}
Then each element in my game engine knows how to update themselves. In your case each element that should update every 2, 6, 8 seconds needs to keep track of how much time has passed and update accordingly:
update: function(delta) {
this.elapsed += delta;
// has 8 seconds passed?
if(this.elapsed >= 8000) {
this.elapsed -= 8000; // reset the elapsed counter
this.doMyUpdate(); // whatever it should be
}
}
The Canvas API along with requestAnimationFrame are rather low level, they are the building blocks for things like animation and game engines. If possible I'd try to use an existing one like cocos2d-js or whatever else is out there these days.

Add a countdown in my scoring script (javascript/jquery)

I have the following script in a js file:
// Ad score
var score = 0;
//$('#score').text(score);
function foundMatchingBlocks(event, params) {
params.elements.remove();
score += 100;
$('#score').text(score);
};
Now on each matching, 100 points are added to var score. This all works. Now I want to extend this a bit. As soon as the page loads I want to start a countdown to reduce the number of points (starting with 100) with 1 point a second for 60 seconds. So the minimum number of points a user can get is 40. When someone gets the points, the counter should reset and countdown again.
Example:
Page loads (timer starts from 100)
User has a match after 10 seconds (+90 points are added)
Counter resets and countdown from 100 again
User found a match after 35 sec (+65 points are added)
etc etc
Problem is, I have no idea how to do this :( Hope someone can help me with this.
The above is fixed, thanks all for helping!!!
The big picture is, you'll need to become pretty familiar with timeouts and intervals in javascript. This is the reference page I keep going back to when I need to refresh my memory: http://www.elated.com/articles/javascript-timers-with-settimeout-and-setinterval/
For your specific task, you'll probably want to use an Interval that triggers every 1000 milliseconds to calculate the second-by-second point reduction, and a separate Timeout for failure that resets every time the user completes their challenge.
Here are a few tips for working with timeouts and intervals that usually lead to followup questions:
When you set a timeout, always capture the return value (I think it's basically a random integer). Save it to some global var for convenience.
var failureTimer; // global var high up in your scope
failureTimer = setTimeout ( "gameOver()", 100000 ); // 100 seconds * 1000ms
Then in whichever method gets called when the player completes their challenge, you call this:
clearTimeout (failureTimer); // resets the timer and gives them another 100 seconds
failureTimer = setTimeout ( "gameOver()", 100000 ); // yes call this again, to start the 100 sec countdown all over again.
The second pain point you're likely to encounter when working with Timeouts and Intervals is how to pass parameters to the functions like gameOver() in my example above. You have to use anonymous functions, as described here:
Pass parameters in setInterval function
For more on anonymous functions, this is a good overview:
http://helephant.com/2008/08/23/javascript-anonymous-functions/
Good luck with your project! Let me know if you have any questions.
Here's some code without the use of timers. Call startCountdown() every time you want to re-initialize the count-down. Call getAvailableScore() when you want to fetch the current available score. You will have to decide what to do when the available score goes to zero.
var beginCountDownTime;
function startCountdown() {
beginCountDownTime = new Date();
}
function getAvailableScore {
var now = new Date();
var delta = (now.getTime() - beginCountDownTime.getTime()) * 1000; // time elapsed in seconds
var points = 100 - (delta / 60);
return(Math.round(Math.max(points, 0))); // return integer result >= 0
}
Maybe something like:
// Ad score
var score = 0;
var pointsAvailable = 100;
//$('#score').text(score);
function foundMatchingBlocks(event, params) {
params.elements.remove();
score += pointsAvailable;
$('#score').text(score);
pointsAvailable = 100;
};
$(document).ready(function() {doTimer();});
function doTimer() {
setTimeout('reducePoints()',1000);
}
function reducePoints() {
if(pointsAvailable>40) {
pointsAvailable--;
}
doTimer();
}

Categories

Resources