From 5540fa8d36d45ff00af94250d99f4a04bbf055da Mon Sep 17 00:00:00 2001 From: vladkuzhyr Date: Wed, 15 May 2024 21:22:10 +0300 Subject: [PATCH 01/11] add method to quizRepo for get set amount question from mongoDb database --- .../java/org/example/QuizBotListener.java | 53 ++++++------------- .../org/example/model/PermanentUserInfo.java | 13 +---- .../org/example/repositories/QuizRepo.java | 18 +++---- .../org/example/services/QuizService.java | 25 +++------ .../org/example/services/UsersService.java | 2 +- 5 files changed, 32 insertions(+), 79 deletions(-) diff --git a/src/main/java/org/example/QuizBotListener.java b/src/main/java/org/example/QuizBotListener.java index 65999e0..5ee7abc 100644 --- a/src/main/java/org/example/QuizBotListener.java +++ b/src/main/java/org/example/QuizBotListener.java @@ -47,6 +47,14 @@ public QuizBotListener(TelegramBot bot, QuizService quizService) { }).addListener((CacheEntryCreatedListener) (cache, entry) -> sendMessage(entry.getKey(), UserBotConstants.STARTING_MESSAGE)).build(); } + private static String getQuizStatText(int quizAmount, int rightAnswerCounter) { + return String.format("❓ Question number: %d" + "\n\n" + "✅ Right answers: %d\\%d" + "\n\n" + "Input " + UserBotConstants.START_QUIZ_COMMAND + " to start quiz or chose quiz another quiz " + UserBotConstants.CHOOSE_TOPIC_COMMAND, quizAmount, rightAnswerCounter, quizAmount); + } + + private static String getCanceledQuizStatText(int questionCount, int rightAnswerCounter) { + return String.format("❓You canceled quiz\n" + "\n" + "The questions were: %d\n\n" + "✅ Right answers: %d\\%d\n" + "\n" + "Input " + UserBotConstants.START_QUIZ_COMMAND + " to start quiz or chose quiz another quiz " + UserBotConstants.CHOOSE_TOPIC_COMMAND, questionCount, rightAnswerCounter, questionCount); + } + @Override public int process(List updates) throws NullPointerException { try { @@ -60,7 +68,10 @@ public int process(List updates) throws NullPointerException { Message message = update.message(); Long userId = message.chat().id(); String messageText = message.text(); - QuizBotSession quizBotSession = sessionCache.computeIfAbsent(userId, () -> new QuizBotSession(QuizBotSessionMode.SESSION_CREATED)); + QuizBotSession quizBotSession = null; + if (messageText.equals(UserBotConstants.START_BOT_COMMAND)) { + quizBotSession = sessionCache.computeIfAbsent(userId, () -> new QuizBotSession(QuizBotSessionMode.SESSION_CREATED)); + } //todo start here switch (messageText) { case UserBotConstants.START_BOT_COMMAND -> { @@ -92,8 +103,9 @@ public int process(List updates) throws NullPointerException { sendMessage(userId, "You are not chosen quiz"); break; } - - userQuizSession = new UserQuizSession(getGeneratedQuiz(currentTopicName, quizBotSession)); + QuizQuestions quizQuestions = quizService.findRandomQuestionsByTopicName(quizBotSession.getCurrentTopicName(), + quizBotSession.getCountOfQuestion()); + userQuizSession = new UserQuizSession(quizQuestions); quizBotSession.setUserQuizSession(userQuizSession); sendMessage(userId, "Quiz: " + quizBotSession.getCurrentTopicName()); quizBotSession.setBotSessionMode(QuizBotSessionMode.QUIZ); @@ -136,33 +148,6 @@ private void setCountOfQuiz(String messageText, Long userId, QuizBotSession quiz quizBotSession.setBotSessionMode(QuizBotSessionMode.SESSION_CREATED); } - private QuizQuestions getGeneratedQuiz(String currentTopicName, QuizBotSession quizBotSession) { - QuizQuestions quizQuestions = quizService.findByTopicName(currentTopicName); - List questionList = quizQuestions.getQuestionList(); - int countOfQuestion = quizBotSession.getCountOfQuestion(); - if (questionList.size() <= countOfQuestion) { - return quizQuestions; - } - QuizQuestions generatedQuizQuestions = new QuizQuestions(); - List generatedQuestionList = new ArrayList<>(); - Set uniqueNumbers = getUniqueNums(questionList.size() - 1, countOfQuestion); - for (Integer i : uniqueNumbers) { - generatedQuestionList.add(questionList.get(i)); - } - generatedQuizQuestions.setQuestionList(generatedQuestionList); - generatedQuizQuestions.setTopicName(quizQuestions.getTopicName()); - return generatedQuizQuestions; - } - - private Set getUniqueNums(int max, int count) { - Set uniqueNums = new HashSet<>(); - Random random = new Random(); - while (count > uniqueNums.size()) { - uniqueNums.add(random.nextInt(max)); - } - return uniqueNums; - } - private void sendMessage(Long userId, String s) { bot.execute(new SendMessage(userId, s)); } @@ -322,14 +307,6 @@ private void clearLastMessageKeyboard(QuizBotSession quizBotSession, Long userId bot.execute(editMessage); } - private static String getQuizStatText(int quizAmount, int rightAnswerCounter) { - return String.format("❓ Question number: %d" + "\n\n" + "✅ Right answers: %d\\%d" + "\n\n" + "Input " + UserBotConstants.START_QUIZ_COMMAND + " to start quiz or chose quiz another quiz " + UserBotConstants.CHOOSE_TOPIC_COMMAND, quizAmount, rightAnswerCounter, quizAmount); - } - - private static String getCanceledQuizStatText(int questionCount, int rightAnswerCounter) { - return String.format("❓You canceled quiz\n" + "\n" + "The questions were: %d\n\n" + "✅ Right answers: %d\\%d\n" + "\n" + "Input " + UserBotConstants.START_QUIZ_COMMAND + " to start quiz or chose quiz another quiz " + UserBotConstants.CHOOSE_TOPIC_COMMAND, questionCount, rightAnswerCounter, questionCount); - } - private String getAnswerText(UserQuizSession userQuizSession, int userAnswerNum) { Question question = userQuizSession.getCurrentQuestion(); List optionsList = question.getOptionList(); diff --git a/src/main/java/org/example/model/PermanentUserInfo.java b/src/main/java/org/example/model/PermanentUserInfo.java index 582c5e3..258fb0e 100644 --- a/src/main/java/org/example/model/PermanentUserInfo.java +++ b/src/main/java/org/example/model/PermanentUserInfo.java @@ -3,7 +3,6 @@ import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Field; -import org.springframework.data.redis.core.RedisHash; @Document public class PermanentUserInfo { @@ -12,16 +11,13 @@ public class PermanentUserInfo { private Long userId; @Field(name = "userName") private String userName; - @Field(name = "isAdmin") - private boolean isAdmin = false; public PermanentUserInfo() { } - public PermanentUserInfo(String userName, Long userId, boolean isAdmin) { + public PermanentUserInfo(String userName, Long userId) { this.userName = userName; this.userId = userId; - this.isAdmin = isAdmin; } public String getUserName() { @@ -40,11 +36,4 @@ public void setUserId(Long userId) { this.userId = userId; } - public boolean getIsAdmin() { - return isAdmin; - } - - public void setAdmin(boolean admin) { - isAdmin = admin; - } } diff --git a/src/main/java/org/example/repositories/QuizRepo.java b/src/main/java/org/example/repositories/QuizRepo.java index 07336eb..0a93aab 100644 --- a/src/main/java/org/example/repositories/QuizRepo.java +++ b/src/main/java/org/example/repositories/QuizRepo.java @@ -2,26 +2,24 @@ import org.example.model.Question; import org.example.model.QuizQuestions; -import org.springframework.data.mongodb.repository.DeleteQuery; +import org.springframework.data.mongodb.repository.Aggregation; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.mongodb.repository.Query; -import org.springframework.data.mongodb.repository.Update; import org.springframework.stereotype.Repository; import java.util.List; @Repository public interface QuizRepo extends MongoRepository { - @Query(value = "{}", fields = "{ 'topicName' : 1, '_id' : 0 }") - List findAllTopicName(); @Query("{'topicName' : ?0}") QuizQuestions findByTopicName(String topicName); - @DeleteQuery("{'topicName' : ?0}") - void deleteByTopicName(String topicName); - - @Query("{'topicName' : ?0}") - @Update("{$push : {'questionList' : {$each : ?1}}}") - void addByTopic(String topicName, List questionList); + @Aggregation({"{ $match: { topicName: ?0 } }", + "{ $project: {topicName: 1,questionList: 1,_class: 1} }", + "{ $unwind: \"$questionList\" }", + "{ $sample: { size: ?1 } }", + "{ $group: {_id: \"$_id\", topicName:{$first:\"$topicName\"},questionList: { $push: \"$questionList\" },_class:{$first:\"$_class\"}} }", + }) + QuizQuestions findRandomQuestionsByTopicName(String topicName, int n); } diff --git a/src/main/java/org/example/services/QuizService.java b/src/main/java/org/example/services/QuizService.java index 4dbb92d..d4c554e 100644 --- a/src/main/java/org/example/services/QuizService.java +++ b/src/main/java/org/example/services/QuizService.java @@ -1,8 +1,6 @@ package org.example.services; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; +import org.example.model.Question; import org.example.model.QuizQuestions; import org.example.repositories.QuizRepo; import org.springframework.beans.factory.annotation.Autowired; @@ -10,7 +8,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; @Service public class QuizService { @@ -20,23 +17,11 @@ public class QuizService { @Autowired public QuizService(QuizRepo quizRepo) { this.quizRepo = quizRepo; - topics = quizRepo.findAllTopicName(); + topics = quizRepo.findAll().stream().map(QuizQuestions::getTopicName).toList(); } public List getTopics() { - ObjectMapper objectMapper = new ObjectMapper(); - List topic = quizRepo.findAllTopicName(); - if (topic == null) { - return List.of(); - } - return topics = topic.stream().map(string -> { - try { - JsonNode jsonNode = objectMapper.readTree(string); - return jsonNode.get("topicName").asText(); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - }).collect(Collectors.toList()); + return topics; } public void deleteAllQuiz() { @@ -48,4 +33,8 @@ public QuizQuestions findByTopicName(String topicName) { return quizRepo.findByTopicName(topicName); } + public QuizQuestions findRandomQuestionsByTopicName(String topicName, int count) { + return quizRepo.findRandomQuestionsByTopicName(topicName, count); + } + } diff --git a/src/main/java/org/example/services/UsersService.java b/src/main/java/org/example/services/UsersService.java index 5d3f4dd..aa7d407 100644 --- a/src/main/java/org/example/services/UsersService.java +++ b/src/main/java/org/example/services/UsersService.java @@ -15,7 +15,7 @@ public UsersService(UserRepo userRepo) { } public PermanentUserInfo addNewUser(String userName, Long userId) { - PermanentUserInfo permanentUserInfo = new PermanentUserInfo(userName, userId, false); + PermanentUserInfo permanentUserInfo = new PermanentUserInfo(userName, userId); userRepo.insert(permanentUserInfo); return permanentUserInfo; } From 9941a0216b520df1721b173fcb943defec4340fc Mon Sep 17 00:00:00 2001 From: vladkuzhyr Date: Thu, 16 May 2024 21:51:08 +0300 Subject: [PATCH 02/11] create method in MongoDBConfig for Listens events from mongodb and look all threads when added new topic to cache --- src/main/java/org/example/Main.java | 2 ++ .../java/org/example/QuizBotListener.java | 7 +--- .../org/example/configs/MongoDBConfig.java | 35 ++++++++++++++++++- .../org/example/repositories/QuizRepo.java | 10 ++++-- .../org/example/services/QuizService.java | 30 +++++++++++++--- 5 files changed, 69 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/example/Main.java b/src/main/java/org/example/Main.java index 9dc714b..e86ad42 100644 --- a/src/main/java/org/example/Main.java +++ b/src/main/java/org/example/Main.java @@ -3,10 +3,12 @@ import com.pengrad.telegrambot.TelegramBot; import org.example.configs.MongoDBConfig; import org.example.services.QuizService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; @PropertySource("classpath:application.properties") public class Main { diff --git a/src/main/java/org/example/QuizBotListener.java b/src/main/java/org/example/QuizBotListener.java index 5ee7abc..b204cff 100644 --- a/src/main/java/org/example/QuizBotListener.java +++ b/src/main/java/org/example/QuizBotListener.java @@ -26,10 +26,7 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; import java.util.List; -import java.util.Random; -import java.util.Set; import java.util.concurrent.TimeUnit; public class QuizBotListener implements UpdatesListener { @@ -69,9 +66,7 @@ public int process(List updates) throws NullPointerException { Long userId = message.chat().id(); String messageText = message.text(); QuizBotSession quizBotSession = null; - if (messageText.equals(UserBotConstants.START_BOT_COMMAND)) { - quizBotSession = sessionCache.computeIfAbsent(userId, () -> new QuizBotSession(QuizBotSessionMode.SESSION_CREATED)); - } + quizBotSession = sessionCache.computeIfAbsent(userId, () -> new QuizBotSession(QuizBotSessionMode.SESSION_CREATED)); //todo start here switch (messageText) { case UserBotConstants.START_BOT_COMMAND -> { diff --git a/src/main/java/org/example/configs/MongoDBConfig.java b/src/main/java/org/example/configs/MongoDBConfig.java index de2d7af..45bd7d8 100644 --- a/src/main/java/org/example/configs/MongoDBConfig.java +++ b/src/main/java/org/example/configs/MongoDBConfig.java @@ -3,13 +3,25 @@ import com.mongodb.ConnectionString; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; +import com.mongodb.client.model.changestream.FullDocument; +import com.mongodb.client.model.changestream.OperationType; +import org.example.model.QuizQuestions; +import org.example.services.QuizService; import org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; +import org.springframework.data.mongodb.core.ChangeStreamOptions; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.aggregation.Aggregation; +import org.springframework.data.mongodb.core.messaging.ChangeStreamRequest; +import org.springframework.data.mongodb.core.messaging.DefaultMessageListenerContainer; +import org.springframework.data.mongodb.core.messaging.Subscription; +import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; @Configuration @@ -18,12 +30,13 @@ @EnableMongoRepositories("org.example.repositories") public class MongoDBConfig extends AbstractMongoClientConfiguration { - @Value("${spring.data.mongodb.database}") private String databaseName; + @Value("${spring.data.mongodb.uri}") private String connectionUri; + @NotNull @Override protected String getDatabaseName() { @@ -42,4 +55,24 @@ public MongoClient reconnectToDB() { currentClient.close(); return MongoClients.create(new ConnectionString(connectionUri)); } + + @Bean + public DefaultMessageListenerContainer messageListenerContainer(MongoTemplate mongoTemplate, QuizService quizService) { + DefaultMessageListenerContainer container = new DefaultMessageListenerContainer(mongoTemplate); + container.start(); + ChangeStreamOptions changeStreamOptions = ChangeStreamOptions.builder() + .filter(Aggregation.newAggregation(Aggregation.match(Criteria.where("operationType").is(OperationType.INSERT.getValue())))) + .fullDocumentLookup(FullDocument.UPDATE_LOOKUP) + .build(); + ChangeStreamRequest.ChangeStreamRequestOptions options = new ChangeStreamRequest.ChangeStreamRequestOptions(databaseName, "quizQuestions", changeStreamOptions); + + Subscription subscription = container.register(new ChangeStreamRequest<>(message -> { + QuizQuestions quizQuestions = message.getBody(); + if (quizQuestions != null) { + String topic = quizQuestions.getTopicName(); + quizService.addTopic(topic); + } + }, options), QuizQuestions.class); + return container; + } } diff --git a/src/main/java/org/example/repositories/QuizRepo.java b/src/main/java/org/example/repositories/QuizRepo.java index 0a93aab..5c2d55b 100644 --- a/src/main/java/org/example/repositories/QuizRepo.java +++ b/src/main/java/org/example/repositories/QuizRepo.java @@ -1,14 +1,11 @@ package org.example.repositories; -import org.example.model.Question; import org.example.model.QuizQuestions; import org.springframework.data.mongodb.repository.Aggregation; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.mongodb.repository.Query; import org.springframework.stereotype.Repository; -import java.util.List; - @Repository public interface QuizRepo extends MongoRepository { @@ -22,4 +19,11 @@ public interface QuizRepo extends MongoRepository { "{ $group: {_id: \"$_id\", topicName:{$first:\"$topicName\"},questionList: { $push: \"$questionList\" },_class:{$first:\"$_class\"}} }", }) QuizQuestions findRandomQuestionsByTopicName(String topicName, int n); + + @Aggregation({ + "{$project: {_id: 0,topicName: 1}}", + "{$group: {_id: 0,topicName: { $push: \"$topicName\" }}}", + "{$project: {topicName: 1,_id: 0}}" + }) + String findAllTopic(); } diff --git a/src/main/java/org/example/services/QuizService.java b/src/main/java/org/example/services/QuizService.java index d4c554e..224c193 100644 --- a/src/main/java/org/example/services/QuizService.java +++ b/src/main/java/org/example/services/QuizService.java @@ -1,31 +1,51 @@ package org.example.services; -import org.example.model.Question; +import org.cache2k.Cache; +import org.cache2k.Cache2kBuilder; import org.example.model.QuizQuestions; import org.example.repositories.QuizRepo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; @Service public class QuizService { - private static List topics = new ArrayList<>(); + private final Lock lock = new ReentrantLock(); + private Cache> topicsCache; private final QuizRepo quizRepo; @Autowired public QuizService(QuizRepo quizRepo) { this.quizRepo = quizRepo; - topics = quizRepo.findAll().stream().map(QuizQuestions::getTopicName).toList(); + topicsCache = new Cache2kBuilder>() {} + .eternal(true) + .build(); + List topics = Arrays.stream(quizRepo.findAllTopic().split(",")).toList(); + topicsCache.put("topics", topics); } public List getTopics() { - return topics; + return topicsCache.get("topics"); + } + + public synchronized void addTopic(String topicName){ + lock.lock(); + try { + List topics = new ArrayList<>(topicsCache.get("topics")); + topics.add(topicName); + topicsCache.put("topics", topics); + } finally { + lock.unlock(); + } } public void deleteAllQuiz() { - topics = new ArrayList<>(); + topicsCache.remove("topics"); quizRepo.deleteAll(); } From 0d8d0fe8157d7c0ed606fca069982528247b5642 Mon Sep 17 00:00:00 2001 From: vladkuzhyr Date: Fri, 17 May 2024 17:58:50 +0300 Subject: [PATCH 03/11] add palette of QuizBotSessionMode in QuizBotListener --- docker-compose.yml | 6 +- pom.xml | 12 -- .../java/org/example/QuizBotListener.java | 110 +++++++++--------- .../org/example/model/QuizBotSession.java | 10 +- .../org/example/services/QuizService.java | 11 +- .../model/QuizQuestionsSessionTest.java | 13 --- .../model/UserQuizQuestionsSessionTest.java | 27 +---- 7 files changed, 62 insertions(+), 127 deletions(-) delete mode 100644 src/test/java/org/example/model/QuizQuestionsSessionTest.java diff --git a/docker-compose.yml b/docker-compose.yml index dc98105..f41eff6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,12 +2,10 @@ services: bot: build: . environment: - - SPRING_DATA_MONGODB_URI=${SPRING_DATA_MONGODB_URI} - TELEGRAM_USER_TOKEN=${TELEGRAM_USER_TOKEN} - - TELEGRAM_ADMIN_TOKEN=${TELEGRAM_ADMIN_TOKEN} - SPRING_DATA_MONGODB_DATABASE=${SPRING_DATA_MONGODB_DATABASE} - - REDIS_PORT=${REDIS_PORT} - - REDIS_HOSTNAME=${REDIS_HOSTNAME} + - SPRING_DATA_MONGODB_URI=${SPRING_DATA_MONGODB_URI} + grafana: image: "grafana/grafana-enterprise:10.4.2" diff --git a/pom.xml b/pom.xml index 2dc2381..2f18f1e 100644 --- a/pom.xml +++ b/pom.xml @@ -70,19 +70,7 @@ - - org.apache.maven.plugins - maven-jar-plugin - 3.2.0 - - - - org.example.Main - - - - maven-assembly-plugin 3.7.1 diff --git a/src/main/java/org/example/QuizBotListener.java b/src/main/java/org/example/QuizBotListener.java index b204cff..89c3c5b 100644 --- a/src/main/java/org/example/QuizBotListener.java +++ b/src/main/java/org/example/QuizBotListener.java @@ -65,9 +65,39 @@ public int process(List updates) throws NullPointerException { Message message = update.message(); Long userId = message.chat().id(); String messageText = message.text(); - QuizBotSession quizBotSession = null; - quizBotSession = sessionCache.computeIfAbsent(userId, () -> new QuizBotSession(QuizBotSessionMode.SESSION_CREATED)); - //todo start here + QuizBotSession quizBotSession = sessionCache.computeIfAbsent(userId, + () -> new QuizBotSession(QuizBotSessionMode.SESSION_CREATED)); + switch (quizBotSession.getBotSessionMode()) { + case TOPIC_CHOICE -> { + if (messageText.equals(UserBotConstants.CANCEL_COMMAND)) { + quizBotSession.setBotSessionMode(QuizBotSessionMode.SESSION_CREATED); + sendMessage(userId, UserBotConstants.STARTING_MESSAGE); + return UpdatesListener.CONFIRMED_UPDATES_ALL; + } + choiceTopic(messageText, quizBotSession, userId); + return UpdatesListener.CONFIRMED_UPDATES_ALL; + } + case QUIZ -> { + if (messageText.equals(UserBotConstants.CANCEL_COMMAND)) { + clearLastMessageKeyboard(quizBotSession, userId); + sendStatsCanceledQuiz(userId, quizBotSession); + return UpdatesListener.CONFIRMED_UPDATES_ALL; + } + sendMessage(userId, "Please finish this quiz"); + return UpdatesListener.CONFIRMED_UPDATES_ALL; + } + + case QUESTION_COUNT_CHOICE -> { + if (messageText.equals(UserBotConstants.CANCEL_COMMAND)) { + quizBotSession.setBotSessionMode(QuizBotSessionMode.SESSION_CREATED); + sendMessage(userId, UserBotConstants.STARTING_MESSAGE); + return UpdatesListener.CONFIRMED_UPDATES_ALL; + } + setCountOfQuiz(messageText, userId, quizBotSession); + return UpdatesListener.CONFIRMED_UPDATES_ALL; + } + } + switch (messageText) { case UserBotConstants.START_BOT_COMMAND -> { clearLastMessageKeyboard(quizBotSession, userId); @@ -75,65 +105,35 @@ public int process(List updates) throws NullPointerException { sessionCache.put(userId, new QuizBotSession(QuizBotSessionMode.SESSION_CREATED)); return UpdatesListener.CONFIRMED_UPDATES_ALL; } - case UserBotConstants.CHOOSE_TOPIC_COMMAND -> { - UserQuizSession userQuizSession = quizBotSession.getUserQuizSession(); - if (userQuizSession != null) { - sendMessage(userId, "Please finish this quiz"); - break; - } - sendTopics(userId, quizBotSession); - } + case UserBotConstants.CHOOSE_TOPIC_COMMAND -> sendTopics(userId, quizBotSession); case UserBotConstants.START_QUIZ_COMMAND -> { - UserQuizSession userQuizSession = quizBotSession.getUserQuizSession(); - if (userQuizSession != null) { - sendMessage(userId, "Please finish this quiz"); - break; - } String currentTopicName = quizBotSession.getCurrentTopicName(); - if (currentTopicName == null) { - sendMessage(userId, "Topic is not chosen, please use " + UserBotConstants.CHOOSE_TOPIC_COMMAND + " command to choose"); - break; + if (currentTopicName.isEmpty()) { + sendMessage(userId, "Pleas choice topic " + UserBotConstants.CHOOSE_TOPIC_COMMAND); + return UpdatesListener.CONFIRMED_UPDATES_ALL; } - if (quizBotSession.getBotSessionMode().equals(QuizBotSessionMode.QUESTION_COUNT_CHOICE)) { - sendMessage(userId, "You are not chosen quiz"); - break; - } - QuizQuestions quizQuestions = quizService.findRandomQuestionsByTopicName(quizBotSession.getCurrentTopicName(), - quizBotSession.getCountOfQuestion()); - userQuizSession = new UserQuizSession(quizQuestions); + int countOfQuestion = quizBotSession.getCountOfQuestion(); + QuizQuestions quizQuestions = quizService.findRandomQuestionsByTopicName(currentTopicName, countOfQuestion); + UserQuizSession userQuizSession = new UserQuizSession(quizQuestions); + sendMessage(userId, "Quiz: " + currentTopicName); quizBotSession.setUserQuizSession(userQuizSession); - sendMessage(userId, "Quiz: " + quizBotSession.getCurrentTopicName()); - quizBotSession.setBotSessionMode(QuizBotSessionMode.QUIZ); sendQuestion(userId, quizBotSession); + quizBotSession.setBotSessionMode(QuizBotSessionMode.QUIZ); } - case UserBotConstants.CANCEL_COMMAND -> { - UserQuizSession userQuizSession = quizBotSession.getUserQuizSession(); - if (userQuizSession == null) { - sendMessage(userId, "You aren't begin quiz"); - break; - } - clearLastMessageKeyboard(quizBotSession, userId); - sendStatsCanceledQuiz(userId, quizBotSession); - } - } - - if (messageText.matches("^[1-9][0-9]*$")) { - if (quizBotSession.getBotSessionMode().equals(QuizBotSessionMode.QUESTION_COUNT_CHOICE)) { - setCountOfQuiz(messageText, userId, quizBotSession); - } - if (quizBotSession.getBotSessionMode().equals(QuizBotSessionMode.TOPIC_CHOICE)) { - choiceTopic(messageText, quizBotSession, userId); - } + case UserBotConstants.CANCEL_COMMAND -> sendMessage(userId, "Nothing canceled"); + default -> sendMessage(userId, "Input a valid command"); } - return UpdatesListener.CONFIRMED_UPDATES_ALL; } catch (Exception e) { log.error(e.getMessage()); } - return UpdatesListener.CONFIRMED_UPDATES_ALL; } private void setCountOfQuiz(String messageText, Long userId, QuizBotSession quizBotSession) { + if (!messageText.matches("^[1-9][0-9]*$")) { + sendMessage(userId, "Input a number or input " + UserBotConstants.CANCEL_COMMAND + " for cancel count of question choice"); + return; + } int countOfQuestions = Integer.parseInt(messageText); if (countOfQuestions > 20 || countOfQuestions < 5) { sendMessage(userId, "Input valid count of question"); @@ -269,26 +269,24 @@ private InlineKeyboardMarkup buildInlineKeyboard(int keyboardLength) { } private void choiceTopic(String messageText, QuizBotSession quizBotSession, Long userId) { + if (!messageText.matches("^[1-9][0-9]*$")) { + sendMessage(userId, "Input a number or input " + UserBotConstants.CANCEL_COMMAND + " for cancel topic choice"); + return; + } int topicIndex = Integer.parseInt(messageText) - 1; List allTopicName = quizService.getTopics(); if (allTopicName.isEmpty()) { - quizBotSession.setBotSessionMode(QuizBotSessionMode.SESSION_CREATED); sendMessage(userId, "Sorry nothing quiz, send " + UserBotConstants.CHOOSE_TOPIC_COMMAND + " for choice quiz"); return; } - if (topicIndex >= allTopicName.size()) { - sendMessage(userId, "You input over large digital, send me correct digital"); - sendTopics(userId, quizBotSession); - return; - } else if (topicIndex < 0) { - sendMessage(userId, "You input so small digital, send me correct digital"); + if (topicIndex >= allTopicName.size() || topicIndex < 0) { + sendMessage(userId, "Send me correct digital from 1 to " + allTopicName.size()); sendTopics(userId, quizBotSession); return; } String currentTopicName = allTopicName.get(topicIndex); quizBotSession.setCurrentTopicName(currentTopicName); - quizBotSession.setCurrentQuiz(quizService.findByTopicName(currentTopicName)); quizBotSession.setBotSessionMode(QuizBotSessionMode.QUESTION_COUNT_CHOICE); sendMessage(userId, "Input count to your quiz (at 5 to 20)"); } diff --git a/src/main/java/org/example/model/QuizBotSession.java b/src/main/java/org/example/model/QuizBotSession.java index 9d31329..c4bec8a 100644 --- a/src/main/java/org/example/model/QuizBotSession.java +++ b/src/main/java/org/example/model/QuizBotSession.java @@ -5,9 +5,8 @@ public class QuizBotSession { private QuizBotSessionMode botSessionMode; - private QuizQuestions currentQuizQuestions; private UserQuizSession userQuizSession; - private String currentTopicName; + private String currentTopicName = ""; private int lastKeyboardBotMessageId = 0; private String lastKeyboardBotMessageText; private int countOfQuestion = 0; @@ -48,13 +47,6 @@ public void setLastKeyboardBotMessageText(String lastKeyboardBotMessageText) { this.lastKeyboardBotMessageText = lastKeyboardBotMessageText; } - public QuizQuestions getCurrentQuiz() { - return currentQuizQuestions; - } - - public void setCurrentQuiz(QuizQuestions currentQuizQuestions) { - this.currentQuizQuestions = currentQuizQuestions; - } public int getCountOfQuestion() { return countOfQuestion; diff --git a/src/main/java/org/example/services/QuizService.java b/src/main/java/org/example/services/QuizService.java index 224c193..2bbfc46 100644 --- a/src/main/java/org/example/services/QuizService.java +++ b/src/main/java/org/example/services/QuizService.java @@ -16,7 +16,7 @@ @Service public class QuizService { private final Lock lock = new ReentrantLock(); - private Cache> topicsCache; + private final Cache> topicsCache; private final QuizRepo quizRepo; @Autowired @@ -44,15 +44,6 @@ public synchronized void addTopic(String topicName){ } } - public void deleteAllQuiz() { - topicsCache.remove("topics"); - quizRepo.deleteAll(); - } - - public QuizQuestions findByTopicName(String topicName) { - return quizRepo.findByTopicName(topicName); - } - public QuizQuestions findRandomQuestionsByTopicName(String topicName, int count) { return quizRepo.findRandomQuestionsByTopicName(topicName, count); } diff --git a/src/test/java/org/example/model/QuizQuestionsSessionTest.java b/src/test/java/org/example/model/QuizQuestionsSessionTest.java deleted file mode 100644 index 71aae85..0000000 --- a/src/test/java/org/example/model/QuizQuestionsSessionTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.example.model; - -import org.junit.jupiter.api.BeforeEach; - -class QuizQuestionsSessionTest { - private QuizBotSession quizBotSession; - - @BeforeEach - void setUp() { - quizBotSession = new QuizBotSession(); - } - -} \ No newline at end of file diff --git a/src/test/java/org/example/model/UserQuizQuestionsSessionTest.java b/src/test/java/org/example/model/UserQuizQuestionsSessionTest.java index 08f0e89..5ca08af 100644 --- a/src/test/java/org/example/model/UserQuizQuestionsSessionTest.java +++ b/src/test/java/org/example/model/UserQuizQuestionsSessionTest.java @@ -1,7 +1,7 @@ package org.example.model; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.ArrayList; @@ -26,14 +26,9 @@ public void setUp() { @Test void isNextQuestionAvailable(){ - Assertions.assertTrue(userQuizSession.isNextQuestionAvailable()); + Assertions.assertNotNull(userQuizSession.getNextQuestion()); } - @Test - void isNextQuestionNotAvailable() { - userQuizSession = new UserQuizSession(new QuizQuestions()); - Assertions.assertFalse(userQuizSession.isNextQuestionAvailable()); - } @Test void incRightCounter() { @@ -44,13 +39,7 @@ void incRightCounter() { @Test void getCurrentQuestion() { - Assertions.assertNull(userQuizSession.getCurrentQuestionIndex()); - userQuizSession.getNextQuestion(); - Assertions.assertEquals(userQuizSession.getCurrentQuestionIndex(), question1); - userQuizSession.getNextQuestion(); - Assertions.assertEquals(userQuizSession.getCurrentQuestionIndex(), question2); - userQuizSession.getNextQuestion(); - Assertions.assertEquals(userQuizSession.getCurrentQuestionIndex(), question2); + } @Test @@ -61,8 +50,6 @@ void getNextQuestion() { @Test void getQuestionCounter() { - Assertions.assertEquals(userQuizSession.getQuestionCounter(),0); - userQuizSession.getNextQuestion(); Assertions.assertEquals(userQuizSession.getQuestionCounter(),1); userQuizSession.getNextQuestion(); Assertions.assertEquals(userQuizSession.getQuestionCounter(),2); @@ -77,12 +64,6 @@ void getQuestionAmount() { @Test void getRightAnswerCounter() { - Assertions.assertEquals(userQuizSession.getRightAnswerCounter(),0); - userQuizSession.incRightCounter(); - Assertions.assertEquals(userQuizSession.getRightAnswerCounter(),1); - userQuizSession.incRightCounter(); - Assertions.assertEquals(userQuizSession.getRightAnswerCounter(),2); - userQuizSession.incRightCounter(); - Assertions.assertEquals(userQuizSession.getRightAnswerCounter(),2); + } } \ No newline at end of file From 1f63e010d3a182c525a9108cda387d977a09b58f Mon Sep 17 00:00:00 2001 From: vladkuzhyr Date: Thu, 23 May 2024 18:58:32 +0300 Subject: [PATCH 04/11] add event listens on delete and create method for updating topicList --- pom.xml | 21 ++----- .../org/example/configs/MongoDBConfig.java | 62 +++++++++---------- .../org/example/services/QuizService.java | 4 ++ 3 files changed, 41 insertions(+), 46 deletions(-) diff --git a/pom.xml b/pom.xml index 2f18f1e..928e019 100644 --- a/pom.xml +++ b/pom.xml @@ -18,18 +18,10 @@ 4.11.1 2.16.1 2.17.2 + 5.10.2 + 1.6.0.Final - - org.springframework.data - spring-data-redis - 3.2.5 - - - redis.clients - jedis - 5.1.2 - com.github.pengrad java-telegram-bot-api @@ -51,15 +43,15 @@ ${jackson-databind.version} - org.junit-pioneer - junit-pioneer - 2.2.0 + org.junit.jupiter + junit-jupiter-api + ${junit-jupiter-api.version} test org.cache2k cache2k-base-bom - 1.6.0.Final + ${cache2k-base-bom.version} pom @@ -70,7 +62,6 @@ - maven-assembly-plugin 3.7.1 diff --git a/src/main/java/org/example/configs/MongoDBConfig.java b/src/main/java/org/example/configs/MongoDBConfig.java index 45bd7d8..edd78e3 100644 --- a/src/main/java/org/example/configs/MongoDBConfig.java +++ b/src/main/java/org/example/configs/MongoDBConfig.java @@ -1,29 +1,29 @@ package org.example.configs; + import com.mongodb.ConnectionString; +import com.mongodb.client.ChangeStreamIterable; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; -import com.mongodb.client.model.changestream.FullDocument; -import com.mongodb.client.model.changestream.OperationType; -import org.example.model.QuizQuestions; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.model.Aggregates; +import com.mongodb.client.model.Filters; +import org.bson.Document; +import org.bson.conversions.Bson; import org.example.services.QuizService; import org.jetbrains.annotations.NotNull; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; -import org.springframework.data.mongodb.core.ChangeStreamOptions; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.aggregation.Aggregation; -import org.springframework.data.mongodb.core.messaging.ChangeStreamRequest; -import org.springframework.data.mongodb.core.messaging.DefaultMessageListenerContainer; -import org.springframework.data.mongodb.core.messaging.Subscription; -import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; +import java.util.Arrays; +import java.util.List; + @Configuration @ComponentScan(basePackages = "org.example") @PropertySource("classpath:application.properties") @@ -50,29 +50,29 @@ public MongoClient mongoClient() { return MongoClients.create(new ConnectionString(connectionUri)); } - public MongoClient reconnectToDB() { - MongoClient currentClient = mongoClient(); - currentClient.close(); - return MongoClients.create(new ConnectionString(connectionUri)); - } - @Bean - public DefaultMessageListenerContainer messageListenerContainer(MongoTemplate mongoTemplate, QuizService quizService) { - DefaultMessageListenerContainer container = new DefaultMessageListenerContainer(mongoTemplate); - container.start(); - ChangeStreamOptions changeStreamOptions = ChangeStreamOptions.builder() - .filter(Aggregation.newAggregation(Aggregation.match(Criteria.where("operationType").is(OperationType.INSERT.getValue())))) - .fullDocumentLookup(FullDocument.UPDATE_LOOKUP) - .build(); - ChangeStreamRequest.ChangeStreamRequestOptions options = new ChangeStreamRequest.ChangeStreamRequestOptions(databaseName, "quizQuestions", changeStreamOptions); + public ChangeStreamIterable runEventListener(MongoTemplate mongoTemplate, QuizService quizService) { + MongoCollection collection = mongoTemplate.getCollection("quizQuestions"); + List pipeline = List.of( + Aggregates.match(Filters.in("operationType", Arrays.asList("insert", "delete")))); + ChangeStreamIterable changeStream = collection.watch(pipeline); + changeStream.forEach(event -> { + String operationType = event.getOperationTypeString(); + if (operationType == null) { + return; + } - Subscription subscription = container.register(new ChangeStreamRequest<>(message -> { - QuizQuestions quizQuestions = message.getBody(); - if (quizQuestions != null) { - String topic = quizQuestions.getTopicName(); - quizService.addTopic(topic); + switch (operationType) { + case "insert" -> { + Document document = event.getFullDocument(); + if (document != null && document.containsKey("topicName")) { + quizService.addTopic(document.getString("topicName")); + } + } + case "delete" -> quizService.updateTopics(); } - }, options), QuizQuestions.class); - return container; + + }); + return changeStream; } } diff --git a/src/main/java/org/example/services/QuizService.java b/src/main/java/org/example/services/QuizService.java index 2bbfc46..445b39a 100644 --- a/src/main/java/org/example/services/QuizService.java +++ b/src/main/java/org/example/services/QuizService.java @@ -48,4 +48,8 @@ public QuizQuestions findRandomQuestionsByTopicName(String topicName, int count) return quizRepo.findRandomQuestionsByTopicName(topicName, count); } + public void updateTopics(){ + List topics = Arrays.stream(quizRepo.findAllTopic().split(",")).toList(); + topicsCache.put("topics", topics); + } } From 3978e8b87c1c23570c19135b5c703a0eb1e28ac2 Mon Sep 17 00:00:00 2001 From: vladkuzhyr Date: Wed, 26 Jun 2024 21:54:28 +0300 Subject: [PATCH 05/11] create github-actions.yml --- .github/workflows/github-actions.yml | 27 ++++++++ Makefile | 6 ++ docker-compose.yml | 4 +- .../java/org/example/QuizBotListener.java | 29 ++++---- .../org/example/configs/MongoDBConfig.java | 1 - .../org/example/model/PermanentUserInfo.java | 4 +- src/main/java/org/example/model/Question.java | 2 +- .../org/example/model/QuizBotSession.java | 2 +- .../org/example/services/QuizService.java | 2 +- src/main/resources/log4j2.xml | 3 +- src/main/resources/topics | 4 -- .../example/QuizQuestionsBotListenerTest.java | 18 ----- .../org/example/model/QuestionOptionTest.java | 12 ---- .../java/org/example/model/QuestionTest.java | 29 -------- .../org/example/model/QuizQuestionsTest.java | 44 ------------ .../model/UserQuizQuestionsSessionTest.java | 69 ------------------- src/test/java/services/QuizServiceTest.java | 5 ++ src/test/java/services/UsersService.java | 4 ++ 18 files changed, 67 insertions(+), 198 deletions(-) create mode 100644 .github/workflows/github-actions.yml create mode 100644 Makefile delete mode 100644 src/main/resources/topics delete mode 100644 src/test/java/org/example/QuizQuestionsBotListenerTest.java delete mode 100644 src/test/java/org/example/model/QuestionOptionTest.java delete mode 100644 src/test/java/org/example/model/QuestionTest.java delete mode 100644 src/test/java/org/example/model/QuizQuestionsTest.java delete mode 100644 src/test/java/org/example/model/UserQuizQuestionsSessionTest.java create mode 100644 src/test/java/services/QuizServiceTest.java create mode 100644 src/test/java/services/UsersService.java diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml new file mode 100644 index 0000000..e82c5ff --- /dev/null +++ b/.github/workflows/github-actions.yml @@ -0,0 +1,27 @@ +name: Build project +on: + push: + branches: + - master + pull_request: + branches: + - * +jobs: + + Explore-GitHub-Actions: + runs-on: ubuntu-latest + steps: + + - uses: actions/checkout@v4 + + - name: Set up JDK 17 for x64 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'corretto' + architecture: x64 + + + - name: Build & Test + run: + mvn -B clean package \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8640475 --- /dev/null +++ b/Makefile @@ -0,0 +1,6 @@ +mBuild: + mvn clean -Dmaven.test.skip package -e +run: + java -jar target/knowBot-1.0-SNAPSHOT-jar-with-dependencies.jar +doc: + docker-compose up -d --build \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index f41eff6..6f4f509 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,10 +6,10 @@ services: - SPRING_DATA_MONGODB_DATABASE=${SPRING_DATA_MONGODB_DATABASE} - SPRING_DATA_MONGODB_URI=${SPRING_DATA_MONGODB_URI} - grafana: image: "grafana/grafana-enterprise:10.4.2" ports: - "3000:3000" depends_on: - - bot \ No newline at end of file + - bot + - prometheus \ No newline at end of file diff --git a/src/main/java/org/example/QuizBotListener.java b/src/main/java/org/example/QuizBotListener.java index 89c3c5b..0c70533 100644 --- a/src/main/java/org/example/QuizBotListener.java +++ b/src/main/java/org/example/QuizBotListener.java @@ -38,18 +38,14 @@ public class QuizBotListener implements UpdatesListener { public QuizBotListener(TelegramBot bot, QuizService quizService) { this.bot = bot; this.quizService = quizService; - this.sessionCache = Cache2kBuilder.of(Long.class, QuizBotSession.class).expireAfterWrite(120, TimeUnit.SECONDS).addListener((CacheEntryExpiredListener) (cache, entry) -> { - clearLastMessageKeyboard(cache.get(entry.getKey()), entry.getKey()); - sendMessage(entry.getKey(), "You've been thinking too long, so you'll have to start over." + " Write /start or /choice."); - }).addListener((CacheEntryCreatedListener) (cache, entry) -> sendMessage(entry.getKey(), UserBotConstants.STARTING_MESSAGE)).build(); - } - - private static String getQuizStatText(int quizAmount, int rightAnswerCounter) { - return String.format("❓ Question number: %d" + "\n\n" + "✅ Right answers: %d\\%d" + "\n\n" + "Input " + UserBotConstants.START_QUIZ_COMMAND + " to start quiz or chose quiz another quiz " + UserBotConstants.CHOOSE_TOPIC_COMMAND, quizAmount, rightAnswerCounter, quizAmount); - } - - private static String getCanceledQuizStatText(int questionCount, int rightAnswerCounter) { - return String.format("❓You canceled quiz\n" + "\n" + "The questions were: %d\n\n" + "✅ Right answers: %d\\%d\n" + "\n" + "Input " + UserBotConstants.START_QUIZ_COMMAND + " to start quiz or chose quiz another quiz " + UserBotConstants.CHOOSE_TOPIC_COMMAND, questionCount, rightAnswerCounter, questionCount); + this.sessionCache = Cache2kBuilder.of(Long.class, QuizBotSession.class) + .expireAfterWrite(120, TimeUnit.SECONDS) + .addListener((CacheEntryExpiredListener) (cache, entry) -> { + clearLastMessageKeyboard(cache.get(entry.getKey()), entry.getKey()); + sendMessage(entry.getKey(), "You've been thinking too long, so you'll have " + + "to start over." + " Write /start or /choice."); + }) + .build(); } @Override @@ -101,6 +97,7 @@ public int process(List updates) throws NullPointerException { switch (messageText) { case UserBotConstants.START_BOT_COMMAND -> { clearLastMessageKeyboard(quizBotSession, userId); + sendMessage(userId, UserBotConstants.STARTING_MESSAGE); sessionCache.remove(userId); sessionCache.put(userId, new QuizBotSession(QuizBotSessionMode.SESSION_CREATED)); return UpdatesListener.CONFIRMED_UPDATES_ALL; @@ -129,6 +126,14 @@ public int process(List updates) throws NullPointerException { return UpdatesListener.CONFIRMED_UPDATES_ALL; } + private static String getQuizStatText(int quizAmount, int rightAnswerCounter) { + return String.format("❓ Question number: %d" + "\n\n" + "✅ Right answers: %d\\%d" + "\n\n" + "Input " + UserBotConstants.START_QUIZ_COMMAND + " to start quiz or chose quiz another quiz " + UserBotConstants.CHOOSE_TOPIC_COMMAND, quizAmount, rightAnswerCounter, quizAmount); + } + + private static String getCanceledQuizStatText(int questionCount, int rightAnswerCounter) { + return String.format("❓You canceled quiz\n" + "\n" + "The questions were: %d\n\n" + "✅ Right answers: %d\\%d\n" + "\n" + "Input " + UserBotConstants.START_QUIZ_COMMAND + " to start quiz or chose quiz another quiz " + UserBotConstants.CHOOSE_TOPIC_COMMAND, questionCount, rightAnswerCounter, questionCount); + } + private void setCountOfQuiz(String messageText, Long userId, QuizBotSession quizBotSession) { if (!messageText.matches("^[1-9][0-9]*$")) { sendMessage(userId, "Input a number or input " + UserBotConstants.CANCEL_COMMAND + " for cancel count of question choice"); diff --git a/src/main/java/org/example/configs/MongoDBConfig.java b/src/main/java/org/example/configs/MongoDBConfig.java index edd78e3..432a600 100644 --- a/src/main/java/org/example/configs/MongoDBConfig.java +++ b/src/main/java/org/example/configs/MongoDBConfig.java @@ -71,7 +71,6 @@ public ChangeStreamIterable runEventListener(MongoTemplate mongoTempla } case "delete" -> quizService.updateTopics(); } - }); return changeStream; } diff --git a/src/main/java/org/example/model/PermanentUserInfo.java b/src/main/java/org/example/model/PermanentUserInfo.java index 258fb0e..30024e7 100644 --- a/src/main/java/org/example/model/PermanentUserInfo.java +++ b/src/main/java/org/example/model/PermanentUserInfo.java @@ -8,9 +8,9 @@ public class PermanentUserInfo { @Id @Field(name = "userId") - private Long userId; + private Long userId = 0L; @Field(name = "userName") - private String userName; + private String userName = ""; public PermanentUserInfo() { } diff --git a/src/main/java/org/example/model/Question.java b/src/main/java/org/example/model/Question.java index 421b7fa..ab30262 100644 --- a/src/main/java/org/example/model/Question.java +++ b/src/main/java/org/example/model/Question.java @@ -12,7 +12,7 @@ public class Question { @Id @JsonIgnore - private ObjectId id; + private ObjectId id = new ObjectId(); private String question = ""; private String answerDescription = ""; private List optionList = new ArrayList<>(); diff --git a/src/main/java/org/example/model/QuizBotSession.java b/src/main/java/org/example/model/QuizBotSession.java index c4bec8a..65fff0e 100644 --- a/src/main/java/org/example/model/QuizBotSession.java +++ b/src/main/java/org/example/model/QuizBotSession.java @@ -8,7 +8,7 @@ public class QuizBotSession { private UserQuizSession userQuizSession; private String currentTopicName = ""; private int lastKeyboardBotMessageId = 0; - private String lastKeyboardBotMessageText; + private String lastKeyboardBotMessageText =""; private int countOfQuestion = 0; public QuizBotSession(QuizBotSessionMode botSessionMode) { diff --git a/src/main/java/org/example/services/QuizService.java b/src/main/java/org/example/services/QuizService.java index 445b39a..d1ba491 100644 --- a/src/main/java/org/example/services/QuizService.java +++ b/src/main/java/org/example/services/QuizService.java @@ -33,7 +33,7 @@ public List getTopics() { return topicsCache.get("topics"); } - public synchronized void addTopic(String topicName){ + public void addTopic(String topicName){ lock.lock(); try { List topics = new ArrayList<>(topicsCache.get("topics")); diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index 23c259b..50077b1 100644 --- a/src/main/resources/log4j2.xml +++ b/src/main/resources/log4j2.xml @@ -8,7 +8,7 @@ - + @@ -17,6 +17,5 @@ - diff --git a/src/main/resources/topics b/src/main/resources/topics deleted file mode 100644 index 72581d0..0000000 --- a/src/main/resources/topics +++ /dev/null @@ -1,4 +0,0 @@ -Python Programming -Spring Framework -Java Programming -CSS (Cascading Style Sheets) diff --git a/src/test/java/org/example/QuizQuestionsBotListenerTest.java b/src/test/java/org/example/QuizQuestionsBotListenerTest.java deleted file mode 100644 index 29d8443..0000000 --- a/src/test/java/org/example/QuizQuestionsBotListenerTest.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.example; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class QuizQuestionsBotListenerTest { - private QuizBotListener quizBotListener; - - @BeforeEach - void setUp() { - } - - @Test - void process() { - - } - -} \ No newline at end of file diff --git a/src/test/java/org/example/model/QuestionOptionTest.java b/src/test/java/org/example/model/QuestionOptionTest.java deleted file mode 100644 index 30890be..0000000 --- a/src/test/java/org/example/model/QuestionOptionTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.example.model; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class QuestionOptionTest { - - @Test - void getOptionText() { - } -} \ No newline at end of file diff --git a/src/test/java/org/example/model/QuestionTest.java b/src/test/java/org/example/model/QuestionTest.java deleted file mode 100644 index 4b5c04c..0000000 --- a/src/test/java/org/example/model/QuestionTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.example.model; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class QuestionTest { - private Question question; - - @BeforeEach - void setUp() { - question = new Question(); - } - - @Test - void getQuestion() { - Assertions.assertNotNull(question.getQuestion()); - } - - @Test - void getAnswerDescription() { - Assertions.assertNotNull(question.getAnswerDescription()); - } - - @Test - void getOptionList() { - Assertions.assertNotNull(question.getOptionList()); - } -} \ No newline at end of file diff --git a/src/test/java/org/example/model/QuizQuestionsTest.java b/src/test/java/org/example/model/QuizQuestionsTest.java deleted file mode 100644 index e1cc12b..0000000 --- a/src/test/java/org/example/model/QuizQuestionsTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.example.model; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -class QuizQuestionsTest { - private QuizQuestions quizQuestions; - - @BeforeEach - void setUp() { - quizQuestions = new QuizQuestions(); - } - - @Test - void getTopicName() { - assertNotNull(quizQuestions.getTopicName()); - } - - @Test - void setTopicName() { - quizQuestions.setTopicName(null); - Assertions.assertNotNull(quizQuestions.getTopicName()); - quizQuestions.setTopicName("java"); - Assertions.assertEquals(quizQuestions.getTopicName(),"java"); - } - - @Test - void getQuestionList() { - assertNotNull(quizQuestions.getQuestionList()); - } - - @Test - void setQuestionList() { - List questionList = new ArrayList<>(); - quizQuestions.setQuestionList(questionList); - Assertions.assertEquals(quizQuestions.getQuestionList(),questionList); - } -} \ No newline at end of file diff --git a/src/test/java/org/example/model/UserQuizQuestionsSessionTest.java b/src/test/java/org/example/model/UserQuizQuestionsSessionTest.java deleted file mode 100644 index 5ca08af..0000000 --- a/src/test/java/org/example/model/UserQuizQuestionsSessionTest.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.example.model; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.List; - -class UserQuizQuestionsSessionTest { - private UserQuizSession userQuizSession; - private Question question1; - private Question question2; - - @BeforeEach - public void setUp() { - List questionList = new ArrayList<>(); - question1 = new Question("asddsasda",new ArrayList<>(),"asdsdasd"); - question2 = new Question("asddsasdsssa",new ArrayList<>(),"asdsdasd"); - questionList.add(question1); - questionList.add(question2); - QuizQuestions quizQuestions = new QuizQuestions(); - quizQuestions.setQuestionList(questionList); - userQuizSession = new UserQuizSession(quizQuestions); - } - - @Test - void isNextQuestionAvailable(){ - Assertions.assertNotNull(userQuizSession.getNextQuestion()); - } - - - @Test - void incRightCounter() { - Assertions.assertEquals(userQuizSession.getRightAnswerCounter(),0); - userQuizSession.incRightCounter(); - Assertions.assertEquals(userQuizSession.getRightAnswerCounter(),1); - } - - @Test - void getCurrentQuestion() { - - } - - @Test - void getNextQuestion() { - Assertions.assertEquals(userQuizSession.getNextQuestion(), question1); - Assertions.assertEquals(userQuizSession.getNextQuestion(), question2); - } - - @Test - void getQuestionCounter() { - Assertions.assertEquals(userQuizSession.getQuestionCounter(),1); - userQuizSession.getNextQuestion(); - Assertions.assertEquals(userQuizSession.getQuestionCounter(),2); - userQuizSession.getNextQuestion(); - Assertions.assertEquals(userQuizSession.getQuestionCounter(),2); - } - - @Test - void getQuestionAmount() { - Assertions.assertEquals(userQuizSession.getQuestionAmount(),2); - } - - @Test - void getRightAnswerCounter() { - - } -} \ No newline at end of file diff --git a/src/test/java/services/QuizServiceTest.java b/src/test/java/services/QuizServiceTest.java new file mode 100644 index 0000000..04e00ed --- /dev/null +++ b/src/test/java/services/QuizServiceTest.java @@ -0,0 +1,5 @@ +package services; + +public class QuizServiceTest { + +} diff --git a/src/test/java/services/UsersService.java b/src/test/java/services/UsersService.java new file mode 100644 index 0000000..9842eee --- /dev/null +++ b/src/test/java/services/UsersService.java @@ -0,0 +1,4 @@ +package services; + +public class UsersService { +} From 6e52409fa91a8db2b24d267348aece05dac845b0 Mon Sep 17 00:00:00 2001 From: vladkuzhyr Date: Wed, 26 Jun 2024 21:57:57 +0300 Subject: [PATCH 06/11] fix indents in github-actions --- .github/workflows/github-actions.yml | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index e82c5ff..28d60e0 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -1,27 +1,26 @@ name: Build project + on: push: branches: - master pull_request: branches: - - * -jobs: + - '*' +jobs: Explore-GitHub-Actions: runs-on: ubuntu-latest steps: - - - uses: actions/checkout@v4 - - - name: Set up JDK 17 for x64 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'corretto' - architecture: x64 + - name: Checkout repository + uses: actions/checkout@v4 + - name: Set up JDK 17 for x64 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'corretto' + architecture: 'x64' - - name: Build & Test - run: - mvn -B clean package \ No newline at end of file + - name: Build & Test + run: mvn -B clean package From a9dc16adddfb7c825125a6a211d48ce4833724ee Mon Sep 17 00:00:00 2001 From: vladkuzhyr Date: Wed, 26 Jun 2024 22:01:01 +0300 Subject: [PATCH 07/11] test actions --- .github/workflows/github-actions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 28d60e0..f21bf6b 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -3,7 +3,7 @@ name: Build project on: push: branches: - - master + - actions pull_request: branches: - '*' From 61f47c49e474eef6fe5c629b0e468a71b4a9a24f Mon Sep 17 00:00:00 2001 From: vladkuzhyr Date: Wed, 26 Jun 2024 22:11:40 +0300 Subject: [PATCH 08/11] update github-actions.yml and docker-compose.yml --- .github/workflows/github-actions.yml | 3 +++ docker-compose.yml | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index f21bf6b..7cc41e5 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -24,3 +24,6 @@ jobs: - name: Build & Test run: mvn -B clean package + + - name: create & run docker image + run: make doc \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 6f4f509..6429811 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,5 +11,4 @@ services: ports: - "3000:3000" depends_on: - - bot - - prometheus \ No newline at end of file + - bot \ No newline at end of file From e04f439515131941d25715d06b29d6ba661a8356 Mon Sep 17 00:00:00 2001 From: vladkuzhyr Date: Wed, 26 Jun 2024 22:14:17 +0300 Subject: [PATCH 09/11] update github-actions.yml --- .github/workflows/github-actions.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 7cc41e5..7d2d4d6 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -3,10 +3,10 @@ name: Build project on: push: branches: - - actions + - * pull_request: branches: - - '*' + - * jobs: Explore-GitHub-Actions: @@ -26,4 +26,4 @@ jobs: run: mvn -B clean package - name: create & run docker image - run: make doc \ No newline at end of file + run: docker-compose up -d --build \ No newline at end of file From 1c1f4bdb2d347ec156ff95c923f42c47509bb370 Mon Sep 17 00:00:00 2001 From: vladkuzhyr Date: Wed, 26 Jun 2024 22:15:18 +0300 Subject: [PATCH 10/11] update github-actions.yml --- .github/workflows/github-actions.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 7d2d4d6..562fe4f 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -3,10 +3,10 @@ name: Build project on: push: branches: - - * + - "*" pull_request: branches: - - * + - "*" jobs: Explore-GitHub-Actions: From 44d87096f6ad7aaa2fe610b25d3d897ea7fc6acc Mon Sep 17 00:00:00 2001 From: vladkuzhyr Date: Wed, 26 Jun 2024 22:23:55 +0300 Subject: [PATCH 11/11] update github-actions.yml --- .github/workflows/github-actions.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml index 562fe4f..dbad7f8 100644 --- a/.github/workflows/github-actions.yml +++ b/.github/workflows/github-actions.yml @@ -25,5 +25,13 @@ jobs: - name: Build & Test run: mvn -B clean package - - name: create & run docker image - run: docker-compose up -d --build \ No newline at end of file + - name: Install Docker Compose + run: sudo apt-get update && sudo apt-get install -y docker-compose + + - name: Create & run Docker image + run: docker-compose up -d --build + + - name: Clean up Docker resources + run: | + docker-compose down + docker system prune -af \ No newline at end of file