I'm working on a script that fetches and then parses a large amount of XML documents. The relevant part of the code is shown below. (URL has been hidden for privacy. The asterisks in the code are not actually there, they are used for reference later in the question)
var xmlhttp = new XMLHttpRequest();
var xmlDoc;
var chunk = parseInt(1, 10);
var subChunk = parseInt(0, 10);
var indvCount = parseInt(0, 10);
var total = parseInt(0, 10);
var max = parseInt(5000, 10);
var end = parseInt(chunk, 10) * parseInt(20, 10);
var start = parseInt(end, 10) - parseInt(19, 10);
function loadXML() {
xmlhttp.abort();
*xmlhttp.open("GET", "URL-GOES-HERE?start=" + start + "&end=" + end, false);
xmlhttp.setRequestHeader('Content-Type', 'text/xml', 'Pragma', 'no-cache');
xmlhttp.send("");
while (xmlhttp.readyState != 4) { }
xmlDoc = xmlhttp.responseXML;
readXML();
}
function readXML() {
while (subChunk < 20) {
*indvCount = xmlDoc.getElementsByTagName("Value")[subChunk].childNodes[0].nodeValue;
total = parseInt(total, 10) + parseInt(indvCount, 10);
subChunk = parseInt(subChunk, 10) + parseInt(1, 10);
}
chunk = parseInt(chunk, 10) + parseInt(1, 10);
subChunk = parseInt(0, 10)
end = parseInt(chunk, 10) * parseInt(20, 10);
start = parseInt(end, 10) - parseInt(19, 10);
if (chunk > max) {
alert(total);
} else {
loadXML();
}
}
When chunk is equal to approx. 5,000 or more, I get an Out of Memory error. The error usually refers to one of the asterisk'ed lines of code. Using Windows Task Manger, I can confirm that Internet Explorer's memory usage stays at about 6,000K, so I don't think I have a memory leak.
Does anyone know a way to prevent this?
Here's your readXML rewritten to eliminate useless cruft. Critique/questions after the code:
function readXML() {
while (subChunk < 20) {
indvCount = xmlDoc.getElementsByTagName("Value")[subChunk].childNodes[0].nodeValue;
total = total + parseInt(indvCount, 10);
subChunk++;
}
chunk++;
subChunk = 0;
end = chunk * 20;
start = end - 19;
if (chunk > max) {
alert(total);
} else {
loadXML();
}
}
Where do you initialize subChunk? The first time readXML is called, subChunk (if this is all of your code) will be undefined.
Ditto for total. Where does that get defined/initalized?
Ditto for chunk. Where does that get defined initialized?
Ditto for max. Where does that get defined initialized?
Note that I've eliminated all but one parseint. Unless you're doing all kinds of crazy int/string conversions in there, the ONLY place it would strictly be required is to turn your XML-retrieved string into a number for your total count.
Ok. how about re-writing like this... it'd still be using global variables (bad bad bad), but somewhat more correct and and efficient:
function readXML() {
var values = xmlDoc.getElementsByTagName("Value");
for (i = 0; i < values.length; i++) {
total += parseInt(values[i].childNodes[0].nodeValue);
}
chunk++;
end = chunk * 20;
start = end - 19;
if (...) { ... }
}
Your code does a repeated getElementsByTagName call (expensive), accesses one value, then throws away everything else. Does another gEBTN() call, accesses another value, throws away the results, yada yada yada. A major waste of CPU cycles, memory, etc... With the above construct, you do gEBTN() ONCE then iterate over the results, pulling out all the relevant nodes.
Related
I am very new to JavaScript and I'm sure this question has been answered quite a bit, but when I search my question I don't seem to find an answer (or one that I actually understand :D)
Currently, I'm trying to create a tool to help kids with there multiplication facts and I'm having trouble getting the program to generate new random numbers.
var r1 = Math.floor(Math.random() * 13);
var r2 = Math.floor(Math.random() * 13);
function start() {
println("Welcome to the multipilcation helper! ");
var num = readLine("Pick a number you want to practice or type 'random'!");
var ques = readLine("How many questions do you want?");
if (num == "random") {
for (var i = 0; i < ques; i++) {
var answer = r1 * r2;
println(r1 + "*" + r2);
var check = readLine("what is the answer");
if (check == answer) {
println("thats correct!");
} else {
println("thats wrong! ");
}
}
}
}
The problem is that my variables seem to pick a random number as soon as the script starts and stick with it instead of giving me a new random number.
Can anyone help me out and tell me how to get a new random number every time the variable is called?
Simply create yourself a method like the one below and use it like r() to get a new random number every call.
function r() {
return Math.floor(Math.random() * 13);
}
console.log(r());
console.log(r());
console.log(r());
In your loop you should be reassigning the random numbers so that they are reassigned every iteration of the loop. Otherwise they stay static to the value you give them at the top.
Also, you should use triple equals in Javascript when checking for equality as it is best practice.
function start() {
console.log("Welcome to the multipilcation helper! ");
var num = prompt("Pick a number you want to practice or type 'random'!");
var ques = prompt("How many questions do you want?");
if (num == "random") {
for (var i = 0; i < ques; i++) {
var r1 = Math.floor(Math.random() * 13);
var r2 = Math.floor(Math.random() * 13);
var answer = r1 * r2;
console.log(r1 + "*" + r2);
var check = prompt("what is the answer");
if (check == answer) {
console.log("thats correct!");
} else {
console.log("thats wrong! ");
}
}
}
}
start()
You random numbers are being static at the moment. They need to be called again. Move your r1 and r2 assignments inside the for.
I don't have enough reputation to comment, but will update the answer
if you explain it with more details.
You need to put the random call in a function in order for it to create a new number each time. When you assign it directly to a variable as you have, it only runs once and stores that value in the variable.
// pick a number between 0 and 13
var random = function() {
return Math.floor(Math.random() * 13);
}
function start(){
for(var i = 0; i < 15; i++){
// call random function for each number and store in a var
var number1 = random();
var number2 = random();
var answer = number1 * number2;
console.log('equation:', number1 + '*' + number2);
console.log('answer:', answer);
}
}
// call the start function
start()
So, first and foremost, it's important to note that I'm adding a feature to something I didn't design. I'm really new to JavaScript, and I'm trying to edit an existing Discord bot. I discovered that the simplest way to achieve my goal would be to edit the root function at which it generates Random numbers. The relavant snippet of the original code (taken from the dice-expression-evaluator module https://github.com/dbkang/dice-expression-evaluator) is as follows:
Dice.prototype.roll = function () {
var rolls = [];
var sum = 0;
for (var i = 0; i < this.diceCount; i++) {
var roll = random.integer(1, this.sideCount) * this.coefficient;
rolls.push(roll);
sum += roll;
}
return {roll: sum, dice: rolls};
};
This original code works just fine, but doesn't include my desired feature (a simple-but-verbose sort of whitelist.) the 4 variables not defined in that particular code block are rather self-explanatory. My version of the code (slightly edited for privacy reasons) is as follows:
Dice.prototype.roll = function () {
var rolls = [];
var sum = 0;
var range = this.whitelist(); //already tried it with () after whitelist
console.log(range.join(','));
for (var i = 0; i < this.diceCount; i++) {
var roll = random.integer(range[0], range[1]) * this.coefficient; //changed the 2 function arguments, but both are still integers
rolls.push(roll);
sum += roll;
}
return {roll: sum, dice: rolls};
};
Dice.prototype.whitelist = function () {
let user0 = "a";
let user1 = "b";
let user2 = "c";
let user3 = "d";
let user = message.author.id;
let die = this.sideCount;
console.log(user);
console.log(string(die));
if (user==user0) {
var min = Math.ceil(0.76 * die);
var max = die;
} else if (user==user1) {
var min = Math.ceil(0.76 * die);
var max = die;
} else if (user==user2) {
var min = 1;
var max = die;
} else if (user==user3) {
var min = 1;
var max = die;
} else {
var min = 1;
var max = die;
}
return [min, max];
};
The message.author.id variable is available to the function that started the whole function chain 3 scopes up, but in MY version of the code, (even after correcting a few missing semicolons and similarly minute errors) a dice expression that is perfectly functional in the original code generates an "invalid dice expression" error. Other than the introduction of a new variable and the variables in the random.integer call, I see no functional difference between the old and new versions of Dice.prototype.roll. By my understanding, my whitelist function returns an array of integers, and those integers are being injected directly into the random.integer function call in a perfectly reasonable way... I am incredibly confused.
I want to generate an Unique 5 digits ID + 784 at the begining, the constraint, I can execute the script only one time, and I have to avoid the first 100 numbers so It can't be 00100 and lower. Since I use timestamp and I can execute only my script one time how I can handle this ?
I did this it's maybe dumb but at least I tried.
ConcatedID();
function ConcatedID()
{
var uniqID = checkProtectedRange();
if (checkProtectedRange())
{
var BarcodeID = 784 + uniqID;
return BarcodeID;
}
else
checkProtectedRange();
}
function checkProtectedRange()
{
var uniqueID = GenerateUniqueID();
var checkRange = uniqueID.substr(uniqueID.length - 3);
var checkRangeINT = parseInt(checkRange);
if (checkRangeINT <= 100)
return (false);
else
return (true);
}
function GenerateUniqueID()
{
var lengthID = 5;
var timestamp = + new Date();
var ts = timestamp.toString();
var parts = ts.split("").reverse();
var id = "";
var min = 0;
var max = parts.length -1;
for (var i = 0; i < lengthID; ++i)
{
var index = Math.floor(Math.random() * (max - min + 1)) + min;
id += parts[index];
}
gs.log('Generate ID ' + id);
return id;
}
Without being able to track previously used IDs, you're left with chance to prevent duplicates. Your shenanigans with Date doesn't really change that. See the birthday problem.
Given that, just follow the most straight-forward method: Generate a random string consisting of five digits.
function GenerateUniqueID() {
return ('0000'+(Math.random() * (100000 - 101) + 101)|0).slice(-5);
}
Or, if you want just the final integer with constraints applied:
function GenerateUniqueID() {
return (Math.random() * (78500000 - 78400101) + 78400101)|0;
}
I have not seen anything that specifically answers this question.
I intend to develop a text-based game that involves an action occurring every time an idle bar fills up(every x seconds passes)
I'm just trying to figure out the very basic layout of my javascript that will make the battling system in this game.
I'm trying to make the computer re-calculate pDamThisRound if pDamThisRound is not > baseD which is this case is 10.
If it is greater than baseD my code works and prints pDamThisRound. But if it isn't the code just prints nothing.
var baseD = 10;
var pStr = 25;
var pDam = Math.floor((baseD + pStr) / 2);
var pDamThisRound;
var pDamTR = function() {
pDamThisRound = (Math.floor(Math.random() * 2 * pDam));
};
pDamTR();
if(pDamThisRound > baseD) {
document.getElementById("h").innerHTML = pDamThisRound;
}
else {
pDamTR();
}
https://jsfiddle.net/qfnvf1y8/4/
the code just prints nothing
That's because there isn't any code which prints anything. Look at your else block:
else {
pDamTR();
}
What does that function do?:
var pDamTR = function() {
pDamThisRound = (Math.floor(Math.random() * 2 * pDam));
};
Nowhere do you produce any output.
Basically, if you want to print something then, well, print something. Just like you already do in your if block. For example:
document.getElementById("h").innerHTML = "something";
The function pDamTR is probably executing, the problem is that its assigning something to a variable, but doing nothing with it.
Here you go, a corrected version with a while operator:
https://jsfiddle.net/qfnvf1y8/6/
var baseD = 10;
var pStr = 25;
var pDam = Math.floor((baseD + pStr) / 2);
var pDamThisRound;
var pDamTR = function() {
pDamThisRound = (Math.floor(Math.random() * 2 * pDam));
};
pDamTR();
while(pDamThisRound <= baseD) {
pDamTR();
}
if(pDamThisRound > baseD) {
document.getElementById("h").innerHTML = pDamThisRound;
}
else {
pDamTR();
}
Regards,
Eugene
Several mistakes:
1) your else branch does not print anything
2) if you want pDamThisRound > baseD you need a while loop
while(pDamThisRound <= baseD) {
pDamTR();
}
printpDamTR();
function printpDamTR(){
document.getElementById("h").innerHTML = pDamThisRound;
}
The function printpDamTR would not be necessary, but it generally is a good idea to encapsulate such things, as you are probably going to use it more often. Also it increases the maintainability of your code since you loosen the dependencies between your JS and your HTML.
You can use setTimeout to help you, with something like this:
var baseD = 10;
var pStr = 25;
var pDam = Math.floor((baseD + pStr) / 2);
var timeoutDuration = 3000; // 3 seconds
window.setTimeout(function () {
// execute the check and the update logic here
var pDamThisRound = (Math.floor(Math.random() * 2 * pDam));
if(pDamThisRound > baseD) {
document.getElementById("h").innerHTML = pDamThisRound;
}
}, timeoutDuration);
This will execute the check every 3 seconds
okay so i want if my counter reaches the maximum count, it starts over, with the default counter number which is 0 here is my code:
var picCount = 0; // global
var maxCount = 4;
//Pictures, to add more then 4 pics, add var picFive = "link to image here", var picSix ="bla", you get it.. add in picArray ,picFive and ,picSix
//To change the time delay, change it at the body onload and on the setTimeout
var picOne = "http://screenshots.nl.sftcdn.net/nl/scrn/3342000/3342167/modloader-for-minecraft-02-700x406.jpg"
var picTwo = "http://media.moddb.com/images/downloads/1/31/30912/minecraft_blox.png"
var picThree = "http://www.mupload.nl/img/rl6zeofbb.png"
var picFour = "http://www.mupload.nl/img/rl6zeofbb.png"
var picArray = [picOne, picTwo, picThree, picFour]
//
// gets next picture in array
function nextPic() { // check if adding 1 exceeds number of pics in array
if (picCount.length < maxCount.length) {
picCount = (picCount + 1 < picArray.length) ? picCount + 1 : 5000;
// build the image to write to page using the new pic reference
var build = '<img border="0" src="' + picArray[picCount] + '" width="649">\n';
document.getElementById("imgHolder").innerHTML = build;
// repeat this every 10 seconds.
setTimeout('nextPic()', 10 * 1000) //setTimeout is here
} else {
picCount = (picCount - maxCount < picArray.length) ? picCount + 1 : 5000;
// build the image to write to page using the new pic reference
var build = '<img border="0" src="' + picArray[picCount] + '" width="649">\n';
document.getElementById("imgHolder").innerHTML = build;
// repeat this every 10 seconds.
setTimeout('nextPic()', 10 * 1000) //setTimeout is here
}
}
okay so i hope you guys can help me with this..
That's a lot of messy code.
My fix for an implementation would probably look something like this:
var currentPic = 0;
var picOne = "http://screenshots.nl.sftcdn.net/nl/scrn/3342000/3342167/modloader-for-minecraft-02-700x406.jpg"
var picTwo = "http://media.moddb.com/images/downloads/1/31/30912/minecraft_blox.png"
var picThree = "http://www.mupload.nl/img/rl6zeofbb.png"
var picFour = "http://www.mupload.nl/img/rl6zeofbb.png"
var picArray= [picOne,picTwo,picThree,picFour]
function nextPic() {
if (currentPic < picArray.length) {currentPic++;}
else {currentPic = 0;}
var build='<img border="0" src="'+picArray[currentPic]+'" width="649">';
document.getElementById("imgHolder").innerHTML=build;
// repeat this every 10 seconds.
setTimeout('nextPic()',10 * 1000)//setTimeout is here
}
Despite many other issues which I am sure are present in your code, I believe this line is the cause of your particular problem addressed in the question:
if (picCount.length < maxCount.length) {
maxCount and picCount are just numbers. They do not have a length property. Change it to this:
if (picCount < maxCount) {
var currentPic = 0;
var picArray= ["http://screenshots.nl.sftcdn.net/nl/scrn/3342000/3342167/modloader-for-minecraft-02-700x406.jpg",
"http://media.moddb.com/images/downloads/1/31/30912/minecraft_blox.png",
"http://www.mupload.nl/img/rl6zeofbb.png",
"http://www.mupload.nl/img/rl6zeofbb.png"];
function nextPic() {
(currentPic < picArray.length) ? currentPic++ : currentPic = 0;
var build='<img border="0" src="'+picArray[currentPic]+'" width="649">';
document.getElementById("imgHolder").innerHTML=build;
}
setTimeout('nextPic()',10 * 1000);
I made a few changes that make your code cleaner.
Some tips:
No need to store your image URLs in vars before putting them in the array. Just initialize your array with them.
Don't repeat yourself. Whenever you find yourself using the exact same code in multiple places, you probably need to rethink how you are approaching the problem.
Look up the "ternary operator". In my opinion it makes simple conditional statements easier to read.
No need to use maxCount - the max count will be the length of your picArray.
Although not usually required, try to end all statements with a semicolon.
Don't mind the elitist attitude some people have, but at the same time, try to research as much as you can before asking a question.