diff --git a/bitbucket-app/src/main/java/org/sadtech/bot/vcs/bitbucket/app/scheduler/RatingScheduler.java b/bitbucket-app/src/main/java/org/sadtech/bot/vcs/bitbucket/app/scheduler/RatingScheduler.java
new file mode 100644
index 0000000..8855191
--- /dev/null
+++ b/bitbucket-app/src/main/java/org/sadtech/bot/vcs/bitbucket/app/scheduler/RatingScheduler.java
@@ -0,0 +1,25 @@
+package org.sadtech.bot.vcs.bitbucket.app.scheduler;
+
+/**
+ * // TODO: 01.10.2020 Добавить описание.
+ *
+ * @author upagge 01.10.2020
+ */
+
+import lombok.RequiredArgsConstructor;
+import org.sadtech.bot.vcs.core.service.RatingService;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class RatingScheduler {
+
+ private final RatingService ratingService;
+
+ @Scheduled(cron = "0 */1 * * * *")
+ private void ratingRecalculation() {
+ ratingService.ratingRecalculation();
+ }
+
+}
diff --git a/bitbucket-app/src/main/resources/application-dev.yaml b/bitbucket-app/src/main/resources/application-dev.yaml
index 2f6f089..b803227 100644
--- a/bitbucket-app/src/main/resources/application-dev.yaml
+++ b/bitbucket-app/src/main/resources/application-dev.yaml
@@ -25,7 +25,7 @@ bitbucketbot:
comment-count: 100
init:
start-comment-id: 8157
- use: false
+ use: true
bitbucket:
token: ${BITBUCKET_ADMIN_TOKEN}
url-pull-request-open: http://192.168.236.164:7990/rest/api/1.0/dashboard/pull-requests?limit=150&state=OPEN
diff --git a/bitbucket-app/src/main/resources/liquibase/v.2.0.0/2020-10-01-rating.xml b/bitbucket-app/src/main/resources/liquibase/v.2.0.0/2020-10-01-rating.xml
index 95711a7..e41bb20 100644
--- a/bitbucket-app/src/main/resources/liquibase/v.2.0.0/2020-10-01-rating.xml
+++ b/bitbucket-app/src/main/resources/liquibase/v.2.0.0/2020-10-01-rating.xml
@@ -22,4 +22,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bot-core/src/main/java/org/sadtech/bot/vcs/core/domain/entity/RatingList.java b/bot-core/src/main/java/org/sadtech/bot/vcs/core/domain/entity/RatingList.java
index c4c9d12..90aa74d 100644
--- a/bot-core/src/main/java/org/sadtech/bot/vcs/core/domain/entity/RatingList.java
+++ b/bot-core/src/main/java/org/sadtech/bot/vcs/core/domain/entity/RatingList.java
@@ -1,31 +1,42 @@
-//package org.sadtech.bot.vcs.core.domain.entity;
-//
-//import lombok.EqualsAndHashCode;
-//import lombok.Getter;
-//import lombok.Setter;
-//
-//import javax.persistence.Column;
-//import javax.persistence.Entity;
-//import javax.persistence.Table;
-//
-///**
-// * // TODO: 01.10.2020 Добавить описание.
-// *
-// * @author upagge 01.10.2020
-// */
-//
-//@Getter
-//@Setter
-//@Entity
-//@Table(name = "rating_list")
-//@EqualsAndHashCode(onlyExplicitlyIncluded = true)
-//public class RatingList {
-//
-// @Column(name = "login")
-// @EqualsAndHashCode.Include
-// private String login;
-//
-// @Column(name = "points")
-// private Integer points;
-//
-//}
+package org.sadtech.bot.vcs.core.domain.entity;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+import org.jetbrains.annotations.NotNull;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * // TODO: 01.10.2020 Добавить описание.
+ *
+ * @author upagge 01.10.2020
+ */
+
+@Getter
+@Setter
+@Entity
+@Table(name = "rating_list")
+@EqualsAndHashCode(onlyExplicitlyIncluded = true)
+public class RatingList implements Comparable {
+
+ @Id
+ @Column(name = "login")
+ @EqualsAndHashCode.Include
+ private String login;
+
+ @Column(name = "points")
+ private Integer points;
+
+ @Column(name = "number")
+ private Integer number;
+
+ @Override
+ public int compareTo(@NotNull RatingList ratingList) {
+ return Integer.compare(ratingList.getPoints(), points);
+ }
+
+}
diff --git a/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/RatingHistoryRepository.java b/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/RatingHistoryRepository.java
index d962b53..e03b5a6 100644
--- a/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/RatingHistoryRepository.java
+++ b/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/RatingHistoryRepository.java
@@ -1,8 +1,12 @@
package org.sadtech.bot.vcs.core.repository;
+import lombok.NonNull;
import org.sadtech.basic.context.repository.SimpleManagerRepository;
import org.sadtech.bot.vcs.core.domain.entity.RatingHistory;
+import java.time.LocalDateTime;
+import java.util.List;
+
/**
* // TODO: 01.10.2020 Добавить описание.
*
@@ -10,4 +14,6 @@ import org.sadtech.bot.vcs.core.domain.entity.RatingHistory;
*/
public interface RatingHistoryRepository extends SimpleManagerRepository {
+ List findAllByDateAddBetween(@NonNull LocalDateTime from, @NonNull LocalDateTime to);
+
}
diff --git a/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/RatingListRepository.java b/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/RatingListRepository.java
new file mode 100644
index 0000000..11a9115
--- /dev/null
+++ b/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/RatingListRepository.java
@@ -0,0 +1,24 @@
+package org.sadtech.bot.vcs.core.repository;
+
+import org.sadtech.basic.context.repository.SimpleManagerRepository;
+import org.sadtech.bot.vcs.core.domain.entity.RatingList;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * // TODO: 01.10.2020 Добавить описание.
+ *
+ * @author upagge 01.10.2020
+ */
+public interface RatingListRepository extends SimpleManagerRepository {
+
+ Optional getByLogin(String login);
+
+ List findFirstThree();
+
+ List findLastThree();
+
+ long count();
+
+}
diff --git a/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/impl/RatingHistoryRepositoryImpl.java b/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/impl/RatingHistoryRepositoryImpl.java
index 4ea02b1..eb57c5c 100644
--- a/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/impl/RatingHistoryRepositoryImpl.java
+++ b/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/impl/RatingHistoryRepositoryImpl.java
@@ -1,11 +1,15 @@
package org.sadtech.bot.vcs.core.repository.impl;
+import lombok.NonNull;
import org.sadtech.basic.database.repository.manager.AbstractSimpleManagerRepository;
import org.sadtech.bot.vcs.core.domain.entity.RatingHistory;
import org.sadtech.bot.vcs.core.repository.RatingHistoryRepository;
import org.sadtech.bot.vcs.core.repository.jpa.RatingHistoryJpaRepository;
import org.springframework.stereotype.Repository;
+import java.time.LocalDateTime;
+import java.util.List;
+
/**
* // TODO: 01.10.2020 Добавить описание.
*
@@ -21,4 +25,9 @@ public class RatingHistoryRepositoryImpl extends AbstractSimpleManagerRepository
this.jpaRepository = jpaRepository;
}
+ @Override
+ public List findAllByDateAddBetween(@NonNull LocalDateTime from, @NonNull LocalDateTime to) {
+ return jpaRepository.findAllByDateAddBetween(from, to);
+ }
+
}
diff --git a/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/impl/RatingListRepositoryImpl.java b/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/impl/RatingListRepositoryImpl.java
new file mode 100644
index 0000000..91becbd
--- /dev/null
+++ b/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/impl/RatingListRepositoryImpl.java
@@ -0,0 +1,53 @@
+package org.sadtech.bot.vcs.core.repository.impl;
+
+import org.sadtech.basic.database.repository.manager.AbstractSimpleManagerRepository;
+import org.sadtech.bot.vcs.core.domain.entity.RatingList;
+import org.sadtech.bot.vcs.core.repository.RatingListRepository;
+import org.sadtech.bot.vcs.core.repository.jpa.RatingListJpaRepository;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * // TODO: 01.10.2020 Добавить описание.
+ *
+ * @author upagge 01.10.2020
+ */
+@Repository
+public class RatingListRepositoryImpl extends AbstractSimpleManagerRepository implements RatingListRepository {
+
+ private final RatingListJpaRepository jpaRepository;
+
+ public RatingListRepositoryImpl(RatingListJpaRepository jpaRepository) {
+ super(jpaRepository);
+ this.jpaRepository = jpaRepository;
+ }
+
+ @Override
+ public Optional getByLogin(String login) {
+ return jpaRepository.findById(login);
+ }
+
+ @Override
+ public List findFirstThree() {
+ return jpaRepository.findAll(
+ PageRequest.of(0, 3, Sort.by(Sort.Direction.ASC, "number"))
+ ).getContent();
+ }
+
+ @Override
+ public List findLastThree() {
+ return jpaRepository.findAll(
+ PageRequest.of(0, 3, Sort.by(Sort.Direction.DESC, "number"))
+ ).getContent();
+ }
+
+ @Override
+ public long count() {
+ return jpaRepository.count();
+ }
+
+}
diff --git a/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/jpa/RatingHistoryJpaRepository.java b/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/jpa/RatingHistoryJpaRepository.java
index 9d1ee0b..22fe0ce 100644
--- a/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/jpa/RatingHistoryJpaRepository.java
+++ b/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/jpa/RatingHistoryJpaRepository.java
@@ -3,6 +3,9 @@ package org.sadtech.bot.vcs.core.repository.jpa;
import org.sadtech.bot.vcs.core.domain.entity.RatingHistory;
import org.springframework.data.jpa.repository.JpaRepository;
+import java.time.LocalDateTime;
+import java.util.List;
+
/**
* // TODO: 01.10.2020 Добавить описание.
*
@@ -10,4 +13,6 @@ import org.springframework.data.jpa.repository.JpaRepository;
*/
public interface RatingHistoryJpaRepository extends JpaRepository {
+ List findAllByDateAddBetween(LocalDateTime from, LocalDateTime to);
+
}
diff --git a/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/jpa/RatingListJpaRepository.java b/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/jpa/RatingListJpaRepository.java
new file mode 100644
index 0000000..2b0a662
--- /dev/null
+++ b/bot-core/src/main/java/org/sadtech/bot/vcs/core/repository/jpa/RatingListJpaRepository.java
@@ -0,0 +1,13 @@
+package org.sadtech.bot.vcs.core.repository.jpa;
+
+import org.sadtech.bot.vcs.core.domain.entity.RatingList;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+/**
+ * // TODO: 01.10.2020 Добавить описание.
+ *
+ * @author upagge 01.10.2020
+ */
+public interface RatingListJpaRepository extends JpaRepository {
+
+}
diff --git a/bot-core/src/main/java/org/sadtech/bot/vcs/core/service/RatingService.java b/bot-core/src/main/java/org/sadtech/bot/vcs/core/service/RatingService.java
index 53c1b81..a52c01b 100644
--- a/bot-core/src/main/java/org/sadtech/bot/vcs/core/service/RatingService.java
+++ b/bot-core/src/main/java/org/sadtech/bot/vcs/core/service/RatingService.java
@@ -12,4 +12,8 @@ public interface RatingService {
void addRating(@NonNull String login, @NonNull PointType type, @NonNull Integer points);
+ void ratingRecalculation();
+
+ String getRatingTop(@NonNull String login);
+
}
diff --git a/bot-core/src/main/java/org/sadtech/bot/vcs/core/service/impl/RatingServiceImpl.java b/bot-core/src/main/java/org/sadtech/bot/vcs/core/service/impl/RatingServiceImpl.java
index 60ca6a7..d9ddb3c 100644
--- a/bot-core/src/main/java/org/sadtech/bot/vcs/core/service/impl/RatingServiceImpl.java
+++ b/bot-core/src/main/java/org/sadtech/bot/vcs/core/service/impl/RatingServiceImpl.java
@@ -4,11 +4,19 @@ import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.sadtech.bot.vcs.core.domain.PointType;
import org.sadtech.bot.vcs.core.domain.entity.RatingHistory;
+import org.sadtech.bot.vcs.core.domain.entity.RatingList;
+import org.sadtech.bot.vcs.core.exception.NotFoundException;
import org.sadtech.bot.vcs.core.repository.RatingHistoryRepository;
+import org.sadtech.bot.vcs.core.repository.RatingListRepository;
import org.sadtech.bot.vcs.core.service.RatingService;
+import org.sadtech.bot.vcs.core.utils.Smile;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
/**
* // TODO: 01.10.2020 Добавить описание.
@@ -20,6 +28,7 @@ import java.time.LocalDateTime;
public class RatingServiceImpl implements RatingService {
private final RatingHistoryRepository ratingHistoryRepository;
+ private final RatingListRepository ratingListRepository;
@Override
public void addRating(@NonNull String login, @NonNull PointType type, @NonNull Integer points) {
@@ -31,4 +40,67 @@ public class RatingServiceImpl implements RatingService {
ratingHistoryRepository.save(ratingHistory);
}
+ @Override
+ public void ratingRecalculation() {
+ AtomicInteger i = new AtomicInteger();
+ final List newRatingList = ratingHistoryRepository.findAllByDateAddBetween(LocalDateTime.now().minusDays(30L), LocalDateTime.now()).stream()
+ .collect(Collectors.groupingBy(RatingHistory::getLogin, Collectors.summingInt(RatingHistory::getPoints)))
+ .entrySet().stream()
+ .map(this::createRatingList)
+ .sorted()
+ .peek(ratingList -> ratingList.setNumber(i.getAndIncrement()))
+ .collect(Collectors.toList());
+ ratingListRepository.saveAll(newRatingList);
+ }
+
+ private RatingList createRatingList(Map.Entry entry) {
+ final RatingList ratingList = new RatingList();
+ ratingList.setLogin(entry.getKey());
+ ratingList.setPoints(entry.getValue());
+ return ratingList;
+ }
+
+ @Override
+ public String getRatingTop(@NonNull String login) {
+ final RatingList personRating = ratingListRepository.getByLogin(login)
+ .orElseThrow(() -> new NotFoundException("Пользователь не найден"));
+ final Integer numberRatingList = personRating.getNumber();
+ final long countPerson = ratingListRepository.count();
+ final String threeMessage = ratingListRepository.findFirstThree().stream()
+ .map(this::createString)
+ .collect(Collectors.joining("\n"));
+ final String lastMessage = ratingListRepository.findLastThree().stream()
+ .map(this::createString)
+ .limit(countPerson - 3)
+ .collect(Collectors.joining("\n"));
+ String message = threeMessage;
+
+ if (numberRatingList <= 2) {
+ if (countPerson > 3) {
+ message += "\n... ... ...\n";
+ }
+ } else if (numberRatingList > 3 && numberRatingList <= (countPerson - 3)) {
+ message += "\n... ... ...\n" + personRating.getNumber() + ": " + personRating.getLogin() + "\n... ... ...\n";
+ } else {
+ message += "\n... ... ...\n";
+ }
+ message += lastMessage;
+ return message;
+ }
+
+ private String createString(RatingList ratingList) {
+ String message = "";
+ final Integer number = ratingList.getNumber();
+ if (number == 0) {
+ message += Smile.TOP_ONE + " " + ratingList.getLogin() + " " + Smile.TOP_ONE;
+ } else if (number == 1) {
+ message += Smile.TOP_TWO + " " + ratingList.getLogin() + " " + Smile.TOP_TWO;
+ } else if (number == 2) {
+ message += Smile.TOP_THREE + " " + ratingList.getLogin() + " " + Smile.TOP_THREE;
+ } else {
+ message += Smile.KAKASHKA + " " + ratingList.getLogin();
+ }
+ return message;
+ }
+
}
diff --git a/bot-core/src/main/java/org/sadtech/bot/vcs/core/utils/Smile.java b/bot-core/src/main/java/org/sadtech/bot/vcs/core/utils/Smile.java
index 8da9305..4ea12f5 100644
--- a/bot-core/src/main/java/org/sadtech/bot/vcs/core/utils/Smile.java
+++ b/bot-core/src/main/java/org/sadtech/bot/vcs/core/utils/Smile.java
@@ -27,6 +27,10 @@ public enum Smile {
DAY_4("\uD83C\uDF11"),
DAY_5("\uD83C\uDF1A"),
TASK("\uD83D\uDCBC"),
+ TOP_ONE("\uD83C\uDF1F\uD83C\uDF1F\uD83C\uDF1F"),
+ TOP_TWO("\uD83D\uDE0E"),
+ TOP_THREE("\uD83E\uDD49"),
+ KAKASHKA("\uD83D\uDCA9"),
MEGA_FUN("\uD83D\uDE02"),
DANGEROUS("⚠️"),
BELL("\uD83D\uDECE"),
diff --git a/telegram-bot/src/main/java/org/sadtech/bot/vcs/telegram/service/unit/RatingTopProcessing.java b/telegram-bot/src/main/java/org/sadtech/bot/vcs/telegram/service/unit/RatingTopProcessing.java
new file mode 100644
index 0000000..6f59d3c
--- /dev/null
+++ b/telegram-bot/src/main/java/org/sadtech/bot/vcs/telegram/service/unit/RatingTopProcessing.java
@@ -0,0 +1,33 @@
+package org.sadtech.bot.vcs.telegram.service.unit;
+
+import lombok.RequiredArgsConstructor;
+import org.sadtech.bot.vcs.core.domain.entity.Person;
+import org.sadtech.bot.vcs.core.exception.NotFoundException;
+import org.sadtech.bot.vcs.core.service.PersonService;
+import org.sadtech.bot.vcs.core.service.RatingService;
+import org.sadtech.social.bot.service.usercode.ProcessingData;
+import org.sadtech.social.core.domain.BoxAnswer;
+import org.sadtech.social.core.domain.content.Message;
+import org.springframework.stereotype.Component;
+
+/**
+ * // TODO: 01.10.2020 Добавить описание.
+ *
+ * @author upagge 01.10.2020
+ */
+@Component
+@RequiredArgsConstructor
+public class RatingTopProcessing implements ProcessingData {
+
+ private final RatingService ratingService;
+ private final PersonService personService;
+
+ @Override
+ public BoxAnswer processing(Message content) {
+ final Person person = personService.getByTelegramId(content.getPersonId())
+ .orElseThrow(() -> new NotFoundException("Пользователь не найден"));
+ return BoxAnswer.builder()
+ .message(ratingService.getRatingTop(person.getLogin()))
+ .build();
+ }
+}
diff --git a/telegram-bot/src/main/java/org/sadtech/bot/vcs/telegram/unit/UnitConfig.java b/telegram-bot/src/main/java/org/sadtech/bot/vcs/telegram/unit/UnitConfig.java
index e3307af..a2eca09 100644
--- a/telegram-bot/src/main/java/org/sadtech/bot/vcs/telegram/unit/UnitConfig.java
+++ b/telegram-bot/src/main/java/org/sadtech/bot/vcs/telegram/unit/UnitConfig.java
@@ -3,6 +3,7 @@ package org.sadtech.bot.vcs.telegram.unit;
import lombok.RequiredArgsConstructor;
import org.sadtech.bot.vcs.core.service.PersonService;
import org.sadtech.bot.vcs.telegram.service.unit.PullRequestProcessing;
+import org.sadtech.bot.vcs.telegram.service.unit.RatingTopProcessing;
import org.sadtech.bot.vcs.telegram.service.unit.TaskProcessing;
import org.sadtech.bot.vcs.telegram.utils.GeneratorKeyBoards;
import org.sadtech.social.bot.domain.unit.AnswerCheck;
@@ -44,7 +45,8 @@ public class UnitConfig {
public AnswerText menu(
AnswerProcessing getTasks,
AnswerProcessing getPr,
- AnswerText settings
+ AnswerText settings,
+ AnswerProcessing getTopRating
) {
return AnswerText.builder()
.boxAnswer(
@@ -56,6 +58,7 @@ public class UnitConfig {
.nextUnit(getTasks)
.nextUnit(getPr)
.nextUnit(settings)
+ .nextUnit(getTopRating)
.build();
}
@@ -97,6 +100,16 @@ public class UnitConfig {
.build();
}
+ @Bean
+ AnswerProcessing getTopRating(
+ RatingTopProcessing ratingTopProcessing
+ ) {
+ return AnswerProcessing.builder()
+ .processingData(ratingTopProcessing)
+ .keyWord("таблица")
+ .keyWord("рейтинга")
+ .build();
+ }
@Bean
public AnswerProcessing noRegister() {
diff --git a/telegram-bot/src/main/java/org/sadtech/bot/vcs/telegram/utils/GeneratorKeyBoards.java b/telegram-bot/src/main/java/org/sadtech/bot/vcs/telegram/utils/GeneratorKeyBoards.java
index 61bf43e..a5cb80c 100644
--- a/telegram-bot/src/main/java/org/sadtech/bot/vcs/telegram/utils/GeneratorKeyBoards.java
+++ b/telegram-bot/src/main/java/org/sadtech/bot/vcs/telegram/utils/GeneratorKeyBoards.java
@@ -17,6 +17,7 @@ public class GeneratorKeyBoards {
public static KeyBoard menu() {
final KeyBoardButtonText tasks = KeyBoardButtonText.builder().label("Мои задачи").build();
final KeyBoardButtonText pr = KeyBoardButtonText.builder().label("Проверить ПР").build();
+ final KeyBoardButtonText top = KeyBoardButtonText.builder().label("\uD83C\uDF1F Таблица рейтинга \uD83C\uDF1F").build();
final KeyBoardButtonText settings = KeyBoardButtonText.builder().label("Настройки").build();
final KeyBoardLine oneLine = KeyBoardLine.builder()
@@ -25,12 +26,17 @@ public class GeneratorKeyBoards {
.build();
final KeyBoardLine twoLine = KeyBoardLine.builder()
+ .buttonKeyBoard(top)
+ .build();
+
+ final KeyBoardLine threeLine = KeyBoardLine.builder()
.buttonKeyBoard(settings)
.build();
return KeyBoard.builder()
.lineKeyBoard(oneLine)
.lineKeyBoard(twoLine)
+ .lineKeyBoard(threeLine)
.build();
}