Discord.js DND Dice Roll Input Change Number - javascript

I've made a "working" dice roll function on my bot. Works fine for what I need, but was wondering how I could make it so depending on what is said in discord it rolls.
So saying !rolld6 would use 6 in var response instead of 20.
if (message.content.toLowerCase().includes("!rolld20")) {
const ayy = client.emojis.cache.find(emoji => emoji.name === "diceroll");
var response = [Math.floor(Math.random() * ((20 - 1) + 1) + 1)];
message.channel.send(`${ayy}` + `Rolling.`)
.then(msg => {
setTimeout(function() {
msg.edit(`${ayy}` + `Rolling..`)
}, 1000);
setTimeout(function() {
msg.edit(`${ayy}` + `Rolling...`)
}, 2000)
setTimeout(function() {
msg.edit(`${ayy}` + `Rolling....`)
}, 3000)
setTimeout(function() {
msg.edit(`${ayy}` + " Rolled... " + response + " " + `${ayy}`).then().catch(console.error)
}, 4000)
})
return;
}
Not even sure what I would search to figure this out so any help is greatly appreciated!

Use a regular expression instead of .includes, and then extract the digits after the d to randomize.
You don't need to subtract 1, then add 1 right after that - those cancel out, nor do you need to put the result into an array - interpolating just the random number generated into the message will work fine.
const match = message.content.match(/!rolld(\d+)/i);
if (match) {
const die = match[1];
const response = 1 + Math.floor(Math.random() * die);
const ayy = client.emojis.cache.find(emoji => emoji.name === "diceroll");

Related

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();

How to ensure invitation code is unique in Redis

I need to generate an unique user friendly code and save it into Redis either until the invited user grads it or it expires.
Since the code has to be user friendly I have decided to use 6 digit number, which the frontend will divide into two groups e.g. xxx-xxx.
Now, on the backend, I have NodeJS and node_redis.
This is how I generate the random string and save it into the Redis:
var invCode = Math.floor(Math.random() * 90000) + 100000;
var key = "invitation-code:" + invCode;
const TTL = 3 * 24 * 60 * 60; // 3 days
redis.client.existsAsync(key)
.then(res => {
if (!res) {
// ok, I can add the key, value pair
return redis.client.setAsync(key, value, 'EX', TTL);
} else {
// I have to generate new key and check it again
// how can I re-iterate the process???
return null;
}
})
.then(res => {
logger.info('InvitationCodeController::generate added <' + key + ', ' + value + '> pair');
})
.catch(error => {
logger.error('InvitationCodeController::generate Error ' + error);
});
Now, the point I cannot figure out is - in case the generated code already exists, how can I re-iterate the process, i.e. to generate another random string, format it, check in Redis and etc.
Since I have async call, I don't think any kind of loop can work for me?
Any ideas?
You could utilize a "attempts" process like the following.
You could also make a while loop similarly by removing the --n portion.
Additionally I think you should use the "NX" parameter for "SETNX" --- Set when the value does not exist. Otherwise it is possible that between the time you check redis for whether the key exists and the time you actually set it, you can overwrite some other key. You might even rewrite it at this point so rely on SETNX throwing an error on failing to set rather than checking the value each time.
const process = require('process');
const redis = require("redis");
const Bluebird = require('bluebird')
Bluebird.promisifyAll(redis.RedisClient.prototype)
Bluebird.promisifyAll(redis.Multi.prototype)
const winston = require('winston');
const logger = winston.createLogger({
level: 'silly',
format: winston.format.json(),
transports: [new winston.transports.Console({
format: winston.format.simple()
})]
});
const client = redis.createClient({
host:'redis-19141.c16.us-east-1-3.ec2.cloud.redislabs.com',
port:'19141'
});
client.auth('I6C2ISvac4suTbxSYcbsjWiz635NK8Wv');
// client.set("string key", "string val", redis.print);
var invCode = Math.floor(Math.random() * 90000) + 100000;
// test invCode being the same --- retry.
invCode = 111111;
var key = "invitation-code:" + invCode;
const TTL = 3 * 24 * 60 * 60; // 3 days
let value = "test";
const trySet = function(key,n){
const used = process.memoryUsage().heapUsed / 1024 / 1024;
logger.info(`The script uses approximately ${Math.round(used * 100) / 100} MB`);
return client.existsAsync(key)
.then(res => {
logger.info("existsAsync res",res);
if (!res) {
logger.info("Key does not exist!");
return client.setAsync(key, value, 'NX','EX', TTL)
.then(res => {
logger.info('InvitationCodeController::generate added <' + key + ', ' + value + '> pair');
return true;
})
} else {
logger.info("Key already exists!");
if(n > 0){
return trySet(key,--n);
}else{
return false;
}
}
})
.catch(error => {
logger.error('InvitationCodeController::generate Error ' + error);
return false;
});
}
trySet(key,50).then(function(res){
if(res){
logger.info('trySet::success');
}else{
logger.info('trySet::failed');
}
}).catch(error => {
logger.error('trySet::error');
});
https://repl.it/repls/ImmediateSufficientCoin
Since code generation is sync process, I figure out, I can do it other way around. Here is the code:
const TTL = 3 * 24 * 60 * 60; // 3 days
var invCode = '';
const pattern = "invitation-code:";
var prepKey = '';
redis.client.keysAsync(pattern + "*")
.then(keys => {
// these are all keys / invitation codes
var isFound = false;
do {
invCode = Math.floor(Math.random() * 90000) + 100000;
prepKey = pattern + invCode;
// traverse keys to check if the invitation code matches
keys.forEach(key => {
if (key === prepKey) {
isFound = true;
}
});
} while (isFound);
return prepKey;
})
.then(key => {
return redis.client.setAsync(key, value, 'EX', TTL);
})
.then(res => {
logger.info('InvitationCodeController::generate added <' + prepKey + ', ' + value + '> pair');
})
.catch(error => {
logger.error('InvitationCodeController::generate Error ' + error);
});
Hope this help anyone else on the topic...

Displaying amount of guilds as activity

I have this code to make it say "Watching (amount of servers my bot is in) servers!"
const activities_list = [
"with the &help command.",
"with the developers console",
"with some code",
"with JavaScript",
client.guilds.size + " servers!"
];
client.on('ready', () => {
setInterval(() => {
const index = Math.floor(Math.random() * (activities_list.length - 1) + 1);
client.user.setActivity(activities_list[index]);
}, 5000);
});
But it gives me this when I see it on discord
"0 servers!"
How do I fix this?
I think the problem is that you're declaring the string before the client is ready (when you type a string with a variable it's saved with that value). Try declaring it in the setInterval argument:
client.on("ready", () => {
setInterval(() => {
let activities = ["your_strings", `${client.guilds.size} servers!`],
index = Math.floor(Math.random() * (activities_list.length - 1) + 1);
client.user.setActivity(activities[index])
}, 5000);
});

Random Count in a "return" without many code

I google for a solution that allows me to generate a random number between 1 and 6. i found this: http://www.w3schools.com/jsref/jsref_random.asp
Now i tryed to use it in my code:
$scope.getUserImage = function (user) {
if (user.avatar) {
return user.avatar;
} else {
return '/images/icons/user-' + user.gender((Math.random() * 6) + 1) + '.svg';
}
};
but with this i get a error, it means that the user.gender isnt any function. I know this is a realy very basic question. I started new with JavaScript. I am a Designer normaly.
Since you want to add the strings together (called 'concatenate' since we're talking about strings), separate each with a + symbol. But the 1-6 logic is also wrong, you'll need to round those numbers down.
$scope.getUserImage = function (user) {
if (user.avatar) {
return user.avatar;
} else {
var randomNumberOneToSix = Math.floor(Math.random() * 6 + 1);
return '/images/icons/user-' + user.gender + randomNumberOneToSix + '.svg';
}
};
Bonus tip: w3schools is not a great resource. Add 'mdn' to every search and use Mozilla's excellent documentation for learning about web technologies.
You miss a "+" to concat gender change this line
return '/images/icons/user-' + user.gender((Math.random() * 6) + 1) + '.svg';
to
return '/images/icons/user-' + user.gender + ((Math.random() * 6) + 1) + '.svg';

Declaring variable within functions

Ok, so I I'm having this strange behaviour that I cannot explain. Look at the following:
$("#completeData").on("click", function() {
var toUpdate = {};
var toUpdateCount = 0;
var ratios = {};
This.calculateGradePerSize();
//1) Select all sizes that are equal to NA or are Equal to 0 (means its a new one)
$.each(This.logements, function(key, l) {
if (l.sizeMyId === "NA" || l.sizeMyId === 0) {
toUpdate[l.rueNum] = l;
toUpdateCount++;
} else { //else init the ratios because it means they are actually present
/**
//My problem is this variable,
I want it to be equal to an empty object
But for reasons I cannot seem to understand,
it takes in account the latter modification in the code
that happens to this variables
*/
ratios[l.sizeMyId] = {};
}
});
console.log(toUpdate);
console.log(ratios);
console.log(This.sizeRatio);
//2) Calculate Ratios and build the ratios function of the toUpdate
$.each(This.sizeRatio, function(sizeMyId, count) {
if (sizeMyId !== "NA" && sizeMyId != 0) {
console.log("COUNT SIZE: " + count + " COUNT LOGEMENT: " + This.countLogement + " toUpdateCount: " + toUpdateCount + " SizeMyId: " + sizeMyId);
console.log("Calculation: " + count / This.countLogement * toUpdateCount);
ratios[sizeMyId].count = Math.ceil(count / This.countLogement * toUpdateCount);
console.log("Calculation WITH CEIL: " + Math.ceil(count / This.countLogement * toUpdateCount));
ratios[sizeMyId].grade = This.sizeGrade[sizeMyId];
ratios[sizeMyId].sizeMyId = sizeMyId;
}
});
console.log(ratios);
});
As explained in the multiline comment, my problem is the ratio variable. I tried declaring the variable without var prefix, so that JS doesn't know its existence but still, I want it to be empty object. In fact, the problem has stronger roots than simply that, I cannot update it. Each change I make to the ratios var are not registered, but I wanna start with the beginning how can I make sure that this variable is empty at the beginning of the function.
I don't know if this question is really worth. Thinking about deleting it. My bug was that the count variable in the each function as well as the ratio definition were the same hence not registering.
As for the variable not being an empty one at function start. It simply how the JS engine works. If there is something not working, more likely than not, there is something wrong in your code.
$.each(This.sizeRatio, function (sizeMyId, count) {
if (sizeMyId !== "NA" && sizeMyId != 0) {
console.log("COUNT SIZE: " + count + " COUNT LOGEMENT: " + This.countLogement + " toUpdateCount: " + toUpdateCount + " SizeMyId: " + sizeMyId);
console.log("Calculation: " + count / This.countLogement * toUpdateCount);
//HERE ratios[sizeMyId].count IS THE SAME than the anonymous function.
ratios[sizeMyId].count = Math.ceil(count / This.countLogement * toUpdateCount);
console.log("Calculation WITH CEIL: " + Math.ceil(count / This.countLogement * toUpdateCount));
ratios[sizeMyId].grade = This.sizeGrade[sizeMyId];
ratios[sizeMyId].sizeMyId = sizeMyId;
}
});

Categories

Resources