Compare commits

...

39 Commits

Author SHA1 Message Date
9e43175704 #80 -- Add validation 2023-03-15 14:18:23 +04:00
7ad962494a #92 -- Restore 2023-02-22 15:59:32 +04:00
ba747cfed3 Merge remote-tracking branch 'origin/master' into master 2023-02-22 15:49:18 +04:00
9972f5e925 #92 -- Add api call 2023-02-22 15:49:10 +04:00
9d5672cdcf #91 -- Add markup page 2023-02-21 18:22:41 +04:00
d72cf99fa6 #92 -- Fix saving in transaction 2023-02-21 17:46:55 +04:00
bc58d72481 #92 -- Fix .git removing for git 2023-02-21 14:43:27 +04:00
513c2cb7ba Merge pull request '#92 -- gitlab repository id' (#93) from 92-id-gitlab into master
Reviewed-on: #93
2023-02-20 14:25:20 +04:00
1e69baea80 #92 -- Fix scheduled time 2023-02-20 14:22:38 +04:00
de6c83c239 #92 -- Move id repository to model 2023-02-20 14:18:37 +04:00
220854401e #92 -- Fix .git removing 2023-02-20 11:08:49 +04:00
a3a032b70b Merge pull request '89-time-series-by-cron' (#90) from 89-time-series-by-cron into master
Reviewed-on: #90
2023-02-20 10:16:32 +04:00
a5c9d15d4f #89 -- Fix logs 2023-02-20 10:10:41 +04:00
78016741cf #89 -- Fix scheduled time series 2023-02-19 23:59:30 +04:00
3de664abb1 #89 -- Divide git api services 2023-02-16 00:39:13 +04:00
aeab50cfb8 #89 -- Create a valid class hierarchy 2023-02-15 18:28:39 +04:00
0d43bf8ccd #89 -- Use git service api to create time series 2023-02-15 00:55:06 +04:00
b8c6aaf9da Merge pull request 'async indexing' (#88) from 81-async-indexing into master
Reviewed-on: #88
2023-02-13 17:56:22 +04:00
616eaaa23a #81 -- Add async tasks 2023-02-13 17:54:49 +04:00
425ff70683 #81 -- Add new time series type 2023-02-13 12:03:13 +04:00
11b42d7e09 #81 -- Start indexing on failed tasks 2023-02-07 23:29:13 +04:00
98ec821748 #81 -- Show indexing status 2023-02-07 22:44:04 +04:00
f9fd839a14 #81 -- Add branch indexing status 2023-02-07 22:30:47 +04:00
5f9b91fd87 Merge pull request 'Декомпозиция' (#87) from 86-bl-decomposition into master
Reviewed-on: #87
2023-02-07 16:40:38 +04:00
4143fcfb20 #86 -- fix fuzzy inference 2023-02-07 16:36:32 +04:00
4216356c35 #86 -- divide bl 2023-02-06 13:54:12 +04:00
09ce44c33e Merge pull request 'list of assessments' (#85) from 84-list-of-consequents into master
Reviewed-on: #85
2023-02-02 13:05:27 +04:00
e4d32a3e92 #84 -- multiple assessments 2023-02-02 13:02:13 +04:00
36e2b09568 #84 -- fix integer cast 2023-02-02 01:01:03 +04:00
6bb39cc4d6 #84 -- fix output 2023-02-02 00:50:57 +04:00
14c17284bd #84 -- rename package 2023-02-01 22:51:12 +04:00
13ff304369 #84 -- change page content 2023-02-01 22:50:04 +04:00
f76976899d #84 -- change page route and semantic 2023-02-01 22:39:40 +04:00
9aa05b83e2 #80 -- fix forecasting 2023-02-01 14:36:07 +04:00
4d7f0f38b8 #80 -- fix forecasting 2023-02-01 01:40:34 +04:00
237a4f9980 fix time series name 2023-02-01 00:16:36 +04:00
412d22fafd #80 -- fix consequents 2023-02-01 00:15:59 +04:00
1cd53459ed #80 -- sout rules 2023-01-31 23:47:30 +04:00
9423af3863 #80 -- partially fix inference 2023-01-31 17:33:05 +04:00
67 changed files with 1310 additions and 697 deletions

View File

@ -2,12 +2,29 @@ package ru.ulstu.extractor;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
import ru.ulstu.extractor.gitrepository.service.IndexService;
@SpringBootApplication @SpringBootApplication
@EnableScheduling @EnableScheduling
@EnableAsync
public class GitExtractorApplication { public class GitExtractorApplication {
private final IndexService indexService;
public GitExtractorApplication(IndexService indexService) {
this.indexService = indexService;
}
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(GitExtractorApplication.class, args); SpringApplication.run(GitExtractorApplication.class, args);
} }
@EventListener(ApplicationReadyEvent.class)
public void doSomethingAfterStartup() {
indexService.indexFailedBranchesOnStart();
}
} }

View File

@ -0,0 +1,39 @@
package ru.ulstu.extractor.assessment.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import ru.ulstu.extractor.assessment.model.FilterBranchForm;
import ru.ulstu.extractor.assessment.service.AssessmentService;
import ru.ulstu.extractor.branch.service.BranchService;
import springfox.documentation.annotations.ApiIgnore;
import java.util.Optional;
import static ru.ulstu.extractor.core.Route.ASSESSMENTS;
@Controller
@ApiIgnore
public class AssessmentController {
private final AssessmentService assessmentService;
private final BranchService branchService;
public AssessmentController(AssessmentService assessmentService,
BranchService branchService) {
this.assessmentService = assessmentService;
this.branchService = branchService;
}
@GetMapping(ASSESSMENTS)
public String getAssessments(Model model, @RequestParam Optional<Integer> branchId) {
model.addAttribute("branches", branchService.findAllValid());
if (branchId.isPresent()) {
model.addAttribute("assessments", assessmentService.getAssessmentsByForecastTendencies(branchId.get()));
model.addAttribute("filterBranchForm", new FilterBranchForm(branchId.get()));
} else {
model.addAttribute("filterBranchForm", new FilterBranchForm());
}
return ASSESSMENTS;
}
}

View File

@ -0,0 +1,46 @@
package ru.ulstu.extractor.assessment.model;
import ru.ulstu.extractor.rule.model.DbRule;
import ru.ulstu.extractor.ts.model.TimeSeriesType;
public class Assessment {
private final String consequent;
private final TimeSeriesType firstAntecedent;
private final String firstAntecedentTendency;
private final TimeSeriesType secondAntecedent;
private final String secondAntecedentTendency;
private final Double degree;
public Assessment(DbRule dbRule, Double degree) {
this.consequent = dbRule.getConsequent();
this.firstAntecedent = dbRule.getFirstAntecedent();
this.firstAntecedentTendency = dbRule.getFirstAntecedentValue().getAntecedentValue();
this.secondAntecedent = dbRule.getSecondAntecedent();
this.secondAntecedentTendency = dbRule.getSecondAntecedentValue().getAntecedentValue();
this.degree = degree;
}
public String getConsequent() {
return consequent;
}
public TimeSeriesType getFirstAntecedent() {
return firstAntecedent;
}
public String getFirstAntecedentTendency() {
return firstAntecedentTendency;
}
public TimeSeriesType getSecondAntecedent() {
return secondAntecedent;
}
public String getSecondAntecedentTendency() {
return secondAntecedentTendency;
}
public Double getDegree() {
return degree;
}
}

View File

@ -1,4 +1,4 @@
package ru.ulstu.extractor.recommendation.model; package ru.ulstu.extractor.assessment.model;
public class FilterBranchForm { public class FilterBranchForm {
private Integer branchId; private Integer branchId;

View File

@ -0,0 +1,131 @@
package ru.ulstu.extractor.assessment.service;
import org.springframework.stereotype.Service;
import ru.ulstu.extractor.assessment.model.Assessment;
import ru.ulstu.extractor.rule.model.AssessmentException;
import ru.ulstu.extractor.rule.model.DbRule;
import ru.ulstu.extractor.rule.service.AntecedentValueService;
import ru.ulstu.extractor.rule.service.DbRuleService;
import ru.ulstu.extractor.rule.service.FuzzyInferenceService;
import ru.ulstu.extractor.ts.model.TimeSeries;
import ru.ulstu.extractor.ts.model.TimeSeriesValue;
import ru.ulstu.extractor.ts.service.TimeSeriesService;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class AssessmentService {
private final DbRuleService ruleService;
private final AntecedentValueService antecedentValueService;
private final TimeSeriesService timeSeriesService;
private final FuzzyInferenceService fuzzyInferenceService;
public AssessmentService(DbRuleService ruleService,
AntecedentValueService antecedentValueService,
TimeSeriesService timeSeriesService,
FuzzyInferenceService fuzzyInferenceService) {
this.ruleService = ruleService;
this.antecedentValueService = antecedentValueService;
this.timeSeriesService = timeSeriesService;
this.fuzzyInferenceService = fuzzyInferenceService;
}
public List<Assessment> getAssessmentsByForecastTendencies(Integer branchId) {
List<TimeSeries> timeSeries = timeSeriesService.getByBranch(branchId);
List<DbRule> dbRules = ruleService.getList();
try {
return getAssessmentsByTimeSeriesTendencies(dbRules, timeSeries);
} catch (AssessmentException ex) {
ex.printStackTrace();
return new ArrayList<>();
}
}
public List<Assessment> getAssessmentsByLastValues(Integer branchId) {
List<TimeSeries> timeSeries = timeSeriesService.getByBranch(branchId);
List<DbRule> dbRules = ruleService.getList();
return getAssessmentsByLastValues(dbRules, timeSeries);
}
private List<Assessment> getSingleAssessmentByTimeSeriesTendencies(List<DbRule> dbRules, List<TimeSeries> timeSeries) throws AssessmentException {
Map<String, Double> variableValues = new HashMap<>();
timeSeries.forEach(ts -> variableValues.put(ts.getTimeSeriesType().name(), timeSeriesService.getLastTimeSeriesTendency(ts)));
return fuzzyInferenceService.getFuzzyInference(dbRules,
antecedentValueService.getList(),
variableValues,
getTSsMin(timeSeries),
getTSsMax(timeSeries));
}
private List<Assessment> getAssessmentsByTimeSeriesTendencies(List<DbRule> dbRules, List<TimeSeries> timeSeries) {
return dbRules
.stream()
.flatMap(dbRule -> {
Map<String, Double> variableValues = new HashMap<>();
timeSeries
.stream()
.filter(ts -> ts.getTimeSeriesType() == dbRule.getFirstAntecedent()
|| ts.getTimeSeriesType() == dbRule.getSecondAntecedent())
.forEach(ts -> variableValues.put(ts.getTimeSeriesType().name(), timeSeriesService
.getLastTimeSeriesTendency(ts)));
return fuzzyInferenceService.getFuzzyInference(List.of(dbRule),
antecedentValueService.getList(),
variableValues,
getTSsMin(timeSeries),
getTSsMax(timeSeries)).stream();
})
.sorted(Comparator.comparing(Assessment::getDegree))
.collect(Collectors.toList());
}
private List<Assessment> getAssessmentsByLastValues(List<DbRule> dbRules, List<TimeSeries> timeSeries) {
Map<String, Double> variableValues = new HashMap<>();
timeSeries.forEach(ts -> variableValues.put(ts.getTimeSeriesType().name(), ts.getValues().get(ts.getValues().size() - 1).getValue()));
return fuzzyInferenceService.getFuzzyInference(dbRules,
antecedentValueService.getList(),
variableValues,
getTSsMin(timeSeries),
getTSsMax(timeSeries));
}
private Double getMin(List<Double> values) {
return values.stream().mapToDouble(v -> v).min().getAsDouble();
}
private Map.Entry<String, Double> getTSMin(TimeSeries ts) {
return Map.entry(ts.getTimeSeriesType().name(),
getMin(ts.getValues().stream().map(TimeSeriesValue::getValue).collect(Collectors.toList())));
}
private Map<String, Double> getTSsMin(List<TimeSeries> tss) {
Map<String, Double> res = new HashMap<>();
tss.forEach(ts -> {
Map.Entry<String, Double> entry = getTSMin(ts);
res.put(entry.getKey(), entry.getValue());
});
return res;
}
private Double getMax(List<Double> values) {
return values.stream().mapToDouble(v -> v).max().getAsDouble();
}
private Map.Entry<String, Double> getTSMax(TimeSeries ts) {
return Map.entry(ts.getTimeSeriesType().name(),
getMax(ts.getValues().stream().map(TimeSeriesValue::getValue).collect(Collectors.toList())));
}
private Map<String, Double> getTSsMax(List<TimeSeries> tss) {
Map<String, Double> res = new HashMap<>();
tss.forEach(ts -> {
Map.Entry<String, Double> entry = getTSMax(ts);
res.put(entry.getKey(), entry.getValue());
});
return res;
}
}

View File

@ -7,12 +7,14 @@ package ru.ulstu.extractor.branch.model;
import org.hibernate.annotations.Fetch; import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.FetchMode;
import ru.ulstu.extractor.commit.model.Commit;
import ru.ulstu.extractor.core.BaseEntity; import ru.ulstu.extractor.core.BaseEntity;
import ru.ulstu.extractor.gitrepository.model.GitRepository; import ru.ulstu.extractor.gitrepository.model.GitRepository;
import ru.ulstu.extractor.model.Commit;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
@ -20,6 +22,8 @@ import javax.persistence.OneToMany;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static ru.ulstu.extractor.branch.model.IndexingStatus.EMPTY;
@Entity @Entity
public class Branch extends BaseEntity { public class Branch extends BaseEntity {
private String name; private String name;
@ -32,6 +36,9 @@ public class Branch extends BaseEntity {
@Fetch(FetchMode.SUBSELECT) @Fetch(FetchMode.SUBSELECT)
private List<Commit> commits = new ArrayList<>(); private List<Commit> commits = new ArrayList<>();
@Enumerated(EnumType.STRING)
private IndexingStatus indexingStatus = EMPTY;
public Branch() { public Branch() {
} }
@ -67,4 +74,12 @@ public class Branch extends BaseEntity {
public void setCommits(List<Commit> commits) { public void setCommits(List<Commit> commits) {
this.commits = commits; this.commits = commits;
} }
public IndexingStatus getIndexingStatus() {
return indexingStatus;
}
public void setIndexingStatus(IndexingStatus indexingStatus) {
this.indexingStatus = indexingStatus;
}
} }

View File

@ -0,0 +1,5 @@
package ru.ulstu.extractor.branch.model;
public enum IndexingStatus {
EMPTY, INDEXING, ERROR, FINISHED
}

View File

@ -5,17 +5,23 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import ru.ulstu.extractor.branch.model.Branch; import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.branch.model.IndexingStatus;
import ru.ulstu.extractor.gitrepository.model.GitRepository; import ru.ulstu.extractor.gitrepository.model.GitRepository;
import java.util.List; import java.util.List;
import java.util.Optional;
public interface BranchRepository extends JpaRepository<Branch, Integer> { public interface BranchRepository extends JpaRepository<Branch, Integer> {
Branch findByGitRepositoryAndName(GitRepository gitRepository, String name); Branch findByGitRepositoryAndName(GitRepository gitRepository, String name);
Optional<Branch> findByGitRepository_UrlAndName(String repositoryUrl, String name);
@Query("select count(c) from Commit c LEFT JOIN c.branch b LEFT JOIN GitRepository r where r.id = ?1 AND b.name = ?2") @Query("select count(c) from Commit c LEFT JOIN c.branch b LEFT JOIN GitRepository r where r.id = ?1 AND b.name = ?2")
int getCommitsCount(Integer repositoryId, String name); int getCommitsCount(Integer repositoryId, String name);
List<Branch> findByGitRepositoryId(Integer repositoryId); List<Branch> findByGitRepositoryId(Integer repositoryId);
Page<Branch> findByGitRepository(GitRepository gitRepository, Pageable pageable); Page<Branch> findByGitRepository(GitRepository gitRepository, Pageable pageable);
List<Branch> findAllByIndexingStatus(IndexingStatus indexingStatus);
} }

View File

@ -10,13 +10,16 @@ import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import ru.ulstu.extractor.branch.model.Branch; import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.branch.model.IndexingStatus;
import ru.ulstu.extractor.branch.repository.BranchRepository; import ru.ulstu.extractor.branch.repository.BranchRepository;
import ru.ulstu.extractor.commit.model.Commit;
import ru.ulstu.extractor.commit.service.CommitService; import ru.ulstu.extractor.commit.service.CommitService;
import ru.ulstu.extractor.core.BaseEntity; import ru.ulstu.extractor.core.BaseEntity;
import ru.ulstu.extractor.gitrepository.model.GitRepository; import ru.ulstu.extractor.gitrepository.model.GitRepository;
import ru.ulstu.extractor.model.Commit; import ru.ulstu.extractor.ts.service.TimeSeriesService;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
@ -24,16 +27,25 @@ public class BranchService {
private final static Logger LOG = LoggerFactory.getLogger(BranchService.class); private final static Logger LOG = LoggerFactory.getLogger(BranchService.class);
private final BranchRepository branchRepository; private final BranchRepository branchRepository;
private final CommitService commitService; private final CommitService commitService;
private final TimeSeriesService timeSeriesService;
public BranchService(BranchRepository branchRepository, public BranchService(BranchRepository branchRepository,
CommitService commitService) { CommitService commitService,
TimeSeriesService timeSeriesService) {
this.branchRepository = branchRepository; this.branchRepository = branchRepository;
this.commitService = commitService; this.commitService = commitService;
this.timeSeriesService = timeSeriesService;
}
@Transactional
public Branch save(Branch branch) {
return branchRepository.save(branch);
} }
@Transactional @Transactional
public Branch save(Branch branch, List<Commit> commits) { public Branch save(Branch branch, List<Commit> commits) {
LOG.debug("Start save {} branch with {} commits ", branch.getName(), commits.size()); LOG.debug("Start save {} branch with {} commits ", branch.getName(), commits.size());
LOG.debug("Current branch contains {} commits ", branch.getCommits().size());
List<Integer> commitsToRemoveIds = branch.getCommits().stream().map(BaseEntity::getId).collect(Collectors.toList()); List<Integer> commitsToRemoveIds = branch.getCommits().stream().map(BaseEntity::getId).collect(Collectors.toList());
branch.setCommits(commitService.save(commits)); branch.setCommits(commitService.save(commits));
LOG.debug("Save branch {} ", branch.getName()); LOG.debug("Save branch {} ", branch.getName());
@ -43,19 +55,47 @@ public class BranchService {
return branch; return branch;
} }
@Transactional
public Branch addCommits(Branch branch, List<Commit> commits) { public Branch addCommits(Branch branch, List<Commit> commits) {
LOG.debug("Start add commits to {} branch with {} commits ", branch.getName(), commits.size()); LOG.debug("Start add commits to {} branch with {} commits ", branch.getName(), commits.size());
commitService.save(commits); branch.getCommits().addAll(commitService.save(commits));
LOG.debug("Save branch {} ", branch.getName()); LOG.debug("Save branch {} ", branch.getName());
commitService.updateBranchId(commits, branch.getId()); return save(branch);
return branch;
} }
public Branch findByRepositoryAndName(GitRepository gitRepository, String branchName) { public Branch findByRepositoryAndName(GitRepository gitRepository, String branchName) {
return branchRepository.findByGitRepositoryAndName(gitRepository, branchName); return branchRepository.findByGitRepositoryAndName(gitRepository, branchName);
} }
public Branch findByRepositoryAndNameOrCreate(GitRepository gitRepository, String branchName) {
Branch branch = branchRepository.findByGitRepositoryAndName(gitRepository, branchName);
return branch == null
? branchRepository.save(new Branch(gitRepository, branchName))
: branch;
}
public Optional<Branch> findByBranchId(Integer branchId) {
return branchRepository.findById(branchId);
}
public List<Branch> findAll() { public List<Branch> findAll() {
return branchRepository.findAll(); return branchRepository.findAll();
} }
public List<Branch> findAllByIndexingStatus(IndexingStatus indexingStatus) {
return branchRepository.findAllByIndexingStatus(indexingStatus);
}
@Transactional
public Branch updateStatus(Branch branch, IndexingStatus indexingStatus) {
branch.setIndexingStatus(indexingStatus);
return branchRepository.save(branch);
}
public List<Branch> findAllValid() {
return findAll()
.stream()
.filter(timeSeriesService::isBranchContainsAllTimeSeries)
.collect(Collectors.toList());
}
} }

View File

@ -3,7 +3,7 @@
* You may use, distribute and modify this code, please write to: romanov73@gmail.com. * You may use, distribute and modify this code, please write to: romanov73@gmail.com.
*/ */
package ru.ulstu.extractor.model; package ru.ulstu.extractor.commit.model;
import org.hibernate.annotations.Fetch; import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.FetchMode;

View File

@ -10,12 +10,12 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
import ru.ulstu.extractor.commit.model.Commit;
import ru.ulstu.extractor.commit.model.CommitAuthorStatistic; import ru.ulstu.extractor.commit.model.CommitAuthorStatistic;
import ru.ulstu.extractor.commit.model.CommitEntityStatistic; import ru.ulstu.extractor.commit.model.CommitEntityStatistic;
import ru.ulstu.extractor.commit.model.CommitTimeStatistic; import ru.ulstu.extractor.commit.model.CommitTimeStatistic;
import ru.ulstu.extractor.commit.model.CommitUrlStatistic; import ru.ulstu.extractor.commit.model.CommitUrlStatistic;
import ru.ulstu.extractor.gitrepository.model.GitRepository; import ru.ulstu.extractor.gitrepository.model.GitRepository;
import ru.ulstu.extractor.model.Commit;
import java.util.List; import java.util.List;

View File

@ -8,8 +8,8 @@ package ru.ulstu.extractor.commit.service;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.ulstu.extractor.author.service.AuthorService; import ru.ulstu.extractor.author.service.AuthorService;
import ru.ulstu.extractor.commit.model.Commit;
import ru.ulstu.extractor.commit.repository.CommitRepository; import ru.ulstu.extractor.commit.repository.CommitRepository;
import ru.ulstu.extractor.model.Commit;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -44,14 +44,6 @@ public class CommitService {
jdbcTemplate.update("DELETE FROM commit where branch_id is null"); jdbcTemplate.update("DELETE FROM commit where branch_id is null");
} }
public void updateBranchId(List<Commit> commits, Integer branchId) {
List<String> commitIds = commits.stream().map(c -> c.getId().toString()).collect(Collectors.toList());
String updateQuery = "update commit set branch_id = ? where id in (%s)";
updateQuery = String.format(updateQuery, String.join(",", commitIds));
jdbcTemplate.update(updateQuery, branchId);
}
public List<Commit> findByRepositoryIdAndName(Integer repositoryId, String branchName) { public List<Commit> findByRepositoryIdAndName(Integer repositoryId, String branchName) {
return commitRepository.findByRepositoryIdAndBranchName(repositoryId, branchName); return commitRepository.findByRepositoryIdAndBranchName(repositoryId, branchName);
} }

View File

@ -8,7 +8,7 @@ import javax.persistence.Version;
import java.io.Serializable; import java.io.Serializable;
@MappedSuperclass @MappedSuperclass
public abstract class BaseEntity implements Serializable, Comparable { public abstract class BaseEntity implements Serializable, Comparable<BaseEntity> {
@Id @Id
@GeneratedValue(strategy = GenerationType.TABLE) @GeneratedValue(strategy = GenerationType.TABLE)
private Integer id; private Integer id;
@ -49,10 +49,10 @@ public abstract class BaseEntity implements Serializable, Comparable {
} }
BaseEntity other = (BaseEntity) obj; BaseEntity other = (BaseEntity) obj;
if (id == null) { if (id == null) {
if (other.id != null) { if (other.getId() != null) {
return false; return false;
} }
} else if (!id.equals(other.id)) { } else if (!id.equals(other.getId())) {
return false; return false;
} }
return true; return true;
@ -75,8 +75,8 @@ public abstract class BaseEntity implements Serializable, Comparable {
} }
@Override @Override
public int compareTo(Object o) { public int compareTo(BaseEntity o) {
return id != null ? id.compareTo(((BaseEntity) o).getId()) : -1; return id != null ? id.compareTo(o.getId()) : -1;
} }
public void reset() { public void reset() {

View File

@ -13,12 +13,13 @@ public class Route {
public static final String DELETE_INDEXED_REPOSITORY = "deleteRepository"; public static final String DELETE_INDEXED_REPOSITORY = "deleteRepository";
public static final String LIST_REPOSITORY_BRANCHES = "listBranches"; public static final String LIST_REPOSITORY_BRANCHES = "listBranches";
public static final String DELETE_BRANCH = "deleteBranch"; public static final String DELETE_BRANCH = "deleteBranch";
public static final String REINDEX_BRANCH = "reindexBranch";
public static final String INDEXING_NEW_REPOSITORY = "indexNewRepository"; public static final String INDEXING_NEW_REPOSITORY = "indexNewRepository";
public static final String FILTER_COMMITS = "filterCommits"; public static final String FILTER_COMMITS = "filterCommits";
public static final String STATISTIC = "statistic"; public static final String STATISTIC = "statistic";
public static final String LIST_RULE = "listRules"; public static final String LIST_RULE = "listRules";
public static final String ADD_RULE = "addRule"; public static final String ADD_RULE = "addRule";
public static final String RECOMMENDATIONS = "recommendations"; public static final String ASSESSMENTS = "assessments";
public static final String DELETE_RULE = "deleteRule"; public static final String DELETE_RULE = "deleteRule";
public static String getLIST_INDEXED_REPOSITORIES() { public static String getLIST_INDEXED_REPOSITORIES() {
@ -41,7 +42,7 @@ public class Route {
return STATISTIC; return STATISTIC;
} }
public static String getRECOMMENDATIONS() { public static String getASSESSMENTS() {
return RECOMMENDATIONS; return ASSESSMENTS;
} }
} }

View File

@ -11,10 +11,10 @@ import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import ru.ulstu.extractor.commit.model.Commit;
import ru.ulstu.extractor.core.OffsetablePageRequest; import ru.ulstu.extractor.core.OffsetablePageRequest;
import ru.ulstu.extractor.gitrepository.model.FilterForm; import ru.ulstu.extractor.gitrepository.model.FilterForm;
import ru.ulstu.extractor.gitrepository.service.FilteringService; import ru.ulstu.extractor.gitrepository.service.FilteringService;
import ru.ulstu.extractor.model.Commit;
import springfox.documentation.annotations.ApiIgnore; import springfox.documentation.annotations.ApiIgnore;
import java.util.List; import java.util.List;

View File

@ -14,9 +14,13 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import ru.ulstu.extractor.branch.model.Branch; import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.branch.model.IndexingStatus;
import ru.ulstu.extractor.branch.service.BranchService;
import ru.ulstu.extractor.gitrepository.model.FilterForm; import ru.ulstu.extractor.gitrepository.model.FilterForm;
import ru.ulstu.extractor.gitrepository.model.GitRepository;
import ru.ulstu.extractor.gitrepository.model.RepoForm; import ru.ulstu.extractor.gitrepository.model.RepoForm;
import ru.ulstu.extractor.gitrepository.service.GitRepositoryService; import ru.ulstu.extractor.gitrepository.service.GitRepositoryService;
import ru.ulstu.extractor.gitrepository.service.IndexService; import ru.ulstu.extractor.gitrepository.service.IndexService;
@ -25,8 +29,9 @@ import springfox.documentation.annotations.ApiIgnore;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import static ru.ulstu.extractor.core.Route.FILTER_COMMITS;
import static ru.ulstu.extractor.core.Route.INDEXING_NEW_REPOSITORY; import static ru.ulstu.extractor.core.Route.INDEXING_NEW_REPOSITORY;
import static ru.ulstu.extractor.core.Route.LIST_REPOSITORY_BRANCHES;
import static ru.ulstu.extractor.core.Route.REINDEX_BRANCH;
@Controller @Controller
@ApiIgnore @ApiIgnore
@ -34,11 +39,14 @@ public class GitIndexingController {
private final static Logger LOG = LoggerFactory.getLogger(GitIndexingController.class); private final static Logger LOG = LoggerFactory.getLogger(GitIndexingController.class);
private final GitRepositoryService gitRepositoryService; private final GitRepositoryService gitRepositoryService;
private final IndexService indexService; private final IndexService indexService;
private final BranchService branchService;
public GitIndexingController(GitRepositoryService gitRepositoryService, public GitIndexingController(GitRepositoryService gitRepositoryService,
IndexService indexService) { IndexService indexService,
BranchService branchService) {
this.gitRepositoryService = gitRepositoryService; this.gitRepositoryService = gitRepositoryService;
this.indexService = indexService; this.indexService = indexService;
this.branchService = branchService;
} }
@GetMapping(INDEXING_NEW_REPOSITORY) @GetMapping(INDEXING_NEW_REPOSITORY)
@ -64,16 +72,36 @@ public class GitIndexingController {
if (repoForm.getBranch() == null) { if (repoForm.getBranch() == null) {
return INDEXING_NEW_REPOSITORY; return INDEXING_NEW_REPOSITORY;
} else { } else {
GitRepository gitRepository = gitRepositoryService.findByUrlOrCreate(repoForm.getRepo());
Branch branch = branchService.findByRepositoryAndNameOrCreate(gitRepository, repoForm.getBranch());
branch = branchService.updateStatus(branch, IndexingStatus.INDEXING);
try { try {
indexService.index(repoForm.getRepo(), repoForm.getBranch()); indexService.index(gitRepository, branch);
} catch (IOException | GitAPIException ex) { } catch (IOException | GitAPIException ex) {
ex.printStackTrace(); ex.printStackTrace();
model.addAttribute("error", ex.getMessage()); model.addAttribute("error", ex.getMessage());
return INDEXING_NEW_REPOSITORY; return INDEXING_NEW_REPOSITORY;
} }
redirectAttributes.addAttribute("repositoryUrl", repoForm.getRepo()); redirectAttributes.addAttribute("repositoryId", branch.getGitRepository().getId());
redirectAttributes.addAttribute("branchName", repoForm.getBranch()); return "redirect:/" + LIST_REPOSITORY_BRANCHES;
return "redirect:/" + FILTER_COMMITS;
} }
} }
@GetMapping(REINDEX_BRANCH)
public String reindexBranch(Model model,
RedirectAttributes redirectAttributes,
@RequestParam Integer branchId) {
Branch branch = branchService.findByBranchId(branchId).orElseThrow(() -> new RuntimeException("Ветка не найдена по id"));
branch = branchService.updateStatus(branch, IndexingStatus.INDEXING);
try {
indexService.index(branchId);
} catch (IOException | GitAPIException ex) {
ex.printStackTrace();
model.addAttribute("error", ex.getMessage());
return INDEXING_NEW_REPOSITORY;
}
redirectAttributes.addAttribute("repositoryId", branch.getGitRepository().getId());
return "redirect:/" + LIST_REPOSITORY_BRANCHES;
}
} }

View File

@ -12,9 +12,9 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import ru.ulstu.extractor.commit.model.Commit;
import ru.ulstu.extractor.gitrepository.service.GitRepositoryService; import ru.ulstu.extractor.gitrepository.service.GitRepositoryService;
import ru.ulstu.extractor.gitrepository.service.IndexService; import ru.ulstu.extractor.gitrepository.service.IndexService;
import ru.ulstu.extractor.model.Commit;
import ru.ulstu.extractor.util.HttpUtils; import ru.ulstu.extractor.util.HttpUtils;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;

View File

@ -6,7 +6,7 @@
package ru.ulstu.extractor.gitrepository.model; package ru.ulstu.extractor.gitrepository.model;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import ru.ulstu.extractor.model.Commit; import ru.ulstu.extractor.commit.model.Commit;
public class FilterForm { public class FilterForm {
private String filter; private String filter;

View File

@ -1,18 +1,21 @@
package ru.ulstu.extractor.gitrepository.model; package ru.ulstu.extractor.gitrepository.model;
import ru.ulstu.extractor.core.BaseEntity; import ru.ulstu.extractor.core.BaseEntity;
import ru.ulstu.extractor.util.StringUtils;
import javax.persistence.Entity; import javax.persistence.Entity;
@Entity @Entity
public class GitRepository extends BaseEntity { public class GitRepository extends BaseEntity {
private String url; private String url;
private String repositoryId;
public GitRepository() { public GitRepository() {
} }
public GitRepository(String repositoryUrl) { public GitRepository(String repositoryUrl, String repositoryId) {
url = repositoryUrl; this.url = repositoryUrl;
this.repositoryId = repositoryId;
} }
public String getUrl() { public String getUrl() {
@ -23,10 +26,14 @@ public class GitRepository extends BaseEntity {
this.url = url; this.url = url;
} }
public String getRepositoryId() {
return repositoryId;
}
public String getName() { public String getName() {
int lastDelimiterIndex = url.lastIndexOf("/"); int lastDelimiterIndex = url.lastIndexOf("/");
return (lastDelimiterIndex > 0 && lastDelimiterIndex < url.length()) return StringUtils.removeDotGit((lastDelimiterIndex > 0 && lastDelimiterIndex < url.length())
? url.substring(lastDelimiterIndex + 1) ? url.substring(lastDelimiterIndex + 1)
: url; : url);
} }
} }

View File

@ -10,9 +10,9 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.ulstu.extractor.author.repository.AuthorRepository; import ru.ulstu.extractor.author.repository.AuthorRepository;
import ru.ulstu.extractor.commit.model.Commit;
import ru.ulstu.extractor.commit.repository.CommitRepository; import ru.ulstu.extractor.commit.repository.CommitRepository;
import ru.ulstu.extractor.gitrepository.repository.GitRepositoryRepository; import ru.ulstu.extractor.gitrepository.repository.GitRepositoryRepository;
import ru.ulstu.extractor.model.Commit;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;

View File

@ -0,0 +1,17 @@
package ru.ulstu.extractor.gitrepository.service;
import ru.ulstu.extractor.branch.model.Branch;
public interface GitApi {
Integer getBranchesCount(Branch branch);
Integer getStarsCount(Branch branch);
Integer getOpenIssuesCount(Branch branch);
String getFormattedUrl(Branch branch, String template);
Integer getAuthorsCompletedIssues(Branch branch);
String getRepositoryId(String repositoryUrl);
}

View File

@ -0,0 +1,58 @@
package ru.ulstu.extractor.gitrepository.service;
import org.springframework.stereotype.Service;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.http.HttpService;
@Service
public class GitAtheneApi implements GitApi {
private final HttpService httpService;
private static final String BRANCHES_COUNT_URL = "%s/api/v1/repos/%s/%s/branches";
private static final String STARS_COUNT_URL = "%s/api/v1/repos/%s/%s";
private static final String OPEN_ISSUES_URL = "%s/api/v1/repos/%s/%s/issues?state=open";
private static final String COMPLETED_ISSUES_URL = "%s/api/v1/repos/%s/%s/issues?state=closed";
public GitAtheneApi(HttpService httpService) {
this.httpService = httpService;
}
@Override
public Integer getBranchesCount(Branch branch) {
return httpService
.get(getFormattedUrl(branch, BRANCHES_COUNT_URL))
.length();
}
@Override
public Integer getStarsCount(Branch branch) {
return httpService
.get(getFormattedUrl(branch, STARS_COUNT_URL))
.getJSONObject(0)
.getInt("stars_count");
}
@Override
public Integer getOpenIssuesCount(Branch branch) {
return httpService
.get(getFormattedUrl(branch, OPEN_ISSUES_URL))
.length();
}
@Override
public String getFormattedUrl(Branch branch, String template) {
String[] urlParts = branch.getGitRepository().getUrl().split("/");
return String.format(template, urlParts[0] + "/" + urlParts[1] + "/" + urlParts[2], urlParts[3], urlParts[4]);
}
@Override
public Integer getAuthorsCompletedIssues(Branch branch) {
return httpService
.get(getFormattedUrl(branch, COMPLETED_ISSUES_URL))
.length();
}
@Override
public String getRepositoryId(String repositoryUrl) {
return null;
}
}

View File

@ -15,11 +15,13 @@ import org.eclipse.jgit.treewalk.TreeWalk;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.ulstu.extractor.author.model.Author; import ru.ulstu.extractor.author.model.Author;
import ru.ulstu.extractor.branch.model.Branch; import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.commit.model.Commit;
import ru.ulstu.extractor.gitrepository.model.FileChange; import ru.ulstu.extractor.gitrepository.model.FileChange;
import ru.ulstu.extractor.gitrepository.model.GitRepository; import ru.ulstu.extractor.gitrepository.model.GitRepository;
import ru.ulstu.extractor.gitrepository.model.LineChange; import ru.ulstu.extractor.gitrepository.model.LineChange;
@ -28,7 +30,7 @@ import ru.ulstu.extractor.heuristic.model.BusinessLogicUnit;
import ru.ulstu.extractor.heuristic.model.EntityUnit; import ru.ulstu.extractor.heuristic.model.EntityUnit;
import ru.ulstu.extractor.heuristic.model.ResourceUnit; import ru.ulstu.extractor.heuristic.model.ResourceUnit;
import ru.ulstu.extractor.heuristic.service.StructuralUnitService; import ru.ulstu.extractor.heuristic.service.StructuralUnitService;
import ru.ulstu.extractor.model.Commit; import ru.ulstu.extractor.util.StringUtils;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
@ -55,7 +57,11 @@ import static org.apache.logging.log4j.util.Strings.isBlank;
@Service @Service
public class GitRepositoryService { public class GitRepositoryService {
private final static Logger LOG = LoggerFactory.getLogger(GitRepositoryService.class); private final Map<String, Class<? extends GitApi>> gitApiServiceHolder = Map.of(
"git.athene.tech", GitAtheneApi.class,
"github.com", GithubApi.class,
"gitlab.com", GitlabApi.class);
private static final Logger LOG = LoggerFactory.getLogger(GitRepositoryService.class);
private static final String BRANCH_PREFIX = "refs/remotes/origin/"; private static final String BRANCH_PREFIX = "refs/remotes/origin/";
@Value("${extractor.custom-projects-dir}") @Value("${extractor.custom-projects-dir}")
private String customProjectsDir; private String customProjectsDir;
@ -63,11 +69,14 @@ public class GitRepositoryService {
private final ExecutorService executorServiceCommits = Executors.newFixedThreadPool(8); private final ExecutorService executorServiceCommits = Executors.newFixedThreadPool(8);
private final StructuralUnitService structuralUnitService; private final StructuralUnitService structuralUnitService;
private final GitRepositoryRepository gitRepositoryRepository; private final GitRepositoryRepository gitRepositoryRepository;
private final ApplicationContext applicationContext;
public GitRepositoryService(StructuralUnitService structuralUnitService, public GitRepositoryService(StructuralUnitService structuralUnitService,
GitRepositoryRepository gitRepositoryRepository) { GitRepositoryRepository gitRepositoryRepository,
ApplicationContext applicationContext) {
this.structuralUnitService = structuralUnitService; this.structuralUnitService = structuralUnitService;
this.gitRepositoryRepository = gitRepositoryRepository; this.gitRepositoryRepository = gitRepositoryRepository;
this.applicationContext = applicationContext;
} }
public List<Branch> getRemoteBranches(String url) throws GitAPIException, IOException { public List<Branch> getRemoteBranches(String url) throws GitAPIException, IOException {
@ -187,7 +196,6 @@ public class GitRepositoryService {
return structuralUnitService.getResource(getProjectDirectoryFile(repositoryUrl)); return structuralUnitService.getResource(getProjectDirectoryFile(repositoryUrl));
} }
public void remove(String repositoryUrl) throws IOException { public void remove(String repositoryUrl) throws IOException {
FileUtils.deleteDirectory(getProjectDirectoryFile(repositoryUrl)); FileUtils.deleteDirectory(getProjectDirectoryFile(repositoryUrl));
} }
@ -283,8 +291,7 @@ public class GitRepositoryService {
List<FileChange> changes = new ArrayList<>(); List<FileChange> changes = new ArrayList<>();
String[] strings = output.split("\n"); String[] strings = output.split("\n");
Map<String, List<String>> filesContent = getFilesContent(strings); Map<String, List<String>> filesContent = getFilesContent(strings);
System.out.println(filesContent); for (Map.Entry<String, List<String>> fileSterings : filesContent.entrySet()) {
for(Map.Entry<String, List<String>> fileSterings: filesContent.entrySet()) {
FileChange fileChange = new FileChange(); FileChange fileChange = new FileChange();
fileChange.setFile(fileSterings.getKey()); fileChange.setFile(fileSterings.getKey());
Future<Boolean> futureEntity = executorService.submit(() -> structuralUnitService.containsEntity(getContent(repository, commit, fileSterings.getKey()))); Future<Boolean> futureEntity = executorService.submit(() -> structuralUnitService.containsEntity(getContent(repository, commit, fileSterings.getKey())));
@ -328,7 +335,7 @@ public class GitRepositoryService {
private Map<String, List<String>> getFilesContent(String[] commitStrings) { private Map<String, List<String>> getFilesContent(String[] commitStrings) {
int i = 0; int i = 0;
Map<String, List<String>> result = new HashMap<>(); Map<String, List<String>> result = new HashMap<>();
while (i < commitStrings.length) { while (i < commitStrings.length) {
Optional<String> maybeFileName = getFileName(commitStrings[i]); Optional<String> maybeFileName = getFileName(commitStrings[i]);
if (maybeFileName.isEmpty()) { if (maybeFileName.isEmpty()) {
@ -369,15 +376,15 @@ public class GitRepositoryService {
return index; return index;
} }
private FileChange getChange(FileChange fileChange, List<String> fileContent){ private FileChange getChange(FileChange fileChange, List<String> fileContent) {
int addedLine = 0; int addedLine = 0;
int removedLine = 0; int removedLine = 0;
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
boolean isRemoved = false; boolean isRemoved = false;
boolean isAdded = false; boolean isAdded = false;
for (String line : fileContent){ for (String line : fileContent) {
LineChange lineChange = new LineChange(); LineChange lineChange = new LineChange();
if (line.startsWith("-")){ if (line.startsWith("-")) {
isRemoved = true; isRemoved = true;
if (isAdded) { if (isAdded) {
isAdded = false; isAdded = false;
@ -386,7 +393,7 @@ public class GitRepositoryService {
} }
builder.append(line).append("\n"); builder.append(line).append("\n");
removedLine++; removedLine++;
} else if(line.startsWith("+")){ } else if (line.startsWith("+")) {
isAdded = true; isAdded = true;
if (isRemoved) { if (isRemoved) {
isRemoved = false; isRemoved = false;
@ -399,7 +406,7 @@ public class GitRepositoryService {
if (isRemoved) { if (isRemoved) {
lineChange = setRemoved(lineChange, builder); lineChange = setRemoved(lineChange, builder);
builder.setLength(0); builder.setLength(0);
} else if (isAdded){ } else if (isAdded) {
lineChange = setAdded(lineChange, builder); lineChange = setAdded(lineChange, builder);
builder.setLength(0); builder.setLength(0);
} }
@ -410,17 +417,18 @@ public class GitRepositoryService {
return fileChange; return fileChange;
} }
private LineChange setRemoved(LineChange lineChange, StringBuilder builder){ private LineChange setRemoved(LineChange lineChange, StringBuilder builder) {
lineChange.setLineFrom(builder.toString()); lineChange.setLineFrom(builder.toString());
lineChange.setRemoved(true); lineChange.setRemoved(true);
return lineChange; return lineChange;
} }
private LineChange setAdded(LineChange lineChange, StringBuilder builder){ private LineChange setAdded(LineChange lineChange, StringBuilder builder) {
lineChange.setLineTo(builder.toString()); lineChange.setLineTo(builder.toString());
lineChange.setAdded(true); lineChange.setAdded(true);
return lineChange; return lineChange;
} }
public Page<GitRepository> findAll(Pageable pageable) { public Page<GitRepository> findAll(Pageable pageable) {
return gitRepositoryRepository.findAll(pageable); return gitRepositoryRepository.findAll(pageable);
} }
@ -428,4 +436,21 @@ public class GitRepositoryService {
public GitRepository findById(Integer id) { public GitRepository findById(Integer id) {
return gitRepositoryRepository.getOne(id); return gitRepositoryRepository.getOne(id);
} }
public GitRepository findByUrlOrCreate(String gitRepositoryUrl) {
GitRepository gitRepository = gitRepositoryRepository.findByUrl(gitRepositoryUrl);
return gitRepository == null
? gitRepositoryRepository.save(new GitRepository(gitRepositoryUrl,
applicationContext.getBean(getGitApiServiceClass(gitRepositoryUrl)).getRepositoryId(gitRepositoryUrl)))
: gitRepository;
}
public Class<? extends GitApi> getGitApiServiceClass(Branch branch) {
return getGitApiServiceClass(branch.getGitRepository().getUrl());
}
public Class<? extends GitApi> getGitApiServiceClass(String url) {
return gitApiServiceHolder.get(StringUtils.getServerDomain(url));
}
} }

View File

@ -0,0 +1,59 @@
package ru.ulstu.extractor.gitrepository.service;
import org.springframework.stereotype.Service;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.http.HttpService;
import ru.ulstu.extractor.util.StringUtils;
@Service
public class GithubApi implements GitApi {
private final HttpService httpService;
private static final String BRANCHES_COUNT_URL = "https://api.github.com/repos/%s/%s/branches";
private static final String STARS_COUNT_URL = "https://api.github.com/repos/%s/%s";
private static final String OPEN_ISSUES_URL = "https://api.github.com/repos/%s/%s/issues?state=open";
private static final String AUTHOR_COMPLETED_ISSUES_URL = "https://api.github.com/repos/%s/%s/issues?state=open";
public GithubApi(HttpService httpService) {
this.httpService = httpService;
}
@Override
public Integer getBranchesCount(Branch branch) {
return httpService
.get(getFormattedUrl(branch, BRANCHES_COUNT_URL))
.length();
}
@Override
public Integer getStarsCount(Branch branch) {
return httpService
.get(getFormattedUrl(branch, STARS_COUNT_URL))
.getJSONObject(0)
.getInt("watchers");
}
@Override
public Integer getOpenIssuesCount(Branch branch) {
return httpService
.get(getFormattedUrl(branch, OPEN_ISSUES_URL))
.length();
}
@Override
public String getFormattedUrl(Branch branch, String template) {
String[] urlParts = branch.getGitRepository().getUrl().split("/");
return String.format(template, urlParts[3], StringUtils.removeDotGit(urlParts[4]));
}
@Override
public Integer getAuthorsCompletedIssues(Branch branch) {
return httpService
.get(getFormattedUrl(branch, AUTHOR_COMPLETED_ISSUES_URL))
.length();
}
@Override
public String getRepositoryId(String repositoryUrl) {
return null;
}
}

View File

@ -0,0 +1,74 @@
package ru.ulstu.extractor.gitrepository.service;
import org.json.JSONArray;
import org.springframework.stereotype.Service;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.http.HttpService;
import static ru.ulstu.extractor.util.StringUtils.getUrlParts;
import static ru.ulstu.extractor.util.StringUtils.removeDotGit;
@Service
public class GitlabApi implements GitApi {
private final HttpService httpService;
private static final String BRANCHES_COUNT_URL = "%s/api/v4/projects/%s/repository/branches";
private final static String PROJECT_ID_URL = "https://gitlab.com/api/v4/users/%s/projects?search=%s";
private static final String PROJECT_INFO_URL = "%s/api/v4/projects/%s";
private static final String OPEN_ISSUES_URL = "%s/api/v4/projects/%s/issues?state=opened";
private static final String COMPLETED_ISSUES_URL = "%s/api/v4/projects/%s/issues?state=closed";
public GitlabApi(HttpService httpService) {
this.httpService = httpService;
}
@Override
public Integer getBranchesCount(Branch branch) {
return httpService
.get(getFormattedUrl(branch, BRANCHES_COUNT_URL))
.length();
}
@Override
public Integer getStarsCount(Branch branch) {
return httpService
.get(getFormattedUrl(branch, PROJECT_INFO_URL))
.getJSONObject(0)
.getInt("star_count");
}
@Override
public Integer getOpenIssuesCount(Branch branch) {
return httpService
.get(getFormattedUrl(branch, OPEN_ISSUES_URL))
.length();
}
@Override
public String getFormattedUrl(Branch branch, String template) {
String[] urlParts = getUrlParts(branch.getGitRepository().getUrl());
return String.format(template, urlParts[0] + "/" + urlParts[1] + "/" + urlParts[2], branch.getGitRepository().getRepositoryId());
}
public String getFormattedUrlForProjectId(String repositoryUrl, String template) {
String[] urlParts = getUrlParts(repositoryUrl);
// получаем корректное название репозитория, gitlab всегда добавляет .git в конец
return String.format(template, urlParts[3], removeDotGit(urlParts[4]));
}
@Override
public Integer getAuthorsCompletedIssues(Branch branch) {
return httpService
.get(getFormattedUrl(branch, COMPLETED_ISSUES_URL))
.length();
}
public String getRepositoryId(String repositoryUrl) {
JSONArray projects = httpService.get(getFormattedUrlForProjectId(repositoryUrl, PROJECT_ID_URL));
for (int i = 0; i < projects.length(); i++) {
if (projects.getJSONObject(i).get("name").equals(removeDotGit(getUrlParts(repositoryUrl)[4]))) {
return String.valueOf(projects.getJSONObject(i).getInt("id"));
}
}
throw new RuntimeException("Id проекта не найден: " + repositoryUrl);
}
}

View File

@ -9,13 +9,15 @@ import com.sun.istack.NotNull;
import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.GitAPIException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.ulstu.extractor.branch.model.Branch; import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.branch.model.IndexingStatus;
import ru.ulstu.extractor.branch.service.BranchService; import ru.ulstu.extractor.branch.service.BranchService;
import ru.ulstu.extractor.commit.model.Commit;
import ru.ulstu.extractor.gitrepository.model.GitRepository; import ru.ulstu.extractor.gitrepository.model.GitRepository;
import ru.ulstu.extractor.gitrepository.repository.GitRepositoryRepository; import ru.ulstu.extractor.ts.creator.db.DBTimeSeriesCreator;
import ru.ulstu.extractor.model.Commit;
import ru.ulstu.extractor.ts.creator.AbstractTimeSeriesCreator;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
@ -26,44 +28,74 @@ public class IndexService {
private final static Logger LOG = LoggerFactory.getLogger(IndexService.class); private final static Logger LOG = LoggerFactory.getLogger(IndexService.class);
private final static int COMMITS_PAGE_SIZE = 10; private final static int COMMITS_PAGE_SIZE = 10;
private final GitRepositoryService gitRepositoryService; private final GitRepositoryService gitRepositoryService;
private final GitRepositoryRepository gitRepositoryRepository;
private final BranchService branchService; private final BranchService branchService;
private final List<AbstractTimeSeriesCreator> timeSeriesCreators; private final List<DBTimeSeriesCreator> timeSeriesCreators;
public IndexService(GitRepositoryService gitRepositoryService, public IndexService(GitRepositoryService gitRepositoryService,
GitRepositoryRepository gitRepositoryRepository,
BranchService branchService, BranchService branchService,
List<AbstractTimeSeriesCreator> timeSeriesCreators) { List<DBTimeSeriesCreator> timeSeriesCreators) {
this.gitRepositoryService = gitRepositoryService; this.gitRepositoryService = gitRepositoryService;
this.gitRepositoryRepository = gitRepositoryRepository;
this.branchService = branchService; this.branchService = branchService;
this.timeSeriesCreators = timeSeriesCreators; this.timeSeriesCreators = timeSeriesCreators;
} }
public void index(@NotNull String repositoryUrl, @NotNull String branchName) throws GitAPIException, IOException { @Transactional
GitRepository gitRepository = gitRepositoryRepository.findByUrl(repositoryUrl); @Async
if (gitRepository == null) { public void index(@NotNull Integer branchId) throws GitAPIException, IOException {
gitRepository = gitRepositoryRepository.save(new GitRepository(repositoryUrl)); Branch branch = branchService.findByBranchId(branchId).orElseThrow(() -> new RuntimeException("Ветка репозитория не найдена по id"));
} index(branch.getGitRepository(), branch);
Branch branch = branchService.findByRepositoryAndName(gitRepository, branchName); }
if (branch == null) {
branch = new Branch(gitRepository, branchName); @Transactional
} @Async
public void index(String gitRepositoryUrl, String branchName) throws GitAPIException, IOException {
GitRepository gitRepository = gitRepositoryService.findByUrlOrCreate(gitRepositoryUrl);
Branch branch = branchService.findByRepositoryAndNameOrCreate(gitRepository, branchName);
branch = branchService.updateStatus(branch, IndexingStatus.INDEXING);
index(gitRepository, branch);
}
@Transactional
@Async
public void index(GitRepository gitRepository, Branch branch) throws GitAPIException, IOException {
branchService.save(branch, Collections.emptyList()); branchService.save(branch, Collections.emptyList());
branch = branchService.updateStatus(branch, IndexingStatus.INDEXING);
int commitsFrom = 0; int commitsFrom = 0;
int commitsTo = COMMITS_PAGE_SIZE; int commitsTo = COMMITS_PAGE_SIZE;
List<Commit> commits = gitRepositoryService.getCommits(repositoryUrl, branchName, commitsFrom, commitsTo, true); List<Commit> commits = gitRepositoryService.getCommits(gitRepository.getUrl(), branch.getName(), commitsFrom, commitsTo, true);
while (!commits.isEmpty()) { while (!commits.isEmpty()) {
LOG.debug("{} commits loaded.", commits.size()); LOG.debug("{} commits loaded.", commits.size());
branchService.addCommits(branch, commits); branchService.addCommits(branch, commits);
LOG.debug("{} commits successfully saved. {} {}", commits.size(), repositoryUrl, branchName); LOG.debug("{} commits successfully saved. {} {}", commits.size(), gitRepository.getUrl(), branch.getName());
commitsFrom += COMMITS_PAGE_SIZE; commitsFrom += COMMITS_PAGE_SIZE;
commitsTo += COMMITS_PAGE_SIZE; commitsTo += COMMITS_PAGE_SIZE;
commits = gitRepositoryService.getCommits(repositoryUrl, branchName, commitsFrom, commitsTo, false); commits = gitRepositoryService.getCommits(gitRepository.getUrl(), branch.getName(), commitsFrom, commitsTo, false);
}
branch = branchService.findByBranchId(branch.getId()).orElseThrow(() -> new RuntimeException("Branch not found by id"));
final Branch branchForSave = branchService.updateStatus(branch, IndexingStatus.FINISHED);
timeSeriesCreators.forEach(tsCreator -> tsCreator.addTimeSeries(branchForSave));
LOG.debug("Complete indexing {} branch", branch.getName());
}
@Transactional
@Async
public void indexFailedBranchesOnStart() {
LOG.info("Старт проверки незавершенных задач для индексирований...");
List<Branch> failedBranches = branchService.findAllByIndexingStatus(IndexingStatus.INDEXING);
if (failedBranches.size() > 0) {
LOG.info("Найдено {} незавершенных задач для индексирования", failedBranches.size());
failedBranches.forEach(failedBranch -> {
try {
index(failedBranch.getId());
LOG.info("Завершено индексирование ветки {}", failedBranch.getName());
} catch (Exception ex) {
LOG.warn(ex.getMessage());
}
});
LOG.info("Завершено индексирование незавершенных задач");
} else {
LOG.info("Не найдено незавершенных веток для индексирования");
} }
Integer repositoryId = gitRepository.getId();
final Branch branchForSave = branch;
timeSeriesCreators.forEach(tsCreator -> tsCreator.addTimeSeries(repositoryId, branchForSave));
LOG.debug("Complete indexing {} branch", branchName);
} }
} }

View File

@ -1,5 +1,6 @@
package ru.ulstu.extractor.http; package ru.ulstu.extractor.http;
import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -8,6 +9,7 @@ import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClient;
import java.time.Duration;
import java.util.Optional; import java.util.Optional;
@Service @Service
@ -21,16 +23,44 @@ public class HttpService {
public JSONObject post(String url, JSONObject postData) { public JSONObject post(String url, JSONObject postData) {
log.debug("Service call: {}", url); log.debug("Service call: {}", url);
JSONObject response = new JSONObject(Optional.ofNullable(client JSONObject response = null;
.post() try {
.uri(url) response = new JSONObject(Optional.ofNullable(client
.contentType(MediaType.APPLICATION_JSON) .post()
.body(BodyInserters.fromValue(postData.toString())) .uri(url)
.accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON)
.retrieve() .body(BodyInserters.fromValue(postData.toString()))
.bodyToMono(String.class) .accept(MediaType.APPLICATION_JSON)
.block()).orElse("{response:\"empty\"}")); .retrieve()
.bodyToMono(String.class)
.toFuture().get()).orElse("{response:\"empty\"}"));
} catch (Exception e) {
return new JSONObject("{response:\"empty\"}");
}
log.debug("Service response: {}", response); log.debug("Service response: {}", response);
return response; return response;
} }
public JSONArray get(String url) {
log.debug("Service call: {}", url);
try {
String response = client
.get()
.uri(url)
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(String.class)
.timeout(Duration.ofMinutes(1))
.toFuture().get();
if (response.startsWith("[")) {
return new JSONArray(response);
} else {
JSONArray jsonArray = new JSONArray();
jsonArray.put(0, new JSONObject(response));
return jsonArray;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
} }

View File

@ -1,39 +0,0 @@
package ru.ulstu.extractor.recommendation.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import ru.ulstu.extractor.branch.service.BranchService;
import ru.ulstu.extractor.recommendation.model.FilterBranchForm;
import ru.ulstu.extractor.rule.service.FuzzyInferenceService;
import springfox.documentation.annotations.ApiIgnore;
import java.util.Optional;
import static ru.ulstu.extractor.core.Route.RECOMMENDATIONS;
@Controller
@ApiIgnore
public class RecommendationController {
private final FuzzyInferenceService fuzzyInferenceService;
private final BranchService branchService;
public RecommendationController(FuzzyInferenceService fuzzyInferenceService,
BranchService branchService) {
this.fuzzyInferenceService = fuzzyInferenceService;
this.branchService = branchService;
}
@GetMapping(RECOMMENDATIONS)
public String getRecommendations(Model model, @RequestParam Optional<Integer> branchId) {
model.addAttribute("branches", branchService.findAll());
if (branchId.isPresent()) {
model.addAttribute("recommendations", fuzzyInferenceService.getRecommendations(branchId.get()));
model.addAttribute("filterBranchForm", new FilterBranchForm(branchId.get()));
} else {
model.addAttribute("filterBranchForm", new FilterBranchForm());
}
return RECOMMENDATIONS;
}
}

View File

@ -11,7 +11,8 @@ public class AntecedentValue extends BaseEntity {
public AntecedentValue() { public AntecedentValue() {
} }
public AntecedentValue(String antecedentValue) { public AntecedentValue(Integer id, String antecedentValue) {
this.setId(id);
this.antecedentValue = antecedentValue; this.antecedentValue = antecedentValue;
} }

View File

@ -0,0 +1,7 @@
package ru.ulstu.extractor.rule.model;
public class AssessmentException extends RuntimeException {
public AssessmentException(String message) {
super(message);
}
}

View File

@ -1,77 +1,78 @@
package ru.ulstu.extractor.rule.service; package ru.ulstu.extractor.rule.service;
import com.fuzzylite.Engine; import com.fuzzylite.Engine;
import com.fuzzylite.activation.Highest; import com.fuzzylite.activation.General;
import com.fuzzylite.defuzzifier.Centroid; import com.fuzzylite.defuzzifier.Centroid;
import com.fuzzylite.norm.s.BoundedSum;
import com.fuzzylite.norm.s.Maximum; import com.fuzzylite.norm.s.Maximum;
import com.fuzzylite.norm.t.AlgebraicProduct; import com.fuzzylite.norm.t.AlgebraicProduct;
import com.fuzzylite.norm.t.Minimum;
import com.fuzzylite.rule.Rule; import com.fuzzylite.rule.Rule;
import com.fuzzylite.rule.RuleBlock; import com.fuzzylite.rule.RuleBlock;
import com.fuzzylite.term.Triangle; import com.fuzzylite.term.Triangle;
import com.fuzzylite.variable.InputVariable; import com.fuzzylite.variable.InputVariable;
import com.fuzzylite.variable.OutputVariable; import com.fuzzylite.variable.OutputVariable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.ulstu.extractor.gitrepository.service.GitRepositoryService; import ru.ulstu.extractor.assessment.model.Assessment;
import ru.ulstu.extractor.rule.model.AntecedentValue; import ru.ulstu.extractor.rule.model.AntecedentValue;
import ru.ulstu.extractor.rule.model.DbRule; 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.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static java.lang.String.format;
@Service @Service
public class FuzzyInferenceService { public class FuzzyInferenceService {
private final static Logger LOG = LoggerFactory.getLogger(FuzzyInferenceService.class);
private final static String OUTPUT_VARIABLE_NAME = "state"; private final static String OUTPUT_VARIABLE_NAME = "state";
private final static String RULE_TEMPLATE = "if %s is %s and %s is %s then " private final static String RULE_TEMPLATE = "if %s is %s and %s is %s then "
+ OUTPUT_VARIABLE_NAME + OUTPUT_VARIABLE_NAME
+ " is %s"; + " is %s";
private final DbRuleService ruleService; private final static String NO_RESULT = "Нет результата";
private final AntecedentValueService antecedentValueService;
private final GitRepositoryService gitRepositoryService;
private final TimeSeriesService timeSeriesService;
public FuzzyInferenceService(DbRuleService ruleService, private List<String> getRulesFromDb(List<DbRule> dbRules, Map<String, Double> variableValues) {
AntecedentValueService antecedentValueService, validateVariables(variableValues, dbRules);
GitRepositoryService gitRepositoryService, return dbRules.stream().map(this::getFuzzyRule).collect(Collectors.toList());
TimeSeriesService timeSeriesService) {
this.ruleService = ruleService;
this.antecedentValueService = antecedentValueService;
this.gitRepositoryService = gitRepositoryService;
this.timeSeriesService = timeSeriesService;
}
public List<String> getRulesFromDb(Map<String, Double> variableValues) {
List<DbRule> dbDbRules = ruleService.getList();
validateVariables(variableValues, dbDbRules);
return dbDbRules.stream().map(this::getFuzzyRule).collect(Collectors.toList());
} }
private String getFuzzyRule(DbRule dbRule) { private String getFuzzyRule(DbRule dbRule) {
return String.format(RULE_TEMPLATE, return format(RULE_TEMPLATE,
dbRule.getFirstAntecedent().name(), dbRule.getFirstAntecedent().name(),
dbRule.getFirstAntecedentValue().getAntecedentValue(), dbRule.getFirstAntecedentValue().getAntecedentValue(),
dbRule.getSecondAntecedent().name(), dbRule.getSecondAntecedent().name(),
dbRule.getSecondAntecedentValue().getAntecedentValue(), dbRule.getSecondAntecedentValue().getAntecedentValue(),
dbRule.getConsequent()); dbRule.getId());
} }
private RuleBlock getRuleBlock(Engine engine, private RuleBlock getRuleBlock(Engine engine,
List<DbRule> dbRules,
Map<String, Double> variableValues, Map<String, Double> variableValues,
Map<String, Double> min,
Map<String, Double> max,
List<AntecedentValue> antecedentValues, List<AntecedentValue> antecedentValues,
List<String> consequentValues) { List<Integer> consequentValues) {
variableValues.forEach((key, value) -> { variableValues.forEach((key, value) -> {
InputVariable input = new InputVariable(); InputVariable input = new InputVariable();
input.setName(key); input.setName(key);
input.setDescription(""); input.setDescription("");
input.setEnabled(true); input.setEnabled(true);
input.setRange(-0.1, antecedentValues.size() + 1.1); double delta = antecedentValues.size() > 1
? (max.get(key) - min.get(key)) / (antecedentValues.size() - 1)
: (max.get(key) - min.get(key));
input.setRange(min.get(key), max.get(key));
input.setLockValueInRange(false); input.setLockValueInRange(false);
for (int i = 0; i < antecedentValues.size(); i++) { for (int i = 0; i < antecedentValues.size(); i++) {
input.addTerm(new Triangle(antecedentValues.get(i).getAntecedentValue(), i - 0.1, i + 2.1)); input.addTerm(
new Triangle(
antecedentValues.get(i).getAntecedentValue(),
min.get(key) + i * delta - 0.5 * delta,
min.get(key) + i * delta + delta + 0.5 * delta
)
);
} }
engine.addInputVariable(input); engine.addInputVariable(input);
}); });
@ -80,13 +81,13 @@ public class FuzzyInferenceService {
output.setName(OUTPUT_VARIABLE_NAME); output.setName(OUTPUT_VARIABLE_NAME);
output.setDescription(""); output.setDescription("");
output.setEnabled(true); output.setEnabled(true);
output.setRange(-0.1, antecedentValues.size() + 0.1); output.setRange(0, consequentValues.size() + 0.1);
output.setAggregation(new Maximum()); output.setAggregation(new Maximum());
output.setDefuzzifier(new Centroid(100)); output.setDefuzzifier(new Centroid(10));
output.setDefaultValue(Double.NaN); output.setDefaultValue(Double.NaN);
output.setLockValueInRange(false); output.setLockValueInRange(false);
for (int i = 0; i < consequentValues.size(); i++) { for (int i = 0; i < consequentValues.size(); i++) {
output.addTerm(new Triangle(consequentValues.get(i), i - 0.1, i + 2.1)); output.addTerm(new Triangle(consequentValues.get(i).toString(), i, i + 2.1));
} }
engine.addOutputVariable(output); engine.addOutputVariable(output);
@ -94,11 +95,14 @@ public class FuzzyInferenceService {
mamdani.setName("mamdani"); mamdani.setName("mamdani");
mamdani.setDescription(""); mamdani.setDescription("");
mamdani.setEnabled(true); mamdani.setEnabled(true);
mamdani.setConjunction(new AlgebraicProduct()); mamdani.setConjunction(new Minimum());
mamdani.setDisjunction(new BoundedSum()); //mamdani.setDisjunction(null);
mamdani.setImplication(new AlgebraicProduct()); mamdani.setImplication(new AlgebraicProduct());
mamdani.setActivation(new Highest()); mamdani.setActivation(new General());
getRulesFromDb(variableValues).forEach(r -> mamdani.addRule(Rule.parse(r, engine))); getRulesFromDb(dbRules, variableValues).forEach(r -> {
LOG.info(r);
mamdani.addRule(Rule.parse(r, engine));
});
return mamdani; return mamdani;
} }
@ -109,31 +113,40 @@ public class FuzzyInferenceService {
return engine; return engine;
} }
public String getRecommendations(Integer branchId) { public List<Assessment> getFuzzyInference(List<DbRule> dbRules,
List<TimeSeries> timeSeries = timeSeriesService.getByBranch(branchId); List<AntecedentValue> antecedentValues,
Map<String, Double> variableValues,
Map<String, Double> min,
Map<String, Double> max) {
Engine engine = getFuzzyEngine(); Engine engine = getFuzzyEngine();
List<AntecedentValue> antecedentValues = antecedentValueService.getList(); List<Integer> consequentValues = dbRules.stream().map(DbRule::getId).collect(Collectors.toList());
List<String> consequentValues = ruleService.getConsequentList(); engine.addRuleBlock(getRuleBlock(engine, dbRules, variableValues, min, max, antecedentValues, consequentValues));
Map<String, Double> variableValues = new HashMap<>(); Map.Entry<String, Double> consequent = getConsequent(engine, variableValues);
timeSeries.forEach(ts -> variableValues.put(ts.getTimeSeriesType().name(), timeSeriesService.getLastTimeSeriesTendency(ts))); if (consequent.getKey().equals(NO_RESULT)) {
engine.addRuleBlock(getRuleBlock(engine, variableValues, antecedentValues, consequentValues)); return new ArrayList<>();
return getConsequent(engine, variableValues); }
return dbRules
.stream()
.filter(r -> r.getId().equals(Integer.valueOf(consequent.getKey())))
.map(r -> new Assessment(r, consequent.getValue()))
.collect(Collectors.toList());
} }
private void validateVariables(Map<String, Double> variableValues, List<DbRule> dbDbRules) { private void validateVariables(Map<String, Double> variableValues, List<DbRule> dbDbRules) {
for (DbRule dbRule : dbDbRules) { for (DbRule dbRule : dbDbRules) {
if (!variableValues.containsKey(dbRule.getFirstAntecedent().name())) { if (!variableValues.containsKey(dbRule.getFirstAntecedent().name())) {
throw new RuntimeException(String.format("Переменной в правиле не задано значение (нет временного ряда): %s ", throw new RuntimeException(format("Переменной в правиле не задано значение (нет временного ряда): %s ",
dbRule.getFirstAntecedent().name())); dbRule.getFirstAntecedent().name()));
} }
if (!variableValues.containsKey(dbRule.getSecondAntecedent().name())) { if (!variableValues.containsKey(dbRule.getSecondAntecedent().name())) {
throw new RuntimeException(String.format("Переменной в правиле не задано значение (нет временного ряда): %s ", throw new RuntimeException(format("Переменной в правиле не задано значение (нет временного ряда): %s ",
dbRule.getSecondAntecedent().name())); dbRule.getSecondAntecedent().name()));
} }
} }
} }
private String getConsequent(Engine engine, Map<String, Double> variableValues) { private Map.Entry<String, Double> getConsequent(Engine engine, Map<String, Double> variableValues) {
OutputVariable outputVariable = engine.getOutputVariable(OUTPUT_VARIABLE_NAME); OutputVariable outputVariable = engine.getOutputVariable(OUTPUT_VARIABLE_NAME);
for (Map.Entry<String, Double> variableValue : variableValues.entrySet()) { for (Map.Entry<String, Double> variableValue : variableValues.entrySet()) {
InputVariable inputVariable = engine.getInputVariable(variableValue.getKey()); InputVariable inputVariable = engine.getInputVariable(variableValue.getKey());
@ -141,10 +154,10 @@ public class FuzzyInferenceService {
} }
engine.process(); engine.process();
if (outputVariable != null) { if (outputVariable != null) {
outputVariable.defuzzify(); LOG.info("Output: {}", outputVariable.getValue());
} }
return (outputVariable == null || Double.isNaN(outputVariable.getValue())) return (outputVariable == null || Double.isNaN(outputVariable.getValue()))
? "Нет рекомендаций" ? Map.entry(NO_RESULT, 0.0)
: outputVariable.highestMembership(outputVariable.getValue()).getSecond().getName(); : Map.entry(outputVariable.highestMembershipTerm(outputVariable.getValue()).getName(), outputVariable.getValue());
} }
} }

View File

@ -0,0 +1,27 @@
package ru.ulstu.extractor.ts.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import ru.ulstu.extractor.ts.model.TimeSeries;
import ru.ulstu.extractor.ts.service.TimeSeriesService;
import springfox.documentation.annotations.ApiIgnore;
import java.util.List;
@Controller
@ApiIgnore
public class TimeSeriesMarkupController {
private final TimeSeriesService timeSeriesService;
public TimeSeriesMarkupController(TimeSeriesService timeSeriesService) {
this.timeSeriesService = timeSeriesService;
}
@GetMapping("time-series-markup")
public String markupTs(Model model) {
List<TimeSeries> ts = timeSeriesService.getAllTimeSeries();
model.addAttribute("ts", ts);
return "markup";
}
}

View File

@ -1,49 +1,10 @@
package ru.ulstu.extractor.ts.creator; 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.TimeSeriesType;
import ru.ulstu.extractor.ts.model.TimeSeriesValue;
import ru.ulstu.extractor.ts.service.TimeSeriesService; import ru.ulstu.extractor.ts.service.TimeSeriesService;
import java.util.Comparator;
import java.util.List;
import static ru.ulstu.extractor.ts.util.TimeSeriesDateMapper.mapTimeSeriesToInterval;
public abstract class AbstractTimeSeriesCreator { public abstract class AbstractTimeSeriesCreator {
public abstract TimeSeriesType getTimeSeriesType(); public abstract TimeSeriesType getTimeSeriesType();
/**
* Извлечь список точек временных рядов
*
* @param repositoryId
* @param branchName
* @return
*/
public abstract List<TimeSeries> getTimeSeries(Integer repositoryId, String branchName);
public abstract TimeSeriesService getTimeSeriesService(); public abstract TimeSeriesService getTimeSeriesService();
/**
* Сохранить извлеченные временные ряды
*
* @param repositoryId
* @param branch
*/
public void addTimeSeries(Integer repositoryId, Branch branch) {
// извлеченные временных рядов
List<TimeSeries> timeSeries = getTimeSeries(repositoryId, branch.getName());
// сгруппированные по временным интервалам точки временных рядов
timeSeries.forEach(ts -> ts.setValues(mapTimeSeriesToInterval(getTimeSeriesService().getTimeSeriesInterval(), ts.getValues())));
getTimeSeriesService().save(sortTimeSeries(timeSeries), branch);
}
private List<TimeSeries> sortTimeSeries(List<TimeSeries> timeSeries) {
for (TimeSeries ts : timeSeries) {
ts.getValues().sort(Comparator.comparing(TimeSeriesValue::getDate));
}
return timeSeries;
}
} }

View File

@ -1,54 +0,0 @@
package ru.ulstu.extractor.ts.creator;
import org.springframework.stereotype.Component;
import ru.ulstu.extractor.branch.service.BranchService;
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;
import ru.ulstu.extractor.ts.service.TimeSeriesService;
import ru.ulstu.extractor.ts.util.Dummy;
import java.util.Collections;
import java.util.List;
@Component
public class AuthorsCommitTS extends AbstractTimeSeriesCreator {
private final TimeSeriesService timeSeriesService;
private final BranchService branchService;
private final GitRepositoryService gitRepositoryService;
public AuthorsCommitTS(TimeSeriesService timeSeriesService,
BranchService branchService,
GitRepositoryService gitRepositoryService) {
this.timeSeriesService = timeSeriesService;
this.branchService = branchService;
this.gitRepositoryService = gitRepositoryService;
}
@Override
public TimeSeriesType getTimeSeriesType() {
return TimeSeriesType.AUTHOR_COMMITS;
}
@Override
public List<TimeSeries> getTimeSeries(Integer repositoryId, String branchName) {
GitRepository gitRepository = gitRepositoryService.findById(repositoryId);
//TODO: добавить постраничное чтение
return Collections.singletonList(
new TimeSeries(
String.format("%s %s %s",
gitRepository.getName(),
branchName,
getTimeSeriesType().getDescription()),
branchService.findByRepositoryAndName(gitRepository, branchName),
getTimeSeriesType(),
Dummy.getDefaultTimeSeries()));
}
@Override
public TimeSeriesService getTimeSeriesService() {
return timeSeriesService;
}
}

View File

@ -1,54 +0,0 @@
package ru.ulstu.extractor.ts.creator;
import org.springframework.stereotype.Component;
import ru.ulstu.extractor.branch.service.BranchService;
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;
import ru.ulstu.extractor.ts.service.TimeSeriesService;
import ru.ulstu.extractor.ts.util.Dummy;
import java.util.Collections;
import java.util.List;
@Component
public class AuthorsCompletedIssueTS extends AbstractTimeSeriesCreator {
private final TimeSeriesService timeSeriesService;
private final BranchService branchService;
private final GitRepositoryService gitRepositoryService;
public AuthorsCompletedIssueTS(TimeSeriesService timeSeriesService,
BranchService branchService,
GitRepositoryService gitRepositoryService) {
this.timeSeriesService = timeSeriesService;
this.branchService = branchService;
this.gitRepositoryService = gitRepositoryService;
}
@Override
public List<TimeSeries> getTimeSeries(Integer repositoryId, String branchName) {
GitRepository gitRepository = gitRepositoryService.findById(repositoryId);
//TODO: добавить постраничное чтение
return Collections.singletonList(
new TimeSeries(
String.format("%s %s %s",
gitRepository.getName(),
branchName,
getTimeSeriesType().getDescription()),
branchService.findByRepositoryAndName(gitRepository, branchName),
getTimeSeriesType(),
Dummy.getDefaultTimeSeries()));
}
@Override
public TimeSeriesService getTimeSeriesService() {
return timeSeriesService;
}
@Override
public TimeSeriesType getTimeSeriesType() {
return TimeSeriesType.AUTHOR_COMPLETED_ISSUES;
}
}

View File

@ -1,53 +0,0 @@
package ru.ulstu.extractor.ts.creator;
import org.springframework.stereotype.Component;
import ru.ulstu.extractor.branch.service.BranchService;
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;
import ru.ulstu.extractor.ts.service.TimeSeriesService;
import ru.ulstu.extractor.ts.util.Dummy;
import java.util.Collections;
import java.util.List;
@Component
public class AuthorsIssueTS extends AbstractTimeSeriesCreator {
private final TimeSeriesService timeSeriesService;
private final BranchService branchService;
private final GitRepositoryService gitRepositoryService;
public AuthorsIssueTS(TimeSeriesService timeSeriesService,
BranchService branchService,
GitRepositoryService gitRepositoryService) {
this.timeSeriesService = timeSeriesService;
this.branchService = branchService;
this.gitRepositoryService = gitRepositoryService;
}
@Override
public List<TimeSeries> getTimeSeries(Integer repositoryId, String branchName) {
GitRepository gitRepository = gitRepositoryService.findById(repositoryId);
return Collections.singletonList(
new TimeSeries(
String.format("%s %s %s",
gitRepository.getName(),
branchName,
getTimeSeriesType().getDescription()),
branchService.findByRepositoryAndName(gitRepository, branchName),
getTimeSeriesType(),
Dummy.getDefaultTimeSeries()));
}
@Override
public TimeSeriesService getTimeSeriesService() {
return timeSeriesService;
}
@Override
public TimeSeriesType getTimeSeriesType() {
return TimeSeriesType.AUTHOR_ISSUES;
}
}

View File

@ -1,53 +0,0 @@
package ru.ulstu.extractor.ts.creator;
import org.springframework.stereotype.Component;
import ru.ulstu.extractor.branch.service.BranchService;
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;
import ru.ulstu.extractor.ts.service.TimeSeriesService;
import ru.ulstu.extractor.ts.util.Dummy;
import java.util.Collections;
import java.util.List;
@Component
public class BranchTS extends AbstractTimeSeriesCreator {
private final TimeSeriesService timeSeriesService;
private final BranchService branchService;
private final GitRepositoryService gitRepositoryService;
public BranchTS(TimeSeriesService timeSeriesService,
BranchService branchService,
GitRepositoryService gitRepositoryService) {
this.timeSeriesService = timeSeriesService;
this.branchService = branchService;
this.gitRepositoryService = gitRepositoryService;
}
@Override
public TimeSeriesType getTimeSeriesType() {
return TimeSeriesType.BRANCHES;
}
@Override
public List<TimeSeries> getTimeSeries(Integer repositoryId, String branchName) {
GitRepository gitRepository = gitRepositoryService.findById(repositoryId);
return Collections.singletonList(
new TimeSeries(
String.format("%s %s %s",
gitRepository.getName(),
branchName,
getTimeSeriesType().getDescription()),
branchService.findByRepositoryAndName(gitRepository, branchName),
getTimeSeriesType(),
Dummy.getDefaultTimeSeries()));
}
@Override
public TimeSeriesService getTimeSeriesService() {
return timeSeriesService;
}
}

View File

@ -1,53 +0,0 @@
package ru.ulstu.extractor.ts.creator;
import org.springframework.stereotype.Component;
import ru.ulstu.extractor.branch.service.BranchService;
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;
import ru.ulstu.extractor.ts.service.TimeSeriesService;
import ru.ulstu.extractor.ts.util.Dummy;
import java.util.Collections;
import java.util.List;
@Component
public class IssuesTS extends AbstractTimeSeriesCreator {
private final TimeSeriesService timeSeriesService;
private final BranchService branchService;
private final GitRepositoryService gitRepositoryService;
public IssuesTS(TimeSeriesService timeSeriesService,
BranchService branchService,
GitRepositoryService gitRepositoryService) {
this.timeSeriesService = timeSeriesService;
this.branchService = branchService;
this.gitRepositoryService = gitRepositoryService;
}
@Override
public List<TimeSeries> getTimeSeries(Integer repositoryId, String branchName) {
GitRepository gitRepository = gitRepositoryService.findById(repositoryId);
return Collections.singletonList(
new TimeSeries(
String.format("%s %s %s",
gitRepository.getName(),
branchName,
getTimeSeriesType().getDescription()),
branchService.findByRepositoryAndName(gitRepository, branchName),
getTimeSeriesType(),
Dummy.getDefaultTimeSeries()));
}
@Override
public TimeSeriesService getTimeSeriesService() {
return timeSeriesService;
}
@Override
public TimeSeriesType getTimeSeriesType() {
return TimeSeriesType.ISSUES;
}
}

View File

@ -1,53 +0,0 @@
package ru.ulstu.extractor.ts.creator;
import org.springframework.stereotype.Component;
import ru.ulstu.extractor.branch.service.BranchService;
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;
import ru.ulstu.extractor.ts.service.TimeSeriesService;
import ru.ulstu.extractor.ts.util.Dummy;
import java.util.Collections;
import java.util.List;
@Component
public class StarTS extends AbstractTimeSeriesCreator {
private final TimeSeriesService timeSeriesService;
private final BranchService branchService;
private final GitRepositoryService gitRepositoryService;
public StarTS(TimeSeriesService timeSeriesService,
BranchService branchService,
GitRepositoryService gitRepositoryService) {
this.timeSeriesService = timeSeriesService;
this.branchService = branchService;
this.gitRepositoryService = gitRepositoryService;
}
@Override
public List<TimeSeries> getTimeSeries(Integer repositoryId, String branchName) {
GitRepository gitRepository = gitRepositoryService.findById(repositoryId);
return Collections.singletonList(
new TimeSeries(
String.format("%s %s %s",
gitRepository.getName(),
branchName,
getTimeSeriesType().getDescription()),
branchService.findByRepositoryAndName(gitRepository, branchName),
getTimeSeriesType(),
Dummy.getDefaultTimeSeries()));
}
@Override
public TimeSeriesService getTimeSeriesService() {
return timeSeriesService;
}
@Override
public TimeSeriesType getTimeSeriesType() {
return TimeSeriesType.STARS;
}
}

View File

@ -1,12 +1,12 @@
package ru.ulstu.extractor.ts.creator; package ru.ulstu.extractor.ts.creator.db;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.ulstu.extractor.author.model.Author; import ru.ulstu.extractor.author.model.Author;
import ru.ulstu.extractor.author.service.AuthorService; import ru.ulstu.extractor.author.service.AuthorService;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.branch.service.BranchService; import ru.ulstu.extractor.branch.service.BranchService;
import ru.ulstu.extractor.commit.model.Commit;
import ru.ulstu.extractor.commit.service.CommitService; 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.TimeSeries;
import ru.ulstu.extractor.ts.model.TimeSeriesType; import ru.ulstu.extractor.ts.model.TimeSeriesType;
import ru.ulstu.extractor.ts.model.TimeSeriesValue; import ru.ulstu.extractor.ts.model.TimeSeriesValue;
@ -16,46 +16,44 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
@Component @Component
public class AuthorTS extends AbstractTimeSeriesCreator { public class AuthorsCommitTS extends DBTimeSeriesCreator {
private final TimeSeriesService timeSeriesService; private final TimeSeriesService timeSeriesService;
private final CommitService commitService; private final CommitService commitService;
private final AuthorService authorService; private final AuthorService authorService;
private final GitRepositoryService gitRepositoryService;
private final BranchService branchService; private final BranchService branchService;
public AuthorTS(TimeSeriesService timeSeriesService, public AuthorsCommitTS(TimeSeriesService timeSeriesService,
CommitService commitService, CommitService commitService,
AuthorService authorService, AuthorService authorService,
GitRepositoryService gitRepositoryService, BranchService branchService) {
BranchService branchService) {
this.timeSeriesService = timeSeriesService; this.timeSeriesService = timeSeriesService;
this.commitService = commitService; this.commitService = commitService;
this.authorService = authorService; this.authorService = authorService;
this.gitRepositoryService = gitRepositoryService;
this.branchService = branchService; this.branchService = branchService;
} }
@Override @Override
public TimeSeriesType getTimeSeriesType() { public TimeSeriesType getTimeSeriesType() {
return TimeSeriesType.AUTHORS; return TimeSeriesType.AUTHOR_COMMITS;
} }
@Override @Override
public List<TimeSeries> getTimeSeries(Integer repositoryId, String branchName) { public List<TimeSeries> getTimeSeries(Branch branch) {
List<TimeSeries> timeSeriesResult = new ArrayList<>(); List<TimeSeries> timeSeriesResult = new ArrayList<>();
List<Author> authors = authorService.findAll(); List<Author> authors = authorService.findAll();
GitRepository gitRepository = gitRepositoryService.findById(repositoryId); List<Commit> commits = new ArrayList<>(commitService.findByRepositoryIdAndName(branch.getGitRepository().getId(),
List<ru.ulstu.extractor.model.Commit> commits = new ArrayList<>(commitService.findByRepositoryIdAndName(repositoryId, branchName)); branch.getName()));
for (Author author : authors) { for (Author author : authors) {
TimeSeries timeSeries = new TimeSeries( TimeSeries timeSeries = new TimeSeries(
String.format("%s %s %s %s", String.format("%s %s %s %s",
gitRepository.getName(), branch.getGitRepository().getName(),
branchName, branch.getName(),
author.getName(), author.getName(),
getTimeSeriesType().getDescription()), getTimeSeriesType().getDescription()),
branchService.findByRepositoryAndName(gitRepository, branchName), branchService.findByRepositoryAndName(branch.getGitRepository(),
branch.getName()),
getTimeSeriesType()); getTimeSeriesType());
for (ru.ulstu.extractor.model.Commit commit : commits) { for (Commit commit : commits) {
if (commit.getAuthor().equals(author)) { if (commit.getAuthor().equals(author)) {
timeSeries.getValues().add(new TimeSeriesValue(commit.getDate(), 1.0)); timeSeries.getValues().add(new TimeSeriesValue(commit.getDate(), 1.0));
} }

View File

@ -1,9 +1,8 @@
package ru.ulstu.extractor.ts.creator; package ru.ulstu.extractor.ts.creator.db;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.branch.service.BranchService; import ru.ulstu.extractor.branch.service.BranchService;
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.TimeSeries;
import ru.ulstu.extractor.ts.model.TimeSeriesType; import ru.ulstu.extractor.ts.model.TimeSeriesType;
import ru.ulstu.extractor.ts.service.TimeSeriesService; import ru.ulstu.extractor.ts.service.TimeSeriesService;
@ -13,30 +12,25 @@ import java.util.Collections;
import java.util.List; import java.util.List;
@Component @Component
public class ClassTS extends AbstractTimeSeriesCreator { public class ClassTS extends DBTimeSeriesCreator {
private final TimeSeriesService timeSeriesService; private final TimeSeriesService timeSeriesService;
private final BranchService branchService; private final BranchService branchService;
private final GitRepositoryService gitRepositoryService;
public ClassTS(TimeSeriesService timeSeriesService, public ClassTS(TimeSeriesService timeSeriesService,
BranchService branchService, BranchService branchService) {
GitRepositoryService gitRepositoryService) {
this.timeSeriesService = timeSeriesService; this.timeSeriesService = timeSeriesService;
this.branchService = branchService; this.branchService = branchService;
this.gitRepositoryService = gitRepositoryService;
} }
@Override @Override
public List<TimeSeries> getTimeSeries(Integer repositoryId, String branchName) { public List<TimeSeries> getTimeSeries(Branch branch) {
GitRepository gitRepository = gitRepositoryService.findById(repositoryId);
return Collections.singletonList( return Collections.singletonList(
new TimeSeries( new TimeSeries(
String.format("%s %s %s", String.format("%s %s %s",
gitRepository.getName(), branch.getGitRepository().getName(),
branchName, branch.getName(),
getTimeSeriesType().getDescription()), getTimeSeriesType().getDescription()),
branchService.findByRepositoryAndName(gitRepository, branchName), branchService.findByRepositoryAndName(branch.getGitRepository(), branch.getName()),
getTimeSeriesType(), getTimeSeriesType(),
Dummy.getDefaultTimeSeries())); Dummy.getDefaultTimeSeries()));
} }

View File

@ -1,10 +1,9 @@
package ru.ulstu.extractor.ts.creator; package ru.ulstu.extractor.ts.creator.db;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.branch.service.BranchService; import ru.ulstu.extractor.branch.service.BranchService;
import ru.ulstu.extractor.commit.service.CommitService; 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.TimeSeries;
import ru.ulstu.extractor.ts.model.TimeSeriesType; import ru.ulstu.extractor.ts.model.TimeSeriesType;
import ru.ulstu.extractor.ts.model.TimeSeriesValue; import ru.ulstu.extractor.ts.model.TimeSeriesValue;
@ -15,35 +14,33 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Component @Component
public class CommitsTS extends AbstractTimeSeriesCreator { public class CommitsTS extends DBTimeSeriesCreator {
private final TimeSeriesService timeSeriesService; private final TimeSeriesService timeSeriesService;
private final CommitService commitService; private final CommitService commitService;
private final GitRepositoryService gitRepositoryService;
private final BranchService branchService; private final BranchService branchService;
public CommitsTS(TimeSeriesService timeSeriesService, public CommitsTS(TimeSeriesService timeSeriesService,
CommitService commitService, CommitService commitService,
GitRepositoryService gitRepositoryService,
BranchService branchService) { BranchService branchService) {
this.timeSeriesService = timeSeriesService; this.timeSeriesService = timeSeriesService;
this.commitService = commitService; this.commitService = commitService;
this.gitRepositoryService = gitRepositoryService;
this.branchService = branchService; this.branchService = branchService;
} }
@Override @Override
public List<TimeSeries> getTimeSeries(Integer repositoryId, String branchName) { public List<TimeSeries> getTimeSeries(Branch branch) {
GitRepository gitRepository = gitRepositoryService.findById(repositoryId);
//TODO: добавить постраничное чтение //TODO: добавить постраничное чтение
return Collections.singletonList( return Collections.singletonList(
new TimeSeries( new TimeSeries(
String.format("%s %s %s", String.format("%s %s %s",
gitRepository.getName(), branch.getGitRepository().getName(),
branchName, branch.getName(),
getTimeSeriesType().getDescription()), getTimeSeriesType().getDescription()),
branchService.findByRepositoryAndName(gitRepository, branchName), branchService.findByRepositoryAndName(branch.getGitRepository(),
branch.getName()),
getTimeSeriesType(), getTimeSeriesType(),
commitService.findByRepositoryIdAndName(repositoryId, branchName) commitService.findByRepositoryIdAndName(branch.getGitRepository().getId(),
branch.getName())
.stream() .stream()
.map(c -> new TimeSeriesValue(c.getDate(), 1.0)) .map(c -> new TimeSeriesValue(c.getDate(), 1.0))
.collect(Collectors.toList()))); .collect(Collectors.toList())));

View File

@ -0,0 +1,42 @@
package ru.ulstu.extractor.ts.creator.db;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.ts.creator.AbstractTimeSeriesCreator;
import ru.ulstu.extractor.ts.model.TimeSeries;
import ru.ulstu.extractor.ts.model.TimeSeriesValue;
import java.util.Comparator;
import java.util.List;
import static ru.ulstu.extractor.ts.util.TimeSeriesDateMapper.mapTimeSeriesToInterval;
public abstract class DBTimeSeriesCreator extends AbstractTimeSeriesCreator {
/**
* Извлечь список точек временных рядов
*
* @param branch
* @return
*/
public abstract List<TimeSeries> getTimeSeries(Branch branch);
/**
* Сохранить извлеченные временные ряды
*
* @param branch
*/
public void addTimeSeries(Branch branch) {
// извлеченные временных рядов
List<TimeSeries> timeSeries = getTimeSeries(branch);
// сгруппированные по временным интервалам точки временных рядов
timeSeries.forEach(ts -> ts.setValues(mapTimeSeriesToInterval(getTimeSeriesService().getTimeSeriesInterval(), ts.getValues())));
getTimeSeriesService().save(sortTimeSeries(timeSeries), branch);
}
private List<TimeSeries> sortTimeSeries(List<TimeSeries> timeSeries) {
for (TimeSeries ts : timeSeries) {
ts.getValues().sort(Comparator.comparing(TimeSeriesValue::getDate));
}
return timeSeries;
}
}

View File

@ -1,9 +1,8 @@
package ru.ulstu.extractor.ts.creator; package ru.ulstu.extractor.ts.creator.db;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.branch.service.BranchService; import ru.ulstu.extractor.branch.service.BranchService;
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.TimeSeries;
import ru.ulstu.extractor.ts.model.TimeSeriesType; import ru.ulstu.extractor.ts.model.TimeSeriesType;
import ru.ulstu.extractor.ts.service.TimeSeriesService; import ru.ulstu.extractor.ts.service.TimeSeriesService;
@ -13,30 +12,25 @@ import java.util.Collections;
import java.util.List; import java.util.List;
@Component @Component
public class DependenceTS extends AbstractTimeSeriesCreator { public class DependenceTS extends DBTimeSeriesCreator {
private final TimeSeriesService timeSeriesService; private final TimeSeriesService timeSeriesService;
private final BranchService branchService; private final BranchService branchService;
private final GitRepositoryService gitRepositoryService;
public DependenceTS(TimeSeriesService timeSeriesService, public DependenceTS(TimeSeriesService timeSeriesService,
BranchService branchService, BranchService branchService) {
GitRepositoryService gitRepositoryService) {
this.timeSeriesService = timeSeriesService; this.timeSeriesService = timeSeriesService;
this.branchService = branchService; this.branchService = branchService;
this.gitRepositoryService = gitRepositoryService;
} }
@Override @Override
public List<TimeSeries> getTimeSeries(Integer repositoryId, String branchName) { public List<TimeSeries> getTimeSeries(Branch branch) {
GitRepository gitRepository = gitRepositoryService.findById(repositoryId);
return Collections.singletonList( return Collections.singletonList(
new TimeSeries( new TimeSeries(
String.format("%s %s %s", String.format("%s %s %s",
gitRepository.getName(), branch.getGitRepository().getName(),
branchName, branch.getName(),
getTimeSeriesType().getDescription()), getTimeSeriesType().getDescription()),
branchService.findByRepositoryAndName(gitRepository, branchName), branchService.findByRepositoryAndName(branch.getGitRepository(), branch.getName()),
getTimeSeriesType(), getTimeSeriesType(),
Dummy.getDefaultTimeSeries())); Dummy.getDefaultTimeSeries()));
} }

View File

@ -1,11 +1,11 @@
package ru.ulstu.extractor.ts.creator; package ru.ulstu.extractor.ts.creator.db;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.branch.service.BranchService; import ru.ulstu.extractor.branch.service.BranchService;
import ru.ulstu.extractor.commit.model.Commit;
import ru.ulstu.extractor.commit.service.CommitService; import ru.ulstu.extractor.commit.service.CommitService;
import ru.ulstu.extractor.gitrepository.model.FileChange; import ru.ulstu.extractor.gitrepository.model.FileChange;
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.TimeSeries;
import ru.ulstu.extractor.ts.model.TimeSeriesType; import ru.ulstu.extractor.ts.model.TimeSeriesType;
import ru.ulstu.extractor.ts.model.TimeSeriesValue; import ru.ulstu.extractor.ts.model.TimeSeriesValue;
@ -17,36 +17,32 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Component @Component
public class EntityTS extends AbstractTimeSeriesCreator { public class EntityTS extends DBTimeSeriesCreator {
private final TimeSeriesService timeSeriesService; private final TimeSeriesService timeSeriesService;
private final CommitService commitService; private final CommitService commitService;
private final GitRepositoryService gitRepositoryService;
private final BranchService branchService; private final BranchService branchService;
public EntityTS(TimeSeriesService timeSeriesService, public EntityTS(TimeSeriesService timeSeriesService,
CommitService commitService, CommitService commitService,
GitRepositoryService gitRepositoryService,
BranchService branchService) { BranchService branchService) {
this.timeSeriesService = timeSeriesService; this.timeSeriesService = timeSeriesService;
this.commitService = commitService; this.commitService = commitService;
this.gitRepositoryService = gitRepositoryService;
this.branchService = branchService; this.branchService = branchService;
} }
@Override @Override
public List<TimeSeries> getTimeSeries(Integer repositoryId, String branchName) { public List<TimeSeries> getTimeSeries(Branch branch) {
GitRepository gitRepository = gitRepositoryService.findById(repositoryId);
return Collections.singletonList( return Collections.singletonList(
new TimeSeries( new TimeSeries(
String.format("%s %s %s", String.format("%s %s %s",
gitRepository.getName(), branch.getGitRepository().getName(),
branchName, branch.getName(),
getTimeSeriesType().getDescription()), getTimeSeriesType().getDescription()),
branchService.findByRepositoryAndName(gitRepository, branchName), branchService.findByRepositoryAndName(branch.getGitRepository(), branch.getName()),
getTimeSeriesType(), getTimeSeriesType(),
commitService.findByRepositoryIdAndName(repositoryId, branchName) commitService.findByRepositoryIdAndName(branch.getGitRepository().getId(), branch.getName())
.stream() .stream()
.map(c -> new TimeSeriesValue(c.getDate(), findEntity(repositoryId, branchName))) .map(c -> new TimeSeriesValue(c.getDate(), findEntity(branch.getGitRepository().getId(), branch.getName())))
.collect(Collectors.toList()))); .collect(Collectors.toList())));
} }
@ -61,9 +57,9 @@ public class EntityTS extends AbstractTimeSeriesCreator {
} }
public Double findEntity(Integer repositoryId, String branchName) { public Double findEntity(Integer repositoryId, String branchName) {
List<ru.ulstu.extractor.model.Commit> commits = new ArrayList<>(commitService.findByRepositoryIdAndName(repositoryId, branchName)); List<Commit> commits = new ArrayList<>(commitService.findByRepositoryIdAndName(repositoryId, branchName));
double value = 0; double value = 0;
for (ru.ulstu.extractor.model.Commit commit : commits) { for (Commit commit : commits) {
for (FileChange fileChange : commit.getFileChanges()) { for (FileChange fileChange : commit.getFileChanges()) {
if ((fileChange.getContainsEntity() != null) && (fileChange.getContainsEntity())) { if ((fileChange.getContainsEntity() != null) && (fileChange.getContainsEntity())) {
value = value + 1; value = value + 1;

View File

@ -1,12 +1,11 @@
package ru.ulstu.extractor.ts.creator; package ru.ulstu.extractor.ts.creator.db;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.branch.service.BranchService; import ru.ulstu.extractor.branch.service.BranchService;
import ru.ulstu.extractor.commit.model.Commit;
import ru.ulstu.extractor.commit.service.CommitService; import ru.ulstu.extractor.commit.service.CommitService;
import ru.ulstu.extractor.gitrepository.model.FileChange; import ru.ulstu.extractor.gitrepository.model.FileChange;
import ru.ulstu.extractor.gitrepository.model.GitRepository;
import ru.ulstu.extractor.gitrepository.service.GitRepositoryService;
import ru.ulstu.extractor.model.Commit;
import ru.ulstu.extractor.ts.model.TimeSeries; import ru.ulstu.extractor.ts.model.TimeSeries;
import ru.ulstu.extractor.ts.model.TimeSeriesType; import ru.ulstu.extractor.ts.model.TimeSeriesType;
import ru.ulstu.extractor.ts.model.TimeSeriesValue; import ru.ulstu.extractor.ts.model.TimeSeriesValue;
@ -16,34 +15,32 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
@Component @Component
public class FileTS extends AbstractTimeSeriesCreator { public class FileTS extends DBTimeSeriesCreator {
private final TimeSeriesService timeSeriesService; private final TimeSeriesService timeSeriesService;
private final GitRepositoryService gitRepositoryService;
private final CommitService commitService; private final CommitService commitService;
private final BranchService branchService; private final BranchService branchService;
public FileTS(TimeSeriesService timeSeriesService, public FileTS(TimeSeriesService timeSeriesService,
GitRepositoryService gitRepositoryService,
CommitService commitService, CommitService commitService,
BranchService branchService) { BranchService branchService) {
this.timeSeriesService = timeSeriesService; this.timeSeriesService = timeSeriesService;
this.gitRepositoryService = gitRepositoryService;
this.commitService = commitService; this.commitService = commitService;
this.branchService = branchService; this.branchService = branchService;
} }
@Override @Override
public List<TimeSeries> getTimeSeries(Integer repositoryId, String branchName) { public List<TimeSeries> getTimeSeries(Branch branch) {
GitRepository gitRepository = gitRepositoryService.findById(repositoryId);
List<TimeSeries> timeSeriesResult = new ArrayList<>(); List<TimeSeries> timeSeriesResult = new ArrayList<>();
List<Commit> commits = new ArrayList<>(commitService.findByRepositoryIdAndName(repositoryId, branchName)); List<Commit> commits = new ArrayList<>(commitService.findByRepositoryIdAndName(branch.getGitRepository().getId(),
branch.getName()));
double value = 0; double value = 0;
TimeSeries timeSeries = new TimeSeries( TimeSeries timeSeries = new TimeSeries(
String.format("%s %s %s", String.format("%s %s %s",
gitRepository.getName(), branch.getGitRepository().getName(),
branchName, branch.getName(),
getTimeSeriesType().getDescription()), getTimeSeriesType().getDescription()),
branchService.findByRepositoryAndName(gitRepository, branchName), branchService.findByRepositoryAndName(branch.getGitRepository(),
branch.getName()),
getTimeSeriesType()); getTimeSeriesType());
for (Commit commit : commits) { for (Commit commit : commits) {
for (FileChange fileChange : commit.getFileChanges()) { for (FileChange fileChange : commit.getFileChanges()) {

View File

@ -1,9 +1,8 @@
package ru.ulstu.extractor.ts.creator; package ru.ulstu.extractor.ts.creator.db;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.branch.service.BranchService; import ru.ulstu.extractor.branch.service.BranchService;
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.TimeSeries;
import ru.ulstu.extractor.ts.model.TimeSeriesType; import ru.ulstu.extractor.ts.model.TimeSeriesType;
import ru.ulstu.extractor.ts.service.TimeSeriesService; import ru.ulstu.extractor.ts.service.TimeSeriesService;
@ -13,30 +12,25 @@ import java.util.Collections;
import java.util.List; import java.util.List;
@Component @Component
public class InterfaceTS extends AbstractTimeSeriesCreator { public class InterfaceTS extends DBTimeSeriesCreator {
private final TimeSeriesService timeSeriesService; private final TimeSeriesService timeSeriesService;
private final BranchService branchService; private final BranchService branchService;
private final GitRepositoryService gitRepositoryService;
public InterfaceTS(TimeSeriesService timeSeriesService, public InterfaceTS(TimeSeriesService timeSeriesService,
BranchService branchService, BranchService branchService) {
GitRepositoryService gitRepositoryService) {
this.timeSeriesService = timeSeriesService; this.timeSeriesService = timeSeriesService;
this.branchService = branchService; this.branchService = branchService;
this.gitRepositoryService = gitRepositoryService;
} }
@Override @Override
public List<TimeSeries> getTimeSeries(Integer repositoryId, String branchName) { public List<TimeSeries> getTimeSeries(Branch branch) {
GitRepository gitRepository = gitRepositoryService.findById(repositoryId);
return Collections.singletonList( return Collections.singletonList(
new TimeSeries( new TimeSeries(
String.format("%s %s %s", String.format("%s %s %s",
gitRepository.getName(), branch.getGitRepository().getName(),
branchName, branch.getName(),
getTimeSeriesType().getDescription()), getTimeSeriesType().getDescription()),
branchService.findByRepositoryAndName(gitRepository, branchName), branchService.findByRepositoryAndName(branch.getGitRepository(), branch.getName()),
getTimeSeriesType(), getTimeSeriesType(),
Dummy.getDefaultTimeSeries())); Dummy.getDefaultTimeSeries()));
} }

View File

@ -1,9 +1,8 @@
package ru.ulstu.extractor.ts.creator; package ru.ulstu.extractor.ts.creator.db;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.branch.service.BranchService; import ru.ulstu.extractor.branch.service.BranchService;
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.TimeSeries;
import ru.ulstu.extractor.ts.model.TimeSeriesType; import ru.ulstu.extractor.ts.model.TimeSeriesType;
import ru.ulstu.extractor.ts.service.TimeSeriesService; import ru.ulstu.extractor.ts.service.TimeSeriesService;
@ -13,30 +12,25 @@ import java.util.Collections;
import java.util.List; import java.util.List;
@Component @Component
public class ProcessTS extends AbstractTimeSeriesCreator { public class ProcessTS extends DBTimeSeriesCreator {
private final TimeSeriesService timeSeriesService; private final TimeSeriesService timeSeriesService;
private final BranchService branchService; private final BranchService branchService;
private final GitRepositoryService gitRepositoryService;
public ProcessTS(TimeSeriesService timeSeriesService, public ProcessTS(TimeSeriesService timeSeriesService,
BranchService branchService, BranchService branchService) {
GitRepositoryService gitRepositoryService) {
this.timeSeriesService = timeSeriesService; this.timeSeriesService = timeSeriesService;
this.branchService = branchService; this.branchService = branchService;
this.gitRepositoryService = gitRepositoryService;
} }
@Override @Override
public List<TimeSeries> getTimeSeries(Integer repositoryId, String branchName) { public List<TimeSeries> getTimeSeries(Branch branch) {
GitRepository gitRepository = gitRepositoryService.findById(repositoryId);
return Collections.singletonList( return Collections.singletonList(
new TimeSeries( new TimeSeries(
String.format("%s %s %s", String.format("%s %s %s",
gitRepository.getName(), branch.getGitRepository().getName(),
branchName, branch.getName(),
getTimeSeriesType().getDescription()), getTimeSeriesType().getDescription()),
branchService.findByRepositoryAndName(gitRepository, branchName), branchService.findByRepositoryAndName(branch.getGitRepository(), branch.getName()),
getTimeSeriesType(), getTimeSeriesType(),
Dummy.getDefaultTimeSeries())); Dummy.getDefaultTimeSeries()));
} }

View File

@ -0,0 +1,45 @@
package ru.ulstu.extractor.ts.creator.scheduled;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.gitrepository.service.GitRepositoryService;
import ru.ulstu.extractor.ts.model.TimeSeriesType;
import ru.ulstu.extractor.ts.model.TimeSeriesValue;
import ru.ulstu.extractor.ts.service.TimeSeriesService;
@Component
public class BranchTS extends ScheduledTimeSeriesCreator {
private final TimeSeriesService timeSeriesService;
private final GitRepositoryService gitRepositoryService;
private final ApplicationContext applicationContext;
public BranchTS(TimeSeriesService timeSeriesService,
GitRepositoryService gitRepositoryService,
ApplicationContext applicationContext) {
this.timeSeriesService = timeSeriesService;
this.gitRepositoryService = gitRepositoryService;
this.applicationContext = applicationContext;
}
@Override
public TimeSeriesType getTimeSeriesType() {
return TimeSeriesType.BRANCHES;
}
@Override
public TimeSeriesService getTimeSeriesService() {
return timeSeriesService;
}
@Override
public GitRepositoryService getGitRepositoryService() {
return gitRepositoryService;
}
@Override
public TimeSeriesValue getNewTimeSeriesValue(Branch branch) {
return new TimeSeriesValue(applicationContext.getBean(getGitRepositoryService().getGitApiServiceClass(branch))
.getBranchesCount(branch));
}
}

View File

@ -0,0 +1,45 @@
package ru.ulstu.extractor.ts.creator.scheduled;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.gitrepository.service.GitRepositoryService;
import ru.ulstu.extractor.ts.model.TimeSeriesType;
import ru.ulstu.extractor.ts.model.TimeSeriesValue;
import ru.ulstu.extractor.ts.service.TimeSeriesService;
@Component
public class IssuesTS extends ScheduledTimeSeriesCreator {
private final TimeSeriesService timeSeriesService;
private final ApplicationContext applicationContext;
private final GitRepositoryService gitRepositoryService;
public IssuesTS(TimeSeriesService timeSeriesService,
ApplicationContext applicationContext,
GitRepositoryService gitRepositoryService) {
this.timeSeriesService = timeSeriesService;
this.applicationContext = applicationContext;
this.gitRepositoryService = gitRepositoryService;
}
@Override
public TimeSeriesValue getNewTimeSeriesValue(Branch branch) {
return new TimeSeriesValue(applicationContext.getBean(getGitRepositoryService().getGitApiServiceClass(branch))
.getOpenIssuesCount(branch));
}
@Override
public TimeSeriesService getTimeSeriesService() {
return timeSeriesService;
}
@Override
public TimeSeriesType getTimeSeriesType() {
return TimeSeriesType.ISSUES;
}
@Override
public GitRepositoryService getGitRepositoryService() {
return gitRepositoryService;
}
}

View File

@ -0,0 +1,23 @@
package ru.ulstu.extractor.ts.creator.scheduled;
import org.springframework.transaction.annotation.Transactional;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.gitrepository.service.GitRepositoryService;
import ru.ulstu.extractor.ts.creator.AbstractTimeSeriesCreator;
import ru.ulstu.extractor.ts.model.TimeSeries;
import ru.ulstu.extractor.ts.model.TimeSeriesValue;
import java.util.Collections;
public abstract class ScheduledTimeSeriesCreator extends AbstractTimeSeriesCreator {
@Transactional
public void addTimeSeriesValue(Branch branch) {
TimeSeries timeSeries = getTimeSeriesService().findByBranchAndTypeOrCreate(branch, getTimeSeriesType());
timeSeries.getValues().add(getNewTimeSeriesValue(branch));
getTimeSeriesService().save(Collections.singletonList(timeSeries), branch);
}
public abstract TimeSeriesValue getNewTimeSeriesValue(Branch branch);
public abstract GitRepositoryService getGitRepositoryService();
}

View File

@ -0,0 +1,45 @@
package ru.ulstu.extractor.ts.creator.scheduled;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.gitrepository.service.GitRepositoryService;
import ru.ulstu.extractor.ts.model.TimeSeriesType;
import ru.ulstu.extractor.ts.model.TimeSeriesValue;
import ru.ulstu.extractor.ts.service.TimeSeriesService;
@Component
public class StarTS extends ScheduledTimeSeriesCreator {
private final TimeSeriesService timeSeriesService;
private final ApplicationContext applicationContext;
private final GitRepositoryService gitRepositoryService;
public StarTS(TimeSeriesService timeSeriesService,
ApplicationContext applicationContext,
GitRepositoryService gitRepositoryService) {
this.timeSeriesService = timeSeriesService;
this.applicationContext = applicationContext;
this.gitRepositoryService = gitRepositoryService;
}
@Override
public TimeSeriesService getTimeSeriesService() {
return timeSeriesService;
}
@Override
public TimeSeriesType getTimeSeriesType() {
return TimeSeriesType.STARS;
}
@Override
public GitRepositoryService getGitRepositoryService() {
return gitRepositoryService;
}
@Override
public TimeSeriesValue getNewTimeSeriesValue(Branch branch) {
return new TimeSeriesValue(applicationContext.getBean(getGitRepositoryService().getGitApiServiceClass(branch))
.getStarsCount(branch));
}
}

View File

@ -33,6 +33,13 @@ public class TimeSeries extends BaseEntity {
public TimeSeries() { public TimeSeries() {
} }
public TimeSeries(Branch branch, TimeSeriesType timeSeriesType) {
this(String.format("%s %s %s",
branch.getGitRepository().getName(),
branch.getName(),
timeSeriesType.getDescription()), branch, timeSeriesType);
}
public TimeSeries(String name, Branch branch, TimeSeriesType timeSeriesType) { public TimeSeries(String name, Branch branch, TimeSeriesType timeSeriesType) {
this(name, branch, timeSeriesType, new ArrayList<>()); this(name, branch, timeSeriesType, new ArrayList<>());
} }

View File

@ -7,7 +7,7 @@ public enum TimeSeriesType {
AUTHOR_COMPLETED_ISSUES("Временной ряд завершенных задач авторов"), AUTHOR_COMPLETED_ISSUES("Временной ряд завершенных задач авторов"),
AUTHORS("Временной ряд авторов"), AUTHORS("Временной ряд авторов"),
BRANCHES("Временной ряд веток"), BRANCHES("Временной ряд веток"),
CLASSES("Временной ряд кклассов"), CLASSES("Временной ряд классов"),
DEPENDENCIES("Временной ряд зависимостей"), DEPENDENCIES("Временной ряд зависимостей"),
ENTITIES("Временной ряд сущностей"), ENTITIES("Временной ряд сущностей"),
FILES("Временной файлов"), FILES("Временной файлов"),

View File

@ -18,6 +18,11 @@ public class TimeSeriesValue extends BaseEntity {
this.value = value; this.value = value;
} }
public TimeSeriesValue(Integer value) {
this.date = new Date();
this.value = Double.valueOf(value);
}
public TimeSeriesValue(TimeSeries timeSeries, Date date, Double value) { public TimeSeriesValue(TimeSeries timeSeries, Date date, Double value) {
this.date = date; this.date = date;
this.value = value; this.value = value;

View File

@ -1,7 +1,9 @@
package ru.ulstu.extractor.ts.repository; package ru.ulstu.extractor.ts.repository;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.ts.model.TimeSeries; import ru.ulstu.extractor.ts.model.TimeSeries;
import ru.ulstu.extractor.ts.model.TimeSeriesType;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -10,4 +12,6 @@ public interface TimeSeriesRepository extends JpaRepository<TimeSeries, Integer>
Optional<TimeSeries> findByName(String name); Optional<TimeSeries> findByName(String name);
List<TimeSeries> getTimeSeriesByBranchId(Integer branchId); List<TimeSeries> getTimeSeriesByBranchId(Integer branchId);
Optional<TimeSeries> getTimeSeriesByBranchAndTimeSeriesType(Branch branch, TimeSeriesType timeSeriesType);
} }

View File

@ -0,0 +1,34 @@
package ru.ulstu.extractor.ts.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.branch.service.BranchService;
import ru.ulstu.extractor.ts.creator.scheduled.ScheduledTimeSeriesCreator;
import java.util.List;
@Service
public class ScheduledTimeSeriesService {
private final Logger log = LoggerFactory.getLogger(ScheduledTimeSeriesService.class);
private final List<ScheduledTimeSeriesCreator> scheduledTimeSeriesCreators;
private final BranchService branchService;
public ScheduledTimeSeriesService(List<ScheduledTimeSeriesCreator> scheduledTimeSeriesCreators,
BranchService branchService) {
this.scheduledTimeSeriesCreators = scheduledTimeSeriesCreators;
this.branchService = branchService;
}
@Scheduled(cron = "0 0 8 * * *", zone = "Europe/Samara")
public void addTimeSeriesPoints() {
log.debug("Старт добавления новых точек временного ряда");
List<Branch> branches = branchService.findAll();
branches.forEach(branch -> {
scheduledTimeSeriesCreators.forEach(creator -> creator.addTimeSeriesValue(branch));
});
log.debug("Завершение добавления новых точек временного ряда");
}
}

View File

@ -5,6 +5,7 @@
package ru.ulstu.extractor.ts.service; package ru.ulstu.extractor.ts.service;
import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -25,10 +26,13 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Stream;
@Service @Service
public class TimeSeriesService { public class TimeSeriesService {
private final static Logger LOG = LoggerFactory.getLogger(TimeSeriesService.class); private final static Logger LOG = LoggerFactory.getLogger(TimeSeriesService.class);
private final static int MIN_TIME_SERIES_LENGTH = 5;
private final static double DEFAULT_TIME_SERIES_TENDENCY = 0.0;
private final TimeSeriesRepository timeSeriesRepository; private final TimeSeriesRepository timeSeriesRepository;
private final TimeSeriesValueRepository timeSeriesValueRepository; private final TimeSeriesValueRepository timeSeriesValueRepository;
private final TimeSeriesDateMapper.TimeSeriesInterval timeSeriesInterval = TimeSeriesDateMapper.TimeSeriesInterval.HOUR; private final TimeSeriesDateMapper.TimeSeriesInterval timeSeriesInterval = TimeSeriesDateMapper.TimeSeriesInterval.HOUR;
@ -46,19 +50,19 @@ public class TimeSeriesService {
@Transactional @Transactional
public TimeSeries save(String timeSeriesName, Branch branch, TimeSeriesType timeSeriesType, List<TimeSeriesValue> timeSeriesValues) { public TimeSeries save(String timeSeriesName, Branch branch, TimeSeriesType timeSeriesType, List<TimeSeriesValue> timeSeriesValues) {
LOG.debug("Start save {} time series with {} time series values ", timeSeriesName, timeSeriesValues.size()); LOG.debug("Начало сохранения временного ряда {} с {} значениями", timeSeriesName, timeSeriesValues.size());
final TimeSeries timeSeries = findOrCreate(timeSeriesName, branch, timeSeriesType); final TimeSeries timeSeries = findOrCreate(timeSeriesName, branch, timeSeriesType);
List<TimeSeriesValue> timeSeriesValuesToRemove = timeSeries.getValues(); List<TimeSeriesValue> timeSeriesValuesToRemove = timeSeries.getValues();
timeSeries.setValues(timeSeriesValues); timeSeries.setValues(timeSeriesValues);
LOG.debug("Save time series {} ", timeSeries.getName()); LOG.debug("Сохранение временного ряда {} ", timeSeries.getName());
TimeSeries savedTimeSeries = timeSeriesRepository.save(timeSeries); TimeSeries savedTimeSeries = timeSeriesRepository.save(timeSeries);
LOG.debug("Clear {} time series values ", timeSeriesValuesToRemove.size()); LOG.debug("Очистить {} точек временного ряда", timeSeriesValuesToRemove.size());
timeSeriesValueRepository.deleteAll(timeSeriesValuesToRemove); timeSeriesValueRepository.deleteAll(timeSeriesValuesToRemove);
sendToTimeSeriesService(savedTimeSeries); sendToTimeSeriesService(savedTimeSeries);
return savedTimeSeries; return savedTimeSeries;
} }
public TimeSeries findOrCreate(String timeSeriesName, Branch branch, TimeSeriesType timeSeriesType) { private TimeSeries findOrCreate(String timeSeriesName, Branch branch, TimeSeriesType timeSeriesType) {
Optional<TimeSeries> maybeTimeSeries = timeSeriesRepository.findByName(timeSeriesName); Optional<TimeSeries> maybeTimeSeries = timeSeriesRepository.findByName(timeSeriesName);
if (maybeTimeSeries.isPresent()) { if (maybeTimeSeries.isPresent()) {
LOG.debug("TimeSeries {} exists.", maybeTimeSeries.get().getName()); LOG.debug("TimeSeries {} exists.", maybeTimeSeries.get().getName());
@ -67,6 +71,15 @@ public class TimeSeriesService {
return timeSeriesRepository.save(new TimeSeries(timeSeriesName, branch, timeSeriesType)); return timeSeriesRepository.save(new TimeSeries(timeSeriesName, branch, timeSeriesType));
} }
public TimeSeries findByBranchAndTypeOrCreate(Branch branch, TimeSeriesType timeSeriesType) {
Optional<TimeSeries> maybeTimeSeries = timeSeriesRepository.getTimeSeriesByBranchAndTimeSeriesType(branch, timeSeriesType);
if (maybeTimeSeries.isPresent()) {
LOG.debug("TimeSeries {} exists.", maybeTimeSeries.get().getName());
return maybeTimeSeries.get();
}
return timeSeriesRepository.save(new TimeSeries(branch, timeSeriesType));
}
/** /**
* Сохранить список временных рядов * Сохранить список временных рядов
* *
@ -90,7 +103,7 @@ public class TimeSeriesService {
new Thread(() -> { new Thread(() -> {
try { try {
httpService.post(TIME_SERIES_SAVE_SERVICE_URL, new JSONObject(new JsonTimeSeries(timeSeries))); httpService.post(TIME_SERIES_SAVE_SERVICE_URL, new JSONObject(new JsonTimeSeries(timeSeries)));
LOG.debug("Успешно отправлен на сервис"); LOG.debug("{} успешно отправлен на сервис временных рядов", timeSeries.getName());
} catch (Exception ex) { } catch (Exception ex) {
LOG.debug(ex.getMessage()); LOG.debug(ex.getMessage());
} }
@ -103,7 +116,7 @@ public class TimeSeriesService {
public TimeSeries getById(Integer tsId) { public TimeSeries getById(Integer tsId) {
return timeSeriesRepository.findById(tsId) return timeSeriesRepository.findById(tsId)
.orElseThrow(() -> new RuntimeException("Time series not found by id " + tsId)); .orElseThrow(() -> new RuntimeException("Временной ряд не найден по идентификатору " + tsId));
} }
public List<TimeSeriesType> getAllTimeSeriesTypes() { public List<TimeSeriesType> getAllTimeSeriesTypes() {
@ -114,10 +127,23 @@ public class TimeSeriesService {
return timeSeriesRepository.getTimeSeriesByBranchId(branchId); return timeSeriesRepository.getTimeSeriesByBranchId(branchId);
} }
public Double getLastTimeSeriesTendency(TimeSeries ts) { public double getLastTimeSeriesTendency(TimeSeries ts) {
JSONObject response = httpService.post(TIME_SERIES_TENDENCY_URL, new JSONObject(new SmoothingTimeSeries(ts))); if (ts != null && ts.getValues().size() > MIN_TIME_SERIES_LENGTH) {
LOG.debug("Успешно отправлен на сервис сглаживания"); JSONObject response = httpService.post(TIME_SERIES_TENDENCY_URL, new JSONObject(new SmoothingTimeSeries(ts)));
response.get("timeSeries"); LOG.debug("Успешно отправлен на сервис сглаживания");
return 0.0; if (response.has("response") && response.getString("response").equals("empty")) {
return DEFAULT_TIME_SERIES_TENDENCY;
}
JSONArray jsonArray = response.getJSONObject("timeSeries").getJSONArray("values");
return jsonArray.getJSONObject(jsonArray.length() - 1).getDouble("value");
}
return DEFAULT_TIME_SERIES_TENDENCY;
}
public boolean isBranchContainsAllTimeSeries(Branch b) {
List<TimeSeries> timeSeries = getByBranch(b.getId());
return Stream.of(TimeSeriesType.values()).allMatch(type -> timeSeries
.stream()
.anyMatch(ts -> type == ts.getTimeSeriesType()));
} }
} }

View File

@ -9,6 +9,7 @@ import java.nio.file.FileSystems;
public class StringUtils { public class StringUtils {
public final static String EMPTY_STRING = ""; public final static String EMPTY_STRING = "";
public final static String SERVER_DOMAIN_PATTERN = "%s";
private final static String PATH_SEPARATOR = FileSystems.getDefault().getSeparator(); private final static String PATH_SEPARATOR = FileSystems.getDefault().getSeparator();
public static String addPathSeparator(String path) { public static String addPathSeparator(String path) {
@ -25,4 +26,19 @@ public class StringUtils {
public static boolean fileInSubdirectory(String filePath, String projectPath, String subDirectory) { public static boolean fileInSubdirectory(String filePath, String projectPath, String subDirectory) {
return filePath.startsWith(projectPath + PATH_SEPARATOR + subDirectory); return filePath.startsWith(projectPath + PATH_SEPARATOR + subDirectory);
} }
public static String getServerDomain(String url) {
String[] urlParts = url.split("/");
return urlParts[2];
}
public static String[] getUrlParts(String gitRepositoryUrl) {
return gitRepositoryUrl.split("/");
}
public static String removeDotGit(String repositoryName) {
return repositoryName.lastIndexOf(".git") > 0
? repositoryName.substring(0, repositoryName.lastIndexOf(".git"))
: repositoryName;
}
} }

View File

@ -11,6 +11,9 @@ logging.level.sun.rmi.transport=off
logging.level.javax.management.remote.rmi=off logging.level.javax.management.remote.rmi=off
logging.level.java.rmi.server=off logging.level.java.rmi.server=off
extractor.custom-projects-dir= extractor.custom-projects-dir=
server.error.include-stacktrace=always
server.error.include-exception=true
server.error.include-message=always
# Thymeleaf Settings # Thymeleaf Settings
spring.thymeleaf.cache=false spring.thymeleaf.cache=false
messages.basename.path=messages_en.properties messages.basename.path=messages_en.properties

View File

@ -99,4 +99,32 @@
OR branch_id is null; OR branch_id is null;
</sql> </sql>
</changeSet> </changeSet>
<changeSet author="orion" id="20230207-220000-1">
<addColumn tableName="branch">
<column name="indexing_status" type="varchar(100)"/>
</addColumn>
<update tableName="branch">
<column name="indexing_status" value="FINISHED"/>
</update>
</changeSet>
<changeSet author="orion" id="20230220-120000-1">
<addColumn tableName="git_repository">
<column name="repository_id" type="varchar(100)"/>
</addColumn>
</changeSet>
<changeSet author="orion" id="20230220-120000-2">
<dropForeignKeyConstraint baseTableName="time_series"
constraintName="fk_time_series_branch"/>
<addForeignKeyConstraint baseTableName="time_series" baseColumnNames="branch_id"
constraintName="fk_time_series_branch" referencedTableName="branch"
referencedColumnNames="id" onDelete="CASCADE"/>
</changeSet>
<changeSet author="orion" id="20230220-120000-3">
<dropForeignKeyConstraint baseTableName="time_series_value"
constraintName="fk_time_series"/>
<addForeignKeyConstraint baseTableName="time_series_value" baseColumnNames="time_series_id"
constraintName="fk_time_series"
referencedTableName="time_series"
referencedColumnNames="id" onDelete="CASCADE"/>
</changeSet>
</databaseChangeLog> </databaseChangeLog>

View File

@ -7,7 +7,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head> </head>
<div class="container" layout:fragment="content"> <div class="container" layout:fragment="content">
<form action="#" th:action="${@route.RECOMMENDATIONS}" th:object="${filterBranchForm}" method="get"> <form action="#" th:action="${@route.ASSESSMENTS}" th:object="${filterBranchForm}" method="get">
<div class="row"> <div class="row">
<div class="col-md-2 col-sm-12"> <div class="col-md-2 col-sm-12">
Репозиторий-ветка Репозиторий-ветка
@ -26,17 +26,27 @@
]) ])
; ;
$('#select-branch').selectpicker('refresh'); $('#select-branch').selectpicker('refresh');
</script> </script>
</div> </div>
<input type="submit" class="btn btn-outline-success w-100" value="Применить фильтр"/> <input type="submit" class="btn btn-outline-success w-100" value="Применить фильтр"/>
</div> </div>
<div th:if="*{branchId == null}">Выбрерите ветку для получения рекомендаций</div> <div th:if="*{branchId == null}">Выбрерите ветку для получения оценки репозитория</div>
<input type="hidden" th:field="*{branchId}"> <input type="hidden" th:field="*{branchId}">
</form> </form>
<div th:each="recommendation: ${recommendations}"> <div th:if="${assessments != null && #lists.size(assessments) > 0}">
<div th:text="${recommendation}"></div> <h5>Состояние репозитория описывается следующими выражениями:</h5>
<div th:each="assessment: ${assessments}">
<span th:text="${assessment.consequent}"></span>
вследствие тенденции '<span th:text="${assessment.firstAntecedentTendency}"></span>' показателя '<span
th:text="${assessment.firstAntecedent.description}"></span>'
и тенденции '<span th:text="${assessment.secondAntecedentTendency}"></span>' показателя '<span
th:text="${assessment.secondAntecedent.description}"></span>';
<span class="badge badge-warning" th:text="${assessment.degree}"></span>
</div>
</div>
<div th:if="${assessments != null && #lists.size(assessments) == 0}">
<h5>Нет результатов</h5>
</div> </div>
</div> </div>
</html> </html>

View File

@ -41,7 +41,7 @@
<a class="nav-link" href="/listRules" th:text="Правила">Link</a> <a class="nav-link" href="/listRules" th:text="Правила">Link</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="/recommendations" th:text="Рекомендации">Link</a> <a class="nav-link" href="/assessments" th:text="Рекомендации">Link</a>
</li> </li>
</ul> </ul>
</div> </div>

View File

@ -32,16 +32,26 @@
</p> </p>
<div class="collapse" id="collapseExample"> <div class="collapse" id="collapseExample">
<p class="card card-body"> <p class="card card-body">
<div th:utext="'Failed URL: ' + ${url}" th:remove="tag">${url}</div> <div>
</p> <span><strong>Status</strong></span>
<div th:if="${exception != null}" th:utext="'Exception: ' + ${exception.message}" th:remove="tag"> <span th:text="${status}"></span>
${exception.message} </div>
<div>
<span><strong>Error</strong></span>
<span th:text="${error}"></span>
</div>
<div>
<span><strong>Message</strong></span>
<span th:text="${message}"></span>
</div>
<div th:if="${exception != null}">
<span><strong>Exception</strong></span>
<span th:text="${exception}"></span>
</div>
<div th:if="${trace != null}">
<span><strong>Stacktrace</strong></span>
<span th:text="${trace}"></span>
</div> </div>
<ul th:remove="tag">
<li th:if="${exception != null && exception.stackTrace != null}" th:each="ste : ${exception.stackTrace}"
th:remove="tag"><span
th:utext="${ste}" th:remove="tag">${ste}</span></li>
</ul>
</div> </div>
</div> </div>
</div> </div>

View File

@ -12,17 +12,25 @@
<thead class="thead-dark"> <thead class="thead-dark">
<tr> <tr>
<th scope="col">Ветки</th> <th scope="col">Ветки</th>
<th width="10%"></th> <th width="20%"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr th:each="branch: ${branches}"> <tr th:each="branch: ${branches}">
<td> <td>
<a th:href="@{${@route.FILTER_COMMITS} + '?branchName='+${branch.name}+'&repositoryUrl='+${repository.url}}" <a th:href="@{${@route.FILTER_COMMITS} + '?branchName='+${branch.name}+'&repositoryUrl='+${repository.url}}"
th:text="${branch.name}"/> th:text="${branch.name}"></a>
</td> </td>
<td> <td>
<a role="button" class="btn btn-danger" <a role="button" class="btn btn-primary" title="Повторить индексацию ветки"
th:if="${branch.indexingStatus.name() != 'INDEXING'}"
th:href="@{'reindexBranch?branchId=' + ${branch.id}}">
<i class="fa fa-repeat" aria-hidden="true"></i>
</a>
<a role="button" class="btn btn-dark disabled"
th:if="${branch.indexingStatus.name() == 'INDEXING'}">Индексируется...
</a>
<a role="button" class="btn btn-danger" th:if="${branch.indexingStatus.name() != 'INDEXING'}"
th:href="@{'deleteBranch?id=' + ${branch.id} + '&repositoryId='+${repository.id}}" th:href="@{'deleteBranch?id=' + ${branch.id} + '&repositoryId='+${repository.id}}"
onclick="return confirm('Удалить ветку?')"> onclick="return confirm('Удалить ветку?')">
<i class="fa fa-times" aria-hidden="true"></i> <i class="fa fa-times" aria-hidden="true"></i>

View File

@ -0,0 +1,24 @@
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:th="http://www.w3.org/1999/xhtml"
layout:decorate="~{default}">
<head>
<title>Простая обработка формы на Spring MVC</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<div class="container" layout:fragment="content">
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th scope="col" colspan="10">Разметка временных рядов</th>
</tr>
</thead>
<tbody>
<tr th:each="t: ${ts}">
<td><span class="badge badge-success" th:text="${t.name}"></span></td>
<td><span class="badge badge-success" th:text="${#lists.size(t.values)}"></span></td>
</tr>
</tbody>
</table>
</div>
</html>

View File

@ -2,7 +2,9 @@ package ru.ulstu;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import ru.ulstu.extractor.branch.model.Branch;
import ru.ulstu.extractor.ts.model.TimeSeries; import ru.ulstu.extractor.ts.model.TimeSeries;
import ru.ulstu.extractor.ts.model.TimeSeriesType;
import ru.ulstu.extractor.ts.model.TimeSeriesValue; import ru.ulstu.extractor.ts.model.TimeSeriesValue;
import ru.ulstu.extractor.ts.util.TimeSeriesDateMapper; import ru.ulstu.extractor.ts.util.TimeSeriesDateMapper;
@ -17,13 +19,13 @@ public class TimeSeriesMapperTest {
c1.set(2020, 5, 1, 1, 1, 1); c1.set(2020, 5, 1, 1, 1, 1);
Calendar c2 = GregorianCalendar.getInstance(); Calendar c2 = GregorianCalendar.getInstance();
c2.set(2020, 5, 2, 2, 1, 1); c2.set(2020, 5, 2, 2, 1, 1);
TimeSeries timeSeries = new TimeSeries("Тестовый", TimeSeries timeSeries = new TimeSeries("Тестовый", new Branch(), TimeSeriesType.COMMITS,
Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0), Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0),
new TimeSeriesValue(c2.getTime(), 10.0))); new TimeSeriesValue(c2.getTime(), 10.0)));
TimeSeriesDateMapper mapper = new TimeSeriesDateMapper(); TimeSeriesDateMapper mapper = new TimeSeriesDateMapper();
timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.MONTH, timeSeries); timeSeries = TimeSeriesDateMapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.MONTH, timeSeries);
Assert.assertEquals(1, timeSeries.getValues().size()); Assert.assertEquals(1, timeSeries.getValues().size());
Assert.assertEquals(Integer.valueOf(20), timeSeries.getValues().get(0).getValue()); Assert.assertEquals(Double.valueOf(20), timeSeries.getValues().get(0).getValue());
} }
@Test @Test
@ -32,13 +34,13 @@ public class TimeSeriesMapperTest {
c1.set(2020, 5, 1, 1, 1, 1); c1.set(2020, 5, 1, 1, 1, 1);
Calendar c2 = GregorianCalendar.getInstance(); Calendar c2 = GregorianCalendar.getInstance();
c2.set(2020, 5, 2, 1, 1, 1); c2.set(2020, 5, 2, 1, 1, 1);
TimeSeries timeSeries = new TimeSeries("Тестовый", TimeSeries timeSeries = new TimeSeries("Тестовый", new Branch(), TimeSeriesType.COMMITS,
Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0), Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0),
new TimeSeriesValue(c2.getTime(), 10.0))); new TimeSeriesValue(c2.getTime(), 10.0)));
TimeSeriesDateMapper mapper = new TimeSeriesDateMapper(); TimeSeriesDateMapper mapper = new TimeSeriesDateMapper();
timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.MONTH, timeSeries); timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.MONTH, timeSeries);
Assert.assertEquals(1, timeSeries.getValues().size()); Assert.assertEquals(1, timeSeries.getValues().size());
Assert.assertEquals(Integer.valueOf(20), timeSeries.getValues().get(0).getValue()); Assert.assertEquals(Double.valueOf(20), timeSeries.getValues().get(0).getValue());
} }
@Test @Test
@ -47,13 +49,13 @@ public class TimeSeriesMapperTest {
c1.set(2020, 5, 1, 1, 1, 1); c1.set(2020, 5, 1, 1, 1, 1);
Calendar c2 = GregorianCalendar.getInstance(); Calendar c2 = GregorianCalendar.getInstance();
c2.set(2020, 5, 2, 1, 1, 1); c2.set(2020, 5, 2, 1, 1, 1);
TimeSeries timeSeries = new TimeSeries("Тестовый", TimeSeries timeSeries = new TimeSeries("Тестовый", new Branch(), TimeSeriesType.COMMITS,
Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0), Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0),
new TimeSeriesValue(c2.getTime(), 10.0))); new TimeSeriesValue(c2.getTime(), 10.0)));
TimeSeriesDateMapper mapper = new TimeSeriesDateMapper(); TimeSeriesDateMapper mapper = new TimeSeriesDateMapper();
timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.MONTH, timeSeries); timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.MONTH, timeSeries);
Assert.assertEquals(1, timeSeries.getValues().size()); Assert.assertEquals(1, timeSeries.getValues().size());
Assert.assertEquals(Integer.valueOf(20), timeSeries.getValues().get(0).getValue()); Assert.assertEquals(Double.valueOf(20), timeSeries.getValues().get(0).getValue());
} }
@Test @Test
@ -62,13 +64,13 @@ public class TimeSeriesMapperTest {
c1.set(2020, 5, 1, 1, 1, 1); c1.set(2020, 5, 1, 1, 1, 1);
Calendar c2 = GregorianCalendar.getInstance(); Calendar c2 = GregorianCalendar.getInstance();
c2.set(2020, 6, 2, 1, 1, 1); c2.set(2020, 6, 2, 1, 1, 1);
TimeSeries timeSeries = new TimeSeries("Тестовый", TimeSeries timeSeries = new TimeSeries("Тестовый", new Branch(), TimeSeriesType.COMMITS,
Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0), Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0),
new TimeSeriesValue(c2.getTime(), 10.0))); new TimeSeriesValue(c2.getTime(), 10.0)));
TimeSeriesDateMapper mapper = new TimeSeriesDateMapper(); TimeSeriesDateMapper mapper = new TimeSeriesDateMapper();
timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.MONTH, timeSeries); timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.MONTH, timeSeries);
Assert.assertEquals(2, timeSeries.getValues().size()); Assert.assertEquals(2, timeSeries.getValues().size());
Assert.assertEquals(Integer.valueOf(10), timeSeries.getValues().get(0).getValue()); Assert.assertEquals(Double.valueOf(10), timeSeries.getValues().get(0).getValue());
} }
@Test @Test
@ -77,13 +79,13 @@ public class TimeSeriesMapperTest {
c1.set(2020, 5, 1, 1, 1, 1); c1.set(2020, 5, 1, 1, 1, 1);
Calendar c2 = GregorianCalendar.getInstance(); Calendar c2 = GregorianCalendar.getInstance();
c2.set(2020, 5, 2, 1, 1, 1); c2.set(2020, 5, 2, 1, 1, 1);
TimeSeries timeSeries = new TimeSeries("Тестовый", TimeSeries timeSeries = new TimeSeries("Тестовый", new Branch(), TimeSeriesType.COMMITS,
Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0), Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0),
new TimeSeriesValue(c2.getTime(), 10.0))); new TimeSeriesValue(c2.getTime(), 10.0)));
TimeSeriesDateMapper mapper = new TimeSeriesDateMapper(); TimeSeriesDateMapper mapper = new TimeSeriesDateMapper();
timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.YEAR, timeSeries); timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.YEAR, timeSeries);
Assert.assertEquals(1, timeSeries.getValues().size()); Assert.assertEquals(1, timeSeries.getValues().size());
Assert.assertEquals(Integer.valueOf(20), timeSeries.getValues().get(0).getValue()); Assert.assertEquals(Double.valueOf(20), timeSeries.getValues().get(0).getValue());
} }
@Test @Test
@ -92,12 +94,12 @@ public class TimeSeriesMapperTest {
c1.set(2020, 5, 1, 1, 1, 1); c1.set(2020, 5, 1, 1, 1, 1);
Calendar c2 = GregorianCalendar.getInstance(); Calendar c2 = GregorianCalendar.getInstance();
c2.set(2021, 5, 2, 1, 1, 1); c2.set(2021, 5, 2, 1, 1, 1);
TimeSeries timeSeries = new TimeSeries("Тестовый", TimeSeries timeSeries = new TimeSeries("Тестовый", new Branch(), TimeSeriesType.COMMITS,
Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0), Arrays.asList(new TimeSeriesValue(c1.getTime(), 10.0),
new TimeSeriesValue(c2.getTime(), 10.0))); new TimeSeriesValue(c2.getTime(), 10.0)));
TimeSeriesDateMapper mapper = new TimeSeriesDateMapper(); TimeSeriesDateMapper mapper = new TimeSeriesDateMapper();
timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.YEAR, timeSeries); timeSeries = mapper.mapTimeSeriesToInterval(TimeSeriesDateMapper.TimeSeriesInterval.YEAR, timeSeries);
Assert.assertEquals(2, timeSeries.getValues().size()); Assert.assertEquals(2, timeSeries.getValues().size());
Assert.assertEquals(Integer.valueOf(10), timeSeries.getValues().get(0).getValue()); Assert.assertEquals(Double.valueOf(10), timeSeries.getValues().get(0).getValue());
} }
} }