lvl system not working with mysql - Discord Bot - mysql

So Im trying to make leveling system in my bot but the problem is that when it reaches enough xp to lvl up it will remove the xp but wont add level. I dont know what is wrong with my code but its not working Im using the same technique for editing xp so it adds them but its not working for lvl so Imagine it like this. User message ---> generates enough xp for lvl up ---> lvls up. But instead of that it remains on level 1 I think I was searching everywhere for answer but found none. My code is here:
let prf = ".";
let messageArray = message.content.split(" ");
if(message.author.bot) return;
con.query(`SELECT * FROM xplvl WHERE id = '${message.author.id}'`, (err, rows) => {
if (err) throw err;
let sql;
if (rows.length < 1){
sql = `INSERT INTO xplvl (id, xp, lvl) VALUES ('${message.author.id}', ${Generatexp()}, ${lvlup()})`
}else{
let xp = rows[0].xp;
let lvl = rows[0].lvl;
let tnlx = 100 * lvl;
let l = 1;
sql = `UPDATE xplvl SET xp = ${xp + Generatexp()} WHERE id = '${message.author.id}'`;
if(xp >= tnlx) {
sql = `UPDATE xplvl SET lvl = ${lvl + l} WHERE id = '${message.author.id}'`;
sql = `UPDATE xplvl SET xp = 0`;
message.channel.send("You leveled up!")
con.query(sql);
return;
}
}
con.query(sql)
})

It's not working because every time you go in to update the level, you are explicitly resetting the experience points back to zero which brings back to level 1 on any subsequent attempts. Then it updates ALL RECORDS back to an xp = 0.
REMOVE your update query resetting the XP = 0.
You are building the sql command to update the level, but never executing it. Then immediately change the sql command to just the xp = 0 (which will do for EVERY record) and thus the level never gets updated.
I also don't think you really mean to reset the xp level and here's why. Your level's appear to be multiple of 100... thus
Level Points
1 100
2 200
3 300
By resetting the xp, getting to level 1 is no problem. Person earned 100 points. Now they are forced back to 0. Now the person has to get 100 points again and it says... ok, you hit level 1 again, back to level 1 and reset to zero. It will never get to 200.

Related

Error: On Activation: Select: Type: Nothing expected, Array,String,Config entry when running specified code in Arma 3

So, my issue is whenever I run this code block within a trigger with condition any player,
private _all_freedom_units = ["B_FRD_Freedomer_Patrolman_01","B_FRD_Freedomer_Sniper_01", "B_FRD_Freedomer_Exo_1", "B_FRD_Freedomer_Warrior_01", "B_FRD_Freedomer_SEVA_01", "B_FRD_Freedomer_Gaurdian_01", "B_FRD_Freedomer_Seva_II_01"];
private _final_pos = [0,0,0];
private _position_player = [0, 0, 0];
_direction = getDir player;
if (_direction > 0 and _direction < 90) then {cardinal_direction = "North";};
if (_direction > 90 and _direction < 180) then {cardinal_direction = "South";};
if (_direction > 180 and _direction < 250) then{cardinal_direction = "South";};
if (_direction > 250 and _direction < 359) then{cardinal_direction = "North";};
_position_player = getPos player;
_position_player_x = _position_player select 0;
_position_player_y = _position_player select 1;
if (cardinal_direction == "North") then{
_random_x = [250, 500] call BIS_fnc_randomInt;
_random_y = [250, 500] call BIS_fnc_randomInt;
_final_pos set [0 , _position_player_x + 200 + _random_x];
_final_pos set [1 , _position_player_y + 200 + _random_y];
};
if (cardinal_direction == "South") then{
_random_x = [-250, -500] call BIS_fnc_randomInt;
_random_y = [-250, -500] call BIS_fnc_randomInt;
_final_pos set [0 , _position_player_x + _random_x];
_final_pos set [1 , _position_player_y + _random_y];
};
_position = _final_pos;
_group_freedom_patrol = createGroup [west, true];
hint str _final_pos select 0;
_random_number = floor random 5;
The editor returns with,
On Activation: Select: Type Nothing, expected Array,String,Config entry
I have a suspicion from similar reports that it's centered around these statements
_position_player = getPos player;
_position_player_x = _position_player select 0;
_position_player_y = _position_player select 1;
Because of the "select" aspect of the error code, but I just started Arma 3 scripting
A similar post recommended dealing with the Condition portion of the Trigger, but the fixes their didn't work. I'm not quite sure what the issue is at this point, as I'm new to Arma 3 scripted.
The big issue here is I'm 90% sure it's an issue with syntax, because if it was logic the trigger would allow me to use the code in the first place. In this case, the built in checks are barring me from running the code, and syntax errors are harder than logic for me.
The code is intended to run properly, grab the first player who enters the trigger, and using the position data and angle it should (this part of the code isn't included as I'm testing in chunks and this chunk isn't working) spawn units in front of the player, min 250 out, heading towards them,
But as I explained previously, the Arma 3 debugger is yelling at me before I can even test the code.
Take this with a grain of salt, I haven't scripted for Arma 3 for quite the time.
I think if the errors comes up in the editor, then it may be because the player may not be defined (makes sense in the editor). You should check that. Either way - to make it multiplayer compatible - you should use the the "thisList" variable to access the list of the objects which are in the trigger area. If this only triggers for players, then you can use "thisList select 0".
See the passed variables for On Activation in the documentation

Sending info to database and retrieving as well as using for k,v, in pairs() do

Issue i have come across is i have an item, if you use this item it writes to the database with your id and the item name. which is correct and this is what i want to happen, but i want it to first look at the database and see if the item is already there and if so stop the insert.
This is the item.
QBCore.Functions.CreateUseableItem("pumpshotgun_bp", function(source, item)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if Player.Functions.GetItemBySlot(item.slot) ~= nil then
QBCore.Functions.TriggerCallback('sin-crafting:server:getCrafts', src, function(result)
if result ~= nil then
TriggerClientEvent("sin-crafting:client:Update", source, "pumpshotgun_bp")
end
end)
end
end)
after that i query the info to the database
QBCore.Functions.CreateCallback('sin-crafting:server:getCrafts', function(source, cb)
local Player = QBCore.Functions.GetPlayer(source)
local cid = Player.PlayerData.citizenid
local printList = {}
MySQL.query('SELECT * FROM player_crafts WHERE cid = ?', { Player.PlayerData.citizenid }, function(crafts, item)
for k, v in pairs(crafts) do
if v == nil then
end
table.insert(printList,
{
citizenid = v.citizenid,
blueprint = v.blueprint,
}
)
end
cb(json.encode(printList))
end)
end)
and then
the item then triggers this when used and changed info from the item_bp to the actual name for the database
RegisterNetEvent('sin-crafting:client:Update', function(data)
if data == "pumpshotgun_bp" then
TriggerServerEvent('sin-crafting:server:newBlueprint', 'pumpshotgun')
end
end)
Problem now is when i use that item again it will write it again to the database and i dont want that i want instead to set up a notify script that will tell them they have already learned that.
This is the first half of my issue, the second half is pulling the list from the database and and checking it in the script. I really need help as I have been trying to do this for over a week now and cant find a way to do it
This is the config to use for the for k,v in pairs() do, <---which I cant figure out how to do right....
Config.Weapons = {
"pumpshotgun",
"dbshotgun",
"assaultrifle",
"smg",
"combatpistol",
"gusenberg",
"microsmg",
"carbinerifle",
"compactrifle",
"heavypistol",
"machinepistol",
"revolver",
"rifle_silencer",
"pistol_silencer",
"smg_silencer",
"shotgun_silencer",
"weapon_optics",
}

MySQL and LUA not triggering correctly or code incorrect

I am struggling to trigger a server event succesfully on my FiveM server. Or maybe it gets triggered but the server event is incorrect. However I do not get any errors and I don't know what to fix...
Server-side
RegisterServerEvent('carwash:pay')
AddEventHandler('carwash:pay', function()
local _source = source
local price = 20
local identifier = GetPlayerIdentifier(_source)
MySQL.Async.fetchAll("SELECT * FROM economy WHERE identifier = #identifier", {
['#identifier'] = identifier
}, function(result)
if result >= 20 then
MySQL.Async.execute('UPDATE economy SET cash = cash - #price WHERE identifier = #identifier',
{ ['#identifier'] = identifier, ['#price'] = price }
)
end
end)
end)
Client-Side
TriggerServerEvent('carwash:pay')
I don't know if you're still working on it or figured it out but for those who have the same problem, I'm gonna answer this.
The problem here is that you are comparing a whole table (SELECT * FROM economy...) to the number 20.
Besides, a "fetchAll" will allways output an array, so, in order to acces the column cash from the table economy, you need to use "result[1].cash".
Then, sometimes the "error" is not a syntaxe one, you need to put some "print()" here and there to understand where it stops, changes or just check if it works.
e.g. :
RegisterServerEvent('carwash:pay')
AddEventHandler('carwash:pay', function()
local _source = source
local price = 20
local identifier = GetPlayerIdentifier(_source)
MySQL.Async.fetchAll("SELECT * FROM economy WHERE identifier = #identifier", {['#identifier'] = identifier},
function(result)
-- CHECK WHAT IT RESULT
print(result)
if result >= 20 then
MySQL.Async.execute('UPDATE economy SET cash = cash - #price WHERE identifier = #identifier', { ['#identifier'] = identifier, ['#price'] = price })
end
end)
end)

Update planned order - two committed modifications, only one saved

I need to update two information on one object: the quantity (PLAF-gsmng) and refresh the planned order via the module function 'MD_SET_ACTION_PLAF'.
I successfully find a way to update each data separately. But when I execute the both solutions the second modification is not saved on the database.
Do you know how I can change the quantity & set the action on PLAF (Planned order) table ?
Do you know other module function to update only the quantity ?
Maybe a parameter missing ?
It's like if the second object is locked (sm12 empty, no sy-subrc = locked) ... and the modification is not committed.
I tried to:
change the order of the algorithm (refresh and after, change PLAF)
add, remove, move the COMMIT WORK & COMMIT WORK AND WAIT
add DEQUEUE_ALL or DEQUEUE_EMPLAFE
This is the current code:
1) Read the data
lv_plannedorder = '00000000001'
"Read PLAF data
SELECT SINGLE * FROM PLAF INTO ls_plaf WHERE plnum = lv_plannedorder.
2) Update Quantity data
" Standard configuration for FM MD_PLANNED_ORDER_CHANGE
CLEAR ls_610.
ls_610-nodia = 'X'. " No dialog display
ls_610-bapco = space. " BAPI type. Do not use mode 2 -> Action PLAF-MDACC will be autmatically set up to APCH by the FM
ls_610-bapix = 'X'. " Run BAPI
ls_610-unlox = 'X'. " Update PLAF
" Customize values
MOVE p_gsmng TO ls_plaf-gsmng. " Change quantity value
MOVE sy-datlo TO ls_plaf-mdacd. " Change by/datetime, because ls_610-bapco <> 2.
MOVE sy-uzeit TO ls_plaf-mdact.
CALL FUNCTION 'MD_PLANNED_ORDER_CHANGE'
EXPORTING
ecm61o = ls_610
eplaf = ls_plaf
EXCEPTIONS
locked = 1
locking_error = 2
OTHERS = 3.
" Already committed on the module function
" sy-subrc = 0
If I go on the PLAF table, I can see that the quantity is edited. It's working :)
3) Refresh BOM & change Action (MDACC) and others fields
CLEAR ls_imdcd.
ls_imdcd-pafxl = 'X'.
CALL FUNCTION 'MD_SET_ACTION_PLAF'
EXPORTING
iplnum = lv_plannedorder
iaccto = 'BOME'
iaenkz = 'X'
imdcd = ls_imdcd
EXCEPTIONS
illegal_interface = 1
system_failure = 2
error_message = 3
OTHERS = 4.
IF sy-subrc = 0.
COMMIT WORK.
ENDIF.
If I go on the table, no modification (only the modif. of the part 2. can be found on it).
Any idea ?
Maybe because the ls_610-bapco = space ?
It should be possible to update planned order quantity with MD_SET_ACTION_PLAF too, at least SAP Help tells us so. Why don't you use it like that?
Its call for changing the quantity should possibly look like this:
DATA: lt_acct LIKE TABLE OF MDACCTO,
ls_acct LIKE LINE OF lt_acct.
ls_acct-accto = 'BOME'.
APPEND lt_acct.
ls_acct-accto = 'CPOD'.
APPEND lt_acct.
is_mdcd-GSMNG = 'value' "updated quantity value
CALL FUNCTION 'MD_SET_ACTION_PLAF'
EXPORTING
iplnum = iv_plnum
iaenkz = 'X'
IVBKZ = 'X'
imdcd = is_mdcd "filled with your BOME-related data + new quantity
TABLES
TMDACCTO = lt_accto
EXCEPTIONS
illegal_interface = 1
system_failure = 2
error_message = 3.
So there is no more need for separate call of MD_PLANNED_ORDER_CHANGE anymore and no more problems with update.
I used word possibly because I didn't find any example of this FM call in the Web (and SAP docu is quite ambiguous), so I propose this solution just as is, without verification.
P.S. Possible actions are listed in T46AS table, and possible impact of imdcd fields on order can be checked in MDAC transaction. It is somewhat GUI equivalent of this FM for single order.

PHP prevent MySQL race condition

I am trying to prevent users joining at the "same time" from selecting the same available admin.
What i'm doing is:
$conn->beginTransaction();
$sth = $conn->query("SELECT admin,room FROM admins WHERE live = 1 AND available = 1 ORDER BY RAND() LIMIT 1 FOR UPDATE");
$free_admin = $sth->fetch();
if (!empty($free_admin)) {
$conn->query("UPDATE admins SET available = 0 WHERE room = " . $free_admin['room']);
.
.
$conn->commit();
} else {
$conn->rollBack();
}
Unfortunately it's not really working. When there is a high traffic, many users end up selecting the same free admin which causes an issue.
How can i lock a SELECTED row so i can read it and update it by only one user before any other user can read it?
In the updatestatement, use
WHERE room = ... AND availabe = 1
After the query, check mysql affected_rows to verify you did change the availability succesfully, and if not, restart.