I've got an object that I get from a sql query and I want to delete an item inside of it. The thing is that after I delete it, that item has no information but it's still there as:
<1 empty item>
so I would like to know if there is a way to completely remove it and have a clean object with only my data."
The code is to establish matches between two players from the database and it used to work but I would have to verify that the selected player was not the one being left out since they are odd and I wanted a random one to be left out. So I realized it was way easier to simply remove the player that is not going to take part in the matches from the object.
I will leave the hole code.
let tournamentID = args[0];
let categoryID = args[1];
let tournamentSQL = 'SELECT * FROM tournaments WHERE tournamentID = ?';
let tournamentData = [tournamentID];
let matchesCreated = 0;
con.query(tournamentSQL, tournamentData, function(err, result){
if(err) throw err;
let playersSQL = "SELECT * FROM players WHERE tournamentID = ?";
if(result.length == 0){
return message.channel.send('Ingresaste un TournamentID incorrecto');
};
if (result[0].modality > 1){
return message.channel.send('Este torneo es por equipos, usa .partidosequipos');
};
let actualRound = result[0].actualRound + 1;
con.query(playersSQL, tournamentData, function(err, resultPlayers){
if(resultPlayers.length == 0){
return message.channel.send('Este torneo no tiene jugadores.');
};
if(err) throw err;
let roundPlayers = resultPlayers.length - 1;
if(resultPlayers.length % 2 != 0){
let player = Math.round(Math.random() * roundPlayers);
console.log(player);
message.channel.send(`La cantidad de jugadores en el torneo es impar, el jugador ${resultPlayers[player]} no jugará en esta ronda y ya clasificó a la siguiente`);
delete resultPlayers[player];
matchCreating(roundPlayers, resultPlayers, result, categoryID, client, message, actualRound);
} else{
matchCreating(roundPlayers, resultPlayers, result, categoryID, client, message, actualRound);
}
Hope I was able to explain my self.
Thank you for your help.
You need to use splice to delete a particular index
var playersSQL = "SELECT * FROM players WHERE tournamentID = ?";
con.query(playersSQL, tournamentData, function(err, resultPlayers){
if(resultPlayers.length % 2 != 0){
let player = Math.round(Math.random() * roundPlayers);
resultPlayers.splice(player, 1);
}
}
Related
I'm trying to code a fighting discord bot game but I ran into troubles lately!
Everything works with reactions.
So basically what i want to do is : roll a dice to determine the one who starts. The winner rolls 2 dices to determine the damages he will do and then its player 2's turn.
Until here, everything works.
What i would like it to do is loop this last part when the first player rolls the 2 dices to inflict damages.
I tried placing while loops userhealth<=0 here and there, but it never works.
I know it has to do with promises and stuff like that, but Im still lost.
A little help would be appreciated!
Here is the code:
const { ReactionCollector } = require('discord.js');
function rolldice(numero){
return Math.floor(Math.random() * numero + 1);
}
function premier(msg,user){
diceroll1 = rolldice(20)
diceroll2 = rolldice(20)
msg.channel.send(`${msg.author.tag} a eu : ${diceroll1} \n\n ${user.tag} a eu : ${diceroll2}`)
if(diceroll1 > diceroll2){
msg.channel.send(`${msg.author.tag} gagne`)
return msg.author.id
}
else if(diceroll1 < diceroll2){
msg.channel.send(`${user.tag} gagne`)
return user.id
}
else{
msg.channel.send(`Vous avez fait égalité. On recommence le tirage.`)
premier(msg,user)
}
}
function attaque1(msg, user){
damagedice1 = rolldice(6)
damagedice2 = rolldice(6)
somme = damagedice1 + damagedice2
return {somme,damagedice1,damagedice2}
}
function bagarre(msg,user,winner,user1health,user2health,fighter1,fighter2){
if(winner === msg.author.id){
msg.channel.send(`Joueur 1 Clique sur 🎲 pour determiner les dégats que tu vas infliger.`).then((riposte) => {
riposte.react('🎲')
var atksmme = attaque1(msg,user)
const filter1 = (reaction, user) => {
return ['🎲'].includes(reaction.emoji.name) && user.id === fighter1;
};
const collector1 = riposte.createReactionCollector(filter1,{
max: 1
});
collector1.on('collect',(collected,reason) => {
user2health = user2health - atksmme.somme
msg.channel.send(`${msg.author.tag} inflige ${atksmme.somme} de dégâts à ${user.tag}! (${atksmme.damagedice1} + ${atksmme.damagedice2})`)
msg.channel.send(`Il reste ${user2health} points de vie à ${user.tag}`)
if(user2health<=0) return msg.channel.send('Vous avez perdu')
collector1.stop()
msg.channel.send(`Joueur 2 Clique sur 🎲 pour determiner les dégats que tu vas infliger.`).then((riposte1) => {
riposte1.react('🎲')
var atk2smme = attaque1(msg,user)
const filter2 = (reaction, user) => {
return ['🎲'].includes(reaction.emoji.name) && user.id === fighter2;
};
const collector2 = riposte1.createReactionCollector(filter2,{
max: 1
});
collector2.on('collect',(collected,reason) => {
user1health = user1health - atk2smme.somme
msg.channel.send(`${user.tag} inflige ${atk2smme.somme} de dégâts à ${msg.author.tag}! (${atk2smme.damagedice1} + ${atk2smme.damagedice2})`)
msg.channel.send(`Il reste ${user1health} points de vie à ${msg.author.tag}`)
if(user1health<=0) return msg.channel.send('Vous avez perdu')
collector2.stop()
})
})
})
})
}
else if(winner === user.id){
var atksmme = attaque1(msg,user)
user1health = user1health - atksmme.somme
msg.channel.send(`${user.tag} inflige ${atksmme.somme} de dégâts à ${msg.author.tag}! (${atksmme.damagedice1} + ${atksmme.damagedice2})`)
msg.channel.send(`Il reste ${user1health} points de vie à ${msg.author.tag}`)
}
}
module.exports = {
name: 'fight',
args : true,
usage : '#<user>',
async execute(msg,args) {
//VARIABLES
const { client } = msg;
var diceroll1;
var diceroll2;
var damagedice1;
var damagedice2;
var user1health = 12;
var user2health = 12;
var winner;
//checks if the username to fight is in the msg
var author1 = msg.author.username;
var user = msg.mentions.users.first();
if(!user) return msg.reply("you did not specify who you would like to fight!");
//checks if the users is trying to fight themselves
if(user.id == msg.author.id) return msg.reply('you cannot fight yourself!');
//checks if the user is trying to fight the bot
if(user.bot == true)
return msg.reply('you cannot fight a bot!');
//saves the two user ids to variables
var fighter1 = msg.author.id;
var fighter2 = user.id;
var challenged = user.toString();
msg.channel.send(`${challenged}, tu veux te battre?`).then((bataille) => {
bataille.react('🎲')
const filter = (reaction, user) => {
return ['🎲'].includes(reaction.emoji.name) && user.id === fighter2;
};
const collector = bataille.createReactionCollector(filter,{
max: 1
});
collector.on('collect',(collected,reason) => {
winner = premier(msg,user)
bagarre(msg,user,winner,user1health,user2health,fighter1,fighter2)
})
})
}}
Okay, there's a lot of weird things about this.
First of all, there are a lot of unused variables. Please use a proper IDE like Visual Studio Code that informs you about these things.
Second, you should be using await instead of then in most cases. (dont just replace then with await - see javascript async tutorials for good examples)
Third, this is just all a mess. You will have to divide your code into more functions: Create a function to initiate an attack from one user to another. That code should be usable for both player 1 and 2 so that no code is copypasted for both players. Then you can just call that function after one player has made their turn to start the next turn for the other player.
I am in the progress of making a discord bot. This is one of the commands that auto-does itself.
What it is supposed to do it's if someone type .team buy 1, save the data that comes out of another bot.
I would like to whitelist this command to 2 specific channels, identified by their channel id, and just ignore the message if it is not in the 2 channels.
How can I edit the code to do it?
const fs = require("fs");
module.exports.run = (client, message) => {
if ([509042284793430032, 501784044649054231].includes(message.channel.id)) return;
try {
//check if it's a different message //like when a user enters "team buy 234"
if (message.embeds[0].description.indexOf("❓") === 0) return;
//retrieve the team data
var teamData = JSON.parse(fs.readFileSync(client.config.dataFolder + "/teamUpgrades.json", "utf8"));
//get the current purchases data from the message
var arr = message.embeds[0].description.split("\n");
//loop and save the data in "items" object
for (var i = 0; i < arr.length; i++) {
if (arr[i] == "") continue;
if (arr[i].indexOf("Unlocks") > -1) continue; //skip locked items
var opt = arr[i].split("|"); //item's info
var name = opt[0].trim();
if (name.indexOf("**") > -1)
name = name.substring(name.indexOf("**") + 2, name.length - 2).trim(); //bold
else
name = name.split(" ")[1]; //not bold
var price = opt[1].trim();
price = price.substring(3, price.length - 1);
price = parseInt(price.split(",").join(""));
var count = opt[2].trim();
count = parseInt(count.substring(1, count.length - 2).split(",").join(""));
var eps = opt[3].trim();
eps = parseFloat(eps.split(" ")[0].substring(1));
//if the item doesn't exist, create it
if (!teamData.items[name]) teamData.items[name] = {};
teamData.items[name].price = price;
teamData.items[name].eps = eps;
teamData.items[name].count = count;
}
//the best item to buy, let's give it a very high number first
var minItem = {
name: "",
min: Number.MAX_SAFE_INTEGER
};
for (var name in teamData.items) {
//The average price/eps
var average = Number(teamData.items[name].price) / Number(teamData.items[name].eps);
//if the current item is less than the minimum item, replace it.
if (average < minItem.min) {
minItem.name = name;
minItem.min = average;
}
}
//write the current data into the json file
fs.writeFileSync(client.config.dataFolder + "/teamUpgrades.json", JSON.stringify(teamData));
message.channel.send(minItem.name);
} catch (err) {
console.log(err);
}
}
You can check if message.channel.id is equal to one of your IDs and if not, ignore it.
module.exports.run = (client, message) => {
if (['ID 1 here', 'ID 2 here'].includes(message.channel.id)) return;
};
Why the loop only return the last value?
Can someone help me to get all the values return in the SQL insert
tableau.forEach(function(obj) {
for(let i = 0; i < obj.produits.length; i++) {
let bd_nom = obj.produits[ii].nom
let bd_description = obj.produits[ii].description
let bd_titre = obj.titre
records = [[bd_nom, bd_description, bd_titre]]
con.connect(function(err) {
let sql = "INSERT INTO scrapeded (nom, text, titre) VALUES ?";
con.query(sql, [records], function (err, result) {
console.log(result)
console.log("Nombre de rangée affectée : " + result.affectedRows)
console.log("Nombre d'enregistrement affectée avec avertissement : " + result.warningCount)
console.log("Message du serveur mySQL : " + result.message)
})
})
}
})
You're implicitly assigning and reassigning to the global variable records on each iteration. So, by the time the asynchronous query starts, the main thread has ended and records remains as the last value it was assigned.
Declare it with const instead to ensure that there's a new binding for each iteration.
Also, there's no need to declare an array and then immediately destructure it to select the first element - instead, simply declare records as a single-dimensional array with two items:
tableau.forEach(function(obj) {
for(let i = 0; i < obj.produits.length; i++) {
let bd_nom = obj.produits[ii].nom
let bd_description = obj.produits[ii].description
let bd_titre = obj.titre
const records = [bd_nom, bd_description, bd_titre]
con.connect(function(err) {
let sql = "INSERT INTO scrapeded (nom, text, titre) VALUES ?";
con.query(sql, records, function (err, result) {
console.log(result)
console.log("Nombre de rangée affectée : " + result.affectedRows)
console.log("Nombre d'enregistrement affectée avec avertissement : " + result.warningCount)
console.log("Message du serveur mySQL : " + result.message)
})
})
}
})
I have a callable function that should return a value, but the only thing ever returned is null. Below is the current version of the function. I have also tried having a return on the first promise (the original once call), and at the end in another then returning the GUID. It actually returned data in that case, but it returned immediately and the GUID was empty.
How can I accomplish my goal and still return the GUID? I don't know when the function is called if I will use a new GUID that I generate, or one that already exists in the database.
There is a similar question here: Receiving returned data from firebase callable functions , but in that case it was because he never returned a promise from the function. I am returning a promise on all code paths. Unless I have to return the initial promise from the once call? In which case, how can I return the GUID when I don't know it yet?
I am also trying to throw an error in a couple of places and the error shows up in the logs for the function, but is never sent to the client that called the function.
I am going off of the examples here: https://firebase.google.com/docs/functions/callable
Sorry for the code bomb.
Calling the function:
var newGame = firebase.functions().httpsCallable('findCreateGame');
newGame({}).then(function(result) {
// Read result of the Cloud Function.
//var sGameID = result.data.guid;
console.log(result);
}).catch(function(error) {
console.log(error);
});
Function:
exports.findCreateGame = functions.https.onCall((data, context) => {
console.log("findCurrentGame Called.")
/**
* WHAT NEEDS DONE
*
*
* Pull in user's information
* Determine their win/loss ratio and search for a game using transactions in either low medium or high queue
* If there are no open games in their bracket, search the one above, then below
* If no open games anywhere, create a new game in their bracket
* If an open game is found, write the UID to the game and add the game's ID to the user's profile
*
*/
var uid = context.auth.uid;
var section = "";
var sUsername = "";
var sProfilePic = "";
var currentGames = null;
var sGUID = "";
//Get the user's info
var userref = admin.database().ref('users/' + uid);
userref.once("value", function(data) {
var ratio = 0;
var wins = parseInt(data.val().wins);
var losses = parseInt(data.val().losses);
var lives = parseInt(data.val().lives);
if (lives < 1){
//This user is out of lives, should not have been able to get here
//Throw an exception so that we can see why it failed
throw new functions.https.HttpsError('permission-denied', 'You do not have enough lives to start a new game.');
}
sUsername = data.val().username;
sProfilePic = data.val().profilepicture;
//Handle if they have no losses
if (losses == 0){
ratio = 100;
} else {
ratio = (wins / losses) * 100;
}
//If they have played less than 5 games, put them in noob tier
if (wins + losses < 5){
ratio = 0;
}
if (ratio <= 33){
section = "noob";
} else if (ratio > 33 && ratio <= 66){
section = "average";
} else {
section = "expert";
}
}).then(() => {
//Get all of the games this user is currently in
admin.database().ref('games').orderByChild(uid).once('value', function(data) {
currentGames = data.val();
}).then(() => {
//Generate a new GUID in case we need to set up a new game
sGUID = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
var queueref = admin.database().ref('gamequeue/' + section);
queueref.transaction(function(currentGUID) {
if (currentGUID == null){
//Write our GUID in the queue
return sGUID;
} else {
//Get the id of the game we just got
sGUID = currentGUID
return null;
}
}).then((res) => {
if (res.snapshot.val() != null){
//This means we are creating the game lobby
//Generate a new answer
var newAnswer = "";
while (newAnswer.length < 4){
var temp = Math.floor(Math.random() * 9) + 1;
temp = temp.toString();
if (!newAnswer.includes(temp)){
newAnswer += temp;
}
}
var obj = {username: sUsername, score: 0, profilepicture: sProfilePic};
return admin.database().ref('games/' + sGUID).set({id: sGUID, requestor: uid, [uid]: obj, answer: newAnswer, turn: uid, status: 'pending'}).then(() => {
return {guid: sGUID};
});
} else {
//We found a game to join
//If we are in a duplicate request situation, make sure the GUID is a string
if (typeof(sGUID) != 'string'){
sGUID = Object.keys(sGUID)[0];
}
//Make sure we didn't find our own game request
if (currentGames[sGUID] != null){
//Add this GUID back to the queue, we shouldn't have removed it
return admin.database().ref('gamequeue/' + section + '/' + sGUID).set('');
//Throw an exception that says you can only have one open game at a time
throw new functions.https.HttpsError('already-exists', 'We are still finding a match for your last request. You are only allowed one open request at a time.');
} else {
//Get the current game info
admin.database().ref('games/' + sGUID).once('value', function(data) {
var sRequestor = data.val().requestor;
var sOpponentUsername = data.val()[sRequestor].username;
var sOpponentProfilePic = data.val()[sRequestor].profilepicture;
//Write all of our info to the game
return admin.database().ref('games/' + sGUID).update({[sRequestor]: {opponentusername: sUsername, opponentprofilepicture: sProfilePic}, [uid]: {username: sUsername, score: 0, opponentusername: sOpponentUsername, opponentprofilepicture: sOpponentProfilePic}, status: 'active'}).then(() => {
return {guid: sGUID};
});
});
}
}
});
});
})
});
The documentation for callable functions explains:
To return data after an asynchronous operation, return a promise. The
data returned by the promise is sent back to the client.
You have many asynchronous operations that must be chained together. A return needs to be added to each of these statements (as shown):
return userref.once("value", function(data) {...
return admin.database().ref('games').orderByChild(uid).once('value', function(data) {...
return queueref.transaction(function(currentGUID) {...
return admin.database().ref('games/' + sGUID).once('value', function(data) {...
EDIT 2
I accidently communicated that the exception was of type IndexOutOfBounds but it is actually of type IndexOutOfRange.
I'm trying to save some objects to a server. These are the actions that are taken:
The javascript array is an array of Text objects.
These Text objects are put inside a TextModel list when they are transfered to the controller. (by using JQuery.Post)
Each element in the TextModels list then needs to be put into a new server object, TextInfo.
Each TextInfo object is put into a new array that's stored in a PageInfo object
The PageInfo object is send to the server for further processing.
The process errors on #3. For some reason I get an IndexOutOfRange exception when looping through the TextModel list. After all TextModel list elements are added (looped through) to the new TextInfo list, the error comes. This when it tries to increase the for-loops counter (i). I expect it to increase i and then exit the loop when the condition isn't met but it seemingly errors on i++.
I have no idea what could be causing this error. As seen in the code I only use the listed objects to fill the properties of the new object, I don't try to edit the properties while in the loop. Any insight as to what could cause the problem would be helpful. Thanks in advance.
Edit 1
Apparently this wasn't clear enough. All objects send with the post are received as expected in the controller. Count always holds the expected amount of elements and all elements are properly set. See JSON example & Image 1 for details.
Text object as defined in Javascript (#1)
function Text() {
//this.Id = 0;
this.text = "Hallo";
this.x = 0;
this.y = 0;
this.fillColor = "black";
this.fontFamily = "Arial";
this.fontStyle = "normal";
this.fontSize = "18pt";
this.fontWeight = "normal";
this.textAlignment = "start";
this.angle = 0;
}
function addText(text, fillColor, fontSize, fontFamily, fontStyle, fontWeight, textAlignment, x, y, angle) {
var textTemp = new Text;
textTemp.text = multilineText(text, fontSize, fontFamily, fontStyle);
textTemp.fillColor = fillColor;
textTemp.fontSize = fontSize;
textTemp.fontFamily = fontFamily;
textTemp.fontWeight = fontWeight;
textTemp.fontStyle = fontStyle;
textTemp.x = x;
textTemp.y = y;
textTemp.textAlignment = textAlignment;
textTemp.angle = angle;
textObjects.push(textTemp);
}
Javascript JQuery.Post & TextModel in Controller (#2)
// Saves page information
// Called on Save, Next / Previous Page.
// #param curPageNum The currently selected page's number.
function savePage(curPageNum) {
var pageNumber = curPageNum;
var json = JSON.stringify({ TextObjects: textObjects, ImageSource: imageSource, CurrentPageNumber: pageNumber });
alert(json);
$.ajax({
url: "/NextprintPhotobook/SavePageInfo",
type: "POST",
data: json,
contentType: 'application/json; charset=utf-8',
success: function (data) {
console.log(data.message);
showSuccess(data.message);
},
error: function (data) {
console.log(data);
showError("Er is een fout opgetreden bij het opslaan van de foto.");
}
});
}
Controller (#3, #4)
public ActionResult SavePageInfo(List<TextModel> TextObjects, string ImageSource, int CurrentPageNumber)
{
try
{
using (HttpClient client = new HttpClient())
{
#region Define & initialize textInfoArray (Array of Textinfo objects)
// textInfoArray used to set property of the page info object.
TextInfo[] textInfoArray = null;
List<TextInfo> textInfoList = new List<TextInfo>();
if (TextObjects != null)
{
// Build textInfo list.
// textInfoList used to build a list from the TextObjects parameter.
for (int i = 0; i < TextObjects.Count; i++)
{
TextModel textObject = TextObjects[i];
PositionInfo positionInfo = null;
if (textObject.x >= 0 && textObject.y >= 0)
{
int xTemp = textObject.x;
int yTemp = textObject.y;
positionInfo = new PositionInfo()
{
X = xTemp,
Y = yTemp
};
}
string textTemp = textObject.text;
string fontFamilyTemp = textObject.fontFamily;
string fontSizeTemp = textObject.fontSize;
string fontWeightTemp = textObject.fontWeight;
string fontStyleTemp = textObject.fontStyle;
string fillColorTemp = textObject.fillColor;
int rotationTemp = textObject.angle;
string alignmentTemp = textObject.textAlignment;
TextInfo textInfo = new TextInfo()
{
Value = textTemp,
Font = fontFamilyTemp,
Size = fontSizeTemp,
Weight = fontWeightTemp,
Style = fontStyleTemp,
Color = fillColorTemp,
Rotation = rotationTemp,
Position = positionInfo,
Alignment = alignmentTemp
};
textInfoList.Add(textInfo);
}
textInfoArray = textInfoList.ToArray();
}
#endregion
#region Define & initialize PageInfo
PageInfo pageInfo = null;
if (textInfoList == null)
{
return Json(new APIResponse { OK = 0, message = "Er is een onbekende fout opgetreden binnen de API." }, "text/html");
}
string fileName = "";
string tempSource = ImageSource;
fileName = this.getFileNameFromSource(tempSource);
if (fileName == null)
{
return Json(new APIResponse { OK = 0, message = "Er is een onbekende fout opgetreden binnen de API." }, "text/html");
}
if (CurrentPageNumber <= 0)
{
return Json(new APIResponse { OK = 0, message = "Er is een onbekende fout opgetreden binnen de API." }, "text/html");
}
pageInfo = new PageInfo()
{
PageNumber = CurrentPageNumber,
FileName = fileName,
Text = textInfoArray
};
#endregion
client.BaseAddress = new Uri(SERVER_URI);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.PostAsJsonAsync<PageInfo>("api/Xml/SavePageInfo?hash=" + SecurityHash + "&collectionId="
+ CollectionId + "&version=" + Version, pageInfo).Result;
if (response.IsSuccessStatusCode)
{
APIResponse apiResponse = response.Content.ReadAsAsync<APIResponse>().Result;
Logger.log("API response received, see API log for more details.");
return Json(apiResponse, "text/html");
}
else
{
throw new Exception(response.ReasonPhrase);
}
}
}
catch (Exception e)
{
Logger.log("An exception occurred while saving page info: {0}", e.Message);
return Json(new APIResponse { OK = 0, message = "Er is een onbekende fout opgetreden bij het communiceren met de API." }, "text/html");
}
}
JSON Example
This is the JSON that's send:
[{"TextObjects":[{"text":"Test
","x":50,"y":50,"fillColor":"#77DD44","fontFamily":"arial","fontStyle":"normal","fontSize":"18pt","fontWeight":"normal","textAlignment":"start","angle":0}],"ImageSource":"http://localhost:22223//Cyber/1718/1/img/resized/1.jpg","CurrentPageNumber":1}]
C# received object