Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RankSystemListener #17

Merged
merged 6 commits into from
Oct 10, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/java/tech/ypsilon/bbbot/discord/CommandManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,15 @@ public CommandManager(){
//registerFunction(new NotifySelectRoleCommand());
registerFunction(new CensorshipCommand());
registerFunction(new DudenCommand());
registerEventListener(new RankSystemCommand());

registerEventListener(new DefaultListener());
registerEventListener(new CommandListener());
registerEventListener(new RoleListener());
registerEventListener(new ChannelListener());
registerEventListener(new NewMemberJoinListener());
registerEventListener(new CensorWatcherListener());
registerEventListener(new RankSystemListener());
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package tech.ypsilon.bbbot.discord.command;

import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import tech.ypsilon.bbbot.discord.listener.RankSystemListener;
import tech.ypsilon.bbbot.util.EmbedUtil;

public class RankSystemCommand extends Command {
@Override
public String[] getAlias() {
return new String[]{"rank"};
}

@Override
public void onExecute(GuildMessageReceivedEvent e, String[] args) {
EmbedBuilder b = EmbedUtil.createSuccessEmbed();
klegul marked this conversation as resolved.
Show resolved Hide resolved
RankSystemListener.RankInformation rank;
if (args.length == 0) {
rank = RankSystemListener.getRankInformation(e.getAuthor());
b.addField("User", e.getAuthor().getName(), true);
} else {
Member mentionedUser = e.getMessage().getMentionedMembers().get(0);
klegul marked this conversation as resolved.
Show resolved Hide resolved
rank = RankSystemListener.getRankInformation(mentionedUser.getUser());
b.addField("User", mentionedUser.getUser().getName(), true);
}
b.addField("Level", rank.getPoints() + "", true);
b.addField("Aktuelle Streak", rank.getCurrentStreak() + " Tage", false);
b.addField("Längte Streak", rank.getBestStreak() + " Tage", false);
e.getChannel().sendMessage(b.build()).queue();
}

@Override
public String getDescription() {
return "Sehe Details zu deinem Rang, oder dem Rang von anderen: 'kit rank (@User)'";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package tech.ypsilon.bbbot.discord.listener;

import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Updates;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
import org.jetbrains.annotations.NotNull;
import tech.ypsilon.bbbot.database.MongoController;
import tech.ypsilon.bbbot.discord.DiscordController;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class RankSystemListener extends ListenerAdapter {

//Local cache for speed
private HashMap<Long, Long> lastMessage = new HashMap<>();

/**
* Get the corresponding Collection
* @return the collection
*/
private static MongoCollection<Document> getCollection() {
return MongoController.getInstance().getCollection("UserActivity");
}

/**
* Returns milliseconds for a given amount of days
* @param days the amount of days
* @return the millis they take
*/
private Long getMillisForDays(int days) {
return TimeUnit.DAYS.toMillis(days);
}

/**
* Method to calculate points to add
* @param streak the currentStreak
* @return the points to add
*/
private int calculatePoints(int streak) {
return Math.min(streak, 5);
}

/**
* Execute the event
* @param event
*/
@Override
public void onGuildMessageReceived(@NotNull GuildMessageReceivedEvent event) {
if(event.getGuild().getIdLong() != 756547960229199902L) return; //Skip if not Kit Guild

if(lastMessage.getOrDefault(event.getAuthor().getIdLong(), 0L) + getMillisForDays(1) > System.currentTimeMillis())
return; //Skip if cache hits the user last message
Bson filer = Filters.eq("userId", event.getAuthor().getIdLong());
Document user = getCollection().find(filer).first();
boolean newCreate = false;
if(user == null) {
user = new Document("_id", new ObjectId());
user.put("userId", event.getAuthor().getIdLong());
user.put("lastMessage", new Date());
user.put("points", 0);
user.put("currentStreak", 0);
user.put("bestStreak", 1);
getCollection().insertOne(user);
newCreate = true;
}
Date lastMsgUser = user.getDate("lastMessage");
if(lastMsgUser.getTime()+getMillisForDays(1) > System.currentTimeMillis()) { //Skip if database hits the user last message
lastMessage.put(event.getAuthor().getIdLong(), lastMsgUser.getTime()); //Refreshed the local cache if cache didnt hit but database does
return;
}

Integer bestStreak = user.getInteger("bestStreak");
Integer currentStreak = user.getInteger("currentStreak");

List<Bson> updates = new ArrayList<>();
if(lastMsgUser.getTime()+getMillisForDays(2) < System.currentTimeMillis() && !newCreate) { //Lost Streak; No message for more than 48h
if(currentStreak > bestStreak) { //CurrentStreak higher than bestStreak
updates.add(Updates.set("bestStreak", (currentStreak))); //Set bestStreak = currentStreak
bestStreak = currentStreak;
}
updates.add(Updates.set("currentStreak", 1));
currentStreak = 1;
} else {
updates.add(Updates.inc("currentStreak", 1)); //increase currentStreak
}
updates.add(Updates.inc("points", calculatePoints(currentStreak)));
lastMessage.put(event.getAuthor().getIdLong(), System.currentTimeMillis());

getCollection().updateOne(filer, updates);
}

/**
* Get information from User
* @param user the {@link User}
* @return the RankInformation
*/
public static RankInformation getRankInformation(User user) {
return new RankInformation(user.getIdLong());
}

/**
* Databucket of RankInformation
*/
public static class RankInformation {

private ObjectId _id;
private Long userId;
private int points = 0;
private int currentStreak = 0;
private int bestStreak = 0;
private Date lastMessage;

private RankInformation(Long userId) {
Document document = getCollection().find(Filters.eq("userId", userId)).first();
this.userId = userId;
if(document != null) {
_id = document.getObjectId("_id");
this.points = document.getInteger("points");
this.currentStreak = document.getInteger("currentStreak");
this.bestStreak = document.getInteger("bestStreak");
this.lastMessage = document.getDate("lastMessage");
if(this.currentStreak > this.bestStreak)
this.bestStreak = this.currentStreak;
}
}

public ObjectId getID() {
return _id;
}

public Long getUserId() {
return userId;
}

public User getUser() {
return DiscordController.getJDA().getUserById(this.userId);
}

public int getPoints() {
return points;
}

public int getCurrentStreak() {
return currentStreak;
}

public int getBestStreak() {
return bestStreak;
}

public Date getLastMessage() {
return lastMessage;
}
}

}