diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml new file mode 100644 index 0000000..dbad7f8 --- /dev/null +++ b/.github/workflows/github-actions.yml @@ -0,0 +1,37 @@ +name: Build project + +on: + push: + branches: + - "*" + pull_request: + branches: + - "*" + +jobs: + Explore-GitHub-Actions: + runs-on: ubuntu-latest + steps: + - 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 + + - 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 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 dc98105..6429811 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,12 +2,9 @@ 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..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,19 +62,6 @@ - - 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/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 65999e0..0c70533 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 { @@ -41,10 +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(); + 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 @@ -60,73 +61,84 @@ 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)); - //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); + sendMessage(userId, UserBotConstants.STARTING_MESSAGE); sessionCache.remove(userId); 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 (quizBotSession.getBotSessionMode().equals(QuizBotSessionMode.QUESTION_COUNT_CHOICE)) { - sendMessage(userId, "You are not chosen quiz"); - break; + if (currentTopicName.isEmpty()) { + sendMessage(userId, "Pleas choice topic " + UserBotConstants.CHOOSE_TOPIC_COMMAND); + return UpdatesListener.CONFIRMED_UPDATES_ALL; } - - userQuizSession = new UserQuizSession(getGeneratedQuiz(currentTopicName, quizBotSession)); + 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 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"); + return; + } int countOfQuestions = Integer.parseInt(messageText); if (countOfQuestions > 20 || countOfQuestions < 5) { sendMessage(userId, "Input valid count of question"); @@ -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)); } @@ -289,26 +274,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)"); } @@ -322,14 +305,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/configs/MongoDBConfig.java b/src/main/java/org/example/configs/MongoDBConfig.java index de2d7af..432a600 100644 --- a/src/main/java/org/example/configs/MongoDBConfig.java +++ b/src/main/java/org/example/configs/MongoDBConfig.java @@ -1,8 +1,16 @@ 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.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.Value; import org.springframework.context.annotation.Bean; @@ -10,20 +18,25 @@ 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.MongoTemplate; 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") @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() { @@ -37,9 +50,28 @@ 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 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; + } + + switch (operationType) { + case "insert" -> { + Document document = event.getFullDocument(); + if (document != null && document.containsKey("topicName")) { + quizService.addTopic(document.getString("topicName")); + } + } + 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 582c5e3..30024e7 100644 --- a/src/main/java/org/example/model/PermanentUserInfo.java +++ b/src/main/java/org/example/model/PermanentUserInfo.java @@ -3,25 +3,21 @@ 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 { @Id @Field(name = "userId") - private Long userId; + private Long userId = 0L; @Field(name = "userName") - private String userName; - @Field(name = "isAdmin") - private boolean isAdmin = false; + private String userName = ""; 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/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 9d31329..65fff0e 100644 --- a/src/main/java/org/example/model/QuizBotSession.java +++ b/src/main/java/org/example/model/QuizBotSession.java @@ -5,11 +5,10 @@ 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 String lastKeyboardBotMessageText =""; private int countOfQuestion = 0; public QuizBotSession(QuizBotSessionMode botSessionMode) { @@ -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/repositories/QuizRepo.java b/src/main/java/org/example/repositories/QuizRepo.java index 07336eb..5c2d55b 100644 --- a/src/main/java/org/example/repositories/QuizRepo.java +++ b/src/main/java/org/example/repositories/QuizRepo.java @@ -1,27 +1,29 @@ package org.example.repositories; -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); + @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); - @Query("{'topicName' : ?0}") - @Update("{$push : {'questionList' : {$each : ?1}}}") - void addByTopic(String topicName, List questionList); + @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 4dbb92d..d1ba491 100644 --- a/src/main/java/org/example/services/QuizService.java +++ b/src/main/java/org/example/services/QuizService.java @@ -1,51 +1,55 @@ package org.example.services; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; +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.stream.Collectors; +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 final Cache> topicsCache; private final QuizRepo quizRepo; @Autowired public QuizService(QuizRepo quizRepo) { this.quizRepo = quizRepo; - topics = quizRepo.findAllTopicName(); + topicsCache = new Cache2kBuilder>() {} + .eternal(true) + .build(); + List topics = Arrays.stream(quizRepo.findAllTopic().split(",")).toList(); + topicsCache.put("topics", topics); } 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 topicsCache.get("topics"); } - public void deleteAllQuiz() { - topics = new ArrayList<>(); - quizRepo.deleteAll(); + public 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 QuizQuestions findByTopicName(String topicName) { - return quizRepo.findByTopicName(topicName); + 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); + } } 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; } 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/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/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 08f0e89..0000000 --- a/src/test/java/org/example/model/UserQuizQuestionsSessionTest.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.example.model; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Assertions; -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.assertTrue(userQuizSession.isNextQuestionAvailable()); - } - - @Test - void isNextQuestionNotAvailable() { - userQuizSession = new UserQuizSession(new QuizQuestions()); - Assertions.assertFalse(userQuizSession.isNextQuestionAvailable()); - } - - @Test - void incRightCounter() { - Assertions.assertEquals(userQuizSession.getRightAnswerCounter(),0); - userQuizSession.incRightCounter(); - Assertions.assertEquals(userQuizSession.getRightAnswerCounter(),1); - } - - @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 - void getNextQuestion() { - Assertions.assertEquals(userQuizSession.getNextQuestion(), question1); - Assertions.assertEquals(userQuizSession.getNextQuestion(), question2); - } - - @Test - void getQuestionCounter() { - Assertions.assertEquals(userQuizSession.getQuestionCounter(),0); - userQuizSession.getNextQuestion(); - 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() { - 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 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 { +}