[AB-57] [AB-61] reworked commands and services to work with completable futures and moved the database operations to the very last operation so we have transaction safety in more areas

added some cache annotations to the default repository functions
reworked how the undo cations are processed within commands, they are executed in a post command listener when the state is error
added a counter id to generate ids to be unique within servers, changed a few tables to be unique within a server
added future utils class for wrapping a list of futures into one
moved abstracto tables to separate schema in the installer
refactored experience gain to work with more futures and delayed database access
This commit is contained in:
Sheldan
2020-09-20 11:11:20 +02:00
parent 552ecc26b8
commit 76adda90a3
220 changed files with 2691 additions and 1498 deletions

View File

@@ -9,6 +9,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.experience.config.features.ExperienceFeature;
import dev.sheldan.abstracto.experience.converter.LeaderBoardModelConverter;
import dev.sheldan.abstracto.experience.models.LeaderBoard;
@@ -23,6 +24,7 @@ import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* Shows the experience gain information of the top 10 users in the server, or if a page number is provided as a parameter, only the members which are on this page.
@@ -46,7 +48,7 @@ public class LeaderBoardCommand extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
// parameter is optional, in case its not present, we default to the 0th page
@@ -58,9 +60,9 @@ public class LeaderBoardCommand extends AbstractConditionableCommand {
LeaderBoardEntry userRank = userExperienceService.getRankOfUserInServer(commandContext.getUserInitiatedContext().getAUserInAServer());
leaderBoardModel.setUserExecuting(converter.fromLeaderBoardEntry(userRank));
MessageToSend messageToSend = templateService.renderEmbedTemplate(LEADER_BOARD_POST_EMBED_TEMPLATE, leaderBoardModel);
channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel());
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
.thenApply(aVoid -> CommandResult.fromSuccess());
return CommandResult.fromSuccess();
}
@Override
@@ -72,6 +74,7 @@ public class LeaderBoardCommand extends AbstractConditionableCommand {
.name("leaderboard")
.module(ExperienceModule.EXPERIENCE)
.templated(true)
.async(true)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)

View File

@@ -11,16 +11,19 @@ import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.models.FullRole;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.RoleService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.experience.config.features.ExperienceFeature;
import dev.sheldan.abstracto.experience.models.database.ADisabledExpRole;
import dev.sheldan.abstracto.experience.models.templates.DisabledExperienceRolesModel;
import dev.sheldan.abstracto.experience.service.management.DisabledExpRoleManagementService;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* Creates an embed containing the roles for which the experience gain has been disabled.
@@ -38,7 +41,7 @@ public class ListDisabledExperienceRoles extends AbstractConditionableCommand {
private ChannelService channelService;
@Override
public CommandResult execute(CommandContext commandContext) {
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
checkParameters(commandContext);
List<ADisabledExpRole> disabledRolesForServer = disabledExpRoleManagementService.getDisabledRolesForServer(commandContext.getUserInitiatedContext().getServer());
DisabledExperienceRolesModel disabledExperienceRolesModel = (DisabledExperienceRolesModel) ContextConverter.fromCommandContext(commandContext, DisabledExperienceRolesModel.class);
@@ -50,8 +53,8 @@ public class ListDisabledExperienceRoles extends AbstractConditionableCommand {
.build();
disabledExperienceRolesModel.getRoles().add(role);
});
channelService.sendEmbedTemplateInChannel("list_disabled_experience_roles", disabledExperienceRolesModel, commandContext.getChannel());
return CommandResult.fromSuccess();
List<CompletableFuture<Message>> futures = channelService.sendEmbedTemplateInChannel("list_disabled_experience_roles", disabledExperienceRolesModel, commandContext.getChannel());
return FutureUtils.toSingleFutureGeneric(futures).thenApply(aVoid -> CommandResult.fromSuccess());
}
@Override

View File

@@ -9,6 +9,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.experience.config.features.ExperienceFeature;
import dev.sheldan.abstracto.experience.converter.LeaderBoardModelConverter;
import dev.sheldan.abstracto.experience.models.LeaderBoardEntry;
@@ -23,6 +24,7 @@ import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* Command used to show an embed containing information about the experience amount, level and message count of a ember on a server
@@ -48,7 +50,7 @@ public class Rank extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
checkParameters(commandContext);
RankModel rankModel = (RankModel) ContextConverter.fromCommandContext(commandContext, RankModel.class);
LeaderBoardEntry userRank = userExperienceService.getRankOfUserInServer(commandContext.getUserInitiatedContext().getAUserInAServer());
@@ -56,9 +58,8 @@ public class Rank extends AbstractConditionableCommand {
AUserExperience experienceObj = userRank.getExperience();
rankModel.setExperienceToNextLevel(experienceLevelService.calculateExperienceToNextLevel(experienceObj.getCurrentLevel().getLevel(), experienceObj.getExperience()));
MessageToSend messageToSend = templateService.renderEmbedTemplate(RANK_POST_EMBED_TEMPLATE, rankModel);
channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel());
return CommandResult.fromSuccess();
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
.thenApply(aVoid -> CommandResult.fromSuccess());
}
@Override
@@ -69,6 +70,7 @@ public class Rank extends AbstractConditionableCommand {
.name("rank")
.module(ExperienceModule.EXPERIENCE)
.templated(true)
.async(true)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)

View File

@@ -19,6 +19,7 @@ import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* Command used to define which commands are to be awarded at which level
@@ -34,7 +35,7 @@ public class SetExpRole extends AbstractConditionableCommand {
private RoleService roleService;
@Override
public CommandResult execute(CommandContext commandContext) {
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
checkParameters(commandContext);
Integer level = (Integer) commandContext.getParameters().getParameters().get(0);
ARole role = (ARole) commandContext.getParameters().getParameters().get(1);
@@ -43,8 +44,8 @@ public class SetExpRole extends AbstractConditionableCommand {
throw new RoleNotFoundInGuildException(role.getId(), server.getId());
}
log.info("Setting role {} to be used for level {} on server {}", role.getId(), level, server.getId());
experienceRoleService.setRoleToLevel(role, level, commandContext.getUserInitiatedContext().getChannel());
return CommandResult.fromSuccess();
return experienceRoleService.setRoleToLevel(role, level, commandContext.getUserInitiatedContext().getChannel())
.thenApply(aVoid -> CommandResult.fromSuccess());
}
@Override
@@ -57,6 +58,7 @@ public class SetExpRole extends AbstractConditionableCommand {
.name("setExpRole")
.module(ExperienceModule.EXPERIENCE)
.templated(true)
.async(true)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)

View File

@@ -16,6 +16,7 @@ import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* Command used to synchronize the actual awarded roles which what is defined to be awarded in the database.
@@ -31,11 +32,11 @@ public class SyncRoles extends AbstractConditionableCommand {
private AUserExperienceService userExperienceService;
@Override
public CommandResult execute(CommandContext commandContext) {
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
AServer server = commandContext.getUserInitiatedContext().getServer();
log.info("Synchronizing roles on server {}", server.getId());
userExperienceService.syncUserRolesWithFeedback(server, commandContext.getUserInitiatedContext().getChannel());
return CommandResult.fromSuccess();
return userExperienceService.syncUserRolesWithFeedback(server, commandContext.getUserInitiatedContext().getChannel())
.thenApply(aVoid -> CommandResult.fromSuccess());
}
@Override
@@ -46,6 +47,7 @@ public class SyncRoles extends AbstractConditionableCommand {
.name("syncExpRoles")
.module(ExperienceModule.EXPERIENCE)
.templated(true)
.async(true)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)

View File

@@ -15,6 +15,7 @@ import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* Command used to remove a role from the roles to be awarded at certain levels. If there are users with this role currently, their role
@@ -27,13 +28,13 @@ public class UnSetExpRole extends AbstractConditionableCommand {
private ExperienceRoleService experienceRoleService;
@Override
public CommandResult execute(CommandContext commandContext) {
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
checkParameters(commandContext);
ARole role = (ARole) commandContext.getParameters().getParameters().get(0);
// 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().getChannel());
return CommandResult.fromSuccess();
return experienceRoleService.unsetRole(role, commandContext.getUserInitiatedContext().getChannel())
.thenApply(aVoid -> CommandResult.fromSuccess());
}
@Override
@@ -45,6 +46,7 @@ public class UnSetExpRole extends AbstractConditionableCommand {
.name("unSetExpRole")
.module(ExperienceModule.EXPERIENCE)
.templated(true)
.async(true)
.causesReaction(true)
.supportsEmbedException(true)
.parameters(parameters)

View File

@@ -30,9 +30,12 @@ public class JoiningUserRoleListener implements JoinListener {
@Override
public void execute(Member member, Guild guild, AUserInAServer aUserInAServer) {
AUserExperience userExperience = userExperienceManagementService.findUserInServer(aUserInAServer);
Long userInServerId = aUserInAServer.getUserInServerId();
if(userExperience != null) {
log.info("User {} joined {} with previous experience. Setting up experience role again (if necessary).", member.getUser().getIdLong(), guild.getIdLong());
userExperienceService.syncForSingleUser(userExperience);
userExperienceService.syncForSingleUser(userExperience).thenAccept(result ->
log.trace("Finished re-assigning experience for re-joning user {} in server {}.", userInServerId, guild.getIdLong())
);
}
}

View File

@@ -4,8 +4,10 @@ import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.experience.models.database.ADisabledExpRole;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.QueryHints;
import org.springframework.stereotype.Repository;
import javax.persistence.QueryHint;
import java.util.List;
/**
@@ -13,10 +15,15 @@ import java.util.List;
*/
@Repository
public interface DisabledExpRoleRepository extends JpaRepository<ADisabledExpRole, Long> {
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
boolean existsByRole(ARole role);
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
ADisabledExpRole findByRole(ARole role);
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
void deleteByRole(ARole role);
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
List<ADisabledExpRole> getByRole_Server(AServer server);
}

View File

@@ -1,12 +1,32 @@
package dev.sheldan.abstracto.experience.repository;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.QueryHints;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Repository;
import javax.persistence.QueryHint;
import java.util.List;
import java.util.Optional;
/**
* Repository to manage the access to the table managed by {@link AExperienceLevel}
*/
@Repository
public interface ExperienceLevelRepository extends JpaRepository<AExperienceLevel, Integer> {
@NotNull
@Override
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
Optional<AExperienceLevel> findById(@NonNull Integer aLong);
@Override
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
boolean existsById(@NonNull Integer aLong);
@NotNull
@Override
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
List<AExperienceLevel> findAll();
}

View File

@@ -4,12 +4,15 @@ 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 org.jetbrains.annotations.NotNull;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.QueryHints;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Repository;
import javax.persistence.QueryHint;
import java.util.List;
import java.util.Optional;
/**
* Repository to manage the access to the table managed by {@link AExperienceRole}
@@ -22,7 +25,7 @@ public interface ExperienceRoleRepository extends JpaRepository<AExperienceRole,
* @return The {@link AExperienceRole} found or null if the query did not return any results
*/
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
AExperienceRole findByRole(ARole role);
Optional<AExperienceRole> findByRole(ARole role);
/**
* Finds a list of {@link AExperienceRole} (if there are multiple ones, because of misconfiguration) of the given
@@ -41,4 +44,9 @@ public interface ExperienceRoleRepository extends JpaRepository<AExperienceRole,
*/
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
List<AExperienceRole> findByRoleServer(AServer server);
@NotNull
@Override
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
Optional<AExperienceRole> findById(@NonNull Long aLong);
}

View File

@@ -8,7 +8,12 @@ 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.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.experience.config.features.ExperienceFeatureConfig;
import dev.sheldan.abstracto.experience.models.ExperienceGainResult;
import dev.sheldan.abstracto.experience.models.RoleCalculationResult;
import dev.sheldan.abstracto.experience.models.database.*;
import dev.sheldan.abstracto.experience.models.LeaderBoard;
import dev.sheldan.abstracto.experience.models.LeaderBoardEntry;
@@ -28,15 +33,16 @@ import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
@Component
@Slf4j
public class AUserExperienceServiceBean implements AUserExperienceService {
@Autowired
private UserExperienceManagementService userExperienceManagementService;
@@ -64,12 +70,18 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
@Autowired
private DisabledExpRoleManagementService disabledExpRoleManagementService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private BotService botService;
@Autowired
private RunTimeExperienceService runTimeExperienceService;
@Autowired
private AUserExperienceServiceBean self;
/**
* 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
@@ -104,17 +116,17 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
/**
* Calculates the level of the given {@link AUserExperience} according 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, this must include the initial level 0
* * This level will be taken as the initial value, and if no other level qualifies, this will be taken.
* The levels must be ordered.
* @param experienceCount
* @return The appropriate level according to the level config
*/
@Override
public AExperienceLevel calculateLevel(AUserExperience experience, List<AExperienceLevel> levels) {
public AExperienceLevel calculateLevel(List<AExperienceLevel> levels, Long experienceCount) {
AExperienceLevel lastLevel = levels.get(0);
for (AExperienceLevel level : levels) {
if(level.getExperienceNeeded() >= experience.getExperience()) {
if(level.getExperienceNeeded() >= experienceCount) {
return lastLevel;
} else {
lastLevel = level;
@@ -124,9 +136,9 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
}
@Override
public boolean updateUserLevel(AUserExperience userExperience, List<AExperienceLevel> levels) {
public boolean updateUserLevel(AUserExperience userExperience, List<AExperienceLevel> levels, Long experienceCount) {
AUserInAServer user = userExperience.getUser();
AExperienceLevel correctLevel = calculateLevel(userExperience, levels);
AExperienceLevel correctLevel = calculateLevel(levels, experienceCount);
Integer currentLevel = userExperience.getCurrentLevel() != null ? userExperience.getCurrentLevel().getLevel() : 0;
if(!correctLevel.getLevel().equals(currentLevel)) {
log.info("User {} leveled from {} to {}", user.getUserReference().getId(), currentLevel, correctLevel.getLevel());
@@ -146,14 +158,17 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
*/
@Transactional
@Override
public void handleExperienceGain(List<AServer> servers) {
public CompletableFuture<Void> handleExperienceGain(List<AServer> servers) {
List<ExperienceGainResult> resultFutures = new ArrayList<>();
List<CompletableFuture<RoleCalculationResult>> futures = new ArrayList<>();
List<AExperienceLevel> levels = experienceLevelManagementService.getLevelConfig();
// TODO what if there are a lot in here...., transaction size etc
servers.forEach(serverExp -> {
log.trace("Handling experience for server {}", serverExp.getId());
int minExp = configService.getLongValue(ExperienceFeatureConfig.MIN_EXP_KEY, serverExp.getId()).intValue();
int maxExp = configService.getLongValue(ExperienceFeatureConfig.MAX_EXP_KEY, serverExp.getId()).intValue();
Double multiplier = configService.getDoubleValue(ExperienceFeatureConfig.EXP_MULTIPLIER_KEY, serverExp.getId());
PrimitiveIterator.OfInt iterator = new Random().ints(serverExp.getUsers().size(), minExp, maxExp + 1).iterator();
List<AExperienceLevel> levels = experienceLevelManagementService.getLevelConfig();
levels.sort(Comparator.comparing(AExperienceLevel::getExperienceNeeded));
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(serverExp);
List<ADisabledExpRole> disabledExpRoles = disabledExpRoleManagementService.getDisabledRolesForServer(serverExp);
@@ -165,11 +180,23 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
Member member = botService.getMemberInServer(userInAServer);
if(!roleService.hasAnyOfTheRoles(member, disabledRoles)) {
log.trace("Handling {}. The user gains {}", userInAServer.getUserReference().getId(), gainedExperience);
AUserExperience aUserExperience = userExperienceManagementService.incrementExpForUser(userInAServer, gainedExperience.longValue(), 1L);
AUserExperience aUserExperience = userExperienceManagementService.findUserInServer(userInAServer);
if(Boolean.FALSE.equals(aUserExperience.getExperienceGainDisabled())) {
updateUserLevel(aUserExperience, levels);
updateUserRole(aUserExperience, roles);
userExperienceManagementService.saveUser(aUserExperience);
Long newExperienceCount = aUserExperience.getExperience() + gainedExperience.longValue();
AExperienceLevel newLevel = calculateLevel(levels, newExperienceCount);
CompletableFuture<RoleCalculationResult> resultFuture = updateUserRole(aUserExperience, roles, newLevel.getLevel());
Long newMessageCount = aUserExperience.getMessageCount() + 1L;
ExperienceGainResult calculationResult =
ExperienceGainResult
.builder()
.calculationResult(resultFuture)
.newExperience(newExperienceCount)
.newMessageCount(newMessageCount)
.newLevel(newLevel.getLevel())
.userInServerId(userInAServer.getUserInServerId())
.build();
resultFutures.add(calculationResult);
futures.add(resultFuture);
} else {
log.trace("Experience gain was disabled. User did not gain any experience.");
}
@@ -178,6 +205,35 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
}
});
});
return FutureUtils.toSingleFutureGeneric(futures).thenAccept(aVoid ->
self.persistExperienceChanges(resultFutures)
);
}
@Transactional
public void persistExperienceChanges(List<ExperienceGainResult> resultFutures) {
List<AExperienceLevel> levels = experienceLevelManagementService.getLevelConfig();
HashMap<Long, List<AExperienceRole>> serverRoleMapping = new HashMap<>();
resultFutures.forEach(experienceGainResult -> {
AUserInAServer user = userInServerManagementService.loadUser(experienceGainResult.getUserInServerId());
AUserExperience userExperience = userExperienceManagementService.findUserInServer(user);
userExperience.setMessageCount(experienceGainResult.getNewMessageCount());
userExperience.setExperience(experienceGainResult.getNewExperience());
Optional<AExperienceLevel> foundLevel = levels.stream().filter(level -> level.getLevel().equals(experienceGainResult.getNewLevel())).findFirst();
if(foundLevel.isPresent()) {
userExperience.setCurrentLevel(foundLevel.get());
} else {
log.warn("User {} was present, but no level could be found.", userExperience.getUser().getUserReference().getId());
}
AServer server = user.getServerReference();
if(!serverRoleMapping.containsKey(server.getId())) {
serverRoleMapping.put(server.getId(), experienceRoleManagementService.getExperienceRolesForServer(server));
}
List<AExperienceRole> roleConfig = serverRoleMapping.get(server.getId());
AExperienceRole role = experienceRoleService.calculateRole(roleConfig, userExperience.getLevelOrDefault());
userExperience.setCurrentExperienceRole(role);
});
}
/**
@@ -189,28 +245,48 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
* @param roles The list of {@link AExperienceRole} used as a role configuration
*/
@Override
public void updateUserRole(AUserExperience userExperience, List<AExperienceRole> roles) {
public CompletableFuture<RoleCalculationResult> updateUserRole(AUserExperience userExperience, List<AExperienceRole> roles, Integer currentLevel) {
AUserInAServer user = userExperience.getUser();
Function<Void, RoleCalculationResult> returnNullRole = aVoid -> RoleCalculationResult
.builder()
.userInServerId(user.getUserInServerId())
.experienceRoleId(null)
.build();
if(!botService.isUserInGuild(userExperience.getUser())) {
log.trace("User {} is not in server {} anymore. No role calculation done.", userExperience.getUser().getUserInServerId(), userExperience.getUser().getServerReference().getId());
return CompletableFuture.completedFuture(returnNullRole.apply(null));
}
Long userInServerId = user.getUserInServerId();
log.trace("Updating experience role for user {} in server {}", user.getUserReference().getId(), user.getServerReference().getId());
AExperienceRole role = experienceRoleService.calculateRole(userExperience, roles);
AExperienceRole role = experienceRoleService.calculateRole(roles, currentLevel);
Member member = botService.getMemberInServer(user.getServerReference(), user.getUserReference());
boolean currentlyHasNoExperienceRole = userExperience.getCurrentExperienceRole() == null;
if(role == null) {
if(!currentlyHasNoExperienceRole && botService.isUserInGuild(userExperience.getUser())){
roleService.removeRoleFromUser(user, userExperience.getCurrentExperienceRole().getRole());
if(!currentlyHasNoExperienceRole){
return roleService.removeRoleFromUserFuture(user, userExperience.getCurrentExperienceRole().getRole())
.thenApply(returnNullRole);
}
userExperience.setCurrentExperienceRole(null);
return;
return CompletableFuture.completedFuture(returnNullRole.apply(null));
}
boolean userHasRoleAlready = roleService.memberHasRole(member, role.getRole());
Long experienceRoleId = role.getId();
Function<Void, RoleCalculationResult> fullResult = aVoid -> RoleCalculationResult
.builder()
.experienceRoleId(experienceRoleId)
.userInServerId(userInServerId)
.build();
if(!userHasRoleAlready && (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());
CompletableFuture<Void> removalFuture;
if(!currentlyHasNoExperienceRole && botService.isUserInGuild(userExperience.getUser())) {
roleService.removeRoleFromUser(user, userExperience.getCurrentExperienceRole().getRole());
removalFuture = roleService.removeRoleFromUserFuture(user, userExperience.getCurrentExperienceRole().getRole());
} else {
removalFuture = CompletableFuture.completedFuture(null);
}
roleService.addRoleToUser(user, role.getRole());
CompletableFuture<Void> addRoleFuture = roleService.addRoleToUserFuture(user, role.getRole());
return CompletableFuture.allOf(removalFuture, addRoleFuture).thenApply(fullResult);
}
userExperience.setCurrentExperienceRole(role);
return CompletableFuture.completedFuture(fullResult.apply(null));
}
/**
@@ -219,15 +295,17 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
* @param server The {@link AServer} to update the users for
*/
@Override
public void syncUserRoles(AServer server) {
public List<CompletableFuture<RoleCalculationResult>> syncUserRoles(AServer server) {
List<CompletableFuture<RoleCalculationResult>> results = new ArrayList<>();
List<AUserExperience> aUserExperiences = userExperienceManagementService.loadAllUsers(server);
log.info("Found {} users to synchronize", aUserExperiences.size());
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());
updateUserRole(userExperience, roles);
results.add(updateUserRole(userExperience, roles, userExperience.getCurrentLevel().getLevel()));
}
return results;
}
/**
@@ -236,11 +314,35 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
* @param channel The {@link AChannel} in which the {@link dev.sheldan.abstracto.experience.models.templates.UserSyncStatusModel}
*/
@Override
public void syncUserRolesWithFeedback(AServer server, AChannel channel) {
public CompletableFuture<Void> syncUserRolesWithFeedback(AServer server, AChannel channel) {
List<AUserExperience> aUserExperiences = userExperienceManagementService.loadAllUsers(server);
log.info("Found {} users to synchronize", aUserExperiences.size());
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(server);
executeActionOnUserExperiencesWithFeedBack(aUserExperiences, channel, (AUserExperience experience) -> updateUserRole(experience, roles));
CompletableFutureList<RoleCalculationResult> calculations = executeActionOnUserExperiencesWithFeedBack(aUserExperiences, channel, (AUserExperience experience) -> updateUserRole(experience, roles, experience.getLevelOrDefault()));
return calculations.getMainFuture().thenAccept(aVoid ->
self.syncRolesInStorage(calculations.getObjects())
);
}
/**
* Updates the actually stored experience roles in the database
* @param results The list of {@link RoleCalculationResult} which should be applied
*/
@Transactional
public void syncRolesInStorage(List<RoleCalculationResult> results) {
results.forEach(result -> {
if(result != null) {
AUserInAServer user = userInServerManagementService.loadUser(result.getUserInServerId());
AUserExperience userExperience = userExperienceManagementService.findUserInServer(user);
log.trace("Updating experience role for {} in server {} to {}", user.getUserInServerId(), user.getServerReference(), result.getExperienceRoleId());
if(result.getExperienceRoleId() != null) {
AExperienceRole role = experienceRoleManagementService.getExperienceRoleById(result.getExperienceRoleId());
userExperience.setCurrentExperienceRole(role);
} else {
userExperience.setCurrentExperienceRole(null);
}
}
});
}
/**
@@ -250,7 +352,8 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
* @param toExecute The {@link Consumer} which should be executed on each element of the passed list
*/
@Override
public void executeActionOnUserExperiencesWithFeedBack(List<AUserExperience> experiences, AChannel channel, Consumer<AUserExperience> toExecute) {
public CompletableFutureList<RoleCalculationResult> executeActionOnUserExperiencesWithFeedBack(List<AUserExperience> experiences, AChannel channel, Function<AUserExperience, CompletableFuture<RoleCalculationResult>> toExecute) {
List<CompletableFuture<RoleCalculationResult>> futures = new ArrayList<>();
MessageToSend status = getUserSyncStatusUpdateModel(0, experiences.size());
try {
Message statusMessage = messageService.createStatusMessage(status, channel).get();
@@ -261,7 +364,7 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
status = getUserSyncStatusUpdateModel(i, experiences.size());
messageService.updateStatusMessage(channel, statusMessage.getIdLong(), status);
}
toExecute.accept(experiences.get(i));
futures.add(toExecute.apply(experiences.get(i)));
log.trace("Synchronizing {} out of {}", i, experiences.size());
}
status = getUserSyncStatusUpdateModel(experiences.size(), experiences.size());
@@ -270,6 +373,8 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
log.info("Failed to synchronize users.", e);
Thread.currentThread().interrupt();
}
return new CompletableFutureList<>(futures);
}
@Override
@@ -294,11 +399,11 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
* @param userExperience The {@link AUserExperience} to synchronize the role for
*/
@Override
public void syncForSingleUser(AUserExperience userExperience) {
public CompletableFuture<RoleCalculationResult> syncForSingleUser(AUserExperience userExperience) {
AUserInAServer user = userExperience.getUser();
log.info("Synchronizing for user {} in server {}", user.getUserReference().getId(), user.getServerReference().getId());
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(user.getServerReference());
updateUserRole(userExperience, roles);
return updateUserRole(userExperience, roles, userExperience.getLevelOrDefault());
}
/**

View File

@@ -3,6 +3,9 @@ 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.core.service.management.RoleManagementService;
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
import dev.sheldan.abstracto.experience.models.RoleCalculationResult;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import dev.sheldan.abstracto.experience.models.database.AExperienceRole;
import dev.sheldan.abstracto.experience.models.database.AUserExperience;
@@ -11,9 +14,12 @@ import dev.sheldan.abstracto.experience.service.management.ExperienceRoleManagem
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@Component
@@ -29,6 +35,12 @@ public class ExperienceRoleServiceBean implements ExperienceRoleService {
@Autowired
private AUserExperienceService userExperienceService;
@Autowired
private ExperienceRoleServiceBean self;
@Autowired
private RoleManagementService roleManagementService;
/**
* UnSets the current configuration for the passed level, and sets the {@link ARole} to be used for this level
* in the given {@link AServer}
@@ -36,11 +48,19 @@ public class ExperienceRoleServiceBean implements ExperienceRoleService {
* @param level The level the {@link ARole} should be awarded at
*/
@Override
public void setRoleToLevel(ARole role, Integer level, AChannel feedbackChannel) {
public CompletableFuture<Void> setRoleToLevel(ARole role, Integer level, AChannel feedbackChannel) {
Long roleId = role.getId();
return unsetRole(role, feedbackChannel).thenAccept(aVoid ->
self.unsetRoleInDb(level, roleId)
);
}
@Transactional
public void unsetRoleInDb(Integer level, Long roleId) {
AExperienceLevel experienceLevel = experienceLevelService.getLevel(level).orElseThrow(() -> new IllegalArgumentException(String.format("Could not find level %s", level)));
unsetRole(role, feedbackChannel);
experienceRoleManagementService.removeAllRoleAssignmentsForLevelInServer(experienceLevel, role.getServer());
experienceRoleManagementService.setLevelToRole(experienceLevel, role);
ARole loadedRole = roleManagementService.findRole(roleId);
experienceRoleManagementService.removeAllRoleAssignmentsForLevelInServer(experienceLevel, loadedRole.getServer());
experienceRoleManagementService.setLevelToRole(experienceLevel, loadedRole);
}
/**
@@ -50,35 +70,52 @@ public class ExperienceRoleServiceBean implements ExperienceRoleService {
* configuration
*/
@Override
public void unsetRole(ARole role, AChannel feedbackChannel) {
AExperienceRole roleInServer = experienceRoleManagementService.getRoleInServer(role);
if(roleInServer != null) {
public CompletableFuture<Void> unsetRole(ARole role, AChannel feedbackChannel) {
Optional<AExperienceRole> roleInServerOptional = experienceRoleManagementService.getRoleInServerOptional(role);
if(roleInServerOptional.isPresent()) {
AExperienceRole roleInServer = roleInServerOptional.get();
if(!roleInServer.getUsers().isEmpty()) {
log.info("Recalculating the roles for {} users, because their current role was removed from experience tracking.", roleInServer.getUsers().size());
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(role.getServer());
roles.removeIf(role1 -> role1.getId().equals(roleInServer.getId()));
userExperienceService.executeActionOnUserExperiencesWithFeedBack(roleInServer.getUsers(), feedbackChannel,
(AUserExperience ex) -> userExperienceService.updateUserRole(ex, roles));
Long roleId = role.getId();
CompletableFutureList<RoleCalculationResult> calculationResults = userExperienceService.executeActionOnUserExperiencesWithFeedBack(roleInServer.getUsers(), feedbackChannel,
(AUserExperience ex) -> userExperienceService.updateUserRole(ex, roles, ex.getLevelOrDefault()));
return calculationResults.getMainFuture().thenAccept(aVoid ->
self.persistData(calculationResults, roleId)
);
} else {
experienceRoleManagementService.unsetRole(roleInServer);
return CompletableFuture.completedFuture(null);
}
experienceRoleManagementService.unsetRole(roleInServer);
} else {
log.info("Experience role is not define in server - skipping unset.");
return CompletableFuture.completedFuture(null);
}
}
@Transactional
public void persistData(CompletableFutureList<RoleCalculationResult> results, Long roleId) {
AExperienceRole roleInServer = experienceRoleManagementService.getRoleInServer(roleId);
experienceRoleManagementService.unsetRole(roleInServer);
userExperienceService.syncRolesInStorage(results.getObjects());
}
/**
* 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}
* Finds the best {@link AExperienceRole} for the level of the passed {@link AUserExperience}, returns null if the passed
* roles are empty/null
* @param roles The role configuration to be used when calculating the appropriate {@link AExperienceRole}
* @param currentLevel
* @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.isEmpty()) {
public AExperienceRole calculateRole(List<AExperienceRole> roles, Integer currentLevel) {
if(roles == null || roles.isEmpty()) {
return null;
}
AExperienceRole lastRole = null;
for (AExperienceRole experienceRole : roles) {
if(userExperience.getCurrentLevel().getLevel() >= experienceRole.getLevel().getLevel()) {
if(currentLevel >= experienceRole.getLevel().getLevel()) {
lastRole = experienceRole;
} else {
return lastRole;

View File

@@ -32,7 +32,7 @@ public class HasLevelCondition implements SystemCondition {
Long userId = (Long) parameters.get(USER_ID_VARIABLE);
Integer level = (Integer) parameters.get(LEVEL_VARIABLE);
Optional<AUserInAServer> userInServerOptional = userInServerManagementService.loadUser(userId);
Optional<AUserInAServer> userInServerOptional = userInServerManagementService.loadUserConditional(userId);
if(userInServerOptional.isPresent()) {
AUserInAServer userInServer = userInServerOptional.get();
AUserExperience user = userExperienceManagementService.findUserInServer(userInServer);

View File

@@ -1,7 +1,9 @@
package dev.sheldan.abstracto.experience.service.management;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import dev.sheldan.abstracto.experience.models.database.AExperienceRole;
import dev.sheldan.abstracto.experience.repository.ExperienceRoleRepository;
@@ -10,6 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
@Component
@Slf4j
@@ -18,6 +21,9 @@ public class ExperienceRoleManagementServiceBean implements ExperienceRoleManage
@Autowired
private ExperienceRoleRepository experienceRoleRepository;
@Autowired
private RoleManagementService roleManagementService;
/**
* Removes *all* assignments of roles for the given level
* @param level The level to remove the roles for
@@ -37,14 +43,35 @@ public class ExperienceRoleManagementServiceBean implements ExperienceRoleManage
@Override
public AExperienceRole getRoleInServer(ARole role) {
return this.getRoleInServerOptional(role).orElseThrow(AbstractoRunTimeException::new);
}
@Override
public Optional<AExperienceRole> getRoleInServerOptional(ARole role) {
return experienceRoleRepository.findByRole(role);
}
@Override
public AExperienceRole getRoleInServer(Long roleId) {
ARole role = roleManagementService.findRole(roleId);
return getRoleInServer(role);
}
@Override
public List<AExperienceRole> getExperienceRolesForServer(AServer server) {
return experienceRoleRepository.findByRoleServer(server);
}
@Override
public AExperienceRole getExperienceRoleById(Long experienceRoleId) {
return getExperienceRoleByIdOptional(experienceRoleId).orElseThrow(() -> new AbstractoRunTimeException("Experience role not found"));
}
@Override
public Optional<AExperienceRole> getExperienceRoleByIdOptional(Long experienceRoleId) {
return experienceRoleRepository.findById(experienceRoleId);
}
/**
* Creates a new role if nothing is found, and if its found the experience role will be set to the given level.
* @param level The {@link AExperienceLevel} to set the role for
@@ -53,18 +80,20 @@ public class ExperienceRoleManagementServiceBean implements ExperienceRoleManage
*/
@Override
public AExperienceRole setLevelToRole(AExperienceLevel level, ARole role) {
AExperienceRole byRoleServerAndRole = experienceRoleRepository.findByRole(role);
if(byRoleServerAndRole != null) {
byRoleServerAndRole.setLevel(level);
Optional<AExperienceRole> byRoleServerAndRoleOptional = getRoleInServerOptional(role);
AExperienceRole experienceRole;
if(byRoleServerAndRoleOptional.isPresent()) {
experienceRole = byRoleServerAndRoleOptional.get();
experienceRole.setLevel(level);
} else {
byRoleServerAndRole = AExperienceRole
experienceRole = AExperienceRole
.builder()
.level(level)
.roleServer(role.getServer())
.role(role)
.build();
byRoleServerAndRole = experienceRoleRepository.save(byRoleServerAndRole);
experienceRole = experienceRoleRepository.save(experienceRole);
}
return byRoleServerAndRole;
return experienceRole;
}
}

View File

@@ -51,7 +51,7 @@ public abstract class ExperienceRelatedTest {
for (int i = 0; i < levelsWithRoles.size(); i++) {
AExperienceLevel level = levelsWithRoles.get(i);
ARole role = ARole.builder().id((long)i).server(server).build();
roles.add(AExperienceRole.builder().level(level).roleServer(server).role(role).build());
roles.add(AExperienceRole.builder().level(level).id(role.getId()).roleServer(server).role(role).build());
}
return roles;
}

View File

@@ -9,6 +9,7 @@ import dev.sheldan.abstracto.experience.service.management.DisabledExpRoleManage
import dev.sheldan.abstracto.test.MockUtils;
import dev.sheldan.abstracto.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.test.command.CommandTestUtilities;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
@@ -20,6 +21,7 @@ import java.util.Arrays;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
@Slf4j
public class DisableExpForRoleTest {
@InjectMocks

View File

@@ -22,6 +22,7 @@ import org.mockito.junit.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import static org.mockito.Mockito.*;
@@ -45,7 +46,7 @@ public class LeaderBoardCommandTest {
@Test(expected = IncorrectParameterException.class)
public void testIncorrectParameterType() {
CommandTestUtilities.executeWrongParametersTest(testUnit);
CommandTestUtilities.executeWrongParametersTestAsync(testUnit);
}
@Test
@@ -68,9 +69,9 @@ public class LeaderBoardCommandTest {
when(converter.fromLeaderBoardEntry(executingUserRank)).thenReturn(leaderBoardEntryModel);
MessageToSend messageToSend = MessageToSend.builder().build();
when(templateService.renderEmbedTemplate(eq(LeaderBoardCommand.LEADER_BOARD_POST_EMBED_TEMPLATE), any(LeaderBoardModel.class))).thenReturn(messageToSend);
CommandResult result = testUnit.execute(context);
CompletableFuture<CommandResult> result = testUnit.executeAsync(context);
verify(channelService, times(1)).sendMessageToSendToChannel(messageToSend, context.getChannel());
CommandTestUtilities.checkSuccessfulCompletion(result);
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
}
@Test

View File

@@ -12,14 +12,17 @@ import dev.sheldan.abstracto.experience.service.management.DisabledExpRoleManage
import dev.sheldan.abstracto.test.MockUtils;
import dev.sheldan.abstracto.test.command.CommandConfigValidator;
import dev.sheldan.abstracto.test.command.CommandTestUtilities;
import net.dv8tion.jda.api.entities.Role;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import static org.mockito.Mockito.*;
@@ -43,11 +46,11 @@ public class ListDisabledExperienceRolesTest {
CommandContext context = CommandTestUtilities.getNoParameters();
AServer server = context.getUserInitiatedContext().getServer();
when(disabledExpRoleManagementService.getDisabledRolesForServer(server)).thenReturn(new ArrayList<>());
CommandResult result = testUnit.execute(context);
CommandTestUtilities.checkSuccessfulCompletion(result);
when(channelService.sendEmbedTemplateInChannel(eq("list_disabled_experience_roles"),
any(DisabledExperienceRolesModel.class), eq(context.getChannel()))).thenReturn(CommandTestUtilities.messageFutureList());
CompletableFuture<CommandResult> result = testUnit.executeAsync(context);
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
verify(roleService, times(0)).getRoleFromGuild(any(ARole.class));
verify(channelService, times(1)).sendEmbedTemplateInChannel(eq("list_disabled_experience_roles"),
any(DisabledExperienceRolesModel.class), eq(context.getChannel()));
}
@Test
@@ -57,11 +60,14 @@ public class ListDisabledExperienceRolesTest {
ADisabledExpRole disabledExpRole1 = ADisabledExpRole.builder().role(MockUtils.getRole(4L, server)).build();
ADisabledExpRole disabledExpRole2 = ADisabledExpRole.builder().role(MockUtils.getRole(6L, server)).build();
when(disabledExpRoleManagementService.getDisabledRolesForServer(server)).thenReturn(Arrays.asList(disabledExpRole1, disabledExpRole2));
CommandResult result = testUnit.execute(context);
CommandTestUtilities.checkSuccessfulCompletion(result);
verify(roleService, times(2)).getRoleFromGuild(any(ARole.class));
verify(channelService, times(1)).sendEmbedTemplateInChannel(eq("list_disabled_experience_roles"),
any(DisabledExperienceRolesModel.class), eq(context.getChannel()));
Role role1 = Mockito.mock(Role.class);
Role role2 = Mockito.mock(Role.class);
when(roleService.getRoleFromGuild(disabledExpRole1.getRole())).thenReturn(role1);
when(roleService.getRoleFromGuild(disabledExpRole2.getRole())).thenReturn(role2);
when(channelService.sendEmbedTemplateInChannel(eq("list_disabled_experience_roles"),
any(DisabledExperienceRolesModel.class), eq(context.getChannel()))).thenReturn(CommandTestUtilities.messageFutureList());
CompletableFuture<CommandResult> result = testUnit.executeAsync(context);
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
}
@Test

View File

@@ -22,6 +22,8 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.concurrent.CompletableFuture;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
@@ -59,9 +61,9 @@ public class RankTest {
when(experienceLevelService.calculateExperienceToNextLevel(currentLevelValue, currentExperience)).thenReturn(140L);
MessageToSend messageToSend = MessageToSend.builder().build();
when(templateService.renderEmbedTemplate(eq(Rank.RANK_POST_EMBED_TEMPLATE), any(RankModel.class))).thenReturn(messageToSend);
CommandResult result = testUnit.execute(context);
CompletableFuture<CommandResult> result = testUnit.executeAsync(context);
verify(channelService, Mockito.times(1)).sendMessageToSendToChannel(messageToSend, context.getChannel());
CommandTestUtilities.checkSuccessfulCompletion(result);
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
}
@Test

View File

@@ -18,6 +18,7 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import static org.mockito.Mockito.*;
@@ -35,24 +36,24 @@ public class SetExpRoleTest {
@Test(expected = InsufficientParametersException.class)
public void testTooLittleParameters() {
CommandTestUtilities.executeNoParametersTest(testUnit);
CommandTestUtilities.executeNoParametersTestAsync(testUnit);
}
@Test(expected = InsufficientParametersException.class)
public void testRoleMissing() {
CommandContext context = CommandTestUtilities.getWithParameters(Arrays.asList(4));
testUnit.execute(context);
testUnit.executeAsync(context);
}
@Test(expected = IncorrectParameterException.class)
public void testIncorrectParameterType() {
CommandTestUtilities.executeWrongParametersTest(testUnit);
CommandTestUtilities.executeWrongParametersTestAsync(testUnit);
}
@Test(expected = IncorrectParameterException.class)
public void testLevelProvidedButNotRole() {
CommandContext context = CommandTestUtilities.getWithParameters(Arrays.asList(4, ""));
testUnit.execute(context);
testUnit.executeAsync(context);
}
@Test
@@ -62,9 +63,9 @@ public class SetExpRoleTest {
Integer levelToSetTo = 4;
CommandContext context = CommandTestUtilities.enhanceWithParameters(noParameters, Arrays.asList(levelToSetTo, changedRole));
when(roleService.isRoleInServer(changedRole)).thenReturn(true);
CommandResult result = testUnit.execute(context);
CommandTestUtilities.checkSuccessfulCompletion(result);
verify(experienceRoleService, times(1)).setRoleToLevel(changedRole, levelToSetTo, context.getUserInitiatedContext().getChannel());
when(experienceRoleService.setRoleToLevel(changedRole, levelToSetTo, context.getUserInitiatedContext().getChannel())).thenReturn(CompletableFuture.completedFuture(null));
CompletableFuture<CommandResult> result = testUnit.executeAsync(context);
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
}
@Test(expected = RoleNotFoundInGuildException.class)
@@ -74,7 +75,7 @@ public class SetExpRoleTest {
Integer levelToSetTo = 4;
CommandContext context = CommandTestUtilities.enhanceWithParameters(noParameters, Arrays.asList(levelToSetTo, changedRole));
when(roleService.isRoleInServer(changedRole)).thenReturn(false);
testUnit.execute(context);
testUnit.executeAsync(context);
}
@Test

View File

@@ -13,6 +13,8 @@ import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.concurrent.CompletableFuture;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
@@ -27,11 +29,11 @@ public class SyncRolesTest {
@Test
public void executeCommand() {
CommandContext context = CommandTestUtilities.getNoParameters();
CommandResult result = testUnit.execute(context);
AServer server = context.getUserInitiatedContext().getServer();
AChannel channel = context.getUserInitiatedContext().getChannel();
verify(userExperienceService, times(1)).syncUserRolesWithFeedback(server, channel);
CommandTestUtilities.checkSuccessfulCompletion(result);
when(userExperienceService.syncUserRolesWithFeedback(server, channel)).thenReturn(CompletableFuture.completedFuture(null));
CompletableFuture<CommandResult> result = testUnit.executeAsync(context);
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
}
@Test

View File

@@ -16,9 +16,9 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
public class UnSetExpRoleTest {
@@ -31,12 +31,12 @@ public class UnSetExpRoleTest {
@Test(expected = InsufficientParametersException.class)
public void testTooLittleParameters() {
CommandTestUtilities.executeNoParametersTest(testUnit);
CommandTestUtilities.executeNoParametersTestAsync(testUnit);
}
@Test(expected = IncorrectParameterException.class)
public void testIncorrectParameterType() {
CommandTestUtilities.executeWrongParametersTest(testUnit);
CommandTestUtilities.executeWrongParametersTestAsync(testUnit);
}
@Test
@@ -44,9 +44,9 @@ public class UnSetExpRoleTest {
CommandContext noParameters = CommandTestUtilities.getNoParameters();
ARole changedRole = MockUtils.getRole(4L, noParameters.getUserInitiatedContext().getServer());
CommandContext context = CommandTestUtilities.enhanceWithParameters(noParameters, Arrays.asList(changedRole));
CommandResult result = testUnit.execute(context);
CommandTestUtilities.checkSuccessfulCompletion(result);
verify(experienceRoleService, times(1)).unsetRole(changedRole, context.getUserInitiatedContext().getChannel());
when(experienceRoleService.unsetRole(changedRole, context.getUserInitiatedContext().getChannel())).thenReturn(CompletableFuture.completedFuture(null));
CompletableFuture<CommandResult> result = testUnit.executeAsync(context);
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
}
@Test

View File

@@ -16,6 +16,8 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.concurrent.CompletableFuture;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
@@ -41,8 +43,8 @@ public class JoiningUserRoleListenerTest extends ExperienceRelatedTest {
Guild guild = Mockito.mock(Guild.class);
AUserExperience experience = AUserExperience.builder().experience(3L).user(aUserInAServer).build();
when(userExperienceManagementService.findUserInServer(aUserInAServer)).thenReturn(experience);
when(userExperienceService.syncForSingleUser(experience)).thenReturn(CompletableFuture.completedFuture(null));
testUnit.execute(member, guild, aUserInAServer);
verify(userExperienceService, times(1)).syncForSingleUser(experience);
}
@Test

View File

@@ -10,6 +10,7 @@ import dev.sheldan.abstracto.experience.ExperienceRelatedTest;
import dev.sheldan.abstracto.experience.config.features.ExperienceFeatureConfig;
import dev.sheldan.abstracto.experience.models.LeaderBoard;
import dev.sheldan.abstracto.experience.models.LeaderBoardEntry;
import dev.sheldan.abstracto.experience.models.RoleCalculationResult;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import dev.sheldan.abstracto.experience.models.database.AExperienceRole;
import dev.sheldan.abstracto.experience.models.database.AUserExperience;
@@ -77,11 +78,14 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
@Captor
private ArgumentCaptor<AUserExperience> aUserExperienceArgumentCaptor;
@Mock
private AUserExperienceServiceBean self;
@Test
public void testCalculateLevelTooLow() {
AUserExperience experienceToCalculate = AUserExperience.builder().experience(50L).build();
List<AExperienceLevel> levels = getLevelConfiguration();
AExperienceLevel calculatedLevel = testUnit.calculateLevel(experienceToCalculate, levels);
AExperienceLevel calculatedLevel = testUnit.calculateLevel(levels, experienceToCalculate.getExperience());
Assert.assertEquals(0, calculatedLevel.getLevel().intValue());
}
@@ -89,7 +93,7 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
public void testCalculateLevelBetweenLevels() {
AUserExperience experienceToCalculate = AUserExperience.builder().experience(250L).build();
List<AExperienceLevel> levels = getLevelConfiguration();
AExperienceLevel calculatedLevel = testUnit.calculateLevel(experienceToCalculate, levels);
AExperienceLevel calculatedLevel = testUnit.calculateLevel(levels, experienceToCalculate.getExperience());
Assert.assertEquals(2, calculatedLevel.getLevel().intValue());
}
@@ -97,7 +101,7 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
public void testCalculateLevelTooHigh() {
AUserExperience experienceToCalculate = AUserExperience.builder().experience(500L).build();
List<AExperienceLevel> levels = getLevelConfiguration();
AExperienceLevel calculatedLevel = testUnit.calculateLevel(experienceToCalculate, levels);
AExperienceLevel calculatedLevel = testUnit.calculateLevel(levels, experienceToCalculate.getExperience());
Assert.assertEquals(3, calculatedLevel.getLevel().intValue());
}
@@ -106,7 +110,7 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
List<AExperienceLevel> levels = getLevelConfiguration();
AUserInAServer userObject = MockUtils.getUserObject(2L, MockUtils.getServer());
AUserExperience experienceToCalculate = AUserExperience.builder().user(userObject).currentLevel(levels.get(1)).experience(250L).build();
Assert.assertTrue(testUnit.updateUserLevel(experienceToCalculate, levels));
Assert.assertTrue(testUnit.updateUserLevel(experienceToCalculate, levels, experienceToCalculate.getExperience()));
}
@Test
@@ -114,7 +118,7 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
List<AExperienceLevel> levels = getLevelConfiguration();
AUserInAServer userObject = MockUtils.getUserObject(2L, MockUtils.getServer());
AUserExperience experienceToCalculate = AUserExperience.builder().user(userObject).currentLevel(levels.get(2)).experience(250L).build();
Assert.assertFalse(testUnit.updateUserLevel(experienceToCalculate, levels));
Assert.assertFalse(testUnit.updateUserLevel(experienceToCalculate, levels, experienceToCalculate.getExperience()));
}
@Test
@@ -126,9 +130,8 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
AUserInAServer userToUse = serverToUse.getUsers().get(0);
AExperienceRole previousExperienceRole = experienceRoles.get(1);
when(botService.isUserInGuild(userToUse)).thenReturn(true);
AExperienceRole newAwardedRole = testRoleRelatedScenario(false, levels, servers, serverToUse, experienceRoles, userToUse, previousExperienceRole);
verify(roleService, times(1)).addRoleToUser(userToUse, newAwardedRole.getRole());
verify(roleService, times(1)).removeRoleFromUser(userToUse, previousExperienceRole.getRole());
testRoleRelatedScenario(levels, servers, serverToUse, experienceRoles, userToUse, previousExperienceRole);
verify(roleService, times(1)).removeRoleFromUserFuture(userToUse, previousExperienceRole.getRole());
}
@Test
@@ -139,7 +142,7 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
List<AExperienceRole> experienceRoles = getExperienceRoles(levels, serverToUse);
AUserInAServer userToUse = serverToUse.getUsers().get(0);
AExperienceRole previousExperienceRole = experienceRoles.get(1);
AExperienceRole newAwardedRole = testRoleRelatedScenario(true, levels, servers, serverToUse, experienceRoles, userToUse, previousExperienceRole);
AExperienceRole newAwardedRole = testRoleRelatedScenario(levels, servers, serverToUse, experienceRoles, userToUse, previousExperienceRole);
verify(roleService, times(0)).addRoleToUser(userToUse, newAwardedRole.getRole());
verify(roleService, times(0)).removeRoleFromUser(userToUse, previousExperienceRole.getRole());
}
@@ -153,20 +156,14 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
levels.add(AExperienceLevel.builder().level(4).experienceNeeded(400L).build());
mockSimpleServer(levels, experienceRoles, serverToUse);
AUserInAServer userToUse = serverToUse.getUsers().get(0);
Member jdaMember = Mockito.mock(Member.class);
when(botService.getMemberInServer(serverToUse, userToUse.getUserReference())).thenReturn(jdaMember);
AExperienceRole previousExperienceRole = experienceRoles.get(3);
AUserExperience newUserExperience = mockServerWithSingleUser(levels, serverToUse, 401L, 3, previousExperienceRole, false);
AExperienceRole newAwardedRole = experienceRoles.get(3);
when(experienceRoleService.calculateRole(newUserExperience, experienceRoles)).thenReturn(newAwardedRole);
when(roleService.memberHasRole(jdaMember, newAwardedRole.getRole())).thenReturn(true);
when(userExperienceManagementService.findUserInServer(userToUse)).thenReturn(newUserExperience);
testUnit.handleExperienceGain(servers);
verify(userExperienceManagementService, times(1)).saveUser(eq(newUserExperience));
verify(roleService, times(0)).removeRoleFromUser(userToUse, previousExperienceRole.getRole());
verify(roleService, times(0)).addRoleToUser(userToUse, newAwardedRole.getRole());
Assert.assertEquals(4, newUserExperience.getCurrentLevel().getLevel().intValue());
Assert.assertEquals(3L, newUserExperience.getCurrentExperienceRole().getRole().getId().longValue());
}
@Test
@@ -177,15 +174,9 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
List<AExperienceRole> experienceRoles = getExperienceRoles(levels, serverToUse);
mockSimpleServer(levels, experienceRoles, serverToUse);
AUserInAServer userToUse = serverToUse.getUsers().get(0);
Member jdaMember = Mockito.mock(Member.class);
when(botService.getMemberInServer(serverToUse, userToUse.getUserReference())).thenReturn(jdaMember);
AUserExperience newUserExperience = mockServerWithSingleUser(levels, serverToUse, 101L, 1, null, false);
when(experienceRoleService.calculateRole(newUserExperience, experienceRoles)).thenReturn(experienceRoles.get(1));
when(userExperienceManagementService.findUserInServer(userToUse)).thenReturn(newUserExperience);
testUnit.handleExperienceGain(servers);
verify(userExperienceManagementService, times(1)).saveUser(eq(newUserExperience));
Assert.assertEquals(1, newUserExperience.getCurrentLevel().getLevel().intValue());
Assert.assertEquals(1L, newUserExperience.getCurrentExperienceRole().getRole().getId().longValue());
}
@Test
@@ -196,13 +187,10 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
List<AExperienceRole> experienceRoles = getExperienceRoles(levels, serverToUse);
mockSimpleServer(levels, experienceRoles, serverToUse);
AUserInAServer userToUse = serverToUse.getUsers().get(0);
Member jdaMember = Mockito.mock(Member.class);
when(botService.getMemberInServer(serverToUse, userToUse.getUserReference())).thenReturn(jdaMember);
AUserExperience newUserExperience = mockServerWithSingleUser(levels, serverToUse, 50L, 0, null, false);
when(experienceRoleService.calculateRole(newUserExperience, experienceRoles)).thenReturn(null);
when(userExperienceManagementService.findUserInServer(userToUse)).thenReturn(newUserExperience);
testUnit.handleExperienceGain(servers);
verify(userExperienceManagementService, times(1)).saveUser(eq(newUserExperience));
Assert.assertEquals(0, newUserExperience.getCurrentLevel().getLevel().intValue());
Assert.assertNull(newUserExperience.getCurrentExperienceRole());
}
@@ -219,14 +207,12 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
when(botService.getMemberInServer(serverToUse, userToUse.getUserReference())).thenReturn(jdaMember);
AUserExperience newUserExperience = mockServerWithSingleUser(levels, serverToUse, 50L, 0, experienceRoles.get(0), false);
when(experienceRoleService.calculateRole(newUserExperience, experienceRoles)).thenReturn(null);
when(botService.isUserInGuild(userToUse)).thenReturn(true);
when(userExperienceManagementService.findUserInServer(userToUse)).thenReturn(newUserExperience);
when(roleService.removeRoleFromUserFuture(newUserExperience.getUser(), newUserExperience.getCurrentExperienceRole().getRole())).thenReturn(CompletableFuture.completedFuture(null));
testUnit.handleExperienceGain(servers);
verify(userExperienceManagementService, times(1)).saveUser(eq(newUserExperience));
verify(roleService, times(1)).removeRoleFromUser(userToUse, experienceRoles.get(0).getRole());
verify(roleService, times(0)).addRoleToUser(eq(userToUse), any(ARole.class));
Assert.assertEquals(0, newUserExperience.getCurrentLevel().getLevel().intValue());
Assert.assertNull(newUserExperience.getCurrentExperienceRole());
verify(roleService, times(1)).removeRoleFromUserFuture(userToUse, experienceRoles.get(0).getRole());
verify(roleService, times(0)).addRoleToUserFuture(eq(userToUse), any(ARole.class));
}
@Test
@@ -238,7 +224,7 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
mockSimpleServer(levels, experienceRoles, serverToUse);
AUserInAServer userToUse = serverToUse.getUsers().get(0);
AUserExperience newUserExperience = mockServerWithSingleUser(levels, serverToUse, 50L, 0, experienceRoles.get(0), true);
when(userExperienceManagementService.findUserInServer(userToUse)).thenReturn(newUserExperience);
testUnit.handleExperienceGain(servers);
verify(userExperienceManagementService, times(0)).saveUser(eq(newUserExperience));
verify(roleService, times(0)).removeRoleFromUser(userToUse, experienceRoles.get(0).getRole());
@@ -275,16 +261,12 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
List<AExperienceRole> experienceRoles = getExperienceRoles(levels, serverToUse);
mockSimpleServer(levels, experienceRoles, serverToUse);
AUserInAServer userToUse = serverToUse.getUsers().get(0);
Member jdaMember = Mockito.mock(Member.class);
when(botService.getMemberInServer(serverToUse, userToUse.getUserReference())).thenReturn(jdaMember);
AUserExperience newUserExperience = mockServerWithSingleUser(levels, serverToUse, 101L, 1, experienceRoles.get(1), false);
when(experienceRoleService.calculateRole(newUserExperience, experienceRoles)).thenReturn(experienceRoles.get(1));
testUnit.handleExperienceGain(servers);
verify(userExperienceManagementService, times(1)).saveUser(eq(newUserExperience));
when(userExperienceManagementService.findUserInServer(userToUse)).thenReturn(newUserExperience);
CompletableFuture<Void> future = testUnit.handleExperienceGain(servers);
future.join();
verify(roleService, times(0)).removeRoleFromUser(userToUse, experienceRoles.get(0).getRole());
verify(roleService, times(0)).addRoleToUser(eq(userToUse), any(ARole.class));
Assert.assertEquals(1, newUserExperience.getCurrentLevel().getLevel().intValue());
Assert.assertEquals(experienceRoles.get(1).getRole().getId(), newUserExperience.getCurrentExperienceRole().getRole().getId());
}
@Test
@@ -304,27 +286,19 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
List<AExperienceRole> experienceRoles = getExperienceRoles(levels, aServer);
mockSimpleServer(levels, experienceRoles, aServer);
AUserInAServer userToUse = aServer.getUsers().get(0);
Member jdaMember = Mockito.mock(Member.class);
when(botService.getMemberInServer(aServer, userToUse.getUserReference())).thenReturn(jdaMember);
AExperienceRole role = experienceRoles.get(experienceRoleIndices.get(i));
AUserExperience newUserExperience = mockServerWithSingleUser(levels, aServer, experienceValues, level, role, false);
when(experienceRoleService.calculateRole(newUserExperience, experienceRoles)).thenReturn(role);
when(userExperienceManagementService.findUserInServer(userToUse)).thenReturn(newUserExperience);
userExperiences.add(newUserExperience);
allExperienceRoles.add(experienceRoles);
}
testUnit.handleExperienceGain(servers);
List<Integer> newLevels = Arrays.asList(1,3);
List<Integer> newExperienceRoleIndices = Arrays.asList(1, 2);
for (int i = 0; i < servers.size(); i++) {
AServer server = servers.get(i);
AUserExperience newUserExperience = userExperiences.get(i);
AUserInAServer userToUse = server.getUsers().get(0);
List<AExperienceRole> experienceRoles = allExperienceRoles.get(i);
verify(userExperienceManagementService, times(2)).saveUser(aUserExperienceArgumentCaptor.capture());
verify(roleService, times(0)).removeRoleFromUser(userToUse, experienceRoles.get(0).getRole());
verify(roleService, times(0)).addRoleToUser(eq(userToUse), any(ARole.class));
Assert.assertEquals(newLevels.get(i).intValue(), newUserExperience.getCurrentLevel().getLevel().intValue());
Assert.assertEquals(experienceRoles.get(newExperienceRoleIndices.get(i)).getRole().getId(), newUserExperience.getCurrentExperienceRole().getRole().getId());
}
}
@@ -336,7 +310,7 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
AExperienceRole afterRole = usedExperienceRoles.get(0);
Integer removals = 0;
Integer adds = 1;
executeSyncSingleUserTest(server, usedExperienceRoles, previousRole, afterRole, removals, adds);
executeSyncSingleUserTest(server, usedExperienceRoles, previousRole, afterRole);
}
@Test
@@ -347,7 +321,7 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
AExperienceRole afterRole = null;
Integer removals = 1;
Integer adds = 0;
executeSyncSingleUserTest(server, usedExperienceRoles, previousRole, afterRole, removals, adds);
executeSyncSingleUserTest(server, usedExperienceRoles, previousRole, afterRole);
}
@Test
@@ -358,7 +332,7 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
AExperienceRole afterRole = usedExperienceRoles.get(0);
Integer removals = 0;
Integer adds = 0;
executeSyncSingleUserTest(server, usedExperienceRoles, previousRole, afterRole, removals, adds);
executeSyncSingleUserTest(server, usedExperienceRoles, previousRole, afterRole);
}
@Test
@@ -369,7 +343,7 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
AExperienceRole afterRole = usedExperienceRoles.get(1);
Integer removals = 1;
Integer adds = 1;
executeSyncSingleUserTest(server, usedExperienceRoles, previousRole, afterRole, removals, adds);
executeSyncSingleUserTest(server, usedExperienceRoles, previousRole, afterRole);
}
@Test
@@ -438,7 +412,8 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
AExperienceRole secondPreviousRole = null;
AExperienceRole secondAfterRole = null;
AExperienceLevel level0 = AExperienceLevel.builder().level(0).build();
AUserExperience experience = AUserExperience.builder().experience(40L).user(MockUtils.getUserObject(3L, server)).currentLevel(level0).build();
AExperienceLevel level1 = AExperienceLevel.builder().level(1).build();
AUserExperience experience = AUserExperience.builder().experience(40L).user(MockUtils.getUserObject(3L, server)).currentLevel(level1).build();
AUserExperience experience2 = AUserExperience.builder().experience(201L).user(MockUtils.getUserObject(4L, server)).currentLevel(level0).build();
List<AUserExperience> experiences = Arrays.asList(experience, experience2);
@@ -451,15 +426,19 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
experience2.setCurrentExperienceRole(secondPreviousRole);
when(userExperienceManagementService.loadAllUsers(server)).thenReturn(experiences);
when(experienceRoleManagementService.getExperienceRolesForServer(server)).thenReturn(usedExperienceRoles);
when(experienceRoleService.calculateRole(experience, usedExperienceRoles)).thenReturn(firstAfterRole);
when(experienceRoleService.calculateRole(experience2, usedExperienceRoles)).thenReturn(secondAfterRole);
when(experienceRoleService.calculateRole(usedExperienceRoles, experience.getLevelOrDefault())).thenReturn(firstAfterRole);
when(experienceRoleService.calculateRole(usedExperienceRoles, experience2.getLevelOrDefault())).thenReturn(secondAfterRole);
when(botService.getMemberInServer(server, experience.getUser().getUserReference())).thenReturn(firstMember);
when(botService.getMemberInServer(server, experience2.getUser().getUserReference())).thenReturn(secondMember);
when(botService.isUserInGuild(experience.getUser())).thenReturn(true);
when(botService.isUserInGuild(experience2.getUser())).thenReturn(true);
when(roleService.addRoleToUserFuture(experience.getUser(), firstAfterRole.getRole())).thenReturn(CompletableFuture.completedFuture(null));
when(roleService.memberHasRole(firstMember, firstAfterRole.getRole())).thenReturn(false);
testUnit.syncUserRoles(server);
Assert.assertNull(experience2.getCurrentExperienceRole());
Assert.assertEquals(usedExperienceRoles.get(0).getRole().getId(), experience.getCurrentExperienceRole().getRole().getId());
verify(roleService, times(1)).addRoleToUser(users.get(0), usedExperienceRoles.get(0).getRole());
List<CompletableFuture<RoleCalculationResult>> futures = testUnit.syncUserRoles(server);
RoleCalculationResult result = futures.get(0).join();
RoleCalculationResult result2 = futures.get(1).join();
Assert.assertEquals(firstAfterRole.getRole().getId(), result.getExperienceRoleId());
Assert.assertNull(result2.getExperienceRoleId());
}
@Test
@@ -547,7 +526,7 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
verify(messageService, times(messageCount)).updateStatusMessage(channel, messageId, statusMessage);
}
private void executeSyncSingleUserTest(AServer server, List<AExperienceRole> usedExperienceRoles, AExperienceRole previousRole, AExperienceRole afterRole, Integer removals, Integer adds) {
private void executeSyncSingleUserTest(AServer server, List<AExperienceRole> usedExperienceRoles, AExperienceRole previousRole, AExperienceRole afterRole) {
AExperienceLevel level0 = AExperienceLevel.builder().level(0).build();
AUserExperience experience = AUserExperience.builder().experience(40L).user(MockUtils.getUserObject(3L, server)).currentLevel(level0).build();
List<AUserExperience> experiences = Arrays.asList(experience);
@@ -557,26 +536,25 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
when(botService.getMemberInServer(server, users.get(0).getUserReference())).thenReturn(firstMember);
experience.setCurrentExperienceRole(previousRole);
when(experienceRoleManagementService.getExperienceRolesForServer(server)).thenReturn(usedExperienceRoles);
when(experienceRoleService.calculateRole(experience, usedExperienceRoles)).thenReturn(afterRole);
when(experienceRoleService.calculateRole(usedExperienceRoles, experience.getLevelOrDefault())).thenReturn(afterRole);
when(botService.getMemberInServer(server, experience.getUser().getUserReference())).thenReturn(firstMember);
if(removals > 0) {
users.forEach(aUserInAServer -> when(botService.isUserInGuild(aUserInAServer)).thenReturn(true));
users.forEach(aUserInAServer -> when(botService.isUserInGuild(aUserInAServer)).thenReturn(true));
if(afterRole != null) {
when(roleService.addRoleToUserFuture(experience.getUser(), afterRole.getRole())).thenReturn(CompletableFuture.completedFuture(null));
}
if(previousRole != null) {
when(roleService.removeRoleFromUserFuture(experience.getUser(), previousRole.getRole())).thenReturn(CompletableFuture.completedFuture(null));
}
if(afterRole != null && previousRole != null) {
boolean sameRole = previousRole.getRole().getId().equals(afterRole.getRole().getId());
when(roleService.memberHasRole(firstMember, afterRole.getRole())).thenReturn(sameRole);
}
testUnit.syncForSingleUser(experience);
CompletableFuture<RoleCalculationResult> calculationFuture = testUnit.syncForSingleUser(experience);
RoleCalculationResult result = calculationFuture.join();
if(afterRole != null) {
Assert.assertEquals(afterRole.getRole().getId(), experience.getCurrentExperienceRole().getRole().getId());
Assert.assertEquals(afterRole.getRole().getId(), result.getExperienceRoleId());
} else {
Assert.assertNull(experience.getCurrentExperienceRole());
}
if(previousRole != null) {
verify(roleService, times(removals)).removeRoleFromUser(experience.getUser(), previousRole.getRole());
}
if(afterRole != null) {
verify(roleService, times(adds)).addRoleToUser(experience.getUser(), afterRole.getRole());
Assert.assertNull(result.getExperienceRoleId());
}
}
@@ -597,19 +575,16 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
Assert.assertEquals(pageSize, entries.size());
}
private AExperienceRole testRoleRelatedScenario(boolean shouldHaveRole, List<AExperienceLevel> levels, List<AServer> servers, AServer serverToUse, List<AExperienceRole> experienceRoles, AUserInAServer userToUse, AExperienceRole previousExperienceRole) {
private AExperienceRole testRoleRelatedScenario(List<AExperienceLevel> levels, List<AServer> servers, AServer serverToUse, List<AExperienceRole> experienceRoles, AUserInAServer userToUse, AExperienceRole previousExperienceRole) {
mockSimpleServer(levels, experienceRoles, serverToUse);
Member jdaMember = Mockito.mock(Member.class);
when(botService.getMemberInServer(serverToUse, userToUse.getUserReference())).thenReturn(jdaMember);
AUserExperience newUserExperience = mockServerWithSingleUser(levels, serverToUse, 301L, 1, previousExperienceRole, false);
AExperienceRole newAwardedRole = experienceRoles.get(3);
when(experienceRoleService.calculateRole(newUserExperience, experienceRoles)).thenReturn(newAwardedRole);
when(roleService.memberHasRole(jdaMember, newAwardedRole.getRole())).thenReturn(shouldHaveRole);
testUnit.handleExperienceGain(servers);
verify(userExperienceManagementService, times(1)).saveUser(eq(newUserExperience));
Assert.assertEquals(3, newUserExperience.getCurrentLevel().getLevel().intValue());
Assert.assertEquals(3L, newUserExperience.getCurrentExperienceRole().getRole().getId().longValue());
when(roleService.removeRoleFromUserFuture(newUserExperience.getUser(), newUserExperience.getCurrentExperienceRole().getRole())).thenReturn(CompletableFuture.completedFuture(null));
when(userExperienceManagementService.findUserInServer(userToUse)).thenReturn(newUserExperience);
testUnit.handleExperienceGain(servers).join();
return newAwardedRole;
}
@@ -624,9 +599,7 @@ public class AUserExperienceServiceBeanTest extends ExperienceRelatedTest {
}
private AUserExperience mockUser(Long experience, AExperienceLevel currentLevel, AUserInAServer firstUser, boolean hasExpDisabled, AExperienceRole currentRole) {
AUserExperience newUserExperience = AUserExperience.builder().currentLevel(currentLevel).experience(experience).user(firstUser).experienceGainDisabled(hasExpDisabled).currentExperienceRole(currentRole).build();
when(userExperienceManagementService.incrementExpForUser(eq(firstUser), anyLong(), anyLong())).thenReturn(newUserExperience);
return newUserExperience;
return AUserExperience.builder().currentLevel(currentLevel).experience(experience).user(firstUser).experienceGainDisabled(hasExpDisabled).currentExperienceRole(currentRole).messageCount(0L).build();
}
private void mockSimpleServer(List<AExperienceLevel> levels, List<AExperienceRole> experienceRoles, AServer server) {

View File

@@ -4,7 +4,10 @@ import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AChannelType;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
import dev.sheldan.abstracto.experience.ExperienceRelatedTest;
import dev.sheldan.abstracto.experience.models.RoleCalculationResult;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import dev.sheldan.abstracto.experience.models.database.AExperienceRole;
import dev.sheldan.abstracto.experience.models.database.AUserExperience;
@@ -22,6 +25,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import static org.mockito.Mockito.*;
@@ -40,6 +44,12 @@ public class ExperienceRoleServiceBeanTest extends ExperienceRelatedTest {
@Mock
private AUserExperienceService userExperienceService;
@Mock
private RoleManagementService roleManagementService;
@Mock
private ExperienceRoleServiceBean self;
@Test
public void testSettingRoleToLevelWithoutOldUsers() {
@@ -48,10 +58,23 @@ public class ExperienceRoleServiceBeanTest extends ExperienceRelatedTest {
AExperienceLevel level = AExperienceLevel.builder().experienceNeeded(10L).level(levelCount).build();
ARole roleToChange = getRole(1L, server);
AExperienceRole previousExperienceRole = AExperienceRole.builder().role(roleToChange).roleServer(server).level(level).build();
when(experienceRoleManagementService.getRoleInServer(roleToChange)).thenReturn(previousExperienceRole);
when(experienceLevelService.getLevel(levelCount)).thenReturn(Optional.of(level));
testingUnit.setRoleToLevel(roleToChange, levelCount, getFeedbackChannel(server));
when(experienceRoleManagementService.getRoleInServerOptional(roleToChange)).thenReturn(Optional.of(previousExperienceRole));
CompletableFuture<Void> future = testingUnit.setRoleToLevel(roleToChange, levelCount, getFeedbackChannel(server));
future.join();
verify(experienceRoleManagementService, times(1)).unsetRole(previousExperienceRole);
}
@Test
public void testUnsetRoleInDb() {
AServer server = MockUtils.getServer();
Integer levelCount = 10;
AExperienceLevel level = AExperienceLevel.builder().experienceNeeded(10L).level(levelCount).build();
ARole roleToChange = getRole(1L, server);
when(experienceLevelService.getLevel(levelCount)).thenReturn(Optional.of(level));
when(roleManagementService.findRole(roleToChange.getId())).thenReturn(roleToChange);
testingUnit.unsetRoleInDb(levelCount, roleToChange.getId());
verify(experienceRoleManagementService, times(1)).removeAllRoleAssignmentsForLevelInServer(level, server);
verify(experienceRoleManagementService, times(1)).setLevelToRole(level, roleToChange);
verify(experienceRoleManagementService, times(0)).getExperienceRolesForServer(server);
@@ -70,23 +93,23 @@ public class ExperienceRoleServiceBeanTest extends ExperienceRelatedTest {
List<AUserExperience> users = Arrays.asList(firstUser, secondUser);
AExperienceRole previousExperienceRole = AExperienceRole.builder().role(roleToChange).id(roleToChange.getId()).roleServer(server).level(level).users(users).build();
AExperienceRole newExperienceRole = AExperienceRole.builder().role(newRoleToAward).id(newRoleToAward.getId()).roleServer(server).level(level).build();
when(experienceRoleManagementService.getRoleInServer(roleToChange)).thenReturn(previousExperienceRole);
when(experienceLevelService.getLevel(levelCount)).thenReturn(Optional.of(level));
when(experienceRoleManagementService.getRoleInServerOptional(roleToChange)).thenReturn(Optional.of(previousExperienceRole));
when(experienceRoleManagementService.getExperienceRolesForServer(server)).thenReturn(new ArrayList<>(Arrays.asList(newExperienceRole, previousExperienceRole)));
AChannel feedBackChannel = getFeedbackChannel(server);
testingUnit.setRoleToLevel(roleToChange, levelCount, feedBackChannel);
verify(experienceRoleManagementService, times(1)).unsetRole(previousExperienceRole);
verify(experienceRoleManagementService, times(1)).removeAllRoleAssignmentsForLevelInServer(level, server);
verify(experienceRoleManagementService, times(1)).setLevelToRole(level, roleToChange);
verify(experienceRoleManagementService, times(1)).getExperienceRolesForServer(server);
verify(userExperienceService, times(1)).executeActionOnUserExperiencesWithFeedBack(eq(users), eq(feedBackChannel), any());
List<CompletableFuture<RoleCalculationResult>> futures = new ArrayList<>();
futures.add(CompletableFuture.completedFuture(null));
CompletableFutureList<RoleCalculationResult> futuresList = new CompletableFutureList<>(futures);
when(userExperienceService.executeActionOnUserExperiencesWithFeedBack(eq(users), eq(feedBackChannel), any())).thenReturn(futuresList);
CompletableFuture<Void> future = testingUnit.setRoleToLevel(roleToChange, levelCount, feedBackChannel);
future.join();
verify(experienceRoleManagementService, times(0)).unsetRole(previousExperienceRole);
}
@Test
public void testCalculateRoleForLevelInBetween() {
List<AExperienceRole> roles = getExperienceRoles();
AUserExperience userExperience = AUserExperience.builder().currentLevel(AExperienceLevel.builder().level(6).build()).build();
AExperienceRole aExperienceRole = testingUnit.calculateRole(userExperience, roles);
AExperienceRole aExperienceRole = testingUnit.calculateRole(roles, userExperience.getLevelOrDefault());
Assert.assertEquals(aExperienceRole.getLevel().getLevel().intValue(), 5);
}
@@ -94,7 +117,7 @@ public class ExperienceRoleServiceBeanTest extends ExperienceRelatedTest {
public void testCalculateRoleForLevelBelow() {
List<AExperienceRole> roles = getExperienceRoles();
AUserExperience userExperience = AUserExperience.builder().currentLevel(AExperienceLevel.builder().level(4).build()).build();
AExperienceRole aExperienceRole = testingUnit.calculateRole(userExperience, roles);
AExperienceRole aExperienceRole = testingUnit.calculateRole(roles, userExperience.getLevelOrDefault());
Assert.assertNull(aExperienceRole);
}
@@ -102,7 +125,7 @@ public class ExperienceRoleServiceBeanTest extends ExperienceRelatedTest {
public void testCalculateRoleForLevelOver() {
List<AExperienceRole> roles = getExperienceRoles();
AUserExperience userExperience = AUserExperience.builder().currentLevel(AExperienceLevel.builder().level(11).build()).build();
AExperienceRole aExperienceRole = testingUnit.calculateRole(userExperience, roles);
AExperienceRole aExperienceRole = testingUnit.calculateRole(roles, userExperience.getLevelOrDefault());
Assert.assertEquals(aExperienceRole.getLevel().getLevel().intValue(), 10);
}
@@ -110,7 +133,7 @@ public class ExperienceRoleServiceBeanTest extends ExperienceRelatedTest {
public void testCalculateRoleForLevelExact() {
List<AExperienceRole> roles = getExperienceRoles();
AUserExperience userExperience = AUserExperience.builder().currentLevel(AExperienceLevel.builder().level(10).build()).build();
AExperienceRole aExperienceRole = testingUnit.calculateRole(userExperience, roles);
AExperienceRole aExperienceRole = testingUnit.calculateRole(roles, userExperience.getLevelOrDefault());
Assert.assertEquals(aExperienceRole.getLevel().getLevel().intValue(), 10);
}
@@ -118,7 +141,7 @@ public class ExperienceRoleServiceBeanTest extends ExperienceRelatedTest {
public void testCalculateRoleForNoRoleConfigFound() {
List<AExperienceRole> roles = new ArrayList<>();
AUserExperience userExperience = AUserExperience.builder().currentLevel(AExperienceLevel.builder().level(6).build()).build();
AExperienceRole aExperienceRole = testingUnit.calculateRole(userExperience, roles);
AExperienceRole aExperienceRole = testingUnit.calculateRole(roles, userExperience.getLevelOrDefault());
Assert.assertNull(aExperienceRole);
}

View File

@@ -19,6 +19,7 @@ import org.mockito.junit.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
@@ -77,7 +78,7 @@ public class ExperienceRoleManagementServiceBeanTest extends ExperienceRelatedTe
@Test
public void testFindExperienceRoleForRoleInServer() {
AExperienceRole expRole = getExperienceRoleForLevel(37);
when((experienceRoleRepository.findByRole(expRole.getRole()))).thenReturn(expRole);
when((experienceRoleRepository.findByRole(expRole.getRole()))).thenReturn(Optional.of(expRole));
AExperienceRole roleInServer = testUnit.getRoleInServer(expRole.getRole());
Assert.assertEquals(expRole.getRole().getId(), roleInServer.getRole().getId());
verify(experienceRoleRepository, times(1)).findByRole(expRole.getRole());
@@ -104,7 +105,7 @@ public class ExperienceRoleManagementServiceBeanTest extends ExperienceRelatedTe
public void setLevelToRoleWhichHasAnExistingMapping() {
int level = 5;
AExperienceRole experienceRole = getExperienceRoleForLevel(level);
when(experienceRoleRepository.findByRole(experienceRole.getRole())).thenReturn(experienceRole);
when(experienceRoleRepository.findByRole(experienceRole.getRole())).thenReturn(Optional.of(experienceRole));
AExperienceLevel newLevel = AExperienceLevel.builder().level(8).build();
AExperienceRole updatedExperienceRole = testUnit.setLevelToRole(newLevel, experienceRole.getRole());
verify(experienceRoleRepository, times(1)).findByRole(experienceRole.getRole());
@@ -115,7 +116,7 @@ public class ExperienceRoleManagementServiceBeanTest extends ExperienceRelatedTe
public void setLevelToRoleWithoutAMappingExistingPreviously() {
int level = 5;
AExperienceRole experienceRole = getExperienceRoleForLevel(level);
when(experienceRoleRepository.findByRole(experienceRole.getRole())).thenReturn(null);
when(experienceRoleRepository.findByRole(experienceRole.getRole())).thenReturn(Optional.empty());
when(experienceRoleRepository.save(any(AExperienceRole.class))).thenReturn(experienceRole);
AExperienceLevel newLevel = AExperienceLevel.builder().level(8).build();
AExperienceRole updatedExperienceRole = testUnit.setLevelToRole(newLevel, experienceRole.getRole());