Leaderboards level system discord js - node.js

I have this xp system and I save each id in a json with a name.
How can I display a top 5 people?
Is there a way to retrieve the data and display 5 at a time?
I would try to sort and after creating a forum to display fixed 5 but I don't know exactly how I could do that.
Any ideas?
const xp = require("../../xp.json")
if(!xp[message.author.id]) {
xp[message.author.id] = {
xp: 0,
level:1
};
}
let curxp = xp[message.author.id].xp;
let curlvl = xp[message.author.id].level;
let nxtLevelXp = curlvl * 300;
let difference = nxtLevelXp - curxp;
For example, this is how I retrieve the data for display

Use the Object.entries , here is an example -
const xp = require("../../xp.json");
var top5 = Object.entries(xp).sort((a,b)=>b[1].level - a[1].level).splice(0,5);
Try mapping them

Related

Exporting Gcal with Colours

Is there any way to export colours from Goggle Calander and post them into Goggle Sheets - I've seen posts from 2019 from various sites saying that this functionality was impossible, but I use colours to break up my calendar and I would love to bring colours over to help with my stats.
You can follow this guide:
Create a new Google Sheet
Create a new Bound Script via Extensions > Apps Script
Activate Advanced Service for accesing Calendar API Colors
Copy this code in:
const sS = SpreadsheetApp.getActiveSheet()
function bringCalendarToSheet() {
// Getting the colors for the Calendar and Events
const colors = Calendar.Colors.get()
const colorsCalendar = colors.calendar
const colorsEvents = colors.event
// Parsing and setting the data for the Calendar Colors
const A1 = sS.getRange('A1').setValue('Calendar Colors')
const colorsCalendarLength = Object.keys(colorsCalendar).length
const rCC = sS.getRange(2, 1, 1, colorsCalendarLength).setBackgrounds([Object.keys(colorsCalendar).map(k => {
return colorsCalendar[k].background
})])
// Parsing and setting the data for the Event Colors
const A3 = sS.getRange('A3').setValue('Event Colors')
const colorsEventsLength = Object.keys(colorsEvents).length
const rEC = sS.getRange(4, 1, 1, colorsEventsLength).setBackgrounds(
[Object.keys(colorsEvents).map(k => {
return colorsEvents[k].background
})]
)
}
This will show all Calendar available colors:
Result:

Level system Discordjs

I am making a Level system for my bot. It's working perfectly, but there's one problem about the level system, It is when the bot making a restart, the current exp is resetting too. How can I stop it like that?
Here is my current code.
const db = require('quick.db');
if (!db[msg.author.id]) db[msg.author.id] = {
xp: 0,
level: 0
};
db[msg.author.id].xp++;
let userInfo = db[msg.author.id];
if(userInfo.xp > 100) {
userInfo.level++
userInfo.xp = 0
msg.reply("Congratulations, you level up")
}
if(msg.content.toLowerCase().startsWith(`${prefix}level`)) {
let userInfo = db[msg.author.id];
let member = msg.mentions.members.first();
let embed = new MessageEmbed()
.setTitle('Level Checking')
.setDescription("<#" + msg.member.id + ">" + ` Your current level is: ${userInfo.level}`)
.setColor('RANDOM')
.addFields({name:"Level", value: `${userInfo.level}`})
.addField("XP", userInfo.xp+"/100")
.setTimestamp()
.setFooter('Level | Reborn')
if(!member) return msg.channel.send({embeds: [embed]})
let memberInfo = db[member.id]
let embed2 = new MessageEmbed()
.setTitle('Level Checking')
.setDescription("<#" + msg.member.id + ">" + ` Your current level is: ${memberInfo.level}`)
.setColor('RANDOM')
.addFields({name:"Level", value: `${memberInfo.level}`})
.addField("XP", memberInfo.xp+"/100")
.setTimestamp()
.setFooter('Level | Reborn')
msg.channel.sendEmbed({embeds: [embed2]})
}
I'm using Discordjs v13
I don't see you are connecting to a database. All I see that you are using quick.db
I have not used quick.db but from the way you have written I am assuming that it is storing the data in a temp variable called db. You need to store that db in a database (for you library it should be sqlite3)
You are storing the data in the variable db.
Variables always get resettet when your bot restarts.
To keep the data you need to write the data to the actual database
For example:
db.set(msg.author.id.'level', 0) would set the users level to 0
Check the docs for more inforamtion about how getting data(and how to set/modify it)
You can use mongo db its a good database service, you can find a lot of documentation on internet and its easy to use
https://www.mongodb.com/, its free to use.
https://www.youtube.com/watch?v=8no3SktqagY, this video will explain you everything
I hope it will help

Array list with 2 values and doing it to a top 10 list

im working on a Discord bot and have a reputation system with fs (npm package) and saving peoples reps in a file and doing the file name as they discord id
now im working on a top 10 command and would need some help here, i currently have this as code:
let users = [];
let reps = [];
fs.readdirSync('./data/reps/').forEach(obj => {
users.push(obj.replace('.json', ''))
let file = fs.readFileSync(`./data/reps/${obj}`)
let data = JSON.parse(file)
reps.push(data.reps)
})
let top = [...users, ...reps]
top.sort((a,b) => {a - b})
console.log(top)
the files form the users are like this:
{
"users": [
"437762415275278337"
],
"reps": 1
}
users are the current users that can't rep the persion anymore and don't need to use it in the command
i wan to get the top 10 of reps so that i can get the user id and how many reps they have, how could i do it with the code above?
You could try this
const topTen = fs.readdirSync('./data/reps/').map(obj => {
const file = fs.readFileSync(`./data/reps/${obj}`);
const data = JSON.parse(file);
return { ...data, name: obj.replace('.json', '') };
}).sort((a, b) => a.reps - b.reps).slice(0, 10);
console.log(topTen);
I would change how you push the data
const users = [];
fs.readdirSync('./data/reps/').forEach(obj => {
let file = fs.readFileSync(`./data/reps/${obj}`)
let data = JSON.parse(file)
reps.push({ reps: data.reps, id: obj.replace(".json", "") });
})
That way when you sort the array the id goes along with
//define this after the fs.readdirSync.forEach method
const top = users.sort((a,b)=> a.reps-b.reps).slice(0,10);
If you want an array of top ids
const topIds = top.map(e => e.id);
If you want a quick string of it:
const str = top.map(e => `${e.id}: ${e.reps}`).join("\n");
Also you should probably just have one or two json files, one would be the array of user id's and their reps and then the other could be of user id's and who they can't rep anymore

java.lang.NumberFormatException: For input string: "16000$" in kotlin

I want to make display show "16000$" before click increase btn or decrease btn.
when I make code like this error caused by :java.lang.NumberFormatException: For input string: "16000$ . but I should display $. Lets check my code and help me plz.
var productprice = findViewById<TextView>(R.id.productPrice)
productprice.text= intent.getStringExtra("price")+"$"
var price = productPrice.text.toString().toInt()
var inc_val= price
var getPrice = price
decrease.isEnabled=false
increase.setOnClickListener {
increaseInteger()
getPrice+= inc_val
productprice.text=getPrice.toString()+"$"
}
decrease.setOnClickListener {
decreaseInteger()
getPrice -= inc_val
productprice.text=getPrice.toString()+"$"
}
You are trying to parse the string with "$" to int, Hence you are getting NumberFormatException.
Try this instead:
var productprice = findViewById<TextView>(R.id.productPrice)
productprice.text= intent.getStringExtra("price")+"$"
var price = parseInt(intent.getStringExtra("price"))
var inc_val= price
var getPrice = price
decrease.isEnabled=false
increase.setOnClickListener {
increaseInteger()
getPrice+= inc_val
productprice.text=getPrice.toString()+"$"
}
decrease.setOnClickListener {
decreaseInteger()
getPrice -= inc_val
productprice.text=getPrice.toString()+"$"
}
var price = productPrice.text.toString().toInt() - you try to convert "16000$" to Int here. Please get substring here first.
Formally, right code is:
val priceText = productPrice.text.toString()
val price = priceText.substring(0, priceText.length - 1).toInt()
However really I advice you to store value internally. You price is part of model. E.g. you can avoid text parsing and just read value from model. E.g. code will be like this:
var price = intent.getIntExtra("price") // we store int value here, not String
var inc_val= price
decrease.isEnabled=false
displayPrice()
increase.setOnClickListener {
intent.setIntExtra(intent.getIntExtra("price") + inc_val) // read, update, save
displayPrice()
}
decrease.setOnClickListener {
intent.setIntExtra(intent.getIntExtra("price") - inc_val) // read, update, save
displayPrice()
}
/*this function just shows price*/
fun displayPrice() {
val price = intent.getIntExtra("price")
productprice.text= "$price\$"
}

Revit API SetPointElementReference(PointOnPlane) - wrong workplane

I try to create a family instance using CreateAdaptiveComponentInstance and try to host it on a reference point, that's also a control point of a CurveByPoints (spline).
The family links properly to the reference point, but the rotation of the reference point's workplane is totally ignored.
Try this standalone example. Move the reference point P2 -> The cross section at P1 will not rotate.
Now, rebuild and change the >> if(true) << to 'false'. Now you see what I want. But as soon as you move the point P2, the link between P2's coordinates and the family is broken.
CurveByPoints spl = null;
ReferencePointArray pts = null;
// create ref points
var p1 = doc.FamilyCreate.NewReferencePoint(new XYZ( 0, 0, 0)); p1.Name = "P1";
var p2 = doc.FamilyCreate.NewReferencePoint(new XYZ(10,10, 0)); p2.Name = "P2";
var p3 = doc.FamilyCreate.NewReferencePoint(new XYZ(30,20, 0)); p3.Name = "P3";
pts = new ReferencePointArray();
pts.Append(p1); pts.Append(p2); pts.Append(p3);
// create a spline
spl = doc.FamilyCreate.NewCurveByPoints(pts);
spl.Visible = true;
spl.IsReferenceLine = false; // MOdelliinie
// change points to adaptive points
foreach(ReferencePoint p in pts)
{
AdaptiveComponentFamilyUtils.MakeAdaptivePoint(doc, p.Id, AdaptivePointType.PlacementPoint);
p.CoordinatePlaneVisibility = CoordinatePlaneVisibility.Always;
p.ShowNormalReferencePlaneOnly = true;
}
// find an adaptive family to place at the points
FamilySymbol fam_sym = null;
var filter = new FilteredElementCollector(doc);
ICollection<Element> col = filter.OfClass(typeof(FamilySymbol)).ToElements();
if(col!=null)
{
foreach(FamilySymbol ele in col)
{
if(ele == null || !AdaptiveComponentInstanceUtils.IsAdaptiveFamilySymbol(ele) ) {continue;}
if(fam_sym == null)
{
fam_sym=ele;
}
if(ele.Name == "profil_adapt_offset_einfach2") // use a special one instead of the first matching
{
fam_sym = ele as FamilySymbol;
break;
}
}
}
// create family instances
if(fam_sym != null)
{
if(true) // this is waht I want. Try "false" to see what I expect
{
foreach (ReferencePoint p in pts)
{
var inst = AdaptiveComponentInstanceUtils.CreateAdaptiveComponentInstance(doc, fam_sym);
var placements = AdaptiveComponentInstanceUtils.GetInstancePlacementPointElementRefIds(inst);
ReferencePoint fam_pt = doc.GetElement(placements.FirstOrDefault()) as ReferencePoint;
var pl = Plane.CreateByNormalAndOrigin(new XYZ(1,0,0), p.Position);
// #### I THINK HERE IS MY PROBLEM ####
// "plane" just points to the reference POINT,
// and not the XZ-PLANE of the reference point.
Reference plane = p.GetCoordinatePlaneReferenceYZ();
PointOnPlane pop = doc.Application.Create.NewPointOnPlane(plane, UV.Zero, UV.BasisU, 0.0);
fam_pt.SetPointElementReference(pop);
}
}
else
{
// create family instances and place along the path
// -> looks good until you move a reference point
double ltot=0.0;
for(var i=0; i<pts.Size-1; ++i)
{
ltot += pts.get_Item(i).Position.DistanceTo(pts.get_Item(i+1).Position);
}
double lfromstart=0;
for(var i=0; i<pts.Size; ++i)
{
if(i>0)
{
lfromstart += pts.get_Item(i).Position.DistanceTo(pts.get_Item(i-1).Position);
}
var inst = AdaptiveComponentInstanceUtils.CreateAdaptiveComponentInstance(doc, fam_sym);
var placements = AdaptiveComponentInstanceUtils.GetInstancePlacementPointElementRefIds(inst);
var location = new PointLocationOnCurve(PointOnCurveMeasurementType.NormalizedCurveParameter, lfromstart / ltot, PointOnCurveMeasureFrom.Beginning);
PointOnEdge po = doc.Application.Create.NewPointOnEdge(spl.GeometryCurve.Reference, location);
// attach first adaptive point to ref point
var firstPoint = doc.GetElement(placements.FirstOrDefault()) as ReferencePoint;
firstPoint.SetPointElementReference(po);
}
}
}
I'm using Revit 2018.2, here.
People might also search for: GetCoordinatePlaneReferenceXZ, GetCoordinatePlaneReferenceXY.
[edit1]
NewReferencePoint() does not create SketchPlanes
When I manually move a generated reference point -> Now the SketchPlane for this ReferencePoint is generated. But how create that with the API?
[edi2]
- I found that e.g. manually changing the ReferencePoint.CoordinatePlaneVisibility=true will create the SketchPlane I need. But I can't do that in code:
var sel = new List<ElementId>();
foreach (ReferencePoint p in pts)
{
sel.Add(p.Id);
// make plane visible
p.CoordinatePlaneVisibility = CoordinatePlaneVisibility.Always;
// shake point
ElementTransformUtils.MoveElement(doc, p.Id, XYZ.BasisX);
ElementTransformUtils.MoveElement(doc, p.Id, XYZ.BasisX.Negate());
}
ui_doc.Selection.SetElementIds(sel);
doc.Regenerate();
ui_doc.RefreshActiveView();
Will it help if you use the NewReferencePoint overload taking a Transform argument, cf. NewReferencePoint Method (Transform)? That might define the required plane for you and associate it with the point.
The development team replied to your detailed description and test project provided in the attached ZIP file:
The developer seems to be in need of some API we haven’t exposed. PointElement’s API was written before RIDL, so the entire user interface is not exposed to the API. They need an API to get the reference plane that is normal to the the curve that it is driving. This plane is not the same as what is exposed by API PointElement.GetCoordinatePlaneReferenceYZ() (one among the three planes exposed to API).
As per SketchPlanes not being created (in the macro seen in the linked zip file), yes that is correct and matches the UI. SketchPlanes are elements and are different from Autodesk.Revit.DB.Reference. We don’t create them until we have to. And they get garbage collected too. At the end of description, I see some code that should work (assuming they wrapped it in a transaction). Normally selection of the point alone will trigger creation of the SketchPlane from the UI. That aside, I would still not recommend putting the point on SketchPlane for what they want to do.
While, what they want does not exist in API, it still does not quite mean there is no workaround for what they want to achieve. If the Selection or Reference API exposes selectable/visible references on an element, Autodesk.Revit.DB.Reference, then one can iterate over these and host the point. This is generic Element/Reference API.
I hope this clarifies.

Resources