mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-03 16:27:53 +00:00
[AB-25] refactoring experience collection to work instantly instead of delayed job
adding level up notification for experience
This commit is contained in:
@@ -10,8 +10,6 @@ import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.service.RoleService;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import dev.sheldan.abstracto.experience.config.ExperienceFeatureDefinition;
|
||||
import dev.sheldan.abstracto.experience.service.ExperienceRoleService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -34,12 +32,6 @@ public class SetExpRole extends AbstractConditionableCommand {
|
||||
@Autowired
|
||||
private ExperienceRoleService experienceRoleService;
|
||||
|
||||
@Autowired
|
||||
private RoleService roleService;
|
||||
|
||||
@Autowired
|
||||
private RoleManagementService roleManagementService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
Integer level = (Integer) commandContext.getParameters().getParameters().get(0);
|
||||
@@ -48,7 +40,7 @@ public class SetExpRole extends AbstractConditionableCommand {
|
||||
throw new EntityGuildMismatchException();
|
||||
}
|
||||
log.info("Setting role {} to be used for level {} on server {}", role.getId(), level, role.getGuild().getId());
|
||||
return experienceRoleService.setRoleToLevel(role, level, commandContext.getChannel().getIdLong())
|
||||
return experienceRoleService.setRoleToLevel(role, level, commandContext.getChannel())
|
||||
.thenApply(aVoid -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@@ -56,8 +48,21 @@ public class SetExpRole extends AbstractConditionableCommand {
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
List<ParameterValidator> levelValidators = Arrays.asList(MinIntegerValueValidator.min(0L));
|
||||
parameters.add(Parameter.builder().name("level").validators(levelValidators).templated(true).type(Integer.class).build());
|
||||
parameters.add(Parameter.builder().name("role").templated(true).type(Role.class).build());
|
||||
Parameter level = Parameter
|
||||
.builder()
|
||||
.name("level")
|
||||
.validators(levelValidators)
|
||||
.templated(true)
|
||||
.type(Integer.class)
|
||||
.build();
|
||||
parameters.add(level);
|
||||
Parameter role = Parameter
|
||||
.builder()
|
||||
.name("role")
|
||||
.templated(true)
|
||||
.type(Role.class)
|
||||
.build();
|
||||
parameters.add(role);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).hasExample(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("setExpRole")
|
||||
|
||||
@@ -39,7 +39,7 @@ public class SyncRoles extends AbstractConditionableCommand {
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
AServer server = serverManagementService.loadServer(commandContext.getGuild());
|
||||
log.info("Synchronizing roles on server {}", server.getId());
|
||||
return userExperienceService.syncUserRolesWithFeedback(server, commandContext.getChannel().getIdLong())
|
||||
return userExperienceService.syncUserRolesWithFeedback(server, commandContext.getChannel())
|
||||
.thenApply(aVoid -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public class UnSetExpRole extends AbstractConditionableCommand {
|
||||
if(!experienceRole.isPresent()) {
|
||||
throw new ExperienceRoleNotFoundException();
|
||||
}
|
||||
return experienceRoleService.unsetRoles(actualRole, commandContext.getChannel().getIdLong())
|
||||
return experienceRoleService.unsetRoles(actualRole, commandContext.getChannel())
|
||||
.thenApply(aVoid -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package dev.sheldan.abstracto.experience.job;
|
||||
|
||||
import dev.sheldan.abstracto.experience.model.ServerExperience;
|
||||
import dev.sheldan.abstracto.experience.service.AUserExperienceService;
|
||||
import dev.sheldan.abstracto.experience.service.RunTimeExperienceService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -12,10 +11,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* This {@link QuartzJobBean job} is executed regularly and calls the the {@link AUserExperienceService service}
|
||||
@@ -26,10 +21,7 @@ import java.util.Map;
|
||||
@DisallowConcurrentExecution
|
||||
@Component
|
||||
@PersistJobDataAfterExecution
|
||||
public class ExperiencePersistingJob extends QuartzJobBean {
|
||||
|
||||
@Autowired
|
||||
private AUserExperienceService userExperienceService;
|
||||
public class ExperienceCleanupJob extends QuartzJobBean {
|
||||
|
||||
@Autowired
|
||||
private RunTimeExperienceService runTimeExperienceService;
|
||||
@@ -37,19 +29,9 @@ public class ExperiencePersistingJob extends QuartzJobBean {
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
|
||||
runTimeExperienceService.takeLock();
|
||||
log.info("Cleaning up experience runtime storage.");
|
||||
try {
|
||||
Map<Long, List<ServerExperience>> runtimeExperience = runTimeExperienceService.getRuntimeExperience();
|
||||
log.info("Running experience persisting job.");
|
||||
Long pastMinute = (Instant.now().getEpochSecond() / 60) - 1;
|
||||
if(runtimeExperience.containsKey(pastMinute)) {
|
||||
List<ServerExperience> foundServers = runtimeExperience.get(pastMinute);
|
||||
log.info("Found experience from {} servers to persist.", foundServers.size());
|
||||
userExperienceService.handleExperienceGain(foundServers).thenAccept(aVoid -> {
|
||||
runTimeExperienceService.takeLock();
|
||||
runTimeExperienceService.getRuntimeExperience().remove(pastMinute);
|
||||
runTimeExperienceService.releaseLock();
|
||||
});
|
||||
}
|
||||
runTimeExperienceService.cleanupRunTimeStorage();
|
||||
} finally {
|
||||
runTimeExperienceService.releaseLock();
|
||||
}
|
||||
@@ -4,9 +4,7 @@ import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageReceivedListener;
|
||||
import dev.sheldan.abstracto.core.listener.sync.jda.MessageReceivedListener;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.experience.config.ExperienceFeatureDefinition;
|
||||
import dev.sheldan.abstracto.experience.service.AUserExperienceService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -25,9 +23,6 @@ public class ExperienceTrackerListener implements AsyncMessageReceivedListener {
|
||||
@Autowired
|
||||
private AUserExperienceService userExperienceService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MessageReceivedModel model) {
|
||||
Message message = model.getMessage();
|
||||
@@ -35,8 +30,7 @@ public class ExperienceTrackerListener implements AsyncMessageReceivedListener {
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
if(userExperienceService.experienceGainEnabledInChannel(message.getChannel())) {
|
||||
AUserInAServer cause = userInServerManagementService.loadOrCreateUser(model.getServerId(), model.getMessage().getAuthor().getIdLong());
|
||||
userExperienceService.addExperience(cause);
|
||||
userExperienceService.addExperience(message.getMember(), model.getMessage());
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
} else {
|
||||
return DefaultListenerResult.IGNORED;
|
||||
|
||||
@@ -42,7 +42,7 @@ public class JoiningUserRoleListener implements AsyncJoinListener {
|
||||
Optional<AUserExperience> userExperienceOptional = userExperienceManagementService.findByUserInServerIdOptional(aUserInAServer.getUserInServerId());
|
||||
if(userExperienceOptional.isPresent()) {
|
||||
log.info("User {} joined {} with previous experience. Setting up experience role again (if necessary).", model.getJoiningUser().getUserId(), model.getServerId());
|
||||
userExperienceService.syncForSingleUser(userExperienceOptional.get()).thenAccept(result ->
|
||||
userExperienceService.syncForSingleUser(userExperienceOptional.get(), model.getMember()).thenAccept(result ->
|
||||
log.info("Finished re-assigning experience for re-joining user {} in server {}.", model.getJoiningUser().getUserId(), model.getServerId())
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -21,6 +21,7 @@ public interface ExperienceRoleRepository extends JpaRepository<AExperienceRole,
|
||||
* @return The {@link AExperienceRole experienceRole} found or null if the query did not return any results
|
||||
*/
|
||||
Optional<AExperienceRole> findByRole(ARole role);
|
||||
List<AExperienceRole> findByRole_IdIn(List<Long> role);
|
||||
|
||||
/**
|
||||
* Finds a list of {@link AExperienceRole experienceRoles} (if there are multiple ones, because of misconfiguration) of the given
|
||||
|
||||
@@ -5,6 +5,7 @@ import dev.sheldan.abstracto.experience.model.database.AUserExperience;
|
||||
import dev.sheldan.abstracto.experience.model.database.LeaderBoardEntryResult;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
@@ -52,4 +53,8 @@ public interface UserExperienceRepository extends JpaRepository<AUserExperience
|
||||
"WHERE rank.id = :userInServerId", nativeQuery = true)
|
||||
LeaderBoardEntryResult getRankOfUserInServer(@Param("userInServerId") Long id, @Param("serverId") Long serverId);
|
||||
|
||||
@Modifying(clearAutomatically = true)
|
||||
@Query("update AUserExperience u set u.currentExperienceRole = null where u.currentExperienceRole.id = :roleId")
|
||||
void removeExperienceRoleFromUsers(@Param("roleId") Long experienceRoleId);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,36 +1,49 @@
|
||||
package dev.sheldan.abstracto.experience.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.core.models.template.display.RoleDisplay;
|
||||
import dev.sheldan.abstracto.core.service.*;
|
||||
import dev.sheldan.abstracto.core.service.management.*;
|
||||
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.experience.config.ExperienceFeatureConfig;
|
||||
import dev.sheldan.abstracto.experience.config.ExperienceFeatureDefinition;
|
||||
import dev.sheldan.abstracto.experience.config.ExperienceFeatureMode;
|
||||
import dev.sheldan.abstracto.experience.exception.NoExperienceTrackedException;
|
||||
import dev.sheldan.abstracto.experience.model.*;
|
||||
import dev.sheldan.abstracto.experience.model.LeaderBoard;
|
||||
import dev.sheldan.abstracto.experience.model.LeaderBoardEntry;
|
||||
import dev.sheldan.abstracto.experience.model.RoleCalculationResult;
|
||||
import dev.sheldan.abstracto.experience.model.database.*;
|
||||
import dev.sheldan.abstracto.experience.model.template.LevelUpNotificationModel;
|
||||
import dev.sheldan.abstracto.experience.model.template.UserSyncStatusModel;
|
||||
import dev.sheldan.abstracto.experience.service.management.DisabledExpRoleManagementService;
|
||||
import dev.sheldan.abstracto.experience.service.management.ExperienceLevelManagementService;
|
||||
import dev.sheldan.abstracto.experience.service.management.ExperienceRoleManagementService;
|
||||
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static dev.sheldan.abstracto.experience.config.ExperienceFeatureConfig.EXP_COOLDOWN_SECONDS_KEY;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
@@ -81,38 +94,49 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
private ChannelGroupService channelGroupService;
|
||||
|
||||
@Autowired
|
||||
private DefaultConfigManagementService defaultConfigManagementService;
|
||||
private SecureRandom secureRandom;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Autowired
|
||||
private AUserExperienceServiceBean self;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("experienceUpdateExecutor")
|
||||
private TaskExecutor experienceUpdateExecutor;
|
||||
|
||||
@Override
|
||||
public void addExperience(AUserInAServer userInAServer) {
|
||||
public void addExperience(Member member, Message message) {
|
||||
runTimeExperienceService.takeLock();
|
||||
try {
|
||||
Long minute = Instant.now().getEpochSecond() / 60;
|
||||
Map<Long, List<ServerExperience>> runtimeExperience = runTimeExperienceService.getRuntimeExperience();
|
||||
Long serverId = userInAServer.getServerReference().getId();
|
||||
Long userInServerId = userInAServer.getUserInServerId();
|
||||
if(runtimeExperience.containsKey(minute)) {
|
||||
log.debug("Minute {} already tracked, adding user {} in server {}.",
|
||||
minute, userInAServer.getUserReference().getId(), serverId);
|
||||
List<ServerExperience> existing = runtimeExperience.get(minute);
|
||||
for (ServerExperience server : existing) {
|
||||
if (server.getServerId().equals(serverId) && server.getUserInServerIds().stream().noneMatch(userInServerId::equals)) {
|
||||
server.getUserInServerIds().add(userInServerId);
|
||||
break;
|
||||
Map<Long, Map<Long, Instant>> runtimeExperience = runTimeExperienceService.getRuntimeExperience();
|
||||
Long serverId = member.getGuild().getIdLong();
|
||||
Long userId = member.getIdLong();
|
||||
boolean receivesNewExperience = false;
|
||||
if(!runtimeExperience.containsKey(serverId)) {
|
||||
runtimeExperience.put(serverId, new HashMap<>());
|
||||
receivesNewExperience = true;
|
||||
} else {
|
||||
Map<Long, Instant> serverExperience = runtimeExperience.get(serverId);
|
||||
if(!serverExperience.containsKey(userId)) {
|
||||
receivesNewExperience = true;
|
||||
} else {
|
||||
Instant latestExperience = serverExperience.get(userId);
|
||||
if(latestExperience.isBefore(Instant.now())) {
|
||||
receivesNewExperience = true;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
log.debug("Minute {} did not exist yet. Creating new entry for user {} in server {}.", minute, userInAServer.getUserReference().getId(), serverId);
|
||||
ServerExperience serverExperience = ServerExperience
|
||||
.builder()
|
||||
.serverId(serverId)
|
||||
.build();
|
||||
serverExperience.getUserInServerIds().add(userInServerId);
|
||||
runtimeExperience.put(minute, new ArrayList<>(Arrays.asList(serverExperience)));
|
||||
}
|
||||
if(receivesNewExperience) {
|
||||
Map<Long, Instant> serverExperience = runtimeExperience.get(serverId);
|
||||
// we store when the user is eligible for experience _again_
|
||||
Long maxSeconds = configService.getLongValueOrConfigDefault(EXP_COOLDOWN_SECONDS_KEY, serverId);
|
||||
serverExperience.put(userId, Instant.now().plus(maxSeconds, ChronoUnit.SECONDS));
|
||||
CompletableFuture.runAsync(() -> self.addExperienceToMember(member, message), experienceUpdateExecutor);
|
||||
}
|
||||
} finally {
|
||||
runTimeExperienceService.releaseLock();
|
||||
@@ -148,317 +172,199 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CompletableFuture<Void> handleExperienceGain(List<ServerExperience> servers) {
|
||||
List<ExperienceGainResult> resultFutures = new ArrayList<>();
|
||||
List<CompletableFuture<RoleCalculationResult>> futures = new ArrayList<>();
|
||||
CompletableFuture<Void> experienceFuture = new CompletableFuture<>();
|
||||
// TODO what if there are a lot in here...., transaction size etc
|
||||
servers.forEach(serverExp -> {
|
||||
List<CompletableFuture<Member>> memberFutures = new ArrayList<>();
|
||||
serverExp.getUserInServerIds().forEach(userInAServerId -> {
|
||||
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(userInAServerId);
|
||||
CompletableFuture<Member> memberFuture = memberService.getMemberInServerAsync(userInAServer);
|
||||
memberFutures.add(memberFuture);
|
||||
});
|
||||
|
||||
FutureUtils.toSingleFutureGeneric(memberFutures).whenComplete((unused, throwable) -> {
|
||||
self.updateFoundMembers(memberFutures, serverExp.getServerId(), resultFutures, futures);
|
||||
experienceFuture.complete(null);
|
||||
}).exceptionally(throwable -> {
|
||||
experienceFuture.completeExceptionally(throwable);
|
||||
public CompletableFuture<Void> syncUserRolesWithFeedback(AServer server, MessageChannel messageChannel) {
|
||||
List<AUserExperience> aUserExperiences = userExperienceManagementService.loadAllUsers(server);
|
||||
List<Long> userIds = aUserExperiences
|
||||
.stream()
|
||||
.map(aUserExperience -> aUserExperience.getUser().getUserReference().getId())
|
||||
.collect(Collectors.toList());
|
||||
log.info("Synchronizing experience roles for {} users.", userIds.size());
|
||||
CompletableFuture<Void> returnFuture = new CompletableFuture<>();
|
||||
Long serverId = server.getId();
|
||||
int supposedUserCount = userIds.size();
|
||||
memberService.getMembersInServerAsync(server.getId(), userIds).whenComplete((members, throwable) -> {
|
||||
if(throwable != null) {
|
||||
log.warn("Failed to load all members in server {} for syncing experience. We started with {} and got {}.",
|
||||
serverId, supposedUserCount, members.size(), throwable);
|
||||
}
|
||||
self.syncUsers(members, serverId, messageChannel).thenAccept(unused -> {
|
||||
log.info("Finished syncing users for experience roles.");
|
||||
returnFuture.complete(null);
|
||||
}).exceptionally(throwable1 -> {
|
||||
returnFuture.complete(null);
|
||||
return null;
|
||||
});
|
||||
});
|
||||
return experienceFuture
|
||||
.thenCompose(unused -> FutureUtils.toSingleFutureGeneric(futures))
|
||||
.whenComplete((unused, throwable) -> self.persistExperienceChanges(resultFutures));
|
||||
return returnFuture;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateFoundMembers(List<CompletableFuture<Member>> memberFutures, Long serverId, List<ExperienceGainResult> resultFutures, List<CompletableFuture<RoleCalculationResult>> futures) {
|
||||
List<AExperienceLevel> levels = experienceLevelManagementService.getLevelConfig();
|
||||
SystemConfigProperty defaultExpMultiplier = defaultConfigManagementService.getDefaultConfig(ExperienceFeatureConfig.EXP_MULTIPLIER_KEY);
|
||||
SystemConfigProperty defaultMinExp = defaultConfigManagementService.getDefaultConfig(ExperienceFeatureConfig.MIN_EXP_KEY);
|
||||
SystemConfigProperty defaultMaxExp = defaultConfigManagementService.getDefaultConfig(ExperienceFeatureConfig.MAX_EXP_KEY);
|
||||
AServer server = serverManagementService.loadOrCreate(serverId);
|
||||
int minExp = configService.getLongValue(ExperienceFeatureConfig.MIN_EXP_KEY, serverId, defaultMinExp.getLongValue()).intValue();
|
||||
int maxExp = configService.getLongValue(ExperienceFeatureConfig.MAX_EXP_KEY, serverId, defaultMaxExp.getLongValue()).intValue();
|
||||
Double multiplier = configService.getDoubleValue(ExperienceFeatureConfig.EXP_MULTIPLIER_KEY, serverId, defaultExpMultiplier.getDoubleValue());
|
||||
PrimitiveIterator.OfInt iterator = new Random().ints(memberFutures.size(), minExp, maxExp + 1).iterator();
|
||||
levels.sort(Comparator.comparing(AExperienceLevel::getExperienceNeeded));
|
||||
public CompletableFuture<Void> syncUsers(List<Member> members, Long serverId, MessageChannel messageChannel) {
|
||||
AtomicInteger currentCount = new AtomicInteger();
|
||||
MessageToSend status = getUserSyncStatusUpdateModel(0, members.size(), serverId);
|
||||
Message statusMessage = messageService.createStatusMessage(status, messageChannel).join();
|
||||
|
||||
AServer server = serverManagementService.loadServer(serverId);
|
||||
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(server);
|
||||
List<ADisabledExpRole> disabledExpRoles = disabledExpRoleManagementService.getDisabledRolesForServer(server);
|
||||
List<ARole> disabledRoles = disabledExpRoles.stream().map(ADisabledExpRole::getRole).collect(Collectors.toList());
|
||||
roles.sort(Comparator.comparing(role -> role.getLevel().getLevel()));
|
||||
log.info("Handling {} experiences for server {}. Using {} roles.", memberFutures.size(), serverId, roles.size());
|
||||
memberFutures.forEach(future -> {
|
||||
if(!future.isCompletedExceptionally()) {
|
||||
Integer gainedExperience = iterator.next();
|
||||
gainedExperience = (int) Math.floor(gainedExperience * multiplier);
|
||||
Member member = future.join();
|
||||
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(member);
|
||||
Long userInServerId = userInAServer.getUserInServerId();
|
||||
if(!roleService.hasAnyOfTheRoles(member, disabledRoles)) {
|
||||
log.debug("Handling {}. The user might gain {}.", userInServerId, gainedExperience);
|
||||
Optional<AUserExperience> aUserExperienceOptional = userExperienceManagementService.findByUserInServerIdOptional(userInAServer.getUserInServerId());
|
||||
if(aUserExperienceOptional.isPresent()) {
|
||||
AUserExperience aUserExperience = aUserExperienceOptional.get();
|
||||
if(Boolean.FALSE.equals(aUserExperience.getExperienceGainDisabled())) {
|
||||
log.debug("User {} will gain experience.", userInServerId);
|
||||
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())
|
||||
.serverId(serverId)
|
||||
.userInServerId(userInAServer.getUserInServerId())
|
||||
.build();
|
||||
resultFutures.add(calculationResult);
|
||||
futures.add(resultFuture);
|
||||
} else {
|
||||
log.debug("Experience gain was disabled. User did not gain any experience.");
|
||||
}
|
||||
} else {
|
||||
log.info("User experience for user {} was not found. Planning to create new instance.", userInAServer.getUserInServerId());
|
||||
Long newExperience = gainedExperience.longValue();
|
||||
AExperienceLevel newLevel = calculateLevel(levels, newExperience);
|
||||
Long newMessageCount = 1L;
|
||||
CompletableFuture<RoleCalculationResult> resultFuture = applyInitialRole(userInAServer, roles, newLevel.getLevel());
|
||||
ExperienceGainResult calculationResult =
|
||||
ExperienceGainResult
|
||||
.builder()
|
||||
.calculationResult(resultFuture)
|
||||
.newExperience(newExperience)
|
||||
.newMessageCount(newMessageCount)
|
||||
.newLevel(newLevel.getLevel())
|
||||
.createUserExperience(true)
|
||||
.userInServerId(userInAServer.getUserInServerId())
|
||||
.build();
|
||||
resultFutures.add(calculationResult);
|
||||
futures.add(resultFuture);
|
||||
}
|
||||
} else {
|
||||
log.debug("User {} has a role which makes the user unable to gain experience.", userInAServer.getUserInServerId());
|
||||
}
|
||||
}
|
||||
|
||||
List<CompletableFuture<Void>> futures = members
|
||||
.stream()
|
||||
.map(member -> this.syncUser(member, roles)
|
||||
.thenAccept(unused -> {
|
||||
currentCount.set(currentCount.get() + 1);
|
||||
log.debug("Finished synchronizing {} users.", currentCount.get());
|
||||
if(currentCount.get() % 50 == 0) {
|
||||
log.info("Notifying for {} current users with synchronize.", currentCount.get());
|
||||
MessageToSend newStatus = getUserSyncStatusUpdateModel(currentCount.get(), members.size(), serverId);
|
||||
messageService.updateStatusMessage(messageChannel, statusMessage.getIdLong(), newStatus);
|
||||
}
|
||||
}))
|
||||
.collect(Collectors.toList());
|
||||
return FutureUtils.toSingleFutureGeneric(futures).thenAccept(unused -> {
|
||||
MessageToSend newStatus = getUserSyncStatusUpdateModel(currentCount.get(), members.size(), serverId);
|
||||
messageService.updateStatusMessage(messageChannel, statusMessage.getIdLong(), newStatus);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the appropriate {@link AExperienceRole experienceRole} based on the current level and awards the referenced the {@link AUserInAServer userinAServer}
|
||||
* the {@link net.dv8tion.jda.api.entities.Role role}. If the user already left the guild, this will not award a {@link net.dv8tion.jda.api.entities.Role}, but just
|
||||
* return the instance in order to be persisted
|
||||
* @param aUserInAServer The {@link AUserInAServer userInAServer} which does not have a {@link AUserExperience userExperience} object,
|
||||
* therefore we need to calculate the appropriate role and award the role
|
||||
* @param roles A list of {@link AExperienceRole experienceRoles} representing the configuration which is used to calculate the appropriate
|
||||
* {@link AExperienceRole experienceRole}
|
||||
* @param currentLevel The current level of the user which was reached.
|
||||
* @return A {@link CompletableFuture future} containing the {@link RoleCalculationResult result} of the role calculation, which completes after the user has been awarded the role.
|
||||
*/
|
||||
private CompletableFuture<RoleCalculationResult> applyInitialRole(AUserInAServer aUserInAServer, List<AExperienceRole> roles, Integer currentLevel) {
|
||||
AExperienceRole role = experienceRoleService.calculateRole(roles, currentLevel);
|
||||
if(role == null) {
|
||||
log.debug("No experience role calculated. Applying none to user {} in server {}.",
|
||||
aUserInAServer.getUserReference().getId(), aUserInAServer.getServerReference().getId());
|
||||
return CompletableFuture.completedFuture(RoleCalculationResult
|
||||
.builder()
|
||||
.userInServerId(aUserInAServer.getUserInServerId())
|
||||
.experienceRoleId(null)
|
||||
.build());
|
||||
}
|
||||
Long experienceRoleId = role.getId();
|
||||
Long userInServerId = aUserInAServer.getUserInServerId();
|
||||
log.debug("Applying {} as the first experience role for user {} in server {}.",
|
||||
experienceRoleId, aUserInAServer.getUserReference().getId(), aUserInAServer.getServerReference().getId());
|
||||
return roleService.addRoleToUserAsync(aUserInAServer, role.getRole()).thenApply(aVoid -> RoleCalculationResult
|
||||
.builder()
|
||||
.experienceRoleId(experienceRoleId)
|
||||
.userInServerId(userInServerId)
|
||||
.build());
|
||||
public CompletableFuture<Void> syncUser(Member member, List<AExperienceRole> roles) {
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(member);
|
||||
AUserExperience userExperience = userExperienceManagementService.findByUserInServerId(aUserInAServer.getUserInServerId());
|
||||
return calculateAndApplyExperienceRole(userExperience, member, roles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Persists the list of {@link ExperienceGainResult results} in the database. If the creation of {@link AUserExperience userExperience} object was requested,
|
||||
* this will happen here, also the correct level is selected
|
||||
* @param resultFutures A list of {@link ExperienceGainResult results} which define what should be changed for the given {@link AUserExperience userExperience} object:
|
||||
* The level, experience, experienceRole, message account could change, or the object could not even exist
|
||||
*/
|
||||
@Transactional
|
||||
public void persistExperienceChanges(List<ExperienceGainResult> resultFutures) {
|
||||
// we do have the _value_ of the level, but we require the actual instance
|
||||
Map<Integer, AExperienceLevel> levels = experienceLevelManagementService.getLevelConfigAsMap();
|
||||
log.info("Storing {} experience gain results.", resultFutures.size());
|
||||
HashMap<Long, List<AExperienceRole>> serverRoleMapping = new HashMap<>();
|
||||
resultFutures.forEach(experienceGainResult -> {
|
||||
AUserInAServer user = userInServerManagementService.loadOrCreateUser(experienceGainResult.getUserInServerId());
|
||||
AUserExperience userExperience;
|
||||
if(experienceGainResult.isCreateUserExperience()) {
|
||||
userExperience = userExperienceManagementService.createUserInServer(user);
|
||||
log.info("Creating new experience user for user in server {}.", experienceGainResult.getUserInServerId());
|
||||
@Override
|
||||
public CompletableFuture<Void> syncForSingleUser(AUserExperience userExperience, Member member) {
|
||||
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(userExperience.getServer());
|
||||
roles.sort(Comparator.comparing(role -> role.getLevel().getLevel()));
|
||||
return calculateAndApplyExperienceRole(userExperience, member, roles);
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> calculateAndApplyExperienceRole(AUserExperience userExperience, Member member, List<AExperienceRole> roles) {
|
||||
AExperienceRole calculatedNewRole = experienceRoleService.calculateRole(roles, userExperience.getCurrentLevel().getLevel());
|
||||
Long oldRoleId = userExperience.getCurrentExperienceRole() != null && userExperience.getCurrentExperienceRole().getRole() != null ? userExperience.getCurrentExperienceRole().getRole().getId() : null;
|
||||
Long newRoleId = calculatedNewRole != null ? calculatedNewRole.getRole().getId() : null;
|
||||
|
||||
userExperience.setCurrentExperienceRole(calculatedNewRole);
|
||||
|
||||
CompletableFuture<Void> returningFuture;
|
||||
if(!Objects.equals(oldRoleId, newRoleId)) {
|
||||
CompletableFuture<Void> addingFuture;
|
||||
if(oldRoleId != null) {
|
||||
addingFuture = roleService.removeRoleFromMemberAsync(member, oldRoleId);
|
||||
} else {
|
||||
userExperience = userExperienceManagementService.findByUserInServerId(experienceGainResult.getUserInServerId());
|
||||
addingFuture = CompletableFuture.completedFuture(null);
|
||||
}
|
||||
userExperience.setMessageCount(experienceGainResult.getNewMessageCount());
|
||||
userExperience.setExperience(experienceGainResult.getNewExperience());
|
||||
// only search the levels if the level changed, or if there is no level currently set
|
||||
AExperienceLevel currentLevel = userExperience.getCurrentLevel();
|
||||
boolean userExperienceHasLevel = currentLevel != null;
|
||||
if(!userExperienceHasLevel || !currentLevel.getLevel().equals(experienceGainResult.getNewLevel())) {
|
||||
AExperienceLevel foundLevel = levels.get(experienceGainResult.getNewLevel());
|
||||
if(foundLevel != null) {
|
||||
log.info("User {} in server {} changed the level. Old level {}. New level {}.", experienceGainResult.getUserInServerId(), experienceGainResult.getServerId(), currentLevel.getLevel(), experienceGainResult.getNewLevel());
|
||||
userExperience.setCurrentLevel(foundLevel);
|
||||
} else {
|
||||
log.warn("User {} was present, but no level matching the calculation result {} could be found.", userExperience.getUser().getUserReference().getId(), experienceGainResult.getNewLevel());
|
||||
}
|
||||
CompletableFuture<Void> removingFeature;
|
||||
if(newRoleId != null) {
|
||||
removingFeature = roleService.addRoleToMemberAsync(member, newRoleId);
|
||||
} else {
|
||||
removingFeature = CompletableFuture.completedFuture(null);
|
||||
}
|
||||
AServer server = user.getServerReference();
|
||||
// "Caching" the experience roles for this server
|
||||
if(!serverRoleMapping.containsKey(server.getId())) {
|
||||
serverRoleMapping.put(server.getId(), experienceRoleManagementService.getExperienceRolesForServer(server));
|
||||
}
|
||||
RoleCalculationResult roleCalculationResult = experienceGainResult.getCalculationResult().join();
|
||||
if(roleCalculationResult.getExperienceRoleId() != null) {
|
||||
AExperienceRole role = experienceRoleManagementService.getExperienceRoleById(roleCalculationResult.getExperienceRoleId());
|
||||
userExperience.setCurrentExperienceRole(role);
|
||||
}
|
||||
if(experienceGainResult.isCreateUserExperience()) {
|
||||
userExperienceManagementService.saveUser(userExperience);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
Long userInServerId = user.getUserInServerId();
|
||||
Long serverId = user.getServerReference().getId();
|
||||
log.debug("Updating experience role for user {} in server {}", user.getUserReference().getId(), serverId);
|
||||
AExperienceRole role = experienceRoleService.calculateRole(roles, currentLevel);
|
||||
boolean currentlyHasNoExperienceRole = userExperience.getCurrentExperienceRole() == null;
|
||||
// if calculation results in no role, do not add a role
|
||||
if(role == null) {
|
||||
log.debug("User {} in server {} does not have an experience role, according to new calculation.",
|
||||
user.getUserReference().getId(), serverId);
|
||||
// if the user has a experience role currently, remove it
|
||||
if(!currentlyHasNoExperienceRole && !userExperience.getCurrentExperienceRole().getRole().getDeleted()){
|
||||
return roleService.removeRoleFromUserAsync(user, userExperience.getCurrentExperienceRole().getRole())
|
||||
.thenApply(returnNullRole);
|
||||
}
|
||||
return CompletableFuture.completedFuture(returnNullRole.apply(null));
|
||||
returningFuture = CompletableFuture.allOf(addingFuture, removingFeature);
|
||||
} else {
|
||||
returningFuture = CompletableFuture.completedFuture(null);
|
||||
}
|
||||
Long experienceRoleId = role.getId();
|
||||
Long roleId = role.getRole().getId();
|
||||
// if the new role is already the one configured in the database
|
||||
Long userId = user.getUserReference().getId();
|
||||
Long oldUserExperienceRoleId = currentlyHasNoExperienceRole ? 0L : userExperience.getCurrentExperienceRole().getRole().getId();
|
||||
return memberService.getMemberInServerAsync(user).thenCompose(member -> {
|
||||
boolean userHasRoleAlready = roleService.memberHasRole(member, roleId);
|
||||
boolean userHasOldRole = false;
|
||||
boolean rolesChanged = true;
|
||||
if(!currentlyHasNoExperienceRole) {
|
||||
userHasOldRole = roleService.memberHasRole(member, oldUserExperienceRoleId);
|
||||
rolesChanged = !roleId.equals(oldUserExperienceRoleId);
|
||||
}
|
||||
Function<Void, RoleCalculationResult> fullResult = aVoid -> RoleCalculationResult
|
||||
.builder()
|
||||
.experienceRoleId(experienceRoleId)
|
||||
.userInServerId(userInServerId)
|
||||
.build();
|
||||
// if the roles changed or
|
||||
// the user does not have the new target role already
|
||||
// the user still has the old role
|
||||
if(!userHasRoleAlready || userHasOldRole) {
|
||||
CompletableFuture<Void> removalFuture;
|
||||
if(userHasOldRole && rolesChanged) {
|
||||
log.info("User {} in server {} loses experience role {}.", userId, serverId, oldUserExperienceRoleId);
|
||||
removalFuture = roleService.removeRoleFromMemberAsync(member, oldUserExperienceRoleId);
|
||||
} else {
|
||||
removalFuture = CompletableFuture.completedFuture(null);
|
||||
}
|
||||
CompletableFuture<Void> addRoleFuture;
|
||||
if(!userHasRoleAlready) {
|
||||
log.info("User {} in server {} gets a new role {} because of experience.", userId, serverId, roleId);
|
||||
addRoleFuture = roleService.addRoleToMemberAsync(member, roleId);
|
||||
} else {
|
||||
addRoleFuture = CompletableFuture.completedFuture(null);
|
||||
}
|
||||
return CompletableFuture.allOf(removalFuture, addRoleFuture).thenApply(fullResult);
|
||||
}
|
||||
// we are turning the full calculation result regardless
|
||||
return CompletableFuture.completedFuture(fullResult.apply(null));
|
||||
});
|
||||
return returningFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
roles.sort(Comparator.comparing(role -> role.getLevel().getLevel()));
|
||||
for (int i = 0; i < aUserExperiences.size(); i++) {
|
||||
AUserExperience userExperience = aUserExperiences.get(i);
|
||||
log.info("Synchronizing {} out of {}. User in Server {}.", i, aUserExperiences.size(), userExperience.getUser().getUserInServerId());
|
||||
results.add(updateUserRole(userExperience, roles, userExperience.getCurrentLevel().getLevel()));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> syncUserRolesWithFeedback(AServer server, Long channelId) {
|
||||
AChannel channel = channelManagementService.loadChannel(channelId);
|
||||
List<AUserExperience> aUserExperiences = userExperienceManagementService.loadAllUsers(server);
|
||||
log.info("Found {} users to synchronize", aUserExperiences.size());
|
||||
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(server);
|
||||
roles.sort(Comparator.comparing(role -> role.getLevel().getLevel()));
|
||||
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 results} which should be applied
|
||||
*/
|
||||
@Transactional
|
||||
public void syncRolesInStorage(List<RoleCalculationResult> results) {
|
||||
HashMap<Long, AExperienceRole> experienceRoleHashMap = new HashMap<>();
|
||||
results.forEach(result -> {
|
||||
if(result != null) {
|
||||
AUserInAServer user = userInServerManagementService.loadOrCreateUser(result.getUserInServerId());
|
||||
AUserExperience userExperience = userExperienceManagementService.findUserInServer(user);
|
||||
log.debug("Updating experience role for {} in server {} to {}", user.getUserInServerId(), user.getServerReference().getId(), result.getExperienceRoleId());
|
||||
if(result.getExperienceRoleId() != null) {
|
||||
log.debug("User experience {} gets new experience role with id {}.", userExperience.getId(), result.getExperienceRoleId());
|
||||
AExperienceRole role;
|
||||
if(!experienceRoleHashMap.containsKey(result.getExperienceRoleId())) {
|
||||
role = experienceRoleManagementService.getExperienceRoleById(result.getExperienceRoleId());
|
||||
experienceRoleHashMap.put(result.getExperienceRoleId(), role);
|
||||
} else {
|
||||
role = experienceRoleHashMap.get(result.getExperienceRoleId());
|
||||
}
|
||||
userExperience.setCurrentExperienceRole(role);
|
||||
} else {
|
||||
log.debug("User experience {} does not get a user experience role.", userExperience.getId());
|
||||
userExperience.setCurrentExperienceRole(null);
|
||||
public void addExperienceToMember(Member member, Message message) {
|
||||
long serverId = member.getGuild().getIdLong();
|
||||
AServer server = serverManagementService.loadOrCreate(serverId);
|
||||
List<ADisabledExpRole> disabledExpRoles = disabledExpRoleManagementService.getDisabledRolesForServer(server);
|
||||
List<ARole> disabledRoles = disabledExpRoles
|
||||
.stream()
|
||||
.map(ADisabledExpRole::getRole)
|
||||
.collect(Collectors.toList());
|
||||
if(roleService.hasAnyOfTheRoles(member, disabledRoles)) {
|
||||
log.debug("User {} has a experience disable role in server {} - not giving any experience.", member.getIdLong(), serverId);
|
||||
return;
|
||||
}
|
||||
List<AExperienceLevel> levels = experienceLevelManagementService.getLevelConfig();
|
||||
levels.sort(Comparator.comparing(AExperienceLevel::getExperienceNeeded));
|
||||
|
||||
Long minExp = configService.getLongValueOrConfigDefault(ExperienceFeatureConfig.MIN_EXP_KEY, serverId);
|
||||
Long maxExp = configService.getLongValueOrConfigDefault(ExperienceFeatureConfig.MAX_EXP_KEY, serverId);
|
||||
Double multiplier = configService.getDoubleValueOrConfigDefault(ExperienceFeatureConfig.EXP_MULTIPLIER_KEY, serverId);
|
||||
Long experienceRange = maxExp - minExp + 1;
|
||||
Long gainedExperience = (secureRandom.nextInt(experienceRange.intValue()) + minExp);
|
||||
gainedExperience = (long) Math.floor(gainedExperience * multiplier);
|
||||
|
||||
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(server);
|
||||
roles.sort(Comparator.comparing(role -> role.getLevel().getLevel()));
|
||||
|
||||
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(member);
|
||||
Long userInServerId = userInAServer.getUserInServerId();
|
||||
log.debug("Handling {}. The user might gain {}.", userInServerId, gainedExperience);
|
||||
Optional<AUserExperience> aUserExperienceOptional = userExperienceManagementService.findByUserInServerIdOptional(userInAServer.getUserInServerId());
|
||||
AUserExperience aUserExperience = aUserExperienceOptional.orElseGet(() -> userExperienceManagementService.createUserInServer(userInAServer));
|
||||
if(Boolean.FALSE.equals(aUserExperience.getExperienceGainDisabled())) {
|
||||
Long oldExperience = aUserExperience.getExperience();
|
||||
Long newExperienceCount = oldExperience + gainedExperience;
|
||||
aUserExperience.setExperience(newExperienceCount);
|
||||
AExperienceLevel newLevel = calculateLevel(levels, newExperienceCount);
|
||||
RoleCalculationResult result = RoleCalculationResult
|
||||
.builder()
|
||||
.build();
|
||||
if(!Objects.equals(newLevel.getLevel(), aUserExperience.getCurrentLevel().getLevel())) {
|
||||
Integer oldLevel = aUserExperience.getCurrentLevel() != null ? aUserExperience.getCurrentLevel().getLevel() : 0;
|
||||
log.info("User {} in server {} changed level. New {}, Old {}.", member.getIdLong(),
|
||||
member.getGuild().getIdLong(), newLevel.getLevel(),
|
||||
oldLevel);
|
||||
aUserExperience.setCurrentLevel(newLevel);
|
||||
AExperienceRole calculatedNewRole = experienceRoleService.calculateRole(roles, newLevel.getLevel());
|
||||
Long oldRoleId = aUserExperience.getCurrentExperienceRole() != null ? aUserExperience.getCurrentExperienceRole().getRole().getId() : null;
|
||||
Long newRoleId = calculatedNewRole != null ? calculatedNewRole.getRole().getId() : null;
|
||||
result.setOldRoleId(oldRoleId);
|
||||
result.setNewRoleId(newRoleId);
|
||||
if(message != null && featureModeService.featureModeActive(ExperienceFeatureDefinition.EXPERIENCE, serverId, ExperienceFeatureMode.LEVEL_UP_NOTIFICATION)) {
|
||||
LevelUpNotificationModel model = LevelUpNotificationModel
|
||||
.builder()
|
||||
.memberDisplay(MemberDisplay.fromMember(member))
|
||||
.oldExperience(oldExperience)
|
||||
.newExperience(newExperienceCount)
|
||||
.newLevel(newLevel.getLevel())
|
||||
.oldLevel(oldLevel)
|
||||
.newRole(oldRoleId != null ? RoleDisplay.fromRole(oldRoleId) : null)
|
||||
.newRole(newRoleId != null ? RoleDisplay.fromRole(newRoleId) : null)
|
||||
.build();
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate("experience_level_up_notification", model);
|
||||
FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, message.getChannel())).thenAccept(unused -> {
|
||||
log.info("Sent level up notification to user {} in server {} in channel {}.", member.getIdLong(), serverId, message.getChannel().getIdLong());
|
||||
}).exceptionally(throwable -> {
|
||||
log.warn("Failed to send level up notification to user {} in server {} in channel {}.", member.getIdLong(), serverId, message.getChannel().getIdLong());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
aUserExperience.setCurrentExperienceRole(calculatedNewRole);
|
||||
}
|
||||
aUserExperience.setMessageCount(aUserExperience.getMessageCount() + 1L);
|
||||
if(!aUserExperienceOptional.isPresent()) {
|
||||
userExperienceManagementService.saveUser(aUserExperience);
|
||||
}
|
||||
if(!Objects.equals(result.getOldRoleId(), result.getNewRoleId())) {
|
||||
if(result.getOldRoleId() != null) {
|
||||
roleService.removeRoleFromMemberAsync(member, result.getOldRoleId()).thenAccept(unused -> {
|
||||
log.debug("Removed role {} to member {} in server {}.", result.getOldRoleId(), member.getIdLong(), member.getGuild().getIdLong());
|
||||
}).exceptionally(throwable -> {
|
||||
log.warn("Failed to remove role {} from {} member {} in server {}.", result.getOldRoleId(), member.getIdLong(), member.getGuild().getIdLong(), throwable);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
if(result.getNewRoleId() != null) {
|
||||
roleService.addRoleToMemberAsync(member, result.getNewRoleId()).thenAccept(unused -> {
|
||||
log.debug("Added role {} to member {} in server {}.", result.getOldRoleId(), member.getIdLong(), member.getGuild().getIdLong());
|
||||
}).exceptionally(throwable -> {
|
||||
log.warn("Failed to add role {} to {} member {} in server {}.", result.getOldRoleId(), member.getIdLong(), member.getGuild().getIdLong(), throwable);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log.debug("Experience gain was disabled. User did not gain any experience.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -488,29 +394,6 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
return userExperience;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFutureList<RoleCalculationResult> executeActionOnUserExperiencesWithFeedBack(List<AUserExperience> experiences, AChannel channel, Function<AUserExperience, CompletableFuture<RoleCalculationResult>> toExecute) {
|
||||
List<CompletableFuture<RoleCalculationResult>> futures = new ArrayList<>();
|
||||
Long serverId = channel.getServer().getId();
|
||||
MessageToSend status = getUserSyncStatusUpdateModel(0, experiences.size(), serverId);
|
||||
Message statusMessage = messageService.createStatusMessage(status, channel).join();
|
||||
int interval = Math.min(Math.max(experiences.size() / 10, 1), 100);
|
||||
for (int i = 0; i < experiences.size(); i++) {
|
||||
if((i % interval) == 1) {
|
||||
log.info("Updating feedback message with new index {} out of {}.", i, experiences.size());
|
||||
status = getUserSyncStatusUpdateModel(i, experiences.size(), serverId);
|
||||
messageService.updateStatusMessage(channel, statusMessage.getIdLong(), status);
|
||||
}
|
||||
AUserExperience userExperience = experiences.get(i);
|
||||
futures.add(toExecute.apply(userExperience));
|
||||
log.debug("Synchronizing {} out of {}. User in server ID {}.", i, experiences.size(), userExperience.getUser().getUserInServerId());
|
||||
}
|
||||
status = getUserSyncStatusUpdateModel(experiences.size(), experiences.size(), serverId);
|
||||
messageService.updateStatusMessage(channel, statusMessage.getIdLong(), status);
|
||||
|
||||
return new CompletableFutureList<>(futures);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableExperienceForUser(AUserInAServer userInAServer) {
|
||||
log.info("Disabling experience gain for user {} in server {}.", userInAServer.getUserReference().getId(), userInAServer.getServerReference().getId());
|
||||
@@ -537,15 +420,6 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
return templateService.renderEmbedTemplate("user_sync_status_message", statusModel, serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
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());
|
||||
roles.sort(Comparator.comparing(role -> role.getLevel().getLevel()));
|
||||
return updateUserRole(userExperience, roles, userExperience.getLevelOrDefault());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LeaderBoard findLeaderBoardData(AServer server, Integer page) {
|
||||
if(page <= 0) {
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
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.MessageService;
|
||||
import dev.sheldan.abstracto.core.service.RoleService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
|
||||
import dev.sheldan.abstracto.experience.model.RoleCalculationResult;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.experience.model.database.AExperienceLevel;
|
||||
import dev.sheldan.abstracto.experience.model.database.AExperienceRole;
|
||||
import dev.sheldan.abstracto.experience.model.database.AUserExperience;
|
||||
import dev.sheldan.abstracto.experience.model.template.LevelRole;
|
||||
import dev.sheldan.abstracto.experience.model.template.UserSyncStatusModel;
|
||||
import dev.sheldan.abstracto.experience.service.management.ExperienceLevelManagementService;
|
||||
import dev.sheldan.abstracto.experience.service.management.ExperienceRoleManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@@ -34,89 +36,46 @@ public class ExperienceRoleServiceBean implements ExperienceRoleService {
|
||||
@Autowired
|
||||
private ExperienceLevelManagementService experienceLevelService;
|
||||
|
||||
@Autowired
|
||||
private AUserExperienceService userExperienceService;
|
||||
|
||||
@Autowired
|
||||
private ExperienceRoleServiceBean self;
|
||||
|
||||
@Autowired
|
||||
private RoleManagementService roleManagementService;
|
||||
|
||||
@Autowired
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Autowired
|
||||
private RoleService roleService;
|
||||
|
||||
/**
|
||||
* 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 awarded at
|
||||
*/
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> setRoleToLevel(Role role, Integer level, Long channelId) {
|
||||
Long roleId = role.getIdLong();
|
||||
ARole aRoleToSet = roleManagementService.findRole(roleId);
|
||||
public CompletableFuture<Void> setRoleToLevel(Role role, Integer level, GuildMessageChannel messageChannel) {
|
||||
ARole aRoleToSet = roleManagementService.findRole(role.getIdLong());
|
||||
List<AExperienceRole> experienceRoles = getExperienceRolesAtLevel(level, aRoleToSet.getServer());
|
||||
List<ARole> rolesToUnset = experienceRoles.stream().map(AExperienceRole::getRole).collect(Collectors.toList());
|
||||
List<ARole> rolesToUnset = experienceRoles
|
||||
.stream()
|
||||
.map(AExperienceRole::getRole)
|
||||
.collect(Collectors.toList());
|
||||
if(rolesToUnset.size() == 1 && rolesToUnset.contains(aRoleToSet)) {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
if(!rolesToUnset.contains(aRoleToSet)) {
|
||||
rolesToUnset.add(aRoleToSet);
|
||||
}
|
||||
AExperienceLevel experienceLevel;
|
||||
if(!experienceRoles.isEmpty()) {
|
||||
experienceLevel = experienceRoles.get(0).getLevel();
|
||||
} else {
|
||||
experienceLevel = experienceLevelService.getLevel(level);
|
||||
}
|
||||
AExperienceRole newExperienceRole = experienceRoleManagementService.setLevelToRole(experienceLevel, aRoleToSet);
|
||||
Long newlyCreatedExperienceRoleId = newExperienceRole.getId();
|
||||
CompletableFuture<Void> future = new CompletableFuture<>();
|
||||
unsetRoles(rolesToUnset, channelId, newExperienceRole).thenAccept(aVoid ->
|
||||
self.unsetRoleInDb(level, roleId)
|
||||
).thenAccept(unused -> future.complete(null)).exceptionally(throwable -> {
|
||||
self.deleteExperienceRoleViaId(newlyCreatedExperienceRoleId);
|
||||
future.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
|
||||
return future;
|
||||
experienceRoleManagementService.setLevelToRole(experienceLevel, aRoleToSet);
|
||||
if(!rolesToUnset.isEmpty()) {
|
||||
return unsetRoles(rolesToUnset, messageChannel);
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteExperienceRoleViaId(Long newlyCreatedExperienceRoleId) {
|
||||
AExperienceRole reLoadedRole = experienceRoleManagementService.getExperienceRoleById(newlyCreatedExperienceRoleId);
|
||||
experienceRoleManagementService.unsetRole(reLoadedRole);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all previous defined {@link AExperienceRole experienceRoles} from the given level and sets the {@link ARole}
|
||||
* (defined by its ID) to the level.
|
||||
* @param level The level which the {@link ARole role} should be set to
|
||||
* @param roleId The ID of the {@link Role} which should have its level set
|
||||
*/
|
||||
@Transactional
|
||||
public void unsetRoleInDb(Integer level, Long roleId) {
|
||||
log.info("Unsetting role {} from level {}.", roleId, level);
|
||||
AExperienceLevel experienceLevel = experienceLevelService.getLevelOptional(level).orElseThrow(() -> new IllegalArgumentException(String.format("Could not find level %s", level)));
|
||||
ARole loadedRole = roleManagementService.findRole(roleId);
|
||||
experienceRoleManagementService.removeAllRoleAssignmentsForLevelInServerExceptRole(experienceLevel, loadedRole.getServer(), loadedRole);
|
||||
experienceRoleManagementService.setLevelToRole(experienceLevel, loadedRole);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.model.database.AExperienceRole}
|
||||
* configuration
|
||||
*/
|
||||
@Override
|
||||
public CompletableFuture<Void> unsetRoles(ARole role, Long feedbackChannelId) {
|
||||
return unsetRoles(Arrays.asList(role), feedbackChannelId);
|
||||
public CompletableFuture<Void> unsetRoles(ARole role, GuildMessageChannel messageChannel) {
|
||||
return unsetRoles(Arrays.asList(role), messageChannel);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -125,64 +84,56 @@ public class ExperienceRoleServiceBean implements ExperienceRoleService {
|
||||
return experienceRoleManagementService.getExperienceRolesAtLevelInServer(levelObj, server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> unsetRoles(List<ARole> rolesToUnset, Long feedbackChannelId) {
|
||||
return unsetRoles(rolesToUnset, feedbackChannelId, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> unsetRoles(List<ARole> rolesToUnset, Long feedbackChannelId, AExperienceRole toAdd) {
|
||||
if(rolesToUnset.isEmpty()) {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
public CompletableFuture<Void> unsetRoles(List<ARole> rolesToUnset, GuildMessageChannel messageChannel) {
|
||||
List<AExperienceRole> rolesInServer = experienceRoleManagementService.getRolesInServer(rolesToUnset);
|
||||
Integer totalCount = 0;
|
||||
for (AExperienceRole aExperienceRole : rolesInServer) {
|
||||
totalCount += aExperienceRole.getUsers().size();
|
||||
}
|
||||
AServer server = rolesToUnset.get(0).getServer();
|
||||
AChannel channel = channelManagementService.loadChannel(feedbackChannelId);
|
||||
List<AExperienceRole> experienceRolesNecessaryToRemove = new ArrayList<>();
|
||||
List<AUserExperience> usersToUpdate = new ArrayList<>();
|
||||
rolesToUnset.forEach(role -> {
|
||||
Optional<AExperienceRole> roleInServerOptional = experienceRoleManagementService.getRoleInServerOptional(role);
|
||||
if(roleInServerOptional.isPresent()) {
|
||||
AExperienceRole experienceRole = roleInServerOptional.get();
|
||||
experienceRolesNecessaryToRemove.add(experienceRole);
|
||||
usersToUpdate.addAll(experienceRole.getUsers());
|
||||
} else {
|
||||
log.info("Experience role {} is not defined in server {} - skipping unset.", role.getId(), server.getId());
|
||||
AtomicInteger totalCountAtomic = new AtomicInteger(totalCount);
|
||||
long serverId = messageChannel.getGuild().getIdLong();
|
||||
MessageToSend status = getUserSyncStatusUpdateModel(0, totalCount, serverId);
|
||||
Message statusMessage = messageService.createStatusMessage(status, messageChannel).join();
|
||||
AtomicInteger atomicInteger = new AtomicInteger();
|
||||
List<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||
rolesInServer.forEach(experienceRole -> {
|
||||
experienceRole.getUsers().forEach(aUserExperience -> {
|
||||
futures.add(roleService.removeRoleFromUserAsync(aUserExperience.getUser(), experienceRole.getRole()).thenAccept(unused -> {
|
||||
atomicInteger.set(atomicInteger.get() + 1);
|
||||
log.debug("Finished synchronizing {} users.", atomicInteger.get());
|
||||
if(atomicInteger.get() % 50 == 0) {
|
||||
log.info("Notifying for {} current users with synchronize.", atomicInteger.get());
|
||||
MessageToSend newStatus = getUserSyncStatusUpdateModel(atomicInteger.get(), totalCountAtomic.get(), serverId);
|
||||
messageService.updateStatusMessage(messageChannel, statusMessage.getIdLong(), newStatus);
|
||||
}
|
||||
}));
|
||||
});
|
||||
});
|
||||
CompletableFuture<Void> returningFuture = new CompletableFuture<>();
|
||||
experienceRoleManagementService.unsetRoles(rolesInServer);
|
||||
FutureUtils.toSingleFutureGeneric(futures).whenComplete((unused, throwable) -> {
|
||||
MessageToSend newStatus = getUserSyncStatusUpdateModel(atomicInteger.get(), totalCountAtomic.get(), serverId);
|
||||
messageService.updateStatusMessage(messageChannel, statusMessage.getIdLong(), newStatus);
|
||||
if(throwable != null) {
|
||||
log.warn("Failed to unset role in server {}.", serverId, throwable);
|
||||
}
|
||||
returningFuture.complete(null);
|
||||
});
|
||||
log.info("Recalculating the roles for {} users, because their current role was removed from experience tracking.", usersToUpdate.size());
|
||||
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(server);
|
||||
roles.removeIf(role1 -> experienceRolesNecessaryToRemove.stream().anyMatch(aExperienceRole -> aExperienceRole.getId().equals(role1.getId())));
|
||||
if(toAdd != null) {
|
||||
roles.add(toAdd);
|
||||
}
|
||||
roles.sort(Comparator.comparing(innerRole -> innerRole.getLevel().getLevel()));
|
||||
List<Long> roleIds = experienceRolesNecessaryToRemove.stream().map(AExperienceRole::getId).collect(Collectors.toList());
|
||||
if(toAdd != null) {
|
||||
roleIds.removeIf(aLong -> aLong.equals(toAdd.getRole().getId()));
|
||||
}
|
||||
CompletableFutureList<RoleCalculationResult> calculationResults = userExperienceService.executeActionOnUserExperiencesWithFeedBack(usersToUpdate, channel,
|
||||
(AUserExperience ex) -> userExperienceService.updateUserRole(ex, roles, ex.getLevelOrDefault()));
|
||||
return calculationResults.getMainFuture().thenAccept(aVoid -> self.persistData(calculationResults, roleIds));
|
||||
return returningFuture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the changed experience roles for all of the {@link AUserExperience userExperiences} which are referenced in the list of
|
||||
* {@link RoleCalculationResult results}. This is only executed after a role is being "unset", which means, we also
|
||||
* have to remove the existing {@link AExperienceRole experienceRole}
|
||||
* @param results A list of {@link CompletableFuture futures} which each contain a {@link RoleCalculationResult result}, for the members who got
|
||||
* their {@link AExperienceRole experienceRole} removed
|
||||
* @param roleIds The IDs of the {@link AExperienceRole experienceRoles} which were removed from the experience roles
|
||||
*/
|
||||
@Transactional
|
||||
public void persistData(CompletableFutureList<RoleCalculationResult> results, List<Long> roleIds) {
|
||||
log.info("Persisting {} role calculation results.", results.getFutures().size());
|
||||
roleIds.forEach(roleId -> {
|
||||
log.info("Deleting experience role {}.", roleId);
|
||||
deleteExperienceRoleViaId(roleId);
|
||||
});
|
||||
userExperienceService.syncRolesInStorage(results.getObjects());
|
||||
private MessageToSend getUserSyncStatusUpdateModel(Integer current, Integer total, Long serverId) {
|
||||
UserSyncStatusModel statusModel = UserSyncStatusModel
|
||||
.builder()
|
||||
.currentCount(current)
|
||||
.totalUserCount(total)
|
||||
.build();
|
||||
return templateService.renderEmbedTemplate("user_sync_status_message", statusModel, serverId);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AExperienceRole calculateRole(List<AExperienceRole> roles, Integer currentLevel) {
|
||||
if(roles == null || roles.isEmpty()) {
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
package dev.sheldan.abstracto.experience.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.metric.service.CounterMetric;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricService;
|
||||
import dev.sheldan.abstracto.experience.model.ServerExperience;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -20,18 +17,9 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
@Component
|
||||
public class RunTimeExperienceService {
|
||||
|
||||
@Autowired
|
||||
private MetricService metricService;
|
||||
|
||||
public static final String EXPERIENCE_RUNTIME_STORAGE = "experience.runtime.storage";
|
||||
private static final CounterMetric EXPERIENCE_RUNTIME_STORAGE_METRIC = CounterMetric
|
||||
.builder()
|
||||
.name(EXPERIENCE_RUNTIME_STORAGE)
|
||||
.build();
|
||||
|
||||
private Map<Long, List<ServerExperience>> runtimeExperience = new HashMap<>();
|
||||
private Map<Long,Map<Long, Instant>> runtimeExperience = new HashMap<>();
|
||||
private static final Lock lock = new ReentrantLock();
|
||||
public Map<Long, List<ServerExperience>> getRuntimeExperience() {
|
||||
public Map<Long, Map<Long, Instant>> getRuntimeExperience() {
|
||||
return runtimeExperience;
|
||||
}
|
||||
|
||||
@@ -49,12 +37,16 @@ public class RunTimeExperienceService {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
metricService.registerGauge(EXPERIENCE_RUNTIME_STORAGE_METRIC, runtimeExperience, serverList -> serverList.values().stream()
|
||||
.mapToInt(minuteEntry -> minuteEntry.stream()
|
||||
.mapToInt(individualServerList -> individualServerList.getUserInServerIds().size()).sum()).sum(),
|
||||
"Number of entries in runtime experience storage");
|
||||
public void cleanupRunTimeStorage() {
|
||||
Instant now = Instant.now();
|
||||
runtimeExperience.forEach((serverId, userInstantMap) -> {
|
||||
List<Long> userIdsToRemove = new ArrayList<>();
|
||||
userInstantMap.forEach((userId, instant) -> {
|
||||
if(instant.isBefore(now)) {
|
||||
userIdsToRemove.add(userId);
|
||||
}
|
||||
});
|
||||
userIdsToRemove.forEach(userInstantMap::remove);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,7 +3,6 @@ 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.model.database.AExperienceLevel;
|
||||
import dev.sheldan.abstracto.experience.model.database.AExperienceRole;
|
||||
import dev.sheldan.abstracto.experience.repository.ExperienceRoleRepository;
|
||||
@@ -13,6 +12,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@@ -22,7 +22,7 @@ public class ExperienceRoleManagementServiceBean implements ExperienceRoleManage
|
||||
private ExperienceRoleRepository experienceRoleRepository;
|
||||
|
||||
@Autowired
|
||||
private RoleManagementService roleManagementService;
|
||||
private UserExperienceManagementService userExperienceManagementService;
|
||||
|
||||
/**
|
||||
* Removes *all* assignments of roles for the given level
|
||||
@@ -46,12 +46,30 @@ public class ExperienceRoleManagementServiceBean implements ExperienceRoleManage
|
||||
experienceRoleRepository.delete(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsetRoles(List<AExperienceRole> roles) {
|
||||
log.info("Deleting {} roles.", roles.size());
|
||||
roles.forEach(experienceRole -> {
|
||||
userExperienceManagementService.removeExperienceRoleFromUsers(experienceRole);
|
||||
});
|
||||
experienceRoleRepository.deleteAll(roles);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AExperienceRole getRoleInServer(ARole role) {
|
||||
// TODO throw different exception
|
||||
return this.getRoleInServerOptional(role).orElseThrow(AbstractoRunTimeException::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AExperienceRole> getRolesInServer(List<ARole> roles) {
|
||||
List<Long> roleIds = roles
|
||||
.stream()
|
||||
.map(ARole::getId)
|
||||
.collect(Collectors.toList());
|
||||
return experienceRoleRepository.findByRole_IdIn(roleIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<AExperienceRole> getRoleInServerOptional(ARole role) {
|
||||
return experienceRoleRepository.findByRole(role);
|
||||
|
||||
@@ -5,6 +5,7 @@ import dev.sheldan.abstracto.core.exception.UserInServerNotFoundException;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.experience.model.database.AExperienceLevel;
|
||||
import dev.sheldan.abstracto.experience.model.database.AExperienceRole;
|
||||
import dev.sheldan.abstracto.experience.model.database.AUserExperience;
|
||||
import dev.sheldan.abstracto.experience.model.database.LeaderBoardEntryResult;
|
||||
import dev.sheldan.abstracto.experience.repository.UserExperienceRepository;
|
||||
@@ -32,6 +33,11 @@ public class UserExperienceManagementServiceBean implements UserExperienceManage
|
||||
return byId.orElseGet(() -> createUserInServer(aUserInAServer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeExperienceRoleFromUsers(AExperienceRole experienceRole) {
|
||||
repository.removeExperienceRoleFromUsers(experienceRole.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<AUserExperience> findByUserInServerIdOptional(Long userInServerId) {
|
||||
return repository.findById(userInServerId);
|
||||
|
||||
@@ -6,4 +6,11 @@ abstracto.systemConfigs.expMultiplier.name=expMultiplier
|
||||
abstracto.systemConfigs.expMultiplier.doubleValue=1
|
||||
|
||||
abstracto.featureFlags.experience.featureName=experience
|
||||
abstracto.featureFlags.experience.enabled=false
|
||||
abstracto.featureFlags.experience.enabled=false
|
||||
|
||||
abstracto.systemConfigs.expCooldownSeconds.name=expCooldownSeconds
|
||||
abstracto.systemConfigs.expCooldownSeconds.longValue=60
|
||||
|
||||
abstracto.featureModes.levelUpNotification.featureName=experience
|
||||
abstracto.featureModes.levelUpNotification.mode=levelUpNotification
|
||||
abstracto.featureModes.levelUpNotification.enabled=false
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
|
||||
<include file="update/updates.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
|
||||
<include file="user_experience.xml" relativeToChangelogFile="true"/>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<changeSet author="Sheldan" id="drop_user_experience_role_foreign_key">
|
||||
<dropForeignKeyConstraint baseTableName="user_experience" constraintName="fk_user_experience_role" />
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
|
||||
<changeSet author="Sheldan" id="experience-job-update_schedule">
|
||||
<update tableName="scheduler_job">
|
||||
<column name="cron_expression" value="0 0 * * * ?"/>
|
||||
<column name="clazz" value="dev.sheldan.abstracto.experience.job.ExperienceCleanupJob"/>
|
||||
<where>name='experienceJob'</where>
|
||||
</update>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
|
||||
<include file="jobs.xml" relativeToChangelogFile="true"/>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -8,4 +8,5 @@
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="1.0-experience/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.2.15/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.4.8/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -1,57 +0,0 @@
|
||||
package dev.sheldan.abstracto.experience.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.service.RoleService;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
|
||||
import dev.sheldan.abstracto.experience.service.ExperienceRoleService;
|
||||
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.Arrays;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SetExpRoleTest {
|
||||
|
||||
@InjectMocks
|
||||
private SetExpRole testUnit;
|
||||
|
||||
@Mock
|
||||
private ExperienceRoleService experienceRoleService;
|
||||
|
||||
@Mock
|
||||
private RoleService roleService;
|
||||
|
||||
@Mock
|
||||
private RoleManagementService roleManagementService;
|
||||
|
||||
private static final Long CHANNEL_ID = 4L;
|
||||
|
||||
@Test
|
||||
public void setExpRole() {
|
||||
CommandContext noParameters = CommandTestUtilities.getNoParameters();
|
||||
Role roleToChange = Mockito.mock(Role.class);
|
||||
when(roleToChange.getGuild()).thenReturn(noParameters.getGuild());
|
||||
Integer levelToSetTo = 4;
|
||||
when(noParameters.getChannel().getIdLong()).thenReturn(CHANNEL_ID);
|
||||
CommandContext context = CommandTestUtilities.enhanceWithParameters(noParameters, Arrays.asList(levelToSetTo, roleToChange));
|
||||
when(experienceRoleService.setRoleToLevel(roleToChange, levelToSetTo, CHANNEL_ID)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
CompletableFuture<CommandResult> result = testUnit.executeAsync(context);
|
||||
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateCommand() {
|
||||
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@ import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
|
||||
import dev.sheldan.abstracto.experience.service.AUserExperienceService;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
@@ -28,21 +30,19 @@ public class SyncRolesTest {
|
||||
@Mock
|
||||
private AUserExperienceService userExperienceService;
|
||||
|
||||
@Mock
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Mock
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
private static final Long CHANNEL_ID = 4L;
|
||||
@Mock
|
||||
private GuildMessageChannel messageChannel;
|
||||
|
||||
@Test
|
||||
public void executeCommand() {
|
||||
CommandContext context = CommandTestUtilities.getNoParameters();
|
||||
CommandContext context = Mockito.mock(CommandContext.class);
|
||||
AServer server = Mockito.mock(AServer.class);
|
||||
when(serverManagementService.loadServer(context.getGuild())).thenReturn(server);
|
||||
when(context.getChannel().getIdLong()).thenReturn(CHANNEL_ID);
|
||||
when(userExperienceService.syncUserRolesWithFeedback(server, CHANNEL_ID)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(context.getChannel()).thenReturn(messageChannel);
|
||||
when(userExperienceService.syncUserRolesWithFeedback(server, messageChannel)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
CompletableFuture<CommandResult> result = testUnit.executeAsync(context);
|
||||
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
|
||||
}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
package dev.sheldan.abstracto.experience.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
|
||||
import dev.sheldan.abstracto.experience.model.database.AExperienceRole;
|
||||
import dev.sheldan.abstracto.experience.service.ExperienceRoleService;
|
||||
import dev.sheldan.abstracto.experience.service.management.ExperienceRoleManagementService;
|
||||
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.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class UnSetExpRoleTest {
|
||||
|
||||
@InjectMocks
|
||||
private UnSetExpRole testUnit;
|
||||
|
||||
@Mock
|
||||
private ExperienceRoleService experienceRoleService;
|
||||
|
||||
@Mock
|
||||
private RoleManagementService roleManagementService;
|
||||
|
||||
@Mock
|
||||
private ExperienceRoleManagementService experienceRoleManagementService;
|
||||
|
||||
private static final Long CHANNEL_ID = 4L;
|
||||
|
||||
@Test
|
||||
public void setUnSetExpRole() {
|
||||
CommandContext noParameters = CommandTestUtilities.getNoParameters();
|
||||
ARole changedRole = Mockito.mock(ARole.class);
|
||||
CommandContext context = CommandTestUtilities.enhanceWithParameters(noParameters, Arrays.asList(changedRole));
|
||||
when(context.getChannel().getIdLong()).thenReturn(CHANNEL_ID);
|
||||
ARole actualRole = Mockito.mock(ARole.class);
|
||||
AServer server = Mockito.mock(AServer.class);
|
||||
when(actualRole.getServer()).thenReturn(server);
|
||||
when(roleManagementService.findRole(changedRole.getId())).thenReturn(actualRole);
|
||||
when(experienceRoleManagementService.getRoleInServerOptional(actualRole)).thenReturn(Optional.of(Mockito.mock(AExperienceRole.class)));
|
||||
when(experienceRoleService.unsetRoles(actualRole, CHANNEL_ID)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
CompletableFuture<CommandResult> result = testUnit.executeAsync(context);
|
||||
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateCommand() {
|
||||
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package dev.sheldan.abstracto.experience.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.experience.service.AUserExperienceService;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageType;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.entities.channel.unions.MessageChannelUnion;
|
||||
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 static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ExperienceTrackerListenerTest {
|
||||
|
||||
@InjectMocks
|
||||
public ExperienceTrackerListener testUnit;
|
||||
|
||||
@Mock
|
||||
private AUserExperienceService userExperienceService;
|
||||
|
||||
@Mock
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Mock
|
||||
private MessageReceivedModel model;
|
||||
|
||||
@Mock
|
||||
private User user;
|
||||
|
||||
private static final Long SERVER_ID = 4L;
|
||||
private static final Long USER_ID = 5L;
|
||||
|
||||
@Test
|
||||
public void testExperienceTracking() {
|
||||
AUserInAServer userInAServer = Mockito.mock(AUserInAServer.class);
|
||||
Message mockedMessage = Mockito.mock(Message.class);
|
||||
when(mockedMessage.isFromGuild()).thenReturn(true);
|
||||
when(mockedMessage.isWebhookMessage()).thenReturn(false);
|
||||
MessageChannelUnion channel = Mockito.mock(MessageChannelUnion.class);
|
||||
MessageType type = MessageType.DEFAULT;
|
||||
when(mockedMessage.getType()).thenReturn(type);
|
||||
when(userInServerManagementService.loadOrCreateUser(SERVER_ID, USER_ID)).thenReturn(userInAServer);
|
||||
when(model.getMessage()).thenReturn(mockedMessage);
|
||||
when(userExperienceService.experienceGainEnabledInChannel(channel)).thenReturn(true);
|
||||
when(mockedMessage.getChannel()).thenReturn(channel);
|
||||
when(model.getServerId()).thenReturn(SERVER_ID);
|
||||
when(mockedMessage.getAuthor()).thenReturn(user);
|
||||
when(user.getIdLong()).thenReturn(USER_ID);
|
||||
testUnit.execute(model);
|
||||
verify(userExperienceService, times(1)).addExperience(userInAServer);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import dev.sheldan.abstracto.core.service.management.UserInServerManagementServi
|
||||
import dev.sheldan.abstracto.experience.model.database.AUserExperience;
|
||||
import dev.sheldan.abstracto.experience.service.AUserExperienceService;
|
||||
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -46,6 +47,9 @@ public class JoiningUserRoleListenerTest {
|
||||
@Mock
|
||||
private MemberJoinModel model;
|
||||
|
||||
@Mock
|
||||
private Member member;
|
||||
|
||||
private static final Long SERVER_ID = 1L;
|
||||
private static final Long USER_ID = 2L;
|
||||
private static final Long USER_IN_SERVER_ID = 3L;
|
||||
@@ -63,7 +67,8 @@ public class JoiningUserRoleListenerTest {
|
||||
public void testUserWithExperienceRejoining() {
|
||||
AUserExperience experience = Mockito.mock(AUserExperience.class);
|
||||
when(userExperienceManagementService.findByUserInServerIdOptional(USER_IN_SERVER_ID)).thenReturn(Optional.of(experience));
|
||||
when(userExperienceService.syncForSingleUser(experience)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(userExperienceService.syncForSingleUser(experience, member)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(model.getMember()).thenReturn(member);
|
||||
DefaultListenerResult result = testUnit.execute(model);
|
||||
Assert.assertEquals(DefaultListenerResult.PROCESSED, result);
|
||||
}
|
||||
@@ -72,7 +77,7 @@ public class JoiningUserRoleListenerTest {
|
||||
public void testUserWithOutExperienceRejoining() {
|
||||
when(userExperienceManagementService.findByUserInServerIdOptional(USER_IN_SERVER_ID)).thenReturn(Optional.empty());
|
||||
testUnit.execute(model);
|
||||
verify(userExperienceService, times(0)).syncForSingleUser(any());
|
||||
verify(userExperienceService, times(0)).syncForSingleUser(any(), any());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,830 +0,0 @@
|
||||
package dev.sheldan.abstracto.experience.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
|
||||
import dev.sheldan.abstracto.core.service.*;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.DefaultConfigManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.experience.config.ExperienceFeatureConfig;
|
||||
import dev.sheldan.abstracto.experience.exception.NoExperienceTrackedException;
|
||||
import dev.sheldan.abstracto.experience.model.*;
|
||||
import dev.sheldan.abstracto.experience.model.database.AExperienceLevel;
|
||||
import dev.sheldan.abstracto.experience.model.database.AExperienceRole;
|
||||
import dev.sheldan.abstracto.experience.model.database.AUserExperience;
|
||||
import dev.sheldan.abstracto.experience.model.database.LeaderBoardEntryResult;
|
||||
import dev.sheldan.abstracto.experience.model.template.UserSyncStatusModel;
|
||||
import dev.sheldan.abstracto.experience.service.management.DisabledExpRoleManagementService;
|
||||
import dev.sheldan.abstracto.experience.service.management.ExperienceLevelManagementService;
|
||||
import dev.sheldan.abstracto.experience.service.management.ExperienceRoleManagementService;
|
||||
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.*;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
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.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AUserExperienceServiceBeanTest {
|
||||
|
||||
@InjectMocks
|
||||
private AUserExperienceServiceBean testUnit;
|
||||
|
||||
@Mock
|
||||
private UserExperienceManagementService userExperienceManagementService;
|
||||
|
||||
@Mock
|
||||
private ExperienceRoleService experienceRoleService;
|
||||
|
||||
@Mock
|
||||
private ExperienceLevelManagementService experienceLevelManagementService;
|
||||
|
||||
@Mock
|
||||
private ExperienceRoleManagementService experienceRoleManagementService;
|
||||
|
||||
@Mock
|
||||
private ConfigService configService;
|
||||
|
||||
@Mock
|
||||
private RoleService roleService;
|
||||
|
||||
@Mock
|
||||
private MessageService messageService;
|
||||
|
||||
@Mock
|
||||
private TemplateService templateService;
|
||||
|
||||
@Mock
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Mock
|
||||
private DisabledExpRoleManagementService disabledExpRoleManagementService;
|
||||
|
||||
@Mock
|
||||
private MemberService memberService;
|
||||
|
||||
@Mock
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Mock
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Mock
|
||||
private AUserExperienceServiceBean self;
|
||||
|
||||
@Mock
|
||||
private DefaultConfigManagementService defaultConfigManagementService;
|
||||
|
||||
@Mock
|
||||
private AUserExperience userExperience;
|
||||
|
||||
@Mock
|
||||
private AUserExperience userExperience2;
|
||||
|
||||
@Mock
|
||||
private AUserInAServer aUserInAServer;
|
||||
|
||||
@Mock
|
||||
private AUserInAServer aUserInAServer2;
|
||||
|
||||
@Mock
|
||||
private AUser user;
|
||||
|
||||
@Mock
|
||||
private AUser user2;
|
||||
|
||||
@Mock
|
||||
private ServerExperience serverExperience;
|
||||
|
||||
@Mock
|
||||
private AServer server;
|
||||
|
||||
@Mock
|
||||
private Member firstMember;
|
||||
|
||||
@Mock
|
||||
private Member secondMember;
|
||||
|
||||
@Mock
|
||||
private AExperienceLevel level0;
|
||||
|
||||
@Mock
|
||||
private AExperienceLevel level1;
|
||||
|
||||
@Mock
|
||||
private AExperienceLevel level2;
|
||||
|
||||
@Mock
|
||||
private AExperienceLevel level3;
|
||||
|
||||
@Mock
|
||||
private AExperienceRole experienceRole1;
|
||||
|
||||
@Mock
|
||||
private ARole aRole1;
|
||||
|
||||
@Mock
|
||||
private AExperienceRole experienceRole2;
|
||||
|
||||
@Mock
|
||||
private ARole aRole2;
|
||||
|
||||
private List<AExperienceLevel> levels = new ArrayList<>();
|
||||
private List<AExperienceRole> experienceRoles = new ArrayList<>();
|
||||
|
||||
private static final Long USER_IN_SERVER_ID = 4L;
|
||||
private static final Long USER_ID = 8L;
|
||||
private static final Long SERVER_ID = 9L;
|
||||
private static final Long CHANNEL_ID = 7L;
|
||||
private static final Long DEFAULT_MIN_EXP = 10L;
|
||||
private static final Long DEFAULT_MAX_EXP = 25L;
|
||||
private static final Double DEFAULT_EXP_MULTIPLIER = 1D;
|
||||
private static final Long LOW_EXP = 50L;
|
||||
private static final Long MID_EXP = 250L;
|
||||
private static final Long HIGH_EXP = 500L;
|
||||
private static final Long LVL_0_EXP = 0L;
|
||||
private static final Long LVL_1_EXP = 100L;
|
||||
private static final Long LVL_2_EXP = 200L;
|
||||
private static final Long LVL_3_EXP = 300L;
|
||||
private static final Integer ZERO_LVL = 0;
|
||||
private static final Integer SECOND_LVL = 2;
|
||||
|
||||
private static final Long ROLE_ID = 4L;
|
||||
private static final Long SECOND_ROLE_ID = 7L;
|
||||
private static final Long MESSAGE_COUNT = 10L;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.levels = Arrays.asList(level0, level1, level2, level3);
|
||||
this.experienceRoles = Arrays.asList(experienceRole1, experienceRole2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateLevelTooLow() {
|
||||
this.levels = Arrays.asList(level0, level1);
|
||||
setupLevels(1);
|
||||
AExperienceLevel calculatedLevel = testUnit.calculateLevel(levels, LOW_EXP);
|
||||
Assert.assertEquals(level0, calculatedLevel);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateLevelBetweenLevels() {
|
||||
this.levels = Arrays.asList(level0, level1, level2);
|
||||
setupLevels(3);
|
||||
AExperienceLevel calculatedLevel = testUnit.calculateLevel(levels, MID_EXP);
|
||||
Assert.assertEquals(level2, calculatedLevel);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateLevelTooHigh() {
|
||||
this.levels = Arrays.asList(level0, level1, level2, level3);
|
||||
setupLevels(3);
|
||||
AExperienceLevel calculatedLevel = testUnit.calculateLevel(levels, HIGH_EXP);
|
||||
Assert.assertEquals(level3, calculatedLevel);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateUserExperienceLevelChanged() {
|
||||
AUserExperience experienceToCalculate = Mockito.mock(AUserExperience.class);
|
||||
when(experienceToCalculate.getUser()).thenReturn(aUserInAServer);
|
||||
when(aUserInAServer.getUserReference()).thenReturn(user);
|
||||
when(experienceToCalculate.getCurrentLevel()).thenReturn(level0);
|
||||
when(level0.getLevel()).thenReturn(ZERO_LVL);
|
||||
when(level2.getLevel()).thenReturn(SECOND_LVL);
|
||||
setupLevels(3);
|
||||
Assert.assertTrue(testUnit.updateUserLevel(experienceToCalculate, levels, MID_EXP));
|
||||
verify(experienceToCalculate, times(1)).setCurrentLevel(level2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateUserExperienceLevelNotChanged() {
|
||||
AUserExperience experienceToCalculate = Mockito.mock(AUserExperience.class);
|
||||
when(experienceToCalculate.getCurrentLevel()).thenReturn(level2);
|
||||
when(experienceToCalculate.getExperience()).thenReturn(MID_EXP);
|
||||
setupLevels(3);
|
||||
Assert.assertFalse(testUnit.updateUserLevel(experienceToCalculate, levels, experienceToCalculate.getExperience()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleExperienceGainSingleUser() {
|
||||
when(serverExperience.getUserInServerIds()).thenReturn(Arrays.asList(USER_IN_SERVER_ID));
|
||||
when(userInServerManagementService.loadOrCreateUser(USER_IN_SERVER_ID)).thenReturn(aUserInAServer);
|
||||
when(memberService.getMemberInServerAsync(aUserInAServer)).thenReturn(CompletableFuture.completedFuture(firstMember));
|
||||
when(serverExperience.getServerId()).thenReturn(SERVER_ID);
|
||||
testUnit.handleExperienceGain(Arrays.asList(serverExperience)).join();
|
||||
ArgumentCaptor<List<CompletableFuture<Member>>> listArgumentCaptor = ArgumentCaptor.forClass(List.class);
|
||||
verify(self, times(1)).updateFoundMembers(listArgumentCaptor.capture(), eq(SERVER_ID), anyList(), anyList());
|
||||
Assert.assertEquals(firstMember, listArgumentCaptor.getValue().get(0).join());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleExperienceMemberFailed() {
|
||||
when(serverExperience.getUserInServerIds()).thenReturn(Arrays.asList(USER_IN_SERVER_ID));
|
||||
when(userInServerManagementService.loadOrCreateUser(USER_IN_SERVER_ID)).thenReturn(aUserInAServer);
|
||||
CompletableFuture<Member> future = new CompletableFuture<>();
|
||||
when(memberService.getMemberInServerAsync(aUserInAServer)).thenReturn(future);
|
||||
future.completeExceptionally(new RuntimeException());
|
||||
when(serverExperience.getServerId()).thenReturn(SERVER_ID);
|
||||
testUnit.handleExperienceGain(Arrays.asList(serverExperience)).join();
|
||||
ArgumentCaptor<List<CompletableFuture<Member>>> listArgumentCaptor = ArgumentCaptor.forClass(List.class);
|
||||
verify(self, times(1)).updateFoundMembers(listArgumentCaptor.capture(), eq(SERVER_ID), anyList(), anyList());
|
||||
Assert.assertTrue(listArgumentCaptor.getValue().get(0).isCompletedExceptionally());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGainExpSingleUserLvlUpOneServerWithoutRole() {
|
||||
/*
|
||||
* In this scenario, the user has a role before, but the config changed, and now there are no experience roles.
|
||||
* Hence the user should lose the experience role.
|
||||
*/
|
||||
setupServerId();
|
||||
setupLevels(3);
|
||||
when(experienceRole1.getRole()).thenReturn(aRole1);
|
||||
setExperienceRoleLevels();
|
||||
setupServerConfig();
|
||||
setupDefaultConfig();
|
||||
setupLevelsAndRolesAndNoDisallowed();
|
||||
setupUserInServer();
|
||||
when(userExperience.getMessageCount()).thenReturn(MESSAGE_COUNT);
|
||||
when(experienceRoleService.calculateRole(eq(experienceRoles), any())).thenReturn(null);
|
||||
when(userExperience.getExperience()).thenReturn(500L);
|
||||
when(userExperienceManagementService.findByUserInServerIdOptional(USER_IN_SERVER_ID)).thenReturn(Optional.of(userExperience));
|
||||
when(userExperience.getCurrentExperienceRole()).thenReturn(experienceRole1);
|
||||
when(userExperience.getUser()).thenReturn(aUserInAServer);
|
||||
when(roleService.removeRoleFromUserAsync(aUserInAServer, aRole1)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
ArrayList<ExperienceGainResult> experienceResults = new ArrayList<>();
|
||||
ArrayList<CompletableFuture<RoleCalculationResult>> roleCalculationResults = new ArrayList<>();
|
||||
List<CompletableFuture<Member>> memberFutures = Arrays.asList(CompletableFuture.completedFuture(firstMember));
|
||||
testUnit.updateFoundMembers(memberFutures, SERVER_ID, experienceResults, roleCalculationResults);
|
||||
Assert.assertEquals(1, experienceResults.size());
|
||||
ExperienceGainResult result = experienceResults.get(0);
|
||||
Assert.assertEquals(MESSAGE_COUNT + 1, result.getNewMessageCount().longValue());
|
||||
Assert.assertEquals(1, roleCalculationResults.size());
|
||||
RoleCalculationResult roleCalcResult = roleCalculationResults.get(0).join();
|
||||
Assert.assertNull(roleCalcResult.getExperienceRoleId());
|
||||
Assert.assertEquals(USER_IN_SERVER_ID, roleCalcResult.getUserInServerId());
|
||||
verify(roleService, times(1)).removeRoleFromUserAsync(aUserInAServer, aRole1);
|
||||
verify(roleService, times(0)).addRoleToUserAsync(any(AUserInAServer.class), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLevelUpGainingNewRoleButUserAlreadyHasRole() {
|
||||
setupServerId();
|
||||
setupServerConfig();
|
||||
setupDefaultConfig();
|
||||
setupLevelsAndRolesAndNoDisallowed();
|
||||
when(memberService.getMemberInServerAsync(aUserInAServer)).thenReturn(CompletableFuture.completedFuture(firstMember));
|
||||
setupUserInServer();
|
||||
when(userExperience.getExperience()).thenReturn(199L);
|
||||
when(experienceRole1.getLevel()).thenReturn(level0);
|
||||
when(experienceRole2.getRole()).thenReturn(aRole2);
|
||||
when(experienceRole2.getLevel()).thenReturn(level1);
|
||||
AExperienceRole newRole = experienceRole2;
|
||||
when(aRole2.getId()).thenReturn(ROLE_ID);
|
||||
when(experienceRoleService.calculateRole(eq(experienceRoles), any())).thenReturn(newRole);
|
||||
when(roleService.memberHasRole(firstMember, ROLE_ID)).thenReturn(true);
|
||||
when(userExperienceManagementService.findByUserInServerIdOptional(USER_IN_SERVER_ID)).thenReturn(Optional.of(userExperience));
|
||||
ArrayList<ExperienceGainResult> experienceResults = new ArrayList<>();
|
||||
ArrayList<CompletableFuture<RoleCalculationResult>> roleCalculationResults = new ArrayList<>();
|
||||
List<CompletableFuture<Member>> memberFutures = Arrays.asList(CompletableFuture.completedFuture(firstMember));
|
||||
testUnit.updateFoundMembers(memberFutures, SERVER_ID, experienceResults, roleCalculationResults);
|
||||
verify(roleService, times(0)).addRoleToMember(any(AUserInAServer.class), any(ARole.class));
|
||||
verify(roleService, times(0)).removeRoleFromUser(any(AUserInAServer.class), any(ARole.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLevelUpNotGainingNewRole() {
|
||||
setupServerId();
|
||||
when(experienceRole1.getRole()).thenReturn(aRole1);
|
||||
setExperienceRoleLevels();
|
||||
when(aRole1.getId()).thenReturn(ROLE_ID);
|
||||
setupServerConfig();
|
||||
setupDefaultConfig();
|
||||
setupLevelsAndRolesAndNoDisallowed();
|
||||
when(memberService.getMemberInServerAsync(aUserInAServer)).thenReturn(CompletableFuture.completedFuture(firstMember));
|
||||
setupUserInServer();
|
||||
when(userExperience.getExperience()).thenReturn(500L);
|
||||
when(userExperienceManagementService.findByUserInServerIdOptional(USER_IN_SERVER_ID)).thenReturn(Optional.of(userExperience));
|
||||
AExperienceRole newRole = experienceRole1;
|
||||
when(userExperience.getCurrentExperienceRole()).thenReturn(newRole);
|
||||
when(experienceRoleService.calculateRole(eq(experienceRoles), any())).thenReturn(newRole);
|
||||
|
||||
when(roleService.memberHasRole(firstMember, ROLE_ID)).thenReturn(true);
|
||||
ArrayList<ExperienceGainResult> experienceResults = new ArrayList<>();
|
||||
ArrayList<CompletableFuture<RoleCalculationResult>> roleCalculationResults = new ArrayList<>();
|
||||
List<CompletableFuture<Member>> memberFutures = Arrays.asList(CompletableFuture.completedFuture(firstMember));
|
||||
testUnit.updateFoundMembers(memberFutures, SERVER_ID, experienceResults, roleCalculationResults);
|
||||
verify(roleService, times(0)).addRoleToMember(any(AUserInAServer.class), any(ARole.class));
|
||||
verify(roleService, times(0)).removeRoleFromUser(any(AUserInAServer.class), any(ARole.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleExperienceForUserNotLevelingUpWithoutExistingRole() {
|
||||
setupServerId();
|
||||
when(userExperience.getCurrentExperienceRole()).thenReturn(null);
|
||||
setupServerConfig();
|
||||
setupDefaultConfig();
|
||||
setupLevelsAndRolesAndNoDisallowed();
|
||||
when(memberService.getMemberInServerAsync(aUserInAServer)).thenReturn(CompletableFuture.completedFuture(firstMember));
|
||||
setupUserInServer();
|
||||
when(userExperience.getExperience()).thenReturn(500L);
|
||||
AExperienceRole newRole = experienceRole1;
|
||||
when(experienceRoleService.calculateRole(eq(experienceRoles), any())).thenReturn(newRole);
|
||||
when(aRole1.getId()).thenReturn(ROLE_ID);
|
||||
setupTwoExperienceRoles();
|
||||
when(roleService.memberHasRole(firstMember, ROLE_ID)).thenReturn(false);
|
||||
when(roleService.addRoleToMemberAsync(firstMember, ROLE_ID)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(userExperienceManagementService.findByUserInServerIdOptional(USER_IN_SERVER_ID)).thenReturn(Optional.of(userExperience));
|
||||
when(roleService.addRoleToMemberAsync(firstMember, ROLE_ID)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
ArrayList<ExperienceGainResult> experienceResults = new ArrayList<>();
|
||||
ArrayList<CompletableFuture<RoleCalculationResult>> roleCalculationResults = new ArrayList<>();
|
||||
List<CompletableFuture<Member>> memberFutures = Arrays.asList(CompletableFuture.completedFuture(firstMember));
|
||||
testUnit.updateFoundMembers(memberFutures, SERVER_ID, experienceResults, roleCalculationResults);
|
||||
verify(roleService, times(0)).addRoleToUserAsync(any(AUserInAServer.class), any(ARole.class));
|
||||
verify(roleService, times(0)).removeRoleFromUserAsync(any(AUserInAServer.class), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleExpGainWithTooLittleForRole() {
|
||||
setupServerId();
|
||||
setupServerConfig();
|
||||
setupDefaultConfig();
|
||||
setupLevelsAndRolesAndNoDisallowed();
|
||||
setupUserInServer();
|
||||
when(userExperience.getExperience()).thenReturn(50L);
|
||||
setExperienceRoleLevels();
|
||||
when(userExperience.getCurrentExperienceRole()).thenReturn(null);
|
||||
when(experienceRoleService.calculateRole(eq(experienceRoles), any())).thenReturn(null);
|
||||
|
||||
ArrayList<ExperienceGainResult> experienceResults = new ArrayList<>();
|
||||
ArrayList<CompletableFuture<RoleCalculationResult>> roleCalculationResults = new ArrayList<>();
|
||||
List<CompletableFuture<Member>> memberFutures = Arrays.asList(CompletableFuture.completedFuture(firstMember));
|
||||
testUnit.updateFoundMembers(memberFutures, SERVER_ID, experienceResults, roleCalculationResults);
|
||||
verify(roleService, times(0)).removeRoleFromUserAsync(any(AUserInAServer.class), any());
|
||||
verify(roleService, times(0)).addRoleToUserAsync(any(AUserInAServer.class), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserHasExperienceRoleButNotAnymore() {
|
||||
setupServerId();
|
||||
setupServerConfig();
|
||||
setupDefaultConfig();
|
||||
setupLevelsAndRolesAndNoDisallowed();
|
||||
setupUserInServer();
|
||||
when(userExperience.getExperience()).thenReturn(50L);
|
||||
AExperienceRole previousExperienceRole = experienceRole1;
|
||||
when(userExperience.getCurrentExperienceRole()).thenReturn(previousExperienceRole);
|
||||
when(experienceRole1.getRole()).thenReturn(aRole1);
|
||||
setExperienceRoleLevels();
|
||||
when(experienceRoleService.calculateRole(eq(experienceRoles), any())).thenReturn(null);
|
||||
|
||||
when(roleService.removeRoleFromUserAsync(eq(aUserInAServer), any())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(userExperienceManagementService.findByUserInServerIdOptional(USER_IN_SERVER_ID)).thenReturn(Optional.of(userExperience));
|
||||
ArrayList<ExperienceGainResult> experienceResults = new ArrayList<>();
|
||||
ArrayList<CompletableFuture<RoleCalculationResult>> roleCalculationResults = new ArrayList<>();
|
||||
List<CompletableFuture<Member>> memberFutures = Arrays.asList(CompletableFuture.completedFuture(firstMember));
|
||||
testUnit.updateFoundMembers(memberFutures, SERVER_ID, experienceResults, roleCalculationResults);
|
||||
verify(roleService, times(0)).addRoleToUserAsync(eq(aUserInAServer), any());
|
||||
verify(roleService, times(1)).removeRoleFromUserAsync(eq(aUserInAServer), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleExperienceGainForGainDisabledForUser() {
|
||||
setupServerId();
|
||||
setupServerConfig();
|
||||
setupDefaultConfig();
|
||||
setupLevelsAndRolesAndNoDisallowed();
|
||||
setExperienceRoleLevels();
|
||||
when(userExperience.getExperienceGainDisabled()).thenReturn(true);
|
||||
|
||||
ArrayList<ExperienceGainResult> experienceResults = new ArrayList<>();
|
||||
ArrayList<CompletableFuture<RoleCalculationResult>> roleCalculationResults = new ArrayList<>();
|
||||
when(aUserInAServer.getUserInServerId()).thenReturn(USER_IN_SERVER_ID);
|
||||
when(userInServerManagementService.loadOrCreateUser(firstMember)).thenReturn(aUserInAServer);
|
||||
List<CompletableFuture<Member>> memberFutures = Arrays.asList(CompletableFuture.completedFuture(firstMember));
|
||||
|
||||
when(userExperienceManagementService.findByUserInServerIdOptional(USER_IN_SERVER_ID)).thenReturn(Optional.of(userExperience));
|
||||
testUnit.updateFoundMembers(memberFutures, SERVER_ID, experienceResults, roleCalculationResults);
|
||||
verify(roleService, times(0)).removeRoleFromUserAsync(eq(aUserInAServer), any());
|
||||
verify(roleService, times(0)).addRoleToUserAsync(eq(aUserInAServer), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleExperienceGainForGainDisabledForRole() {
|
||||
setupServerId();
|
||||
setupServerConfig();
|
||||
setupDefaultConfig();
|
||||
setupLevelsAndRolesAndNoDisallowed();
|
||||
setExperienceRoleLevels();
|
||||
when(experienceRole1.getLevel()).thenReturn(level0);
|
||||
when(experienceRole2.getLevel()).thenReturn(level1);
|
||||
ArrayList<ExperienceGainResult> experienceResults = new ArrayList<>();
|
||||
ArrayList<CompletableFuture<RoleCalculationResult>> roleCalculationResults = new ArrayList<>();
|
||||
when(roleService.hasAnyOfTheRoles(eq(firstMember), anyList())).thenReturn(true);
|
||||
when(aUserInAServer.getUserInServerId()).thenReturn(USER_IN_SERVER_ID);
|
||||
when(userInServerManagementService.loadOrCreateUser(firstMember)).thenReturn(aUserInAServer);
|
||||
List<CompletableFuture<Member>> memberFutures = Arrays.asList(CompletableFuture.completedFuture(firstMember));
|
||||
testUnit.updateFoundMembers(memberFutures, SERVER_ID, experienceResults, roleCalculationResults);
|
||||
verify(roleService, times(0)).removeRoleFromUser(aUserInAServer, aRole1);
|
||||
verify(roleService, times(0)).addRoleToMember(eq(aUserInAServer), any(ARole.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleExperienceForUserNotLevelingUpWithExistingRole() {
|
||||
setupServerId();
|
||||
when(userExperienceManagementService.findByUserInServerIdOptional(USER_IN_SERVER_ID)).thenReturn(Optional.of(userExperience));
|
||||
when(userExperience.getUser()).thenReturn(aUserInAServer);
|
||||
when(aUserInAServer.getUserReference()).thenReturn(user);
|
||||
when(aUserInAServer.getServerReference()).thenReturn(server);
|
||||
when(roleService.hasAnyOfTheRoles(eq(firstMember), anyList())).thenReturn(false);
|
||||
when(user.getId()).thenReturn(USER_ID);
|
||||
setExperienceRoleLevels();
|
||||
|
||||
setupServerConfig();
|
||||
setupDefaultConfig();
|
||||
setupLevelsAndRolesAndNoDisallowed();
|
||||
|
||||
when(aUserInAServer.getUserInServerId()).thenReturn(USER_IN_SERVER_ID);
|
||||
when(userInServerManagementService.loadOrCreateUser(firstMember)).thenReturn(aUserInAServer);
|
||||
|
||||
ArrayList<ExperienceGainResult> experienceResults = new ArrayList<>();
|
||||
ArrayList<CompletableFuture<RoleCalculationResult>> roleCalculationResults = new ArrayList<>();
|
||||
List<CompletableFuture<Member>> memberFutures = Arrays.asList(CompletableFuture.completedFuture(firstMember));
|
||||
testUnit.updateFoundMembers(memberFutures, SERVER_ID, experienceResults, roleCalculationResults);
|
||||
verify(roleService, times(0)).removeRoleFromUser(aUserInAServer, aRole1);
|
||||
verify(roleService, times(0)).addRoleToMember(eq(aUserInAServer), any(ARole.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncNoRoleUserGettingRole2() {
|
||||
userExperience.setCurrentExperienceRole(null);
|
||||
AExperienceRole afterRole = experienceRole1;
|
||||
when(experienceRole1.getRole()).thenReturn(aRole1);
|
||||
when(experienceRole1.getId()).thenReturn(ROLE_ID);
|
||||
when(aRole1.getId()).thenReturn(ROLE_ID);
|
||||
when(aUserInAServer.getUserReference()).thenReturn(user);
|
||||
when(aUserInAServer.getServerReference()).thenReturn(server);
|
||||
when(userExperience.getUser()).thenReturn(aUserInAServer);
|
||||
|
||||
when(memberService.getMemberInServerAsync(aUserInAServer)).thenReturn(CompletableFuture.completedFuture(firstMember));
|
||||
|
||||
when(experienceRoleManagementService.getExperienceRolesForServer(server)).thenReturn(experienceRoles);
|
||||
when(experienceRole1.getLevel()).thenReturn(level0);
|
||||
when(experienceRole2.getLevel()).thenReturn(level1);
|
||||
when(experienceRoleService.calculateRole(experienceRoles, userExperience.getLevelOrDefault())).thenReturn(afterRole);
|
||||
when(memberService.getMemberInServerAsync(userExperience.getUser())).thenReturn(CompletableFuture.completedFuture(firstMember));
|
||||
when(roleService.addRoleToMemberAsync(firstMember, ROLE_ID)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
CompletableFuture<RoleCalculationResult> calculationFuture = testUnit.syncForSingleUser(userExperience);
|
||||
RoleCalculationResult result = calculationFuture.join();
|
||||
Assert.assertEquals(ROLE_ID, result.getExperienceRoleId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncUserLosingRole() {
|
||||
AExperienceRole beforeRole = experienceRole1;
|
||||
when(userExperience.getCurrentExperienceRole()).thenReturn(beforeRole);
|
||||
when(aUserInAServer.getUserReference()).thenReturn(user);
|
||||
when(aUserInAServer.getServerReference()).thenReturn(server);
|
||||
when(userExperience.getUser()).thenReturn(aUserInAServer);
|
||||
when(experienceRole1.getRole()).thenReturn(aRole1);
|
||||
|
||||
when(experienceRoleManagementService.getExperienceRolesForServer(server)).thenReturn(experienceRoles);
|
||||
when(experienceRoleService.calculateRole(experienceRoles, userExperience.getLevelOrDefault())).thenReturn(null);
|
||||
when(roleService.removeRoleFromUserAsync(aUserInAServer, aRole1)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(experienceRole1.getLevel()).thenReturn(level0);
|
||||
when(experienceRole2.getLevel()).thenReturn(level1);
|
||||
CompletableFuture<RoleCalculationResult> calculationFuture = testUnit.syncForSingleUser(userExperience);
|
||||
RoleCalculationResult result = calculationFuture.join();
|
||||
Assert.assertNull(result.getExperienceRoleId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncUserKeepingRole() {
|
||||
AExperienceRole beforeRole = experienceRole1;
|
||||
when(userExperience.getCurrentExperienceRole()).thenReturn(beforeRole);
|
||||
AExperienceRole afterRole = experienceRole1;
|
||||
when(aUserInAServer.getUserReference()).thenReturn(user);
|
||||
when(aUserInAServer.getServerReference()).thenReturn(server);
|
||||
when(userExperience.getUser()).thenReturn(aUserInAServer);
|
||||
when(aRole1.getId()).thenReturn(ROLE_ID);
|
||||
when(experienceRole1.getId()).thenReturn(ROLE_ID);
|
||||
when(experienceRole1.getRole()).thenReturn(aRole1);
|
||||
when(memberService.getMemberInServerAsync(aUserInAServer)).thenReturn(CompletableFuture.completedFuture(firstMember));
|
||||
|
||||
when(experienceRoleManagementService.getExperienceRolesForServer(server)).thenReturn(experienceRoles);
|
||||
when(experienceRoleService.calculateRole(experienceRoles, userExperience.getLevelOrDefault())).thenReturn(afterRole);
|
||||
when(memberService.getMemberInServerAsync(userExperience.getUser())).thenReturn(CompletableFuture.completedFuture(firstMember));
|
||||
when(roleService.memberHasRole(firstMember, ROLE_ID)).thenReturn(true);
|
||||
when(experienceRole1.getLevel()).thenReturn(level0);
|
||||
when(experienceRole2.getLevel()).thenReturn(level1);
|
||||
CompletableFuture<RoleCalculationResult> calculationFuture = testUnit.syncForSingleUser(userExperience);
|
||||
RoleCalculationResult result = calculationFuture.join();
|
||||
Assert.assertEquals(ROLE_ID, result.getExperienceRoleId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncUserChangingRole() {
|
||||
AExperienceRole beforeRole = experienceRole1;
|
||||
when(userExperience.getCurrentExperienceRole()).thenReturn(beforeRole);
|
||||
AExperienceRole afterRole = experienceRole2;
|
||||
when(aUserInAServer.getUserReference()).thenReturn(user);
|
||||
when(aUserInAServer.getServerReference()).thenReturn(server);
|
||||
when(userExperience.getUser()).thenReturn(aUserInAServer);
|
||||
|
||||
when(aRole1.getId()).thenReturn(ROLE_ID);
|
||||
when(aRole2.getId()).thenReturn(SECOND_ROLE_ID);
|
||||
when(experienceRole1.getRole()).thenReturn(aRole1);
|
||||
when(experienceRole2.getRole()).thenReturn(aRole2);
|
||||
when(experienceRole2.getId()).thenReturn(SECOND_ROLE_ID);
|
||||
|
||||
when(roleService.memberHasRole(firstMember, ROLE_ID)).thenReturn(true);
|
||||
|
||||
when(memberService.getMemberInServerAsync(aUserInAServer)).thenReturn(CompletableFuture.completedFuture(firstMember));
|
||||
|
||||
when(experienceRoleManagementService.getExperienceRolesForServer(server)).thenReturn(experienceRoles);
|
||||
when(experienceRoleService.calculateRole(experienceRoles, userExperience.getLevelOrDefault())).thenReturn(afterRole);
|
||||
when(memberService.getMemberInServerAsync(aUserInAServer)).thenReturn(CompletableFuture.completedFuture(firstMember));
|
||||
when(experienceRole1.getLevel()).thenReturn(level0);
|
||||
when(experienceRole2.getLevel()).thenReturn(level1);
|
||||
when(roleService.memberHasRole(firstMember, SECOND_ROLE_ID)).thenReturn(false);
|
||||
when(roleService.removeRoleFromMemberAsync(firstMember, ROLE_ID)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(roleService.addRoleToMemberAsync(firstMember, SECOND_ROLE_ID)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
CompletableFuture<RoleCalculationResult> calculationFuture = testUnit.syncForSingleUser(userExperience);
|
||||
RoleCalculationResult result = calculationFuture.join();
|
||||
Assert.assertEquals(SECOND_ROLE_ID, result.getExperienceRoleId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisablingExperienceForUser() {
|
||||
AUserExperience experience = Mockito.mock(AUserExperience.class);
|
||||
when(aUserInAServer.getUserReference()).thenReturn(user);
|
||||
when(aUserInAServer.getServerReference()).thenReturn(server);
|
||||
when(userExperienceManagementService.findUserInServer(aUserInAServer)).thenReturn(experience);
|
||||
testUnit.disableExperienceForUser(aUserInAServer);
|
||||
verify(experience, times(1)).setExperienceGainDisabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnablingExpForUser() {
|
||||
AUserExperience experience = Mockito.mock(AUserExperience.class);
|
||||
when(aUserInAServer.getUserReference()).thenReturn(user);
|
||||
when(aUserInAServer.getServerReference()).thenReturn(server);
|
||||
when(userExperienceManagementService.findUserInServer(aUserInAServer)).thenReturn(experience);
|
||||
testUnit.enableExperienceForUser(aUserInAServer);
|
||||
verify(experience, times(1)).setExperienceGainDisabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindLeaderBoardData() {
|
||||
executeLeaderBoardTest(server, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindLeaderBoardDataSecondPage() {
|
||||
executeLeaderBoardTest(server, 2);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testIllegalLeaderBoardPage() {
|
||||
testUnit.findLeaderBoardData(server, -1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncAllUsers() {
|
||||
AExperienceRole beforeRole = experienceRole1;
|
||||
|
||||
when(userExperience.getCurrentExperienceRole()).thenReturn(beforeRole);
|
||||
AExperienceRole afterRole = experienceRole2;
|
||||
when(aUserInAServer.getUserReference()).thenReturn(user);
|
||||
when(user.getId()).thenReturn(8L);
|
||||
when(aUserInAServer.getServerReference()).thenReturn(server);
|
||||
when(userExperience.getUser()).thenReturn(aUserInAServer);
|
||||
when(userExperience.getCurrentLevel()).thenReturn(level0);
|
||||
|
||||
when(aUserInAServer2.getUserReference()).thenReturn(user2);
|
||||
when(user2.getId()).thenReturn(9L);
|
||||
when(aUserInAServer2.getServerReference()).thenReturn(server);
|
||||
when(userExperience2.getUser()).thenReturn(aUserInAServer2);
|
||||
when(userExperience2.getCurrentLevel()).thenReturn(level0);
|
||||
|
||||
when(userExperience2.getCurrentExperienceRole()).thenReturn(beforeRole);
|
||||
|
||||
when(memberService.getMemberInServerAsync(aUserInAServer)).thenReturn(CompletableFuture.completedFuture(firstMember));
|
||||
when(memberService.getMemberInServerAsync(aUserInAServer2)).thenReturn(CompletableFuture.completedFuture(secondMember));
|
||||
|
||||
|
||||
when(aRole1.getId()).thenReturn(ROLE_ID);
|
||||
when(aRole2.getId()).thenReturn(SECOND_ROLE_ID);
|
||||
when(experienceRole1.getRole()).thenReturn(aRole1);
|
||||
when(experienceRole2.getRole()).thenReturn(aRole2);
|
||||
when(experienceRole2.getId()).thenReturn(SECOND_ROLE_ID);
|
||||
|
||||
when(experienceRoleManagementService.getExperienceRolesForServer(server)).thenReturn(experienceRoles);
|
||||
when(experienceRoleService.calculateRole(experienceRoles, userExperience.getLevelOrDefault())).thenReturn(afterRole);
|
||||
when(experienceRoleService.calculateRole(experienceRoles, userExperience2.getLevelOrDefault())).thenReturn(afterRole);
|
||||
when(memberService.getMemberInServerAsync(aUserInAServer)).thenReturn(CompletableFuture.completedFuture(firstMember));
|
||||
when(memberService.getMemberInServerAsync(aUserInAServer2)).thenReturn(CompletableFuture.completedFuture(secondMember));
|
||||
when(roleService.memberHasRole(firstMember, SECOND_ROLE_ID)).thenReturn(false);
|
||||
when(roleService.memberHasRole(firstMember, ROLE_ID)).thenReturn(true);
|
||||
when(roleService.memberHasRole(secondMember, SECOND_ROLE_ID)).thenReturn(true);
|
||||
when(roleService.removeRoleFromMemberAsync(firstMember, ROLE_ID)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(roleService.addRoleToMemberAsync(firstMember,SECOND_ROLE_ID)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
List<AUserExperience> experiences = Arrays.asList(userExperience, userExperience2);
|
||||
when(userExperienceManagementService.loadAllUsers(server)).thenReturn(experiences);
|
||||
when(experienceRole1.getLevel()).thenReturn(level0);
|
||||
when(experienceRole2.getLevel()).thenReturn(level1);
|
||||
List<CompletableFuture<RoleCalculationResult>> calculationFutures = testUnit.syncUserRoles(server);
|
||||
verify(roleService, times(0)).removeRoleFromMemberAsync(secondMember, ROLE_ID);
|
||||
verify(roleService, times(0)).addRoleToMemberAsync(secondMember, SECOND_ROLE_ID);
|
||||
RoleCalculationResult firstResult = calculationFutures.get(0).join();
|
||||
Assert.assertEquals(SECOND_ROLE_ID, firstResult.getExperienceRoleId());
|
||||
RoleCalculationResult secondResult = calculationFutures.get(1).join();
|
||||
Assert.assertEquals(SECOND_ROLE_ID, secondResult.getExperienceRoleId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRankForUser() {
|
||||
int rank = 1;
|
||||
AUserExperience experienceObj = Mockito.mock(AUserExperience.class);
|
||||
when(aUserInAServer.getUserReference()).thenReturn(user);
|
||||
when(aUserInAServer.getUserInServerId()).thenReturn(USER_IN_SERVER_ID);
|
||||
when(userExperienceManagementService.findByUserInServerIdOptional(USER_IN_SERVER_ID)).thenReturn(Optional.of(experienceObj));
|
||||
LeaderBoardEntryResult leaderBoardEntryTest = Mockito.mock(LeaderBoardEntryResult.class);
|
||||
when(leaderBoardEntryTest.getRank()).thenReturn(rank);
|
||||
when(userExperienceManagementService.getRankOfUserInServer(experienceObj)).thenReturn(leaderBoardEntryTest);
|
||||
LeaderBoardEntry rankOfUserInServer = testUnit.getRankOfUserInServer(aUserInAServer);
|
||||
Assert.assertEquals(experienceObj, rankOfUserInServer.getExperience());
|
||||
Assert.assertEquals(rank, rankOfUserInServer.getRank().intValue());
|
||||
}
|
||||
|
||||
@Test(expected = NoExperienceTrackedException.class)
|
||||
public void testGetRankForUserNoExperienceFound() {
|
||||
when(aUserInAServer.getUserInServerId()).thenReturn(USER_IN_SERVER_ID);
|
||||
when(aUserInAServer.getUserReference()).thenReturn(user);
|
||||
when(userExperienceManagementService.findByUserInServerIdOptional(USER_IN_SERVER_ID)).thenReturn(Optional.empty());
|
||||
testUnit.getRankOfUserInServer(aUserInAServer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRankWhenRankReturnsNull() {
|
||||
AUserExperience experienceObj = Mockito.mock(AUserExperience.class);
|
||||
when(aUserInAServer.getUserReference()).thenReturn(user);
|
||||
when(aUserInAServer.getUserInServerId()).thenReturn(USER_IN_SERVER_ID);
|
||||
when(userExperienceManagementService.findByUserInServerIdOptional(USER_IN_SERVER_ID)).thenReturn(Optional.of(experienceObj));
|
||||
when(userExperienceManagementService.getRankOfUserInServer(experienceObj)).thenReturn(null);
|
||||
LeaderBoardEntry rankOfUserInServer = testUnit.getRankOfUserInServer(aUserInAServer);
|
||||
Assert.assertEquals(experienceObj, rankOfUserInServer.getExperience());
|
||||
Assert.assertEquals(0, rankOfUserInServer.getRank().intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncRolesWithFeedBack() {
|
||||
AChannel channel = Mockito.mock(AChannel.class);
|
||||
when(channel.getServer()).thenReturn(server);
|
||||
when(server.getId()).thenReturn(SERVER_ID);
|
||||
List<AUserExperience> experiences = getUserExperiences(25);
|
||||
|
||||
checkStatusMessages(server, channel, experiences, 13);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSyncRolesWithNoUsers() {
|
||||
AChannel channel = Mockito.mock(AChannel.class);
|
||||
List<AUserExperience> experiences = new ArrayList<>();
|
||||
when(channel.getServer()).thenReturn(server);
|
||||
when(server.getId()).thenReturn(SERVER_ID);
|
||||
checkStatusMessages(server, channel, experiences, 1);
|
||||
}
|
||||
|
||||
private void checkStatusMessages(AServer server, AChannel channel, List<AUserExperience> experiences, int messageCount) {
|
||||
when(userExperienceManagementService.loadAllUsers(server)).thenReturn(experiences);
|
||||
MessageToSend statusMessage = Mockito.mock(MessageToSend.class);
|
||||
when(templateService.renderEmbedTemplate(eq("user_sync_status_message"), any(UserSyncStatusModel.class), eq(SERVER_ID))).thenReturn(statusMessage);
|
||||
long messageId = 5L;
|
||||
Message statusMessageJDA = Mockito.mock(Message.class);
|
||||
when(statusMessageJDA.getIdLong()).thenReturn(messageId);
|
||||
when(messageService.createStatusMessage(statusMessage, channel)).thenReturn(CompletableFuture.completedFuture(statusMessageJDA));
|
||||
when(channelManagementService.loadChannel(CHANNEL_ID)).thenReturn(channel);
|
||||
testUnit.syncUserRolesWithFeedback(server, CHANNEL_ID);
|
||||
verify(messageService, times(messageCount)).updateStatusMessage(channel, messageId, statusMessage);
|
||||
}
|
||||
|
||||
private void setupUserInServer() {
|
||||
when(userExperienceManagementService.findByUserInServerIdOptional(USER_IN_SERVER_ID)).thenReturn(Optional.of(userExperience));
|
||||
when(userInServerManagementService.loadOrCreateUser(firstMember)).thenReturn(aUserInAServer);
|
||||
when(aUserInAServer.getUserReference()).thenReturn(user);
|
||||
when(aUserInAServer.getUserInServerId()).thenReturn(USER_IN_SERVER_ID);
|
||||
when(memberService.getMemberInServerAsync(aUserInAServer)).thenReturn(CompletableFuture.completedFuture(firstMember));
|
||||
when(userExperience.getUser()).thenReturn(aUserInAServer);
|
||||
when(aUserInAServer.getServerReference()).thenReturn(server);
|
||||
when(user.getId()).thenReturn(USER_ID);
|
||||
}
|
||||
|
||||
private void setupTwoExperienceRoles() {
|
||||
when(experienceRole1.getRole()).thenReturn(aRole1);
|
||||
setExperienceRoleLevels();
|
||||
}
|
||||
|
||||
private void setupServerId() {
|
||||
when(server.getId()).thenReturn(SERVER_ID);
|
||||
when(serverManagementService.loadOrCreate(SERVER_ID)).thenReturn(server);
|
||||
}
|
||||
|
||||
private void setupServerConfig() {
|
||||
when(configService.getLongValue(ExperienceFeatureConfig.MIN_EXP_KEY, SERVER_ID, DEFAULT_MIN_EXP)).thenReturn(20L);
|
||||
when(configService.getLongValue(ExperienceFeatureConfig.MAX_EXP_KEY, SERVER_ID, DEFAULT_MAX_EXP)).thenReturn(50L);
|
||||
when(configService.getDoubleValue(ExperienceFeatureConfig.EXP_MULTIPLIER_KEY, SERVER_ID, DEFAULT_EXP_MULTIPLIER)).thenReturn(1.2);
|
||||
}
|
||||
|
||||
private void executeLeaderBoardTest(AServer server, Integer page) {
|
||||
int pageSize = 10;
|
||||
List<AUserExperience> experiences = Arrays.asList(userExperience, userExperience2);
|
||||
when(userExperience.getExperience()).thenReturn(LOW_EXP);
|
||||
when(userExperience.getCurrentLevel()).thenReturn(level0);
|
||||
when(userExperience.getUser()).thenReturn(aUserInAServer);
|
||||
when(userExperience2.getExperience()).thenReturn(MID_EXP);
|
||||
when(userExperience2.getCurrentLevel()).thenReturn(level1);
|
||||
when(userExperience2.getUser()).thenReturn(aUserInAServer2);
|
||||
when(userExperienceManagementService.findLeaderBoardUsersPaginated(server, page - 1, pageSize)).thenReturn(experiences);
|
||||
LeaderBoard leaderBoardData = testUnit.findLeaderBoardData(server, page);
|
||||
page--;
|
||||
List<LeaderBoardEntry> entries = leaderBoardData.getEntries();
|
||||
LeaderBoardEntry firstEntry = entries.get(0);
|
||||
Assert.assertEquals(LOW_EXP, firstEntry.getExperience().getExperience());
|
||||
Assert.assertEquals(level0, firstEntry.getExperience().getCurrentLevel());
|
||||
Assert.assertEquals(aUserInAServer, firstEntry.getExperience().getUser());
|
||||
Assert.assertEquals((page * pageSize) + 1, firstEntry.getRank().intValue());
|
||||
LeaderBoardEntry secondEntry = entries.get(1);
|
||||
Assert.assertEquals(MID_EXP, secondEntry.getExperience().getExperience());
|
||||
Assert.assertEquals(level1, secondEntry.getExperience().getCurrentLevel());
|
||||
Assert.assertEquals(aUserInAServer2, secondEntry.getExperience().getUser());
|
||||
Assert.assertEquals((page * pageSize) + 2, secondEntry.getRank().intValue());
|
||||
Assert.assertEquals(2, entries.size());
|
||||
}
|
||||
|
||||
private void setExperienceRoleLevels() {
|
||||
when(experienceRole1.getLevel()).thenReturn(level0);
|
||||
when(experienceRole2.getLevel()).thenReturn(level1);
|
||||
}
|
||||
|
||||
private void setupLevelsAndRolesAndNoDisallowed() {
|
||||
when(experienceLevelManagementService.getLevelConfig()).thenReturn(levels);
|
||||
when(experienceRoleManagementService.getExperienceRolesForServer(server)).thenReturn(experienceRoles);
|
||||
when(disabledExpRoleManagementService.getDisabledRolesForServer(server)).thenReturn(new ArrayList<>());
|
||||
}
|
||||
|
||||
private void setupDefaultConfig() {
|
||||
SystemConfigProperty minExpProperty = Mockito.mock(SystemConfigProperty.class);
|
||||
when(minExpProperty.getLongValue()).thenReturn(DEFAULT_MIN_EXP);
|
||||
when(defaultConfigManagementService.getDefaultConfig(ExperienceFeatureConfig.MIN_EXP_KEY)).thenReturn(minExpProperty);
|
||||
SystemConfigProperty maxExpProperty = Mockito.mock(SystemConfigProperty.class);
|
||||
when(maxExpProperty.getLongValue()).thenReturn(DEFAULT_MAX_EXP);
|
||||
when(defaultConfigManagementService.getDefaultConfig(ExperienceFeatureConfig.MAX_EXP_KEY)).thenReturn(maxExpProperty);
|
||||
SystemConfigProperty expMultiplierProperty = Mockito.mock(SystemConfigProperty.class);
|
||||
when(expMultiplierProperty.getDoubleValue()).thenReturn(DEFAULT_EXP_MULTIPLIER);
|
||||
when(defaultConfigManagementService.getDefaultConfig(ExperienceFeatureConfig.EXP_MULTIPLIER_KEY)).thenReturn(expMultiplierProperty);
|
||||
}
|
||||
|
||||
protected List<AUserExperience> getUserExperiences(int count) {
|
||||
List<AUserExperience> experiences = new ArrayList<>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
AUserExperience experience = Mockito.mock(AUserExperience.class);
|
||||
when(experience.getUser()).thenReturn(aUserInAServer);
|
||||
when(aUserInAServer.getServerReference()).thenReturn(server);
|
||||
when(aUserInAServer.getUserReference()).thenReturn(user);
|
||||
experiences.add(experience);
|
||||
}
|
||||
return experiences;
|
||||
}
|
||||
|
||||
private void setupLevels(int count) {
|
||||
if(count >= 0) {
|
||||
when(level0.getExperienceNeeded()).thenReturn(LVL_0_EXP);
|
||||
}
|
||||
if(count >= 1) {
|
||||
when(level1.getExperienceNeeded()).thenReturn(LVL_1_EXP);
|
||||
}
|
||||
if(count >= 2) {
|
||||
when(level2.getExperienceNeeded()).thenReturn(LVL_2_EXP);
|
||||
}
|
||||
if(count >= 3) {
|
||||
when(level3.getExperienceNeeded()).thenReturn(LVL_3_EXP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -53,21 +53,6 @@ public class ExperienceRoleServiceBeanTest {
|
||||
private static final Long CHANNEL_ID = 4L;
|
||||
private static final Long ROLE_ID = 5L;
|
||||
|
||||
@Test
|
||||
public void testUnsetRoleInDb() {
|
||||
Integer levelCount = 10;
|
||||
AExperienceLevel level = Mockito.mock(AExperienceLevel.class);
|
||||
ARole roleToChange = Mockito.mock(ARole.class);
|
||||
when(roleToChange.getServer()).thenReturn(server);
|
||||
when(experienceLevelService.getLevelOptional(levelCount)).thenReturn(Optional.of(level));
|
||||
when(roleManagementService.findRole(roleToChange.getId())).thenReturn(roleToChange);
|
||||
testingUnit.unsetRoleInDb(levelCount, roleToChange.getId());
|
||||
|
||||
verify(experienceRoleManagementService, times(1)).removeAllRoleAssignmentsForLevelInServerExceptRole(level, server, roleToChange);
|
||||
verify(experienceRoleManagementService, times(1)).setLevelToRole(level, roleToChange);
|
||||
verify(experienceRoleManagementService, times(0)).getExperienceRolesForServer(server);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateRoleForLevelInBetween() {
|
||||
List<AExperienceRole> roles = getExperienceRoles();
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package dev.sheldan.abstracto.experience.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.service.ExecutorService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
|
||||
@Configuration
|
||||
public class ExperienceExecutorConfig {
|
||||
|
||||
@Autowired
|
||||
private ExecutorService executorService;
|
||||
|
||||
@Bean(name = "experienceUpdateExecutor")
|
||||
public TaskExecutor experienceUpdateExecutor() {
|
||||
return executorService.setupExecutorFor("experienceUpdateExecutor");
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,14 @@ package dev.sheldan.abstracto.experience.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static dev.sheldan.abstracto.experience.config.ExperienceFeatureMode.LEVEL_UP_NOTIFICATION;
|
||||
|
||||
/**
|
||||
* {@link FeatureConfig} instance containing the required configuration concerning system config and post targets for
|
||||
* the {@link ExperienceFeatureDefinition} feature.
|
||||
@@ -26,6 +29,7 @@ public class ExperienceFeatureConfig implements FeatureConfig {
|
||||
* The multiplier which is applied to each calculated gained experience
|
||||
*/
|
||||
public static final String EXP_MULTIPLIER_KEY = "expMultiplier";
|
||||
public static final String EXP_COOLDOWN_SECONDS_KEY = "expCooldownSeconds";
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
@@ -37,6 +41,11 @@ public class ExperienceFeatureConfig implements FeatureConfig {
|
||||
*/
|
||||
@Override
|
||||
public List<String> getRequiredSystemConfigKeys() {
|
||||
return Arrays.asList(EXP_MULTIPLIER_KEY, MIN_EXP_KEY, MAX_EXP_KEY);
|
||||
return Arrays.asList(EXP_MULTIPLIER_KEY, MIN_EXP_KEY, MAX_EXP_KEY, EXP_COOLDOWN_SECONDS_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getAvailableModes() {
|
||||
return Arrays.asList(LEVEL_UP_NOTIFICATION);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.experience.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum ExperienceFeatureMode implements FeatureMode {
|
||||
LEVEL_UP_NOTIFICATION("levelUpNotification");
|
||||
|
||||
private final String key;
|
||||
|
||||
ExperienceFeatureMode(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
@@ -15,10 +15,6 @@ import java.util.concurrent.CompletableFuture;
|
||||
@Setter
|
||||
@Builder
|
||||
public class ExperienceGainResult {
|
||||
/**
|
||||
* The calculation result contained in a {@link CompletableFuture future}. The future is necessary, because the calculation both calculates the new role
|
||||
* and removes/adds {@link net.dv8tion.jda.api.entities.Role role} to the {@link net.dv8tion.jda.api.entities.Member member}
|
||||
*/
|
||||
private CompletableFuture<RoleCalculationResult> calculationResult;
|
||||
/**
|
||||
* The ID of the {@link dev.sheldan.abstracto.core.models.database.AUserInAServer user} for which this is the result
|
||||
|
||||
@@ -4,20 +4,10 @@ import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* The result of calculating the appropriate {@link dev.sheldan.abstracto.experience.model.database.AExperienceRole role} for a {@link dev.sheldan.abstracto.experience.model.database.AUserExperience user}
|
||||
* in a server.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class RoleCalculationResult {
|
||||
/**
|
||||
* The ID of the {@link dev.sheldan.abstracto.experience.model.database.AExperienceRole role} which was given to the user. Can be null, in case no role is given.
|
||||
*/
|
||||
private Long experienceRoleId;
|
||||
/**
|
||||
* The ID of a {@link dev.sheldan.abstracto.core.models.database.AUserInAServer user} for who the role was calculated for.
|
||||
*/
|
||||
private Long userInServerId;
|
||||
private Long oldRoleId;
|
||||
private Long newRoleId;
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package dev.sheldan.abstracto.experience.model;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Container object to store the experience in runtime and group it together. This basically is just a list of users who were tracked by experience.
|
||||
* The actual calculation of the appropriate experience amount is done later.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class ServerExperience {
|
||||
/**
|
||||
* The ID of the {@link dev.sheldan.abstracto.core.models.database.AServer} for which this experience were collected
|
||||
*/
|
||||
private Long serverId;
|
||||
/**
|
||||
* A list of IDs of the {@link dev.sheldan.abstracto.core.models.database.AUserInAServer} which should be given experience
|
||||
*/
|
||||
@Builder.Default
|
||||
private List<Long> userInServerIds = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package dev.sheldan.abstracto.experience.model.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.core.models.template.display.RoleDisplay;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class LevelUpNotificationModel {
|
||||
private MemberDisplay memberDisplay;
|
||||
private Integer oldLevel;
|
||||
private Integer newLevel;
|
||||
private RoleDisplay oldRole;
|
||||
private RoleDisplay newRole;
|
||||
private Long oldExperience;
|
||||
private Long newExperience;
|
||||
}
|
||||
@@ -1,21 +1,17 @@
|
||||
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.utils.CompletableFutureList;
|
||||
import dev.sheldan.abstracto.experience.model.LeaderBoard;
|
||||
import dev.sheldan.abstracto.experience.model.LeaderBoardEntry;
|
||||
import dev.sheldan.abstracto.experience.model.RoleCalculationResult;
|
||||
import dev.sheldan.abstracto.experience.model.ServerExperience;
|
||||
import dev.sheldan.abstracto.experience.model.database.AExperienceLevel;
|
||||
import dev.sheldan.abstracto.experience.model.database.AExperienceRole;
|
||||
import dev.sheldan.abstracto.experience.model.database.AUserExperience;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Service providing the required mechanisms to provide experience tracking.
|
||||
@@ -24,12 +20,7 @@ import java.util.function.Function;
|
||||
*/
|
||||
public interface AUserExperienceService {
|
||||
String EXPERIENCE_GAIN_CHANNEL_GROUP_KEY = "experienceGain";
|
||||
/**
|
||||
* Adds the given {@link AUserInAServer userInAServer} to the list of user who gained experience in the current minute.
|
||||
* Does not add the user to the list of users, if it is already in there.
|
||||
* @param userInAServer The {@link AUserInAServer userInAServer} to be added to the list of users gaining experience
|
||||
*/
|
||||
void addExperience(AUserInAServer userInAServer);
|
||||
void addExperience(Member member, Message message);
|
||||
|
||||
/**
|
||||
* Calculates the appropriate level for the given experience amount according to the given {@link AExperienceLevel levels}
|
||||
@@ -51,58 +42,9 @@ public interface AUserExperienceService {
|
||||
*/
|
||||
boolean updateUserLevel(AUserExperience userExperience, List<AExperienceLevel> levels, Long experienceCount);
|
||||
|
||||
/**
|
||||
* Iterates through the given list of {@link AServer servers} and increases the experience of the users contained in the
|
||||
* {@link ServerExperience serverExperience} object, also increments the level and changes the role if necessary.
|
||||
* This uses the respective configurable max/minExp and multiplier for each {@link AServer server} and increases the message count
|
||||
* of each user by 1.
|
||||
* @param serverExp The list of {@link AServer servers} containing the users which get experience
|
||||
* @return A {@link CompletableFuture future} completing when the experience gain was calculated and roles were assigned
|
||||
*/
|
||||
CompletableFuture<Void> handleExperienceGain(List<ServerExperience> serverExp);
|
||||
CompletableFuture<Void> syncUserRolesWithFeedback(AServer server, MessageChannel messageChannel);
|
||||
|
||||
/**
|
||||
* Calculates the currently appropriate {@link AExperienceRole} for the given user and updates the role on the
|
||||
* {@link net.dv8tion.jda.api.entities.Member} and ond the {@link AUserExperience}. Effectively synchronizes the
|
||||
* state in the server and the database.
|
||||
* @param userExperience The {@link AUserExperience userExperience} object to recalculate the {@link AExperienceRole experienceRole} for
|
||||
* @param roles The list of {@link AExperienceRole roles} used as a role configuration
|
||||
* @param currentLevel The current level of the user
|
||||
* @return A {@link CompletableFuture future} containing the {@link RoleCalculationResult result} of the role calculation,
|
||||
* completing after the role of the {@link net.dv8tion.jda.api.entities.Member} has been updated, if any
|
||||
*/
|
||||
CompletableFuture<RoleCalculationResult> updateUserRole(AUserExperience userExperience, List<AExperienceRole> roles, Integer currentLevel);
|
||||
|
||||
/**
|
||||
* Synchronizes the state ({@link AExperienceRole}, {@link net.dv8tion.jda.api.entities.Role})
|
||||
* of all the users provided in the {@link AServer} object in the {@link AUserExperience}
|
||||
* and on the {@link net.dv8tion.jda.api.entities.Member} according
|
||||
* to how much experience the user has. Runs completely in the background.
|
||||
* @param server The {@link AServer} to update the users for
|
||||
* @return The list of {@link CompletableFuture futures} for each update of the users in the {@link AServer server}
|
||||
*/
|
||||
List<CompletableFuture<RoleCalculationResult>> syncUserRoles(AServer server);
|
||||
|
||||
/**
|
||||
* Synchronizes the state ({@link AExperienceRole}, {@link net.dv8tion.jda.api.entities.Role})
|
||||
* of all the users provided in the {@link AServer} object in the {@link AUserExperience}
|
||||
* and on the {@link net.dv8tion.jda.api.entities.Member} according
|
||||
* to how much experience the user has. This method provides feedback back to the user in the provided {@link AChannel channel}
|
||||
* while the process is going own.
|
||||
* @param server The {@link AServer} to update users for
|
||||
* @param channelId The ID of a {@link AChannel channel} in which the {@link dev.sheldan.abstracto.experience.model.template.UserSyncStatusModel statusUpdate}
|
||||
* should be posted to
|
||||
* @return A {@link CompletableFuture future} which completes after all the role changes have been completed
|
||||
*/
|
||||
CompletableFuture<Void> syncUserRolesWithFeedback(AServer server, Long channelId);
|
||||
|
||||
/**
|
||||
* Recalculates the role of a single user in a server and synchronize the {@link net.dv8tion.jda.api.entities.Role}
|
||||
* in the {@link net.dv8tion.jda.api.entities.Guild}
|
||||
* @param userExperience The {@link AUserExperience} to synchronize the role for
|
||||
* @return A {@link CompletableFuture future} which completes after the roles have been synced for the given {@link AUserInAServer user}
|
||||
*/
|
||||
CompletableFuture<RoleCalculationResult> syncForSingleUser(AUserExperience userExperience);
|
||||
CompletableFuture<Void> syncForSingleUser(AUserExperience userExperience, Member member);
|
||||
|
||||
/**
|
||||
* Loads the desired page of the ordered complete leaderboard from the {@link AServer} and returns the information as a {@link LeaderBoard}
|
||||
@@ -122,19 +64,6 @@ public interface AUserExperienceService {
|
||||
*/
|
||||
LeaderBoardEntry getRankOfUserInServer(AUserInAServer userInAServer);
|
||||
|
||||
/**
|
||||
* Provides a method to execute an action on a list of {@link AUserExperience} and provide feedback in the given {@link AChannel}
|
||||
* in the form of {@link dev.sheldan.abstracto.experience.model.template.UserSyncStatusModel} to be rendered with a certain
|
||||
* template
|
||||
* @param experiences The list of {@link AUserExperience} to be working on
|
||||
* @param channel The {@link AChannel} used to provide feedback to the user
|
||||
* @param toExecute The {@link Function} which should be executed on each element of the passed list,
|
||||
* this function needs to take a {@link AUserExperience userExperience} as parameter and returns a {@link CompletableFuture}
|
||||
* with a {@link RoleCalculationResult} for each of them. These futures are then returned.
|
||||
* @return A {@link CompletableFutureList completeFutureList} which represents the individual {@link RoleCalculationResult results} and a primary future, which is completed after all of the individual ones are
|
||||
*/
|
||||
CompletableFutureList<RoleCalculationResult> executeActionOnUserExperiencesWithFeedBack(List<AUserExperience> experiences, AChannel channel, Function<AUserExperience, CompletableFuture<RoleCalculationResult>> toExecute);
|
||||
|
||||
/**
|
||||
* Disables the experience gain for a user directly. This sets the `experienceGainDisabled` on the respective {@link AUserExperience} object to true
|
||||
* @param userInAServer The {@link AUserInAServer} to disable experience gain for
|
||||
@@ -147,12 +76,6 @@ public interface AUserExperienceService {
|
||||
*/
|
||||
void enableExperienceForUser(AUserInAServer userInAServer);
|
||||
|
||||
/**
|
||||
* Updates the actually stored experience roles in the database
|
||||
* @param results The list of {@link RoleCalculationResult} which should be updated in the database
|
||||
*/
|
||||
void syncRolesInStorage(List<RoleCalculationResult> results);
|
||||
|
||||
boolean experienceGainEnabledInChannel(MessageChannel messageChannel);
|
||||
|
||||
AUserExperience createUserExperienceForUser(AUserInAServer aUserInAServer, Long experience, Long messageCount);
|
||||
|
||||
@@ -7,6 +7,7 @@ import dev.sheldan.abstracto.experience.model.database.AExperienceRole;
|
||||
import dev.sheldan.abstracto.experience.model.database.AUserExperience;
|
||||
import dev.sheldan.abstracto.experience.model.template.LevelRole;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -15,34 +16,12 @@ import java.util.concurrent.CompletableFuture;
|
||||
* Service providing several methods surrounding {@link dev.sheldan.abstracto.experience.model.database.AExperienceRole experienceRole}.
|
||||
*/
|
||||
public interface ExperienceRoleService {
|
||||
/**
|
||||
* Creates an {@link dev.sheldan.abstracto.experience.model.database.AExperienceRole experienceRole} according to the given
|
||||
* parameters. This actually updates the {@link net.dv8tion.jda.api.entities.Member members}
|
||||
* which currently possessed the given role before and provides a display to see how far the progress is
|
||||
* @param role The {@link ARole role} to set the level to
|
||||
* @param level The new level the {@link ARole role} should be awarded at
|
||||
* @param channelId The ID of the {@link dev.sheldan.abstracto.core.models.database.AChannel} in which the status updates
|
||||
* should be sent to
|
||||
* @return A {@link CompletableFuture future} which completes, after all the updates on the {@link net.dv8tion.jda.api.entities.Member}
|
||||
* have been completed
|
||||
*/
|
||||
CompletableFuture<Void> setRoleToLevel(Role role, Integer level, Long channelId);
|
||||
|
||||
/**
|
||||
* Removes the role from the {@link dev.sheldan.abstracto.experience.model.database.AExperienceRole} configuration,
|
||||
* this will also update all the {@link net.dv8tion.jda.api.entities.Member} which previously had this role and re-calculates
|
||||
* a new {@link AExperienceRole experienceRole} for them while also updating them in the guild
|
||||
* @param role The {@link ARole} to remove from the {@link dev.sheldan.abstracto.experience.model.database.AExperienceRole}
|
||||
* configuration
|
||||
* @param channelId The ID of the {@link dev.sheldan.abstracto.core.models.database.AChannel} in which the status updates
|
||||
* should be sent to
|
||||
* @return A {@link CompletableFuture future} which completes, after all the updates on the {@link net.dv8tion.jda.api.entities.Member}
|
||||
* have been completed
|
||||
*/
|
||||
CompletableFuture<Void> unsetRoles(ARole role, Long channelId);
|
||||
CompletableFuture<Void> setRoleToLevel(Role role, Integer level, GuildMessageChannel messageChannel);
|
||||
|
||||
CompletableFuture<Void> unsetRoles(ARole role, GuildMessageChannel messageChannel);
|
||||
List<AExperienceRole> getExperienceRolesAtLevel(Integer level, AServer server);
|
||||
CompletableFuture<Void> unsetRoles(List<ARole> roles, Long channelId);
|
||||
CompletableFuture<Void> unsetRoles(List<ARole> roles, Long channelId, AExperienceRole toAdd);
|
||||
CompletableFuture<Void> unsetRoles(List<ARole> roles, GuildMessageChannel messageChannel);
|
||||
|
||||
/**
|
||||
* Calculates the appropriate {@link AExperienceRole experienceRole} based on the provided list of {@link AExperienceRole experienceRole}
|
||||
|
||||
@@ -37,6 +37,7 @@ public interface ExperienceRoleManagementService {
|
||||
* @param role The {@link AExperienceRole experienceRole} to delete.
|
||||
*/
|
||||
void unsetRole(AExperienceRole role);
|
||||
void unsetRoles(List<AExperienceRole> role);
|
||||
|
||||
/**
|
||||
* Retrieves the {@link AExperienceRole experienceRole} which uses the given {@link ARole role} in the {@link AServer server}
|
||||
@@ -44,6 +45,7 @@ public interface ExperienceRoleManagementService {
|
||||
* @return the {@link AExperienceRole experienceRole} which uses the given {@link ARole role}
|
||||
*/
|
||||
AExperienceRole getRoleInServer(ARole role);
|
||||
List<AExperienceRole> getRolesInServer(List<ARole> role);
|
||||
|
||||
/**
|
||||
* Retrieves a possible {@link AExperienceRole role}, if it exists, for the given {@link ARole}. Returns an empty Optional if it does not exist
|
||||
|
||||
@@ -3,6 +3,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.model.database.AExperienceRole;
|
||||
import dev.sheldan.abstracto.experience.model.database.AUserExperience;
|
||||
import dev.sheldan.abstracto.experience.model.database.LeaderBoardEntryResult;
|
||||
|
||||
@@ -19,6 +20,7 @@ public interface UserExperienceManagementService {
|
||||
* @return The {@link AUserExperience userExperience} object representing the {@link AUserInAServer userInAServer}
|
||||
*/
|
||||
AUserExperience findUserInServer(AUserInAServer aUserInAServer);
|
||||
void removeExperienceRoleFromUsers(AExperienceRole experienceRole);
|
||||
|
||||
/**
|
||||
* Retrieves a possible {@link AUserExperience userExperience} for the given ID of the {@link AUserInAServer}.
|
||||
|
||||
@@ -29,13 +29,6 @@ public class JoinLogger implements AsyncJoinListener {
|
||||
@Autowired
|
||||
private PostTargetService postTargetService;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private JoinLogger self;
|
||||
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MemberJoinModel listenerModel) {
|
||||
MemberJoinLogModel model = MemberJoinLogModel
|
||||
|
||||
@@ -3,6 +3,7 @@ package dev.sheldan.abstracto.logging.listener;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncLeaveListener;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.listener.MemberLeaveModel;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
@@ -27,13 +28,6 @@ public class LeaveLogger implements AsyncLeaveListener {
|
||||
@Autowired
|
||||
private PostTargetService postTargetService;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private LeaveLogger self;
|
||||
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return LoggingFeatureDefinition.LOGGING;
|
||||
@@ -41,8 +35,14 @@ public class LeaveLogger implements AsyncLeaveListener {
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MemberLeaveModel listenerModel) {
|
||||
ServerUser leavingUser = ServerUser
|
||||
.builder()
|
||||
.userId(listenerModel.getUser().getIdLong())
|
||||
.serverId(listenerModel.getServerId())
|
||||
.build();
|
||||
MemberLeaveModel model = MemberLeaveModel
|
||||
.builder()
|
||||
.leavingUser(leavingUser)
|
||||
.user(listenerModel.getUser())
|
||||
.build();
|
||||
log.debug("Logging leave event for user {} in server {}.", listenerModel.getUser().getIdLong(), listenerModel.getServerId());
|
||||
|
||||
@@ -21,6 +21,14 @@ public class RoleDisplay {
|
||||
.build();
|
||||
}
|
||||
|
||||
public static RoleDisplay fromRole(Long roleId) {
|
||||
return RoleDisplay
|
||||
.builder()
|
||||
.roleId(roleId)
|
||||
.roleMention("<@&" + roleId + '>')
|
||||
.build();
|
||||
}
|
||||
|
||||
public static RoleDisplay fromARole(ARole role) {
|
||||
return RoleDisplay
|
||||
.builder()
|
||||
|
||||
Reference in New Issue
Block a user