Skip to content

Commit

Permalink
feat(command): Added leaderboard to XP system (#87)
Browse files Browse the repository at this point in the history
  • Loading branch information
Seb committed Apr 19, 2022
1 parent a11b6e6 commit ba81384
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 27 deletions.
120 changes: 95 additions & 25 deletions src/main/java/de/voidtech/gerald/commands/utils/ExperienceCommand.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main.java.de.voidtech.gerald.commands.utils;

import java.awt.Color;
import java.util.Arrays;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -18,7 +19,6 @@
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.MessageChannel;
import net.dv8tion.jda.api.entities.MessageEmbed;

@Command
Expand All @@ -33,55 +33,87 @@ public class ExperienceCommand extends AbstractCommand {
@Override
public void executeInternal(CommandContext context, List<String> args) {
Server server = serverService.getServer(context.getGuild().getId());
if (args.isEmpty()) sendLevelCard(context.getChannel(), context.getMember(), server.getId());
if (args.isEmpty()) sendLevelCard(context, context.getMember(), server.getId());
else {
String ID = ParsingUtils.filterSnowflake(args.get(0));
if (ParsingUtils.isSnowflake(ID)) {
Member mentionedMember = context.getGuild().getMemberById(ID);
Member mentionedMember = context.getGuild().retrieveMemberById(ID).complete();
if (mentionedMember == null) context.getChannel().sendMessage("**You need to mention another member to see their XP!**").queue();
else sendLevelCard(context.getChannel(), mentionedMember, server.getId());
else sendLevelCard(context, mentionedMember, server.getId());
} else {
switch (args.get(0)) {
case "levels":
showAllLevelRoles(context.getChannel(), server, context.getGuild());
showAllLevelRoles(context, server, context.getGuild());
break;
case "addrole":
addLevelUpRole(context.getChannel(), args, server);
addLevelUpRole(context, args, server);
break;
case "removerole":
removeLevelUpRole(context.getChannel(), args, server);
removeLevelUpRole(context, args, server);
break;
case "leaderboard":
showServerLeaderboard(context, server);
break;
case "lb":
showServerLeaderboard(context, server);
break;
}
}
}
}

private void addLevelUpRole(MessageChannel channel, List<String> args, Server server) {
private void showServerLeaderboard(CommandContext context, Server server) {
List<Experience> topTenMembers = xpService.getServerLeaderboardChunk(server.getId(), 10, 0);
int userPosition = xpService.getUserLeaderboardPosition(server.getId(), context.getAuthor().getId());
Experience userXP = xpService.getUserExperience(context.getAuthor().getId(), server.getId());

String leaderboard = "";
int rank = 1;

for (Experience xp : topTenMembers) {
leaderboard += numberToEmoji(rank) + " <@" + xp.getUserID() + ">\n";
leaderboard += "```js\nLevel " + xp.getCurrentLevel() + " | XP " + xp.getTotalExperience() + "\n```";
rank++;
}

leaderboard += "\n**Your Position**\n";
leaderboard += numberToEmoji(userPosition) + " <@" + userXP.getUserID() + ">\n";
leaderboard += "```js\nLevel " + userXP.getCurrentLevel() + " | XP " + userXP.getTotalExperience() + "\n```";

MessageEmbed leaderboardEmbed = new EmbedBuilder()
.setColor(Color.ORANGE)
.setDescription(leaderboard)
.setTitle(context.getGuild().getName() + "'s Most Active Members")
.build();
context.reply(leaderboardEmbed);
}

private void addLevelUpRole(CommandContext context, List<String> args, Server server) {
if (args.size() < 3) {
channel.sendMessage("**You need to supply more arguments! Make sure you have a level and a role mention or ID!**").queue();
context.reply("**You need to supply more arguments! Make sure you have a level and a role mention or ID!**");
return;
}

String level = args.get(1);
if (!ParsingUtils.isInteger(level)) {
channel.sendMessage("**You need to provide a valid number for the level!**").queue();
context.reply("**You need to provide a valid number for the level!**");
return;
}

if (xpService.serverHasRoleForLevel(server.getId(), Integer.parseInt(level))) {
channel.sendMessage("**There is already a role set up for this level!**").queue();
context.reply("**There is already a role set up for this level!**");
return;
}

String roleID = ParsingUtils.filterSnowflake(args.get(2));
if (!ParsingUtils.isSnowflake(roleID)) {
channel.sendMessage("**Please provide a valid role mention or role ID**").queue();
context.reply("**Please provide a valid role mention or role ID**");
return;
}

Guild guild = channel.getJDA().getGuildById(server.getGuildID());
Guild guild = context.getJDA().getGuildById(server.getGuildID());
if (guild.getRoleById(roleID) == null) {
channel.sendMessage("**Please provide a valid role mention or role ID**").queue();
context.reply("**Please provide a valid role mention or role ID**");
return;
}

Expand All @@ -92,23 +124,61 @@ private void addLevelUpRole(MessageChannel channel, List<String> args, Server se
.setTitle("Added Level Up Role!")
.setDescription("Level: `" + level + "`\nRole: <@&" + roleID + ">")
.build();
channel.sendMessageEmbeds(newRoleEmbed).queue();
context.reply(newRoleEmbed);
}

private String numberToEmoji(int number) {
List<String> digits = Arrays.asList(String.valueOf(number).split("")); //Wowzer
String finalNumber = "";
for (String digit : digits) {
finalNumber += convertSingleDigitToEmoji(digit);
}
return finalNumber;
}

private String convertSingleDigitToEmoji(String digit) {
switch (digit) {
case "0":
return ":zero";
case "1":
return ":one:";
case "2":
return ":two:";
case "3":
return ":three:";
case "4":
return ":four:";
case "5":
return ":five:";
case "6":
return ":six:";
case "7":
return ":seven:";
case "8":
return ":eight:";
case "9":
return ":nine:";
case "10":
return ":ten:";
default:
return ":zero:";
}
}

private void removeLevelUpRole(MessageChannel channel, List<String> args, Server server) {
private void removeLevelUpRole(CommandContext context, List<String> args, Server server) {
if (args.size() < 2) {
channel.sendMessage("**You need to provide a level to remove the role from!**").queue();
context.reply("**You need to provide a level to remove the role from!**");
return;
}

String level = args.get(1);
if (!ParsingUtils.isInteger(level)) {
channel.sendMessage("**You need to provide a valid number for the level!**").queue();
context.reply("**You need to provide a valid number for the level!**");
return;
}

if (!xpService.serverHasRoleForLevel(server.getId(), Integer.parseInt(level))) {
channel.sendMessage("**There isn't a role set up for this level!**").queue();
context.reply("**There isn't a role set up for this level!**");
return;
}

Expand All @@ -118,13 +188,13 @@ private void removeLevelUpRole(MessageChannel channel, List<String> args, Server
.setTitle("Removed Level Up Role!")
.setDescription("Role for level `" + level + "` has been removed")
.build();
channel.sendMessageEmbeds(roleDeletedEmbed).queue();
context.reply(roleDeletedEmbed);
}

private void showAllLevelRoles(MessageChannel channel, Server server, Guild guild) {
private void showAllLevelRoles(CommandContext context, Server server, Guild guild) {
List<LevelUpRole> levelUpRoles = xpService.getAllLevelUpRolesForServer(server.getId());
if (levelUpRoles.isEmpty())
channel.sendMessage("**There are no level roles set up in this server! See the help page for more info!**").queue();
context.reply("**There are no level roles set up in this server! See the help page for more info!**");
else {
String roleMessage = "";
for (LevelUpRole role : levelUpRoles) {
Expand All @@ -135,18 +205,18 @@ private void showAllLevelRoles(MessageChannel channel, Server server, Guild guil
.setTitle("Level up roles for " + guild.getName())
.setDescription(roleMessage)
.build();
channel.sendMessageEmbeds(levelRolesEmbed).queue();
context.reply(levelRolesEmbed);
}
}

private void sendLevelCard(MessageChannel channel, Member member, long serverID) {
private void sendLevelCard(CommandContext context, Member member, long serverID) {
Experience userXP = xpService.getUserExperience(member.getId(), serverID);

byte[] xpCard = xpService.getExperienceCard(member.getUser().getAvatarUrl(),
userXP.getCurrentExperience(), xpService.xpNeededForLevel(userXP.getNextLevel()),
userXP.getCurrentLevel(), 1, member.getUser().getName() + "#" + member.getUser().getDiscriminator(),
"#FF0000", "#2E2E2E");
channel.sendFile(xpCard, "xpcard.png").queue();
context.replyWithFile(xpCard, "xpcard.png");
}

@Override
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/de/voidtech/gerald/entities/Experience.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ public long getCurrentExperience() {
return this.experienceGainedToNextLevel;
}

public long getTotalExperience() {
return this.totalExperience;
}

public long getLastMessageTime() {
return this.lastMessageTime;
}
Expand Down
41 changes: 39 additions & 2 deletions src/main/java/de/voidtech/gerald/service/ExperienceService.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class ExperienceService {
public byte[] getExperienceCard(String avatarURL, long xpAchieved, long xpNeeded,
long level, long rank, String username, String barColour, String background) {
try {
String cardURL = config.getExperienceCardApiURL() + "?avatar_url=" + avatarURL +
String cardURL = config.getExperienceCardApiURL() + "xpcard/?avatar_url=" + avatarURL +
"&xp=" + xpAchieved + "&xp_needed=" + xpNeeded + "&level=" + level + "&rank=" + rank
+ "&username=" + URLEncoder.encode(username, StandardCharsets.UTF_8.toString())
+ "&bar_colour=" + URLEncoder.encode(barColour, StandardCharsets.UTF_8.toString())
Expand Down Expand Up @@ -91,6 +91,43 @@ private ServerExperienceConfig getServerExperienceConfig(long serverID) {
}
}

public List<Experience> getServerLeaderboard(long serverID) {
try(Session session = sessionFactory.openSession())
{
@SuppressWarnings("unchecked")
List<Experience> leaderboard = session.createQuery("FROM Experience WHERE serverID = :serverID ORDER BY totalExperience DESC")
.setParameter("serverID", serverID)
.list();
return leaderboard;
}
}

public List<Experience> getServerLeaderboardChunk(long serverID, int limit, int offset) {
try(Session session = sessionFactory.openSession())
{
@SuppressWarnings("unchecked")
List<Experience> leaderboard = session.createQuery("FROM Experience WHERE serverID = :serverID ORDER BY totalExperience DESC")
.setParameter("serverID", serverID)
.setMaxResults(limit)
.setFirstResult(offset)
.list();
return leaderboard;
}
}

public int getUserLeaderboardPosition(long serverID, String userID) {
List<Experience> leaderboard = getServerLeaderboard(serverID);
int position = 0;
boolean found = false;

while (!found & leaderboard.iterator().hasNext()) {
position++;
if (leaderboard.iterator().next().getUserID().equals(userID)) found = true;
}

return position;
}

private List<LevelUpRole> getRolesForLevelFromServer(long id, long level) {
try(Session session = sessionFactory.openSession())
{
Expand Down Expand Up @@ -166,7 +203,7 @@ public void removeLevelUpRole(long level, long serverID) {
}

public long xpNeededForLevel(long level) {
return 5 * (level ^ 2) + (50 * level) + 100;
return (long) Math.ceil(Math.sqrt(5000 * (Math.pow(level, 3))));
}

private long xpToNextLevel(long nextLevel, long currentXP) {
Expand Down

0 comments on commit ba81384

Please sign in to comment.