added command to sync roles for the whole server

added command to remove a role from the experience roles
added leaderboard command
added rank command
fixed missfire configuration for cron jobs (they should not be executed)
added ability to configure recovery for jobs
added tracking of message count
added join listener to automatically give the appropriate role for a joined user
added parameter to join listener containing the userInAServer
re-added command exception templates
added method to create a status message (basically only a single message is returned and expected)
added method to edit a single message in a channel to channel service
fixed cases in which there are no embeds, but we still used the embed principle of sending messages (only text was send)
added more functions to channel service to send messages with
moved joined listeners to their separate transaction
This commit is contained in:
Sheldan
2020-04-12 19:35:42 +02:00
parent 6a31dfde8a
commit edb270e887
53 changed files with 828 additions and 25 deletions

View File

@@ -0,0 +1,83 @@
package dev.sheldan.abstracto.experience.commands;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.experience.config.ExperienceFeatures;
import dev.sheldan.abstracto.experience.converter.LeaderBoardModelConverter;
import dev.sheldan.abstracto.experience.models.LeaderBoard;
import dev.sheldan.abstracto.experience.models.LeaderBoardEntry;
import dev.sheldan.abstracto.experience.models.templates.LeaderBoardModel;
import dev.sheldan.abstracto.experience.service.ExperienceTrackerService;
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
import dev.sheldan.abstracto.templating.model.MessageToSend;
import dev.sheldan.abstracto.templating.service.TemplateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
@Slf4j
public class LeaderBoardCommand extends AbstractConditionableCommand {
public static final String LEADERBOARD_POST_EMBED_TEMPLATE = "leaderboard_post";
@Autowired
private ExperienceTrackerService experienceTrackerService;
@Autowired
private UserExperienceManagementService userExperienceManagementService;
@Autowired
private TemplateService templateService;
@Autowired
private ChannelService channelService;
@Autowired
private LeaderBoardModelConverter converter;
@Override
public CommandResult execute(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
Integer page = parameters.size() > 0 ? (Integer) parameters.get(0) : 0;
LeaderBoard leaderBoard = experienceTrackerService.findLeaderBoardData(commandContext.getUserInitiatedContext().getServer(), page);
LeaderBoardModel leaderBoardModel = (LeaderBoardModel) ContextConverter.fromCommandContext(commandContext, LeaderBoardModel.class);
leaderBoardModel.setUserExperiences(converter.fromLeaderBoard(leaderBoard));
LeaderBoardEntry userRank = experienceTrackerService.getRankOfUserInServer(commandContext.getUserInitiatedContext().getAUserInAServer());
leaderBoardModel.setUserExecuting(converter.fromLeaderBoardEntry(userRank));
MessageToSend messageToSend = templateService.renderEmbedTemplate(LEADERBOARD_POST_EMBED_TEMPLATE, leaderBoardModel);
channelService.sendMessageToEndInTextChannel(messageToSend, commandContext.getChannel());
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("page").optional(true).type(Integer.class).build());
HelpInfo helpInfo = HelpInfo.builder().longHelp("Shows the leaderboard, first 10 places or given page.").usage("leaderboard").build();
return CommandConfiguration.builder()
.name("leaderboard")
.module(ExperienceModule.EXPERIENCE)
.description("Shows the leaderboard, first 10 places or given page.")
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public String getFeature() {
return ExperienceFeatures.EXPERIENCE;
}
}

View File

@@ -0,0 +1,71 @@
package dev.sheldan.abstracto.experience.commands;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
import dev.sheldan.abstracto.experience.config.ExperienceFeatures;
import dev.sheldan.abstracto.experience.converter.LeaderBoardModelConverter;
import dev.sheldan.abstracto.experience.models.LeaderBoardEntry;
import dev.sheldan.abstracto.experience.models.database.AUserExperience;
import dev.sheldan.abstracto.experience.models.templates.RankModel;
import dev.sheldan.abstracto.experience.service.ExperienceLevelService;
import dev.sheldan.abstracto.experience.service.ExperienceTrackerService;
import dev.sheldan.abstracto.templating.model.MessageToSend;
import dev.sheldan.abstracto.templating.service.TemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class Rank extends AbstractConditionableCommand {
@Autowired
private LeaderBoardModelConverter converter;
@Autowired
private TemplateService templateService;
@Autowired
private ExperienceTrackerService experienceTrackerService;
@Autowired
private ExperienceLevelService experienceLevelService;
@Override
public CommandResult execute(CommandContext commandContext) {
RankModel rankModel = (RankModel) ContextConverter.fromCommandContext(commandContext, RankModel.class);
LeaderBoardEntry userRank = experienceTrackerService.getRankOfUserInServer(commandContext.getUserInitiatedContext().getAUserInAServer());
rankModel.setRankUser(converter.fromLeaderBoardEntry(userRank));
AUserExperience experienceObj = userRank.getExperience();
rankModel.setExperienceToNextLevel(experienceLevelService.calculateExperienceToNextLevel(experienceObj.getCurrentLevel().getLevel(), experienceObj.getExperience()));
MessageToSend messageToSend = templateService.renderEmbedTemplate("rank_post", rankModel);
channelService.sendMessageToEndInTextChannel(messageToSend, commandContext.getChannel());
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
HelpInfo helpInfo = HelpInfo.builder().longHelp("Shows the leaderboard, first 10 places or given page.").usage("rank").build();
return CommandConfiguration.builder()
.name("rank")
.module(ExperienceModule.EXPERIENCE)
.description("Shows your experience, rank and level on this server.")
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public String getFeature() {
return ExperienceFeatures.EXPERIENCE;
}
}

View File

@@ -0,0 +1,47 @@
package dev.sheldan.abstracto.experience.commands;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.experience.config.ExperienceFeatures;
import dev.sheldan.abstracto.experience.service.ExperienceTrackerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class SyncRoles extends AbstractConditionableCommand {
@Autowired
private ExperienceTrackerService experienceTrackerService;
@Override
public CommandResult execute(CommandContext commandContext) {
experienceTrackerService.syncUserRolesWithFeedback(commandContext.getUserInitiatedContext().getServer(), commandContext.getUserInitiatedContext().getChannel());
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
HelpInfo helpInfo = HelpInfo.builder().longHelp("Syncs the role of the current known users with their respective xp.").usage("syncExpRoles").build();
return CommandConfiguration.builder()
.name("syncExpRoles")
.module(ExperienceModule.EXPERIENCE)
.description("Syncs the roles of the users with their respective experience.")
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public String getFeature() {
return ExperienceFeatures.EXPERIENCE;
}
}

View File

@@ -0,0 +1,56 @@
package dev.sheldan.abstracto.experience.commands;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
import dev.sheldan.abstracto.experience.config.ExperienceFeatures;
import dev.sheldan.abstracto.experience.service.ExperienceRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class UnSetRole extends AbstractConditionableCommand {
@Autowired
private RoleManagementService roleManagementService;
@Autowired
private ExperienceRoleService experienceRoleService;
@Override
public CommandResult execute(CommandContext commandContext) {
Long roleId = (Long) commandContext.getParameters().getParameters().get(0);
ARole role = roleManagementService.findRole(roleId);
experienceRoleService.unsetRole(role, commandContext.getUserInitiatedContext().getServer());
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("roleId").type(Long.class).build());
HelpInfo helpInfo = HelpInfo.builder().longHelp("Removes the role from the experience tracking").usage("unsetRole <roleId>").build();
return CommandConfiguration.builder()
.name("unsetRole")
.module(ExperienceModule.EXPERIENCE)
.description("Removes the role from experience tracking")
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public String getFeature() {
return ExperienceFeatures.EXPERIENCE;
}
}

View File

@@ -0,0 +1,40 @@
package dev.sheldan.abstracto.experience.converter;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.experience.models.LeaderBoard;
import dev.sheldan.abstracto.experience.models.LeaderBoardEntry;
import dev.sheldan.abstracto.experience.models.templates.LeaderBoardEntryModel;
import net.dv8tion.jda.api.entities.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class LeaderBoardModelConverter {
@Autowired
private BotService botService;
public List<LeaderBoardEntryModel> fromLeaderBoard(LeaderBoard leaderBoard) {
List<LeaderBoardEntryModel> models = new ArrayList<>();
leaderBoard.getEntries().forEach(leaderBoardEntry -> {
LeaderBoardEntryModel entry = fromLeaderBoardEntry(leaderBoardEntry);
models.add(entry);
});
return models;
}
public LeaderBoardEntryModel fromLeaderBoardEntry(LeaderBoardEntry leaderBoardEntry) {
AUserInAServer entryUser = leaderBoardEntry.getExperience().getUser();
Member entryMember = botService.getMemberInServer(entryUser.getServerReference().getId(), entryUser.getUserReference().getId());
return LeaderBoardEntryModel
.builder()
.experience(leaderBoardEntry.getExperience())
.member(entryMember).rank(leaderBoardEntry.getRank())
.rank(leaderBoardEntry.getRank())
.build();
}
}

View File

@@ -28,7 +28,7 @@ public class ExperiencePersistingJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
HashMap<Long, List<AServer>> runtimeExperience = experienceTrackerService.getRuntimeExperience();
log.info("Storing experience");
log.info("Persisting experience");
Long pastMinute = (Instant.now().getEpochSecond() / 60) - 1;
if(runtimeExperience.containsKey(pastMinute)) {
experienceTrackerService.handleExperienceGain(runtimeExperience.get(pastMinute));

View File

@@ -0,0 +1,39 @@
package dev.sheldan.abstracto.experience.listener;
import dev.sheldan.abstracto.core.listener.JoinListener;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.UserManagementService;
import dev.sheldan.abstracto.experience.config.ExperienceFeatures;
import dev.sheldan.abstracto.experience.models.database.AUserExperience;
import dev.sheldan.abstracto.experience.service.ExperienceTrackerService;
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class JoiningUserRoleListener implements JoinListener {
@Autowired
private UserExperienceManagementService userExperienceManagementService;
@Autowired
private UserManagementService userManagementService;
@Autowired
private ExperienceTrackerService experienceTrackerService;
@Override
public void execute(Member member, Guild guild, AUserInAServer aUserInAServer) {
AUserExperience userExperience = userExperienceManagementService.findUserInServer(aUserInAServer);
if(userExperience != null) {
experienceTrackerService.syncForSingleUser(userExperience);
}
}
@Override
public String getFeature() {
return ExperienceFeatures.EXPERIENCE;
}
}

View File

@@ -1,9 +1,28 @@
package dev.sheldan.abstracto.experience.repository;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.experience.LeaderBoardEntryResult;
import dev.sheldan.abstracto.experience.models.database.AUserExperience;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface UserExperienceRepository extends JpaRepository<AUserExperience, Long> {
List<AUserExperience> findByUser_ServerReference(AServer server);
List<AUserExperience> findTop10ByUser_ServerReferenceOrderByExperienceDesc(AServer server, Pageable pageable);
@Query(value = "WITH user_experience_ranked AS" +
"( " +
" SELECT id, experience, experience_role_id, level_id, message_count, ROW_NUMBER() OVER ( ORDER BY experience DESC ) " +
" FROM user_experience" +
") " +
"SELECT rank.id as \"id\", rank.experience as \"experience\", rank.message_count as \"messageCount\", rank.level_id as \"level\", rank.row_number as \"rank\" " +
"FROM user_experience_ranked rank " +
"where rank.id = :userInServerId", nativeQuery = true)
LeaderBoardEntryResult getRankOfUserInServer(@Param("userInServerId") Long id);
}

View File

@@ -1,5 +1,6 @@
package dev.sheldan.abstracto.experience.service;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import dev.sheldan.abstracto.experience.service.management.ExperienceLevelManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -22,4 +23,10 @@ public class ExperienceLevelServiceBean implements ExperienceLevelService {
return 5L * (level * level) + 50 * level + 100;
}
@Override
public Long calculateExperienceToNextLevel(Integer level, Long currentExperience) {
AExperienceLevel nextLevel = experienceLevelManagementService.getLevel(level + 1);
return nextLevel.getExperienceNeeded() - currentExperience;
}
}

View File

@@ -3,11 +3,15 @@ package dev.sheldan.abstracto.experience.service;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import dev.sheldan.abstracto.experience.models.database.AExperienceRole;
import dev.sheldan.abstracto.experience.service.management.ExperienceLevelManagementService;
import dev.sheldan.abstracto.experience.service.management.ExperienceRoleManagementService;
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class ExperienceRoleServiceBean implements ExperienceRoleService {
@@ -17,6 +21,12 @@ public class ExperienceRoleServiceBean implements ExperienceRoleService {
@Autowired
private ExperienceLevelManagementService experienceLevelService;
@Autowired
private ExperienceTrackerService experienceTrackerService;
@Autowired
private UserExperienceManagementService userExperienceManagementService;
@Override
public void setRoleToLevel(ARole role, Integer level, AServer server) {
AExperienceLevel experienceLevel = experienceLevelService.getLevel(level);
@@ -24,4 +34,17 @@ public class ExperienceRoleServiceBean implements ExperienceRoleService {
experienceRoleManagementService.setLevelToRole(experienceLevel, role, server);
}
@Override
public void unsetRole(ARole role, AServer server) {
AExperienceRole roleInServer = experienceRoleManagementService.getRoleInServer(role, server);
if(roleInServer.getUsers().size() > 0) {
roleInServer.getUsers().forEach(userExperience -> {
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRoleForServer(server);
roles.removeIf(role1 -> role1.getId().equals(roleInServer.getId()));
experienceTrackerService.handleExperienceRoleForUser(userExperience, roles);
});
}
experienceRoleManagementService.unsetRole(roleInServer);
}
}

View File

@@ -1,22 +1,32 @@
package dev.sheldan.abstracto.experience.service;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.ConfigService;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.core.service.RoleService;
import dev.sheldan.abstracto.experience.LeaderBoardEntryResult;
import dev.sheldan.abstracto.experience.models.LeaderBoard;
import dev.sheldan.abstracto.experience.models.LeaderBoardEntry;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import dev.sheldan.abstracto.experience.models.database.AExperienceRole;
import dev.sheldan.abstracto.experience.models.database.AUserExperience;
import dev.sheldan.abstracto.experience.models.templates.UserSyncStatusModel;
import dev.sheldan.abstracto.experience.service.management.ExperienceLevelManagementService;
import dev.sheldan.abstracto.experience.service.management.ExperienceRoleManagementService;
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
import dev.sheldan.abstracto.templating.model.MessageToSend;
import dev.sheldan.abstracto.templating.service.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.ExecutionException;
@Component
@Slf4j
@@ -42,6 +52,12 @@ public class ExperienceTrackerServiceBean implements ExperienceTrackerService {
@Autowired
private RoleService roleService;
@Autowired
private MessageService messageService;
@Autowired
private TemplateService templateService;
@Override
public void addExperience(AUserInAServer userInAServer) {
Long second = Instant.now().getEpochSecond() / 60;
@@ -91,7 +107,7 @@ public class ExperienceTrackerServiceBean implements ExperienceTrackerService {
if(userInAServer.getCurrentLevel().getLevel() >= experienceRole.getLevel().getLevel()) {
lastRole = experienceRole;
} else {
return experienceRole;
return lastRole;
}
}
return lastRole;
@@ -106,14 +122,13 @@ public class ExperienceTrackerServiceBean implements ExperienceTrackerService {
log.info("User {} leveled from {} to {}", userInAServer.getUser().getUserReference().getId(), currentLevel, correctLevel);
userInAServer.setCurrentLevel(experienceLevelManagementService.getLevel(correctLevel));
}
userExperienceManagementService.saveUser(userInAServer);
}
@Transactional
@Override
public void handleExperienceGain(List<AServer> servers) {
servers.forEach(serverExp -> {
log.info("Handling experience for server {}", serverExp.getId());
log.debug("Handling experience for server {}", serverExp.getId());
int minExp = configService.getDoubleValue("minExp", serverExp.getId()).intValue();
int maxExp = configService.getDoubleValue("maxExp", serverExp.getId()).intValue();
Integer multiplier = configService.getDoubleValue("multiplier", serverExp.getId()).intValue();
@@ -124,9 +139,10 @@ public class ExperienceTrackerServiceBean implements ExperienceTrackerService {
serverExp.getUsers().forEach(userInAServer -> {
Integer gainedExperience = iterator.next();
gainedExperience *= multiplier;
log.info("Handling {}. The user gains {}", userInAServer.getUserReference().getId(), gainedExperience);
log.debug("Handling {}. The user gains {}", userInAServer.getUserReference().getId(), gainedExperience);
AUserExperience userExperience = userExperienceManagementService.findUserInServer(userInAServer);
increaseExpForUser(userExperience, gainedExperience.longValue(), levels);
userExperience.setMessageCount(userExperience.getMessageCount() + 1);
handleExperienceRoleForUser(userExperience, roles);
});
});
@@ -135,11 +151,14 @@ public class ExperienceTrackerServiceBean implements ExperienceTrackerService {
@Override
public void handleExperienceRoleForUser(AUserExperience userExperience, List<AExperienceRole> roles) {
AExperienceRole role = calculateRole(userExperience, roles);
boolean currentlyHasNoExperienceRole = userExperience.getCurrentExperienceRole() == null;
if(role == null) {
if(!currentlyHasNoExperienceRole){
roleService.removeRoleFromUser(userExperience.getUser(), userExperience.getCurrentExperienceRole().getRole());
}
return;
}
boolean currentlyHasNoExperienceRole = userExperience.getCurrentExperienceRole() == null;
if(currentlyHasNoExperienceRole || !role.getRole().getId().equals(userExperience.getCurrentExperienceRole().getId())) {
if(currentlyHasNoExperienceRole || !role.getRole().getId().equals(userExperience.getCurrentExperienceRole().getRole().getId())) {
log.info("User {} gets a new role {}", userExperience.getUser().getUserReference().getId(), role.getRole().getId());
if(!currentlyHasNoExperienceRole) {
roleService.removeRoleFromUser(userExperience.getUser(), userExperience.getCurrentExperienceRole().getRole());
@@ -149,4 +168,78 @@ public class ExperienceTrackerServiceBean implements ExperienceTrackerService {
}
}
@Override
public void syncUserRoles(AServer server) {
List<AUserExperience> aUserExperiences = userExperienceManagementService.loadAllUsers(server);
log.info("Found {} users to synchronize", aUserExperiences.size());
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRoleForServer(server);
for (int i = 0; i < aUserExperiences.size(); i++) {
AUserExperience userExperience = aUserExperiences.get(i);
log.debug("Synchronizing {} out of {}", i, aUserExperiences.size());
handleExperienceRoleForUser(userExperience, roles);
}
}
@Override
public void syncUserRolesWithFeedback(AServer server, AChannel channel) {
List<AUserExperience> aUserExperiences = userExperienceManagementService.loadAllUsers(server);
log.info("Found {} users to synchronize", aUserExperiences.size());
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRoleForServer(server);
UserSyncStatusModel statusModel = UserSyncStatusModel.builder().currentCount(0).totalUserCount(aUserExperiences.size()).build();
MessageToSend status = templateService.renderEmbedTemplate("status_message", statusModel);
try {
Message statusMessage = messageService.createStatusMessage(status, channel).get();
for (int i = 0; i < aUserExperiences.size(); i++) {
if((i % 100) == 1) {
UserSyncStatusModel incrementalStatusModel = UserSyncStatusModel.builder().currentCount(i).totalUserCount(aUserExperiences.size()).build();
status = templateService.renderEmbedTemplate("status_message", incrementalStatusModel);
messageService.updateStatusMessage(channel, statusMessage.getIdLong(), status);
}
log.debug("Synchronizing {} out of {}", i, aUserExperiences.size());
AUserExperience userExperience = aUserExperiences.get(i);
handleExperienceRoleForUser(userExperience, roles);
}
UserSyncStatusModel incrementalStatusModel = UserSyncStatusModel.builder().currentCount(aUserExperiences.size()).totalUserCount(aUserExperiences.size()).build();
status = templateService.renderEmbedTemplate("status_message", incrementalStatusModel);
messageService.updateStatusMessage(channel, statusMessage.getIdLong(), status);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
@Override
public void syncForSingleUser(AUserExperience userExperience) {
log.info("Synchronizing for user {}", userExperience.getUser().getUserReference().getId());
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRoleForServer(userExperience.getUser().getServerReference());
handleExperienceRoleForUser(userExperience, roles);
}
@Override
public LeaderBoard findLeaderBoardData(AServer server, Integer page) {
List<AUserExperience> experiences = userExperienceManagementService.findLeaderboardUsersPaginated(server, page * 10, (page +1) * 10);
log.info("We found {}", experiences.size());
List<LeaderBoardEntry> entries = new ArrayList<>();
for (int i = 0; i < experiences.size(); i++) {
AUserExperience userExperience = experiences.get(i);
entries.add(LeaderBoardEntry.builder().experience(userExperience).rank(i + 1).build());
}
return LeaderBoard.builder().entries(entries).build();
}
@Override
public LeaderBoardEntry getRankOfUserInServer(AUserInAServer userInAServer) {
AUserExperience experience = userExperienceManagementService.findUserInServer(userInAServer);
LeaderBoardEntryResult rankOfUserInServer = userExperienceManagementService.getRankOfUserInServer(experience);
AUserExperience aUserExperience = AUserExperience
.builder()
.experience(rankOfUserInServer.getExperience())
.user(userInAServer)
.messageCount(rankOfUserInServer.getMessageCount())
.id(userInAServer.getUserInServerId())
.currentLevel(experienceLevelManagementService.getLevel(rankOfUserInServer.getLevel()))
.build();
return LeaderBoardEntry.builder().experience(aUserExperience).rank(rankOfUserInServer.getRank()).build();
}
}

View File

@@ -24,6 +24,16 @@ public class ExperienceRoleManagementServiceBean implements ExperienceRoleManage
});
}
@Override
public void unsetRole(AExperienceRole role) {
experienceRoleRepository.delete(role);
}
@Override
public AExperienceRole getRoleInServer(ARole role, AServer server) {
return experienceRoleRepository.findByRoleServerAndRole(server, role);
}
@Override
public List<AExperienceRole> getExperienceRoleForServer(AServer server) {
return experienceRoleRepository.findByRoleServer(server);

View File

@@ -1,12 +1,16 @@
package dev.sheldan.abstracto.experience.service.management;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.experience.LeaderBoardEntryResult;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import dev.sheldan.abstracto.experience.models.database.AUserExperience;
import dev.sheldan.abstracto.experience.repository.UserExperienceRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
@@ -37,6 +41,7 @@ public class UserExperienceManagementServiceBean implements UserExperienceManage
AUserExperience userExperience = AUserExperience
.builder()
.experience(0L)
.messageCount(0L)
.user(aUserInAServer)
.id(aUserInAServer.getUserInServerId())
.currentLevel(startingLevel)
@@ -49,6 +54,21 @@ public class UserExperienceManagementServiceBean implements UserExperienceManage
public void saveUser(AUserExperience userExperience) {
repository.save(userExperience);
}
@Override
public List<AUserExperience> loadAllUsers(AServer server) {
return repository.findByUser_ServerReference(server);
}
@Override
public List<AUserExperience> findLeaderboardUsersPaginated(AServer aServer, Integer start, Integer end) {
return repository.findTop10ByUser_ServerReferenceOrderByExperienceDesc(aServer, PageRequest.of(start, end));
}
@Override
public LeaderBoardEntryResult getRankOfUserInServer(AUserExperience userExperience) {
return repository.getRankOfUserInServer(userExperience.getId());
}
}

View File

@@ -4,6 +4,8 @@ abstracto.scheduling.jobs.experienceJob.clazz=dev.sheldan.abstracto.experience.j
abstracto.scheduling.jobs.experienceJob.standAlone=true
abstracto.scheduling.jobs.experienceJob.active=true
abstracto.scheduling.jobs.experienceJob.cronExpression=30 * * * * ?
abstracto.scheduling.jobs.experienceJob.recovery=false
abstracto.features.experience=true

View File

@@ -0,0 +1,21 @@
{
<#macro userDisplay user>
${user.rank} ${user.member.effectiveName} ${user.experience.experience} ${user.experience.currentLevel.level} ${user.experience.messageCount}
</#macro>
"author": {
"name": "${member.effectiveName}",
"avatar": "${member.user.effectiveAvatarUrl}"
},
"color" : {
"r": 200,
"g": 0,
"b": 255
},
"description": "
Rank | Name | Experience | Level | Messages
<#list userExperiences as user>
<@userDisplay user=user />
</#list>
<@userDisplay user=userExecuting />
"
}

View File

@@ -0,0 +1,38 @@
{
"author": {
"name": "${member.effectiveName}",
"avatar": "${member.user.effectiveAvatarUrl}"
},
"color" : {
"r": 200,
"g": 0,
"b": 255
},
"fields": [
{
"name": "XP",
"value": "${rankUser.experience.experience}",
"inline": "true"
},
{
"name": "Level",
"value": "${rankUser.experience.currentLevel.level}",
"inline": "true"
},
{
"name": "Messages",
"value": "${rankUser.experience.messageCount}",
"inline": "true"
},
{
"name": "XP to next Level",
"value": "${experienceToNextLevel}",
"inline": "true"
},
{
"name": "Rank",
"value": "${rankUser.rank}",
"inline": "true"
}
]
}

View File

@@ -0,0 +1,3 @@
{
"additionalMessage": "Updating users: ${currentCount}/${totalUserCount}."
}