added experience tracking and automatic role assigning at given levels

includes: set role command to set a role to a given level (it clears out previous levels)
automatic level config generation on startup
min/max/multiplier configuration
job to persist the xp of the previous minute
added delayed scheduler start, so that events have a discord context in order to function
added role listener to automatically add and mark roles when they are created/deleted
fixed user in a server not being created correctly
added role service to give users role given by id
added server reference to role
This commit is contained in:
Sheldan
2020-04-11 17:21:55 +02:00
parent 87c97d5069
commit 6a31dfde8a
72 changed files with 1165 additions and 80 deletions

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>utility</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>experience-tracking-impl</artifactId>
<dependencies>
<dependency>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>experience-tracking-int</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,19 @@
package dev.sheldan.abstracto.experience.commands;
import dev.sheldan.abstracto.core.command.config.ModuleInfo;
import dev.sheldan.abstracto.core.command.config.ModuleInterface;
public class ExperienceModule implements ModuleInterface {
public static final String EXPERIENCE = "utility";
@Override
public ModuleInfo getInfo() {
return ModuleInfo.builder().name(EXPERIENCE).description("Module containing commands related to experience tracking.").build();
}
@Override
public String getParentModule() {
return "default";
}
}

View File

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

View File

@@ -0,0 +1,17 @@
package dev.sheldan.abstracto.experience.config;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@Getter
@Setter
@ConfigurationProperties(prefix = "abstracto.experience")
public class ExperienceConfig {
private Integer minExp;
private Integer maxExp;
private Integer multiplier;
private Integer maxLvl;
}

View File

@@ -0,0 +1,28 @@
package dev.sheldan.abstracto.experience.config;
import dev.sheldan.abstracto.core.listener.ServerConfigListener;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.ConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class ExperienceConfigListener implements ServerConfigListener {
@Autowired
private ExperienceConfig experienceConfig;
@Autowired
private ConfigService service;
@Override
public void updateServerConfig(AServer server) {
log.info("Setting up experience for {}", server.getId());
service.createDoubleValueIfNotExist("minExp", server.getId(), experienceConfig.getMinExp().doubleValue());
service.createDoubleValueIfNotExist("maxExp", server.getId(), experienceConfig.getMaxExp().doubleValue());
service.createDoubleValueIfNotExist("multiplier", server.getId(), experienceConfig.getMultiplier().doubleValue());
}
}

View File

@@ -0,0 +1,5 @@
package dev.sheldan.abstracto.experience.config;
public class ExperienceFeatures {
public static String EXPERIENCE = "experience";
}

View File

@@ -0,0 +1,30 @@
package dev.sheldan.abstracto.experience.config;
import dev.sheldan.abstracto.experience.service.ExperienceLevelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class ExperienceLevelLoader {
@Autowired
private ExperienceConfig experienceConfig;
@Autowired
private ExperienceLevelService experienceLevelService;
@EventListener
public void handleContextRefreshEvent(ContextRefreshedEvent ctxStartEvt) {
Integer maxLevel = experienceConfig.getMaxLvl();
Long experience = 0L;
experienceLevelService.createExperienceLevel(0, 0L);
for (int i = 1; i < maxLevel; i++) {
experience = experience + experienceLevelService.calculateExperienceForLevel(i - 1);
experienceLevelService.createExperienceLevel(i, experience);
}
}
}

View File

@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.experience.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:experience.properties")
public class ExperienceProperties {
}

View File

@@ -0,0 +1,41 @@
package dev.sheldan.abstracto.experience.job;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.experience.service.ExperienceTrackerService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
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.HashMap;
import java.util.List;
@Slf4j
@DisallowConcurrentExecution
@Component
@PersistJobDataAfterExecution
public class ExperiencePersistingJob extends QuartzJobBean {
@Autowired
private ExperienceTrackerService experienceTrackerService;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
HashMap<Long, List<AServer>> runtimeExperience = experienceTrackerService.getRuntimeExperience();
log.info("Storing experience");
Long pastMinute = (Instant.now().getEpochSecond() / 60) - 1;
if(runtimeExperience.containsKey(pastMinute)) {
experienceTrackerService.handleExperienceGain(runtimeExperience.get(pastMinute));
runtimeExperience.remove(pastMinute);
}
}
}

View File

@@ -0,0 +1,34 @@
package dev.sheldan.abstracto.experience.listener;
import dev.sheldan.abstracto.core.listener.MessageReceivedListener;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.UserManagementService;
import dev.sheldan.abstracto.experience.config.ExperienceFeatures;
import dev.sheldan.abstracto.experience.service.ExperienceTrackerService;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Component
public class ExperienceTrackerListener implements MessageReceivedListener {
@Autowired
private ExperienceTrackerService experienceTrackerService;
@Autowired
private UserManagementService userManagementService;
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void execute(Message message) {
AUserInAServer cause = userManagementService.loadUser(message.getMember());
experienceTrackerService.addExperience(cause);
}
@Override
public String getFeature() {
return ExperienceFeatures.EXPERIENCE;
}
}

View File

@@ -0,0 +1,10 @@
package dev.sheldan.abstracto.experience.repository;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ExperienceLevelRepository extends JpaRepository<AExperienceLevel, Integer> {
AExperienceLevel findTopByExperienceNeededGreaterThanOrderByExperienceNeededAsc(Long experience);
}

View File

@@ -0,0 +1,17 @@
package dev.sheldan.abstracto.experience.repository;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import dev.sheldan.abstracto.experience.models.database.AExperienceRole;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface ExperienceRoleRepository extends JpaRepository<AExperienceRole, Long> {
AExperienceRole findByRoleServerAndRole(AServer server, ARole role);
List<AExperienceRole> findByLevelAndRoleServer(AExperienceLevel level, AServer server);
List<AExperienceRole> findByRoleServer(AServer server);
}

View File

@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.experience.repository;
import dev.sheldan.abstracto.experience.models.database.AUserExperience;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserExperienceRepository extends JpaRepository<AUserExperience, Long> {
}

View File

@@ -0,0 +1,25 @@
package dev.sheldan.abstracto.experience.service;
import dev.sheldan.abstracto.experience.service.management.ExperienceLevelManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class ExperienceLevelServiceBean implements ExperienceLevelService {
@Autowired
private ExperienceLevelManagementService experienceLevelManagementService;
@Override
public void createExperienceLevel(Integer level, Long experienceNeeded) {
if(!experienceLevelManagementService.levelExists(level)) {
experienceLevelManagementService.createExperienceLevel(level, experienceNeeded);
}
}
@Override
public Long calculateExperienceForLevel(Integer level) {
return 5L * (level * level) + 50 * level + 100;
}
}

View File

@@ -0,0 +1,27 @@
package dev.sheldan.abstracto.experience.service;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import dev.sheldan.abstracto.experience.service.management.ExperienceLevelManagementService;
import dev.sheldan.abstracto.experience.service.management.ExperienceRoleManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class ExperienceRoleServiceBean implements ExperienceRoleService {
@Autowired
private ExperienceRoleManagementService experienceRoleManagementService;
@Autowired
private ExperienceLevelManagementService experienceLevelService;
@Override
public void setRoleToLevel(ARole role, Integer level, AServer server) {
AExperienceLevel experienceLevel = experienceLevelService.getLevel(level);
experienceRoleManagementService.unSetLevelInServer(experienceLevel, server);
experienceRoleManagementService.setLevelToRole(experienceLevel, role, server);
}
}

View File

@@ -0,0 +1,152 @@
package dev.sheldan.abstracto.experience.service;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.ConfigService;
import dev.sheldan.abstracto.core.service.RoleService;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import dev.sheldan.abstracto.experience.models.database.AExperienceRole;
import dev.sheldan.abstracto.experience.models.database.AUserExperience;
import dev.sheldan.abstracto.experience.service.management.ExperienceLevelManagementService;
import dev.sheldan.abstracto.experience.service.management.ExperienceRoleManagementService;
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.util.*;
@Component
@Slf4j
public class ExperienceTrackerServiceBean implements ExperienceTrackerService {
private HashMap<Long, List<AServer>> runtimeExperience = new HashMap<>();
@Autowired
private UserExperienceManagementService userExperienceManagementService;
@Autowired
private ExperienceLevelService experienceLevelService;
@Autowired
private ExperienceLevelManagementService experienceLevelManagementService;
@Autowired
private ExperienceRoleManagementService experienceRoleManagementService;
@Autowired
private ConfigService configService;
@Autowired
private RoleService roleService;
@Override
public void addExperience(AUserInAServer userInAServer) {
Long second = Instant.now().getEpochSecond() / 60;
if(runtimeExperience.containsKey(second)) {
List<AServer> existing = runtimeExperience.get(second);
existing.forEach(server -> {
if(server.getUsers().stream().noneMatch(userInAServer1 -> userInAServer.getUserInServerId().equals(userInAServer1.getUserInServerId()))) {
server.getUsers().add(userInAServer);
}
});
} else {
AServer server = AServer
.builder()
.id(userInAServer.getServerReference().getId())
.build();
server.getUsers().add(userInAServer);
runtimeExperience.put(second, Arrays.asList(server));
}
}
@Override
public HashMap<Long, List<AServer>> getRuntimeExperience() {
return runtimeExperience;
}
@Override
public Integer calculateLevel(AUserExperience userInAServer, List<AExperienceLevel> levels) {
AExperienceLevel lastLevel = levels.get(0);
for (AExperienceLevel level : levels) {
if(level.getExperienceNeeded() >= userInAServer.getExperience()) {
return lastLevel.getLevel();
} else {
lastLevel = level;
}
}
return lastLevel.getLevel();
}
@Override
public AExperienceRole calculateRole(AUserExperience userInAServer, List<AExperienceRole> roles) {
if(roles.size() == 0) {
return null;
}
AExperienceRole lastRole = null;
for (AExperienceRole experienceRole : roles) {
if(userInAServer.getCurrentLevel().getLevel() >= experienceRole.getLevel().getLevel()) {
lastRole = experienceRole;
} else {
return experienceRole;
}
}
return lastRole;
}
@Override
public void increaseExpForUser(AUserExperience userInAServer, Long experience, List<AExperienceLevel> levels) {
userInAServer.setExperience(userInAServer.getExperience() + experience);
Integer correctLevel = calculateLevel(userInAServer, levels);
Integer currentLevel = userInAServer.getCurrentLevel() != null ? userInAServer.getCurrentLevel().getLevel() : 0;
if(!correctLevel.equals(currentLevel)) {
log.info("User {} leveled from {} to {}", userInAServer.getUser().getUserReference().getId(), currentLevel, correctLevel);
userInAServer.setCurrentLevel(experienceLevelManagementService.getLevel(correctLevel));
}
userExperienceManagementService.saveUser(userInAServer);
}
@Transactional
@Override
public void handleExperienceGain(List<AServer> servers) {
servers.forEach(serverExp -> {
log.info("Handling experience for server {}", serverExp.getId());
int minExp = configService.getDoubleValue("minExp", serverExp.getId()).intValue();
int maxExp = configService.getDoubleValue("maxExp", serverExp.getId()).intValue();
Integer multiplier = configService.getDoubleValue("multiplier", serverExp.getId()).intValue();
PrimitiveIterator.OfInt iterator = new Random().ints(serverExp.getUsers().size(), minExp, maxExp + 1).iterator();
List<AExperienceLevel> levels = experienceLevelManagementService.getLevelConfig();
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRoleForServer(serverExp);
levels.sort(Comparator.comparing(AExperienceLevel::getExperienceNeeded));
serverExp.getUsers().forEach(userInAServer -> {
Integer gainedExperience = iterator.next();
gainedExperience *= multiplier;
log.info("Handling {}. The user gains {}", userInAServer.getUserReference().getId(), gainedExperience);
AUserExperience userExperience = userExperienceManagementService.findUserInServer(userInAServer);
increaseExpForUser(userExperience, gainedExperience.longValue(), levels);
handleExperienceRoleForUser(userExperience, roles);
});
});
}
@Override
public void handleExperienceRoleForUser(AUserExperience userExperience, List<AExperienceRole> roles) {
AExperienceRole role = calculateRole(userExperience, roles);
if(role == null) {
return;
}
boolean currentlyHasNoExperienceRole = userExperience.getCurrentExperienceRole() == null;
if(currentlyHasNoExperienceRole || !role.getRole().getId().equals(userExperience.getCurrentExperienceRole().getId())) {
log.info("User {} gets a new role {}", userExperience.getUser().getUserReference().getId(), role.getRole().getId());
if(!currentlyHasNoExperienceRole) {
roleService.removeRoleFromUser(userExperience.getUser(), userExperience.getCurrentExperienceRole().getRole());
}
userExperience.setCurrentExperienceRole(role);
roleService.addRoleToUser(userExperience.getUser(), userExperience.getCurrentExperienceRole().getRole());
}
}
}

View File

@@ -0,0 +1,46 @@
package dev.sheldan.abstracto.experience.service.management;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import dev.sheldan.abstracto.experience.repository.ExperienceLevelRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class ExperienceLevelManagementServiceBean implements ExperienceLevelManagementService {
@Autowired
private ExperienceLevelRepository experienceLevelRepository;
@Override
public AExperienceLevel createExperienceLevel(Integer level, Long neededExperience) {
AExperienceLevel experienceLevel = AExperienceLevel
.builder()
.experienceNeeded(neededExperience)
.level(level)
.build();
experienceLevelRepository.save(experienceLevel);
return experienceLevel;
}
@Override
public boolean levelExists(Integer level) {
return experienceLevelRepository.existsById(level);
}
@Override
public AExperienceLevel getLevel(Integer level) {
return experienceLevelRepository.getOne(level);
}
@Override
public AExperienceLevel getLevelClosestTo(Long experience) {
return experienceLevelRepository.findTopByExperienceNeededGreaterThanOrderByExperienceNeededAsc(experience);
}
@Override
public List<AExperienceLevel> getLevelConfig() {
return experienceLevelRepository.findAll();
}
}

View File

@@ -0,0 +1,47 @@
package dev.sheldan.abstracto.experience.service.management;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import dev.sheldan.abstracto.experience.models.database.AExperienceRole;
import dev.sheldan.abstracto.experience.repository.ExperienceRoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class ExperienceRoleManagementServiceBean implements ExperienceRoleManagementService {
@Autowired
private ExperienceRoleRepository experienceRoleRepository;
@Override
public void unSetLevelInServer(AExperienceLevel level, AServer server) {
List<AExperienceRole> existingExperienceRoles = experienceRoleRepository.findByLevelAndRoleServer(level, server);
existingExperienceRoles.forEach(existingRole -> {
experienceRoleRepository.delete(existingRole);
});
}
@Override
public List<AExperienceRole> getExperienceRoleForServer(AServer server) {
return experienceRoleRepository.findByRoleServer(server);
}
@Override
public void setLevelToRole(AExperienceLevel level, ARole role, AServer server) {
AExperienceRole byRoleServerAndRole = experienceRoleRepository.findByRoleServerAndRole(server, role);
if(byRoleServerAndRole != null) {
byRoleServerAndRole.setLevel(level);
} else {
byRoleServerAndRole = AExperienceRole
.builder()
.level(level)
.roleServer(server)
.role(role)
.build();
}
experienceRoleRepository.save(byRoleServerAndRole);
}
}

View File

@@ -0,0 +1,54 @@
package dev.sheldan.abstracto.experience.service.management;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import dev.sheldan.abstracto.experience.models.database.AUserExperience;
import dev.sheldan.abstracto.experience.repository.UserExperienceRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class UserExperienceManagementServiceBean implements UserExperienceManagementService {
@Autowired
private UserExperienceRepository repository;
@Autowired
private ExperienceLevelManagementService experienceLevelManagementService;
@Override
public void setExperienceTo(AUserExperience aUserInAServer, Long experience) {
aUserInAServer.setExperience(experience);
repository.save(aUserInAServer);
}
@Override
public AUserExperience findUserInServer(AUserInAServer aUserInAServer) {
Optional<AUserExperience> byId = repository.findById(aUserInAServer.getUserInServerId());
return byId.orElseGet(() -> createUserInServer(aUserInAServer));
}
@Override
public AUserExperience createUserInServer(AUserInAServer aUserInAServer) {
AExperienceLevel startingLevel = experienceLevelManagementService.getLevel(0);
AUserExperience userExperience = AUserExperience
.builder()
.experience(0L)
.user(aUserInAServer)
.id(aUserInAServer.getUserInServerId())
.currentLevel(startingLevel)
.build();
repository.save(userExperience);
return userExperience;
}
@Override
public void saveUser(AUserExperience userExperience) {
repository.save(userExperience);
}
}

View File

@@ -0,0 +1,14 @@
abstracto.scheduling.jobs.experienceJob.name=experienceJob
abstracto.scheduling.jobs.experienceJob.group=experience
abstracto.scheduling.jobs.experienceJob.clazz=dev.sheldan.abstracto.experience.job.ExperiencePersistingJob
abstracto.scheduling.jobs.experienceJob.standAlone=true
abstracto.scheduling.jobs.experienceJob.active=true
abstracto.scheduling.jobs.experienceJob.cronExpression=30 * * * * ?
abstracto.features.experience=true
abstracto.experience.minExp=10
abstracto.experience.maxExp=25
abstracto.experience.multiplier=1
abstracto.experience.maxLvl=200

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>utility</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>experience-tracking-int</artifactId>
<dependencies>
<dependency>
<groupId>dev.sheldan.abstracto.templating</groupId>
<artifactId>templating-interface</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.sheldan.abstracto.scheduling</groupId>
<artifactId>scheduling-int</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,20 @@
package dev.sheldan.abstracto.experience.models.database;
import lombok.*;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Builder
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "experience_level")
@Getter
@Setter
public class AExperienceLevel {
@Id
private Integer level;
private Long experienceNeeded;
}

View File

@@ -0,0 +1,45 @@
package dev.sheldan.abstracto.experience.models.database;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import lombok.*;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Builder
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "experience_role")
@Getter
@Setter
public class AExperienceRole {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "level_id")
private AExperienceLevel level;
@ManyToOne(fetch = FetchType.LAZY)
@Getter
@Setter
@JoinColumn(name = "server_id")
private AServer roleServer;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "role_id")
private ARole role;
@OneToMany(
fetch = FetchType.LAZY,
cascade = CascadeType.ALL,
orphanRemoval = true)
@Builder.Default
@JoinColumn(name = "experience_role_id")
private List<AUserExperience> users = new ArrayList<>();
}

View File

@@ -0,0 +1,34 @@
package dev.sheldan.abstracto.experience.models.database;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import lombok.*;
import javax.persistence.*;
@Builder
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "user_experience")
@Getter
@Setter
public class AUserExperience {
@Id
private Long id;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
private AUserInAServer user;
private Long experience;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "level_id")
private AExperienceLevel currentLevel;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "experience_role_id")
private AExperienceRole currentExperienceRole;
}

View File

@@ -0,0 +1,6 @@
package dev.sheldan.abstracto.experience.service;
public interface ExperienceLevelService {
void createExperienceLevel(Integer level, Long experienceNeeded);
Long calculateExperienceForLevel(Integer level);
}

View File

@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.experience.service;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.experience.models.database.AExperienceRole;
public interface ExperienceRoleService {
void setRoleToLevel(ARole role, Integer level, AServer server);
}

View File

@@ -0,0 +1,20 @@
package dev.sheldan.abstracto.experience.service;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import dev.sheldan.abstracto.experience.models.database.AExperienceRole;
import dev.sheldan.abstracto.experience.models.database.AUserExperience;
import java.util.HashMap;
import java.util.List;
public interface ExperienceTrackerService {
void addExperience(AUserInAServer userInAServer);
HashMap<Long, List<AServer>> getRuntimeExperience();
Integer calculateLevel(AUserExperience userInAServer, List<AExperienceLevel> levels);
AExperienceRole calculateRole(AUserExperience userInAServer, List<AExperienceRole> roles);
void increaseExpForUser(AUserExperience userInAServer, Long experience, List<AExperienceLevel> levels);
void handleExperienceGain(List<AServer> serverExp);
void handleExperienceRoleForUser(AUserExperience userExperience, List<AExperienceRole> roles);
}

View File

@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.experience.service.management;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import java.util.List;
public interface ExperienceLevelManagementService {
AExperienceLevel createExperienceLevel(Integer level, Long neededExperience);
boolean levelExists(Integer level);
AExperienceLevel getLevel(Integer level);
AExperienceLevel getLevelClosestTo(Long experience);
List<AExperienceLevel> getLevelConfig();
}

View File

@@ -0,0 +1,14 @@
package dev.sheldan.abstracto.experience.service.management;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.experience.models.database.AExperienceLevel;
import dev.sheldan.abstracto.experience.models.database.AExperienceRole;
import java.util.List;
public interface ExperienceRoleManagementService {
void setLevelToRole(AExperienceLevel level, ARole role, AServer server);
void unSetLevelInServer(AExperienceLevel level, AServer server);
List<AExperienceRole> getExperienceRoleForServer(AServer server);
}

View File

@@ -0,0 +1,12 @@
package dev.sheldan.abstracto.experience.service.management;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.experience.models.database.AUserExperience;
public interface UserExperienceManagementService {
void setExperienceTo(AUserExperience aUserInAServer, Long experience);
AUserExperience findUserInServer(AUserInAServer aUserInAServer);
AUserExperience createUserInServer(AUserInAServer aUserInAServer);
void saveUser(AUserExperience userExperience);
}

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>dev.sheldan.abstracto</groupId>
<artifactId>abstracto-modules</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>experience-tracking</artifactId>
<packaging>pom</packaging>
<modules>
<module>experience-tracking-int</module>
<module>experience-tracking-impl</module>
</modules>
<dependencies>
<dependency>
<groupId>dev.sheldan.abstracto.core</groupId>
<artifactId>core-interface</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>