mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-07 01:30:49 +00:00
added javadoc to experience tracking module
changed persistence configuration for entities, so cascade is more correct changed the way channels get their server assigned added feature to only change the exp role of a user, if he doesn't already have the new target role added the name of the needed feature, to the message indicating that a feature has been disabled updated unsetExpRole to have a status update message, because there might be a lot of users which need a role update
This commit is contained in:
@@ -20,6 +20,7 @@ import java.util.List;
|
||||
public class ExpScale extends AbstractConditionableCommand {
|
||||
|
||||
public static final String EXP_MULTIPLIER_KEY = "expMultiplier";
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ 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.AUserExperienceService;
|
||||
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
|
||||
import dev.sheldan.abstracto.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
@@ -30,7 +30,7 @@ public class LeaderBoardCommand extends AbstractConditionableCommand {
|
||||
|
||||
public static final String LEADERBOARD_POST_EMBED_TEMPLATE = "leaderboard_post";
|
||||
@Autowired
|
||||
private ExperienceTrackerService experienceTrackerService;
|
||||
private AUserExperienceService userExperienceService;
|
||||
|
||||
@Autowired
|
||||
private UserExperienceManagementService userExperienceManagementService;
|
||||
@@ -48,12 +48,13 @@ public class LeaderBoardCommand extends AbstractConditionableCommand {
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
// parameter is optional, in case its not present, we default to the 0th page
|
||||
Integer page = parameters.size() > 0 ? (Integer) parameters.get(0) : 0;
|
||||
LeaderBoard leaderBoard = experienceTrackerService.findLeaderBoardData(commandContext.getUserInitiatedContext().getServer(), page);
|
||||
LeaderBoard leaderBoard = userExperienceService.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());
|
||||
LeaderBoardEntry userRank = userExperienceService.getRankOfUserInServer(commandContext.getUserInitiatedContext().getAUserInAServer());
|
||||
leaderBoardModel.setUserExecuting(converter.fromLeaderBoardEntry(userRank));
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(LEADERBOARD_POST_EMBED_TEMPLATE, leaderBoardModel);
|
||||
channelService.sendMessageToEndInTextChannel(messageToSend, commandContext.getChannel());
|
||||
|
||||
@@ -13,7 +13,7 @@ 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.experience.service.AUserExperienceService;
|
||||
import dev.sheldan.abstracto.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -25,6 +25,7 @@ import java.util.List;
|
||||
@Component
|
||||
public class Rank extends AbstractConditionableCommand {
|
||||
|
||||
public static final String RANK_POST_EMBED_TEMPLATE = "rank_post";
|
||||
@Autowired
|
||||
private LeaderBoardModelConverter converter;
|
||||
|
||||
@@ -32,7 +33,7 @@ public class Rank extends AbstractConditionableCommand {
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ExperienceTrackerService experienceTrackerService;
|
||||
private AUserExperienceService userExperienceService;
|
||||
|
||||
@Autowired
|
||||
private ExperienceLevelService experienceLevelService;
|
||||
@@ -40,11 +41,11 @@ public class Rank extends AbstractConditionableCommand {
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
RankModel rankModel = (RankModel) ContextConverter.fromCommandContext(commandContext, RankModel.class);
|
||||
LeaderBoardEntry userRank = experienceTrackerService.getRankOfUserInServer(commandContext.getUserInitiatedContext().getAUserInAServer());
|
||||
LeaderBoardEntry userRank = userExperienceService.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);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(RANK_POST_EMBED_TEMPLATE, rankModel);
|
||||
channelService.sendMessageToEndInTextChannel(messageToSend, commandContext.getChannel());
|
||||
|
||||
return CommandResult.fromSuccess();
|
||||
|
||||
@@ -41,11 +41,11 @@ public class SetExpRole extends AbstractConditionableCommand {
|
||||
Long roleId = (Long) commandContext.getParameters().getParameters().get(1);
|
||||
ARole role = roleManagementService.findRole(roleId);
|
||||
AServer server = commandContext.getUserInitiatedContext().getServer();
|
||||
if(!roleService.isRoleInServer(server, role)) {
|
||||
if(!roleService.isRoleInServer(role)) {
|
||||
throw new RoleException("Role not found.");
|
||||
}
|
||||
log.info("Setting role {} to be used for level {} on server {}", roleId, level, server.getId());
|
||||
experienceRoleService.setRoleToLevel(role, level, server);
|
||||
experienceRoleService.setRoleToLevel(role, level, server, commandContext.getUserInitiatedContext().getChannel());
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.experience.config.ExperienceFeatures;
|
||||
import dev.sheldan.abstracto.experience.service.ExperienceTrackerService;
|
||||
import dev.sheldan.abstracto.experience.service.AUserExperienceService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -21,13 +21,13 @@ import java.util.List;
|
||||
public class SyncRoles extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private ExperienceTrackerService experienceTrackerService;
|
||||
private AUserExperienceService userExperienceService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
AServer server = commandContext.getUserInitiatedContext().getServer();
|
||||
log.info("Synchronizing roles on server {}", server.getId());
|
||||
experienceTrackerService.syncUserRolesWithFeedback(server, commandContext.getUserInitiatedContext().getChannel());
|
||||
userExperienceService.syncUserRolesWithFeedback(server, commandContext.getUserInitiatedContext().getChannel());
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,9 @@ public class UnSetExpRole extends AbstractConditionableCommand {
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
Long roleId = (Long) commandContext.getParameters().getParameters().get(0);
|
||||
ARole role = roleManagementService.findRole(roleId);
|
||||
experienceRoleService.unsetRole(role, commandContext.getUserInitiatedContext().getServer());
|
||||
// do not check for the existence of the role, because if the role was deleted, users should be able
|
||||
// to get rid of it in the configuration
|
||||
experienceRoleService.unsetRole(role, commandContext.getUserInitiatedContext().getServer(), commandContext.getUserInitiatedContext().getChannel());
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,23 @@ import org.springframework.stereotype.Component;
|
||||
@Setter
|
||||
@ConfigurationProperties(prefix = "abstracto.experience")
|
||||
public class ExperienceConfig {
|
||||
/**
|
||||
* The default min experience range from the properties file. This is used, when the bot joins a new guild.
|
||||
*/
|
||||
private Integer minExp;
|
||||
|
||||
/**
|
||||
* The default max experience range from the properties file. This is used, when the bot joins a new guild.
|
||||
*/
|
||||
private Integer maxExp;
|
||||
|
||||
/**
|
||||
* The default multiplier from the properties file. This is used, when the bot joins a new guild.
|
||||
*/
|
||||
private Integer expMultiplier;
|
||||
|
||||
/**
|
||||
* The defaul maxLevel from the properties file. This configuration applies globally, as the amount of levels does not depend on the server.
|
||||
*/
|
||||
private Integer maxLvl;
|
||||
}
|
||||
@@ -7,6 +7,9 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Listener responsible to configure the required experience configurations in case the bot joins a new server.
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ExperienceConfigListener implements ServerConfigListener {
|
||||
|
||||
@@ -7,6 +7,10 @@ import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Component responsible to create the amount of {@link dev.sheldan.abstracto.experience.models.database.AExperienceLevel}
|
||||
* configured in the {@link ExperienceConfig}. This is executed when the application starts up.
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ExperienceLevelLoader {
|
||||
@@ -20,12 +24,7 @@ public class ExperienceLevelLoader {
|
||||
@EventListener
|
||||
public void handleContextRefreshEvent(ContextRefreshedEvent ctxStartEvt) {
|
||||
Integer maxLevel = experienceConfig.getMaxLvl();
|
||||
Long experience = 0L;
|
||||
log.info("Setting up experience level configuration.");
|
||||
experienceLevelService.createExperienceLevel(0, 0L);
|
||||
for (int i = 1; i < maxLevel; i++) {
|
||||
experience = experience + experienceLevelService.calculateExperienceForLevel(i - 1);
|
||||
experienceLevelService.createExperienceLevel(i, experience);
|
||||
}
|
||||
experienceLevelService.createLevelsUntil(maxLevel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,22 @@ import org.springframework.stereotype.Component;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Converter used to conver from {@link LeaderBoard} to a list of {@link LeaderBoardEntryModel}
|
||||
*/
|
||||
@Component
|
||||
public class LeaderBoardModelConverter {
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
/**
|
||||
* Converts the complete {@link LeaderBoard} into a list of {@link LeaderBoardEntryModel} which contain additional
|
||||
* information available for rendering the leaderboard ({@link Member} reference)
|
||||
* @param leaderBoard The {@link LeaderBoard} object to be converted
|
||||
* @return The list of {@link LeaderBoardEntryModel} which contain the fully fledged information provided to the
|
||||
* leaderboard template
|
||||
*/
|
||||
public List<LeaderBoardEntryModel> fromLeaderBoard(LeaderBoard leaderBoard) {
|
||||
List<LeaderBoardEntryModel> models = new ArrayList<>();
|
||||
leaderBoard.getEntries().forEach(leaderBoardEntry -> {
|
||||
@@ -27,6 +37,13 @@ public class LeaderBoardModelConverter {
|
||||
return models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given {@link LeaderBoardEntry} to a {@link LeaderBoardEntryModel}, which provides a reference to the
|
||||
* {@link Member} object of the given {@link AUserInAServer} for convenience in the template
|
||||
* @param leaderBoardEntry The {@link LeaderBoardEntry} to be converted
|
||||
* @return The {@link LeaderBoardEntryModel} accompanied with the {@link Member} reference, might be null, if the
|
||||
* user left the guild
|
||||
*/
|
||||
public LeaderBoardEntryModel fromLeaderBoardEntry(LeaderBoardEntry leaderBoardEntry) {
|
||||
AUserInAServer entryUser = leaderBoardEntry.getExperience().getUser();
|
||||
Member entryMember = botService.getMemberInServer(entryUser.getServerReference().getId(), entryUser.getUserReference().getId());
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package dev.sheldan.abstracto.experience.job;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.experience.service.ExperienceTrackerService;
|
||||
import dev.sheldan.abstracto.experience.service.AUserExperienceService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.DisallowConcurrentExecution;
|
||||
import org.quartz.JobExecutionContext;
|
||||
@@ -16,6 +16,11 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* This {@link QuartzJobBean} is executed regularly and calls the the {@link AUserExperienceService}
|
||||
* store the tracked experience from runtime. This job also cleans up the already processed entries in the runtime
|
||||
* experience.
|
||||
*/
|
||||
@Slf4j
|
||||
@DisallowConcurrentExecution
|
||||
@Component
|
||||
@@ -23,16 +28,16 @@ import java.util.List;
|
||||
public class ExperiencePersistingJob extends QuartzJobBean {
|
||||
|
||||
@Autowired
|
||||
private ExperienceTrackerService experienceTrackerService;
|
||||
private AUserExperienceService userExperienceService;
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
|
||||
HashMap<Long, List<AServer>> runtimeExperience = experienceTrackerService.getRuntimeExperience();
|
||||
HashMap<Long, List<AServer>> runtimeExperience = userExperienceService.getRuntimeExperience();
|
||||
log.info("Running experience persisting job.");
|
||||
Long pastMinute = (Instant.now().getEpochSecond() / 60) - 1;
|
||||
if(runtimeExperience.containsKey(pastMinute)) {
|
||||
log.info("Found experience to persist.");
|
||||
experienceTrackerService.handleExperienceGain(runtimeExperience.get(pastMinute));
|
||||
userExperienceService.handleExperienceGain(runtimeExperience.get(pastMinute));
|
||||
runtimeExperience.remove(pastMinute);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,18 +4,22 @@ import dev.sheldan.abstracto.core.listener.MessageReceivedListener;
|
||||
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.service.ExperienceTrackerService;
|
||||
import dev.sheldan.abstracto.experience.service.AUserExperienceService;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* This {@link MessageReceivedListener} is responsible to execute the {@link AUserExperienceService} in order to track
|
||||
* that a certain user has send a message, and experience should be awarded.
|
||||
*/
|
||||
@Component
|
||||
public class ExperienceTrackerListener implements MessageReceivedListener {
|
||||
|
||||
@Autowired
|
||||
private ExperienceTrackerService experienceTrackerService;
|
||||
private AUserExperienceService userExperienceService;
|
||||
|
||||
@Autowired
|
||||
private UserManagementService userManagementService;
|
||||
@@ -24,7 +28,7 @@ public class ExperienceTrackerListener implements MessageReceivedListener {
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void execute(Message message) {
|
||||
AUserInAServer cause = userManagementService.loadUser(message.getMember());
|
||||
experienceTrackerService.addExperience(cause);
|
||||
userExperienceService.addExperience(cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,7 +5,7 @@ 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.AUserExperienceService;
|
||||
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
@@ -13,6 +13,10 @@ import net.dv8tion.jda.api.entities.Member;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* If a user joins, this {@link JoinListener} retrieves the previously stored {@link AUserExperience} and gives the
|
||||
* {@link Member} the necessary {@link net.dv8tion.jda.api.entities.Role} according to the current configuration
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class JoiningUserRoleListener implements JoinListener {
|
||||
@@ -24,14 +28,14 @@ public class JoiningUserRoleListener implements JoinListener {
|
||||
private UserManagementService userManagementService;
|
||||
|
||||
@Autowired
|
||||
private ExperienceTrackerService experienceTrackerService;
|
||||
private AUserExperienceService userExperienceService;
|
||||
|
||||
@Override
|
||||
public void execute(Member member, Guild guild, AUserInAServer aUserInAServer) {
|
||||
AUserExperience userExperience = userExperienceManagementService.findUserInServer(aUserInAServer);
|
||||
if(userExperience != null) {
|
||||
log.info("User {} joined {} with previous experience. Setting up experience role again (if necessary).", member.getUser().getIdLong(), guild.getIdLong());
|
||||
experienceTrackerService.syncForSingleUser(userExperience);
|
||||
userExperienceService.syncForSingleUser(userExperience);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,9 @@ import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* Repository to manage the access to the table managed by {@link AExperienceLevel}
|
||||
*/
|
||||
@Repository
|
||||
public interface ExperienceLevelRepository extends JpaRepository<AExperienceLevel, Integer> {
|
||||
AExperienceLevel findTopByExperienceNeededGreaterThanOrderByExperienceNeededAsc(Long experience);
|
||||
}
|
||||
|
||||
@@ -9,9 +9,32 @@ import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Repository to manage the access to the table managed by {@link AExperienceRole}
|
||||
*/
|
||||
@Repository
|
||||
public interface ExperienceRoleRepository extends JpaRepository<AExperienceRole, Long> {
|
||||
/**
|
||||
* Finds the {@link AExperienceRole} of the given {@link AServer} and {@link ARole}
|
||||
* @param server The {@link AServer} to retrieve the {@link AExperienceRole} for
|
||||
* @param role The {@link ARole} to filter for
|
||||
* @return The {@link AExperienceRole} found or null if the query did not return any results
|
||||
*/
|
||||
AExperienceRole findByRoleServerAndRole(AServer server, ARole role);
|
||||
|
||||
/**
|
||||
* Finds a list of {@link AExperienceRole} (if there are multiple ones, because of misconfiguration) of the given
|
||||
* {@link AExperienceLevel} and {@link AServer}
|
||||
* @param level The {@link AExperienceLevel} to search for
|
||||
* @param server The {@link AServer} to search for
|
||||
* @return The list of {@link AExperienceRole} found by the given parameters
|
||||
*/
|
||||
List<AExperienceRole> findByLevelAndRoleServer(AExperienceLevel level, AServer server);
|
||||
|
||||
/**
|
||||
* Finds all {@link AExperienceRole} of the given {@link AServer}
|
||||
* @param server The {@link AServer} to load the list of {@link AExperienceRole} for
|
||||
* @return A list of {@link AExperienceRole} configured to be used on the given {@link AServer}
|
||||
*/
|
||||
List<AExperienceRole> findByRoleServer(AServer server);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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.LeaderBoardEntryResult;
|
||||
import dev.sheldan.abstracto.experience.models.database.AUserExperience;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
@@ -11,11 +11,34 @@ import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Repository to manage the access to the table managed by {@link AUserExperience}
|
||||
*/
|
||||
@Repository
|
||||
public interface UserExperienceRepository extends JpaRepository<AUserExperience, Long> {
|
||||
|
||||
/**
|
||||
* Finds all {@link AUserExperience} of the given {@link AServer}
|
||||
* @param server The {@link AServer} to retriev ethe {@link AUserExperience} for
|
||||
* @return A complete list of {@link AUserExperience} of the given {@link AServer}
|
||||
*/
|
||||
List<AUserExperience> findByUser_ServerReference(AServer server);
|
||||
|
||||
/**
|
||||
* Retrieves the {@link AUserExperience} ordered by experience, and applies the {@link Pageable} to only filter out certain pages.
|
||||
* @param server The {@link AServer} to retrieve the {@link AUserExperience} information for
|
||||
* @param pageable A {@link Pageable} object to indicate the pages which should be retrieved, pagesize is 10
|
||||
* @return A list of {@link AUserExperience} of the given {@link AServer} ordered by the experience of the users, paginated by the given
|
||||
* configuration
|
||||
*/
|
||||
List<AUserExperience> findTop10ByUser_ServerReferenceOrderByExperienceDesc(AServer server, Pageable pageable);
|
||||
|
||||
/**
|
||||
* This returns the {@link LeaderBoardEntryResult} object containing the information about the rank of a user in a server.
|
||||
* @param id The {@link dev.sheldan.abstracto.core.models.database.AUserInAServer} id to search for
|
||||
* @return the {@link LeaderBoardEntryResult} of this {@link dev.sheldan.abstracto.core.models.database.AUserInAServer}
|
||||
* containing rank and experience information
|
||||
*/
|
||||
@Query(value = "WITH user_experience_ranked AS" +
|
||||
"( " +
|
||||
" SELECT id, experience, experience_role_id, level_id, message_count, ROW_NUMBER() OVER ( ORDER BY experience DESC ) " +
|
||||
|
||||
@@ -3,10 +3,11 @@ 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.BotService;
|
||||
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.database.LeaderBoardEntryResult;
|
||||
import dev.sheldan.abstracto.experience.models.LeaderBoard;
|
||||
import dev.sheldan.abstracto.experience.models.LeaderBoardEntry;
|
||||
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
|
||||
@@ -19,6 +20,7 @@ import dev.sheldan.abstracto.experience.service.management.UserExperienceManagem
|
||||
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.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -27,10 +29,11 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ExperienceTrackerServiceBean implements ExperienceTrackerService {
|
||||
public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
|
||||
private HashMap<Long, List<AServer>> runtimeExperience = new HashMap<>();
|
||||
|
||||
@@ -40,6 +43,9 @@ public class ExperienceTrackerServiceBean implements ExperienceTrackerService {
|
||||
@Autowired
|
||||
private ExperienceLevelService experienceLevelService;
|
||||
|
||||
@Autowired
|
||||
private ExperienceRoleService experienceRoleService;
|
||||
|
||||
@Autowired
|
||||
private ExperienceLevelManagementService experienceLevelManagementService;
|
||||
|
||||
@@ -58,6 +64,13 @@ public class ExperienceTrackerServiceBean implements ExperienceTrackerService {
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
/**
|
||||
* Creates the user in the runtime experience, if the user was not in yet. Also creates an entry for the minute, if necessary.
|
||||
* @param userInAServer The {@link AUserInAServer} to be added to the list of users gaining experience
|
||||
*/
|
||||
@Override
|
||||
public void addExperience(AUserInAServer userInAServer) {
|
||||
log.trace("Adding experience for user {} in server {}", userInAServer.getUserReference().getId(), userInAServer.getServerReference().getId());
|
||||
@@ -85,11 +98,17 @@ public class ExperienceTrackerServiceBean implements ExperienceTrackerService {
|
||||
return runtimeExperience;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the level of the given {@link AUserExperience} accoring to the given {@link AExperienceLevel} list
|
||||
* @param experience The {@link AUserExperience} to calculate the level for
|
||||
* @param levels The list of {@link AExperienceLevel} representing the level configuration
|
||||
* @return The appropriate level according to the level config
|
||||
*/
|
||||
@Override
|
||||
public Integer calculateLevel(AUserExperience userInAServer, List<AExperienceLevel> levels) {
|
||||
public Integer calculateLevel(AUserExperience experience, List<AExperienceLevel> levels) {
|
||||
AExperienceLevel lastLevel = levels.get(0);
|
||||
for (AExperienceLevel level : levels) {
|
||||
if(level.getExperienceNeeded() >= userInAServer.getExperience()) {
|
||||
if(level.getExperienceNeeded() >= experience.getExperience()) {
|
||||
return lastLevel.getLevel();
|
||||
} else {
|
||||
lastLevel = level;
|
||||
@@ -99,34 +118,26 @@ public class ExperienceTrackerServiceBean implements ExperienceTrackerService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AExperienceRole calculateRole(AUserExperience userInAServer, List<AExperienceRole> roles) {
|
||||
if(roles.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
AExperienceRole lastRole = null;
|
||||
for (AExperienceRole experienceRole : roles) {
|
||||
if(userInAServer.getCurrentLevel().getLevel() >= experienceRole.getLevel().getLevel()) {
|
||||
lastRole = experienceRole;
|
||||
} else {
|
||||
return lastRole;
|
||||
}
|
||||
}
|
||||
return lastRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void increaseExpForUser(AUserExperience userInAServer, Long experience, List<AExperienceLevel> levels) {
|
||||
AUserInAServer user = userInAServer.getUser();
|
||||
log.trace("Increasing experience for user {} in server {} by {}.", user.getUserReference().getId(), user.getServerReference().getId(), experience);
|
||||
userInAServer.setExperience(userInAServer.getExperience() + experience);
|
||||
Integer correctLevel = calculateLevel(userInAServer, levels);
|
||||
Integer currentLevel = userInAServer.getCurrentLevel() != null ? userInAServer.getCurrentLevel().getLevel() : 0;
|
||||
public boolean updateUserlevel(AUserExperience userExperience, List<AExperienceLevel> levels) {
|
||||
AUserInAServer user = userExperience.getUser();
|
||||
Integer correctLevel = calculateLevel(userExperience, levels);
|
||||
Integer currentLevel = userExperience.getCurrentLevel() != null ? userExperience.getCurrentLevel().getLevel() : 0;
|
||||
if(!correctLevel.equals(currentLevel)) {
|
||||
log.info("User {} leveled from {} to {}", user.getUserReference().getId(), currentLevel, correctLevel);
|
||||
userInAServer.setCurrentLevel(experienceLevelManagementService.getLevel(correctLevel));
|
||||
userExperience.setCurrentLevel(experienceLevelManagementService.getLevel(correctLevel));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the actually gained experience for every user in the given servers and adds them to the users.
|
||||
* This method only actually increases the message count, and calls other methods for experience gain
|
||||
* and role change.
|
||||
* Loads the level and role configuration for each server and sorts them for them to be used.
|
||||
* Only actually updates the role, if the user also changed level.
|
||||
* @param servers The list of {@link AServer} containing the user which need to gain experience
|
||||
*/
|
||||
@Transactional
|
||||
@Override
|
||||
public void handleExperienceGain(List<AServer> servers) {
|
||||
@@ -137,93 +148,133 @@ public class ExperienceTrackerServiceBean implements ExperienceTrackerService {
|
||||
Integer multiplier = configService.getDoubleValue("expMultiplier", serverExp.getId()).intValue();
|
||||
PrimitiveIterator.OfInt iterator = new Random().ints(serverExp.getUsers().size(), minExp, maxExp + 1).iterator();
|
||||
List<AExperienceLevel> levels = experienceLevelManagementService.getLevelConfig();
|
||||
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRoleForServer(serverExp);
|
||||
levels.sort(Comparator.comparing(AExperienceLevel::getExperienceNeeded));
|
||||
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(serverExp);
|
||||
roles.sort(Comparator.comparing(role -> role.getLevel().getLevel()));
|
||||
serverExp.getUsers().forEach(userInAServer -> {
|
||||
Integer gainedExperience = iterator.next();
|
||||
gainedExperience *= multiplier;
|
||||
log.trace("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);
|
||||
AUserExperience aUserExperience = userExperienceManagementService.incrementExpForUser(userInAServer, gainedExperience.longValue(), 1L);
|
||||
updateUserlevel(aUserExperience, levels);
|
||||
updateUserRole(aUserExperience, roles);
|
||||
userExperienceManagementService.saveUser(aUserExperience);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the appropriate level of the user and changes the role, if the {@link AExperienceLevel} changes.
|
||||
* This changes the config in the database, and also gives the {@link net.dv8tion.jda.api.entities.Member} the new
|
||||
* {@link net.dv8tion.jda.api.entities.Role}. If the user does not warrant an {@link AExperienceRole},
|
||||
* this method also removes it. The role is only changed, if the user does not have
|
||||
* @param userExperience The {@link AUserExperience} object to recalculate the {@link AExperienceRole} for
|
||||
* @param roles The list of {@link AExperienceRole} used as a role configuration
|
||||
*/
|
||||
@Override
|
||||
public void handleExperienceRoleForUser(AUserExperience userExperience, List<AExperienceRole> roles) {
|
||||
public void updateUserRole(AUserExperience userExperience, List<AExperienceRole> roles) {
|
||||
AUserInAServer user = userExperience.getUser();
|
||||
log.trace("Updating experience role for user {} in server {}", user.getUserReference().getId(), user.getServerReference().getId());
|
||||
AExperienceRole role = calculateRole(userExperience, roles);
|
||||
AExperienceRole role = experienceRoleService.calculateRole(userExperience, roles);
|
||||
Member member = botService.getMemberInServer(user.getServerReference(), user.getUserReference());
|
||||
boolean currentlyHasNoExperienceRole = userExperience.getCurrentExperienceRole() == null;
|
||||
if(role == null) {
|
||||
if(!currentlyHasNoExperienceRole){
|
||||
roleService.removeRoleFromUser(user, userExperience.getCurrentExperienceRole().getRole());
|
||||
}
|
||||
userExperience.setCurrentExperienceRole(null);
|
||||
return;
|
||||
}
|
||||
if(currentlyHasNoExperienceRole || !role.getRole().getId().equals(userExperience.getCurrentExperienceRole().getRole().getId())) {
|
||||
log.info("User {} in server {} gets a new role {}", user.getUserReference().getId(), user.getServerReference().getId(), role.getRole().getId());
|
||||
if(!currentlyHasNoExperienceRole) {
|
||||
roleService.removeRoleFromUser(user, userExperience.getCurrentExperienceRole().getRole());
|
||||
boolean userHasRoleAlready = roleService.memberHasRole(member, role.getRole());
|
||||
if(!userHasRoleAlready) {
|
||||
if(currentlyHasNoExperienceRole || !role.getRole().getId().equals(userExperience.getCurrentExperienceRole().getRole().getId())) {
|
||||
log.info("User {} in server {} gets a new role {}", user.getUserReference().getId(), user.getServerReference().getId(), role.getRole().getId());
|
||||
if(!currentlyHasNoExperienceRole) {
|
||||
roleService.removeRoleFromUser(user, userExperience.getCurrentExperienceRole().getRole());
|
||||
}
|
||||
roleService.addRoleToUser(user, role.getRole());
|
||||
}
|
||||
userExperience.setCurrentExperienceRole(role);
|
||||
roleService.addRoleToUser(user, userExperience.getCurrentExperienceRole().getRole());
|
||||
}
|
||||
userExperience.setCurrentExperienceRole(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronizes the {@link net.dv8tion.jda.api.entities.Role} of all {@link net.dv8tion.jda.api.entities.Member} in
|
||||
* the given {@link AServer}. This might take a long time to complete, because there are a lot of role changes.
|
||||
* @param server The {@link AServer} to update the users for
|
||||
*/
|
||||
@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);
|
||||
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(server);
|
||||
for (int i = 0; i < aUserExperiences.size(); i++) {
|
||||
AUserExperience userExperience = aUserExperiences.get(i);
|
||||
log.trace("Synchronizing {} out of {}", i, aUserExperiences.size());
|
||||
handleExperienceRoleForUser(userExperience, roles);
|
||||
updateUserRole(userExperience, roles);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronizes the roles of all the users and provides feedback to the user executing
|
||||
* @param server The {@link AServer} to update users for
|
||||
* @param channel The {@link AChannel} in which the {@link dev.sheldan.abstracto.experience.models.templates.UserSyncStatusModel}
|
||||
*/
|
||||
@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();
|
||||
int interval = Math.min(aUserExperiences.size() / 10, 100);
|
||||
for (int i = 0; i < aUserExperiences.size(); i++) {
|
||||
if((i % interval) == 1) {
|
||||
log.trace("Updating feedback message with new index {} out of {}", i, aUserExperiences.size());
|
||||
UserSyncStatusModel incrementalStatusModel = UserSyncStatusModel.builder().currentCount(i).totalUserCount(aUserExperiences.size()).build();
|
||||
status = templateService.renderEmbedTemplate("status_message", incrementalStatusModel);
|
||||
messageService.updateStatusMessage(channel, statusMessage.getIdLong(), status);
|
||||
}
|
||||
log.trace("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();
|
||||
}
|
||||
|
||||
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(server);
|
||||
executeActionOnUserExperiencesWithFeedBack(aUserExperiences, channel, (AUserExperience experience) -> {
|
||||
updateUserRole(experience, roles);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeActionOnUserExperiencesWithFeedBack(List<AUserExperience> experiences, AChannel channel, Consumer<AUserExperience> toExecute) {
|
||||
MessageToSend status = getUserSyncStatusUpdateModel(0, experiences.size());
|
||||
try {
|
||||
Message statusMessage = messageService.createStatusMessage(status, channel).get();
|
||||
int interval = Math.min(Math.max(experiences.size() / 10, 1), 100);
|
||||
for (int i = 0; i < experiences.size(); i++) {
|
||||
if((i % interval) == 1) {
|
||||
log.trace("Updating feedback message with new index {} out of {}", i, experiences.size());
|
||||
status = getUserSyncStatusUpdateModel(i, experiences.size());
|
||||
messageService.updateStatusMessage(channel, statusMessage.getIdLong(), status);
|
||||
}
|
||||
toExecute.accept(experiences.get(i));
|
||||
log.trace("Synchronizing {} out of {}", i, experiences.size());
|
||||
}
|
||||
status = getUserSyncStatusUpdateModel(experiences.size(), experiences.size());
|
||||
messageService.updateStatusMessage(channel, statusMessage.getIdLong(), status);
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
log.info("Failed to synchronize users.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private MessageToSend getUserSyncStatusUpdateModel(Integer current, Integer total) {
|
||||
UserSyncStatusModel statusModel = UserSyncStatusModel.builder().currentCount(current).totalUserCount(total).build();
|
||||
return templateService.renderEmbedTemplate("user_sync_status_message", statusModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the role configuration and executes the method responsible to sync the experience role of the user
|
||||
* @param userExperience The {@link AUserExperience} to synchronize the role for
|
||||
*/
|
||||
@Override
|
||||
public void syncForSingleUser(AUserExperience userExperience) {
|
||||
AUserInAServer user = userExperience.getUser();
|
||||
log.info("Synchronizing for user {} in server {}", user.getUserReference().getId(), user.getServerReference().getId());
|
||||
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRoleForServer(user.getServerReference());
|
||||
handleExperienceRoleForUser(userExperience, roles);
|
||||
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(user.getServerReference());
|
||||
updateUserRole(userExperience, roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the leaderboard data for the given page of the given server
|
||||
* @param server The {@link AServer} to retrieve the leaderboard for
|
||||
* @param page The desired page on the leaderboard. The pagesize is 10
|
||||
* @return The {@link LeaderBoard} containing all necessary information concerning the leaderboard
|
||||
*/
|
||||
@Override
|
||||
public LeaderBoard findLeaderBoardData(AServer server, Integer page) {
|
||||
List<AUserExperience> experiences = userExperienceManagementService.findLeaderboardUsersPaginated(server, page * 10, (page +1) * 10);
|
||||
@@ -235,6 +286,11 @@ public class ExperienceTrackerServiceBean implements ExperienceTrackerService {
|
||||
return LeaderBoard.builder().entries(entries).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an {@link AUserExperience} and loads the appropriate rank of the passed {@link AUserInAServer}
|
||||
* @param userInAServer The {@link AUserInAServer} to retrieve the {@link LeaderBoardEntry} for
|
||||
* @return The {@link LeaderBoardEntry} representing one single row in the leaderboard
|
||||
*/
|
||||
@Override
|
||||
public LeaderBoardEntry getRankOfUserInServer(AUserInAServer userInAServer) {
|
||||
log.info("Retrieving rank for {}", userInAServer.getUserReference().getId());
|
||||
@@ -13,16 +13,34 @@ public class ExperienceLevelServiceBean implements ExperienceLevelService {
|
||||
@Autowired
|
||||
private ExperienceLevelManagementService experienceLevelManagementService;
|
||||
|
||||
@Override
|
||||
public void createExperienceLevel(Integer level, Long experienceNeeded) {
|
||||
private void createExperienceLevel(Integer level, Long experienceNeeded) {
|
||||
if(!experienceLevelManagementService.levelExists(level)) {
|
||||
log.trace("Creating new experience level {} with experience needed {}.", level, experienceNeeded);
|
||||
experienceLevelManagementService.createExperienceLevel(level, experienceNeeded);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates all {@link AExperienceLevel} until (including 0) up until the passed level
|
||||
* @param level The max level to create {@link dev.sheldan.abstracto.experience.models.database.AExperienceLevel} for
|
||||
*/
|
||||
@Override
|
||||
public Long calculateExperienceForLevel(Integer level) {
|
||||
public void createLevelsUntil(Integer level) {
|
||||
createExperienceLevel(0, 0L);
|
||||
long experience = 0L;
|
||||
for (int i = 1; i < level; i++) {
|
||||
experience = experience + calculateExperienceForLevel(i - 1);
|
||||
createExperienceLevel(i, experience);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the required experience to reach this level. This calculated experience is relative, in the sense
|
||||
* the returned experience is the increment from the experience requirement from the level before.
|
||||
* @param level The level to calculate the experience amount for
|
||||
* @return The needed experience to reach this level, if the user already has the level below the passed one
|
||||
*/
|
||||
private Long calculateExperienceForLevel(Integer level) {
|
||||
return 5L * (level * level) + 50 * level + 100;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package dev.sheldan.abstracto.experience.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
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.models.database.AUserExperience;
|
||||
import dev.sheldan.abstracto.experience.service.management.ExperienceLevelManagementService;
|
||||
import dev.sheldan.abstracto.experience.service.management.ExperienceRoleManagementService;
|
||||
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
|
||||
@@ -11,7 +13,9 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@@ -24,30 +28,79 @@ public class ExperienceRoleServiceBean implements ExperienceRoleService {
|
||||
private ExperienceLevelManagementService experienceLevelService;
|
||||
|
||||
@Autowired
|
||||
private ExperienceTrackerService experienceTrackerService;
|
||||
private AUserExperienceService userExperienceService;
|
||||
|
||||
@Autowired
|
||||
private UserExperienceManagementService userExperienceManagementService;
|
||||
|
||||
/**
|
||||
* Unsets the current configuration for the passed level, and sets the {@link ARole} to be used for this level
|
||||
* in the given {@link AServer}
|
||||
* @param role The {@link ARole} to set the level to
|
||||
* @param level The level the {@link ARole} should be awareded at
|
||||
* @param server The {@link AServer} for which this configuration should be done
|
||||
*/
|
||||
@Override
|
||||
public void setRoleToLevel(ARole role, Integer level, AServer server) {
|
||||
public void setRoleToLevel(ARole role, Integer level, AServer server, AChannel feedbackChannel) {
|
||||
AExperienceLevel experienceLevel = experienceLevelService.getLevel(level);
|
||||
experienceRoleManagementService.unSetLevelInServer(experienceLevel, server);
|
||||
unsetRole(role, server, feedbackChannel);
|
||||
experienceRoleManagementService.removeAllRoleAssignmentsForLevelInServer(experienceLevel, server);
|
||||
experienceRoleManagementService.setLevelToRole(experienceLevel, role, server);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the {@link AExperienceRole} and recalculates the experience for all users which currently had the associated
|
||||
* {@link net.dv8tion.jda.api.entities.Role}.
|
||||
* @param role The {@link ARole} to remove from the {@link dev.sheldan.abstracto.experience.models.database.AExperienceRole}
|
||||
* configuration
|
||||
* @param server The {@link AServer} for which the {@link ARole} should be removed from the configuration
|
||||
*/
|
||||
@Override
|
||||
public void unsetRole(ARole role, AServer server) {
|
||||
public void unsetRole(ARole role, AServer server, AChannel feedbackChannel) {
|
||||
AExperienceRole roleInServer = experienceRoleManagementService.getRoleInServer(role, server);
|
||||
if(roleInServer.getUsers().size() > 0) {
|
||||
log.info("Recalculating the roles for {} users, because their current role was removed from experience tracking.", roleInServer.getUsers().size());
|
||||
roleInServer.getUsers().forEach(userExperience -> {
|
||||
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRoleForServer(server);
|
||||
if(roleInServer != null) {
|
||||
if(roleInServer.getUsers().size() > 0) {
|
||||
log.info("Recalculating the roles for {} users, because their current role was removed from experience tracking.", roleInServer.getUsers().size());
|
||||
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(server);
|
||||
roles.removeIf(role1 -> role1.getId().equals(roleInServer.getId()));
|
||||
experienceTrackerService.handleExperienceRoleForUser(userExperience, roles);
|
||||
});
|
||||
|
||||
userExperienceService.executeActionOnUserExperiencesWithFeedBack(roleInServer.getUsers(), feedbackChannel, (AUserExperience ex) -> {
|
||||
userExperienceService.updateUserRole(ex, roles);
|
||||
});
|
||||
}
|
||||
experienceRoleManagementService.unsetRole(roleInServer);
|
||||
}
|
||||
experienceRoleManagementService.unsetRole(roleInServer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the best {@link AExperienceRole} for the level of the passed {@link AUserExperience}
|
||||
* @param userExperience The {@link AUserExperience} containing the level to calculate the {@link AExperienceRole}
|
||||
* @param roles The role configuration to be used when calculating the appropriate {@link AExperienceRole}
|
||||
* @return The best fitting {@link AExperienceRole} according to the level of the {@link AUserExperience}
|
||||
*/
|
||||
@Override
|
||||
public AExperienceRole calculateRole(AUserExperience userExperience, List<AExperienceRole> roles) {
|
||||
if(roles.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
AExperienceRole lastRole = null;
|
||||
for (AExperienceRole experienceRole : roles) {
|
||||
if(userExperience.getCurrentLevel().getLevel() >= experienceRole.getLevel().getLevel()) {
|
||||
lastRole = experienceRole;
|
||||
} else {
|
||||
return lastRole;
|
||||
}
|
||||
}
|
||||
return lastRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AExperienceLevel getLevelOfNextRole(AExperienceLevel startLevel, AServer server) {
|
||||
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(server);
|
||||
roles = roles.stream().filter(role -> role.getLevel().getLevel() < startLevel.getLevel()).collect(Collectors.toList());
|
||||
roles.sort(Comparator.comparing(role -> role.getLevel().getLevel()));
|
||||
AExperienceRole aExperienceRole = roles.stream().findFirst().orElse(null);
|
||||
return aExperienceRole != null ? aExperienceRole.getLevel() : AExperienceLevel.builder().level(200).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,11 +34,6 @@ public class ExperienceLevelManagementServiceBean implements ExperienceLevelMana
|
||||
return experienceLevelRepository.getOne(level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AExperienceLevel getLevelClosestTo(Long experience) {
|
||||
return experienceLevelRepository.findTopByExperienceNeededGreaterThanOrderByExperienceNeededAsc(experience);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AExperienceLevel> getLevelConfig() {
|
||||
return experienceLevelRepository.findAll();
|
||||
|
||||
@@ -18,8 +18,13 @@ public class ExperienceRoleManagementServiceBean implements ExperienceRoleManage
|
||||
@Autowired
|
||||
private ExperienceRoleRepository experienceRoleRepository;
|
||||
|
||||
/**
|
||||
* Removes all assignments of roles for the given level
|
||||
* @param level The level to remove the roles for
|
||||
* @param server The server in which this should happen
|
||||
*/
|
||||
@Override
|
||||
public void unSetLevelInServer(AExperienceLevel level, AServer server) {
|
||||
public void removeAllRoleAssignmentsForLevelInServer(AExperienceLevel level, AServer server) {
|
||||
log.trace("Removing all role assignments for level {}.", level.getLevel());
|
||||
List<AExperienceRole> existingExperienceRoles = experienceRoleRepository.findByLevelAndRoleServer(level, server);
|
||||
existingExperienceRoles.forEach(existingRole -> {
|
||||
@@ -38,7 +43,7 @@ public class ExperienceRoleManagementServiceBean implements ExperienceRoleManage
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AExperienceRole> getExperienceRoleForServer(AServer server) {
|
||||
public List<AExperienceRole> getExperienceRolesForServer(AServer server) {
|
||||
return experienceRoleRepository.findByRoleServer(server);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ 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.LeaderBoardEntryResult;
|
||||
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
|
||||
import dev.sheldan.abstracto.experience.models.database.AUserExperience;
|
||||
import dev.sheldan.abstracto.experience.repository.UserExperienceRepository;
|
||||
@@ -23,12 +23,6 @@ public class UserExperienceManagementServiceBean implements UserExperienceManage
|
||||
@Autowired
|
||||
private ExperienceLevelManagementService experienceLevelManagementService;
|
||||
|
||||
@Override
|
||||
public void setExperienceTo(AUserExperience aUserInAServer, Long experience) {
|
||||
aUserInAServer.setExperience(experience);
|
||||
repository.save(aUserInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AUserExperience findUserInServer(AUserInAServer aUserInAServer) {
|
||||
Optional<AUserExperience> byId = repository.findById(aUserInAServer.getUserInServerId());
|
||||
@@ -38,7 +32,7 @@ public class UserExperienceManagementServiceBean implements UserExperienceManage
|
||||
@Override
|
||||
public AUserExperience createUserInServer(AUserInAServer aUserInAServer) {
|
||||
AExperienceLevel startingLevel = experienceLevelManagementService.getLevel(0);
|
||||
AUserExperience userExperience = AUserExperience
|
||||
return AUserExperience
|
||||
.builder()
|
||||
.experience(0L)
|
||||
.messageCount(0L)
|
||||
@@ -46,13 +40,6 @@ public class UserExperienceManagementServiceBean implements UserExperienceManage
|
||||
.id(aUserInAServer.getUserInServerId())
|
||||
.currentLevel(startingLevel)
|
||||
.build();
|
||||
repository.save(userExperience);
|
||||
return userExperience;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveUser(AUserExperience userExperience) {
|
||||
repository.save(userExperience);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -60,6 +47,34 @@ public class UserExperienceManagementServiceBean implements UserExperienceManage
|
||||
return repository.findByUser_ServerReference(server);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates or updates the {@link AUserExperience} object. Does not change the level or the role.
|
||||
* @param user The {@link AUserInAServer} to increase the experience for
|
||||
* @param experience The experience amount to increase by
|
||||
* @param messageCount The amount of messags to increase the count by
|
||||
* @return The created/changed {@link AUserExperience} object
|
||||
*/
|
||||
@Override
|
||||
public AUserExperience incrementExpForUser(AUserInAServer user, Long experience, Long messageCount) {
|
||||
Optional<AUserExperience> byId = repository.findById(user.getUserInServerId());
|
||||
if(byId.isPresent()) {
|
||||
AUserExperience userExperience = byId.get();
|
||||
userExperience.setMessageCount(userExperience.getMessageCount() + messageCount);
|
||||
userExperience.setExperience(userExperience.getExperience() + experience);
|
||||
return userExperience;
|
||||
} else {
|
||||
AExperienceLevel startingLevel = experienceLevelManagementService.getLevel(0);
|
||||
return AUserExperience
|
||||
.builder()
|
||||
.experience(experience)
|
||||
.messageCount(messageCount)
|
||||
.user(user)
|
||||
.id(user.getUserInServerId())
|
||||
.currentLevel(startingLevel)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AUserExperience> findLeaderboardUsersPaginated(AServer aServer, Integer start, Integer end) {
|
||||
return repository.findTop10ByUser_ServerReferenceOrderByExperienceDesc(aServer, PageRequest.of(start, end));
|
||||
@@ -69,6 +84,11 @@ public class UserExperienceManagementServiceBean implements UserExperienceManage
|
||||
public LeaderBoardEntryResult getRankOfUserInServer(AUserExperience userExperience) {
|
||||
return repository.getRankOfUserInServer(userExperience.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveUser(AUserExperience userExperience) {
|
||||
repository.save(userExperience);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user