1 HİSSƏ 2 HİSSƏ Təəssüf ki, məqalənin ilk versiyası xarakter məhdudiyyətinə uyğun gəlmədi, ona görə də burada bitirəcəyəm: QuizHandler:
package com.whiskels.telegram.bot.handler;
import com.whiskels.telegram.bot.State;
import com.whiskels.telegram.model.Question;
import com.whiskels.telegram.model.User;
import com.whiskels.telegram.repository.JpaQuestionRepository;
import com.whiskels.telegram.repository.JpaUserRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.telegram.telegrambots.meta.api.methods.PartialBotApiMethod;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.whiskels.telegram.util.TelegramUtil.createInlineKeyboardButton;
import static com.whiskels.telegram.util.TelegramUtil.createMessageTemplate;
@Slf4j
@Component
public class QuizHandler implements Handler {
//Храним поддерживаемые CallBackQuery в виде констант
public static final String QUIZ_CORRECT = "/quiz_correct";
public static final String QUIZ_INCORRECT = "/quiz_incorrect";
public static final String QUIZ_START = "/quiz_start";
//Храним варианты ответа
private static final List<string> OPTIONS = List.of("A", "B", "C", "D");
private final JpaUserRepository userRepository;
private final JpaQuestionRepository questionRepository;
public QuizHandler(JpaUserRepository userRepository, JpaQuestionRepository questionRepository) {
this.userRepository = userRepository;
this.questionRepository = questionRepository;
}
@Override
public List<partialbotapimethod<? extends="" serializable="">> handle(User user, String message) {
if (message.startsWith(QUIZ_CORRECT)) {
// действие на коллбек с правильным ответом
return correctAnswer(user, message);
} else if (message.startsWith(QUIZ_INCORRECT)) {
// действие на коллбек с неправильным ответом
return incorrectAnswer(user);
} else {
return startNewQuiz(user);
}
}
private List<partialbotapimethod<? extends="" serializable="">> correctAnswer(User user, String message) {
log.info("correct");
final int currentScore = user.getScore() + 1;
user.setScore(currentScore);
userRepository.save(user);
return nextQuestion(user);
}
private List<partialbotapimethod<? extends="" serializable="">> incorrectAnswer(User user) {
final int currentScore = user.getScore();
// Обновляем лучший итог
if (user.getHighScore() < currentScore) {
user.setHighScore(currentScore);
}
// Меняем статус пользователя
user.setScore(0);
user.setBotState(State.NONE);
userRepository.save(user);
// Создаем кнопку для повторного начала игры
InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup();
List<inlinekeyboardbutton> inlineKeyboardButtonsRowOne = List.of(
createInlineKeyboardButton("Try again?", QUIZ_START));
inlineKeyboardMarkup.setKeyboard(List.of(inlineKeyboardButtonsRowOne));
return List.of(createMessageTemplate(user)
.setText(String.format("Incorrect!%nYou scored *%d* points!", currentScore))
.setReplyMarkup(inlineKeyboardMarkup));
}
private List<partialbotapimethod<? extends="" serializable="">> startNewQuiz(User user) {
user.setBotState(State.PLAYING_QUIZ);
userRepository.save(user);
return nextQuestion(user);
}
private List<partialbotapimethod<? extends="" serializable="">> nextQuestion(User user) {
Question question = questionRepository.getRandomQuestion();
// Собираем список возможных вариантов ответа
List<string> options = new ArrayList<>(List.of(question.getCorrectAnswer(), question.getOptionOne(), question.getOptionTwo(), question.getOptionThree()));
// Перемешиваем
Collections.shuffle(options);
// Начинаем формировать сообщение с вопроса
StringBuilder sb = new StringBuilder();
sb.append('*')
.append(question.getQuestion())
.append("*\n\n");
InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup();
// Создаем два ряда кнопок
List<inlinekeyboardbutton> inlineKeyboardButtonsRowOne = new ArrayList<>();
List<inlinekeyboardbutton> inlineKeyboardButtonsRowTwo = new ArrayList<>();
// Формируем сообщение и записываем CallBackData на кнопки
for (int i = 0; i < options.size(); i++) {
InlineKeyboardButton button = new InlineKeyboardButton();
final String callbackData = options.get(i).equalsIgnoreCase(question.getCorrectAnswer()) ? QUIZ_CORRECT : QUIZ_INCORRECT;
button.setText(OPTIONS.get(i))
.setCallbackData(String.format("%s %d", callbackData, question.getId()));
if (i < 2) {
inlineKeyboardButtonsRowOne.add(button);
} else {
inlineKeyboardButtonsRowTwo.add(button);
}
sb.append(OPTIONS.get(i) + ". " + options.get(i));
sb.append("\n");
}
inlineKeyboardMarkup.setKeyboard(List.of(inlineKeyboardButtonsRowOne, inlineKeyboardButtonsRowTwo));
return List.of(createMessageTemplate(user)
.setText(sb.toString())
.setReplyMarkup(inlineKeyboardMarkup));
}
@Override
public State operatedBotState() {
return null;
}
@Override
public List<string> operatedCallBackQuery() {
return List.of(QUIZ_START, QUIZ_CORRECT, QUIZ_INCORRECT);
}
}
<h3>Verilənlər bazasının doldurulması</h3>Burada verilənlər bazasını işə salma skripti ilə bənzətmə ilə suallarımızı yazacağıq.
DELETE
FROM java_quiz;
INSERT INTO java_quiz (question, answer_correct, option1, option2, option3)
VALUES ('What is a correct syntax to output "Hello World" in Java?', 'System.out.println("Hello World!");',
'print("Hello World!");', 'sout("Hello World!");', 'Systemout.print("Hello world!");'),
('What is the correct way to create an object called foo of Bar class?', 'Bar foo = new Bar();',
'Foo bar = new Foo();', 'Bar foo() = new Foo();', 'Foo bar() = new Bar();'),
('Which operator can be used to compare two values?', '==', '=', '&', '==='),
('Which method can be used to return a string in upper case letters?', 'toUpperCase()', 'camelCase()',
'upperCase()', 'formatUpper()'),
('Which method can be used to find the length of a string?', 'length()', 'getSize()', 'len()', 'getLength()'),
('Which data type is used to create a variable that should store text?', 'String', 'Text', 'Varchar', 'const'),
('How to insert a comment?', '// like this', '# like this', '<-- like this -->', '/ like this');
Qalan yalnız application.yaml düzəltməkdir:
bot:
name: JavaQuiz
token: 1234567:AAF0Wru1Z60p8vPtKihx3odbwSv9O0y_-MM
spring:
datasource:
url: jdbc:postgresql://ec2-54-75-199-252.eu-west-1.compute.amazonaws.com:5432/d5p9skg6nin3mh?user=bozuqwnhjhoubl&password=8a40050de8a0014c14df49aeaac5880f1ac633cc20c78a4cc3b32323231
driver-class-name: org.postgresql.Driver
initialization-mode: never
jpa:
database-platform: org.hibernate.dialect.PostgreSQLDialect
show-sql: true
hibernate:
ddl-auto: update
Verilənlər bazası URL-i Heroku-da URI sahəsində qeyd olunanlardan fərqlidir, ona görə də onun necə qurulmasına dair qısa məlumat vərəqi:
jdbc:postgresql://{Host}:{Port}/{Database}?user={User}&password={Password}
Əgər biz hər şeyi düzgün etmişiksə, o zaman main-i işə saldıqda stacktrace-i görməyəcəyik, hətta əksinə:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.4.RELEASE)
2020-10-02 19:27:43.081 INFO 14536 --- [ main] com.whiskels.telegram.App : Starting App on Kuzmin with PID 14536 (D:\utilities\forJavaRush\target\classes started by whiskels in D:\utilities\forJavaRush)
2020-10-02 19:27:43.087 INFO 14536 --- [ main] com.whiskels.telegram.App : No active profile set, falling back to default profiles: default
2020-10-02 19:27:44.014 INFO 14536 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2020-10-02 19:27:44.131 INFO 14536 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 102ms. Found 2 JPA repository interfaces.
2020-10-02 19:27:44.774 INFO 14536 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2020-10-02 19:27:44.885 INFO 14536 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.4.10.Final}
2020-10-02 19:27:45.053 INFO 14536 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2020-10-02 19:27:45.278 INFO 14536 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2020-10-02 19:27:46.770 INFO 14536 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2020-10-02 19:27:46.790 INFO 14536 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
2020-10-02 19:27:49.731 INFO 14536 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2020-10-02 19:27:49.741 INFO 14536 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2020-10-02 19:27:50.817 INFO 14536 --- [ main] c.g.x.bots.TelegramBotAutoConfiguration : Starting auto config for telegram bots
2020-10-02 19:27:50.830 INFO 14536 --- [ main] c.g.x.bots.TelegramBotAutoConfiguration : Initializing API without webhook support
2020-10-02 19:27:50.831 INFO 14536 --- [ main] c.g.x.bots.TelegramBotAutoConfiguration : Registering polling bot: JavaQuiz
2020-10-02 19:27:51.556 INFO 14536 --- [ main] com.whiskels.telegram.App : Started App in 9.196 seconds (JVM running for 10.023)
Gəlin botumuzla ünsiyyət qurmağa çalışaq: Gəlin tanış olaq Gəlin oynayaq Yardım soruşun Bitdi! Viktorina botu yazdıq. İndi qarşımızda böyük bir iş var - bizə lazımdır:
- bu gün yazılan kodu başa düşmək;
- Spring Data sənədlərini oxuyun;
- logger əlavə edin;
- refaktorinq etmək;
- dizayn nümunələrini tətbiq etmək;
- yardım istəməyi təkcə dövlətlə deyil.
- yeni funksionallıq əlavə etmək;
- lider lövhələri;
- yalnız unikal suallar vermək;
- suallar kateqoriyaları.
GO TO FULL VERSION