diff --git a/src/main/java/ru/ulstu/extractor/gitrepository/service/IndexService.java b/src/main/java/ru/ulstu/extractor/gitrepository/service/IndexService.java index 5d2c1c2..5ceb162 100644 --- a/src/main/java/ru/ulstu/extractor/gitrepository/service/IndexService.java +++ b/src/main/java/ru/ulstu/extractor/gitrepository/service/IndexService.java @@ -62,7 +62,8 @@ public class IndexService { commits = gitRepositoryService.getCommits(repositoryUrl, branchName, commitsFrom, commitsTo, false); } Integer repositoryId = gitRepository.getId(); - timeSeriesCreators.forEach(tsCreator -> tsCreator.addTimeSeries(repositoryId, branchName)); + final Branch branchForSave = branch; + timeSeriesCreators.forEach(tsCreator -> tsCreator.addTimeSeries(repositoryId, branchForSave)); LOG.debug("Complete indexing {} branch", branchName); } } diff --git a/src/main/java/ru/ulstu/extractor/http/SmoothingTimeSeries.java b/src/main/java/ru/ulstu/extractor/http/SmoothingTimeSeries.java new file mode 100644 index 0000000..9224a9c --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/http/SmoothingTimeSeries.java @@ -0,0 +1,29 @@ +package ru.ulstu.extractor.http; + +import ru.ulstu.extractor.ts.model.TimeSeries; + +public class SmoothingTimeSeries { + private JsonTimeSeries originalTimeSeries; + private String methodClassName; + + public SmoothingTimeSeries(TimeSeries timeSeries) { + originalTimeSeries = new JsonTimeSeries(timeSeries); + this.methodClassName = "FTransform"; + } + + public JsonTimeSeries getOriginalTimeSeries() { + return originalTimeSeries; + } + + public void setOriginalTimeSeries(JsonTimeSeries originalTimeSeries) { + this.originalTimeSeries = originalTimeSeries; + } + + public String getMethodClassName() { + return methodClassName; + } + + public void setMethodClassName(String methodClassName) { + this.methodClassName = methodClassName; + } +} diff --git a/src/main/java/ru/ulstu/extractor/recommendation/controller/RecommendationController.java b/src/main/java/ru/ulstu/extractor/recommendation/controller/RecommendationController.java index a303067..4c0f803 100644 --- a/src/main/java/ru/ulstu/extractor/recommendation/controller/RecommendationController.java +++ b/src/main/java/ru/ulstu/extractor/recommendation/controller/RecommendationController.java @@ -29,7 +29,7 @@ public class RecommendationController { public String getRecommendations(Model model, @RequestParam Optional branchId) { model.addAttribute("branches", branchService.findAll()); if (branchId.isPresent()) { - model.addAttribute("recommendations", fuzzyInferenceService.getRecommendations()); + model.addAttribute("recommendations", fuzzyInferenceService.getRecommendations(branchId.get())); model.addAttribute("filterBranchForm", new FilterBranchForm(branchId.get())); } else { model.addAttribute("filterBranchForm", new FilterBranchForm()); diff --git a/src/main/java/ru/ulstu/extractor/rule/controller/RuleController.java b/src/main/java/ru/ulstu/extractor/rule/controller/RuleController.java index 7893dea..4e855df 100644 --- a/src/main/java/ru/ulstu/extractor/rule/controller/RuleController.java +++ b/src/main/java/ru/ulstu/extractor/rule/controller/RuleController.java @@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import ru.ulstu.extractor.rule.model.AddRuleForm; import ru.ulstu.extractor.rule.service.AntecedentValueService; -import ru.ulstu.extractor.rule.service.RuleService; +import ru.ulstu.extractor.rule.service.DbRuleService; import ru.ulstu.extractor.ts.service.TimeSeriesService; import springfox.documentation.annotations.ApiIgnore; @@ -21,14 +21,14 @@ import static ru.ulstu.extractor.core.Route.LIST_RULE; @Controller @ApiIgnore public class RuleController { - private final RuleService ruleService; + private final DbRuleService ruleService; private final AntecedentValueService antecedentValueService; private final TimeSeriesService timeSeriesService; - public RuleController(RuleService ruleService, + public RuleController(DbRuleService dbRuleService, AntecedentValueService antecedentValueService, TimeSeriesService timeSeriesService) { - this.ruleService = ruleService; + this.ruleService = dbRuleService; this.antecedentValueService = antecedentValueService; this.timeSeriesService = timeSeriesService; } diff --git a/src/main/java/ru/ulstu/extractor/rule/service/RuleService.java b/src/main/java/ru/ulstu/extractor/rule/service/DbRuleService.java similarity index 91% rename from src/main/java/ru/ulstu/extractor/rule/service/RuleService.java rename to src/main/java/ru/ulstu/extractor/rule/service/DbRuleService.java index 41ae26b..a35cca2 100644 --- a/src/main/java/ru/ulstu/extractor/rule/service/RuleService.java +++ b/src/main/java/ru/ulstu/extractor/rule/service/DbRuleService.java @@ -10,14 +10,14 @@ import ru.ulstu.extractor.ts.service.TimeSeriesService; import java.util.List; @Service -public class RuleService { +public class DbRuleService { private final RuleRepository ruleRepository; private final TimeSeriesService timeSeriesService; private final AntecedentValueService antecedentValueService; - public RuleService(RuleRepository ruleRepository, - TimeSeriesService timeSeriesService, - AntecedentValueService antecedentValueService) { + public DbRuleService(RuleRepository ruleRepository, + TimeSeriesService timeSeriesService, + AntecedentValueService antecedentValueService) { this.ruleRepository = ruleRepository; this.timeSeriesService = timeSeriesService; this.antecedentValueService = antecedentValueService; diff --git a/src/main/java/ru/ulstu/extractor/rule/service/FuzzyInferenceService.java b/src/main/java/ru/ulstu/extractor/rule/service/FuzzyInferenceService.java index 6ec146e..f011aaf 100644 --- a/src/main/java/ru/ulstu/extractor/rule/service/FuzzyInferenceService.java +++ b/src/main/java/ru/ulstu/extractor/rule/service/FuzzyInferenceService.java @@ -12,8 +12,11 @@ import com.fuzzylite.term.Triangle; import com.fuzzylite.variable.InputVariable; import com.fuzzylite.variable.OutputVariable; import org.springframework.stereotype.Service; +import ru.ulstu.extractor.gitrepository.service.GitRepositoryService; import ru.ulstu.extractor.rule.model.AntecedentValue; import ru.ulstu.extractor.rule.model.DbRule; +import ru.ulstu.extractor.ts.model.TimeSeries; +import ru.ulstu.extractor.ts.service.TimeSeriesService; import java.util.HashMap; import java.util.List; @@ -26,13 +29,19 @@ public class FuzzyInferenceService { private final static String RULE_TEMPLATE = "if %s is %s and %s is %s then " + OUTPUT_VARIABLE_NAME + " is %s"; - private final RuleService ruleService; + private final DbRuleService ruleService; private final AntecedentValueService antecedentValueService; + private final GitRepositoryService gitRepositoryService; + private final TimeSeriesService timeSeriesService; - public FuzzyInferenceService(RuleService ruleService, - AntecedentValueService antecedentValueService) { + public FuzzyInferenceService(DbRuleService ruleService, + AntecedentValueService antecedentValueService, + GitRepositoryService gitRepositoryService, + TimeSeriesService timeSeriesService) { this.ruleService = ruleService; this.antecedentValueService = antecedentValueService; + this.gitRepositoryService = gitRepositoryService; + this.timeSeriesService = timeSeriesService; } public List getRulesFromDb() { @@ -96,13 +105,12 @@ public class FuzzyInferenceService { return engine; } - public String getRecommendations() { + public String getRecommendations(Integer branchId) { + List timeSeries = timeSeriesService.getByBranch(branchId); Engine engine = getFuzzyEngine(); List antecedentValues = antecedentValueService.getList(); Map variableValues = new HashMap<>(); - - variableValues.put("COMMITS", 0.0); - variableValues.put("AUTHORS", 0.0); + timeSeries.forEach(ts -> variableValues.put(ts.getTimeSeriesType().name(), timeSeriesService.getLastTimeSeriesTendency(ts))); engine.addRuleBlock(getRuleBlock(engine, variableValues, antecedentValues)); return getConsequent(engine, variableValues); } @@ -120,6 +128,5 @@ public class FuzzyInferenceService { return (outputVariable == null || Double.isNaN(outputVariable.getValue())) ? "Нет рекомендаций" : outputVariable.highestMembership(outputVariable.getValue()).getSecond().getName(); - //return outputVariable == null ? "" : outputVariable.fuzzyOutputValue(); } } diff --git a/src/main/java/ru/ulstu/extractor/ts/creator/AbstractTimeSeriesCreator.java b/src/main/java/ru/ulstu/extractor/ts/creator/AbstractTimeSeriesCreator.java index 0f470f5..ac353ac 100644 --- a/src/main/java/ru/ulstu/extractor/ts/creator/AbstractTimeSeriesCreator.java +++ b/src/main/java/ru/ulstu/extractor/ts/creator/AbstractTimeSeriesCreator.java @@ -1,5 +1,6 @@ package ru.ulstu.extractor.ts.creator; +import ru.ulstu.extractor.branch.model.Branch; import ru.ulstu.extractor.ts.model.TimeSeries; import ru.ulstu.extractor.ts.model.TimeSeriesType; import ru.ulstu.extractor.ts.model.TimeSeriesValue; @@ -29,15 +30,15 @@ public abstract class AbstractTimeSeriesCreator { * Сохранить извлеченные временные ряды * * @param repositoryId - * @param branchName + * @param branch */ - public void addTimeSeries(Integer repositoryId, String branchName) { + public void addTimeSeries(Integer repositoryId, Branch branch) { // извлеченные временных рядов - List timeSeries = getTimeSeries(repositoryId, branchName); + List timeSeries = getTimeSeries(repositoryId, branch.getName()); // сгруппированные по временным интервалам точки временных рядов timeSeries.forEach(ts -> ts.setValues(mapTimeSeriesToInterval(getTimeSeriesService().getTimeSeriesInterval(), ts.getValues()))); - getTimeSeriesService().save(sortTimeSeries(timeSeries)); + getTimeSeriesService().save(sortTimeSeries(timeSeries), branch); } private List sortTimeSeries(List timeSeries) { diff --git a/src/main/java/ru/ulstu/extractor/ts/creator/CommitsTS.java b/src/main/java/ru/ulstu/extractor/ts/creator/CommitsTS.java index c686a90..0b7ed9d 100644 --- a/src/main/java/ru/ulstu/extractor/ts/creator/CommitsTS.java +++ b/src/main/java/ru/ulstu/extractor/ts/creator/CommitsTS.java @@ -1,7 +1,9 @@ package ru.ulstu.extractor.ts.creator; import org.springframework.stereotype.Component; +import ru.ulstu.extractor.branch.service.BranchService; import ru.ulstu.extractor.commit.service.CommitService; +import ru.ulstu.extractor.gitrepository.model.GitRepository; import ru.ulstu.extractor.gitrepository.service.GitRepositoryService; import ru.ulstu.extractor.ts.model.TimeSeries; import ru.ulstu.extractor.ts.model.TimeSeriesType; @@ -17,24 +19,29 @@ public class CommitsTS extends AbstractTimeSeriesCreator { private final TimeSeriesService timeSeriesService; private final CommitService commitService; private final GitRepositoryService gitRepositoryService; + private final BranchService branchService; public CommitsTS(TimeSeriesService timeSeriesService, CommitService commitService, - GitRepositoryService gitRepositoryService) { + GitRepositoryService gitRepositoryService, + BranchService branchService) { this.timeSeriesService = timeSeriesService; this.commitService = commitService; this.gitRepositoryService = gitRepositoryService; + this.branchService = branchService; } @Override public List getTimeSeries(Integer repositoryId, String branchName) { + GitRepository gitRepository = gitRepositoryService.findById(repositoryId); //TODO: добавить постраничное чтение return Collections.singletonList( new TimeSeries( String.format("%s %s %s", - gitRepositoryService.findById(repositoryId).getName(), + gitRepository.getName(), branchName, getTimeSeriesType().getDescription()), + branchService.findByRepositoryAndName(gitRepository, branchName), getTimeSeriesType(), commitService.findByRepositoryIdAndName(repositoryId, branchName) .stream() diff --git a/src/main/java/ru/ulstu/extractor/ts/model/TimeSeries.java b/src/main/java/ru/ulstu/extractor/ts/model/TimeSeries.java index b6d6931..5e302fa 100644 --- a/src/main/java/ru/ulstu/extractor/ts/model/TimeSeries.java +++ b/src/main/java/ru/ulstu/extractor/ts/model/TimeSeries.java @@ -2,6 +2,7 @@ package ru.ulstu.extractor.ts.model; import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; +import ru.ulstu.extractor.branch.model.Branch; import ru.ulstu.extractor.core.BaseEntity; import javax.persistence.CascadeType; @@ -10,6 +11,7 @@ import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.FetchType; import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import java.util.ArrayList; import java.util.List; @@ -25,22 +27,21 @@ public class TimeSeries extends BaseEntity { @Enumerated(EnumType.STRING) private TimeSeriesType timeSeriesType; - public TimeSeries() { - } + @ManyToOne + private Branch branch; - public TimeSeries(String name) { - this.name = name; + public TimeSeries() { } - public TimeSeries(String name, List values) { - this.name = name; - this.values = values; + public TimeSeries(String name, Branch branch, TimeSeriesType timeSeriesType) { + this(name, branch, timeSeriesType, new ArrayList<>()); } - public TimeSeries(String name, TimeSeriesType timeSeriesType, List values) { + public TimeSeries(String name, Branch branch, TimeSeriesType timeSeriesType, List values) { this.name = name; this.values = values; this.timeSeriesType = timeSeriesType; + this.branch = branch; } public String getName() { @@ -66,4 +67,12 @@ public class TimeSeries extends BaseEntity { public void setTimeSeriesType(TimeSeriesType timeSeriesType) { this.timeSeriesType = timeSeriesType; } + + public Branch getBranch() { + return branch; + } + + public void setBranch(Branch branch) { + this.branch = branch; + } } diff --git a/src/main/java/ru/ulstu/extractor/ts/repository/TimeSeriesRepository.java b/src/main/java/ru/ulstu/extractor/ts/repository/TimeSeriesRepository.java index fbb123e..7346519 100644 --- a/src/main/java/ru/ulstu/extractor/ts/repository/TimeSeriesRepository.java +++ b/src/main/java/ru/ulstu/extractor/ts/repository/TimeSeriesRepository.java @@ -3,8 +3,11 @@ package ru.ulstu.extractor.ts.repository; import org.springframework.data.jpa.repository.JpaRepository; import ru.ulstu.extractor.ts.model.TimeSeries; +import java.util.List; import java.util.Optional; public interface TimeSeriesRepository extends JpaRepository { Optional findByName(String name); + + List getTimeSeriesByBranchId(Integer branchId); } diff --git a/src/main/java/ru/ulstu/extractor/ts/service/TimeSeriesService.java b/src/main/java/ru/ulstu/extractor/ts/service/TimeSeriesService.java index 9c79d0f..4a4b2f2 100644 --- a/src/main/java/ru/ulstu/extractor/ts/service/TimeSeriesService.java +++ b/src/main/java/ru/ulstu/extractor/ts/service/TimeSeriesService.java @@ -9,8 +9,10 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; +import ru.ulstu.extractor.branch.model.Branch; import ru.ulstu.extractor.http.HttpService; import ru.ulstu.extractor.http.JsonTimeSeries; +import ru.ulstu.extractor.http.SmoothingTimeSeries; import ru.ulstu.extractor.ts.model.TimeSeries; import ru.ulstu.extractor.ts.model.TimeSeriesType; import ru.ulstu.extractor.ts.model.TimeSeriesValue; @@ -31,7 +33,8 @@ public class TimeSeriesService { private final TimeSeriesValueRepository timeSeriesValueRepository; private final TimeSeriesDateMapper.TimeSeriesInterval timeSeriesInterval = TimeSeriesDateMapper.TimeSeriesInterval.HOUR; private final HttpService httpService; - private final static String TIME_SERIES_SERVICE_URL = "http://time-series.athene.tech/api/1.0/add-time-series?setKey=git-extractor"; + private final static String TIME_SERIES_SAVE_SERVICE_URL = "http://time-series.athene.tech/api/1.0/add-time-series?setKey=git-extractor"; + private final static String TIME_SERIES_TENDENCY_URL = "http://time-series.athene.tech/api/1.0/add-time-series?setKey=git-extractor"; public TimeSeriesService(TimeSeriesRepository timeSeriesRepository, TimeSeriesValueRepository timeSeriesValueRepository, @@ -42,12 +45,11 @@ public class TimeSeriesService { } @Transactional - public TimeSeries save(String timeSeriesName, TimeSeriesType timeSeriesType, List timeSeriesValues) { + public TimeSeries save(String timeSeriesName, Branch branch, TimeSeriesType timeSeriesType, List timeSeriesValues) { LOG.debug("Start save {} time series with {} time series values ", timeSeriesName, timeSeriesValues.size()); - final TimeSeries timeSeries = findOrCreate(timeSeriesName); + final TimeSeries timeSeries = findOrCreate(timeSeriesName, branch, timeSeriesType); List timeSeriesValuesToRemove = timeSeries.getValues(); timeSeries.setValues(timeSeriesValues); - timeSeries.setTimeSeriesType(timeSeriesType); LOG.debug("Save time series {} ", timeSeries.getName()); TimeSeries savedTimeSeries = timeSeriesRepository.save(timeSeries); LOG.debug("Clear {} time series values ", timeSeriesValuesToRemove.size()); @@ -56,13 +58,13 @@ public class TimeSeriesService { return savedTimeSeries; } - public TimeSeries findOrCreate(String timeSeriesName) { + public TimeSeries findOrCreate(String timeSeriesName, Branch branch, TimeSeriesType timeSeriesType) { Optional maybeTimeSeries = timeSeriesRepository.findByName(timeSeriesName); if (maybeTimeSeries.isPresent()) { LOG.debug("TimeSeries {} exists.", maybeTimeSeries.get().getName()); return maybeTimeSeries.get(); } - return timeSeriesRepository.save(new TimeSeries(timeSeriesName)); + return timeSeriesRepository.save(new TimeSeries(timeSeriesName, branch, timeSeriesType)); } /** @@ -72,10 +74,10 @@ public class TimeSeriesService { * @return сохраненный список ВР */ @Transactional - public List save(List timeSeries) { + public List save(List timeSeries, Branch branch) { List results = new ArrayList<>(); for (TimeSeries ts : timeSeries) { - results.add(save(ts.getName(), ts.getTimeSeriesType(), ts.getValues())); + results.add(save(ts.getName(), branch, ts.getTimeSeriesType(), ts.getValues())); } return results; } @@ -87,7 +89,7 @@ public class TimeSeriesService { private void sendToTimeSeriesService(TimeSeries timeSeries) { new Thread(() -> { try { - httpService.post(TIME_SERIES_SERVICE_URL, new JSONObject(new JsonTimeSeries(timeSeries))); + httpService.post(TIME_SERIES_SAVE_SERVICE_URL, new JSONObject(new JsonTimeSeries(timeSeries))); LOG.debug("Успешно отправлен на сервис"); } catch (Exception ex) { LOG.debug(ex.getMessage()); @@ -107,4 +109,15 @@ public class TimeSeriesService { public List getAllTimeSeriesTypes() { return Arrays.asList(TimeSeriesType.values()); } + + public List getByBranch(Integer branchId) { + return timeSeriesRepository.getTimeSeriesByBranchId(branchId); + } + + public Double getLastTimeSeriesTendency(TimeSeries ts) { + JSONObject response = httpService.post(TIME_SERIES_TENDENCY_URL, new JSONObject(new SmoothingTimeSeries(ts))); + LOG.debug("Успешно отправлен на сервис сглаживания"); + response.get("timeSeries"); + return 0.0; + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 03350a6..f9422ed 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -7,8 +7,9 @@ server.port=8080 server.jetty.connection-idle-timeout=1000s # Available levels are: TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF logging.level.ru.ulstu=DEBUG -logging.level.sun.rmi.transport.tcp=off +logging.level.sun.rmi.transport=off logging.level.javax.management.remote.rmi=off +logging.level.java.rmi.server=off extractor.custom-projects-dir= # Thymeleaf Settings spring.thymeleaf.cache=false diff --git a/src/main/resources/db/changelog-20221012_170000-schema.xml b/src/main/resources/db/changelog-20221012_170000-schema.xml index 765df26..3e4dc33 100644 --- a/src/main/resources/db/changelog-20221012_170000-schema.xml +++ b/src/main/resources/db/changelog-20221012_170000-schema.xml @@ -80,4 +80,23 @@ + + + + + + + + + delete + from time_series_value + where time_series_id in (select id from time_series where time_series_type is null OR branch_id is null); + delete + from time_series + where time_series_type is null + OR branch_id is null; + + \ No newline at end of file