Updating the random number within a variable? - javascript

How can a variable with a random number be updated. I'm using three.js. Here is my code. It works the first time it's called generating a sprite to a random location but then it just keeps going back to the same location. I thought that by calling the variables before they were used I would be updating them but it's not working.
var locX = Math.floor((Math.random()*450)+1);
locX *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
var locY = Math.floor((Math.random()*250)+1);
locY *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
var locZ = Math.floor((Math.random()*350)+1);
locZ *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
function spriteAI1() {
//console.log(c2Sprite.position.x);
//console.log(ranLocX);
//console.log(ranTen);
if (c2Sprite.position.x > 30 && c2Sprite.position.x <= 450) {
c2Sprite.translateX( -10 );
} else if (c2Sprite.position.x < -31 && c2Sprite.position.x >= -450) {
c2Sprite.translateX( 10 );
} else if (c2Sprite.position.z < 31 && c2Sprite.position.x < 31 && c2Sprite.position.z > -29 && c2Sprite.position.x > -29) {
locX;
locY;
locZ;
//c2Sprite.delete;
//scene.remove(c2Sprite);
//console.log("AI1");
c2Sprite.position.set( locX, locY, locZ );
//scene.add( c2Sprite );
//c2Sprite.clone;
}
}

If you want different values each call, declare the vars inside the function, not outside of it. As you currently have it, the vars are set once, and the function, however many times it's called, will reference those once-set values.

Related

Recursively setting a value depending on range using JavaScript

I don't know how to word this but this is what I'm trying to do:
if (score >= 0 && score <= 10) overallScore = 0;
else if (score >= 11 && score <= 20) overallScore = 1;
else if (score >= 21 && score <= 30) overallScore = 2;
else if (score >= 31 && score <= 40) overallScore = 3;
else if (score >= 91 && score <= 100) overallScore = 9;
...
Is there any way to recursively do this using a function?
overallScore = Math.max(0, Math.floor((score - 1) / 10));
no need for recursion. But if you need that:
const getOverall = score => score <= 10 ? 0 : getOverall(score - 10) + 1;
Recursion is not really appropriate here, since you can get the required value in constant time. Recursion becomes interesting when you need at least O(logn) time.
But as you ask for it, here is one way to make it recursive:
function range(score, depth = 0) {
return score <= 10 || depth >= 9 ? 0 : range(score-10, depth+1) + 1;
}
console.log(range(0)); // 0
console.log(range(10)); // 0
console.log(range(11)); // 1
console.log(range(60)); // 5
console.log(range(91)); // 9
console.log(range(110)); // 9

Parse course in textual way from course in degrees?

So im making a compass in node-red, it should have course in degrees (int) as input and string(course) as output:
So i need function that takes in integer and gives me heading in string. How to do it simple and reliable?
I have to convert course 0-360 degrees in string for example: NORTH, NORTH-EAST, EAST......
I tried the following:
var course = parseInt(courseFloatDegrees);
var courseTxt = "";
if (course >= 349 && course <= 11 || course <= 359 && course >= 349 || course === 0) courseTxt = "N";
else if (course >= 11 && course <= 33) courseTxt = "NNE";
else if (course >= 33 && course <= 56) courseTxt = "NE";
else if (course >= 56 && course <= 78) courseTxt = "ENE";
else if (course >= 78 && course <= 101 || course == 90) courseTxt = "E";
else if (course >= 101 && course <= 124) courseTxt = "ESE";
else if (course >= 124 && course <= 146) courseTxt = "SE";
else if (course >= 146 && course <= 168) courseTxt = "SSE";
else if (course >= 168 && course <= 191 || course == 180) courseTxt = "S";
else if (course >= 191 && course <= 214) courseTxt = "SSW";
else if (course >= 214 && course <= 236) courseTxt = "SW";
else if (course >= 236 && course <= 258) courseTxt = "WSW";
else if (course >= 258 && course <= 281 || course == 270) courseTxt = "W";
else if (course >= 281 && course <= 303) courseTxt = "WNW";
else if (course >= 303 && course <= 326) courseTxt = "NW";
else if (course >= 326 && course <= 349) courseTxt = "NNW";
else courseTxt = "INVALID"
But sometimes i get nothing(null-empty string) or "INVALID". Does anybody know fast and simple way to do this without that much else if statements?
There could be ways of doing this more 'simply' in code, but your approach should work. The reason it doesn't is because your if statements are messed up around the 'N' region.
if ((course >= 349 && course <= 11) || (course <= 359 && course >= 349) || (course === 0)) courseTxt = "N";
If you look at the very first two conditions, they are illogical. More than 349 but less than 11? That's never going to happen. If you have a course of 7 degrees, that doesn't meet any of the specified criteria currently.
So the first thing to do is resolve that problem. You need to adjust the line to use OR instead of AND
if(course < 11 || course > 349) courseTxt = "N";
Now your code will be able to handle the settings either side of 360/0 degrees.
That should be enough to get your current code to work, assuming course is always less or equal to 360.
You asked if there is a way to avoid all the if statements. There are probably hundreds of ways to do this, but the simplest, other than if or case statements would probably be to use an array to look up the heading. Here is an example of how it could be done. You could obviously hardcode the step value, but this way you could update your array with any number of more granular headings, and it will still work.e
function getCourse(course)
{
// define our values
var degs = 360;
var strs =
["N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW"];
// make sure course is always within the expected range in case it is incremented past 360
course = course % degs;
// get the step amount based on the number of compass headings we have
var step = degs/strs.length;
// adjust for the last few degrees on the scale which will be north
if(course > degs - (step/2)) course += step/2;
// now just divide the course by the step and read off the relevant heading
var index = Math.floor(course / step);
return strs[index];
}
Nicky,
I used an approach similar to Toby's -- calculating an index into an array of course strings:
var deg = course % 360;
var dirs = ["N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW","N"];
var idx = Math.round(deg * (dirs.length-1)/360);
var dir = dirs[idx];
The trick is to repeat the "N" element at the beginning and end of the array, and use Math.round(...) to jump to the closest integer index number.

Trouble optimizing some code

I'm trying to right a function with three.js. every thing is working as intended but the FPS considerably drops after like 20-30 seconds of running the function. The function is set up to move a sprite then destroy the sprite after it reaches it's destination. Then it spawns a new sprite at a random location. Before moving the sprite it's moving at about 30 FPS. When I start moving the sprite the FPS drops to low 20's. After about 20 to 30 seconds it's at about 9. If I stop moving the sprite the FPS is back up at 30. But if I try to move the sprite again instead of repeating the earlier process it just goes right back to about 9. Now I know that javascript is a garbage collected langue so I figured it just needs some time to clean things up. But even if I let it sit for 10 minutes it still just goes right back down to 9 FPS. On the other had if I reload the page the process starts all over. I also tried just moving the sprite instead of destroying it and respawing but I get the same issue. Also I tried to use the .dispose method but had no luck. Here's the code.
function spriteAI1() {
//console.log(c2Sprite.position.x);
//console.log(ranLocX);
//console.log(ranTen);
console.log(c2Sprite.position);
//var ranTen = Math.floor((Math.random()*8)+2);
if (c2Sprite.position.x > 30 && c2Sprite.position.x <= 450) {
//var ranTen = Math.floor((Math.random()*8)+1);
c2Sprite.translateX( -6 );
} else if (c2Sprite.position.y > 30 && c2Sprite.position.y <= 250) {
//var ranTen = Math.floor((Math.random()*8)+1);
c2Sprite.translateY( -6 );
} else if (c2Sprite.position.z > 30 && c2Sprite.position.z <= 350) {
//var ranTen = Math.floor((Math.random()*8)+1);
c2Sprite.translateZ( -6 );
} else if (c2Sprite.position.x < -30 && c2Sprite.position.x >= -450) {
//var ranTen = Math.floor((Math.random()*8)+1);
c2Sprite.translateX( 6 );
} else if (c2Sprite.position.y < -30 && c2Sprite.position.y >= -250) {
//var ranTen = Math.floor((Math.random()*8)+1);
c2Sprite.translateY( 6 );
} else if (c2Sprite.position.z < -30 && c2Sprite.position.z >= -350) {
//var ranTen = Math.floor((Math.random()*8)+1);
c2Sprite.translateZ( 6 );
} else if (c2Sprite.position.x < 31 && c2Sprite.position.y < 31 && c2Sprite.position.z < 31 && c2Sprite.position.x > -31 && c2Sprite.position.y > -31 && c2Sprite.position.z > -31) {
var locX = Math.floor((Math.random()*450)+1);
locX *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
var locY = Math.floor((Math.random()*250)+1);
locY *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
var locZ = Math.floor((Math.random()*350)+1);
locZ *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
//c2Sprite.delete;
scene.remove(c2Sprite);
//console.log("AI1");
//geometry.dispose();
//material.dispose();
//texture.dispose();
c2ImgMaterial.dispose();
c2Sprite.position.set( locX, locY, locZ );
scene.add( c2Sprite );
//c2Sprite.clone;
}
}

Else if statement with 3 or more conditions?

I have been trying for a long time and cant seem to figure out what i'm doing wrong. The first too conditions seem to work but the third fails.
function spriteAI1() {
if (c2Sprite.position.x >= 30 && c2Sprite.position.x <= 450) {
c2Sprite.translateX( -10 );
} else if (c2Sprite.position.x <= 30 && c2Sprite.position.x >= -450) {
c2Sprite.translateX( 10 );
} else if (c2Sprite.position.z = 30 && c2Sprite.position.x = 30) {
c2Sprite.remove;
c2Sprite.clone;
}
else{}
}
function spriteAI2() {
if (c2Sprite.position.z >= 30 && c2Sprite.position.z <= 350) {
c2Sprite.translateZ( -10 );
} else if (c2Sprite.position.z <= -30 && c2Sprite.position.z >= -350) {
c2Sprite.translateZ( 10 );
} else if (c2Sprite.position.x = 30 && c2Sprite.position.z = 30) {
c2Sprite.remove;
c2Sprite.clone;
}
else{}
}
I'm getting an error on the line
else if (c2Sprite.position.x = 30 && c2Sprite.position.z = 30)
the error says invalid left hand in assignment. But the other function has basically the same line and doesn't generate a error.
I can see two problems in your code.
First, comparison is done using == (double equal signs), not a single one (that's assigning a value). That's probably the source of your problem.
In second place, your last two conditions match a common group of values (they are intersected), in the case when c2Sprite.position.x equals 30, it will enter the second "if". It will match the condition for the third one, but it will not run it.
Make sure you always define well-separated groups of conditions (unless that's the behavior that you want).
Just to make it clear:
if (x >= 30) {
/* this matches 30 and above */
}
else if (x == 30) {
/* this won't execute on x == 30, because it entered the first "if" */
}
You should have done this:
if (x > 30) {
/* this matches numbers strictly greater than 30, i.e. 31, 32, 33... */
}
else if (x == 30) {
/* this will match x == 30 */
}
else {
/* any other value for x */
}

average of five valuesin javascript

I work for a charter school and I'm just learning my way around javascript. I've got some code written by the person who formerly filled my position and it seems to me that it should work, but it doesn't.
This is what I have in the custom HTML page in my SIS:
GED Status: <script language="Javascript">gedCheck('~(ELC_tspp_GED_read_score)','~ (ELC_tspp_GED_wri_score)','~(ELC_tspp_math_GED_score)','~(ELC_science_state_exam_score)','~(soc_sci_state_exam_score)')</script>
That seems to be retrieving the values from the various DB fields correctly, as the javascript routine is evaluating each value to ensure it's at least 410. But that's as far as it goes...
Here's the javascript routine code:
function gedCheck(read,wri,math,sci,soc) {
if( read < 0 && read > 1000 )
read = 0;
if( wri < 0 && wri > 1000 )
wri = 0;
if( math < 0 && math > 1000 )
math = 0;
if( sci < 0 && read > 1000 )
read = 0;
if( soc < 0 && soc > 1000 )
soc = 0;
if ( (read >= 410) && (wri >= 410) && (math >= 410) && (sci >= 410) && (soc >= 410) ) {
if( read+wri+math+sci+soc >= 2250 )
document.write( "PASSED" )
}
else
document.write( "NOT PASSED" )
}
It is supposed to be checking that every score in the GED tests is at least 410, and that the sum of all scores should be at least 2250. However, it's not getting as far as the last part. It's returning "PASSED" if all the scores are over 410.
I tried this but it, also, doesn't work.
function gedCheck(read,wri,math,sci,soc) {
if( read < 0 && read > 1000 )
read = 0;
if( wri < 0 && wri > 1000 )
wri = 0;
if( math < 0 && math > 1000 )
math = 0;
if( sci < 0 && read > 1000 )
read = 0;
if( soc < 0 && soc > 1000 )
soc = 0;
if ( (read >= 410) && (wri >= 410) && (math >= 410) && (sci >= 410) && (soc >= 410) ) {
if( read+wri+math+sci+soc/5 >= 450 )
document.write( "PASSED" )
}
else
document.write( "NOT PASSED" )
}
Would somebody please help me work this out so it either averages all 5 numbers and returns "PASSED" only if the average is 450, OR simply adds all 5 numbers and returns "PASSED" only if the total sum is 2250 or greater?
To get the average, you'll want to do this:
(((read + wri + math + sci + soc) / 5) > 450)
The parenthesis around the addition ensures that you divide the sum of all scores by 5. The way that you have it now, you are only dividing the soc score by 5.
Edit (Rewriting the entire method):
function gedCheck(read, wri, math, sci, soc) {
// As was said before, these should all be ORs
// If the score is less than 0, OR greater than 1000
if( read < 0 || read > 1000 ) {
read = 0;
}
if( wri < 0 || wri > 1000 ) { // I prefer to put the braces around all if/else statements just for absolute clarity
wri = 0;
}
if( math < 0 || math > 1000 ) {
math = 0;
}
if( sci < 0 || read > 1000 ) {
read = 0;
}
if( soc < 0 || soc > 1000 ) {
soc = 0;
}
if ( read >= 410 && // Doing this will only pass the student
wri >= 410 && // if ALL of the conditions are met.
math >= 410 &&
sci >= 410 &&
soc >= 410 &&
( (read + wri + math + sci + soc) >= 2250 || // Separated more for clarity
((read + wri + math + sci + soc) / 5) > 450) ) {
// Either all scores total over 2250
// Or the average of all 5 are over 450 to pass
document.write( "PASSED" )
}
else
document.write( "NOT PASSED" )
}
What about
if ((read >= 410) &&
(wri >= 410) &&
(math >= 410) &&
(sci >= 410) &&
(soc >= 410) &&
(read+wri+math+sci+soc >= 2250)) {
document.write( "PASSED" )
} else {
document.write( "NOT PASSED" )
}
function gedCheck(read, wri, math, sci, soc) {
if( read < 0 || read > 1000 )
read = 0;
if( wri < 0 || wri > 1000 )
wri = 0;
if( math < 0 && math > 1000 )
math = 0;
if( sci < 0 && read > 1000 )
read = 0;
if( soc < 0 && soc > 1000 )
soc = 0;
var total = read + wri + math + sci + soc;
if (read >= 410 && wri >= 410 && math >= 410 && sci >= 410 && soc >= 410 && total >= 2250) {
document.write("PASSED");
} else {
document.write("NOT PASSED");
}
}
That whole first section was impossible code. It was checking to see if a number was BOTH less than zero and greater than 1000. Obviously impossible, so I changed it to use OR.
I also created a total variable, which you can check in the same way as everything else.
Using an array here will help you reduce the amount of duplicated code
function gedCheck(read, wri, math, sci, soc) {
var subjects, totalScore, averageScore;
subjects = [read, wri, math, sci, soc];
totalScore = 0;
averageScore = 0;
for (var i = 0; i < subjects.length; i++) {
if (subjects[i] < 0 || subjects[i] > 1000) {
subjects[i] = 0;
}
totalScore += subjects[i];
};
averageScore = totalScore / subjects.length;
if (averageScore >= 450 || totalScore >= 2250) {
document.write("PASSED");
} else {
document.write("NOT PASSED");
}
}
The first loop iterates through each subject and sets it to zero if necessary, and then adds it to the total score variable.
Then the total score is averaged by the number of subjects.
Then if the average score is equal to or greater than 450, or equal to or greater than 2250, it passes.

Categories

Resources