How loop 2 setIntervals without creating multiple requests? - javascript

function Test(time) {
i = 1;
fun1 = setInterval(function () {
if (i >= 1 && i <= 10) {
$('.class.' + i).children('.BUTTON').click();
}
}, time * i);
fun2 = setInterval(function () {
if (result > 0 && i < 10) {
console.log('The number is ' + i);
i++;
}
else if (result < 0) {
console.log('Sorry at ' + i + ' point you fell in the hole');
clearInterval(fun2);
stats.loss++;
$('.loss').text(stats.loss);
console.log('Number of fell are ' + stats.loss);
} else {
console.log('Exited from maze');
clearInterval(fun);
clearInterval(fun2);
stats.wins++;
$('.wins').text(stats.wins);
console.log('Number of wins are ' + stats.wins);
$('#START').click();
}
}, time * 1.3);
}
Last time I asked about making the if's in a for holding the i, loved it, then, I had the idea of checking the result of the path, showed in this case as points. And this way works great, problem is, what if I want to create an "infinite loop" to check if in the long run my character would be a winner or loser?
Solutions I tried: for,while,do while, they ends up requestin thousands of requests to the server.
tried with A main set interval, but somehow it just creates parallel requests and even If I do clearInterval(masterloop); it just activate the test again and again, speeding up and clicks only the start/reset level button.

Related

Having a hard time getting the right probability outcome (js beginner)

I'm trying to make a simple rolling the dice mechanic with probabilities, if pass the level increase, if fail it decrease and if destroyed usually it resets to a certain level, but I'm having a hard time getting the right results, I am not sure if the outcome is supposed to be like this and just my intuition is wrong or something is actually messing it up.
Basically I am making a while loop that while below certain level it will roll the dice and given the results it will do something accordingly to the rates I input (40% for pass, 59.4% for fail and 0.6% to destroy). But when I do a test with 1000 tries, it always return me an average of destroyed way higher than 0.6%. I don't know if my test function is wrong, if the way I'm testing is wrong, if something on my loop is messing up the probabilities outcome.
function checkPass(successRate, failRate, destroyRate) {
let number = Math.random();
if (number < successRate) {
return 1;
} else if (number < failRate) {
return 0;
} else {
return 2;
}
}
function starforceSim(itemLevel) {
let newObj = {"level": 10, "totalMeso": 0, "destroyed": 0};
while (newObj.level < 11) {
if (newObj.level == 10) {
let passOutcome = checkPass(0.4, 0.994, 1)
if (passOutcome == 1) {
//newObj.totalMeso = newObj.totalMeso + (Math.round(1000 + (Math.pow(itemLevel, 3)) * (Math.pow(newObj.starlevel + 1, 2.7)) / 400));
newObj.level = newObj.level + 1;
} else if (passOutcome == 0) {
//newObj.totalMeso = newObj.totalMeso + (Math.round(1000 + (Math.pow(itemLevel, 3)) * (Math.pow(newObj.starlevel + 1, 2.7)) / 400));
//newObj.level = newObj.level - 1;
} else {
//newObj.totalMeso = newObj.totalMeso + (Math.round(1000 + (Math.pow(itemLevel, 3)) * (Math.pow(newObj.starlevel + 1, 2.7)) / 400));
newObj.destroyed = newObj.destroyed + 1
}
}
}
return newObj;
}
let counter = 0;
for (i=0; i<1000; i++) {
let n = starforceSim(140);
if (n.destroyed > 0) {
counter++
}
}
console.log(counter);
I disabled the decrease level when it fails just to focus on the destroy rates.
Is there a better way to code probabilities or to test them? Is there something wrong with my code?
Math.random is only pseudo-random1
1Source
This means you may not get a perfectly uniform distribution. In my own fiddling, it seems like randomness might get worse if you generate many values in rapid succession [citation needed].
If you want a better source of randomness, check out Crypto.getRandomValues.
I don't see anything wrong with your code. I think your expectations are just off. To verify that this is caused by lame randomness, take David Tansey's advice and study just the randomness output.
You may also notice different randomness quality in different browsers (or, different Javascript engines).

Is there a "repeat [function] until [property = true]" type of loop in MakeCode JS?

I'm making a game in Microsoft MakeCode Arcade for a school project, and I wanted to know if there was a "repeat [function] until [property = true]" type of loop like there is in Luau. I wanted to use this so that the game waits until my player sprite is at a certain coordinate to run some code. I figured out a way to do this in a different way, but I wanted to know just for future reference.
If anyone is wondering, this is what the alternative way I am using.
game.onUpdateInterval(100, function () {
if (level == 1) {
if (myPlayer.x == 950 && myPlayer.y == 140) {
myPlayer.y = 100
myPlayer.x = 10
if (game.ask("Does " + level_1 + " + " + level1_2 + " = " + level1CorrectAns + "?")) {
console.log("Level 1 Completed successfully")
level += 1
LevelChange()
} else {
game.over(false)
}
}
}
})
You could use either while loop or do...while loop
For while loop, the following code will keep on running as long as the condition is true.
let x = 0
while (x < 3) {
x++
}
console.log(x) // print 3
For do...while loop, the following code will keep on running as long as the condition is true. And this loop will run at least once.
let result = '';
let x = 0;
do {
x = x + 1;
result = result + x;
} while (x < 5);
console.log(result); // print "12345"
Coming back to your example, I believe you're running the loop every 100ms (based on first argument of your game.onUpdateInterval.
You could easily do this by adding a timer function and wrap this loop in as an async function.
const timer = ms => new Promise(res => setTimeout(res, ms))
async function updateInterval() {
while () {
// Your logic here
await timer(100) // You can change the timeout to your desired ms
}
}
updateInterval();
While I'm not 100% sure of the functionality of your current workaround, but this is my interpretation (Hope it works)
const timer = (ms) => new Promise((res) => setTimeout(res, ms));
async function updateInterval() {
let state = true; // This is just a condition if the loop should continue
while (state) {
if (level == 1) {
if (myPlayer.x == 950 && myPlayer.y == 140) {
myPlayer.y = 100;
myPlayer.x = 10;
if (
game.ask(
'Does ' +
level_1 +
' + ' +
level1_2 +
' = ' +
level1CorrectAns +
'?'
)
) {
console.log('Level 1 Completed successfully');
level += 1;
LevelChange();
state = false; // Update the state to false, so it will exit the while loop
} else {
game.over(false);
}
}
}
await timer(100); // You can change the timeout to your desired ms
}
}
updateInterval();

Simple number guessing game using Javascript

I'm trying to make a number guessing game on JS for a web dev training I'm on. The problem is that it always prints the keyInYNStrict without giving an another chance for the user. Ignore the fact that the strings and variables are not in English. Basically I want the keyInYNStrict to only come after the arvaus == arvattava is true and the game has ended.
const minLuku = 1;
const maxLuku = 30;
const readlineSync = require('readline-sync');
let arvaus, arvattava, arvaustenLkm
do {
arvaus = readlineSync.question('Ajattelen numeroa 1 ja 30 välillä. Arvaapa vaan');
arvaustenLkm = 1;
arvattava = Math.floor(Math.random() * (maxLuku + 1 - minLuku)) + minLuku
kelvollinen = !isNaN(arvaus) && arvaus > 0 && arvaus < 31;
if (!kelvollinen) {
console.log('Elä viitsi! Laita nyt jokin oikea numero.');
}
else if (arvaus < arvattava){
arvaustenLkm++;
console.log('Kokeile suurempaa lukua.');
} else if (arvaus > arvattava){
arvaustenLkm++;
console.log('Kokeile pienempää lukua.');
} else if (arvaus == arvattava){
console.log('Hienoa. arvasit oikein ' + arvaustenLkm + ' arvauksella.')
}
} while (readlineSync.keyInYNStrict('Haluatko arvata uudestaan?'))
You'll need two while loops nested. The first is to repeat the guessing until the number has been found, the second to ask if the user wished to play again. This becomes clearer if you break a single game into a function, and then wrap "Play again?" around that function.
The following is untested. Notice I also pulled out the "Invalid guess" check to separate it from the game logic. I think that also improves readability, and allows for the option of checking for some other exit condition should the user wish to end early.
EDIT: As I'm thinking about it, there's another problem: Do you want to reset the hidden number each guess? That's probably not consistent with expectations. I've modified the code to reflect.
const minLuku = 1; // Lower bound
const maxLuku = 30; // Upper bound
const readlineSync = require('readline-sync');
let arvaus, arvattava, arvaustenLkm
do {
// Number of guesses
arvaustenLkm = 1;
//Target number
arvattava = Math.floor(Math.random() * (maxLuku + 1 - minLuku)) + minLuku
do {
// User's guess
arvaus = readlineSync.question('Ajattelen numeroa 1 ja 30 välillä. Arvaapa vaan');
// Bad guess test
if (isNaN(arvaus) || arvaus < minLuku || arvaus > maxLuku) {
console.log('Elä viitsi! Laita nyt jokin oikea numero.');
continue;
}
if (arvaus < arvattava){
arvaustenLkm++;
console.log('Kokeile suurempaa lukua.');
} else if (arvaus > arvattava){
arvaustenLkm++;
console.log('Kokeile pienempää lukua.');
} else if (arvaus == arvattava){
console.log('Hienoa. arvasit oikein ' + arvaustenLkm + ' arvauksella.')
}
} while (arvaus != arvattava)
} while (readlineSync.keyInYNStrict('Play again?'))

Async python script from node js

I have a node.js program that runs around 50 different python script instances. I would like to be able to throttle the phase - such that at any one time, only 4 processes will run parallel.
I tried a simple loop that calls a function that runs 4 instances of the python script. I used 60 seconds delay as this is the average time takes the script to run.
function startPythonScraping(){
for(var i = 0; i < finalList.length; i++){
setTimeout(function(){
runFourProccesses(finalList[i]);
}, i*60*1000);
}
}
function runFourProccesses(stockSymbol){
console.log("working on " + stockSymbol);
for(var j = 0; j < 4; j++){
if(j == 0){
trueOrFalse = "y"
} else {
trueOrFalse = "n"
}
let secondPythonProcess = spawn('python', ["/Users/nybgwrn/Desktop/AlphaSecWebsite/getAllData.py", stockSymbol, (j*10).toString(), "10", trueOrFalse]);
secondPythonProcess.stdout.on('data', (data) => {
let messegeFromPython = JSON.stringify(data.toString('utf8')).replace("\\n", "");
console.log(messegeFromPython + " with stock " + stockSymbol);
if(messegeFromPython != "something went wrong"){
//console.log("created file for " + symbol);
} else {
//console.log("couldn't create file for " + symbol + "_" + (j*10).toString() + "-" + (j*10 + 10).toString());
}
});
}
}
It doesn't work because somehow the index i begin with 50 instead of 0, and also I want a better solution as I want to be SURE that only 4 instances are running.
This is usually done using semaphores. A semaphore is basically a pool of locks, so that multiple locks can be held at the same time.
In your case you could use this package and wrap each python process spawning with sem.take and sem.leave.

How to show alert in the next event loop?

I am learning VueJS and created this little practice game to enhance my knowledge on Vue.
http://jsfiddle.net/mzref4o0/1/
this attack method will also determine the winner:
attack: function(isSpecialAttack) {
let youHurt = Math.floor(Math.random() * 10);
let monsterHurt = Math.floor(Math.random() * 10);
if (isSpecialAttack) {
youHurt = Math.floor(Math.random() * (20 - 10 + 1)) + 10;
monsterHurt = Math.floor(Math.random() * (20 - 10 + 1)) + 10;
}
this.you.bloodLevel -= youHurt;
this.monster.bloodLevel -= monsterHurt;
this.messages.push([
{id: this.getRandomId, turn: 'you', msg: 'PLAYER HTIS MONSTER FOR ' + monsterHurt},
{id: this.getRandomId, turn: 'monster', msg: 'MONSTER HTIS PLAYER FOR ' + youHurt}
])
if (this.you.bloodLevel <= 0 || this.monster.bloodLevel <= 0) {
if (this.you.bloodLevel <= 0) {
alert('you lost');
} else {
alert('you won');
}
}
},
The problem is that the alert message shows up before the "attack" happens, meaning the blood bar drops & the message is added after the alert message is shown. How do I make the alert shows up only after those two things happened?
I think this problem is due to event loop... but that's all I know.
What you are trying to achieve can't really work with alert.
alert method is blocking the execution of code, therefore the browser does not start to deal with the re-painting until the block is released.
A solution was suggested in other stackoverflow post.
I highly recommend to use more modern techniques, like vue-js modals.
anyway, this block of code should work :
if (this.you.bloodLevel <= 0 || this.monster.bloodLevel <= 0) {
if (this.you.bloodLevel <= 0) {
setTimeout("alert('you lost');", 1);
} else {
setTimeout("alert('you won');", 1);
}
}

Categories

Resources