From 801e19e07b5a07861a153f0faf616a656e5486b3 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Fri, 16 Jan 2026 17:31:52 +0500 Subject: [PATCH 01/65] initial commit --- .../javarush/{khmelov => vasileva}/cmd/Command.java | 2 +- .../javarush/{khmelov => vasileva}/cmd/EditUser.java | 8 ++++---- .../javarush/{khmelov => vasileva}/cmd/ListUser.java | 6 +++--- .../javarush/{khmelov => vasileva}/cmd/StartPage.java | 2 +- .../javarush/{khmelov => vasileva}/config/Winter.java | 2 +- .../controller/FrontController.java | 10 +++++----- .../{khmelov => vasileva}/controller/HttpResolver.java | 6 +++--- .../javarush/{khmelov => vasileva}/entity/Role.java | 2 +- .../javarush/{khmelov => vasileva}/entity/User.java | 2 +- .../{khmelov => vasileva}/repository/Repository.java | 4 ++-- .../repository/UserRepository.java | 6 +++--- .../{khmelov => vasileva}/service/UserService.java | 6 +++--- 12 files changed, 28 insertions(+), 28 deletions(-) rename src/main/java/com/javarush/{khmelov => vasileva}/cmd/Command.java (96%) rename src/main/java/com/javarush/{khmelov => vasileva}/cmd/EditUser.java (88%) rename src/main/java/com/javarush/{khmelov => vasileva}/cmd/ListUser.java (79%) rename src/main/java/com/javarush/{khmelov => vasileva}/cmd/StartPage.java (68%) rename src/main/java/com/javarush/{khmelov => vasileva}/config/Winter.java (96%) rename src/main/java/com/javarush/{khmelov => vasileva}/controller/FrontController.java (85%) rename src/main/java/com/javarush/{khmelov => vasileva}/controller/HttpResolver.java (91%) rename src/main/java/com/javarush/{khmelov => vasileva}/entity/Role.java (54%) rename src/main/java/com/javarush/{khmelov => vasileva}/entity/User.java (90%) rename src/main/java/com/javarush/{khmelov => vasileva}/repository/Repository.java (74%) rename src/main/java/com/javarush/{khmelov => vasileva}/repository/UserRepository.java (90%) rename src/main/java/com/javarush/{khmelov => vasileva}/service/UserService.java (82%) diff --git a/src/main/java/com/javarush/khmelov/cmd/Command.java b/src/main/java/com/javarush/vasileva/cmd/Command.java similarity index 96% rename from src/main/java/com/javarush/khmelov/cmd/Command.java rename to src/main/java/com/javarush/vasileva/cmd/Command.java index fd4035b..36e6f71 100644 --- a/src/main/java/com/javarush/khmelov/cmd/Command.java +++ b/src/main/java/com/javarush/vasileva/cmd/Command.java @@ -1,4 +1,4 @@ -package com.javarush.khmelov.cmd; +package com.javarush.vasileva.cmd; import jakarta.servlet.http.HttpServletRequest; diff --git a/src/main/java/com/javarush/khmelov/cmd/EditUser.java b/src/main/java/com/javarush/vasileva/cmd/EditUser.java similarity index 88% rename from src/main/java/com/javarush/khmelov/cmd/EditUser.java rename to src/main/java/com/javarush/vasileva/cmd/EditUser.java index ae191b4..bc7c4ed 100644 --- a/src/main/java/com/javarush/khmelov/cmd/EditUser.java +++ b/src/main/java/com/javarush/vasileva/cmd/EditUser.java @@ -1,8 +1,8 @@ -package com.javarush.khmelov.cmd; +package com.javarush.vasileva.cmd; -import com.javarush.khmelov.entity.Role; -import com.javarush.khmelov.entity.User; -import com.javarush.khmelov.service.UserService; +import com.javarush.vasileva.entity.Role; +import com.javarush.vasileva.entity.User; +import com.javarush.vasileva.service.UserService; import jakarta.servlet.http.HttpServletRequest; import java.util.Optional; diff --git a/src/main/java/com/javarush/khmelov/cmd/ListUser.java b/src/main/java/com/javarush/vasileva/cmd/ListUser.java similarity index 79% rename from src/main/java/com/javarush/khmelov/cmd/ListUser.java rename to src/main/java/com/javarush/vasileva/cmd/ListUser.java index 9257917..fcf4b25 100644 --- a/src/main/java/com/javarush/khmelov/cmd/ListUser.java +++ b/src/main/java/com/javarush/vasileva/cmd/ListUser.java @@ -1,7 +1,7 @@ -package com.javarush.khmelov.cmd; +package com.javarush.vasileva.cmd; -import com.javarush.khmelov.entity.User; -import com.javarush.khmelov.service.UserService; +import com.javarush.vasileva.entity.User; +import com.javarush.vasileva.service.UserService; import jakarta.servlet.http.HttpServletRequest; import java.util.Collection; diff --git a/src/main/java/com/javarush/khmelov/cmd/StartPage.java b/src/main/java/com/javarush/vasileva/cmd/StartPage.java similarity index 68% rename from src/main/java/com/javarush/khmelov/cmd/StartPage.java rename to src/main/java/com/javarush/vasileva/cmd/StartPage.java index d268f93..bd5e154 100644 --- a/src/main/java/com/javarush/khmelov/cmd/StartPage.java +++ b/src/main/java/com/javarush/vasileva/cmd/StartPage.java @@ -1,4 +1,4 @@ -package com.javarush.khmelov.cmd; +package com.javarush.vasileva.cmd; @SuppressWarnings("unused") public class StartPage implements Command { diff --git a/src/main/java/com/javarush/khmelov/config/Winter.java b/src/main/java/com/javarush/vasileva/config/Winter.java similarity index 96% rename from src/main/java/com/javarush/khmelov/config/Winter.java rename to src/main/java/com/javarush/vasileva/config/Winter.java index 48bd8a7..53de644 100644 --- a/src/main/java/com/javarush/khmelov/config/Winter.java +++ b/src/main/java/com/javarush/vasileva/config/Winter.java @@ -1,4 +1,4 @@ -package com.javarush.khmelov.config; +package com.javarush.vasileva.config; import lombok.SneakyThrows; diff --git a/src/main/java/com/javarush/khmelov/controller/FrontController.java b/src/main/java/com/javarush/vasileva/controller/FrontController.java similarity index 85% rename from src/main/java/com/javarush/khmelov/controller/FrontController.java rename to src/main/java/com/javarush/vasileva/controller/FrontController.java index 33242b2..18d736f 100644 --- a/src/main/java/com/javarush/khmelov/controller/FrontController.java +++ b/src/main/java/com/javarush/vasileva/controller/FrontController.java @@ -1,8 +1,8 @@ -package com.javarush.khmelov.controller; +package com.javarush.vasileva.controller; -import com.javarush.khmelov.cmd.Command; -import com.javarush.khmelov.config.Winter; -import com.javarush.khmelov.entity.Role; +import com.javarush.vasileva.cmd.Command; +import com.javarush.vasileva.config.Winter; +import com.javarush.vasileva.entity.Role; import jakarta.servlet.ServletConfig; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; @@ -35,7 +35,7 @@ private static String getJsp(String view) { } @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { Command command = httpResolver.resolve(req); String redirect = command.doPost(req); resp.sendRedirect(redirect); diff --git a/src/main/java/com/javarush/khmelov/controller/HttpResolver.java b/src/main/java/com/javarush/vasileva/controller/HttpResolver.java similarity index 91% rename from src/main/java/com/javarush/khmelov/controller/HttpResolver.java rename to src/main/java/com/javarush/vasileva/controller/HttpResolver.java index 18bb761..3b29028 100644 --- a/src/main/java/com/javarush/khmelov/controller/HttpResolver.java +++ b/src/main/java/com/javarush/vasileva/controller/HttpResolver.java @@ -1,7 +1,7 @@ -package com.javarush.khmelov.controller; +package com.javarush.vasileva.controller; -import com.javarush.khmelov.cmd.Command; -import com.javarush.khmelov.config.Winter; +import com.javarush.vasileva.cmd.Command; +import com.javarush.vasileva.config.Winter; import jakarta.servlet.http.HttpServletRequest; public class HttpResolver { diff --git a/src/main/java/com/javarush/khmelov/entity/Role.java b/src/main/java/com/javarush/vasileva/entity/Role.java similarity index 54% rename from src/main/java/com/javarush/khmelov/entity/Role.java rename to src/main/java/com/javarush/vasileva/entity/Role.java index 5ae365f..5c6bacf 100644 --- a/src/main/java/com/javarush/khmelov/entity/Role.java +++ b/src/main/java/com/javarush/vasileva/entity/Role.java @@ -1,4 +1,4 @@ -package com.javarush.khmelov.entity; +package com.javarush.vasileva.entity; public enum Role { USER, ADMIN, GUEST diff --git a/src/main/java/com/javarush/khmelov/entity/User.java b/src/main/java/com/javarush/vasileva/entity/User.java similarity index 90% rename from src/main/java/com/javarush/khmelov/entity/User.java rename to src/main/java/com/javarush/vasileva/entity/User.java index f7fa2d6..79ad921 100644 --- a/src/main/java/com/javarush/khmelov/entity/User.java +++ b/src/main/java/com/javarush/vasileva/entity/User.java @@ -1,4 +1,4 @@ -package com.javarush.khmelov.entity; +package com.javarush.vasileva.entity; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/src/main/java/com/javarush/khmelov/repository/Repository.java b/src/main/java/com/javarush/vasileva/repository/Repository.java similarity index 74% rename from src/main/java/com/javarush/khmelov/repository/Repository.java rename to src/main/java/com/javarush/vasileva/repository/Repository.java index f1abdac..96ac885 100644 --- a/src/main/java/com/javarush/khmelov/repository/Repository.java +++ b/src/main/java/com/javarush/vasileva/repository/Repository.java @@ -1,6 +1,6 @@ -package com.javarush.khmelov.repository; +package com.javarush.vasileva.repository; -import com.javarush.khmelov.entity.User; +import com.javarush.vasileva.entity.User; import java.util.Collection; import java.util.Optional; diff --git a/src/main/java/com/javarush/khmelov/repository/UserRepository.java b/src/main/java/com/javarush/vasileva/repository/UserRepository.java similarity index 90% rename from src/main/java/com/javarush/khmelov/repository/UserRepository.java rename to src/main/java/com/javarush/vasileva/repository/UserRepository.java index 58b32ea..a3528d0 100644 --- a/src/main/java/com/javarush/khmelov/repository/UserRepository.java +++ b/src/main/java/com/javarush/vasileva/repository/UserRepository.java @@ -1,7 +1,7 @@ -package com.javarush.khmelov.repository; +package com.javarush.vasileva.repository; -import com.javarush.khmelov.entity.Role; -import com.javarush.khmelov.entity.User; +import com.javarush.vasileva.entity.Role; +import com.javarush.vasileva.entity.User; import java.util.Collection; import java.util.HashMap; diff --git a/src/main/java/com/javarush/khmelov/service/UserService.java b/src/main/java/com/javarush/vasileva/service/UserService.java similarity index 82% rename from src/main/java/com/javarush/khmelov/service/UserService.java rename to src/main/java/com/javarush/vasileva/service/UserService.java index b17527c..ad963cc 100644 --- a/src/main/java/com/javarush/khmelov/service/UserService.java +++ b/src/main/java/com/javarush/vasileva/service/UserService.java @@ -1,7 +1,7 @@ -package com.javarush.khmelov.service; +package com.javarush.vasileva.service; -import com.javarush.khmelov.entity.User; -import com.javarush.khmelov.repository.UserRepository; +import com.javarush.vasileva.entity.User; +import com.javarush.vasileva.repository.UserRepository; import java.util.Collection; import java.util.Optional; From 005fd631d7d5b24e98bdc2838c361c70ae3d255f Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Tue, 20 Jan 2026 22:59:28 +0500 Subject: [PATCH 02/65] ADD entities (Quest, Question, Answer) --- .../com/javarush/vasileva/cmd/StartPage.java | 6 ------ .../com/javarush/vasileva/entity/Answer.java | 18 +++++++++++++++++ .../com/javarush/vasileva/entity/Quest.java | 20 +++++++++++++++++++ .../javarush/vasileva/entity/Question.java | 19 ++++++++++++++++++ 4 files changed, 57 insertions(+), 6 deletions(-) delete mode 100644 src/main/java/com/javarush/vasileva/cmd/StartPage.java create mode 100644 src/main/java/com/javarush/vasileva/entity/Answer.java create mode 100644 src/main/java/com/javarush/vasileva/entity/Quest.java create mode 100644 src/main/java/com/javarush/vasileva/entity/Question.java diff --git a/src/main/java/com/javarush/vasileva/cmd/StartPage.java b/src/main/java/com/javarush/vasileva/cmd/StartPage.java deleted file mode 100644 index bd5e154..0000000 --- a/src/main/java/com/javarush/vasileva/cmd/StartPage.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.javarush.vasileva.cmd; - -@SuppressWarnings("unused") -public class StartPage implements Command { - -} diff --git a/src/main/java/com/javarush/vasileva/entity/Answer.java b/src/main/java/com/javarush/vasileva/entity/Answer.java new file mode 100644 index 0000000..a0dd730 --- /dev/null +++ b/src/main/java/com/javarush/vasileva/entity/Answer.java @@ -0,0 +1,18 @@ +package com.javarush.vasileva.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class Answer { + private Long id; + private Long questionId; + private Long nextQuestionId; + private String text; + private String description; +} diff --git a/src/main/java/com/javarush/vasileva/entity/Quest.java b/src/main/java/com/javarush/vasileva/entity/Quest.java new file mode 100644 index 0000000..854bc72 --- /dev/null +++ b/src/main/java/com/javarush/vasileva/entity/Quest.java @@ -0,0 +1,20 @@ +package com.javarush.vasileva.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class Quest { + private Long id; + private String title; + private String description; + private Long startQuestionId = 1L; + private List questions; +} diff --git a/src/main/java/com/javarush/vasileva/entity/Question.java b/src/main/java/com/javarush/vasileva/entity/Question.java new file mode 100644 index 0000000..360d68a --- /dev/null +++ b/src/main/java/com/javarush/vasileva/entity/Question.java @@ -0,0 +1,19 @@ +package com.javarush.vasileva.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class Question { + private Long id; + private Long questId; + private String text; + private List answers; +} From 7067bcb61405e00d637e4a6283ba7ec2679c9a5d Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Tue, 20 Jan 2026 23:18:42 +0500 Subject: [PATCH 03/65] ADD services and repositories (Quest, Question) --- .../vasileva/repository/QuestRepository.java | 38 ++++++++++++++++++ .../repository/QuestionRepository.java | 40 +++++++++++++++++++ .../vasileva/repository/Repository.java | 6 +-- .../vasileva/repository/UserRepository.java | 9 ++--- .../vasileva/service/BaseService.java | 13 ++++++ .../vasileva/service/QuestService.java | 31 ++++++++++++++ .../vasileva/service/QuestionService.java | 32 +++++++++++++++ .../vasileva/service/UserService.java | 10 +++-- 8 files changed, 165 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/javarush/vasileva/repository/QuestRepository.java create mode 100644 src/main/java/com/javarush/vasileva/repository/QuestionRepository.java create mode 100644 src/main/java/com/javarush/vasileva/service/BaseService.java create mode 100644 src/main/java/com/javarush/vasileva/service/QuestService.java create mode 100644 src/main/java/com/javarush/vasileva/service/QuestionService.java diff --git a/src/main/java/com/javarush/vasileva/repository/QuestRepository.java b/src/main/java/com/javarush/vasileva/repository/QuestRepository.java new file mode 100644 index 0000000..028a77f --- /dev/null +++ b/src/main/java/com/javarush/vasileva/repository/QuestRepository.java @@ -0,0 +1,38 @@ +package com.javarush.vasileva.repository; + +import com.javarush.vasileva.entity.Quest; +import lombok.NoArgsConstructor; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +@NoArgsConstructor +public class QuestRepository implements Repository { + + private final Map quests = new ConcurrentHashMap<>(); + + @Override + public List getAll() { + return new ArrayList<>(quests.values()); + } + + @Override + public Optional get(long id) { + return Optional.ofNullable(quests.get(id)); + } + + @Override + public void create(Quest entity) { + quests.put(entity.getId(), entity); + } + + @Override + public void update(Quest entity) { + + } + + @Override + public void delete(Quest entity) { + + } +} diff --git a/src/main/java/com/javarush/vasileva/repository/QuestionRepository.java b/src/main/java/com/javarush/vasileva/repository/QuestionRepository.java new file mode 100644 index 0000000..1f3c46a --- /dev/null +++ b/src/main/java/com/javarush/vasileva/repository/QuestionRepository.java @@ -0,0 +1,40 @@ +package com.javarush.vasileva.repository; + +import com.javarush.vasileva.entity.Question; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +@NoArgsConstructor +public class QuestionRepository implements Repository { + private final Map questions = new ConcurrentHashMap<>(); + + @Override + public List getAll() { + return new ArrayList<>(questions.values()); + } + + @Override + public Optional get(long id) { + return Optional.ofNullable(questions.get(id)); + } + + @Override + public void create(Question question) { + questions.put(question.getId(), question); + } + + @Override + public void update(Question entity) { + + } + + @Override + public void delete(Question entity) { + + } +} diff --git a/src/main/java/com/javarush/vasileva/repository/Repository.java b/src/main/java/com/javarush/vasileva/repository/Repository.java index 96ac885..1fdbbd0 100644 --- a/src/main/java/com/javarush/vasileva/repository/Repository.java +++ b/src/main/java/com/javarush/vasileva/repository/Repository.java @@ -1,13 +1,11 @@ package com.javarush.vasileva.repository; -import com.javarush.vasileva.entity.User; - -import java.util.Collection; +import java.util.List; import java.util.Optional; public interface Repository { - Collection getAll(); + List getAll(); Optional get(long id); diff --git a/src/main/java/com/javarush/vasileva/repository/UserRepository.java b/src/main/java/com/javarush/vasileva/repository/UserRepository.java index a3528d0..fa68823 100644 --- a/src/main/java/com/javarush/vasileva/repository/UserRepository.java +++ b/src/main/java/com/javarush/vasileva/repository/UserRepository.java @@ -3,10 +3,7 @@ import com.javarush.vasileva.entity.Role; import com.javarush.vasileva.entity.User; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.concurrent.atomic.AtomicLong; public class UserRepository implements Repository { @@ -23,8 +20,8 @@ public UserRepository() { } @Override - public Collection getAll() { - return map.values(); + public List getAll() { + return new ArrayList<>(map.values()); } @Override diff --git a/src/main/java/com/javarush/vasileva/service/BaseService.java b/src/main/java/com/javarush/vasileva/service/BaseService.java new file mode 100644 index 0000000..e535f5c --- /dev/null +++ b/src/main/java/com/javarush/vasileva/service/BaseService.java @@ -0,0 +1,13 @@ +package com.javarush.vasileva.service; + +import java.util.List; +import java.util.Optional; + +public interface BaseService { + + List getAll(); + + Optional get(Long id); + + void create(T entity); +} diff --git a/src/main/java/com/javarush/vasileva/service/QuestService.java b/src/main/java/com/javarush/vasileva/service/QuestService.java new file mode 100644 index 0000000..cb5a00a --- /dev/null +++ b/src/main/java/com/javarush/vasileva/service/QuestService.java @@ -0,0 +1,31 @@ +package com.javarush.vasileva.service; + +import com.javarush.vasileva.entity.Quest; +import com.javarush.vasileva.repository.QuestRepository; +import com.javarush.vasileva.repository.Repository; + +import java.util.List; +import java.util.Optional; + +public class QuestService implements BaseService { + private final Repository questRepository; + + public QuestService(QuestRepository questRepository) { + this.questRepository = questRepository; + } + + @Override + public List getAll() { + return questRepository.getAll(); + } + + @Override + public Optional get(Long id) { + return questRepository.get(id); + } + + @Override + public void create(Quest entity) { + questRepository.create(entity); + } +} diff --git a/src/main/java/com/javarush/vasileva/service/QuestionService.java b/src/main/java/com/javarush/vasileva/service/QuestionService.java new file mode 100644 index 0000000..83c221e --- /dev/null +++ b/src/main/java/com/javarush/vasileva/service/QuestionService.java @@ -0,0 +1,32 @@ +package com.javarush.vasileva.service; + +import com.javarush.vasileva.entity.Question; +import com.javarush.vasileva.repository.QuestionRepository; +import com.javarush.vasileva.repository.Repository; + +import java.util.List; +import java.util.Optional; + +public class QuestionService implements BaseService { + + private final Repository questionRepository; + + public QuestionService(QuestionRepository questionRepository) { + this.questionRepository = questionRepository; + } + + @Override + public List getAll() { + return questionRepository.getAll(); + } + + @Override + public Optional get(Long id) { + return questionRepository.get(id); + } + + @Override + public void create(Question question) { + questionRepository.create(question); + } +} diff --git a/src/main/java/com/javarush/vasileva/service/UserService.java b/src/main/java/com/javarush/vasileva/service/UserService.java index ad963cc..9daaa89 100644 --- a/src/main/java/com/javarush/vasileva/service/UserService.java +++ b/src/main/java/com/javarush/vasileva/service/UserService.java @@ -3,10 +3,10 @@ import com.javarush.vasileva.entity.User; import com.javarush.vasileva.repository.UserRepository; -import java.util.Collection; +import java.util.List; import java.util.Optional; -public class UserService { +public class UserService implements BaseService { private final UserRepository userRepository; @@ -14,6 +14,7 @@ public UserService(UserRepository userRepository) { this.userRepository = userRepository; } + @Override public void create(User user) { userRepository.create(user); } @@ -26,11 +27,12 @@ public void delete(User user) { userRepository.delete(user); } - public Collection getAll() { + public List getAll() { return userRepository.getAll(); } - public Optional get(long id) { + @Override + public Optional get(Long id) { return userRepository.get(id); } } From 593b08de79931afcdf155b387c76aa54dae07ada Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Tue, 20 Jan 2026 23:23:40 +0500 Subject: [PATCH 04/65] ADD json mapper for quests + quest.json --- pom.xml | 4 + .../javarush/vasileva/mapper/QuestMapper.java | 56 ++++ src/main/resources/quest-1.json | 82 +++++ src/main/resources/quest-2.json | 298 ++++++++++++++++++ 4 files changed, 440 insertions(+) create mode 100644 src/main/java/com/javarush/vasileva/mapper/QuestMapper.java create mode 100644 src/main/resources/quest-1.json create mode 100644 src/main/resources/quest-2.json diff --git a/pom.xml b/pom.xml index 78ee59d..dd6a0bb 100644 --- a/pom.xml +++ b/pom.xml @@ -66,6 +66,10 @@ test + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + diff --git a/src/main/java/com/javarush/vasileva/mapper/QuestMapper.java b/src/main/java/com/javarush/vasileva/mapper/QuestMapper.java new file mode 100644 index 0000000..a99d5a8 --- /dev/null +++ b/src/main/java/com/javarush/vasileva/mapper/QuestMapper.java @@ -0,0 +1,56 @@ +package com.javarush.vasileva.mapper; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.javarush.vasileva.entity.Quest; + +import java.io.File; +import java.io.IOException; + +public class QuestMapper { + private final ObjectMapper objectMapper; + + public QuestMapper() { + this.objectMapper = new ObjectMapper(); + } + + /** + * Читает JSON файл и преобразует в объект Quest. + * @param filePath Путь к JSON файлу + * @return Объект Quest + * @throws IOException Если файл не найден или ошибка парсинга + */ + public Quest readFromJson(String filePath) throws IOException { + File file = new File(filePath); + return objectMapper.readValue(file, Quest.class); + } + + /** + * Сохраняет объект Quest в JSON файл. + * @param quest Объект квеста + * @param filePath Путь для сохранения + * @throws IOException Если ошибка записи + */ + public void writeToJson(Quest quest, String filePath) throws IOException { + objectMapper.writeValue(new File(filePath), quest); + } + + /** + * Преобразует JSON строку в объект Quest. + * @param jsonString JSON в виде строки + * @return Объект Quest + * @throws IOException Если ошибка парсинга + */ + public Quest fromJsonString(String jsonString) throws IOException { + return objectMapper.readValue(jsonString, Quest.class); + } + + /** + * Преобразует объект Quest в JSON строку. + * @param quest Объект квеста + * @return JSON строка + * @throws IOException Если ошибка преобразования + */ + public String toJsonString(Quest quest) throws IOException { + return objectMapper.writeValueAsString(quest); + } +} diff --git a/src/main/resources/quest-1.json b/src/main/resources/quest-1.json new file mode 100644 index 0000000..f6df9d6 --- /dev/null +++ b/src/main/resources/quest-1.json @@ -0,0 +1,82 @@ +{ + "id": 1, + "title": "Космическое приключение", + "description": "Про приключения в космосе", + "questions": [ + { + "id": 1, + "questId": 1, + "text": "Принять вызов НЛО?", + "answers": [ + { + "id": 11, + "questionId": 1, + "nextQuestionId": 2, + "text": "Принять вызов" + }, + { + "id": 12, + "questionId": 1, + "nextQuestionId": 910, + "text": "Отклонить вызов" + } + ] + }, + { + "id": 2, + "questId": 1, + "text": "Поднимешься на мостик к капитану?", + "answers": [ + { + "id": 21, + "questionId": 2, + "nextQuestionId": 3, + "text": "Подняться на мостик" + }, + { + "id": 22, + "questionId": 2, + "nextQuestionId": 910, + "text": "Отказаться подниматься на мостик" + } + ] + }, + { + "id": 3, + "questId": 1, + "text": "Ты поднялся на мостик. Ты кто?", + "answers": [ + { + "id": 31, + "questionId": 3, + "nextQuestionId": 810, + "text": "Рассказать правду о себе" + }, + { + "id": 32, + "questionId": 3, + "nextQuestionId": 911, + "text": "Солгать о себе" + } + ] + }, + { + "id": 810, + "questId": 1, + "text": "Тебя вернули домой, победа", + "answers": null + }, + { + "id": 910, + "questId": 1, + "text": "Ты отклонил вызов, поражение", + "answers": null + }, + { + "id": 911, + "questId": 1, + "text": "Твою ложь разоблачили, поражение", + "answers": null + } + ] +} diff --git a/src/main/resources/quest-2.json b/src/main/resources/quest-2.json new file mode 100644 index 0000000..f10f0b5 --- /dev/null +++ b/src/main/resources/quest-2.json @@ -0,0 +1,298 @@ +{ + "id": 2, + "title": "Тайна Забытого Подземелья", + "description": "Много веков назад дракон Вельдан, хранитель древних знаний, скрылся в недрах горы с Сердцем Дракона — артефактом невообразимой силы, спрятав его в лабиринте, известном как Забытое Подземелье. Тысячи смельчаков отправлялись на поиски реликвии, но никто не вернулся; легенды гласят, что лишь тот, кто проявит мудрость, отвагу и хладнокровие, сможет завладеть Сердцем. Теперь вы — один из искателей: с факелом и мечом перед массивной дверью с драконьей пастью, за которой таятся тьма, сырость и нечто древнее. Дверь медленно приоткрывается — готовы ли вы бросить вызов подземелью?", + "questions": [ + { + "id": 1, + "questId": 2, + "text": "Вы входите в тёмный коридор. Впереди слышен шорох.", + "answers": [ + { + "id": 11, + "questionId": 1, + "nextQuestionId": 2, + "text": "Достанете факел и осторожно продвинетесь вперёд.", + "description": "" + }, + { + "id": 12, + "questionId": 1, + "nextQuestionId": 2, + "text": "Бросите камень в сторону шума, чтобы проверить.", + "description": "Вы пугаете крысу. Путь свободен." + }, + { + "id": 13, + "questionId": 1, + "nextQuestionId": 910, + "text": "Повернётесь и пойдёте назад.", + "description": "Попадаете в тупик." + }, + { + "id": 14, + "questionId": 1, + "nextQuestionId": 910, + "text": "Закричите, чтобы отпугнуть возможного врага.", + "description": "Шум привлекает монстров." + } + ] + }, + { + "id": 2, + "questId": 2, + "text": "Факел осветил три двери. На каждой — символ: огонь, вода, луна. Какую выберете?", + "answers": [ + { + "id": 21, + "questionId": 2, + "nextQuestionId": 3, + "text": "С символом огня (рискованно, но может вести к сокровищам).", + "description": "В комнате лава. Нужно найти мост." + }, + { + "id": 22, + "questionId": 2, + "nextQuestionId": 8, + "text": "С символом воды (кажется безопасной).", + "description": "Подземный ручей." + }, + { + "id": 23, + "questionId": 2, + "nextQuestionId": 910, + "text": "С символом луны (загадочно, возможно, ловушка).", + "description": "Ловушка: пол проваливается." + } + ] + }, + { + "id": 3, + "questId": 2, + "text": "За дверью — комната с ямой посередине. На стене рычаг. Ваши действия?", + "answers": [ + { + "id": 31, + "questionId": 3, + "nextQuestionId": 910, + "text": "Дёрнете рычаг сразу.", + "description": "Яма расширяется." + }, + { + "id": 32, + "questionId": 3, + "nextQuestionId": 4, + "text": "Поищете другой путь, минуя яму.", + "description": "Находите скрытый проход." + }, + { + "id": 33, + "questionId": 3, + "nextQuestionId": 910, + "text": "Попытаетесь перепрыгнуть яму.", + "description": "Падение." + }, + { + "id": 34, + "questionId": 3, + "nextQuestionId": 4, + "text": "Кинете камень на противоположную сторону, проверяя пол.", + "description": "Пол безопасен. Переходите." + } + ] + }, + { + "id": 4, + "questId": 2, + "text": "Рычаг активировал механизм: из стен выдвинулись шипы. Как спастись?", + "answers": [ + { + "id": 41, + "questionId": 4, + "nextQuestionId": 5, + "text": "Прижмётесь к стене и медленно пройдёте.", + "description": "Успешно проходите." + }, + { + "id": 42, + "questionId": 4, + "nextQuestionId": 5, + "text": "Побежите напролом, уклоняясь.", + "description": "Ранение. Здоровье снижается." + }, + { + "id": 43, + "questionId": 4, + "nextQuestionId": 5, + "text": "Найдёте кнопку отключения механизмов.", + "description": "Находите механизм." + }, + { + "id": 44, + "questionId": 4, + "nextQuestionId": 910, + "text": "Вернётесь назад.", + "description": "Путь заблокирован. " + } + ] + }, + { + "id": 5, + "questId": 2, + "text": "В этой комнате — статуя дракона. На постаменте надпись: «Скажи имя древнего бога».", + "answers": [ + { + "id": 51, + "questionId": 5, + "nextQuestionId": 910, + "text": "Азраэль.", + "description": "Статуя атакует." + }, + { + "id": 52, + "questionId": 5, + "nextQuestionId": 6, + "text": "Таргон.", + "description": "Верно! Статуя пропускает." + }, + { + "id": 53, + "questionId": 5, + "nextQuestionId": 910, + "text": "Вельдан.", + "description": "Ошибка. Ловушка." + }, + { + "id": 54, + "questionId": 5, + "nextQuestionId": 5, + "text": "Промолчите и осмотрите комнату ещё раз.", + "description": "Находите надпись с именем: Таргон" + } + ] + }, + { + "id": 3, + "questId": 2, + "text": "За дверью — комната с ямой посередине. На стене рычаг. Ваши действия?", + "answers": [ + { + "id": 31, + "questionId": 3, + "nextQuestionId": 910, + "text": "Дёрнете рычаг сразу.", + "description": "Яма расширяется." + }, + { + "id": 32, + "questionId": 3, + "nextQuestionId": 4, + "text": "Поищете другой путь, минуя яму.", + "description": "Находите скрытый проход." + }, + { + "id": 33, + "questionId": 3, + "nextQuestionId": 910, + "text": "Попытаетесь перепрыгнуть яму.", + "description": "Падение." + }, + { + "id": 34, + "questionId": 3, + "nextQuestionId": 4, + "text": "Кинете камень на противоположную сторону, проверяя пол.", + "description": "Пол безопасен. Переходите." + } + ] + }, + { + "id": 3, + "questId": 2, + "text": "За дверью — комната с ямой посередине. На стене рычаг. Ваши действия?", + "answers": [ + { + "id": 31, + "questionId": 3, + "nextQuestionId": 910, + "text": "Дёрнете рычаг сразу.", + "description": "Яма расширяется." + }, + { + "id": 32, + "questionId": 3, + "nextQuestionId": 4, + "text": "Поищете другой путь, минуя яму.", + "description": "Находите скрытый проход." + }, + { + "id": 33, + "questionId": 3, + "nextQuestionId": 910, + "text": "Попытаетесь перепрыгнуть яму.", + "description": "Падение." + }, + { + "id": 34, + "questionId": 3, + "nextQuestionId": 4, + "text": "Кинете камень на противоположную сторону, проверяя пол.", + "description": "Пол безопасен. Переходите." + } + ] + }, + { + "id": 3, + "questId": 2, + "text": "За дверью — комната с ямой посередине. На стене рычаг. Ваши действия?", + "answers": [ + { + "id": 31, + "questionId": 3, + "nextQuestionId": 910, + "text": "Дёрнете рычаг сразу.", + "description": "Яма расширяется." + }, + { + "id": 32, + "questionId": 3, + "nextQuestionId": 4, + "text": "Поищете другой путь, минуя яму.", + "description": "Находите скрытый проход." + }, + { + "id": 33, + "questionId": 3, + "nextQuestionId": 910, + "text": "Попытаетесь перепрыгнуть яму.", + "description": "Падение." + }, + { + "id": 34, + "questionId": 3, + "nextQuestionId": 4, + "text": "Кинете камень на противоположную сторону, проверяя пол.", + "description": "Пол безопасен. Переходите." + } + ] + }, + { + "id": 810, + "questId": 1, + "text": "Тебя вернули домой, победа", + "answers": null + }, + { + "id": 910, + "questId": 2, + "text": "Проигрыш", + "answers": null + }, + { + "id": 911, + "questId": 1, + "text": "Твою ложь разоблачили, поражение", + "answers": null + } + ] +} From 325a5ee6ba6d764706334544f9594212cb675b8f Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Tue, 20 Jan 2026 23:47:56 +0500 Subject: [PATCH 05/65] ADD servlet/jsp (Home, QuestPage) + Config --- .../java/com/javarush/vasileva/cmd/Home.java | 29 +++++ .../com/javarush/vasileva/cmd/QuestPage.java | 24 +++++ .../com/javarush/vasileva/config/Config.java | 35 ++++++ .../com/javarush/vasileva/config/Winter.java | 2 +- .../vasileva/controller/FrontController.java | 6 +- .../vasileva/controller/HttpResolver.java | 2 +- src/main/webapp/WEB-INF/home.jsp | 19 ++++ src/main/webapp/WEB-INF/quest-page.jsp | 23 ++++ src/main/webapp/static/css/style.css | 102 ++++++++++++++++++ 9 files changed, 239 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/javarush/vasileva/cmd/Home.java create mode 100644 src/main/java/com/javarush/vasileva/cmd/QuestPage.java create mode 100644 src/main/java/com/javarush/vasileva/config/Config.java create mode 100644 src/main/webapp/WEB-INF/home.jsp create mode 100644 src/main/webapp/WEB-INF/quest-page.jsp create mode 100644 src/main/webapp/static/css/style.css diff --git a/src/main/java/com/javarush/vasileva/cmd/Home.java b/src/main/java/com/javarush/vasileva/cmd/Home.java new file mode 100644 index 0000000..a437898 --- /dev/null +++ b/src/main/java/com/javarush/vasileva/cmd/Home.java @@ -0,0 +1,29 @@ +package com.javarush.vasileva.cmd; + +import com.javarush.vasileva.entity.Quest; +import com.javarush.vasileva.service.QuestService; +import jakarta.servlet.http.HttpServletRequest; + +import java.util.List; + +public class Home implements Command { + private final QuestService questService; + + public Home(QuestService questService) { + this.questService = questService; + } + + @Override + public String doGet(HttpServletRequest req) { + try { + List quests = questService.getAll(); + req.setAttribute("quests", quests); + System.out.println("Quests loaded: " + quests.size()); + System.out.println("Loaded quests: " + quests); + + } catch (Exception e) { + System.out.println(e.getMessage()); + } + return getView(); + } +} diff --git a/src/main/java/com/javarush/vasileva/cmd/QuestPage.java b/src/main/java/com/javarush/vasileva/cmd/QuestPage.java new file mode 100644 index 0000000..406cbfe --- /dev/null +++ b/src/main/java/com/javarush/vasileva/cmd/QuestPage.java @@ -0,0 +1,24 @@ +package com.javarush.vasileva.cmd; + +import com.javarush.vasileva.entity.Quest; +import com.javarush.vasileva.service.QuestService; +import jakarta.servlet.http.HttpServletRequest; + +public class QuestPage implements Command { + private final QuestService questService; + + public QuestPage(QuestService questService) { + this.questService = questService; + } + + @Override + public String doGet(HttpServletRequest req) { + String strId = req.getParameter("id"); + if (strId != null && !strId.isEmpty()) { + long id = Long.parseLong(strId); + Quest quest = questService.get(id).orElseThrow(); + req.setAttribute("quest", quest); + } + return getView(); + } +} diff --git a/src/main/java/com/javarush/vasileva/config/Config.java b/src/main/java/com/javarush/vasileva/config/Config.java new file mode 100644 index 0000000..8621116 --- /dev/null +++ b/src/main/java/com/javarush/vasileva/config/Config.java @@ -0,0 +1,35 @@ +package com.javarush.vasileva.config; + +import com.javarush.vasileva.entity.Quest; +import com.javarush.vasileva.entity.Question; +import com.javarush.vasileva.mapper.QuestMapper; +import com.javarush.vasileva.service.QuestService; +import com.javarush.vasileva.service.QuestionService; +import lombok.AllArgsConstructor; + +import java.io.IOException; + +@AllArgsConstructor +public class Config { + private final QuestService questService = Winter.find(QuestService.class); + private final QuestionService questionService = Winter.find(QuestionService.class); + private final QuestMapper questMapper = Winter.find(QuestMapper.class); + + public static final String QUEST_FILE_NAME_1 = "/Users/katiavasileva/IdeaProjects/quest/src/main/resources/quest-1.json"; + public static final String QUEST_FILE_NAME_2 = "/Users/katiavasileva/IdeaProjects/quest/src/main/resources/quest-2.json"; + public static final String[] QUEST_FILES = {QUEST_FILE_NAME_1, QUEST_FILE_NAME_2}; + + public void fillRepository() { + try { + for (String fileName : QUEST_FILES) { + Quest quest = questMapper.readFromJson(fileName); + questService.create(quest); + for (Question question : quest.getQuestions()) { + questionService.create(question); + } + } + } catch (IOException e) { + System.out.println(e.getMessage()); + } + } +} diff --git a/src/main/java/com/javarush/vasileva/config/Winter.java b/src/main/java/com/javarush/vasileva/config/Winter.java index 53de644..9f18661 100644 --- a/src/main/java/com/javarush/vasileva/config/Winter.java +++ b/src/main/java/com/javarush/vasileva/config/Winter.java @@ -15,7 +15,7 @@ public class Winter { public static T find(Class aClass) { Object component = components.get(aClass); if (component == null) { - Constructor constructor = aClass.getConstructors()[0]; + Constructor constructor = aClass.getDeclaredConstructors()[0]; Class[] parameterTypes = constructor.getParameterTypes(); Object[] parameters = new Object[parameterTypes.length]; for (int i = 0; i < parameters.length; i++) { diff --git a/src/main/java/com/javarush/vasileva/controller/FrontController.java b/src/main/java/com/javarush/vasileva/controller/FrontController.java index 18d736f..d7b13e8 100644 --- a/src/main/java/com/javarush/vasileva/controller/FrontController.java +++ b/src/main/java/com/javarush/vasileva/controller/FrontController.java @@ -1,6 +1,7 @@ package com.javarush.vasileva.controller; import com.javarush.vasileva.cmd.Command; +import com.javarush.vasileva.config.Config; import com.javarush.vasileva.config.Winter; import com.javarush.vasileva.entity.Role; import jakarta.servlet.ServletConfig; @@ -12,7 +13,7 @@ import java.io.IOException; -@WebServlet({"", "/home", "/list-user", "/edit-user"}) +@WebServlet({"", "/home", "/list-user", "/edit-user", "/quest-page"}) public class FrontController extends HttpServlet { private final HttpResolver httpResolver = Winter.find(HttpResolver.class); @@ -28,6 +29,9 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se @Override public void init(ServletConfig config) { config.getServletContext().setAttribute("roles", Role.values()); + + Config gameConfig = Winter.find(Config.class); + gameConfig.fillRepository(); } private static String getJsp(String view) { diff --git a/src/main/java/com/javarush/vasileva/controller/HttpResolver.java b/src/main/java/com/javarush/vasileva/controller/HttpResolver.java index 3b29028..75ebd85 100644 --- a/src/main/java/com/javarush/vasileva/controller/HttpResolver.java +++ b/src/main/java/com/javarush/vasileva/controller/HttpResolver.java @@ -10,7 +10,7 @@ public Command resolve(HttpServletRequest request) { // /cmd-example try { String requestURI = request.getRequestURI(); - requestURI = requestURI.equals("/") ? "/start-page" : requestURI; + requestURI = requestURI.equals("/") ? "/home" : requestURI; String kebabName = requestURI.split("[?#/]")[1]; String simpleName = convertKebabStyleToCamelCase(kebabName); String fullName = Command.class.getPackageName() + "." + simpleName; diff --git a/src/main/webapp/WEB-INF/home.jsp b/src/main/webapp/WEB-INF/home.jsp new file mode 100644 index 0000000..372204c --- /dev/null +++ b/src/main/webapp/WEB-INF/home.jsp @@ -0,0 +1,19 @@ +<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +... +<%----%> + + + Home + + + +

Quests

+ + + ${quest.title}
+
+ + + diff --git a/src/main/webapp/WEB-INF/quest-page.jsp b/src/main/webapp/WEB-INF/quest-page.jsp new file mode 100644 index 0000000..dea3ce9 --- /dev/null +++ b/src/main/webapp/WEB-INF/quest-page.jsp @@ -0,0 +1,23 @@ +<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + + + + + New Quest +<%-- +<%-- integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">--%> + +<%-- --%> + + +

${requestScope.quest.title}

+

${requestScope.quest.description}

+ + + + + + + + diff --git a/src/main/webapp/static/css/style.css b/src/main/webapp/static/css/style.css new file mode 100644 index 0000000..c5a3aab --- /dev/null +++ b/src/main/webapp/static/css/style.css @@ -0,0 +1,102 @@ +/* Базовый сброс отступов и полей */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + text-align: center; +} + +body { + font-family: 'Georgia', serif; + background-color: #1a110a; + color: #e6d4b0; + line-height: 1.6; + padding: 20px; + max-width: 1200px; + margin: 0 auto; + background-image: linear-gradient(to bottom, #1a110a, #0d0805); +} + +h1 { + font-size: 2.5rem; + text-align: center; + color: #d4a56c; + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.6); + margin-bottom: 30px; + letter-spacing: 1px; +} + +p { + font-size: 1.1rem; + margin-bottom: 20px; + text-align: justify; +} + +b { + color: #f0c48c; + font-weight: bold; +} + +a { + text-decoration: none; +} + +button { + display: block; + width: 220px; + padding: 12px 20px; + margin: 20px auto; + border: none; + border-radius: 6px; + font-family: 'Georgia', serif; + font-size: 1rem; + cursor: pointer; + transition: all 0.3s ease; + text-transform: uppercase; + letter-spacing: 1px; +} + +button:first-of-type { + background-color: #8b4513; + color: #fff; + box-shadow: 0 4px 6px rgba(139, 69, 19, 0.4); +} + +button:first-of-type:hover { + background-color: #a0522d; + transform: translateY(-2px); +} + +button:last-of-type { + background-color: #4a3a2a; + color: #d4b588; + box-shadow: 0 4px 6px rgba(74, 58, 42, 0.4); +} + +button:last-of-type:hover { + background-color: #5e4c3a; + transform: translateY(-2px); +} + +.quest-text { + background-color: rgba(34, 24, 16, 0.6); + padding: 20px; + border-radius: 8px; + border: 1px solid rgba(102, 71, 45, 0.5); + box-shadow: 0 0 15px rgba(102, 71, 45, 0.3); + color: #e6d4b0; +} + +@media (max-width: 600px) { + h1 { + font-size: 2rem; + } + p { + font-size: 1rem; + padding: 0 10px; + } + button { + width: 180px; + font-size: 0.9rem; + } +} From 32a68c01c3a8536f76447648fd303e8985b2ea63 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Wed, 21 Jan 2026 14:43:37 +0500 Subject: [PATCH 06/65] ADD PlayGame and service/repository for Answer --- .../com/javarush/vasileva/cmd/PlayGame.java | 41 ++++++ .../com/javarush/vasileva/cmd/QuestPage.java | 2 + .../com/javarush/vasileva/config/Config.java | 12 ++ .../vasileva/controller/FrontController.java | 18 +-- .../com/javarush/vasileva/entity/Answer.java | 12 +- .../javarush/vasileva/entity/Question.java | 3 +- .../vasileva/repository/AnswerRepository.java | 37 ++++++ .../vasileva/repository/QuestRepository.java | 1 - .../repository/QuestionRepository.java | 6 +- .../vasileva/repository/UserRepository.java | 1 - .../vasileva/service/AnswerService.java | 28 +++++ .../vasileva/service/BaseService.java | 13 -- .../vasileva/service/QuestService.java | 5 +- .../vasileva/service/QuestionService.java | 5 +- .../vasileva/service/UserService.java | 4 +- src/main/resources/quest-1.json | 30 ++--- src/main/resources/quest-2.json | 119 ++++++------------ src/main/webapp/WEB-INF/play-game.jsp | 36 ++++++ src/main/webapp/WEB-INF/quest-page.jsp | 12 +- 19 files changed, 239 insertions(+), 146 deletions(-) create mode 100644 src/main/java/com/javarush/vasileva/cmd/PlayGame.java create mode 100644 src/main/java/com/javarush/vasileva/repository/AnswerRepository.java create mode 100644 src/main/java/com/javarush/vasileva/service/AnswerService.java delete mode 100644 src/main/java/com/javarush/vasileva/service/BaseService.java create mode 100644 src/main/webapp/WEB-INF/play-game.jsp diff --git a/src/main/java/com/javarush/vasileva/cmd/PlayGame.java b/src/main/java/com/javarush/vasileva/cmd/PlayGame.java new file mode 100644 index 0000000..a964ace --- /dev/null +++ b/src/main/java/com/javarush/vasileva/cmd/PlayGame.java @@ -0,0 +1,41 @@ +package com.javarush.vasileva.cmd; + +import com.javarush.vasileva.entity.Answer; +import com.javarush.vasileva.entity.Quest; +import com.javarush.vasileva.entity.Question; +import com.javarush.vasileva.service.AnswerService; +import com.javarush.vasileva.service.QuestService; +import com.javarush.vasileva.service.QuestionService; +import jakarta.servlet.http.HttpServletRequest; + +import java.util.List; +import java.util.Optional; + +public class PlayGame implements Command { + private final QuestService questService; + private final QuestionService questionService; + private final AnswerService answerService; + + public PlayGame(QuestService questService, QuestionService questionService, AnswerService answerService) { + this.questService = questService; + this.questionService = questionService; + this.answerService = answerService; + } + + @Override + public String doGet(HttpServletRequest req) { + String strId = req.getParameter("id"); + if (strId != null && !strId.isEmpty()) { + long id = Long.parseLong(strId); + Quest quest = questService.get(id).orElseThrow(); + req.setAttribute("quest", quest); + + System.out.println(quest.getStartQuestionId()); + Optional current = questionService.get(quest.getStartQuestionId()); + current.ifPresent(question -> req.setAttribute("question", question)); + List answers = current.get().getAnswers(); + req.setAttribute("answers", answers); + } + return getView(); + } +} diff --git a/src/main/java/com/javarush/vasileva/cmd/QuestPage.java b/src/main/java/com/javarush/vasileva/cmd/QuestPage.java index 406cbfe..8e487c2 100644 --- a/src/main/java/com/javarush/vasileva/cmd/QuestPage.java +++ b/src/main/java/com/javarush/vasileva/cmd/QuestPage.java @@ -4,6 +4,8 @@ import com.javarush.vasileva.service.QuestService; import jakarta.servlet.http.HttpServletRequest; +import java.util.Optional; + public class QuestPage implements Command { private final QuestService questService; diff --git a/src/main/java/com/javarush/vasileva/config/Config.java b/src/main/java/com/javarush/vasileva/config/Config.java index 8621116..26a6368 100644 --- a/src/main/java/com/javarush/vasileva/config/Config.java +++ b/src/main/java/com/javarush/vasileva/config/Config.java @@ -1,18 +1,22 @@ package com.javarush.vasileva.config; +import com.javarush.vasileva.entity.Answer; import com.javarush.vasileva.entity.Quest; import com.javarush.vasileva.entity.Question; import com.javarush.vasileva.mapper.QuestMapper; +import com.javarush.vasileva.service.AnswerService; import com.javarush.vasileva.service.QuestService; import com.javarush.vasileva.service.QuestionService; import lombok.AllArgsConstructor; import java.io.IOException; +import java.util.List; @AllArgsConstructor public class Config { private final QuestService questService = Winter.find(QuestService.class); private final QuestionService questionService = Winter.find(QuestionService.class); + private final AnswerService answerService = Winter.find(AnswerService.class); private final QuestMapper questMapper = Winter.find(QuestMapper.class); public static final String QUEST_FILE_NAME_1 = "/Users/katiavasileva/IdeaProjects/quest/src/main/resources/quest-1.json"; @@ -26,6 +30,14 @@ public void fillRepository() { questService.create(quest); for (Question question : quest.getQuestions()) { questionService.create(question); + List answers = question.getAnswers(); + if (answers == null) { + continue; + } + for (Answer answer : answers) { + answer.setQuestionId(question.getGeneratedId()); + answerService.create(answer); + } } } } catch (IOException e) { diff --git a/src/main/java/com/javarush/vasileva/controller/FrontController.java b/src/main/java/com/javarush/vasileva/controller/FrontController.java index d7b13e8..8f25c25 100644 --- a/src/main/java/com/javarush/vasileva/controller/FrontController.java +++ b/src/main/java/com/javarush/vasileva/controller/FrontController.java @@ -13,19 +13,11 @@ import java.io.IOException; -@WebServlet({"", "/home", "/list-user", "/edit-user", "/quest-page"}) +@WebServlet({"", "/home", "/list-user", "/edit-user", "/quest-page", "/play-game"}) public class FrontController extends HttpServlet { private final HttpResolver httpResolver = Winter.find(HttpResolver.class); - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - Command command = httpResolver.resolve(req); - String view = command.doGet(req); - String jsp = getJsp(view); - req.getRequestDispatcher(jsp).forward(req, resp); - } - @Override public void init(ServletConfig config) { config.getServletContext().setAttribute("roles", Role.values()); @@ -34,6 +26,14 @@ public void init(ServletConfig config) { gameConfig.fillRepository(); } + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + Command command = httpResolver.resolve(req); + String view = command.doGet(req); + String jsp = getJsp(view); + req.getRequestDispatcher(jsp).forward(req, resp); + } + private static String getJsp(String view) { return "/WEB-INF/" + view + ".jsp"; } diff --git a/src/main/java/com/javarush/vasileva/entity/Answer.java b/src/main/java/com/javarush/vasileva/entity/Answer.java index a0dd730..3f3152e 100644 --- a/src/main/java/com/javarush/vasileva/entity/Answer.java +++ b/src/main/java/com/javarush/vasileva/entity/Answer.java @@ -1,18 +1,18 @@ package com.javarush.vasileva.entity; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.*; -@Data +@Getter +@Setter +@ToString +@EqualsAndHashCode @AllArgsConstructor @NoArgsConstructor @Builder public class Answer { private Long id; private Long questionId; - private Long nextQuestionId; + private String nextQuestionId; private String text; private String description; } diff --git a/src/main/java/com/javarush/vasileva/entity/Question.java b/src/main/java/com/javarush/vasileva/entity/Question.java index 360d68a..8702352 100644 --- a/src/main/java/com/javarush/vasileva/entity/Question.java +++ b/src/main/java/com/javarush/vasileva/entity/Question.java @@ -12,7 +12,8 @@ @AllArgsConstructor @Builder public class Question { - private Long id; + private Long generatedId; + private String id; private Long questId; private String text; private List answers; diff --git a/src/main/java/com/javarush/vasileva/repository/AnswerRepository.java b/src/main/java/com/javarush/vasileva/repository/AnswerRepository.java new file mode 100644 index 0000000..a3600e2 --- /dev/null +++ b/src/main/java/com/javarush/vasileva/repository/AnswerRepository.java @@ -0,0 +1,37 @@ +package com.javarush.vasileva.repository; + +import com.javarush.vasileva.entity.Answer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +public class AnswerRepository implements Repository { + private final Map answers = new ConcurrentHashMap<>(); + + @Override + public List getAll() { + return new ArrayList<>(answers.values()); + } + + @Override + public Optional get(long id) { + return Optional.ofNullable(answers.get(id)); + } + + public void create(Answer answer) { + answers.put(answer.getId(), answer); + } + + @Override + public void update(Answer entity) { + + } + + @Override + public void delete(Answer entity) { + + } +} diff --git a/src/main/java/com/javarush/vasileva/repository/QuestRepository.java b/src/main/java/com/javarush/vasileva/repository/QuestRepository.java index 028a77f..00524cc 100644 --- a/src/main/java/com/javarush/vasileva/repository/QuestRepository.java +++ b/src/main/java/com/javarush/vasileva/repository/QuestRepository.java @@ -21,7 +21,6 @@ public Optional get(long id) { return Optional.ofNullable(quests.get(id)); } - @Override public void create(Quest entity) { quests.put(entity.getId(), entity); } diff --git a/src/main/java/com/javarush/vasileva/repository/QuestionRepository.java b/src/main/java/com/javarush/vasileva/repository/QuestionRepository.java index 1f3c46a..4acbef7 100644 --- a/src/main/java/com/javarush/vasileva/repository/QuestionRepository.java +++ b/src/main/java/com/javarush/vasileva/repository/QuestionRepository.java @@ -8,10 +8,12 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; @NoArgsConstructor public class QuestionRepository implements Repository { private final Map questions = new ConcurrentHashMap<>(); + private static final AtomicLong generatedId = new AtomicLong(0); @Override public List getAll() { @@ -23,9 +25,9 @@ public Optional get(long id) { return Optional.ofNullable(questions.get(id)); } - @Override public void create(Question question) { - questions.put(question.getId(), question); + question.setGeneratedId(generatedId.incrementAndGet()); + questions.put(question.getGeneratedId(), question); } @Override diff --git a/src/main/java/com/javarush/vasileva/repository/UserRepository.java b/src/main/java/com/javarush/vasileva/repository/UserRepository.java index fa68823..940c68c 100644 --- a/src/main/java/com/javarush/vasileva/repository/UserRepository.java +++ b/src/main/java/com/javarush/vasileva/repository/UserRepository.java @@ -29,7 +29,6 @@ public Optional get(long id) { return Optional.ofNullable(map.get(id)); } - @Override public void create(User entity) { entity.setId(id.incrementAndGet()); update(entity); diff --git a/src/main/java/com/javarush/vasileva/service/AnswerService.java b/src/main/java/com/javarush/vasileva/service/AnswerService.java new file mode 100644 index 0000000..8c1c467 --- /dev/null +++ b/src/main/java/com/javarush/vasileva/service/AnswerService.java @@ -0,0 +1,28 @@ +package com.javarush.vasileva.service; + +import com.javarush.vasileva.entity.Answer; +import com.javarush.vasileva.repository.AnswerRepository; +import com.javarush.vasileva.repository.Repository; + +import java.util.List; +import java.util.Optional; + +public class AnswerService { + private final Repository answerRepository; + + public AnswerService(AnswerRepository answerRepository) { + this.answerRepository = answerRepository; + } + + public List getAll() { + return answerRepository.getAll(); + } + + public Optional get(Long id) { + return answerRepository.get(id); + } + + public void create(Answer answer) { + answerRepository.create(answer); + } +} diff --git a/src/main/java/com/javarush/vasileva/service/BaseService.java b/src/main/java/com/javarush/vasileva/service/BaseService.java deleted file mode 100644 index e535f5c..0000000 --- a/src/main/java/com/javarush/vasileva/service/BaseService.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.javarush.vasileva.service; - -import java.util.List; -import java.util.Optional; - -public interface BaseService { - - List getAll(); - - Optional get(Long id); - - void create(T entity); -} diff --git a/src/main/java/com/javarush/vasileva/service/QuestService.java b/src/main/java/com/javarush/vasileva/service/QuestService.java index cb5a00a..351a967 100644 --- a/src/main/java/com/javarush/vasileva/service/QuestService.java +++ b/src/main/java/com/javarush/vasileva/service/QuestService.java @@ -7,24 +7,21 @@ import java.util.List; import java.util.Optional; -public class QuestService implements BaseService { +public class QuestService { private final Repository questRepository; public QuestService(QuestRepository questRepository) { this.questRepository = questRepository; } - @Override public List getAll() { return questRepository.getAll(); } - @Override public Optional get(Long id) { return questRepository.get(id); } - @Override public void create(Quest entity) { questRepository.create(entity); } diff --git a/src/main/java/com/javarush/vasileva/service/QuestionService.java b/src/main/java/com/javarush/vasileva/service/QuestionService.java index 83c221e..cbc172d 100644 --- a/src/main/java/com/javarush/vasileva/service/QuestionService.java +++ b/src/main/java/com/javarush/vasileva/service/QuestionService.java @@ -7,7 +7,7 @@ import java.util.List; import java.util.Optional; -public class QuestionService implements BaseService { +public class QuestionService { private final Repository questionRepository; @@ -15,17 +15,14 @@ public QuestionService(QuestionRepository questionRepository) { this.questionRepository = questionRepository; } - @Override public List getAll() { return questionRepository.getAll(); } - @Override public Optional get(Long id) { return questionRepository.get(id); } - @Override public void create(Question question) { questionRepository.create(question); } diff --git a/src/main/java/com/javarush/vasileva/service/UserService.java b/src/main/java/com/javarush/vasileva/service/UserService.java index 9daaa89..1b7e4f8 100644 --- a/src/main/java/com/javarush/vasileva/service/UserService.java +++ b/src/main/java/com/javarush/vasileva/service/UserService.java @@ -6,7 +6,7 @@ import java.util.List; import java.util.Optional; -public class UserService implements BaseService { +public class UserService { private final UserRepository userRepository; @@ -14,7 +14,6 @@ public UserService(UserRepository userRepository) { this.userRepository = userRepository; } - @Override public void create(User user) { userRepository.create(user); } @@ -31,7 +30,6 @@ public List getAll() { return userRepository.getAll(); } - @Override public Optional get(Long id) { return userRepository.get(id); } diff --git a/src/main/resources/quest-1.json b/src/main/resources/quest-1.json index f6df9d6..75160f3 100644 --- a/src/main/resources/quest-1.json +++ b/src/main/resources/quest-1.json @@ -4,76 +4,70 @@ "description": "Про приключения в космосе", "questions": [ { - "id": 1, + "id": "1", "questId": 1, "text": "Принять вызов НЛО?", "answers": [ { "id": 11, - "questionId": 1, - "nextQuestionId": 2, + "nextQuestionId": "2", "text": "Принять вызов" }, { "id": 12, - "questionId": 1, - "nextQuestionId": 910, + "nextQuestionId": "910", "text": "Отклонить вызов" } ] }, { - "id": 2, + "id": "2", "questId": 1, "text": "Поднимешься на мостик к капитану?", "answers": [ { "id": 21, - "questionId": 2, - "nextQuestionId": 3, + "nextQuestionId": "3", "text": "Подняться на мостик" }, { "id": 22, - "questionId": 2, - "nextQuestionId": 910, + "nextQuestionId": "910", "text": "Отказаться подниматься на мостик" } ] }, { - "id": 3, + "id": "3", "questId": 1, "text": "Ты поднялся на мостик. Ты кто?", "answers": [ { "id": 31, - "questionId": 3, - "nextQuestionId": 810, + "nextQuestionId": "810", "text": "Рассказать правду о себе" }, { "id": 32, - "questionId": 3, - "nextQuestionId": 911, + "nextQuestionId": "911", "text": "Солгать о себе" } ] }, { - "id": 810, + "id": "810", "questId": 1, "text": "Тебя вернули домой, победа", "answers": null }, { - "id": 910, + "id": "910", "questId": 1, "text": "Ты отклонил вызов, поражение", "answers": null }, { - "id": 911, + "id": "911", "questId": 1, "text": "Твою ложь разоблачили, поражение", "answers": null diff --git a/src/main/resources/quest-2.json b/src/main/resources/quest-2.json index f10f0b5..4feca85 100644 --- a/src/main/resources/quest-2.json +++ b/src/main/resources/quest-2.json @@ -4,295 +4,258 @@ "description": "Много веков назад дракон Вельдан, хранитель древних знаний, скрылся в недрах горы с Сердцем Дракона — артефактом невообразимой силы, спрятав его в лабиринте, известном как Забытое Подземелье. Тысячи смельчаков отправлялись на поиски реликвии, но никто не вернулся; легенды гласят, что лишь тот, кто проявит мудрость, отвагу и хладнокровие, сможет завладеть Сердцем. Теперь вы — один из искателей: с факелом и мечом перед массивной дверью с драконьей пастью, за которой таятся тьма, сырость и нечто древнее. Дверь медленно приоткрывается — готовы ли вы бросить вызов подземелью?", "questions": [ { - "id": 1, + "id": "1", "questId": 2, "text": "Вы входите в тёмный коридор. Впереди слышен шорох.", "answers": [ { "id": 11, - "questionId": 1, - "nextQuestionId": 2, + "nextQuestionId": "2", "text": "Достанете факел и осторожно продвинетесь вперёд.", "description": "" }, { "id": 12, - "questionId": 1, - "nextQuestionId": 2, + "nnextQuestionId": "2", "text": "Бросите камень в сторону шума, чтобы проверить.", "description": "Вы пугаете крысу. Путь свободен." }, { "id": 13, - "questionId": 1, - "nextQuestionId": 910, + "nextQuestionId": "910", "text": "Повернётесь и пойдёте назад.", "description": "Попадаете в тупик." }, { "id": 14, - "questionId": 1, - "nextQuestionId": 910, + "nextQuestionId": "910", "text": "Закричите, чтобы отпугнуть возможного врага.", "description": "Шум привлекает монстров." } ] }, { - "id": 2, + "id": "2", "questId": 2, "text": "Факел осветил три двери. На каждой — символ: огонь, вода, луна. Какую выберете?", "answers": [ { "id": 21, - "questionId": 2, - "nextQuestionId": 3, + "nextQuestionId": "3", "text": "С символом огня (рискованно, но может вести к сокровищам).", "description": "В комнате лава. Нужно найти мост." }, { "id": 22, - "questionId": 2, - "nextQuestionId": 8, + "nextQuestionId": "8", "text": "С символом воды (кажется безопасной).", "description": "Подземный ручей." }, { "id": 23, - "questionId": 2, - "nextQuestionId": 910, + "nextQuestionId": "910", "text": "С символом луны (загадочно, возможно, ловушка).", "description": "Ловушка: пол проваливается." } ] }, { - "id": 3, + "id": "3", "questId": 2, "text": "За дверью — комната с ямой посередине. На стене рычаг. Ваши действия?", "answers": [ { "id": 31, - "questionId": 3, - "nextQuestionId": 910, + "nextQuestionId": "910", "text": "Дёрнете рычаг сразу.", "description": "Яма расширяется." }, { "id": 32, - "questionId": 3, - "nextQuestionId": 4, + "nextQuestionId": "4", "text": "Поищете другой путь, минуя яму.", "description": "Находите скрытый проход." }, { "id": 33, - "questionId": 3, - "nextQuestionId": 910, + "nextQuestionId": "910", "text": "Попытаетесь перепрыгнуть яму.", "description": "Падение." }, { "id": 34, - "questionId": 3, - "nextQuestionId": 4, + "nextQuestionId": "4", "text": "Кинете камень на противоположную сторону, проверяя пол.", "description": "Пол безопасен. Переходите." } ] }, { - "id": 4, + "id": "4", "questId": 2, "text": "Рычаг активировал механизм: из стен выдвинулись шипы. Как спастись?", "answers": [ { "id": 41, - "questionId": 4, - "nextQuestionId": 5, + "nextQuestionId": "5", "text": "Прижмётесь к стене и медленно пройдёте.", "description": "Успешно проходите." }, { "id": 42, - "questionId": 4, - "nextQuestionId": 5, + "nextQuestionId": "5", "text": "Побежите напролом, уклоняясь.", "description": "Ранение. Здоровье снижается." }, { "id": 43, - "questionId": 4, - "nextQuestionId": 5, + "nextQuestionId": "5", "text": "Найдёте кнопку отключения механизмов.", "description": "Находите механизм." }, { "id": 44, - "questionId": 4, - "nextQuestionId": 910, + "nextQuestionId": "910", "text": "Вернётесь назад.", "description": "Путь заблокирован. " } ] }, { - "id": 5, + "id": "5", "questId": 2, "text": "В этой комнате — статуя дракона. На постаменте надпись: «Скажи имя древнего бога».", "answers": [ { "id": 51, - "questionId": 5, - "nextQuestionId": 910, + "nextQuestionId": "910", "text": "Азраэль.", "description": "Статуя атакует." }, { "id": 52, - "questionId": 5, - "nextQuestionId": 6, + "nextQuestionId": "6", "text": "Таргон.", "description": "Верно! Статуя пропускает." }, { "id": 53, - "questionId": 5, - "nextQuestionId": 910, + "nextQuestionId": "910", "text": "Вельдан.", "description": "Ошибка. Ловушка." }, { "id": 54, - "questionId": 5, - "nextQuestionId": 5, + "nextQuestionId": "5", "text": "Промолчите и осмотрите комнату ещё раз.", "description": "Находите надпись с именем: Таргон" } ] }, { - "id": 3, + "id": "3", "questId": 2, "text": "За дверью — комната с ямой посередине. На стене рычаг. Ваши действия?", "answers": [ { "id": 31, - "questionId": 3, - "nextQuestionId": 910, + "nextQuestionId": "910", "text": "Дёрнете рычаг сразу.", "description": "Яма расширяется." }, { "id": 32, - "questionId": 3, - "nextQuestionId": 4, + "nextQuestionId": "4", "text": "Поищете другой путь, минуя яму.", "description": "Находите скрытый проход." }, { "id": 33, - "questionId": 3, - "nextQuestionId": 910, + "nextQuestionId": "910", "text": "Попытаетесь перепрыгнуть яму.", "description": "Падение." }, { "id": 34, - "questionId": 3, - "nextQuestionId": 4, + "nextQuestionId": "4", "text": "Кинете камень на противоположную сторону, проверяя пол.", "description": "Пол безопасен. Переходите." } ] }, { - "id": 3, + "id": "3", "questId": 2, "text": "За дверью — комната с ямой посередине. На стене рычаг. Ваши действия?", "answers": [ { "id": 31, - "questionId": 3, - "nextQuestionId": 910, + "nextQuestionId": "910", "text": "Дёрнете рычаг сразу.", "description": "Яма расширяется." }, { "id": 32, - "questionId": 3, - "nextQuestionId": 4, + "nextQuestionId": "4", "text": "Поищете другой путь, минуя яму.", "description": "Находите скрытый проход." }, { "id": 33, - "questionId": 3, - "nextQuestionId": 910, + "nextQuestionId": "910", "text": "Попытаетесь перепрыгнуть яму.", "description": "Падение." }, { "id": 34, - "questionId": 3, - "nextQuestionId": 4, + "nextQuestionId": "4", "text": "Кинете камень на противоположную сторону, проверяя пол.", "description": "Пол безопасен. Переходите." } ] }, { - "id": 3, + "id": "3", "questId": 2, "text": "За дверью — комната с ямой посередине. На стене рычаг. Ваши действия?", "answers": [ { "id": 31, - "questionId": 3, - "nextQuestionId": 910, + "nextQuestionId": "910", "text": "Дёрнете рычаг сразу.", "description": "Яма расширяется." }, { "id": 32, - "questionId": 3, - "nextQuestionId": 4, + "nextQuestionId": "4", "text": "Поищете другой путь, минуя яму.", "description": "Находите скрытый проход." }, { "id": 33, - "questionId": 3, - "nextQuestionId": 910, + "nextQuestionId": "910", "text": "Попытаетесь перепрыгнуть яму.", "description": "Падение." }, { "id": 34, - "questionId": 3, - "nextQuestionId": 4, + "nextQuestionId": "4", "text": "Кинете камень на противоположную сторону, проверяя пол.", "description": "Пол безопасен. Переходите." } ] }, { - "id": 810, + "id": "810", "questId": 1, "text": "Тебя вернули домой, победа", "answers": null }, { - "id": 910, + "id": "910", "questId": 2, "text": "Проигрыш", "answers": null - }, - { - "id": 911, - "questId": 1, - "text": "Твою ложь разоблачили, поражение", - "answers": null } ] } diff --git a/src/main/webapp/WEB-INF/play-game.jsp b/src/main/webapp/WEB-INF/play-game.jsp new file mode 100644 index 0000000..4cb57b3 --- /dev/null +++ b/src/main/webapp/WEB-INF/play-game.jsp @@ -0,0 +1,36 @@ +<%@ page contentType="text/html;charset=UTF-8" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + + + + + Play Game + + +

${requestScope.quest.title}

+
+
+ + + Вопрос + + +
+ +
+ +
+ +
+
+
+
+ +
+
+ + diff --git a/src/main/webapp/WEB-INF/quest-page.jsp b/src/main/webapp/WEB-INF/quest-page.jsp index dea3ce9..b43cb8f 100644 --- a/src/main/webapp/WEB-INF/quest-page.jsp +++ b/src/main/webapp/WEB-INF/quest-page.jsp @@ -5,19 +5,19 @@ New Quest -<%-- -<%-- integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">--%> - -<%-- --%>

${requestScope.quest.title}

+

${requestScope.quest.description}

- + + + + + - From 83adc8f1e53e862860ad5a907a2675a0036996a5 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Wed, 21 Jan 2026 16:40:44 +0500 Subject: [PATCH 07/65] MOVE from question to question --- .../com/javarush/vasileva/cmd/PlayGame.java | 65 +++++++++++++---- .../com/javarush/vasileva/config/Config.java | 2 + .../com/javarush/vasileva/entity/Quest.java | 2 +- .../vasileva/repository/AnswerRepository.java | 3 + .../repository/QuestionRepository.java | 7 ++ .../vasileva/service/QuestionService.java | 7 +- src/main/webapp/WEB-INF/home.jsp | 14 ++-- src/main/webapp/WEB-INF/play-game.jsp | 70 +++++++++++++------ src/main/webapp/static/css/style.css | 11 +++ 9 files changed, 137 insertions(+), 44 deletions(-) diff --git a/src/main/java/com/javarush/vasileva/cmd/PlayGame.java b/src/main/java/com/javarush/vasileva/cmd/PlayGame.java index a964ace..a899b5c 100644 --- a/src/main/java/com/javarush/vasileva/cmd/PlayGame.java +++ b/src/main/java/com/javarush/vasileva/cmd/PlayGame.java @@ -1,14 +1,11 @@ package com.javarush.vasileva.cmd; -import com.javarush.vasileva.entity.Answer; -import com.javarush.vasileva.entity.Quest; -import com.javarush.vasileva.entity.Question; +import com.javarush.vasileva.entity.*; import com.javarush.vasileva.service.AnswerService; import com.javarush.vasileva.service.QuestService; import com.javarush.vasileva.service.QuestionService; import jakarta.servlet.http.HttpServletRequest; -import java.util.List; import java.util.Optional; public class PlayGame implements Command { @@ -24,18 +21,60 @@ public PlayGame(QuestService questService, QuestionService questionService, Answ @Override public String doGet(HttpServletRequest req) { - String strId = req.getParameter("id"); - if (strId != null && !strId.isEmpty()) { - long id = Long.parseLong(strId); - Quest quest = questService.get(id).orElseThrow(); + String questIdStr = req.getParameter("id"); + String questionIdStr = req.getParameter("questionId"); + if (questIdStr != null && !questIdStr.isEmpty()) { + long questId = Long.parseLong(questIdStr); + Quest quest = questService.get(questId).orElseThrow(); req.setAttribute("quest", quest); - System.out.println(quest.getStartQuestionId()); - Optional current = questionService.get(quest.getStartQuestionId()); - current.ifPresent(question -> req.setAttribute("question", question)); - List answers = current.get().getAnswers(); - req.setAttribute("answers", answers); + Long currentQuestionId; + if (questionIdStr == null || questionIdStr.isEmpty()) { + currentQuestionId = quest.getStartQuestionId(); + } else { + currentQuestionId = Long.parseLong(questionIdStr); + } + + System.out.println("current" + currentQuestionId); + + Optional currentQuestion = questionService.get(currentQuestionId); + if (currentQuestion.isPresent()) { + req.setAttribute("question", currentQuestion.get()); + req.setAttribute("answers", currentQuestion.get().getAnswers()); + } else { + req.setAttribute("gameOver", true); + } } return getView(); } + + @Override + public String doPost(HttpServletRequest req) { + String questIdStr = req.getParameter("questId"); + String answerIdStr = req.getParameter("selectedAnswerId"); + + if (questIdStr == null || answerIdStr == null) { + return getView() + "?id=" + questIdStr; // Возвращаем на тот же экран + } + + long questId = Long.parseLong(questIdStr); + long answerId = Long.parseLong(answerIdStr); + + Optional answerOpt = answerService.get(answerId); + if (answerOpt.isEmpty()) { + return getView() + "?id=" + questId; + } + + Answer answer = answerOpt.get(); + + String nextQuestionIdStr = answer.getNextQuestionId(); + if (nextQuestionIdStr == null || nextQuestionIdStr.isEmpty()) { + return getView() + "?id=" + questId + "&gameOver=true"; + } + + Optional nextQuestionOpt = questionService.getByIdAndQuestId(nextQuestionIdStr, questId); + long nextQuestionId = nextQuestionOpt.get().getGeneratedId(); + + return getView() + "?id=" + questId + "&questionId=" + nextQuestionId; + } } diff --git a/src/main/java/com/javarush/vasileva/config/Config.java b/src/main/java/com/javarush/vasileva/config/Config.java index 26a6368..3575fab 100644 --- a/src/main/java/com/javarush/vasileva/config/Config.java +++ b/src/main/java/com/javarush/vasileva/config/Config.java @@ -39,6 +39,8 @@ public void fillRepository() { answerService.create(answer); } } + long startQuestionId = quest.getQuestions().get(0).getGeneratedId(); + quest.setStartQuestionId(startQuestionId); } } catch (IOException e) { System.out.println(e.getMessage()); diff --git a/src/main/java/com/javarush/vasileva/entity/Quest.java b/src/main/java/com/javarush/vasileva/entity/Quest.java index 854bc72..e8e581a 100644 --- a/src/main/java/com/javarush/vasileva/entity/Quest.java +++ b/src/main/java/com/javarush/vasileva/entity/Quest.java @@ -15,6 +15,6 @@ public class Quest { private Long id; private String title; private String description; - private Long startQuestionId = 1L; + private Long startQuestionId; private List questions; } diff --git a/src/main/java/com/javarush/vasileva/repository/AnswerRepository.java b/src/main/java/com/javarush/vasileva/repository/AnswerRepository.java index a3600e2..e66c026 100644 --- a/src/main/java/com/javarush/vasileva/repository/AnswerRepository.java +++ b/src/main/java/com/javarush/vasileva/repository/AnswerRepository.java @@ -7,9 +7,11 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; public class AnswerRepository implements Repository { private final Map answers = new ConcurrentHashMap<>(); + private static final AtomicLong generatedId = new AtomicLong(); @Override public List getAll() { @@ -22,6 +24,7 @@ public Optional get(long id) { } public void create(Answer answer) { + answer.setId(generatedId.incrementAndGet()); answers.put(answer.getId(), answer); } diff --git a/src/main/java/com/javarush/vasileva/repository/QuestionRepository.java b/src/main/java/com/javarush/vasileva/repository/QuestionRepository.java index 4acbef7..e53242c 100644 --- a/src/main/java/com/javarush/vasileva/repository/QuestionRepository.java +++ b/src/main/java/com/javarush/vasileva/repository/QuestionRepository.java @@ -25,6 +25,13 @@ public Optional get(long id) { return Optional.ofNullable(questions.get(id)); } + public Optional getByIdAndQuestId(String id, long questId) { + return questions.values().stream() + .filter(question -> question.getId().equals(id)) + .filter(question -> question.getQuestId() == questId) + .findFirst(); + } + public void create(Question question) { question.setGeneratedId(generatedId.incrementAndGet()); questions.put(question.getGeneratedId(), question); diff --git a/src/main/java/com/javarush/vasileva/service/QuestionService.java b/src/main/java/com/javarush/vasileva/service/QuestionService.java index cbc172d..5971d24 100644 --- a/src/main/java/com/javarush/vasileva/service/QuestionService.java +++ b/src/main/java/com/javarush/vasileva/service/QuestionService.java @@ -2,14 +2,13 @@ import com.javarush.vasileva.entity.Question; import com.javarush.vasileva.repository.QuestionRepository; -import com.javarush.vasileva.repository.Repository; import java.util.List; import java.util.Optional; public class QuestionService { - private final Repository questionRepository; + private final QuestionRepository questionRepository; public QuestionService(QuestionRepository questionRepository) { this.questionRepository = questionRepository; @@ -23,6 +22,10 @@ public Optional get(Long id) { return questionRepository.get(id); } + public Optional getByIdAndQuestId(String id, long questId) { + return questionRepository.getByIdAndQuestId(id, questId); + } + public void create(Question question) { questionRepository.create(question); } diff --git a/src/main/webapp/WEB-INF/home.jsp b/src/main/webapp/WEB-INF/home.jsp index 372204c..c4c72e6 100644 --- a/src/main/webapp/WEB-INF/home.jsp +++ b/src/main/webapp/WEB-INF/home.jsp @@ -1,18 +1,20 @@ <%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> -... -<%----%> + + Home - +<%-- +<%-- integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">--%> -

Quests

+

Quests

- ${quest.title}
+
diff --git a/src/main/webapp/WEB-INF/play-game.jsp b/src/main/webapp/WEB-INF/play-game.jsp index 4cb57b3..572761d 100644 --- a/src/main/webapp/WEB-INF/play-game.jsp +++ b/src/main/webapp/WEB-INF/play-game.jsp @@ -8,29 +8,55 @@

${requestScope.quest.title}

-
-
- - - Вопрос - - -
- -
- -
- -
-
+ + +
+

Игра завершена! Спасибо за участие.

+ Вернуться на главную +
+
+ + + + + +
+ Вопрос № ${requestScope.question.id} + +
+ +
+ +
+ + +
+
+
-
-
-
+ + + + + + +
+ Вопрос не найден. Проверьте ID. +
+ Вернуться +
+ diff --git a/src/main/webapp/static/css/style.css b/src/main/webapp/static/css/style.css index c5a3aab..85f0848 100644 --- a/src/main/webapp/static/css/style.css +++ b/src/main/webapp/static/css/style.css @@ -39,6 +39,13 @@ b { a { text-decoration: none; + color: #d4b588; +} + +a:hover { + text-decoration: none; + color: #fff; + font-size: large; } button { @@ -78,6 +85,10 @@ button:last-of-type:hover { transform: translateY(-2px); } +.quest-container { + margin: 30px; +} + .quest-text { background-color: rgba(34, 24, 16, 0.6); padding: 20px; From e0d132d2a2940c34ea4cf6eb55c8849af1fd9bd1 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Thu, 22 Jan 2026 10:43:20 +0500 Subject: [PATCH 08/65] ADD new quest --- .../com/javarush/vasileva/cmd/PlayGame.java | 3 + .../com/javarush/vasileva/config/Config.java | 7 +- src/main/resources/quest-1.json | 6 - src/main/resources/quest-2.json | 430 +++++++++++++--- src/main/resources/quest-3.json | 477 ++++++++++++++++++ 5 files changed, 843 insertions(+), 80 deletions(-) create mode 100644 src/main/resources/quest-3.json diff --git a/src/main/java/com/javarush/vasileva/cmd/PlayGame.java b/src/main/java/com/javarush/vasileva/cmd/PlayGame.java index a899b5c..a2bb546 100644 --- a/src/main/java/com/javarush/vasileva/cmd/PlayGame.java +++ b/src/main/java/com/javarush/vasileva/cmd/PlayGame.java @@ -72,7 +72,10 @@ public String doPost(HttpServletRequest req) { return getView() + "?id=" + questId + "&gameOver=true"; } + System.out.println("Ищем вопрос: id=" + nextQuestionIdStr + ", questId=" + questId); Optional nextQuestionOpt = questionService.getByIdAndQuestId(nextQuestionIdStr, questId); + System.out.println("Найден вопрос: " + nextQuestionOpt.isPresent()); + long nextQuestionId = nextQuestionOpt.get().getGeneratedId(); return getView() + "?id=" + questId + "&questionId=" + nextQuestionId; diff --git a/src/main/java/com/javarush/vasileva/config/Config.java b/src/main/java/com/javarush/vasileva/config/Config.java index 3575fab..0222e31 100644 --- a/src/main/java/com/javarush/vasileva/config/Config.java +++ b/src/main/java/com/javarush/vasileva/config/Config.java @@ -19,9 +19,10 @@ public class Config { private final AnswerService answerService = Winter.find(AnswerService.class); private final QuestMapper questMapper = Winter.find(QuestMapper.class); - public static final String QUEST_FILE_NAME_1 = "/Users/katiavasileva/IdeaProjects/quest/src/main/resources/quest-1.json"; - public static final String QUEST_FILE_NAME_2 = "/Users/katiavasileva/IdeaProjects/quest/src/main/resources/quest-2.json"; - public static final String[] QUEST_FILES = {QUEST_FILE_NAME_1, QUEST_FILE_NAME_2}; + public static final String QUEST_FILE_NAME_1 = "/Users/katiavasileva/IdeaProjects/ProjectPantera/src/main/resources/quest-1.json"; + public static final String QUEST_FILE_NAME_2 = "/Users/katiavasileva/IdeaProjects/ProjectPantera/src/main/resources/quest-2.json"; + public static final String QUEST_FILE_NAME_3 = "/Users/katiavasileva/IdeaProjects/ProjectPantera/src/main/resources/quest-3.json"; + public static final String[] QUEST_FILES = {QUEST_FILE_NAME_1, QUEST_FILE_NAME_2, QUEST_FILE_NAME_3}; public void fillRepository() { try { diff --git a/src/main/resources/quest-1.json b/src/main/resources/quest-1.json index 75160f3..d867679 100644 --- a/src/main/resources/quest-1.json +++ b/src/main/resources/quest-1.json @@ -9,12 +9,10 @@ "text": "Принять вызов НЛО?", "answers": [ { - "id": 11, "nextQuestionId": "2", "text": "Принять вызов" }, { - "id": 12, "nextQuestionId": "910", "text": "Отклонить вызов" } @@ -26,12 +24,10 @@ "text": "Поднимешься на мостик к капитану?", "answers": [ { - "id": 21, "nextQuestionId": "3", "text": "Подняться на мостик" }, { - "id": 22, "nextQuestionId": "910", "text": "Отказаться подниматься на мостик" } @@ -43,12 +39,10 @@ "text": "Ты поднялся на мостик. Ты кто?", "answers": [ { - "id": 31, "nextQuestionId": "810", "text": "Рассказать правду о себе" }, { - "id": 32, "nextQuestionId": "911", "text": "Солгать о себе" } diff --git a/src/main/resources/quest-2.json b/src/main/resources/quest-2.json index 4feca85..19383b0 100644 --- a/src/main/resources/quest-2.json +++ b/src/main/resources/quest-2.json @@ -9,25 +9,21 @@ "text": "Вы входите в тёмный коридор. Впереди слышен шорох.", "answers": [ { - "id": 11, "nextQuestionId": "2", "text": "Достанете факел и осторожно продвинетесь вперёд.", "description": "" }, { - "id": 12, - "nnextQuestionId": "2", + "nextQuestionId": "2", "text": "Бросите камень в сторону шума, чтобы проверить.", "description": "Вы пугаете крысу. Путь свободен." }, { - "id": 13, "nextQuestionId": "910", "text": "Повернётесь и пойдёте назад.", "description": "Попадаете в тупик." }, { - "id": 14, "nextQuestionId": "910", "text": "Закричите, чтобы отпугнуть возможного врага.", "description": "Шум привлекает монстров." @@ -40,19 +36,16 @@ "text": "Факел осветил три двери. На каждой — символ: огонь, вода, луна. Какую выберете?", "answers": [ { - "id": 21, "nextQuestionId": "3", "text": "С символом огня (рискованно, но может вести к сокровищам).", "description": "В комнате лава. Нужно найти мост." }, { - "id": 22, "nextQuestionId": "8", "text": "С символом воды (кажется безопасной).", "description": "Подземный ручей." }, { - "id": 23, "nextQuestionId": "910", "text": "С символом луны (загадочно, возможно, ловушка).", "description": "Ловушка: пол проваливается." @@ -65,25 +58,21 @@ "text": "За дверью — комната с ямой посередине. На стене рычаг. Ваши действия?", "answers": [ { - "id": 31, "nextQuestionId": "910", "text": "Дёрнете рычаг сразу.", "description": "Яма расширяется." }, { - "id": 32, "nextQuestionId": "4", "text": "Поищете другой путь, минуя яму.", "description": "Находите скрытый проход." }, { - "id": 33, "nextQuestionId": "910", "text": "Попытаетесь перепрыгнуть яму.", "description": "Падение." }, { - "id": 34, "nextQuestionId": "4", "text": "Кинете камень на противоположную сторону, проверяя пол.", "description": "Пол безопасен. Переходите." @@ -96,25 +85,21 @@ "text": "Рычаг активировал механизм: из стен выдвинулись шипы. Как спастись?", "answers": [ { - "id": 41, "nextQuestionId": "5", "text": "Прижмётесь к стене и медленно пройдёте.", "description": "Успешно проходите." }, { - "id": 42, "nextQuestionId": "5", "text": "Побежите напролом, уклоняясь.", "description": "Ранение. Здоровье снижается." }, { - "id": 43, "nextQuestionId": "5", "text": "Найдёте кнопку отключения механизмов.", "description": "Находите механизм." }, { - "id": 44, "nextQuestionId": "910", "text": "Вернётесь назад.", "description": "Путь заблокирован. " @@ -127,25 +112,21 @@ "text": "В этой комнате — статуя дракона. На постаменте надпись: «Скажи имя древнего бога».", "answers": [ { - "id": 51, "nextQuestionId": "910", "text": "Азраэль.", "description": "Статуя атакует." }, { - "id": 52, "nextQuestionId": "6", "text": "Таргон.", "description": "Верно! Статуя пропускает." }, { - "id": 53, "nextQuestionId": "910", "text": "Вельдан.", "description": "Ошибка. Ловушка." }, { - "id": 54, "nextQuestionId": "5", "text": "Промолчите и осмотрите комнату ещё раз.", "description": "Находите надпись с именем: Таргон" @@ -153,95 +134,402 @@ ] }, { - "id": "3", + "id": "6", "questId": 2, - "text": "За дверью — комната с ямой посередине. На стене рычаг. Ваши действия?", + "text": "Статуя оживает! Как поступить?", "answers": [ { - "id": 31, + "nextQuestionId": "7", + "text": "Попробуете заговорить с ней.", + "description": "Дракон даёт подсказку." + }, + { "nextQuestionId": "910", - "text": "Дёрнете рычаг сразу.", - "description": "Яма расширяется." + "text": "Атакуете первым.", + "description": "Проигрываете бой." }, { - "id": 32, - "nextQuestionId": "4", - "text": "Поищете другой путь, минуя яму.", - "description": "Находите скрытый проход." + "nextQuestionId": "7", + "text": "Бросите в неё магический свиток.", + "description": "Оглушаете дракона." }, { - "id": 33, - "nextQuestionId": "910", - "text": "Попытаетесь перепрыгнуть яму.", - "description": "Падение." + "nextQuestionId": "7", + "text": "Спрячетесь за колонну.", + "description": "Дракон уходит. " + } + ] + }, + { + "id": "7", + "questId": 2, + "text": "Дракон пропускает вас, но предупреждает: «Следующий — не человек». В коридоре два пути:", + "answers": [ + { + "nextQuestionId": "8", + "text": "Левый — пахнет сыростью (возможно, вода).", + "description": "Вы вышли к ручью." }, { - "id": 34, - "nextQuestionId": "4", - "text": "Кинете камень на противоположную сторону, проверяя пол.", - "description": "Пол безопасен. Переходите." + "nextQuestionId": "9", + "text": "Правый — слышны голоса (люди или монстры?).", + "description": "Вы вступили в бой с бандитами и победили их." + }, + { + "nextQuestionId": "910", + "text": "Вернётесь к статуе за советом.", + "description": "Статуя исчезла." } ] }, { - "id": "3", + "id": "8", "questId": 2, - "text": "За дверью — комната с ямой посередине. На стене рычаг. Ваши действия?", + "text": "В левом коридоре — подземный ручей. Как перебраться?", "answers": [ { - "id": 31, "nextQuestionId": "910", - "text": "Дёрнете рычаг сразу.", - "description": "Яма расширяется." + "text": "Попытаетесь проплыть.", + "description": "Вас уносит течением." }, { - "id": 32, - "nextQuestionId": "4", - "text": "Поищете другой путь, минуя яму.", - "description": "Находите скрытый проход." + "nextQuestionId": "9", + "text": "Найдете упавшее бревно и используете его как мост.", + "description": "Мост готов." }, { - "id": 33, - "nextQuestionId": "910", - "text": "Попытаетесь перепрыгнуть яму.", - "description": "Падение." + "nextQuestionId": "8", + "text": "Используете верёвку, чтобы перемахнуть.", + "description": "Не хватает длины." }, { - "id": 34, - "nextQuestionId": "4", - "text": "Кинете камень на противоположную сторону, проверяя пол.", - "description": "Пол безопасен. Переходите." + "nextQuestionId": "910", + "text": "Поищете обходной путь.", + "description": "Вы заблудились и вас съел дракон." } ] }, { - "id": "3", + "id": "9", "questId": 2, - "text": "За дверью — комната с ямой посередине. На стене рычаг. Ваши действия?", + "text": "На другом берегу — дверь с замком. Как вы поступите?", "answers": [ { - "id": 31, - "nextQuestionId": "910", - "text": "Дёрнете рычаг сразу.", - "description": "Яма расширяется." + "nextQuestionId": "10", + "text": "Взломаете замок отмычкой.", + "description": "У вас получилось взломать замок." }, { - "id": 32, - "nextQuestionId": "4", - "text": "Поищете другой путь, минуя яму.", - "description": "Находите скрытый проход." + "nextQuestionId": "11", + "text": "Ударите по нему мечом.", + "description": "Замок ломается, но шум привлекает врагов." + }, + { + "nextQuestionId": "10", + "text": "Поищете ключ поблизости.", + "description": "Вы находите ключ в соседней комнате." }, { - "id": 33, "nextQuestionId": "910", - "text": "Попытаетесь перепрыгнуть яму.", - "description": "Падение." + "text": "Попробуете выбить дверь плечом.", + "description": "Дверь не поддаётся." + } + ] + }, + { + "id": "10", + "questId": 2, + "text": "За дверью — зал с четырьмя алтарями. На каждом — предмет: меч, книга, череп, кристалл. Какой возьмёте?", + "answers": [ + { + "nextQuestionId": "11", + "text": "Меч (для защиты).", + "description": "Активирует ловушку." }, { - "id": 34, - "nextQuestionId": "4", - "text": "Кинете камень на противоположную сторону, проверяя пол.", - "description": "Пол безопасен. Переходите." + "nextQuestionId": "14", + "text": "Книгу (возможно, подсказка).", + "description": "Подсказка к загадке. " + }, + { + "nextQuestionId": "12", + "text": "Череп (опасно, но магически).", + "description": "Вызывает духа. Вам приходится вступить с ним в бой." + }, + { + "nextQuestionId": "13", + "text": "Кристалл (светится, может быть артефактом).", + "description": "Светит в темноте." + } + ] + }, + { + "id": "11", + "questId": 2, + "text": "Статуя оживает! Как поступить?", + "answers": [ + { + "nextQuestionId": "", + "text": "Попробуете заговорить с ней.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Атакуете первым.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Бросите в неё магический свиток.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Спрячетесь за колонну.", + "description": "" + } + ] + }, + { + "id": "12", + "questId": 2, + "text": "Статуя оживает! Как поступить?", + "answers": [ + { + "nextQuestionId": "", + "text": "Попробуете заговорить с ней.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Атакуете первым.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Бросите в неё магический свиток.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Спрячетесь за колонну.", + "description": "" + } + ] + }, + { + "id": "13", + "questId": 2, + "text": "Статуя оживает! Как поступить?", + "answers": [ + { + "nextQuestionId": "", + "text": "Попробуете заговорить с ней.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Атакуете первым.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Бросите в неё магический свиток.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Спрячетесь за колонну.", + "description": "" + } + ] + }, + { + "id": "14", + "questId": 2, + "text": "Статуя оживает! Как поступить?", + "answers": [ + { + "nextQuestionId": "", + "text": "Попробуете заговорить с ней.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Атакуете первым.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Бросите в неё магический свиток.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Спрячетесь за колонну.", + "description": "" + } + ] + }, + { + "id": "15", + "questId": 2, + "text": "Статуя оживает! Как поступить?", + "answers": [ + { + "nextQuestionId": "", + "text": "Попробуете заговорить с ней.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Атакуете первым.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Бросите в неё магический свиток.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Спрячетесь за колонну.", + "description": "" + } + ] + }, + { + "id": "16", + "questId": 2, + "text": "Статуя оживает! Как поступить?", + "answers": [ + { + "nextQuestionId": "", + "text": "Попробуете заговорить с ней.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Атакуете первым.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Бросите в неё магический свиток.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Спрячетесь за колонну.", + "description": "" + } + ] + }, + { + "id": "17", + "questId": 2, + "text": "Статуя оживает! Как поступить?", + "answers": [ + { + "nextQuestionId": "", + "text": "Попробуете заговорить с ней.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Атакуете первым.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Бросите в неё магический свиток.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Спрячетесь за колонну.", + "description": "" + } + ] + }, + { + "id": "18", + "questId": 2, + "text": "Статуя оживает! Как поступить?", + "answers": [ + { + "nextQuestionId": "", + "text": "Попробуете заговорить с ней.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Атакуете первым.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Бросите в неё магический свиток.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Спрячетесь за колонну.", + "description": "" + } + ] + }, + { + "id": "19", + "questId": 2, + "text": "Статуя оживает! Как поступить?", + "answers": [ + { + "nextQuestionId": "", + "text": "Попробуете заговорить с ней.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Атакуете первым.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Бросите в неё магический свиток.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Спрячетесь за колонну.", + "description": "" + } + ] + }, + { + "id": "20", + "questId": 2, + "text": "Статуя оживает! Как поступить?", + "answers": [ + { + "nextQuestionId": "", + "text": "Попробуете заговорить с ней.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Атакуете первым.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Бросите в неё магический свиток.", + "description": "" + }, + { + "nextQuestionId": "", + "text": "Спрячетесь за колонну.", + "description": "" } ] }, diff --git a/src/main/resources/quest-3.json b/src/main/resources/quest-3.json new file mode 100644 index 0000000..d6fd3f6 --- /dev/null +++ b/src/main/resources/quest-3.json @@ -0,0 +1,477 @@ +{ + "id": 3, + "title": "Автостопом по здравому смыслу (или Не паникуй)", + "description": "Добро пожаловать в квест, который начинается с конца света и быстро переходит к вопросам посложнее. Землю сносят ради гиперпространственной магистрали, предупреждения были вывешены (где-то далеко и давно), а у вас есть лишь выбор, полотенце и крайне смутное представление о происходящем. Впереди — вогоны, сомнительный чай, философские размышления и шанс узнать ответ на Главный вопрос жизни, Вселенной и всего такого. Главное — не паникуйте: Вселенная всё равно делает вид, что всё под контролем.", + "questions": [ + { + "id": "1", + "questId": 3, + "text": "Вы просыпаетесь и узнаёте, что Землю демонтируют ради гиперпространственной магистрали. Что будете делать?", + "answers": [ + { + "nextQuestionId": "2", + "text": "Вы возмущённо требуете документы, разрешения и хотя бы подпись ответственного лица. Вселенная равнодушно зевает." + }, + { + "nextQuestionId": "3", + "text": "Вы вспоминаете главное правило галактического путешественника и лихорадочно ищете полотенце. Это внушает необъяснимое спокойствие." + }, + { + "nextQuestionId": "4", + "text": "Вы уточняете, будет ли обед до конца света, потому что на голодный желудок апокалипсис переносится хуже." + }, + { + "nextQuestionId": "5", + "text": "Вы решаете, что это сон, и пробуете снова уснуть, пока Вселенная не передумала." + } + ] + }, + { + "id": "2", + "questId": 3, + "text": "Перед вами стоит вогон, держащий папку подозрительно толстых стихов.", + "answers": [ + { + "nextQuestionId": "6", + "text": "Вы пытаетесь убежать, но быстро понимаете, что в условиях вакуума это не лучшая стратегия." + }, + { + "nextQuestionId": "7", + "text": "Вы представляете себя галактическим юристом и начинаете говорить словами, смысл которых неизвестен даже вам." + }, + { + "nextQuestionId": "8", + "text": "Вы вежливо просите почитать стихи вслух, подозревая, что хуже уже не будет." + }, + { + "nextQuestionId": "9", + "text": "Вы начинаете плакать заранее, экономя время на эмоциональной реакции." + } + ] + }, + { + "id": "3", + "questId": 3, + "text": "Полотенце найдено. Оно слегка влажное, но внушает доверие.", + "answers": [ + { + "nextQuestionId": "6", + "text": "Вы используете его как универсальное средство защиты от всего непонятного." + }, + { + "nextQuestionId": "10", + "text": "Вы накидываете его как плащ и чувствуете себя героем космооперы." + }, + { + "nextQuestionId": "5", + "text": "Вы обнимаете полотенце, потому что оно единственное, что сейчас вас понимает." + }, + { + "nextQuestionId": "9", + "text": "Вы тут же его теряете, подтверждая законы Вселенной." + } + ] + }, + { + "id": "4", + "questId": 3, + "text": "Мысли о еде не покидают вас даже в момент уничтожения планеты.", + "answers": [ + { + "nextQuestionId": "11", + "text": "Вы решаете сделать бутерброд, игнорируя катастрофу как нечто второстепенное." + }, + { + "nextQuestionId": "12", + "text": "Вы жалуетесь Вселенной на несвоевременность происходящего." + }, + { + "nextQuestionId": "5", + "text": "Вы смиряетесь с судьбой и принимаете происходящее как должное." + }, + { + "nextQuestionId": "13", + "text": "Вы спрашиваете, где чай, потому что без него цивилизация не имеет смысла." + } + ] + }, + { + "id": "5", + "questId": 3, + "text": "Вы понимаете: это не сон, а реальность, причём весьма навязчивая.", + "answers": [ + { + "nextQuestionId": "9", + "text": "Вы начинаете паниковать, громко и без системы." + }, + { + "nextQuestionId": "10", + "text": "Вы вспоминаете надпись «DON’T PANIC» и стараетесь выглядеть уверенно." + }, + { + "nextQuestionId": "12", + "text": "Вы философски принимаете происходящее, как будто читали об этом раньше.", + "description": "" + }, + { + "nextQuestionId": "14", + "text": "Вы выкрикиваете «42!» без всякой причины, но с чувством." + } + ] + }, + { + "id": "6", + "questId": 3, + "text": "Вас без особых церемоний выбрасывают в открытый космос. Он холодный, бесконечный и явно не собирается извиняться.", + "answers": [ + { + "nextQuestionId": "15", + "text": "Вы задерживаете дыхание, словно космос обязан это заметить и проявить такт." + }, + { + "nextQuestionId": "9", + "text": "Вы начинаете кричать, несмотря на смутное подозрение, что звук здесь не работает." + }, + { + "nextQuestionId": "16", + "text": "Вы решаете положиться на сюжетную броню главного героя, даже если не уверены, что вы главный." + }, + { + "nextQuestionId": "12", + "text": "Вы вежливо извиняетесь перед космосом за возможные неудобства. Космос впечатлён." + } + ] + }, + { + "id": "7", + "questId": 3, + "text": "Вы представились галактическим юристом, и теперь все ждут продолжения.", + "answers": [ + { + "nextQuestionId": "8", + "text": "Вы требуете апелляцию, не уточняя, к чему именно. Звучит убедительно." + }, + { + "nextQuestionId": "9", + "text": "Вы начинаете путаться в терминах и случайно признаётесь во всех преступлениях сразу." + }, + { + "nextQuestionId": "10", + "text": "Против всех законов логики вы выигрываете дело. Вогон выглядит озадаченным." + }, + { + "nextQuestionId": "8", + "text": "В качестве «компромисса» вам предлагают послушать стихи." + } + ] + }, + { + "id": "8", + "questId": 3, + "text": "Поэзия начинается. Это заметно сразу.", + "answers": [ + { + "nextQuestionId": "15", + "text": "Вы теряете сознание, руководствуясь инстинктом самосохранения." + }, + { + "nextQuestionId": "6", + "text": "Вы хвалите рифму, чем пугаете всех присутствующих, включая автора." + }, + { + "nextQuestionId": "9", + "text": "Вы записываете цитаты, чтобы пугать ими знакомых.", + "description": "Не хватает длины." + }, + { + "nextQuestionId": "15", + "text": "Вы просите ещё. Реальность слегка трескается." + } + ] + }, + { + "id": "9", + "questId": 3, + "text": "Ситуация становится заметно хуже, чем была мгновение назад.", + "answers": [ + { + "nextQuestionId": "5", + "text": "Вы решаете сдаться и начать всё сначала." + }, + { + "nextQuestionId": "12", + "text": "Вы делаете вид, что так и было задумано." + }, + { + "nextQuestionId": "14", + "text": "Вы задаёте главный философский вопрос: «В чём вообще смысл?»" + }, + { + "nextQuestionId": "3", + "text": "Вы снова начинаете искать полотенце, потому что оно вас ещё ни разу не подводило." + } + ] + }, + { + "id": "10", + "questId": 3, + "text": "Вас подбирает корабль, который выглядит надёжным ровно настолько, насколько это возможно в галактике.", + "answers": [ + { + "nextQuestionId": "16", + "text": "Вы радуетесь спасению и решаете не задавать лишних вопросов." + }, + { + "nextQuestionId": "17", + "text": "Вы внимательно разглядываете экипаж, подозревая худшее." + }, + { + "nextQuestionId": "9", + "text": "Вы прячетесь за ближайшим ящиком. На всякий случай." + }, + { + "nextQuestionId": "11", + "text": "Вы спрашиваете, куда летит корабль, и сразу жалеете об этом." + } + ] + }, + { + "id": "11", + "questId": 3, + "text": "На борту обсуждают еду, и это внезапно кажется важным.", + "answers": [ + { + "nextQuestionId": "13", + "text": "Вы заказываете чай, надеясь, что в этот раз всё будет иначе." + }, + { + "nextQuestionId": "14", + "text": "Вы снова поднимаете тему смысла жизни. Не вовремя, но искренне." + }, + { + "nextQuestionId": "9", + "text": "Вы пробуете что-то странное, светящееся и, возможно, разумное." + }, + { + "nextQuestionId": "12", + "text": "Вы решаете ничего не есть и просто подумать." + } + ] + }, + { + "id": "12", + "questId": 3, + "text": "Вы внезапно ловите себя на том, что задумались. Это опасно, но уже поздно.", + "answers": [ + { + "nextQuestionId": "14", + "text": "Вы размышляете о жизни: зачем она дана, почему всё так странно и кто вообще всё это придумал." + }, + { + "nextQuestionId": "14", + "text": "Вы думаете о Вселенной — бесконечной, равнодушной и удивительно хорошо организованной для хаоса." + }, + { + "nextQuestionId": "14", + "text": "Вы пытаетесь осмыслить всё сразу: жизнь, Вселенную и остальное, но мысль ускользает." + }, + { + "nextQuestionId": "5", + "text": "Вы решаете, что думать — занятие переоценённое, и возвращаетесь к реальности." + } + ] + }, + { + "id": "13", + "questId": 3, + "text": "Вам приносят чай. Он снова не такой, как надо.", + "answers": [ + { + "nextQuestionId": "9", + "text": "Вы возмущаетесь, потому что чай — это вопрос принципа, а не вкуса." + }, + { + "nextQuestionId": "17", + "text": "Вы пытаетесь улучшить напиток научным методом, добавляя ингредиенты сомнительного происхождения." + }, + { + "nextQuestionId": "12", + "text": "Вы философски принимаете чай как символ несовершенства Вселенной." + }, + { + "nextQuestionId": "3", + "text": "Вы отвлекаетесь и спрашиваете, где ваше полотенце." + } + ] + }, + { + "id": "14", + "questId": 3, + "text": "Наступает торжественный момент. Вам задают Главный вопрос жизни, Вселенной и всего такого. Все замолкают. Даже космос делает вид, что слушает.", + "answers": [ + { + "nextQuestionId": "9", + "text": "Вы отвечаете: «Любовь». Это звучит красиво, но Вселенная выглядит разочарованной." + }, + { + "nextQuestionId": "9", + "text": "Вы честно говорите: «Деньги». Вселенная вздыхает и делает пометку." + }, + { + "nextQuestionId": "20", + "text": "Вы уверенно и без лишних слов произносите: 42. Вселенная одобрительно молчит. Это хороший знак." + }, + { + "nextQuestionId": "9", + "text": "Вы заявляете, что вопрос сформулирован некорректно. Вселенная кивает, но продолжает эксперимент." + } + ] + }, + { + "id": "15", + "questId": 3, + "text": "Вы обнаруживаете, что каким-то образом всё ещё существуете.", + "answers": [ + { + "nextQuestionId": "16", + "text": "Вы благодарите Вселенную за то, что она сегодня в хорошем настроении." + }, + { + "nextQuestionId": "12", + "text": "Вы долго и искренне удивляетесь происходящему." + }, + { + "nextQuestionId": "5", + "text": "Вы проверяете, действительно ли вы живы, на всякий случай." + }, + { + "nextQuestionId": "17", + "text": "Вы решаете, что это странно, но, вероятно, нормально." + } + ] + }, + { + "id": "16", + "questId": 3, + "text": "У вас появляется ощущение, что вы близки к истине. Это тревожит.", + "answers": [ + { + "nextQuestionId": "20", + "text": "Вы решаете продолжить путешествие, не вдаваясь в детали." + }, + { + "nextQuestionId": "14", + "text": "Вы задаёте ещё один вопрос, потому что не умеете останавливаться." + }, + { + "nextQuestionId": "12", + "text": "Вы расслабляетесь и позволяете событиям происходить." + }, + { + "nextQuestionId": "3", + "text": "Вы автоматически проверяете, при вас ли полотенце." + } + ] + }, + { + "id": "17", + "questId": 3, + "text": "Перед вами андроид с крайне пессимистичным взглядом на бытие.", + "answers": [ + { + "nextQuestionId": "12", + "text": "Вы искренне сочувствуете ему. Андроид растерян: такого он не ожидал." + }, + { + "nextQuestionId": "9", + "text": "Вы позволяете ему высказаться. Через некоторое время жалеете об этом." + }, + { + "nextQuestionId": "14", + "text": "Вы спрашиваете его о смысле жизни. Он подтверждает, что всё плохо." + }, + { + "nextQuestionId": "16", + "text": "Вы медленно отходите, стараясь не привлекать внимания." + } + ] + }, + { + "id": "18", + "questId": 3, + "text": "Вселенная смотрит на вас с плохо скрываемым интересом.", + "answers": [ + { + "nextQuestionId": "12", + "text": "Вы почтительно кланяетесь, считая это уместным." + }, + { + "nextQuestionId": "16", + "text": "Вы улыбаетесь, демонстрируя уверенность, которой у вас нет." + }, + { + "nextQuestionId": "20", + "text": "Вы прямо спрашиваете: «Ну и что дальше?»" + }, + { + "nextQuestionId": "9", + "text": "Вы решаете убежать, пока всё снова не усложнилось." + } + ] + }, + { + "id": "19", + "questId": 3, + "text": "Вы чувствуете, что ответ уже близко, но всё ещё сомневаетесь.", + "answers": [ + { + "nextQuestionId": "20", + "text": "Вы делаете вывод и принимаете его без проверки.", + "description": "" + }, + { + "nextQuestionId": "9", + "text": "Вы решаете всё усложнить, потому что слишком просто не бывает.", + "description": "" + }, + { + "nextQuestionId": "14", + "text": "Вы спрашиваете ещё раз, на всякий случай." + }, + { + "nextQuestionId": "16", + "text": "Вы напоминаете себе главное правило — не паниковать." + } + ] + }, + { + "id": "20", + "questId": 3, + "text": "После всего пережитого вы наконец понимаете главное.", + "answers": [ + { + "nextQuestionId": "810", + "text": "Всегда носи полотенце" + }, + { + "nextQuestionId": "810", + "text": "Не паникуй" + }, + { + "nextQuestionId": "810", + "text": "Ответ — 42" + }, + { + "nextQuestionId": "810", + "text": "Всё вышеперечисленное" + } + ] + }, + { + "id": "810", + "questId": 3, + "text": "Поздравляем! Вы прошли квест, не сломали Вселенную и, возможно, даже стали немного мудрее.", + "answers": null + } + ] +} From 7cfd4b053f1a6343b25dbdb6ebbd1ba9fe1e719a Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Thu, 22 Jan 2026 10:55:40 +0500 Subject: [PATCH 09/65] ADD automatic id generation for quests --- .../com/javarush/vasileva/config/Config.java | 1 + .../vasileva/repository/QuestRepository.java | 7 ++++-- src/main/resources/quest-1.json | 7 ------ src/main/resources/quest-2.json | 23 ------------------- src/main/resources/quest-3.json | 22 ------------------ 5 files changed, 6 insertions(+), 54 deletions(-) diff --git a/src/main/java/com/javarush/vasileva/config/Config.java b/src/main/java/com/javarush/vasileva/config/Config.java index 0222e31..7b405c5 100644 --- a/src/main/java/com/javarush/vasileva/config/Config.java +++ b/src/main/java/com/javarush/vasileva/config/Config.java @@ -30,6 +30,7 @@ public void fillRepository() { Quest quest = questMapper.readFromJson(fileName); questService.create(quest); for (Question question : quest.getQuestions()) { + question.setQuestId(quest.getId()); questionService.create(question); List answers = question.getAnswers(); if (answers == null) { diff --git a/src/main/java/com/javarush/vasileva/repository/QuestRepository.java b/src/main/java/com/javarush/vasileva/repository/QuestRepository.java index 00524cc..4cf996e 100644 --- a/src/main/java/com/javarush/vasileva/repository/QuestRepository.java +++ b/src/main/java/com/javarush/vasileva/repository/QuestRepository.java @@ -5,11 +5,13 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; @NoArgsConstructor public class QuestRepository implements Repository { private final Map quests = new ConcurrentHashMap<>(); + private final AtomicLong generatedId = new AtomicLong(10); @Override public List getAll() { @@ -21,8 +23,9 @@ public Optional get(long id) { return Optional.ofNullable(quests.get(id)); } - public void create(Quest entity) { - quests.put(entity.getId(), entity); + public void create(Quest quest) { + quest.setId(generatedId.incrementAndGet()); + quests.put(quest.getId(), quest); } @Override diff --git a/src/main/resources/quest-1.json b/src/main/resources/quest-1.json index d867679..563c1c0 100644 --- a/src/main/resources/quest-1.json +++ b/src/main/resources/quest-1.json @@ -1,11 +1,9 @@ { - "id": 1, "title": "Космическое приключение", "description": "Про приключения в космосе", "questions": [ { "id": "1", - "questId": 1, "text": "Принять вызов НЛО?", "answers": [ { @@ -20,7 +18,6 @@ }, { "id": "2", - "questId": 1, "text": "Поднимешься на мостик к капитану?", "answers": [ { @@ -35,7 +32,6 @@ }, { "id": "3", - "questId": 1, "text": "Ты поднялся на мостик. Ты кто?", "answers": [ { @@ -50,19 +46,16 @@ }, { "id": "810", - "questId": 1, "text": "Тебя вернули домой, победа", "answers": null }, { "id": "910", - "questId": 1, "text": "Ты отклонил вызов, поражение", "answers": null }, { "id": "911", - "questId": 1, "text": "Твою ложь разоблачили, поражение", "answers": null } diff --git a/src/main/resources/quest-2.json b/src/main/resources/quest-2.json index 19383b0..419e3b6 100644 --- a/src/main/resources/quest-2.json +++ b/src/main/resources/quest-2.json @@ -1,11 +1,9 @@ { - "id": 2, "title": "Тайна Забытого Подземелья", "description": "Много веков назад дракон Вельдан, хранитель древних знаний, скрылся в недрах горы с Сердцем Дракона — артефактом невообразимой силы, спрятав его в лабиринте, известном как Забытое Подземелье. Тысячи смельчаков отправлялись на поиски реликвии, но никто не вернулся; легенды гласят, что лишь тот, кто проявит мудрость, отвагу и хладнокровие, сможет завладеть Сердцем. Теперь вы — один из искателей: с факелом и мечом перед массивной дверью с драконьей пастью, за которой таятся тьма, сырость и нечто древнее. Дверь медленно приоткрывается — готовы ли вы бросить вызов подземелью?", "questions": [ { "id": "1", - "questId": 2, "text": "Вы входите в тёмный коридор. Впереди слышен шорох.", "answers": [ { @@ -32,7 +30,6 @@ }, { "id": "2", - "questId": 2, "text": "Факел осветил три двери. На каждой — символ: огонь, вода, луна. Какую выберете?", "answers": [ { @@ -54,7 +51,6 @@ }, { "id": "3", - "questId": 2, "text": "За дверью — комната с ямой посередине. На стене рычаг. Ваши действия?", "answers": [ { @@ -81,7 +77,6 @@ }, { "id": "4", - "questId": 2, "text": "Рычаг активировал механизм: из стен выдвинулись шипы. Как спастись?", "answers": [ { @@ -108,7 +103,6 @@ }, { "id": "5", - "questId": 2, "text": "В этой комнате — статуя дракона. На постаменте надпись: «Скажи имя древнего бога».", "answers": [ { @@ -135,7 +129,6 @@ }, { "id": "6", - "questId": 2, "text": "Статуя оживает! Как поступить?", "answers": [ { @@ -162,7 +155,6 @@ }, { "id": "7", - "questId": 2, "text": "Дракон пропускает вас, но предупреждает: «Следующий — не человек». В коридоре два пути:", "answers": [ { @@ -184,7 +176,6 @@ }, { "id": "8", - "questId": 2, "text": "В левом коридоре — подземный ручей. Как перебраться?", "answers": [ { @@ -211,7 +202,6 @@ }, { "id": "9", - "questId": 2, "text": "На другом берегу — дверь с замком. Как вы поступите?", "answers": [ { @@ -238,7 +228,6 @@ }, { "id": "10", - "questId": 2, "text": "За дверью — зал с четырьмя алтарями. На каждом — предмет: меч, книга, череп, кристалл. Какой возьмёте?", "answers": [ { @@ -265,7 +254,6 @@ }, { "id": "11", - "questId": 2, "text": "Статуя оживает! Как поступить?", "answers": [ { @@ -292,7 +280,6 @@ }, { "id": "12", - "questId": 2, "text": "Статуя оживает! Как поступить?", "answers": [ { @@ -319,7 +306,6 @@ }, { "id": "13", - "questId": 2, "text": "Статуя оживает! Как поступить?", "answers": [ { @@ -346,7 +332,6 @@ }, { "id": "14", - "questId": 2, "text": "Статуя оживает! Как поступить?", "answers": [ { @@ -373,7 +358,6 @@ }, { "id": "15", - "questId": 2, "text": "Статуя оживает! Как поступить?", "answers": [ { @@ -400,7 +384,6 @@ }, { "id": "16", - "questId": 2, "text": "Статуя оживает! Как поступить?", "answers": [ { @@ -427,7 +410,6 @@ }, { "id": "17", - "questId": 2, "text": "Статуя оживает! Как поступить?", "answers": [ { @@ -454,7 +436,6 @@ }, { "id": "18", - "questId": 2, "text": "Статуя оживает! Как поступить?", "answers": [ { @@ -481,7 +462,6 @@ }, { "id": "19", - "questId": 2, "text": "Статуя оживает! Как поступить?", "answers": [ { @@ -508,7 +488,6 @@ }, { "id": "20", - "questId": 2, "text": "Статуя оживает! Как поступить?", "answers": [ { @@ -535,13 +514,11 @@ }, { "id": "810", - "questId": 1, "text": "Тебя вернули домой, победа", "answers": null }, { "id": "910", - "questId": 2, "text": "Проигрыш", "answers": null } diff --git a/src/main/resources/quest-3.json b/src/main/resources/quest-3.json index d6fd3f6..fb19d9d 100644 --- a/src/main/resources/quest-3.json +++ b/src/main/resources/quest-3.json @@ -1,11 +1,9 @@ { - "id": 3, "title": "Автостопом по здравому смыслу (или Не паникуй)", "description": "Добро пожаловать в квест, который начинается с конца света и быстро переходит к вопросам посложнее. Землю сносят ради гиперпространственной магистрали, предупреждения были вывешены (где-то далеко и давно), а у вас есть лишь выбор, полотенце и крайне смутное представление о происходящем. Впереди — вогоны, сомнительный чай, философские размышления и шанс узнать ответ на Главный вопрос жизни, Вселенной и всего такого. Главное — не паникуйте: Вселенная всё равно делает вид, что всё под контролем.", "questions": [ { "id": "1", - "questId": 3, "text": "Вы просыпаетесь и узнаёте, что Землю демонтируют ради гиперпространственной магистрали. Что будете делать?", "answers": [ { @@ -28,7 +26,6 @@ }, { "id": "2", - "questId": 3, "text": "Перед вами стоит вогон, держащий папку подозрительно толстых стихов.", "answers": [ { @@ -51,7 +48,6 @@ }, { "id": "3", - "questId": 3, "text": "Полотенце найдено. Оно слегка влажное, но внушает доверие.", "answers": [ { @@ -74,7 +70,6 @@ }, { "id": "4", - "questId": 3, "text": "Мысли о еде не покидают вас даже в момент уничтожения планеты.", "answers": [ { @@ -97,7 +92,6 @@ }, { "id": "5", - "questId": 3, "text": "Вы понимаете: это не сон, а реальность, причём весьма навязчивая.", "answers": [ { @@ -121,7 +115,6 @@ }, { "id": "6", - "questId": 3, "text": "Вас без особых церемоний выбрасывают в открытый космос. Он холодный, бесконечный и явно не собирается извиняться.", "answers": [ { @@ -144,7 +137,6 @@ }, { "id": "7", - "questId": 3, "text": "Вы представились галактическим юристом, и теперь все ждут продолжения.", "answers": [ { @@ -167,7 +159,6 @@ }, { "id": "8", - "questId": 3, "text": "Поэзия начинается. Это заметно сразу.", "answers": [ { @@ -191,7 +182,6 @@ }, { "id": "9", - "questId": 3, "text": "Ситуация становится заметно хуже, чем была мгновение назад.", "answers": [ { @@ -214,7 +204,6 @@ }, { "id": "10", - "questId": 3, "text": "Вас подбирает корабль, который выглядит надёжным ровно настолько, насколько это возможно в галактике.", "answers": [ { @@ -237,7 +226,6 @@ }, { "id": "11", - "questId": 3, "text": "На борту обсуждают еду, и это внезапно кажется важным.", "answers": [ { @@ -260,7 +248,6 @@ }, { "id": "12", - "questId": 3, "text": "Вы внезапно ловите себя на том, что задумались. Это опасно, но уже поздно.", "answers": [ { @@ -283,7 +270,6 @@ }, { "id": "13", - "questId": 3, "text": "Вам приносят чай. Он снова не такой, как надо.", "answers": [ { @@ -306,7 +292,6 @@ }, { "id": "14", - "questId": 3, "text": "Наступает торжественный момент. Вам задают Главный вопрос жизни, Вселенной и всего такого. Все замолкают. Даже космос делает вид, что слушает.", "answers": [ { @@ -329,7 +314,6 @@ }, { "id": "15", - "questId": 3, "text": "Вы обнаруживаете, что каким-то образом всё ещё существуете.", "answers": [ { @@ -352,7 +336,6 @@ }, { "id": "16", - "questId": 3, "text": "У вас появляется ощущение, что вы близки к истине. Это тревожит.", "answers": [ { @@ -375,7 +358,6 @@ }, { "id": "17", - "questId": 3, "text": "Перед вами андроид с крайне пессимистичным взглядом на бытие.", "answers": [ { @@ -398,7 +380,6 @@ }, { "id": "18", - "questId": 3, "text": "Вселенная смотрит на вас с плохо скрываемым интересом.", "answers": [ { @@ -421,7 +402,6 @@ }, { "id": "19", - "questId": 3, "text": "Вы чувствуете, что ответ уже близко, но всё ещё сомневаетесь.", "answers": [ { @@ -446,7 +426,6 @@ }, { "id": "20", - "questId": 3, "text": "После всего пережитого вы наконец понимаете главное.", "answers": [ { @@ -469,7 +448,6 @@ }, { "id": "810", - "questId": 3, "text": "Поздравляем! Вы прошли квест, не сломали Вселенную и, возможно, даже стали немного мудрее.", "answers": null } From d5f4c86f160ca76130906c24bf7063258dbf3409 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Thu, 22 Jan 2026 11:33:43 +0500 Subject: [PATCH 10/65] CHANGE field names in Question and Answer --- .../com/javarush/vasileva/cmd/PlayGame.java | 10 +- .../com/javarush/vasileva/entity/Answer.java | 2 +- .../javarush/vasileva/entity/Question.java | 2 +- .../repository/QuestionRepository.java | 6 +- .../vasileva/service/QuestionService.java | 4 +- src/main/resources/quest-1.json | 24 +-- src/main/resources/quest-2.json | 200 ++++++++--------- src/main/resources/quest-3.json | 202 +++++++++--------- src/main/webapp/WEB-INF/play-game.jsp | 2 +- 9 files changed, 226 insertions(+), 226 deletions(-) diff --git a/src/main/java/com/javarush/vasileva/cmd/PlayGame.java b/src/main/java/com/javarush/vasileva/cmd/PlayGame.java index a2bb546..3829333 100644 --- a/src/main/java/com/javarush/vasileva/cmd/PlayGame.java +++ b/src/main/java/com/javarush/vasileva/cmd/PlayGame.java @@ -35,7 +35,7 @@ public String doGet(HttpServletRequest req) { currentQuestionId = Long.parseLong(questionIdStr); } - System.out.println("current" + currentQuestionId); + System.out.println("current question" + currentQuestionId); Optional currentQuestion = questionService.get(currentQuestionId); if (currentQuestion.isPresent()) { @@ -67,13 +67,13 @@ public String doPost(HttpServletRequest req) { Answer answer = answerOpt.get(); - String nextQuestionIdStr = answer.getNextQuestionId(); - if (nextQuestionIdStr == null || nextQuestionIdStr.isEmpty()) { + String nextQuestionLabelStr = answer.getNextQuestionLabel(); + if (nextQuestionLabelStr == null || nextQuestionLabelStr.isEmpty()) { return getView() + "?id=" + questId + "&gameOver=true"; } - System.out.println("Ищем вопрос: id=" + nextQuestionIdStr + ", questId=" + questId); - Optional nextQuestionOpt = questionService.getByIdAndQuestId(nextQuestionIdStr, questId); + System.out.println("Ищем вопрос: id=" + nextQuestionLabelStr + ", questId=" + questId); + Optional nextQuestionOpt = questionService.getByQuestionLabelAndQuestId(nextQuestionLabelStr, questId); System.out.println("Найден вопрос: " + nextQuestionOpt.isPresent()); long nextQuestionId = nextQuestionOpt.get().getGeneratedId(); diff --git a/src/main/java/com/javarush/vasileva/entity/Answer.java b/src/main/java/com/javarush/vasileva/entity/Answer.java index 3f3152e..cda4e95 100644 --- a/src/main/java/com/javarush/vasileva/entity/Answer.java +++ b/src/main/java/com/javarush/vasileva/entity/Answer.java @@ -12,7 +12,7 @@ public class Answer { private Long id; private Long questionId; - private String nextQuestionId; + private String nextQuestionLabel; private String text; private String description; } diff --git a/src/main/java/com/javarush/vasileva/entity/Question.java b/src/main/java/com/javarush/vasileva/entity/Question.java index 8702352..93abc46 100644 --- a/src/main/java/com/javarush/vasileva/entity/Question.java +++ b/src/main/java/com/javarush/vasileva/entity/Question.java @@ -13,7 +13,7 @@ @Builder public class Question { private Long generatedId; - private String id; + private String label; private Long questId; private String text; private List answers; diff --git a/src/main/java/com/javarush/vasileva/repository/QuestionRepository.java b/src/main/java/com/javarush/vasileva/repository/QuestionRepository.java index e53242c..076b913 100644 --- a/src/main/java/com/javarush/vasileva/repository/QuestionRepository.java +++ b/src/main/java/com/javarush/vasileva/repository/QuestionRepository.java @@ -22,12 +22,12 @@ public List getAll() { @Override public Optional get(long id) { - return Optional.ofNullable(questions.get(id)); + return Optional.ofNullable(questions.get(id)); // generatedId } - public Optional getByIdAndQuestId(String id, long questId) { + public Optional getByQuestionLabelAndQuestId(String questionLabel, long questId) { return questions.values().stream() - .filter(question -> question.getId().equals(id)) + .filter(question -> question.getLabel().equals(questionLabel)) .filter(question -> question.getQuestId() == questId) .findFirst(); } diff --git a/src/main/java/com/javarush/vasileva/service/QuestionService.java b/src/main/java/com/javarush/vasileva/service/QuestionService.java index 5971d24..55ac8e0 100644 --- a/src/main/java/com/javarush/vasileva/service/QuestionService.java +++ b/src/main/java/com/javarush/vasileva/service/QuestionService.java @@ -22,8 +22,8 @@ public Optional get(Long id) { return questionRepository.get(id); } - public Optional getByIdAndQuestId(String id, long questId) { - return questionRepository.getByIdAndQuestId(id, questId); + public Optional getByQuestionLabelAndQuestId(String questionLabel, long questId) { + return questionRepository.getByQuestionLabelAndQuestId(questionLabel, questId); } public void create(Question question) { diff --git a/src/main/resources/quest-1.json b/src/main/resources/quest-1.json index 563c1c0..a0db71f 100644 --- a/src/main/resources/quest-1.json +++ b/src/main/resources/quest-1.json @@ -3,59 +3,59 @@ "description": "Про приключения в космосе", "questions": [ { - "id": "1", + "label": "1", "text": "Принять вызов НЛО?", "answers": [ { - "nextQuestionId": "2", + "nextQuestionLabel": "2", "text": "Принять вызов" }, { - "nextQuestionId": "910", + "nextQuestionLabel": "910", "text": "Отклонить вызов" } ] }, { - "id": "2", + "label": "2", "text": "Поднимешься на мостик к капитану?", "answers": [ { - "nextQuestionId": "3", + "nextQuestionLabel": "3", "text": "Подняться на мостик" }, { - "nextQuestionId": "910", + "nextQuestionLabel": "910", "text": "Отказаться подниматься на мостик" } ] }, { - "id": "3", + "label": "3", "text": "Ты поднялся на мостик. Ты кто?", "answers": [ { - "nextQuestionId": "810", + "nextQuestionLabel": "810", "text": "Рассказать правду о себе" }, { - "nextQuestionId": "911", + "nextQuestionLabel": "911", "text": "Солгать о себе" } ] }, { - "id": "810", + "label": "810", "text": "Тебя вернули домой, победа", "answers": null }, { - "id": "910", + "label": "910", "text": "Ты отклонил вызов, поражение", "answers": null }, { - "id": "911", + "label": "911", "text": "Твою ложь разоблачили, поражение", "answers": null } diff --git a/src/main/resources/quest-2.json b/src/main/resources/quest-2.json index 419e3b6..7a7e498 100644 --- a/src/main/resources/quest-2.json +++ b/src/main/resources/quest-2.json @@ -3,522 +3,522 @@ "description": "Много веков назад дракон Вельдан, хранитель древних знаний, скрылся в недрах горы с Сердцем Дракона — артефактом невообразимой силы, спрятав его в лабиринте, известном как Забытое Подземелье. Тысячи смельчаков отправлялись на поиски реликвии, но никто не вернулся; легенды гласят, что лишь тот, кто проявит мудрость, отвагу и хладнокровие, сможет завладеть Сердцем. Теперь вы — один из искателей: с факелом и мечом перед массивной дверью с драконьей пастью, за которой таятся тьма, сырость и нечто древнее. Дверь медленно приоткрывается — готовы ли вы бросить вызов подземелью?", "questions": [ { - "id": "1", + "label": "1", "text": "Вы входите в тёмный коридор. Впереди слышен шорох.", "answers": [ { - "nextQuestionId": "2", + "nextQuestionLabel": "2", "text": "Достанете факел и осторожно продвинетесь вперёд.", "description": "" }, { - "nextQuestionId": "2", + "nextQuestionLabel": "2", "text": "Бросите камень в сторону шума, чтобы проверить.", "description": "Вы пугаете крысу. Путь свободен." }, { - "nextQuestionId": "910", + "nextQuestionLabel": "910", "text": "Повернётесь и пойдёте назад.", "description": "Попадаете в тупик." }, { - "nextQuestionId": "910", + "nextQuestionLabel": "910", "text": "Закричите, чтобы отпугнуть возможного врага.", "description": "Шум привлекает монстров." } ] }, { - "id": "2", + "label": "2", "text": "Факел осветил три двери. На каждой — символ: огонь, вода, луна. Какую выберете?", "answers": [ { - "nextQuestionId": "3", + "nextQuestionLabel": "3", "text": "С символом огня (рискованно, но может вести к сокровищам).", "description": "В комнате лава. Нужно найти мост." }, { - "nextQuestionId": "8", + "nextQuestionLabel": "8", "text": "С символом воды (кажется безопасной).", "description": "Подземный ручей." }, { - "nextQuestionId": "910", + "nextQuestionLabel": "910", "text": "С символом луны (загадочно, возможно, ловушка).", "description": "Ловушка: пол проваливается." } ] }, { - "id": "3", + "label": "3", "text": "За дверью — комната с ямой посередине. На стене рычаг. Ваши действия?", "answers": [ { - "nextQuestionId": "910", + "nextQuestionLabel": "910", "text": "Дёрнете рычаг сразу.", "description": "Яма расширяется." }, { - "nextQuestionId": "4", + "nextQuestionLabel": "4", "text": "Поищете другой путь, минуя яму.", "description": "Находите скрытый проход." }, { - "nextQuestionId": "910", + "nextQuestionLabel": "910", "text": "Попытаетесь перепрыгнуть яму.", "description": "Падение." }, { - "nextQuestionId": "4", + "nextQuestionLabel": "4", "text": "Кинете камень на противоположную сторону, проверяя пол.", "description": "Пол безопасен. Переходите." } ] }, { - "id": "4", + "label": "4", "text": "Рычаг активировал механизм: из стен выдвинулись шипы. Как спастись?", "answers": [ { - "nextQuestionId": "5", + "nextQuestionLabel": "5", "text": "Прижмётесь к стене и медленно пройдёте.", "description": "Успешно проходите." }, { - "nextQuestionId": "5", + "nextQuestionLabel": "5", "text": "Побежите напролом, уклоняясь.", "description": "Ранение. Здоровье снижается." }, { - "nextQuestionId": "5", + "nextQuestionLabel": "5", "text": "Найдёте кнопку отключения механизмов.", "description": "Находите механизм." }, { - "nextQuestionId": "910", + "nextQuestionLabel": "910", "text": "Вернётесь назад.", "description": "Путь заблокирован. " } ] }, { - "id": "5", + "label": "5", "text": "В этой комнате — статуя дракона. На постаменте надпись: «Скажи имя древнего бога».", "answers": [ { - "nextQuestionId": "910", + "nextQuestionLabel": "910", "text": "Азраэль.", "description": "Статуя атакует." }, { - "nextQuestionId": "6", + "nextQuestionLabel": "6", "text": "Таргон.", "description": "Верно! Статуя пропускает." }, { - "nextQuestionId": "910", + "nextQuestionLabel": "910", "text": "Вельдан.", "description": "Ошибка. Ловушка." }, { - "nextQuestionId": "5", + "nextQuestionLabel": "5", "text": "Промолчите и осмотрите комнату ещё раз.", "description": "Находите надпись с именем: Таргон" } ] }, { - "id": "6", + "label": "6", "text": "Статуя оживает! Как поступить?", "answers": [ { - "nextQuestionId": "7", + "nextQuestionLabel": "7", "text": "Попробуете заговорить с ней.", "description": "Дракон даёт подсказку." }, { - "nextQuestionId": "910", + "nextQuestionLabel": "910", "text": "Атакуете первым.", "description": "Проигрываете бой." }, { - "nextQuestionId": "7", + "nextQuestionLabel": "7", "text": "Бросите в неё магический свиток.", "description": "Оглушаете дракона." }, { - "nextQuestionId": "7", + "nextQuestionLabel": "7", "text": "Спрячетесь за колонну.", "description": "Дракон уходит. " } ] }, { - "id": "7", + "label": "7", "text": "Дракон пропускает вас, но предупреждает: «Следующий — не человек». В коридоре два пути:", "answers": [ { - "nextQuestionId": "8", + "nextQuestionLabel": "8", "text": "Левый — пахнет сыростью (возможно, вода).", "description": "Вы вышли к ручью." }, { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Правый — слышны голоса (люди или монстры?).", "description": "Вы вступили в бой с бандитами и победили их." }, { - "nextQuestionId": "910", + "nextQuestionLabel": "910", "text": "Вернётесь к статуе за советом.", "description": "Статуя исчезла." } ] }, { - "id": "8", + "label": "8", "text": "В левом коридоре — подземный ручей. Как перебраться?", "answers": [ { - "nextQuestionId": "910", + "nextQuestionLabel": "910", "text": "Попытаетесь проплыть.", "description": "Вас уносит течением." }, { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Найдете упавшее бревно и используете его как мост.", "description": "Мост готов." }, { - "nextQuestionId": "8", + "nextQuestionLabel": "8", "text": "Используете верёвку, чтобы перемахнуть.", "description": "Не хватает длины." }, { - "nextQuestionId": "910", + "nextQuestionLabel": "910", "text": "Поищете обходной путь.", "description": "Вы заблудились и вас съел дракон." } ] }, { - "id": "9", + "label": "9", "text": "На другом берегу — дверь с замком. Как вы поступите?", "answers": [ { - "nextQuestionId": "10", + "nextQuestionLabel": "10", "text": "Взломаете замок отмычкой.", "description": "У вас получилось взломать замок." }, { - "nextQuestionId": "11", + "nextQuestionLabel": "11", "text": "Ударите по нему мечом.", "description": "Замок ломается, но шум привлекает врагов." }, { - "nextQuestionId": "10", + "nextQuestionLabel": "10", "text": "Поищете ключ поблизости.", "description": "Вы находите ключ в соседней комнате." }, { - "nextQuestionId": "910", + "nextQuestionLabel": "910", "text": "Попробуете выбить дверь плечом.", "description": "Дверь не поддаётся." } ] }, { - "id": "10", + "label": "10", "text": "За дверью — зал с четырьмя алтарями. На каждом — предмет: меч, книга, череп, кристалл. Какой возьмёте?", "answers": [ { - "nextQuestionId": "11", + "nextQuestionLabel": "11", "text": "Меч (для защиты).", "description": "Активирует ловушку." }, { - "nextQuestionId": "14", + "nextQuestionLabel": "14", "text": "Книгу (возможно, подсказка).", "description": "Подсказка к загадке. " }, { - "nextQuestionId": "12", + "nextQuestionLabel": "12", "text": "Череп (опасно, но магически).", "description": "Вызывает духа. Вам приходится вступить с ним в бой." }, { - "nextQuestionId": "13", + "nextQuestionLabel": "13", "text": "Кристалл (светится, может быть артефактом).", "description": "Светит в темноте." } ] }, { - "id": "11", + "label": "11", "text": "Статуя оживает! Как поступить?", "answers": [ { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Попробуете заговорить с ней.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Атакуете первым.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Бросите в неё магический свиток.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Спрячетесь за колонну.", "description": "" } ] }, { - "id": "12", + "label": "12", "text": "Статуя оживает! Как поступить?", "answers": [ { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Попробуете заговорить с ней.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Атакуете первым.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Бросите в неё магический свиток.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Спрячетесь за колонну.", "description": "" } ] }, { - "id": "13", + "label": "13", "text": "Статуя оживает! Как поступить?", "answers": [ { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Попробуете заговорить с ней.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Атакуете первым.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Бросите в неё магический свиток.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Спрячетесь за колонну.", "description": "" } ] }, { - "id": "14", + "label": "14", "text": "Статуя оживает! Как поступить?", "answers": [ { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Попробуете заговорить с ней.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Атакуете первым.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Бросите в неё магический свиток.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Спрячетесь за колонну.", "description": "" } ] }, { - "id": "15", + "label": "15", "text": "Статуя оживает! Как поступить?", "answers": [ { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Попробуете заговорить с ней.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Атакуете первым.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Бросите в неё магический свиток.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Спрячетесь за колонну.", "description": "" } ] }, { - "id": "16", + "label": "16", "text": "Статуя оживает! Как поступить?", "answers": [ { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Попробуете заговорить с ней.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Атакуете первым.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Бросите в неё магический свиток.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Спрячетесь за колонну.", "description": "" } ] }, { - "id": "17", + "label": "17", "text": "Статуя оживает! Как поступить?", "answers": [ { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Попробуете заговорить с ней.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Атакуете первым.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Бросите в неё магический свиток.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Спрячетесь за колонну.", "description": "" } ] }, { - "id": "18", + "label": "18", "text": "Статуя оживает! Как поступить?", "answers": [ { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Попробуете заговорить с ней.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Атакуете первым.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Бросите в неё магический свиток.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Спрячетесь за колонну.", "description": "" } ] }, { - "id": "19", + "label": "19", "text": "Статуя оживает! Как поступить?", "answers": [ { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Попробуете заговорить с ней.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Атакуете первым.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Бросите в неё магический свиток.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Спрячетесь за колонну.", "description": "" } ] }, { - "id": "20", + "label": "20", "text": "Статуя оживает! Как поступить?", "answers": [ { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Попробуете заговорить с ней.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Атакуете первым.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Бросите в неё магический свиток.", "description": "" }, { - "nextQuestionId": "", + "nextQuestionLabel": "", "text": "Спрячетесь за колонну.", "description": "" } ] }, { - "id": "810", + "label": "810", "text": "Тебя вернули домой, победа", "answers": null }, { - "id": "910", + "label": "910", "text": "Проигрыш", "answers": null } diff --git a/src/main/resources/quest-3.json b/src/main/resources/quest-3.json index fb19d9d..97d6445 100644 --- a/src/main/resources/quest-3.json +++ b/src/main/resources/quest-3.json @@ -3,451 +3,451 @@ "description": "Добро пожаловать в квест, который начинается с конца света и быстро переходит к вопросам посложнее. Землю сносят ради гиперпространственной магистрали, предупреждения были вывешены (где-то далеко и давно), а у вас есть лишь выбор, полотенце и крайне смутное представление о происходящем. Впереди — вогоны, сомнительный чай, философские размышления и шанс узнать ответ на Главный вопрос жизни, Вселенной и всего такого. Главное — не паникуйте: Вселенная всё равно делает вид, что всё под контролем.", "questions": [ { - "id": "1", + "label": "1", "text": "Вы просыпаетесь и узнаёте, что Землю демонтируют ради гиперпространственной магистрали. Что будете делать?", "answers": [ { - "nextQuestionId": "2", + "nextQuestionLabel": "2", "text": "Вы возмущённо требуете документы, разрешения и хотя бы подпись ответственного лица. Вселенная равнодушно зевает." }, { - "nextQuestionId": "3", + "nextQuestionLabel": "3", "text": "Вы вспоминаете главное правило галактического путешественника и лихорадочно ищете полотенце. Это внушает необъяснимое спокойствие." }, { - "nextQuestionId": "4", + "nextQuestionLabel": "4", "text": "Вы уточняете, будет ли обед до конца света, потому что на голодный желудок апокалипсис переносится хуже." }, { - "nextQuestionId": "5", + "nextQuestionLabel": "5", "text": "Вы решаете, что это сон, и пробуете снова уснуть, пока Вселенная не передумала." } ] }, { - "id": "2", + "label": "2", "text": "Перед вами стоит вогон, держащий папку подозрительно толстых стихов.", "answers": [ { - "nextQuestionId": "6", + "nextQuestionLabel": "6", "text": "Вы пытаетесь убежать, но быстро понимаете, что в условиях вакуума это не лучшая стратегия." }, { - "nextQuestionId": "7", + "nextQuestionLabel": "7", "text": "Вы представляете себя галактическим юристом и начинаете говорить словами, смысл которых неизвестен даже вам." }, { - "nextQuestionId": "8", + "nextQuestionLabel": "8", "text": "Вы вежливо просите почитать стихи вслух, подозревая, что хуже уже не будет." }, { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Вы начинаете плакать заранее, экономя время на эмоциональной реакции." } ] }, { - "id": "3", + "label": "3", "text": "Полотенце найдено. Оно слегка влажное, но внушает доверие.", "answers": [ { - "nextQuestionId": "6", + "nextQuestionLabel": "6", "text": "Вы используете его как универсальное средство защиты от всего непонятного." }, { - "nextQuestionId": "10", + "nextQuestionLabel": "10", "text": "Вы накидываете его как плащ и чувствуете себя героем космооперы." }, { - "nextQuestionId": "5", + "nextQuestionLabel": "5", "text": "Вы обнимаете полотенце, потому что оно единственное, что сейчас вас понимает." }, { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Вы тут же его теряете, подтверждая законы Вселенной." } ] }, { - "id": "4", + "label": "4", "text": "Мысли о еде не покидают вас даже в момент уничтожения планеты.", "answers": [ { - "nextQuestionId": "11", + "nextQuestionLabel": "11", "text": "Вы решаете сделать бутерброд, игнорируя катастрофу как нечто второстепенное." }, { - "nextQuestionId": "12", + "nextQuestionLabel": "12", "text": "Вы жалуетесь Вселенной на несвоевременность происходящего." }, { - "nextQuestionId": "5", + "nextQuestionLabel": "5", "text": "Вы смиряетесь с судьбой и принимаете происходящее как должное." }, { - "nextQuestionId": "13", + "nextQuestionLabel": "13", "text": "Вы спрашиваете, где чай, потому что без него цивилизация не имеет смысла." } ] }, { - "id": "5", + "label": "5", "text": "Вы понимаете: это не сон, а реальность, причём весьма навязчивая.", "answers": [ { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Вы начинаете паниковать, громко и без системы." }, { - "nextQuestionId": "10", + "nextQuestionLabel": "10", "text": "Вы вспоминаете надпись «DON’T PANIC» и стараетесь выглядеть уверенно." }, { - "nextQuestionId": "12", + "nextQuestionLabel": "12", "text": "Вы философски принимаете происходящее, как будто читали об этом раньше.", "description": "" }, { - "nextQuestionId": "14", + "nextQuestionLabel": "14", "text": "Вы выкрикиваете «42!» без всякой причины, но с чувством." } ] }, { - "id": "6", + "label": "6", "text": "Вас без особых церемоний выбрасывают в открытый космос. Он холодный, бесконечный и явно не собирается извиняться.", "answers": [ { - "nextQuestionId": "15", + "nextQuestionLabel": "15", "text": "Вы задерживаете дыхание, словно космос обязан это заметить и проявить такт." }, { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Вы начинаете кричать, несмотря на смутное подозрение, что звук здесь не работает." }, { - "nextQuestionId": "16", + "nextQuestionLabel": "16", "text": "Вы решаете положиться на сюжетную броню главного героя, даже если не уверены, что вы главный." }, { - "nextQuestionId": "12", + "nextQuestionLabel": "12", "text": "Вы вежливо извиняетесь перед космосом за возможные неудобства. Космос впечатлён." } ] }, { - "id": "7", + "label": "7", "text": "Вы представились галактическим юристом, и теперь все ждут продолжения.", "answers": [ { - "nextQuestionId": "8", + "nextQuestionLabel": "8", "text": "Вы требуете апелляцию, не уточняя, к чему именно. Звучит убедительно." }, { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Вы начинаете путаться в терминах и случайно признаётесь во всех преступлениях сразу." }, { - "nextQuestionId": "10", + "nextQuestionLabel": "10", "text": "Против всех законов логики вы выигрываете дело. Вогон выглядит озадаченным." }, { - "nextQuestionId": "8", + "nextQuestionLabel": "8", "text": "В качестве «компромисса» вам предлагают послушать стихи." } ] }, { - "id": "8", + "label": "8", "text": "Поэзия начинается. Это заметно сразу.", "answers": [ { - "nextQuestionId": "15", + "nextQuestionLabel": "15", "text": "Вы теряете сознание, руководствуясь инстинктом самосохранения." }, { - "nextQuestionId": "6", + "nextQuestionLabel": "6", "text": "Вы хвалите рифму, чем пугаете всех присутствующих, включая автора." }, { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Вы записываете цитаты, чтобы пугать ими знакомых.", "description": "Не хватает длины." }, { - "nextQuestionId": "15", + "nextQuestionLabel": "15", "text": "Вы просите ещё. Реальность слегка трескается." } ] }, { - "id": "9", + "label": "9", "text": "Ситуация становится заметно хуже, чем была мгновение назад.", "answers": [ { - "nextQuestionId": "5", + "nextQuestionLabel": "5", "text": "Вы решаете сдаться и начать всё сначала." }, { - "nextQuestionId": "12", + "nextQuestionLabel": "12", "text": "Вы делаете вид, что так и было задумано." }, { - "nextQuestionId": "14", + "nextQuestionLabel": "14", "text": "Вы задаёте главный философский вопрос: «В чём вообще смысл?»" }, { - "nextQuestionId": "3", + "nextQuestionLabel": "3", "text": "Вы снова начинаете искать полотенце, потому что оно вас ещё ни разу не подводило." } ] }, { - "id": "10", + "label": "10", "text": "Вас подбирает корабль, который выглядит надёжным ровно настолько, насколько это возможно в галактике.", "answers": [ { - "nextQuestionId": "16", + "nextQuestionLabel": "16", "text": "Вы радуетесь спасению и решаете не задавать лишних вопросов." }, { - "nextQuestionId": "17", + "nextQuestionLabel": "17", "text": "Вы внимательно разглядываете экипаж, подозревая худшее." }, { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Вы прячетесь за ближайшим ящиком. На всякий случай." }, { - "nextQuestionId": "11", + "nextQuestionLabel": "11", "text": "Вы спрашиваете, куда летит корабль, и сразу жалеете об этом." } ] }, { - "id": "11", + "label": "11", "text": "На борту обсуждают еду, и это внезапно кажется важным.", "answers": [ { - "nextQuestionId": "13", + "nextQuestionLabel": "13", "text": "Вы заказываете чай, надеясь, что в этот раз всё будет иначе." }, { - "nextQuestionId": "14", + "nextQuestionLabel": "14", "text": "Вы снова поднимаете тему смысла жизни. Не вовремя, но искренне." }, { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Вы пробуете что-то странное, светящееся и, возможно, разумное." }, { - "nextQuestionId": "12", + "nextQuestionLabel": "12", "text": "Вы решаете ничего не есть и просто подумать." } ] }, { - "id": "12", + "label": "12", "text": "Вы внезапно ловите себя на том, что задумались. Это опасно, но уже поздно.", "answers": [ { - "nextQuestionId": "14", + "nextQuestionLabel": "14", "text": "Вы размышляете о жизни: зачем она дана, почему всё так странно и кто вообще всё это придумал." }, { - "nextQuestionId": "14", + "nextQuestionLabel": "14", "text": "Вы думаете о Вселенной — бесконечной, равнодушной и удивительно хорошо организованной для хаоса." }, { - "nextQuestionId": "14", + "nextQuestionLabel": "14", "text": "Вы пытаетесь осмыслить всё сразу: жизнь, Вселенную и остальное, но мысль ускользает." }, { - "nextQuestionId": "5", + "nextQuestionLabel": "5", "text": "Вы решаете, что думать — занятие переоценённое, и возвращаетесь к реальности." } ] }, { - "id": "13", + "label": "13", "text": "Вам приносят чай. Он снова не такой, как надо.", "answers": [ { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Вы возмущаетесь, потому что чай — это вопрос принципа, а не вкуса." }, { - "nextQuestionId": "17", + "nextQuestionLabel": "17", "text": "Вы пытаетесь улучшить напиток научным методом, добавляя ингредиенты сомнительного происхождения." }, { - "nextQuestionId": "12", + "nextQuestionLabel": "12", "text": "Вы философски принимаете чай как символ несовершенства Вселенной." }, { - "nextQuestionId": "3", + "nextQuestionLabel": "3", "text": "Вы отвлекаетесь и спрашиваете, где ваше полотенце." } ] }, { - "id": "14", + "label": "14", "text": "Наступает торжественный момент. Вам задают Главный вопрос жизни, Вселенной и всего такого. Все замолкают. Даже космос делает вид, что слушает.", "answers": [ { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Вы отвечаете: «Любовь». Это звучит красиво, но Вселенная выглядит разочарованной." }, { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Вы честно говорите: «Деньги». Вселенная вздыхает и делает пометку." }, { - "nextQuestionId": "20", + "nextQuestionLabel": "20", "text": "Вы уверенно и без лишних слов произносите: 42. Вселенная одобрительно молчит. Это хороший знак." }, { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Вы заявляете, что вопрос сформулирован некорректно. Вселенная кивает, но продолжает эксперимент." } ] }, { - "id": "15", + "label": "15", "text": "Вы обнаруживаете, что каким-то образом всё ещё существуете.", "answers": [ { - "nextQuestionId": "16", + "nextQuestionLabel": "16", "text": "Вы благодарите Вселенную за то, что она сегодня в хорошем настроении." }, { - "nextQuestionId": "12", + "nextQuestionLabel": "12", "text": "Вы долго и искренне удивляетесь происходящему." }, { - "nextQuestionId": "5", + "nextQuestionLabel": "5", "text": "Вы проверяете, действительно ли вы живы, на всякий случай." }, { - "nextQuestionId": "17", + "nextQuestionLabel": "17", "text": "Вы решаете, что это странно, но, вероятно, нормально." } ] }, { - "id": "16", + "label": "16", "text": "У вас появляется ощущение, что вы близки к истине. Это тревожит.", "answers": [ { - "nextQuestionId": "20", + "nextQuestionLabel": "20", "text": "Вы решаете продолжить путешествие, не вдаваясь в детали." }, { - "nextQuestionId": "14", + "nextQuestionLabel": "14", "text": "Вы задаёте ещё один вопрос, потому что не умеете останавливаться." }, { - "nextQuestionId": "12", + "nextQuestionLabel": "12", "text": "Вы расслабляетесь и позволяете событиям происходить." }, { - "nextQuestionId": "3", + "nextQuestionLabel": "3", "text": "Вы автоматически проверяете, при вас ли полотенце." } ] }, { - "id": "17", + "label": "17", "text": "Перед вами андроид с крайне пессимистичным взглядом на бытие.", "answers": [ { - "nextQuestionId": "12", + "nextQuestionLabel": "12", "text": "Вы искренне сочувствуете ему. Андроид растерян: такого он не ожидал." }, { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Вы позволяете ему высказаться. Через некоторое время жалеете об этом." }, { - "nextQuestionId": "14", + "nextQuestionLabel": "14", "text": "Вы спрашиваете его о смысле жизни. Он подтверждает, что всё плохо." }, { - "nextQuestionId": "16", + "nextQuestionLabel": "16", "text": "Вы медленно отходите, стараясь не привлекать внимания." } ] }, { - "id": "18", + "label": "18", "text": "Вселенная смотрит на вас с плохо скрываемым интересом.", "answers": [ { - "nextQuestionId": "12", + "nextQuestionLabel": "12", "text": "Вы почтительно кланяетесь, считая это уместным." }, { - "nextQuestionId": "16", + "nextQuestionLabel": "16", "text": "Вы улыбаетесь, демонстрируя уверенность, которой у вас нет." }, { - "nextQuestionId": "20", + "nextQuestionLabel": "20", "text": "Вы прямо спрашиваете: «Ну и что дальше?»" }, { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Вы решаете убежать, пока всё снова не усложнилось." } ] }, { - "id": "19", + "label": "19", "text": "Вы чувствуете, что ответ уже близко, но всё ещё сомневаетесь.", "answers": [ { - "nextQuestionId": "20", + "nextQuestionLabel": "20", "text": "Вы делаете вывод и принимаете его без проверки.", "description": "" }, { - "nextQuestionId": "9", + "nextQuestionLabel": "9", "text": "Вы решаете всё усложнить, потому что слишком просто не бывает.", "description": "" }, { - "nextQuestionId": "14", + "nextQuestionLabel": "14", "text": "Вы спрашиваете ещё раз, на всякий случай." }, { - "nextQuestionId": "16", + "nextQuestionLabel": "16", "text": "Вы напоминаете себе главное правило — не паниковать." } ] }, { - "id": "20", + "label": "20", "text": "После всего пережитого вы наконец понимаете главное.", "answers": [ { - "nextQuestionId": "810", + "nextQuestionLabel": "810", "text": "Всегда носи полотенце" }, { - "nextQuestionId": "810", + "nextQuestionLabel": "810", "text": "Не паникуй" }, { - "nextQuestionId": "810", + "nextQuestionLabel": "810", "text": "Ответ — 42" }, { - "nextQuestionId": "810", + "nextQuestionLabel": "810", "text": "Всё вышеперечисленное" } ] }, { - "id": "810", + "label": "810", "text": "Поздравляем! Вы прошли квест, не сломали Вселенную и, возможно, даже стали немного мудрее.", "answers": null } diff --git a/src/main/webapp/WEB-INF/play-game.jsp b/src/main/webapp/WEB-INF/play-game.jsp index 572761d..55ac0f3 100644 --- a/src/main/webapp/WEB-INF/play-game.jsp +++ b/src/main/webapp/WEB-INF/play-game.jsp @@ -21,7 +21,7 @@
- Вопрос № ${requestScope.question.id} + Вопрос № ${requestScope.question.label}
From 91a0a30cea8c2c8c9f2cd9373934e3b757883afa Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Fri, 23 Jan 2026 14:48:24 +0500 Subject: [PATCH 13/65] ADD html/css for home page --- .../com/javarush/vasileva/entity/Quest.java | 1 + src/main/webapp/WEB-INF/header.jsp | 23 ++++++++ src/main/webapp/WEB-INF/home.jsp | 50 ++++++++++++---- src/main/webapp/WEB-INF/play-game.jsp | 6 +- .../static/bootstrap/css/bootstrap.min.css | 5 ++ .../css/Bold-BS4-Full-Page-Image-Header.css | 9 +++ .../webapp/static/css/Hero-Features-icons.css | 57 +++++++++++++++++++ 7 files changed, 140 insertions(+), 11 deletions(-) create mode 100644 src/main/webapp/WEB-INF/header.jsp create mode 100644 src/main/webapp/static/bootstrap/css/bootstrap.min.css create mode 100644 src/main/webapp/static/css/Bold-BS4-Full-Page-Image-Header.css create mode 100644 src/main/webapp/static/css/Hero-Features-icons.css diff --git a/src/main/java/com/javarush/vasileva/entity/Quest.java b/src/main/java/com/javarush/vasileva/entity/Quest.java index e8e581a..bcf6eba 100644 --- a/src/main/java/com/javarush/vasileva/entity/Quest.java +++ b/src/main/java/com/javarush/vasileva/entity/Quest.java @@ -15,6 +15,7 @@ public class Quest { private Long id; private String title; private String description; + private String text; private Long startQuestionId; private List questions; } diff --git a/src/main/webapp/WEB-INF/header.jsp b/src/main/webapp/WEB-INF/header.jsp new file mode 100644 index 0000000..f245bee --- /dev/null +++ b/src/main/webapp/WEB-INF/header.jsp @@ -0,0 +1,23 @@ +<%@ page contentType="text/html;charset=UTF-8" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + + + + Title + + +
+ +
+ + diff --git a/src/main/webapp/WEB-INF/home.jsp b/src/main/webapp/WEB-INF/home.jsp index c4c72e6..108a039 100644 --- a/src/main/webapp/WEB-INF/home.jsp +++ b/src/main/webapp/WEB-INF/home.jsp @@ -1,21 +1,51 @@ <%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@include file="header.jsp" %> - +<%----%> + + + Home -<%-- -<%-- integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">--%> + <%-- + <%-- integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">--%> -

Quests

- - -
- ${quest.title}
+
+
+
+
+
+
+

Квесты

+
+
+ +
+
+
+

${quest.title}

+

${quest.description}

+
+ +
+
+
+
+
+
+
+
- - +
diff --git a/src/main/webapp/WEB-INF/play-game.jsp b/src/main/webapp/WEB-INF/play-game.jsp index 1a9470b..153ffec 100644 --- a/src/main/webapp/WEB-INF/play-game.jsp +++ b/src/main/webapp/WEB-INF/play-game.jsp @@ -1,7 +1,11 @@ <%@ page contentType="text/html;charset=UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@include file="header.jsp" %> - +<%----%> + + + Play Game diff --git a/src/main/webapp/static/bootstrap/css/bootstrap.min.css b/src/main/webapp/static/bootstrap/css/bootstrap.min.css new file mode 100644 index 0000000..da4b76b --- /dev/null +++ b/src/main/webapp/static/bootstrap/css/bootstrap.min.css @@ -0,0 +1,5 @@ +@charset "UTF-8";/*! + * Bootstrap v5.3.6 (https://getbootstrap.com/) + * Copyright 2011-2025 The Bootstrap Authors + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */:root,[data-bs-theme=light]{--bs-blue:#0d6efd;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#d63384;--bs-red:#dc3545;--bs-orange:#fd7e14;--bs-yellow:#ffc107;--bs-green:#198754;--bs-teal:#20c997;--bs-cyan:#0dcaf0;--bs-black:#000;--bs-white:#fff;--bs-gray:#6c757d;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#6c757d;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#0d6efd;--bs-secondary:#6c757d;--bs-success:#198754;--bs-info:#0dcaf0;--bs-warning:#ffc107;--bs-danger:#dc3545;--bs-light:#f8f9fa;--bs-dark:#212529;--bs-primary-rgb:13,110,253;--bs-secondary-rgb:108,117,125;--bs-success-rgb:25,135,84;--bs-info-rgb:13,202,240;--bs-warning-rgb:255,193,7;--bs-danger-rgb:220,53,69;--bs-light-rgb:248,249,250;--bs-dark-rgb:33,37,41;--bs-primary-text-emphasis:#052c65;--bs-secondary-text-emphasis:#2b2f32;--bs-success-text-emphasis:#0a3622;--bs-info-text-emphasis:#055160;--bs-warning-text-emphasis:#664d03;--bs-danger-text-emphasis:#58151c;--bs-light-text-emphasis:#495057;--bs-dark-text-emphasis:#495057;--bs-primary-bg-subtle:#cfe2ff;--bs-secondary-bg-subtle:#e2e3e5;--bs-success-bg-subtle:#d1e7dd;--bs-info-bg-subtle:#cff4fc;--bs-warning-bg-subtle:#fff3cd;--bs-danger-bg-subtle:#f8d7da;--bs-light-bg-subtle:#fcfcfd;--bs-dark-bg-subtle:#ced4da;--bs-primary-border-subtle:#9ec5fe;--bs-secondary-border-subtle:#c4c8cb;--bs-success-border-subtle:#a3cfbb;--bs-info-border-subtle:#9eeaf9;--bs-warning-border-subtle:#ffe69c;--bs-danger-border-subtle:#f1aeb5;--bs-light-border-subtle:#e9ecef;--bs-dark-border-subtle:#adb5bd;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#212529;--bs-body-color-rgb:33,37,41;--bs-body-bg:#fff;--bs-body-bg-rgb:255,255,255;--bs-emphasis-color:#000;--bs-emphasis-color-rgb:0,0,0;--bs-secondary-color:rgba(33, 37, 41, 0.75);--bs-secondary-color-rgb:33,37,41;--bs-secondary-bg:#e9ecef;--bs-secondary-bg-rgb:233,236,239;--bs-tertiary-color:rgba(33, 37, 41, 0.5);--bs-tertiary-color-rgb:33,37,41;--bs-tertiary-bg:#f8f9fa;--bs-tertiary-bg-rgb:248,249,250;--bs-heading-color:inherit;--bs-link-color:#0d6efd;--bs-link-color-rgb:13,110,253;--bs-link-decoration:underline;--bs-link-hover-color:#0a58ca;--bs-link-hover-color-rgb:10,88,202;--bs-code-color:#d63384;--bs-highlight-color:#212529;--bs-highlight-bg:#fff3cd;--bs-border-width:1px;--bs-border-style:solid;--bs-border-color:#dee2e6;--bs-border-color-translucent:rgba(0, 0, 0, 0.175);--bs-border-radius:0.375rem;--bs-border-radius-sm:0.25rem;--bs-border-radius-lg:0.5rem;--bs-border-radius-xl:1rem;--bs-border-radius-xxl:2rem;--bs-border-radius-2xl:var(--bs-border-radius-xxl);--bs-border-radius-pill:50rem;--bs-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-box-shadow-sm:0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-box-shadow-lg:0 1rem 3rem rgba(0, 0, 0, 0.175);--bs-box-shadow-inset:inset 0 1px 2px rgba(0, 0, 0, 0.075);--bs-focus-ring-width:0.25rem;--bs-focus-ring-opacity:0.25;--bs-focus-ring-color:rgba(13, 110, 253, 0.25);--bs-form-valid-color:#198754;--bs-form-valid-border-color:#198754;--bs-form-invalid-color:#dc3545;--bs-form-invalid-border-color:#dc3545}[data-bs-theme=dark]{color-scheme:dark;--bs-body-color:#dee2e6;--bs-body-color-rgb:222,226,230;--bs-body-bg:#212529;--bs-body-bg-rgb:33,37,41;--bs-emphasis-color:#fff;--bs-emphasis-color-rgb:255,255,255;--bs-secondary-color:rgba(222, 226, 230, 0.75);--bs-secondary-color-rgb:222,226,230;--bs-secondary-bg:#343a40;--bs-secondary-bg-rgb:52,58,64;--bs-tertiary-color:rgba(222, 226, 230, 0.5);--bs-tertiary-color-rgb:222,226,230;--bs-tertiary-bg:#2b3035;--bs-tertiary-bg-rgb:43,48,53;--bs-primary-text-emphasis:#6ea8fe;--bs-secondary-text-emphasis:#a7acb1;--bs-success-text-emphasis:#75b798;--bs-info-text-emphasis:#6edff6;--bs-warning-text-emphasis:#ffda6a;--bs-danger-text-emphasis:#ea868f;--bs-light-text-emphasis:#f8f9fa;--bs-dark-text-emphasis:#dee2e6;--bs-primary-bg-subtle:#031633;--bs-secondary-bg-subtle:#161719;--bs-success-bg-subtle:#051b11;--bs-info-bg-subtle:#032830;--bs-warning-bg-subtle:#332701;--bs-danger-bg-subtle:#2c0b0e;--bs-light-bg-subtle:#343a40;--bs-dark-bg-subtle:#1a1d20;--bs-primary-border-subtle:#084298;--bs-secondary-border-subtle:#41464b;--bs-success-border-subtle:#0f5132;--bs-info-border-subtle:#087990;--bs-warning-border-subtle:#997404;--bs-danger-border-subtle:#842029;--bs-light-border-subtle:#495057;--bs-dark-border-subtle:#343a40;--bs-heading-color:inherit;--bs-link-color:#6ea8fe;--bs-link-hover-color:#8bb9fe;--bs-link-color-rgb:110,168,254;--bs-link-hover-color-rgb:139,185,254;--bs-code-color:#e685b5;--bs-highlight-color:#dee2e6;--bs-highlight-bg:#664d03;--bs-border-color:#495057;--bs-border-color-translucent:rgba(255, 255, 255, 0.15);--bs-form-valid-color:#75b798;--bs-form-valid-border-color:#75b798;--bs-form-invalid-color:#ea868f;--bs-form-invalid-border-color:#ea868f}*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;border:0;border-top:var(--bs-border-width) solid;opacity:.25}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2;color:var(--bs-heading-color)}.h1,h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.h1,h1{font-size:2.5rem}}.h2,h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){.h2,h2{font-size:2rem}}.h3,h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){.h3,h3{font-size:1.75rem}}.h4,h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){.h4,h4{font-size:1.5rem}}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}.small,small{font-size:.875em}.mark,mark{padding:.1875em;color:var(--bs-highlight-color);background-color:var(--bs-highlight-bg)}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,1));text-decoration:underline}a:hover{--bs-link-color-rgb:var(--bs-link-hover-color-rgb)}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:var(--bs-font-monospace);font-size:1em}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:var(--bs-code-color);word-wrap:break-word}a>code{color:inherit}kbd{padding:.1875rem .375rem;font-size:.875em;color:var(--bs-body-bg);background-color:var(--bs-body-color);border-radius:.25rem}kbd kbd{padding:0;font-size:1em}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-secondary-color);text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator{display:none!important}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;line-height:inherit;font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}::file-selector-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}.lead{font-size:1.25rem;font-weight:300}.display-1{font-weight:300;line-height:1.2;font-size:calc(1.625rem + 4.5vw)}@media (min-width:1200px){.display-1{font-size:5rem}}.display-2{font-weight:300;line-height:1.2;font-size:calc(1.575rem + 3.9vw)}@media (min-width:1200px){.display-2{font-size:4.5rem}}.display-3{font-weight:300;line-height:1.2;font-size:calc(1.525rem + 3.3vw)}@media (min-width:1200px){.display-3{font-size:4rem}}.display-4{font-weight:300;line-height:1.2;font-size:calc(1.475rem + 2.7vw)}@media (min-width:1200px){.display-4{font-size:3.5rem}}.display-5{font-weight:300;line-height:1.2;font-size:calc(1.425rem + 2.1vw)}@media (min-width:1200px){.display-5{font-size:3rem}}.display-6{font-weight:300;line-height:1.2;font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){.display-6{font-size:2.5rem}}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:.875em;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote>:last-child{margin-bottom:0}.blockquote-footer{margin-top:-1rem;margin-bottom:1rem;font-size:.875em;color:#6c757d}.blockquote-footer::before{content:"— "}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:var(--bs-body-bg);border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:.875em;color:var(--bs-secondary-color)}.container,.container-fluid,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{--bs-gutter-x:1.5rem;--bs-gutter-y:0;width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}@media (min-width:1400px){.container,.container-lg,.container-md,.container-sm,.container-xl,.container-xxl{max-width:1320px}}:root{--bs-breakpoint-xs:0;--bs-breakpoint-sm:576px;--bs-breakpoint-md:768px;--bs-breakpoint-lg:992px;--bs-breakpoint-xl:1200px;--bs-breakpoint-xxl:1400px}.row{--bs-gutter-x:1.5rem;--bs-gutter-y:0;display:flex;flex-wrap:wrap;margin-top:calc(-1 * var(--bs-gutter-y));margin-right:calc(-.5 * var(--bs-gutter-x));margin-left:calc(-.5 * var(--bs-gutter-x))}.row>*{flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--bs-gutter-x) * .5);padding-left:calc(var(--bs-gutter-x) * .5);margin-top:var(--bs-gutter-y)}.col{flex:1 0 0}.row-cols-auto>*{flex:0 0 auto;width:auto}.row-cols-1>*{flex:0 0 auto;width:100%}.row-cols-2>*{flex:0 0 auto;width:50%}.row-cols-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-4>*{flex:0 0 auto;width:25%}.row-cols-5>*{flex:0 0 auto;width:20%}.row-cols-6>*{flex:0 0 auto;width:16.66666667%}.col-auto{flex:0 0 auto;width:auto}.col-1{flex:0 0 auto;width:8.33333333%}.col-2{flex:0 0 auto;width:16.66666667%}.col-3{flex:0 0 auto;width:25%}.col-4{flex:0 0 auto;width:33.33333333%}.col-5{flex:0 0 auto;width:41.66666667%}.col-6{flex:0 0 auto;width:50%}.col-7{flex:0 0 auto;width:58.33333333%}.col-8{flex:0 0 auto;width:66.66666667%}.col-9{flex:0 0 auto;width:75%}.col-10{flex:0 0 auto;width:83.33333333%}.col-11{flex:0 0 auto;width:91.66666667%}.col-12{flex:0 0 auto;width:100%}.offset-1{margin-left:8.33333333%}.offset-2{margin-left:16.66666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.33333333%}.offset-5{margin-left:41.66666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.33333333%}.offset-8{margin-left:66.66666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.33333333%}.offset-11{margin-left:91.66666667%}.g-0,.gx-0{--bs-gutter-x:0}.g-0,.gy-0{--bs-gutter-y:0}.g-1,.gx-1{--bs-gutter-x:0.25rem}.g-1,.gy-1{--bs-gutter-y:0.25rem}.g-2,.gx-2{--bs-gutter-x:0.5rem}.g-2,.gy-2{--bs-gutter-y:0.5rem}.g-3,.gx-3{--bs-gutter-x:1rem}.g-3,.gy-3{--bs-gutter-y:1rem}.g-4,.gx-4{--bs-gutter-x:1.5rem}.g-4,.gy-4{--bs-gutter-y:1.5rem}.g-5,.gx-5{--bs-gutter-x:3rem}.g-5,.gy-5{--bs-gutter-y:3rem}@media (min-width:576px){.col-sm{flex:1 0 0}.row-cols-sm-auto>*{flex:0 0 auto;width:auto}.row-cols-sm-1>*{flex:0 0 auto;width:100%}.row-cols-sm-2>*{flex:0 0 auto;width:50%}.row-cols-sm-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-sm-4>*{flex:0 0 auto;width:25%}.row-cols-sm-5>*{flex:0 0 auto;width:20%}.row-cols-sm-6>*{flex:0 0 auto;width:16.66666667%}.col-sm-auto{flex:0 0 auto;width:auto}.col-sm-1{flex:0 0 auto;width:8.33333333%}.col-sm-2{flex:0 0 auto;width:16.66666667%}.col-sm-3{flex:0 0 auto;width:25%}.col-sm-4{flex:0 0 auto;width:33.33333333%}.col-sm-5{flex:0 0 auto;width:41.66666667%}.col-sm-6{flex:0 0 auto;width:50%}.col-sm-7{flex:0 0 auto;width:58.33333333%}.col-sm-8{flex:0 0 auto;width:66.66666667%}.col-sm-9{flex:0 0 auto;width:75%}.col-sm-10{flex:0 0 auto;width:83.33333333%}.col-sm-11{flex:0 0 auto;width:91.66666667%}.col-sm-12{flex:0 0 auto;width:100%}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.33333333%}.offset-sm-2{margin-left:16.66666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.33333333%}.offset-sm-5{margin-left:41.66666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.33333333%}.offset-sm-8{margin-left:66.66666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.33333333%}.offset-sm-11{margin-left:91.66666667%}.g-sm-0,.gx-sm-0{--bs-gutter-x:0}.g-sm-0,.gy-sm-0{--bs-gutter-y:0}.g-sm-1,.gx-sm-1{--bs-gutter-x:0.25rem}.g-sm-1,.gy-sm-1{--bs-gutter-y:0.25rem}.g-sm-2,.gx-sm-2{--bs-gutter-x:0.5rem}.g-sm-2,.gy-sm-2{--bs-gutter-y:0.5rem}.g-sm-3,.gx-sm-3{--bs-gutter-x:1rem}.g-sm-3,.gy-sm-3{--bs-gutter-y:1rem}.g-sm-4,.gx-sm-4{--bs-gutter-x:1.5rem}.g-sm-4,.gy-sm-4{--bs-gutter-y:1.5rem}.g-sm-5,.gx-sm-5{--bs-gutter-x:3rem}.g-sm-5,.gy-sm-5{--bs-gutter-y:3rem}}@media (min-width:768px){.col-md{flex:1 0 0}.row-cols-md-auto>*{flex:0 0 auto;width:auto}.row-cols-md-1>*{flex:0 0 auto;width:100%}.row-cols-md-2>*{flex:0 0 auto;width:50%}.row-cols-md-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-md-4>*{flex:0 0 auto;width:25%}.row-cols-md-5>*{flex:0 0 auto;width:20%}.row-cols-md-6>*{flex:0 0 auto;width:16.66666667%}.col-md-auto{flex:0 0 auto;width:auto}.col-md-1{flex:0 0 auto;width:8.33333333%}.col-md-2{flex:0 0 auto;width:16.66666667%}.col-md-3{flex:0 0 auto;width:25%}.col-md-4{flex:0 0 auto;width:33.33333333%}.col-md-5{flex:0 0 auto;width:41.66666667%}.col-md-6{flex:0 0 auto;width:50%}.col-md-7{flex:0 0 auto;width:58.33333333%}.col-md-8{flex:0 0 auto;width:66.66666667%}.col-md-9{flex:0 0 auto;width:75%}.col-md-10{flex:0 0 auto;width:83.33333333%}.col-md-11{flex:0 0 auto;width:91.66666667%}.col-md-12{flex:0 0 auto;width:100%}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.33333333%}.offset-md-2{margin-left:16.66666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.33333333%}.offset-md-5{margin-left:41.66666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.33333333%}.offset-md-8{margin-left:66.66666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.33333333%}.offset-md-11{margin-left:91.66666667%}.g-md-0,.gx-md-0{--bs-gutter-x:0}.g-md-0,.gy-md-0{--bs-gutter-y:0}.g-md-1,.gx-md-1{--bs-gutter-x:0.25rem}.g-md-1,.gy-md-1{--bs-gutter-y:0.25rem}.g-md-2,.gx-md-2{--bs-gutter-x:0.5rem}.g-md-2,.gy-md-2{--bs-gutter-y:0.5rem}.g-md-3,.gx-md-3{--bs-gutter-x:1rem}.g-md-3,.gy-md-3{--bs-gutter-y:1rem}.g-md-4,.gx-md-4{--bs-gutter-x:1.5rem}.g-md-4,.gy-md-4{--bs-gutter-y:1.5rem}.g-md-5,.gx-md-5{--bs-gutter-x:3rem}.g-md-5,.gy-md-5{--bs-gutter-y:3rem}}@media (min-width:992px){.col-lg{flex:1 0 0}.row-cols-lg-auto>*{flex:0 0 auto;width:auto}.row-cols-lg-1>*{flex:0 0 auto;width:100%}.row-cols-lg-2>*{flex:0 0 auto;width:50%}.row-cols-lg-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-lg-4>*{flex:0 0 auto;width:25%}.row-cols-lg-5>*{flex:0 0 auto;width:20%}.row-cols-lg-6>*{flex:0 0 auto;width:16.66666667%}.col-lg-auto{flex:0 0 auto;width:auto}.col-lg-1{flex:0 0 auto;width:8.33333333%}.col-lg-2{flex:0 0 auto;width:16.66666667%}.col-lg-3{flex:0 0 auto;width:25%}.col-lg-4{flex:0 0 auto;width:33.33333333%}.col-lg-5{flex:0 0 auto;width:41.66666667%}.col-lg-6{flex:0 0 auto;width:50%}.col-lg-7{flex:0 0 auto;width:58.33333333%}.col-lg-8{flex:0 0 auto;width:66.66666667%}.col-lg-9{flex:0 0 auto;width:75%}.col-lg-10{flex:0 0 auto;width:83.33333333%}.col-lg-11{flex:0 0 auto;width:91.66666667%}.col-lg-12{flex:0 0 auto;width:100%}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.33333333%}.offset-lg-2{margin-left:16.66666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.33333333%}.offset-lg-5{margin-left:41.66666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.33333333%}.offset-lg-8{margin-left:66.66666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.33333333%}.offset-lg-11{margin-left:91.66666667%}.g-lg-0,.gx-lg-0{--bs-gutter-x:0}.g-lg-0,.gy-lg-0{--bs-gutter-y:0}.g-lg-1,.gx-lg-1{--bs-gutter-x:0.25rem}.g-lg-1,.gy-lg-1{--bs-gutter-y:0.25rem}.g-lg-2,.gx-lg-2{--bs-gutter-x:0.5rem}.g-lg-2,.gy-lg-2{--bs-gutter-y:0.5rem}.g-lg-3,.gx-lg-3{--bs-gutter-x:1rem}.g-lg-3,.gy-lg-3{--bs-gutter-y:1rem}.g-lg-4,.gx-lg-4{--bs-gutter-x:1.5rem}.g-lg-4,.gy-lg-4{--bs-gutter-y:1.5rem}.g-lg-5,.gx-lg-5{--bs-gutter-x:3rem}.g-lg-5,.gy-lg-5{--bs-gutter-y:3rem}}@media (min-width:1200px){.col-xl{flex:1 0 0}.row-cols-xl-auto>*{flex:0 0 auto;width:auto}.row-cols-xl-1>*{flex:0 0 auto;width:100%}.row-cols-xl-2>*{flex:0 0 auto;width:50%}.row-cols-xl-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-xl-4>*{flex:0 0 auto;width:25%}.row-cols-xl-5>*{flex:0 0 auto;width:20%}.row-cols-xl-6>*{flex:0 0 auto;width:16.66666667%}.col-xl-auto{flex:0 0 auto;width:auto}.col-xl-1{flex:0 0 auto;width:8.33333333%}.col-xl-2{flex:0 0 auto;width:16.66666667%}.col-xl-3{flex:0 0 auto;width:25%}.col-xl-4{flex:0 0 auto;width:33.33333333%}.col-xl-5{flex:0 0 auto;width:41.66666667%}.col-xl-6{flex:0 0 auto;width:50%}.col-xl-7{flex:0 0 auto;width:58.33333333%}.col-xl-8{flex:0 0 auto;width:66.66666667%}.col-xl-9{flex:0 0 auto;width:75%}.col-xl-10{flex:0 0 auto;width:83.33333333%}.col-xl-11{flex:0 0 auto;width:91.66666667%}.col-xl-12{flex:0 0 auto;width:100%}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.33333333%}.offset-xl-2{margin-left:16.66666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.33333333%}.offset-xl-5{margin-left:41.66666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.33333333%}.offset-xl-8{margin-left:66.66666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.33333333%}.offset-xl-11{margin-left:91.66666667%}.g-xl-0,.gx-xl-0{--bs-gutter-x:0}.g-xl-0,.gy-xl-0{--bs-gutter-y:0}.g-xl-1,.gx-xl-1{--bs-gutter-x:0.25rem}.g-xl-1,.gy-xl-1{--bs-gutter-y:0.25rem}.g-xl-2,.gx-xl-2{--bs-gutter-x:0.5rem}.g-xl-2,.gy-xl-2{--bs-gutter-y:0.5rem}.g-xl-3,.gx-xl-3{--bs-gutter-x:1rem}.g-xl-3,.gy-xl-3{--bs-gutter-y:1rem}.g-xl-4,.gx-xl-4{--bs-gutter-x:1.5rem}.g-xl-4,.gy-xl-4{--bs-gutter-y:1.5rem}.g-xl-5,.gx-xl-5{--bs-gutter-x:3rem}.g-xl-5,.gy-xl-5{--bs-gutter-y:3rem}}@media (min-width:1400px){.col-xxl{flex:1 0 0}.row-cols-xxl-auto>*{flex:0 0 auto;width:auto}.row-cols-xxl-1>*{flex:0 0 auto;width:100%}.row-cols-xxl-2>*{flex:0 0 auto;width:50%}.row-cols-xxl-3>*{flex:0 0 auto;width:33.33333333%}.row-cols-xxl-4>*{flex:0 0 auto;width:25%}.row-cols-xxl-5>*{flex:0 0 auto;width:20%}.row-cols-xxl-6>*{flex:0 0 auto;width:16.66666667%}.col-xxl-auto{flex:0 0 auto;width:auto}.col-xxl-1{flex:0 0 auto;width:8.33333333%}.col-xxl-2{flex:0 0 auto;width:16.66666667%}.col-xxl-3{flex:0 0 auto;width:25%}.col-xxl-4{flex:0 0 auto;width:33.33333333%}.col-xxl-5{flex:0 0 auto;width:41.66666667%}.col-xxl-6{flex:0 0 auto;width:50%}.col-xxl-7{flex:0 0 auto;width:58.33333333%}.col-xxl-8{flex:0 0 auto;width:66.66666667%}.col-xxl-9{flex:0 0 auto;width:75%}.col-xxl-10{flex:0 0 auto;width:83.33333333%}.col-xxl-11{flex:0 0 auto;width:91.66666667%}.col-xxl-12{flex:0 0 auto;width:100%}.offset-xxl-0{margin-left:0}.offset-xxl-1{margin-left:8.33333333%}.offset-xxl-2{margin-left:16.66666667%}.offset-xxl-3{margin-left:25%}.offset-xxl-4{margin-left:33.33333333%}.offset-xxl-5{margin-left:41.66666667%}.offset-xxl-6{margin-left:50%}.offset-xxl-7{margin-left:58.33333333%}.offset-xxl-8{margin-left:66.66666667%}.offset-xxl-9{margin-left:75%}.offset-xxl-10{margin-left:83.33333333%}.offset-xxl-11{margin-left:91.66666667%}.g-xxl-0,.gx-xxl-0{--bs-gutter-x:0}.g-xxl-0,.gy-xxl-0{--bs-gutter-y:0}.g-xxl-1,.gx-xxl-1{--bs-gutter-x:0.25rem}.g-xxl-1,.gy-xxl-1{--bs-gutter-y:0.25rem}.g-xxl-2,.gx-xxl-2{--bs-gutter-x:0.5rem}.g-xxl-2,.gy-xxl-2{--bs-gutter-y:0.5rem}.g-xxl-3,.gx-xxl-3{--bs-gutter-x:1rem}.g-xxl-3,.gy-xxl-3{--bs-gutter-y:1rem}.g-xxl-4,.gx-xxl-4{--bs-gutter-x:1.5rem}.g-xxl-4,.gy-xxl-4{--bs-gutter-y:1.5rem}.g-xxl-5,.gx-xxl-5{--bs-gutter-x:3rem}.g-xxl-5,.gy-xxl-5{--bs-gutter-y:3rem}}.table{--bs-table-color-type:initial;--bs-table-bg-type:initial;--bs-table-color-state:initial;--bs-table-bg-state:initial;--bs-table-color:var(--bs-emphasis-color);--bs-table-bg:var(--bs-body-bg);--bs-table-border-color:var(--bs-border-color);--bs-table-accent-bg:transparent;--bs-table-striped-color:var(--bs-emphasis-color);--bs-table-striped-bg:rgba(var(--bs-emphasis-color-rgb), 0.05);--bs-table-active-color:var(--bs-emphasis-color);--bs-table-active-bg:rgba(var(--bs-emphasis-color-rgb), 0.1);--bs-table-hover-color:var(--bs-emphasis-color);--bs-table-hover-bg:rgba(var(--bs-emphasis-color-rgb), 0.075);width:100%;margin-bottom:1rem;vertical-align:top;border-color:var(--bs-table-border-color)}.table>:not(caption)>*>*{padding:.5rem .5rem;color:var(--bs-table-color-state,var(--bs-table-color-type,var(--bs-table-color)));background-color:var(--bs-table-bg);border-bottom-width:var(--bs-border-width);box-shadow:inset 0 0 0 9999px var(--bs-table-bg-state,var(--bs-table-bg-type,var(--bs-table-accent-bg)))}.table>tbody{vertical-align:inherit}.table>thead{vertical-align:bottom}.table-group-divider{border-top:calc(var(--bs-border-width) * 2) solid currentcolor}.caption-top{caption-side:top}.table-sm>:not(caption)>*>*{padding:.25rem .25rem}.table-bordered>:not(caption)>*{border-width:var(--bs-border-width) 0}.table-bordered>:not(caption)>*>*{border-width:0 var(--bs-border-width)}.table-borderless>:not(caption)>*>*{border-bottom-width:0}.table-borderless>:not(:first-child){border-top-width:0}.table-striped>tbody>tr:nth-of-type(odd)>*{--bs-table-color-type:var(--bs-table-striped-color);--bs-table-bg-type:var(--bs-table-striped-bg)}.table-striped-columns>:not(caption)>tr>:nth-child(2n){--bs-table-color-type:var(--bs-table-striped-color);--bs-table-bg-type:var(--bs-table-striped-bg)}.table-active{--bs-table-color-state:var(--bs-table-active-color);--bs-table-bg-state:var(--bs-table-active-bg)}.table-hover>tbody>tr:hover>*{--bs-table-color-state:var(--bs-table-hover-color);--bs-table-bg-state:var(--bs-table-hover-bg)}.table-primary{--bs-table-color:#000;--bs-table-bg:#cfe2ff;--bs-table-border-color:#a6b5cc;--bs-table-striped-bg:#c5d7f2;--bs-table-striped-color:#000;--bs-table-active-bg:#bacbe6;--bs-table-active-color:#000;--bs-table-hover-bg:#bfd1ec;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-secondary{--bs-table-color:#000;--bs-table-bg:#e2e3e5;--bs-table-border-color:#b5b6b7;--bs-table-striped-bg:#d7d8da;--bs-table-striped-color:#000;--bs-table-active-bg:#cbccce;--bs-table-active-color:#000;--bs-table-hover-bg:#d1d2d4;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-success{--bs-table-color:#000;--bs-table-bg:#d1e7dd;--bs-table-border-color:#a7b9b1;--bs-table-striped-bg:#c7dbd2;--bs-table-striped-color:#000;--bs-table-active-bg:#bcd0c7;--bs-table-active-color:#000;--bs-table-hover-bg:#c1d6cc;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-info{--bs-table-color:#000;--bs-table-bg:#cff4fc;--bs-table-border-color:#a6c3ca;--bs-table-striped-bg:#c5e8ef;--bs-table-striped-color:#000;--bs-table-active-bg:#badce3;--bs-table-active-color:#000;--bs-table-hover-bg:#bfe2e9;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-warning{--bs-table-color:#000;--bs-table-bg:#fff3cd;--bs-table-border-color:#ccc2a4;--bs-table-striped-bg:#f2e7c3;--bs-table-striped-color:#000;--bs-table-active-bg:#e6dbb9;--bs-table-active-color:#000;--bs-table-hover-bg:#ece1be;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-danger{--bs-table-color:#000;--bs-table-bg:#f8d7da;--bs-table-border-color:#c6acae;--bs-table-striped-bg:#eccccf;--bs-table-striped-color:#000;--bs-table-active-bg:#dfc2c4;--bs-table-active-color:#000;--bs-table-hover-bg:#e5c7ca;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-light{--bs-table-color:#000;--bs-table-bg:#f8f9fa;--bs-table-border-color:#c6c7c8;--bs-table-striped-bg:#ecedee;--bs-table-striped-color:#000;--bs-table-active-bg:#dfe0e1;--bs-table-active-color:#000;--bs-table-hover-bg:#e5e6e7;--bs-table-hover-color:#000;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-dark{--bs-table-color:#fff;--bs-table-bg:#212529;--bs-table-border-color:#4d5154;--bs-table-striped-bg:#2c3034;--bs-table-striped-color:#fff;--bs-table-active-bg:#373b3e;--bs-table-active-color:#fff;--bs-table-hover-bg:#323539;--bs-table-hover-color:#fff;color:var(--bs-table-color);border-color:var(--bs-table-border-color)}.table-responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media (max-width:575.98px){.table-responsive-sm{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:767.98px){.table-responsive-md{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:991.98px){.table-responsive-lg{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1199.98px){.table-responsive-xl{overflow-x:auto;-webkit-overflow-scrolling:touch}}@media (max-width:1399.98px){.table-responsive-xxl{overflow-x:auto;-webkit-overflow-scrolling:touch}}.form-label{margin-bottom:.5rem}.col-form-label{padding-top:calc(.375rem + var(--bs-border-width));padding-bottom:calc(.375rem + var(--bs-border-width));margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + var(--bs-border-width));padding-bottom:calc(.5rem + var(--bs-border-width));font-size:1.25rem}.col-form-label-sm{padding-top:calc(.25rem + var(--bs-border-width));padding-bottom:calc(.25rem + var(--bs-border-width));font-size:.875rem}.form-text{margin-top:.25rem;font-size:.875em;color:var(--bs-secondary-color)}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-clip:padding-box;border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control{transition:none}}.form-control[type=file]{overflow:hidden}.form-control[type=file]:not(:disabled):not([readonly]){cursor:pointer}.form-control:focus{color:var(--bs-body-color);background-color:var(--bs-body-bg);border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-control::-webkit-date-and-time-value{min-width:85px;height:1.5em;margin:0}.form-control::-webkit-datetime-edit{display:block;padding:0}.form-control::placeholder{color:var(--bs-secondary-color);opacity:1}.form-control:disabled{background-color:var(--bs-secondary-bg);opacity:1}.form-control::-webkit-file-upload-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:var(--bs-body-color);background-color:var(--bs-tertiary-bg);pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:var(--bs-border-width);border-radius:0;-webkit-transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.form-control::file-selector-button{padding:.375rem .75rem;margin:-.375rem -.75rem;-webkit-margin-end:.75rem;margin-inline-end:.75rem;color:var(--bs-body-color);background-color:var(--bs-tertiary-bg);pointer-events:none;border-color:inherit;border-style:solid;border-width:0;border-inline-end-width:var(--bs-border-width);border-radius:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-control::-webkit-file-upload-button{-webkit-transition:none;transition:none}.form-control::file-selector-button{transition:none}}.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button{background-color:var(--bs-secondary-bg)}.form-control:hover:not(:disabled):not([readonly])::file-selector-button{background-color:var(--bs-secondary-bg)}.form-control-plaintext{display:block;width:100%;padding:.375rem 0;margin-bottom:0;line-height:1.5;color:var(--bs-body-color);background-color:transparent;border:solid transparent;border-width:var(--bs-border-width) 0}.form-control-plaintext:focus{outline:0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm{padding-right:0;padding-left:0}.form-control-sm{min-height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2));padding:.25rem .5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.form-control-sm::-webkit-file-upload-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-sm::file-selector-button{padding:.25rem .5rem;margin:-.25rem -.5rem;-webkit-margin-end:.5rem;margin-inline-end:.5rem}.form-control-lg{min-height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2));padding:.5rem 1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}.form-control-lg::-webkit-file-upload-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}.form-control-lg::file-selector-button{padding:.5rem 1rem;margin:-.5rem -1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}textarea.form-control{min-height:calc(1.5em + .75rem + calc(var(--bs-border-width) * 2))}textarea.form-control-sm{min-height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2))}textarea.form-control-lg{min-height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2))}.form-control-color{width:3rem;height:calc(1.5em + .75rem + calc(var(--bs-border-width) * 2));padding:.375rem}.form-control-color:not(:disabled):not([readonly]){cursor:pointer}.form-control-color::-moz-color-swatch{border:0!important;border-radius:var(--bs-border-radius)}.form-control-color::-webkit-color-swatch{border:0!important;border-radius:var(--bs-border-radius)}.form-control-color.form-control-sm{height:calc(1.5em + .5rem + calc(var(--bs-border-width) * 2))}.form-control-color.form-control-lg{height:calc(1.5em + 1rem + calc(var(--bs-border-width) * 2))}.form-select{--bs-form-select-bg-img:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");display:block;width:100%;padding:.375rem 2.25rem .375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-body-bg);background-image:var(--bs-form-select-bg-img),var(--bs-form-select-bg-icon,none);background-repeat:no-repeat;background-position:right .75rem center;background-size:16px 12px;border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius);transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-select{transition:none}}.form-select:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-select[multiple],.form-select[size]:not([size="1"]){padding-right:.75rem;background-image:none}.form-select:disabled{background-color:var(--bs-secondary-bg)}.form-select:-moz-focusring{color:transparent;text-shadow:0 0 0 var(--bs-body-color)}.form-select-sm{padding-top:.25rem;padding-bottom:.25rem;padding-left:.5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.form-select-lg{padding-top:.5rem;padding-bottom:.5rem;padding-left:1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}[data-bs-theme=dark] .form-select{--bs-form-select-bg-img:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e")}.form-check{display:block;min-height:1.5rem;padding-left:1.5em;margin-bottom:.125rem}.form-check .form-check-input{float:left;margin-left:-1.5em}.form-check-reverse{padding-right:1.5em;padding-left:0;text-align:right}.form-check-reverse .form-check-input{float:right;margin-right:-1.5em;margin-left:0}.form-check-input{--bs-form-check-bg:var(--bs-body-bg);flex-shrink:0;width:1em;height:1em;margin-top:.25em;vertical-align:top;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--bs-form-check-bg);background-image:var(--bs-form-check-bg-image);background-repeat:no-repeat;background-position:center;background-size:contain;border:var(--bs-border-width) solid var(--bs-border-color);-webkit-print-color-adjust:exact;color-adjust:exact;print-color-adjust:exact}.form-check-input[type=checkbox]{border-radius:.25em}.form-check-input[type=radio]{border-radius:50%}.form-check-input:active{filter:brightness(90%)}.form-check-input:focus{border-color:#86b7fe;outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.form-check-input:checked{background-color:#0d6efd;border-color:#0d6efd}.form-check-input:checked[type=checkbox]{--bs-form-check-bg-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e")}.form-check-input:checked[type=radio]{--bs-form-check-bg-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e")}.form-check-input[type=checkbox]:indeterminate{background-color:#0d6efd;border-color:#0d6efd;--bs-form-check-bg-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e")}.form-check-input:disabled{pointer-events:none;filter:none;opacity:.5}.form-check-input:disabled~.form-check-label,.form-check-input[disabled]~.form-check-label{cursor:default;opacity:.5}.form-switch{padding-left:2.5em}.form-switch .form-check-input{--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e");width:2em;margin-left:-2.5em;background-image:var(--bs-form-switch-bg);background-position:left center;border-radius:2em;transition:background-position .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-switch .form-check-input{transition:none}}.form-switch .form-check-input:focus{--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e")}.form-switch .form-check-input:checked{background-position:right center;--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e")}.form-switch.form-check-reverse{padding-right:2.5em;padding-left:0}.form-switch.form-check-reverse .form-check-input{margin-right:-2.5em;margin-left:0}.form-check-inline{display:inline-block;margin-right:1rem}.btn-check{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.btn-check:disabled+.btn,.btn-check[disabled]+.btn{pointer-events:none;filter:none;opacity:.65}[data-bs-theme=dark] .form-switch .form-check-input:not(:checked):not(:focus){--bs-form-switch-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%28255, 255, 255, 0.25%29'/%3e%3c/svg%3e")}.form-range{width:100%;height:1.5rem;padding:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent}.form-range:focus{outline:0}.form-range:focus::-webkit-slider-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range:focus::-moz-range-thumb{box-shadow:0 0 0 1px #fff,0 0 0 .25rem rgba(13,110,253,.25)}.form-range::-moz-focus-outer{border:0}.form-range::-webkit-slider-thumb{width:1rem;height:1rem;margin-top:-.25rem;-webkit-appearance:none;appearance:none;background-color:#0d6efd;border:0;border-radius:1rem;-webkit-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-range::-webkit-slider-thumb{-webkit-transition:none;transition:none}}.form-range::-webkit-slider-thumb:active{background-color:#b6d4fe}.form-range::-webkit-slider-runnable-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:var(--bs-secondary-bg);border-color:transparent;border-radius:1rem}.form-range::-moz-range-thumb{width:1rem;height:1rem;-moz-appearance:none;appearance:none;background-color:#0d6efd;border:0;border-radius:1rem;-moz-transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.form-range::-moz-range-thumb{-moz-transition:none;transition:none}}.form-range::-moz-range-thumb:active{background-color:#b6d4fe}.form-range::-moz-range-track{width:100%;height:.5rem;color:transparent;cursor:pointer;background-color:var(--bs-secondary-bg);border-color:transparent;border-radius:1rem}.form-range:disabled{pointer-events:none}.form-range:disabled::-webkit-slider-thumb{background-color:var(--bs-secondary-color)}.form-range:disabled::-moz-range-thumb{background-color:var(--bs-secondary-color)}.form-floating{position:relative}.form-floating>.form-control,.form-floating>.form-control-plaintext,.form-floating>.form-select{height:calc(3.5rem + calc(var(--bs-border-width) * 2));min-height:calc(3.5rem + calc(var(--bs-border-width) * 2));line-height:1.25}.form-floating>label{position:absolute;top:0;left:0;z-index:2;max-width:100%;height:100%;padding:1rem .75rem;overflow:hidden;color:rgba(var(--bs-body-color-rgb),.65);text-align:start;text-overflow:ellipsis;white-space:nowrap;pointer-events:none;border:var(--bs-border-width) solid transparent;transform-origin:0 0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}@media (prefers-reduced-motion:reduce){.form-floating>label{transition:none}}.form-floating>.form-control,.form-floating>.form-control-plaintext{padding:1rem .75rem}.form-floating>.form-control-plaintext::placeholder,.form-floating>.form-control::placeholder{color:transparent}.form-floating>.form-control-plaintext:focus,.form-floating>.form-control-plaintext:not(:placeholder-shown),.form-floating>.form-control:focus,.form-floating>.form-control:not(:placeholder-shown){padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-control-plaintext:-webkit-autofill,.form-floating>.form-control:-webkit-autofill{padding-top:1.625rem;padding-bottom:.625rem}.form-floating>.form-select{padding-top:1.625rem;padding-bottom:.625rem;padding-left:.75rem}.form-floating>.form-control-plaintext~label,.form-floating>.form-control:focus~label,.form-floating>.form-control:not(:placeholder-shown)~label,.form-floating>.form-select~label{transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>.form-control:-webkit-autofill~label{transform:scale(.85) translateY(-.5rem) translateX(.15rem)}.form-floating>textarea:focus~label::after,.form-floating>textarea:not(:placeholder-shown)~label::after{position:absolute;inset:1rem 0.375rem;z-index:-1;height:1.5em;content:"";background-color:var(--bs-body-bg);border-radius:var(--bs-border-radius)}.form-floating>textarea:disabled~label::after{background-color:var(--bs-secondary-bg)}.form-floating>.form-control-plaintext~label{border-width:var(--bs-border-width) 0}.form-floating>.form-control:disabled~label,.form-floating>:disabled~label{color:#6c757d}.input-group{position:relative;display:flex;flex-wrap:wrap;align-items:stretch;width:100%}.input-group>.form-control,.input-group>.form-floating,.input-group>.form-select{position:relative;flex:1 1 auto;width:1%;min-width:0}.input-group>.form-control:focus,.input-group>.form-floating:focus-within,.input-group>.form-select:focus{z-index:5}.input-group .btn{position:relative;z-index:2}.input-group .btn:focus{z-index:5}.input-group-text{display:flex;align-items:center;padding:.375rem .75rem;font-size:1rem;font-weight:400;line-height:1.5;color:var(--bs-body-color);text-align:center;white-space:nowrap;background-color:var(--bs-tertiary-bg);border:var(--bs-border-width) solid var(--bs-border-color);border-radius:var(--bs-border-radius)}.input-group-lg>.btn,.input-group-lg>.form-control,.input-group-lg>.form-select,.input-group-lg>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;border-radius:var(--bs-border-radius-lg)}.input-group-sm>.btn,.input-group-sm>.form-control,.input-group-sm>.form-select,.input-group-sm>.input-group-text{padding:.25rem .5rem;font-size:.875rem;border-radius:var(--bs-border-radius-sm)}.input-group-lg>.form-select,.input-group-sm>.form-select{padding-right:3rem}.input-group:not(.has-validation)>.dropdown-toggle:nth-last-child(n+3),.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-control,.input-group:not(.has-validation)>.form-floating:not(:last-child)>.form-select,.input-group:not(.has-validation)>:not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating){border-top-right-radius:0;border-bottom-right-radius:0}.input-group.has-validation>.dropdown-toggle:nth-last-child(n+4),.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-control,.input-group.has-validation>.form-floating:nth-last-child(n+3)>.form-select,.input-group.has-validation>:nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>:not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback){margin-left:calc(-1 * var(--bs-border-width));border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.form-floating:not(:first-child)>.form-control,.input-group>.form-floating:not(:first-child)>.form-select{border-top-left-radius:0;border-bottom-left-radius:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:var(--bs-form-valid-color)}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:var(--bs-success);border-radius:var(--bs-border-radius)}.is-valid~.valid-feedback,.is-valid~.valid-tooltip,.was-validated :valid~.valid-feedback,.was-validated :valid~.valid-tooltip{display:block}.form-control.is-valid,.was-validated .form-control:valid{border-color:var(--bs-form-valid-border-color);padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-valid:focus,.was-validated .form-control:valid:focus{border-color:var(--bs-form-valid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.was-validated textarea.form-control:valid,textarea.form-control.is-valid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-valid,.was-validated .form-select:valid{border-color:var(--bs-form-valid-border-color)}.form-select.is-valid:not([multiple]):not([size]),.form-select.is-valid:not([multiple])[size="1"],.was-validated .form-select:valid:not([multiple]):not([size]),.was-validated .form-select:valid:not([multiple])[size="1"]{--bs-form-select-bg-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-valid:focus,.was-validated .form-select:valid:focus{border-color:var(--bs-form-valid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.form-control-color.is-valid,.was-validated .form-control-color:valid{width:calc(3rem + calc(1.5em + .75rem))}.form-check-input.is-valid,.was-validated .form-check-input:valid{border-color:var(--bs-form-valid-border-color)}.form-check-input.is-valid:checked,.was-validated .form-check-input:valid:checked{background-color:var(--bs-form-valid-color)}.form-check-input.is-valid:focus,.was-validated .form-check-input:valid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-success-rgb),.25)}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:var(--bs-form-valid-color)}.form-check-inline .form-check-input~.valid-feedback{margin-left:.5em}.input-group>.form-control:not(:focus).is-valid,.input-group>.form-floating:not(:focus-within).is-valid,.input-group>.form-select:not(:focus).is-valid,.was-validated .input-group>.form-control:not(:focus):valid,.was-validated .input-group>.form-floating:not(:focus-within):valid,.was-validated .input-group>.form-select:not(:focus):valid{z-index:3}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:.875em;color:var(--bs-form-invalid-color)}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.25rem .5rem;margin-top:.1rem;font-size:.875rem;color:#fff;background-color:var(--bs-danger);border-radius:var(--bs-border-radius)}.is-invalid~.invalid-feedback,.is-invalid~.invalid-tooltip,.was-validated :invalid~.invalid-feedback,.was-validated :invalid~.invalid-tooltip{display:block}.form-control.is-invalid,.was-validated .form-control:invalid{border-color:var(--bs-form-invalid-border-color);padding-right:calc(1.5em + .75rem);background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");background-repeat:no-repeat;background-position:right calc(.375em + .1875rem) center;background-size:calc(.75em + .375rem) calc(.75em + .375rem)}.form-control.is-invalid:focus,.was-validated .form-control:invalid:focus{border-color:var(--bs-form-invalid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.was-validated textarea.form-control:invalid,textarea.form-control.is-invalid{padding-right:calc(1.5em + .75rem);background-position:top calc(.375em + .1875rem) right calc(.375em + .1875rem)}.form-select.is-invalid,.was-validated .form-select:invalid{border-color:var(--bs-form-invalid-border-color)}.form-select.is-invalid:not([multiple]):not([size]),.form-select.is-invalid:not([multiple])[size="1"],.was-validated .form-select:invalid:not([multiple]):not([size]),.was-validated .form-select:invalid:not([multiple])[size="1"]{--bs-form-select-bg-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e");padding-right:4.125rem;background-position:right .75rem center,center right 2.25rem;background-size:16px 12px,calc(.75em + .375rem) calc(.75em + .375rem)}.form-select.is-invalid:focus,.was-validated .form-select:invalid:focus{border-color:var(--bs-form-invalid-border-color);box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.form-control-color.is-invalid,.was-validated .form-control-color:invalid{width:calc(3rem + calc(1.5em + .75rem))}.form-check-input.is-invalid,.was-validated .form-check-input:invalid{border-color:var(--bs-form-invalid-border-color)}.form-check-input.is-invalid:checked,.was-validated .form-check-input:invalid:checked{background-color:var(--bs-form-invalid-color)}.form-check-input.is-invalid:focus,.was-validated .form-check-input:invalid:focus{box-shadow:0 0 0 .25rem rgba(var(--bs-danger-rgb),.25)}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:var(--bs-form-invalid-color)}.form-check-inline .form-check-input~.invalid-feedback{margin-left:.5em}.input-group>.form-control:not(:focus).is-invalid,.input-group>.form-floating:not(:focus-within).is-invalid,.input-group>.form-select:not(:focus).is-invalid,.was-validated .input-group>.form-control:not(:focus):invalid,.was-validated .input-group>.form-floating:not(:focus-within):invalid,.was-validated .input-group>.form-select:not(:focus):invalid{z-index:4}.btn{--bs-btn-padding-x:0.75rem;--bs-btn-padding-y:0.375rem;--bs-btn-font-family: ;--bs-btn-font-size:1rem;--bs-btn-font-weight:400;--bs-btn-line-height:1.5;--bs-btn-color:var(--bs-body-color);--bs-btn-bg:transparent;--bs-btn-border-width:var(--bs-border-width);--bs-btn-border-color:transparent;--bs-btn-border-radius:var(--bs-border-radius);--bs-btn-hover-border-color:transparent;--bs-btn-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.15),0 1px 1px rgba(0, 0, 0, 0.075);--bs-btn-disabled-opacity:0.65;--bs-btn-focus-box-shadow:0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb), .5);display:inline-block;padding:var(--bs-btn-padding-y) var(--bs-btn-padding-x);font-family:var(--bs-btn-font-family);font-size:var(--bs-btn-font-size);font-weight:var(--bs-btn-font-weight);line-height:var(--bs-btn-line-height);color:var(--bs-btn-color);text-align:center;text-decoration:none;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none;border:var(--bs-btn-border-width) solid var(--bs-btn-border-color);border-radius:var(--bs-btn-border-radius);background-color:var(--bs-btn-bg);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.btn{transition:none}}.btn:hover{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color)}.btn-check+.btn:hover{color:var(--bs-btn-color);background-color:var(--bs-btn-bg);border-color:var(--bs-btn-border-color)}.btn:focus-visible{color:var(--bs-btn-hover-color);background-color:var(--bs-btn-hover-bg);border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:focus-visible+.btn{border-color:var(--bs-btn-hover-border-color);outline:0;box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:checked+.btn,.btn.active,.btn.show,.btn:first-child:active,:not(.btn-check)+.btn:active{color:var(--bs-btn-active-color);background-color:var(--bs-btn-active-bg);border-color:var(--bs-btn-active-border-color)}.btn-check:checked+.btn:focus-visible,.btn.active:focus-visible,.btn.show:focus-visible,.btn:first-child:active:focus-visible,:not(.btn-check)+.btn:active:focus-visible{box-shadow:var(--bs-btn-focus-box-shadow)}.btn-check:checked:focus-visible+.btn{box-shadow:var(--bs-btn-focus-box-shadow)}.btn.disabled,.btn:disabled,fieldset:disabled .btn{color:var(--bs-btn-disabled-color);pointer-events:none;background-color:var(--bs-btn-disabled-bg);border-color:var(--bs-btn-disabled-border-color);opacity:var(--bs-btn-disabled-opacity)}.btn-primary{--bs-btn-color:#fff;--bs-btn-bg:#0d6efd;--bs-btn-border-color:#0d6efd;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#0b5ed7;--bs-btn-hover-border-color:#0a58ca;--bs-btn-focus-shadow-rgb:49,132,253;--bs-btn-active-color:#fff;--bs-btn-active-bg:#0a58ca;--bs-btn-active-border-color:#0a53be;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#0d6efd;--bs-btn-disabled-border-color:#0d6efd}.btn-secondary{--bs-btn-color:#fff;--bs-btn-bg:#6c757d;--bs-btn-border-color:#6c757d;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#5c636a;--bs-btn-hover-border-color:#565e64;--bs-btn-focus-shadow-rgb:130,138,145;--bs-btn-active-color:#fff;--bs-btn-active-bg:#565e64;--bs-btn-active-border-color:#51585e;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#6c757d;--bs-btn-disabled-border-color:#6c757d}.btn-success{--bs-btn-color:#fff;--bs-btn-bg:#198754;--bs-btn-border-color:#198754;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#157347;--bs-btn-hover-border-color:#146c43;--bs-btn-focus-shadow-rgb:60,153,110;--bs-btn-active-color:#fff;--bs-btn-active-bg:#146c43;--bs-btn-active-border-color:#13653f;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#198754;--bs-btn-disabled-border-color:#198754}.btn-info{--bs-btn-color:#000;--bs-btn-bg:#0dcaf0;--bs-btn-border-color:#0dcaf0;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#31d2f2;--bs-btn-hover-border-color:#25cff2;--bs-btn-focus-shadow-rgb:11,172,204;--bs-btn-active-color:#000;--bs-btn-active-bg:#3dd5f3;--bs-btn-active-border-color:#25cff2;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#0dcaf0;--bs-btn-disabled-border-color:#0dcaf0}.btn-warning{--bs-btn-color:#000;--bs-btn-bg:#ffc107;--bs-btn-border-color:#ffc107;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#ffca2c;--bs-btn-hover-border-color:#ffc720;--bs-btn-focus-shadow-rgb:217,164,6;--bs-btn-active-color:#000;--bs-btn-active-bg:#ffcd39;--bs-btn-active-border-color:#ffc720;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#ffc107;--bs-btn-disabled-border-color:#ffc107}.btn-danger{--bs-btn-color:#fff;--bs-btn-bg:#dc3545;--bs-btn-border-color:#dc3545;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#bb2d3b;--bs-btn-hover-border-color:#b02a37;--bs-btn-focus-shadow-rgb:225,83,97;--bs-btn-active-color:#fff;--bs-btn-active-bg:#b02a37;--bs-btn-active-border-color:#a52834;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#dc3545;--bs-btn-disabled-border-color:#dc3545}.btn-light{--bs-btn-color:#000;--bs-btn-bg:#f8f9fa;--bs-btn-border-color:#f8f9fa;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#d3d4d5;--bs-btn-hover-border-color:#c6c7c8;--bs-btn-focus-shadow-rgb:211,212,213;--bs-btn-active-color:#000;--bs-btn-active-bg:#c6c7c8;--bs-btn-active-border-color:#babbbc;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#000;--bs-btn-disabled-bg:#f8f9fa;--bs-btn-disabled-border-color:#f8f9fa}.btn-dark{--bs-btn-color:#fff;--bs-btn-bg:#212529;--bs-btn-border-color:#212529;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#424649;--bs-btn-hover-border-color:#373b3e;--bs-btn-focus-shadow-rgb:66,70,73;--bs-btn-active-color:#fff;--bs-btn-active-bg:#4d5154;--bs-btn-active-border-color:#373b3e;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:#212529;--bs-btn-disabled-border-color:#212529}.btn-outline-primary{--bs-btn-color:#0d6efd;--bs-btn-border-color:#0d6efd;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#0d6efd;--bs-btn-hover-border-color:#0d6efd;--bs-btn-focus-shadow-rgb:13,110,253;--bs-btn-active-color:#fff;--bs-btn-active-bg:#0d6efd;--bs-btn-active-border-color:#0d6efd;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#0d6efd;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#0d6efd;--bs-gradient:none}.btn-outline-secondary{--bs-btn-color:#6c757d;--bs-btn-border-color:#6c757d;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#6c757d;--bs-btn-hover-border-color:#6c757d;--bs-btn-focus-shadow-rgb:108,117,125;--bs-btn-active-color:#fff;--bs-btn-active-bg:#6c757d;--bs-btn-active-border-color:#6c757d;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#6c757d;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#6c757d;--bs-gradient:none}.btn-outline-success{--bs-btn-color:#198754;--bs-btn-border-color:#198754;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#198754;--bs-btn-hover-border-color:#198754;--bs-btn-focus-shadow-rgb:25,135,84;--bs-btn-active-color:#fff;--bs-btn-active-bg:#198754;--bs-btn-active-border-color:#198754;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#198754;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#198754;--bs-gradient:none}.btn-outline-info{--bs-btn-color:#0dcaf0;--bs-btn-border-color:#0dcaf0;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#0dcaf0;--bs-btn-hover-border-color:#0dcaf0;--bs-btn-focus-shadow-rgb:13,202,240;--bs-btn-active-color:#000;--bs-btn-active-bg:#0dcaf0;--bs-btn-active-border-color:#0dcaf0;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#0dcaf0;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#0dcaf0;--bs-gradient:none}.btn-outline-warning{--bs-btn-color:#ffc107;--bs-btn-border-color:#ffc107;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#ffc107;--bs-btn-hover-border-color:#ffc107;--bs-btn-focus-shadow-rgb:255,193,7;--bs-btn-active-color:#000;--bs-btn-active-bg:#ffc107;--bs-btn-active-border-color:#ffc107;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#ffc107;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#ffc107;--bs-gradient:none}.btn-outline-danger{--bs-btn-color:#dc3545;--bs-btn-border-color:#dc3545;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#dc3545;--bs-btn-hover-border-color:#dc3545;--bs-btn-focus-shadow-rgb:220,53,69;--bs-btn-active-color:#fff;--bs-btn-active-bg:#dc3545;--bs-btn-active-border-color:#dc3545;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#dc3545;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#dc3545;--bs-gradient:none}.btn-outline-light{--bs-btn-color:#f8f9fa;--bs-btn-border-color:#f8f9fa;--bs-btn-hover-color:#000;--bs-btn-hover-bg:#f8f9fa;--bs-btn-hover-border-color:#f8f9fa;--bs-btn-focus-shadow-rgb:248,249,250;--bs-btn-active-color:#000;--bs-btn-active-bg:#f8f9fa;--bs-btn-active-border-color:#f8f9fa;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#f8f9fa;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#f8f9fa;--bs-gradient:none}.btn-outline-dark{--bs-btn-color:#212529;--bs-btn-border-color:#212529;--bs-btn-hover-color:#fff;--bs-btn-hover-bg:#212529;--bs-btn-hover-border-color:#212529;--bs-btn-focus-shadow-rgb:33,37,41;--bs-btn-active-color:#fff;--bs-btn-active-bg:#212529;--bs-btn-active-border-color:#212529;--bs-btn-active-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);--bs-btn-disabled-color:#212529;--bs-btn-disabled-bg:transparent;--bs-btn-disabled-border-color:#212529;--bs-gradient:none}.btn-link{--bs-btn-font-weight:400;--bs-btn-color:var(--bs-link-color);--bs-btn-bg:transparent;--bs-btn-border-color:transparent;--bs-btn-hover-color:var(--bs-link-hover-color);--bs-btn-hover-border-color:transparent;--bs-btn-active-color:var(--bs-link-hover-color);--bs-btn-active-border-color:transparent;--bs-btn-disabled-color:#6c757d;--bs-btn-disabled-border-color:transparent;--bs-btn-box-shadow:0 0 0 #000;--bs-btn-focus-shadow-rgb:49,132,253;text-decoration:underline}.btn-link:focus-visible{color:var(--bs-btn-color)}.btn-link:hover{color:var(--bs-btn-hover-color)}.btn-group-lg>.btn,.btn-lg{--bs-btn-padding-y:0.5rem;--bs-btn-padding-x:1rem;--bs-btn-font-size:1.25rem;--bs-btn-border-radius:var(--bs-border-radius-lg)}.btn-group-sm>.btn,.btn-sm{--bs-btn-padding-y:0.25rem;--bs-btn-padding-x:0.5rem;--bs-btn-font-size:0.875rem;--bs-btn-border-radius:var(--bs-border-radius-sm)}.fade{transition:opacity .15s linear}@media (prefers-reduced-motion:reduce){.fade{transition:none}}.fade:not(.show){opacity:0}.collapse:not(.show){display:none}.collapsing{height:0;overflow:hidden;transition:height .35s ease}@media (prefers-reduced-motion:reduce){.collapsing{transition:none}}.collapsing.collapse-horizontal{width:0;height:auto;transition:width .35s ease}@media (prefers-reduced-motion:reduce){.collapsing.collapse-horizontal{transition:none}}.dropdown,.dropdown-center,.dropend,.dropstart,.dropup,.dropup-center{position:relative}.dropdown-toggle{white-space:nowrap}.dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{--bs-dropdown-zindex:1000;--bs-dropdown-min-width:10rem;--bs-dropdown-padding-x:0;--bs-dropdown-padding-y:0.5rem;--bs-dropdown-spacer:0.125rem;--bs-dropdown-font-size:1rem;--bs-dropdown-color:var(--bs-body-color);--bs-dropdown-bg:var(--bs-body-bg);--bs-dropdown-border-color:var(--bs-border-color-translucent);--bs-dropdown-border-radius:var(--bs-border-radius);--bs-dropdown-border-width:var(--bs-border-width);--bs-dropdown-inner-border-radius:calc(var(--bs-border-radius) - var(--bs-border-width));--bs-dropdown-divider-bg:var(--bs-border-color-translucent);--bs-dropdown-divider-margin-y:0.5rem;--bs-dropdown-box-shadow:var(--bs-box-shadow);--bs-dropdown-link-color:var(--bs-body-color);--bs-dropdown-link-hover-color:var(--bs-body-color);--bs-dropdown-link-hover-bg:var(--bs-tertiary-bg);--bs-dropdown-link-active-color:#fff;--bs-dropdown-link-active-bg:#0d6efd;--bs-dropdown-link-disabled-color:var(--bs-tertiary-color);--bs-dropdown-item-padding-x:1rem;--bs-dropdown-item-padding-y:0.25rem;--bs-dropdown-header-color:#6c757d;--bs-dropdown-header-padding-x:1rem;--bs-dropdown-header-padding-y:0.5rem;position:absolute;z-index:var(--bs-dropdown-zindex);display:none;min-width:var(--bs-dropdown-min-width);padding:var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x);margin:0;font-size:var(--bs-dropdown-font-size);color:var(--bs-dropdown-color);text-align:left;list-style:none;background-color:var(--bs-dropdown-bg);background-clip:padding-box;border:var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color);border-radius:var(--bs-dropdown-border-radius)}.dropdown-menu[data-bs-popper]{top:100%;left:0;margin-top:var(--bs-dropdown-spacer)}.dropdown-menu-start{--bs-position:start}.dropdown-menu-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-end{--bs-position:end}.dropdown-menu-end[data-bs-popper]{right:0;left:auto}@media (min-width:576px){.dropdown-menu-sm-start{--bs-position:start}.dropdown-menu-sm-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-sm-end{--bs-position:end}.dropdown-menu-sm-end[data-bs-popper]{right:0;left:auto}}@media (min-width:768px){.dropdown-menu-md-start{--bs-position:start}.dropdown-menu-md-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-md-end{--bs-position:end}.dropdown-menu-md-end[data-bs-popper]{right:0;left:auto}}@media (min-width:992px){.dropdown-menu-lg-start{--bs-position:start}.dropdown-menu-lg-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-lg-end{--bs-position:end}.dropdown-menu-lg-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1200px){.dropdown-menu-xl-start{--bs-position:start}.dropdown-menu-xl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xl-end{--bs-position:end}.dropdown-menu-xl-end[data-bs-popper]{right:0;left:auto}}@media (min-width:1400px){.dropdown-menu-xxl-start{--bs-position:start}.dropdown-menu-xxl-start[data-bs-popper]{right:auto;left:0}.dropdown-menu-xxl-end{--bs-position:end}.dropdown-menu-xxl-end[data-bs-popper]{right:0;left:auto}}.dropup .dropdown-menu[data-bs-popper]{top:auto;bottom:100%;margin-top:0;margin-bottom:var(--bs-dropdown-spacer)}.dropup .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-menu[data-bs-popper]{top:0;right:auto;left:100%;margin-top:0;margin-left:var(--bs-dropdown-spacer)}.dropend .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:0;border-bottom:.3em solid transparent;border-left:.3em solid}.dropend .dropdown-toggle:empty::after{margin-left:0}.dropend .dropdown-toggle::after{vertical-align:0}.dropstart .dropdown-menu[data-bs-popper]{top:0;right:100%;left:auto;margin-top:0;margin-right:var(--bs-dropdown-spacer)}.dropstart .dropdown-toggle::after{display:inline-block;margin-left:.255em;vertical-align:.255em;content:""}.dropstart .dropdown-toggle::after{display:none}.dropstart .dropdown-toggle::before{display:inline-block;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropstart .dropdown-toggle:empty::after{margin-left:0}.dropstart .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:var(--bs-dropdown-divider-margin-y) 0;overflow:hidden;border-top:1px solid var(--bs-dropdown-divider-bg);opacity:1}.dropdown-item{display:block;width:100%;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);clear:both;font-weight:400;color:var(--bs-dropdown-link-color);text-align:inherit;text-decoration:none;white-space:nowrap;background-color:transparent;border:0;border-radius:var(--bs-dropdown-item-border-radius,0)}.dropdown-item:focus,.dropdown-item:hover{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg)}.dropdown-item.active,.dropdown-item:active{color:var(--bs-dropdown-link-active-color);text-decoration:none;background-color:var(--bs-dropdown-link-active-bg)}.dropdown-item.disabled,.dropdown-item:disabled{color:var(--bs-dropdown-link-disabled-color);pointer-events:none;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x);margin-bottom:0;font-size:.875rem;color:var(--bs-dropdown-header-color);white-space:nowrap}.dropdown-item-text{display:block;padding:var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);color:var(--bs-dropdown-link-color)}.dropdown-menu-dark{--bs-dropdown-color:#dee2e6;--bs-dropdown-bg:#343a40;--bs-dropdown-border-color:var(--bs-border-color-translucent);--bs-dropdown-box-shadow: ;--bs-dropdown-link-color:#dee2e6;--bs-dropdown-link-hover-color:#fff;--bs-dropdown-divider-bg:var(--bs-border-color-translucent);--bs-dropdown-link-hover-bg:rgba(255, 255, 255, 0.15);--bs-dropdown-link-active-color:#fff;--bs-dropdown-link-active-bg:#0d6efd;--bs-dropdown-link-disabled-color:#adb5bd;--bs-dropdown-header-color:#adb5bd}.btn-group,.btn-group-vertical{position:relative;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;flex:1 1 auto}.btn-group-vertical>.btn-check:checked+.btn,.btn-group-vertical>.btn-check:focus+.btn,.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn-check:checked+.btn,.btn-group>.btn-check:focus+.btn,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:1}.btn-toolbar{display:flex;flex-wrap:wrap;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group{border-radius:var(--bs-border-radius)}.btn-group>.btn-group:not(:first-child),.btn-group>:not(.btn-check:first-child)+.btn{margin-left:calc(-1 * var(--bs-border-width))}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn.dropdown-toggle-split:first-child,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:nth-child(n+3),.btn-group>:not(.btn-check)+.btn{border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after,.dropend .dropdown-toggle-split::after,.dropup .dropdown-toggle-split::after{margin-left:0}.dropstart .dropdown-toggle-split::before{margin-right:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{flex-direction:column;align-items:flex-start;justify-content:center}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{width:100%}.btn-group-vertical>.btn-group:not(:first-child),.btn-group-vertical>.btn:not(:first-child){margin-top:calc(-1 * var(--bs-border-width))}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:nth-child(n+3),.btn-group-vertical>:not(.btn-check)+.btn{border-top-left-radius:0;border-top-right-radius:0}.nav{--bs-nav-link-padding-x:1rem;--bs-nav-link-padding-y:0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-link-color);--bs-nav-link-hover-color:var(--bs-link-hover-color);--bs-nav-link-disabled-color:var(--bs-secondary-color);display:flex;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x);font-size:var(--bs-nav-link-font-size);font-weight:var(--bs-nav-link-font-weight);color:var(--bs-nav-link-color);text-decoration:none;background:0 0;border:0;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out}@media (prefers-reduced-motion:reduce){.nav-link{transition:none}}.nav-link:focus,.nav-link:hover{color:var(--bs-nav-link-hover-color)}.nav-link:focus-visible{outline:0;box-shadow:0 0 0 .25rem rgba(13,110,253,.25)}.nav-link.disabled,.nav-link:disabled{color:var(--bs-nav-link-disabled-color);pointer-events:none;cursor:default}.nav-tabs{--bs-nav-tabs-border-width:var(--bs-border-width);--bs-nav-tabs-border-color:var(--bs-border-color);--bs-nav-tabs-border-radius:var(--bs-border-radius);--bs-nav-tabs-link-hover-border-color:var(--bs-secondary-bg) var(--bs-secondary-bg) var(--bs-border-color);--bs-nav-tabs-link-active-color:var(--bs-emphasis-color);--bs-nav-tabs-link-active-bg:var(--bs-body-bg);--bs-nav-tabs-link-active-border-color:var(--bs-border-color) var(--bs-border-color) var(--bs-body-bg);border-bottom:var(--bs-nav-tabs-border-width) solid var(--bs-nav-tabs-border-color)}.nav-tabs .nav-link{margin-bottom:calc(-1 * var(--bs-nav-tabs-border-width));border:var(--bs-nav-tabs-border-width) solid transparent;border-top-left-radius:var(--bs-nav-tabs-border-radius);border-top-right-radius:var(--bs-nav-tabs-border-radius)}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{isolation:isolate;border-color:var(--bs-nav-tabs-link-hover-border-color)}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:var(--bs-nav-tabs-link-active-color);background-color:var(--bs-nav-tabs-link-active-bg);border-color:var(--bs-nav-tabs-link-active-border-color)}.nav-tabs .dropdown-menu{margin-top:calc(-1 * var(--bs-nav-tabs-border-width));border-top-left-radius:0;border-top-right-radius:0}.nav-pills{--bs-nav-pills-border-radius:var(--bs-border-radius);--bs-nav-pills-link-active-color:#fff;--bs-nav-pills-link-active-bg:#0d6efd}.nav-pills .nav-link{border-radius:var(--bs-nav-pills-border-radius)}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:var(--bs-nav-pills-link-active-color);background-color:var(--bs-nav-pills-link-active-bg)}.nav-underline{--bs-nav-underline-gap:1rem;--bs-nav-underline-border-width:0.125rem;--bs-nav-underline-link-active-color:var(--bs-emphasis-color);gap:var(--bs-nav-underline-gap)}.nav-underline .nav-link{padding-right:0;padding-left:0;border-bottom:var(--bs-nav-underline-border-width) solid transparent}.nav-underline .nav-link:focus,.nav-underline .nav-link:hover{border-bottom-color:currentcolor}.nav-underline .nav-link.active,.nav-underline .show>.nav-link{font-weight:700;color:var(--bs-nav-underline-link-active-color);border-bottom-color:currentcolor}.nav-fill .nav-item,.nav-fill>.nav-link{flex:1 1 auto;text-align:center}.nav-justified .nav-item,.nav-justified>.nav-link{flex-grow:1;flex-basis:0;text-align:center}.nav-fill .nav-item .nav-link,.nav-justified .nav-item .nav-link{width:100%}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{--bs-navbar-padding-x:0;--bs-navbar-padding-y:0.5rem;--bs-navbar-color:rgba(var(--bs-emphasis-color-rgb), 0.65);--bs-navbar-hover-color:rgba(var(--bs-emphasis-color-rgb), 0.8);--bs-navbar-disabled-color:rgba(var(--bs-emphasis-color-rgb), 0.3);--bs-navbar-active-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-brand-padding-y:0.3125rem;--bs-navbar-brand-margin-end:1rem;--bs-navbar-brand-font-size:1.25rem;--bs-navbar-brand-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-brand-hover-color:rgba(var(--bs-emphasis-color-rgb), 1);--bs-navbar-nav-link-padding-x:0.5rem;--bs-navbar-toggler-padding-y:0.25rem;--bs-navbar-toggler-padding-x:0.75rem;--bs-navbar-toggler-font-size:1.25rem;--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%2833, 37, 41, 0.75%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");--bs-navbar-toggler-border-color:rgba(var(--bs-emphasis-color-rgb), 0.15);--bs-navbar-toggler-border-radius:var(--bs-border-radius);--bs-navbar-toggler-focus-width:0.25rem;--bs-navbar-toggler-transition:box-shadow 0.15s ease-in-out;position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;padding:var(--bs-navbar-padding-y) var(--bs-navbar-padding-x)}.navbar>.container,.navbar>.container-fluid,.navbar>.container-lg,.navbar>.container-md,.navbar>.container-sm,.navbar>.container-xl,.navbar>.container-xxl{display:flex;flex-wrap:inherit;align-items:center;justify-content:space-between}.navbar-brand{padding-top:var(--bs-navbar-brand-padding-y);padding-bottom:var(--bs-navbar-brand-padding-y);margin-right:var(--bs-navbar-brand-margin-end);font-size:var(--bs-navbar-brand-font-size);color:var(--bs-navbar-brand-color);text-decoration:none;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{color:var(--bs-navbar-brand-hover-color)}.navbar-nav{--bs-nav-link-padding-x:0;--bs-nav-link-padding-y:0.5rem;--bs-nav-link-font-weight: ;--bs-nav-link-color:var(--bs-navbar-color);--bs-nav-link-hover-color:var(--bs-navbar-hover-color);--bs-nav-link-disabled-color:var(--bs-navbar-disabled-color);display:flex;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link.active,.navbar-nav .nav-link.show{color:var(--bs-navbar-active-color)}.navbar-nav .dropdown-menu{position:static}.navbar-text{padding-top:.5rem;padding-bottom:.5rem;color:var(--bs-navbar-color)}.navbar-text a,.navbar-text a:focus,.navbar-text a:hover{color:var(--bs-navbar-active-color)}.navbar-collapse{flex-grow:1;flex-basis:100%;align-items:center}.navbar-toggler{padding:var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x);font-size:var(--bs-navbar-toggler-font-size);line-height:1;color:var(--bs-navbar-color);background-color:transparent;border:var(--bs-border-width) solid var(--bs-navbar-toggler-border-color);border-radius:var(--bs-navbar-toggler-border-radius);transition:var(--bs-navbar-toggler-transition)}@media (prefers-reduced-motion:reduce){.navbar-toggler{transition:none}}.navbar-toggler:hover{text-decoration:none}.navbar-toggler:focus{text-decoration:none;outline:0;box-shadow:0 0 0 var(--bs-navbar-toggler-focus-width)}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;background-image:var(--bs-navbar-toggler-icon-bg);background-repeat:no-repeat;background-position:center;background-size:100%}.navbar-nav-scroll{max-height:var(--bs-scroll-height,75vh);overflow-y:auto}@media (min-width:576px){.navbar-expand-sm{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-sm .navbar-nav{flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-sm .navbar-nav-scroll{overflow:visible}.navbar-expand-sm .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-sm .offcanvas .offcanvas-header{display:none}.navbar-expand-sm .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:768px){.navbar-expand-md{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-md .navbar-nav{flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-md .navbar-nav-scroll{overflow:visible}.navbar-expand-md .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-md .offcanvas .offcanvas-header{display:none}.navbar-expand-md .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:992px){.navbar-expand-lg{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-lg .navbar-nav{flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-lg .navbar-nav-scroll{overflow:visible}.navbar-expand-lg .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-lg .offcanvas .offcanvas-header{display:none}.navbar-expand-lg .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1200px){.navbar-expand-xl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xl .navbar-nav{flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xl .navbar-nav-scroll{overflow:visible}.navbar-expand-xl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-xl .offcanvas .offcanvas-header{display:none}.navbar-expand-xl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}@media (min-width:1400px){.navbar-expand-xxl{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand-xxl .navbar-nav{flex-direction:row}.navbar-expand-xxl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xxl .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand-xxl .navbar-nav-scroll{overflow:visible}.navbar-expand-xxl .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand-xxl .navbar-toggler{display:none}.navbar-expand-xxl .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand-xxl .offcanvas .offcanvas-header{display:none}.navbar-expand-xxl .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}}.navbar-expand{flex-wrap:nowrap;justify-content:flex-start}.navbar-expand .navbar-nav{flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .nav-link{padding-right:var(--bs-navbar-nav-link-padding-x);padding-left:var(--bs-navbar-nav-link-padding-x)}.navbar-expand .navbar-nav-scroll{overflow:visible}.navbar-expand .navbar-collapse{display:flex!important;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .offcanvas{position:static;z-index:auto;flex-grow:1;width:auto!important;height:auto!important;visibility:visible!important;background-color:transparent!important;border:0!important;transform:none!important;transition:none}.navbar-expand .offcanvas .offcanvas-header{display:none}.navbar-expand .offcanvas .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible}.navbar-dark,.navbar[data-bs-theme=dark]{--bs-navbar-color:rgba(255, 255, 255, 0.55);--bs-navbar-hover-color:rgba(255, 255, 255, 0.75);--bs-navbar-disabled-color:rgba(255, 255, 255, 0.25);--bs-navbar-active-color:#fff;--bs-navbar-brand-color:#fff;--bs-navbar-brand-hover-color:#fff;--bs-navbar-toggler-border-color:rgba(255, 255, 255, 0.1);--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}[data-bs-theme=dark] .navbar-toggler-icon{--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e")}.card{--bs-card-spacer-y:1rem;--bs-card-spacer-x:1rem;--bs-card-title-spacer-y:0.5rem;--bs-card-title-color: ;--bs-card-subtitle-color: ;--bs-card-border-width:var(--bs-border-width);--bs-card-border-color:var(--bs-border-color-translucent);--bs-card-border-radius:var(--bs-border-radius);--bs-card-box-shadow: ;--bs-card-inner-border-radius:calc(var(--bs-border-radius) - (var(--bs-border-width)));--bs-card-cap-padding-y:0.5rem;--bs-card-cap-padding-x:1rem;--bs-card-cap-bg:rgba(var(--bs-body-color-rgb), 0.03);--bs-card-cap-color: ;--bs-card-height: ;--bs-card-color: ;--bs-card-bg:var(--bs-body-bg);--bs-card-img-overlay-padding:1rem;--bs-card-group-margin:0.75rem;position:relative;display:flex;flex-direction:column;min-width:0;height:var(--bs-card-height);color:var(--bs-body-color);word-wrap:break-word;background-color:var(--bs-card-bg);background-clip:border-box;border:var(--bs-card-border-width) solid var(--bs-card-border-color);border-radius:var(--bs-card-border-radius)}.card>hr{margin-right:0;margin-left:0}.card>.list-group{border-top:inherit;border-bottom:inherit}.card>.list-group:first-child{border-top-width:0;border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card>.list-group:last-child{border-bottom-width:0;border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card>.card-header+.list-group,.card>.list-group+.card-footer{border-top:0}.card-body{flex:1 1 auto;padding:var(--bs-card-spacer-y) var(--bs-card-spacer-x);color:var(--bs-card-color)}.card-title{margin-bottom:var(--bs-card-title-spacer-y);color:var(--bs-card-title-color)}.card-subtitle{margin-top:calc(-.5 * var(--bs-card-title-spacer-y));margin-bottom:0;color:var(--bs-card-subtitle-color)}.card-text:last-child{margin-bottom:0}.card-link+.card-link{margin-left:var(--bs-card-spacer-x)}.card-header{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);margin-bottom:0;color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-bottom:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-header:first-child{border-radius:var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0}.card-footer{padding:var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x);color:var(--bs-card-cap-color);background-color:var(--bs-card-cap-bg);border-top:var(--bs-card-border-width) solid var(--bs-card-border-color)}.card-footer:last-child{border-radius:0 0 var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius)}.card-header-tabs{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-bottom:calc(-1 * var(--bs-card-cap-padding-y));margin-left:calc(-.5 * var(--bs-card-cap-padding-x));border-bottom:0}.card-header-tabs .nav-link.active{background-color:var(--bs-card-bg);border-bottom-color:var(--bs-card-bg)}.card-header-pills{margin-right:calc(-.5 * var(--bs-card-cap-padding-x));margin-left:calc(-.5 * var(--bs-card-cap-padding-x))}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:var(--bs-card-img-overlay-padding);border-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom,.card-img-top{width:100%}.card-img,.card-img-top{border-top-left-radius:var(--bs-card-inner-border-radius);border-top-right-radius:var(--bs-card-inner-border-radius)}.card-img,.card-img-bottom{border-bottom-right-radius:var(--bs-card-inner-border-radius);border-bottom-left-radius:var(--bs-card-inner-border-radius)}.card-group>.card{margin-bottom:var(--bs-card-group-margin)}@media (min-width:576px){.card-group{display:flex;flex-flow:row wrap}.card-group>.card{flex:1 0 0;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:not(:last-child)>.card-header,.card-group>.card:not(:last-child)>.card-img-top{border-top-right-radius:0}.card-group>.card:not(:last-child)>.card-footer,.card-group>.card:not(:last-child)>.card-img-bottom{border-bottom-right-radius:0}.card-group>.card:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:not(:first-child)>.card-header,.card-group>.card:not(:first-child)>.card-img-top{border-top-left-radius:0}.card-group>.card:not(:first-child)>.card-footer,.card-group>.card:not(:first-child)>.card-img-bottom{border-bottom-left-radius:0}}.accordion{--bs-accordion-color:var(--bs-body-color);--bs-accordion-bg:var(--bs-body-bg);--bs-accordion-transition:color 0.15s ease-in-out,background-color 0.15s ease-in-out,border-color 0.15s ease-in-out,box-shadow 0.15s ease-in-out,border-radius 0.15s ease;--bs-accordion-border-color:var(--bs-border-color);--bs-accordion-border-width:var(--bs-border-width);--bs-accordion-border-radius:var(--bs-border-radius);--bs-accordion-inner-border-radius:calc(var(--bs-border-radius) - (var(--bs-border-width)));--bs-accordion-btn-padding-x:1.25rem;--bs-accordion-btn-padding-y:1rem;--bs-accordion-btn-color:var(--bs-body-color);--bs-accordion-btn-bg:var(--bs-accordion-bg);--bs-accordion-btn-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23212529' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m2 5 6 6 6-6'/%3e%3c/svg%3e");--bs-accordion-btn-icon-width:1.25rem;--bs-accordion-btn-icon-transform:rotate(-180deg);--bs-accordion-btn-icon-transition:transform 0.2s ease-in-out;--bs-accordion-btn-active-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23052c65' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m2 5 6 6 6-6'/%3e%3c/svg%3e");--bs-accordion-btn-focus-box-shadow:0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-accordion-body-padding-x:1.25rem;--bs-accordion-body-padding-y:1rem;--bs-accordion-active-color:var(--bs-primary-text-emphasis);--bs-accordion-active-bg:var(--bs-primary-bg-subtle)}.accordion-button{position:relative;display:flex;align-items:center;width:100%;padding:var(--bs-accordion-btn-padding-y) var(--bs-accordion-btn-padding-x);font-size:1rem;color:var(--bs-accordion-btn-color);text-align:left;background-color:var(--bs-accordion-btn-bg);border:0;border-radius:0;overflow-anchor:none;transition:var(--bs-accordion-transition)}@media (prefers-reduced-motion:reduce){.accordion-button{transition:none}}.accordion-button:not(.collapsed){color:var(--bs-accordion-active-color);background-color:var(--bs-accordion-active-bg);box-shadow:inset 0 calc(-1 * var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color)}.accordion-button:not(.collapsed)::after{background-image:var(--bs-accordion-btn-active-icon);transform:var(--bs-accordion-btn-icon-transform)}.accordion-button::after{flex-shrink:0;width:var(--bs-accordion-btn-icon-width);height:var(--bs-accordion-btn-icon-width);margin-left:auto;content:"";background-image:var(--bs-accordion-btn-icon);background-repeat:no-repeat;background-size:var(--bs-accordion-btn-icon-width);transition:var(--bs-accordion-btn-icon-transition)}@media (prefers-reduced-motion:reduce){.accordion-button::after{transition:none}}.accordion-button:hover{z-index:2}.accordion-button:focus{z-index:3;outline:0;box-shadow:var(--bs-accordion-btn-focus-box-shadow)}.accordion-header{margin-bottom:0}.accordion-item{color:var(--bs-accordion-color);background-color:var(--bs-accordion-bg);border:var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)}.accordion-item:first-of-type{border-top-left-radius:var(--bs-accordion-border-radius);border-top-right-radius:var(--bs-accordion-border-radius)}.accordion-item:first-of-type>.accordion-header .accordion-button{border-top-left-radius:var(--bs-accordion-inner-border-radius);border-top-right-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:not(:first-of-type){border-top:0}.accordion-item:last-of-type{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-item:last-of-type>.accordion-header .accordion-button.collapsed{border-bottom-right-radius:var(--bs-accordion-inner-border-radius);border-bottom-left-radius:var(--bs-accordion-inner-border-radius)}.accordion-item:last-of-type>.accordion-collapse{border-bottom-right-radius:var(--bs-accordion-border-radius);border-bottom-left-radius:var(--bs-accordion-border-radius)}.accordion-body{padding:var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x)}.accordion-flush>.accordion-item{border-right:0;border-left:0;border-radius:0}.accordion-flush>.accordion-item:first-child{border-top:0}.accordion-flush>.accordion-item:last-child{border-bottom:0}.accordion-flush>.accordion-item>.accordion-collapse,.accordion-flush>.accordion-item>.accordion-header .accordion-button,.accordion-flush>.accordion-item>.accordion-header .accordion-button.collapsed{border-radius:0}[data-bs-theme=dark] .accordion-button::after{--bs-accordion-btn-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236ea8fe'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708'/%3e%3c/svg%3e");--bs-accordion-btn-active-icon:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%236ea8fe'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708'/%3e%3c/svg%3e")}.breadcrumb{--bs-breadcrumb-padding-x:0;--bs-breadcrumb-padding-y:0;--bs-breadcrumb-margin-bottom:1rem;--bs-breadcrumb-bg: ;--bs-breadcrumb-border-radius: ;--bs-breadcrumb-divider-color:var(--bs-secondary-color);--bs-breadcrumb-item-padding-x:0.5rem;--bs-breadcrumb-item-active-color:var(--bs-secondary-color);display:flex;flex-wrap:wrap;padding:var(--bs-breadcrumb-padding-y) var(--bs-breadcrumb-padding-x);margin-bottom:var(--bs-breadcrumb-margin-bottom);font-size:var(--bs-breadcrumb-font-size);list-style:none;background-color:var(--bs-breadcrumb-bg);border-radius:var(--bs-breadcrumb-border-radius)}.breadcrumb-item+.breadcrumb-item{padding-left:var(--bs-breadcrumb-item-padding-x)}.breadcrumb-item+.breadcrumb-item::before{float:left;padding-right:var(--bs-breadcrumb-item-padding-x);color:var(--bs-breadcrumb-divider-color);content:var(--bs-breadcrumb-divider, "/")}.breadcrumb-item.active{color:var(--bs-breadcrumb-item-active-color)}.pagination{--bs-pagination-padding-x:0.75rem;--bs-pagination-padding-y:0.375rem;--bs-pagination-font-size:1rem;--bs-pagination-color:var(--bs-link-color);--bs-pagination-bg:var(--bs-body-bg);--bs-pagination-border-width:var(--bs-border-width);--bs-pagination-border-color:var(--bs-border-color);--bs-pagination-border-radius:var(--bs-border-radius);--bs-pagination-hover-color:var(--bs-link-hover-color);--bs-pagination-hover-bg:var(--bs-tertiary-bg);--bs-pagination-hover-border-color:var(--bs-border-color);--bs-pagination-focus-color:var(--bs-link-hover-color);--bs-pagination-focus-bg:var(--bs-secondary-bg);--bs-pagination-focus-box-shadow:0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-pagination-active-color:#fff;--bs-pagination-active-bg:#0d6efd;--bs-pagination-active-border-color:#0d6efd;--bs-pagination-disabled-color:var(--bs-secondary-color);--bs-pagination-disabled-bg:var(--bs-secondary-bg);--bs-pagination-disabled-border-color:var(--bs-border-color);display:flex;padding-left:0;list-style:none}.page-link{position:relative;display:block;padding:var(--bs-pagination-padding-y) var(--bs-pagination-padding-x);font-size:var(--bs-pagination-font-size);color:var(--bs-pagination-color);text-decoration:none;background-color:var(--bs-pagination-bg);border:var(--bs-pagination-border-width) solid var(--bs-pagination-border-color);transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}@media (prefers-reduced-motion:reduce){.page-link{transition:none}}.page-link:hover{z-index:2;color:var(--bs-pagination-hover-color);background-color:var(--bs-pagination-hover-bg);border-color:var(--bs-pagination-hover-border-color)}.page-link:focus{z-index:3;color:var(--bs-pagination-focus-color);background-color:var(--bs-pagination-focus-bg);outline:0;box-shadow:var(--bs-pagination-focus-box-shadow)}.active>.page-link,.page-link.active{z-index:3;color:var(--bs-pagination-active-color);background-color:var(--bs-pagination-active-bg);border-color:var(--bs-pagination-active-border-color)}.disabled>.page-link,.page-link.disabled{color:var(--bs-pagination-disabled-color);pointer-events:none;background-color:var(--bs-pagination-disabled-bg);border-color:var(--bs-pagination-disabled-border-color)}.page-item:not(:first-child) .page-link{margin-left:calc(-1 * var(--bs-border-width))}.page-item:first-child .page-link{border-top-left-radius:var(--bs-pagination-border-radius);border-bottom-left-radius:var(--bs-pagination-border-radius)}.page-item:last-child .page-link{border-top-right-radius:var(--bs-pagination-border-radius);border-bottom-right-radius:var(--bs-pagination-border-radius)}.pagination-lg{--bs-pagination-padding-x:1.5rem;--bs-pagination-padding-y:0.75rem;--bs-pagination-font-size:1.25rem;--bs-pagination-border-radius:var(--bs-border-radius-lg)}.pagination-sm{--bs-pagination-padding-x:0.5rem;--bs-pagination-padding-y:0.25rem;--bs-pagination-font-size:0.875rem;--bs-pagination-border-radius:var(--bs-border-radius-sm)}.badge{--bs-badge-padding-x:0.65em;--bs-badge-padding-y:0.35em;--bs-badge-font-size:0.75em;--bs-badge-font-weight:700;--bs-badge-color:#fff;--bs-badge-border-radius:var(--bs-border-radius);display:inline-block;padding:var(--bs-badge-padding-y) var(--bs-badge-padding-x);font-size:var(--bs-badge-font-size);font-weight:var(--bs-badge-font-weight);line-height:1;color:var(--bs-badge-color);text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:var(--bs-badge-border-radius)}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.alert{--bs-alert-bg:transparent;--bs-alert-padding-x:1rem;--bs-alert-padding-y:1rem;--bs-alert-margin-bottom:1rem;--bs-alert-color:inherit;--bs-alert-border-color:transparent;--bs-alert-border:var(--bs-border-width) solid var(--bs-alert-border-color);--bs-alert-border-radius:var(--bs-border-radius);--bs-alert-link-color:inherit;position:relative;padding:var(--bs-alert-padding-y) var(--bs-alert-padding-x);margin-bottom:var(--bs-alert-margin-bottom);color:var(--bs-alert-color);background-color:var(--bs-alert-bg);border:var(--bs-alert-border);border-radius:var(--bs-alert-border-radius)}.alert-heading{color:inherit}.alert-link{font-weight:700;color:var(--bs-alert-link-color)}.alert-dismissible{padding-right:3rem}.alert-dismissible .btn-close{position:absolute;top:0;right:0;z-index:2;padding:1.25rem 1rem}.alert-primary{--bs-alert-color:var(--bs-primary-text-emphasis);--bs-alert-bg:var(--bs-primary-bg-subtle);--bs-alert-border-color:var(--bs-primary-border-subtle);--bs-alert-link-color:var(--bs-primary-text-emphasis)}.alert-secondary{--bs-alert-color:var(--bs-secondary-text-emphasis);--bs-alert-bg:var(--bs-secondary-bg-subtle);--bs-alert-border-color:var(--bs-secondary-border-subtle);--bs-alert-link-color:var(--bs-secondary-text-emphasis)}.alert-success{--bs-alert-color:var(--bs-success-text-emphasis);--bs-alert-bg:var(--bs-success-bg-subtle);--bs-alert-border-color:var(--bs-success-border-subtle);--bs-alert-link-color:var(--bs-success-text-emphasis)}.alert-info{--bs-alert-color:var(--bs-info-text-emphasis);--bs-alert-bg:var(--bs-info-bg-subtle);--bs-alert-border-color:var(--bs-info-border-subtle);--bs-alert-link-color:var(--bs-info-text-emphasis)}.alert-warning{--bs-alert-color:var(--bs-warning-text-emphasis);--bs-alert-bg:var(--bs-warning-bg-subtle);--bs-alert-border-color:var(--bs-warning-border-subtle);--bs-alert-link-color:var(--bs-warning-text-emphasis)}.alert-danger{--bs-alert-color:var(--bs-danger-text-emphasis);--bs-alert-bg:var(--bs-danger-bg-subtle);--bs-alert-border-color:var(--bs-danger-border-subtle);--bs-alert-link-color:var(--bs-danger-text-emphasis)}.alert-light{--bs-alert-color:var(--bs-light-text-emphasis);--bs-alert-bg:var(--bs-light-bg-subtle);--bs-alert-border-color:var(--bs-light-border-subtle);--bs-alert-link-color:var(--bs-light-text-emphasis)}.alert-dark{--bs-alert-color:var(--bs-dark-text-emphasis);--bs-alert-bg:var(--bs-dark-bg-subtle);--bs-alert-border-color:var(--bs-dark-border-subtle);--bs-alert-link-color:var(--bs-dark-text-emphasis)}@keyframes progress-bar-stripes{0%{background-position-x:var(--bs-progress-height)}}.progress,.progress-stacked{--bs-progress-height:1rem;--bs-progress-font-size:0.75rem;--bs-progress-bg:var(--bs-secondary-bg);--bs-progress-border-radius:var(--bs-border-radius);--bs-progress-box-shadow:var(--bs-box-shadow-inset);--bs-progress-bar-color:#fff;--bs-progress-bar-bg:#0d6efd;--bs-progress-bar-transition:width 0.6s ease;display:flex;height:var(--bs-progress-height);overflow:hidden;font-size:var(--bs-progress-font-size);background-color:var(--bs-progress-bg);border-radius:var(--bs-progress-border-radius)}.progress-bar{display:flex;flex-direction:column;justify-content:center;overflow:hidden;color:var(--bs-progress-bar-color);text-align:center;white-space:nowrap;background-color:var(--bs-progress-bar-bg);transition:var(--bs-progress-bar-transition)}@media (prefers-reduced-motion:reduce){.progress-bar{transition:none}}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:var(--bs-progress-height) var(--bs-progress-height)}.progress-stacked>.progress{overflow:visible}.progress-stacked>.progress>.progress-bar{width:100%}.progress-bar-animated{animation:1s linear infinite progress-bar-stripes}@media (prefers-reduced-motion:reduce){.progress-bar-animated{animation:none}}.list-group{--bs-list-group-color:var(--bs-body-color);--bs-list-group-bg:var(--bs-body-bg);--bs-list-group-border-color:var(--bs-border-color);--bs-list-group-border-width:var(--bs-border-width);--bs-list-group-border-radius:var(--bs-border-radius);--bs-list-group-item-padding-x:1rem;--bs-list-group-item-padding-y:0.5rem;--bs-list-group-action-color:var(--bs-secondary-color);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-tertiary-bg);--bs-list-group-action-active-color:var(--bs-body-color);--bs-list-group-action-active-bg:var(--bs-secondary-bg);--bs-list-group-disabled-color:var(--bs-secondary-color);--bs-list-group-disabled-bg:var(--bs-body-bg);--bs-list-group-active-color:#fff;--bs-list-group-active-bg:#0d6efd;--bs-list-group-active-border-color:#0d6efd;display:flex;flex-direction:column;padding-left:0;margin-bottom:0;border-radius:var(--bs-list-group-border-radius)}.list-group-numbered{list-style-type:none;counter-reset:section}.list-group-numbered>.list-group-item::before{content:counters(section, ".") ". ";counter-increment:section}.list-group-item{position:relative;display:block;padding:var(--bs-list-group-item-padding-y) var(--bs-list-group-item-padding-x);color:var(--bs-list-group-color);text-decoration:none;background-color:var(--bs-list-group-bg);border:var(--bs-list-group-border-width) solid var(--bs-list-group-border-color)}.list-group-item:first-child{border-top-left-radius:inherit;border-top-right-radius:inherit}.list-group-item:last-child{border-bottom-right-radius:inherit;border-bottom-left-radius:inherit}.list-group-item.disabled,.list-group-item:disabled{color:var(--bs-list-group-disabled-color);pointer-events:none;background-color:var(--bs-list-group-disabled-bg)}.list-group-item.active{z-index:2;color:var(--bs-list-group-active-color);background-color:var(--bs-list-group-active-bg);border-color:var(--bs-list-group-active-border-color)}.list-group-item+.list-group-item{border-top-width:0}.list-group-item+.list-group-item.active{margin-top:calc(-1 * var(--bs-list-group-border-width));border-top-width:var(--bs-list-group-border-width)}.list-group-item-action{width:100%;color:var(--bs-list-group-action-color);text-align:inherit}.list-group-item-action:not(.active):focus,.list-group-item-action:not(.active):hover{z-index:1;color:var(--bs-list-group-action-hover-color);text-decoration:none;background-color:var(--bs-list-group-action-hover-bg)}.list-group-item-action:not(.active):active{color:var(--bs-list-group-action-active-color);background-color:var(--bs-list-group-action-active-bg)}.list-group-horizontal{flex-direction:row}.list-group-horizontal>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal>.list-group-item.active{margin-top:0}.list-group-horizontal>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}@media (min-width:576px){.list-group-horizontal-sm{flex-direction:row}.list-group-horizontal-sm>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-sm>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-sm>.list-group-item.active{margin-top:0}.list-group-horizontal-sm>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-sm>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:768px){.list-group-horizontal-md{flex-direction:row}.list-group-horizontal-md>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-md>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-md>.list-group-item.active{margin-top:0}.list-group-horizontal-md>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-md>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:992px){.list-group-horizontal-lg{flex-direction:row}.list-group-horizontal-lg>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-lg>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-lg>.list-group-item.active{margin-top:0}.list-group-horizontal-lg>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-lg>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:1200px){.list-group-horizontal-xl{flex-direction:row}.list-group-horizontal-xl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xl>.list-group-item.active{margin-top:0}.list-group-horizontal-xl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}@media (min-width:1400px){.list-group-horizontal-xxl{flex-direction:row}.list-group-horizontal-xxl>.list-group-item:first-child:not(:last-child){border-bottom-left-radius:var(--bs-list-group-border-radius);border-top-right-radius:0}.list-group-horizontal-xxl>.list-group-item:last-child:not(:first-child){border-top-right-radius:var(--bs-list-group-border-radius);border-bottom-left-radius:0}.list-group-horizontal-xxl>.list-group-item.active{margin-top:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item{border-top-width:var(--bs-list-group-border-width);border-left-width:0}.list-group-horizontal-xxl>.list-group-item+.list-group-item.active{margin-left:calc(-1 * var(--bs-list-group-border-width));border-left-width:var(--bs-list-group-border-width)}}.list-group-flush{border-radius:0}.list-group-flush>.list-group-item{border-width:0 0 var(--bs-list-group-border-width)}.list-group-flush>.list-group-item:last-child{border-bottom-width:0}.list-group-item-primary{--bs-list-group-color:var(--bs-primary-text-emphasis);--bs-list-group-bg:var(--bs-primary-bg-subtle);--bs-list-group-border-color:var(--bs-primary-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-primary-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-primary-border-subtle);--bs-list-group-active-color:var(--bs-primary-bg-subtle);--bs-list-group-active-bg:var(--bs-primary-text-emphasis);--bs-list-group-active-border-color:var(--bs-primary-text-emphasis)}.list-group-item-secondary{--bs-list-group-color:var(--bs-secondary-text-emphasis);--bs-list-group-bg:var(--bs-secondary-bg-subtle);--bs-list-group-border-color:var(--bs-secondary-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-secondary-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-secondary-border-subtle);--bs-list-group-active-color:var(--bs-secondary-bg-subtle);--bs-list-group-active-bg:var(--bs-secondary-text-emphasis);--bs-list-group-active-border-color:var(--bs-secondary-text-emphasis)}.list-group-item-success{--bs-list-group-color:var(--bs-success-text-emphasis);--bs-list-group-bg:var(--bs-success-bg-subtle);--bs-list-group-border-color:var(--bs-success-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-success-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-success-border-subtle);--bs-list-group-active-color:var(--bs-success-bg-subtle);--bs-list-group-active-bg:var(--bs-success-text-emphasis);--bs-list-group-active-border-color:var(--bs-success-text-emphasis)}.list-group-item-info{--bs-list-group-color:var(--bs-info-text-emphasis);--bs-list-group-bg:var(--bs-info-bg-subtle);--bs-list-group-border-color:var(--bs-info-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-info-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-info-border-subtle);--bs-list-group-active-color:var(--bs-info-bg-subtle);--bs-list-group-active-bg:var(--bs-info-text-emphasis);--bs-list-group-active-border-color:var(--bs-info-text-emphasis)}.list-group-item-warning{--bs-list-group-color:var(--bs-warning-text-emphasis);--bs-list-group-bg:var(--bs-warning-bg-subtle);--bs-list-group-border-color:var(--bs-warning-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-warning-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-warning-border-subtle);--bs-list-group-active-color:var(--bs-warning-bg-subtle);--bs-list-group-active-bg:var(--bs-warning-text-emphasis);--bs-list-group-active-border-color:var(--bs-warning-text-emphasis)}.list-group-item-danger{--bs-list-group-color:var(--bs-danger-text-emphasis);--bs-list-group-bg:var(--bs-danger-bg-subtle);--bs-list-group-border-color:var(--bs-danger-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-danger-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-danger-border-subtle);--bs-list-group-active-color:var(--bs-danger-bg-subtle);--bs-list-group-active-bg:var(--bs-danger-text-emphasis);--bs-list-group-active-border-color:var(--bs-danger-text-emphasis)}.list-group-item-light{--bs-list-group-color:var(--bs-light-text-emphasis);--bs-list-group-bg:var(--bs-light-bg-subtle);--bs-list-group-border-color:var(--bs-light-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-light-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-light-border-subtle);--bs-list-group-active-color:var(--bs-light-bg-subtle);--bs-list-group-active-bg:var(--bs-light-text-emphasis);--bs-list-group-active-border-color:var(--bs-light-text-emphasis)}.list-group-item-dark{--bs-list-group-color:var(--bs-dark-text-emphasis);--bs-list-group-bg:var(--bs-dark-bg-subtle);--bs-list-group-border-color:var(--bs-dark-border-subtle);--bs-list-group-action-hover-color:var(--bs-emphasis-color);--bs-list-group-action-hover-bg:var(--bs-dark-border-subtle);--bs-list-group-action-active-color:var(--bs-emphasis-color);--bs-list-group-action-active-bg:var(--bs-dark-border-subtle);--bs-list-group-active-color:var(--bs-dark-bg-subtle);--bs-list-group-active-bg:var(--bs-dark-text-emphasis);--bs-list-group-active-border-color:var(--bs-dark-text-emphasis)}.btn-close{--bs-btn-close-color:#000;--bs-btn-close-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414'/%3e%3c/svg%3e");--bs-btn-close-opacity:0.5;--bs-btn-close-hover-opacity:0.75;--bs-btn-close-focus-shadow:0 0 0 0.25rem rgba(13, 110, 253, 0.25);--bs-btn-close-focus-opacity:1;--bs-btn-close-disabled-opacity:0.25;box-sizing:content-box;width:1em;height:1em;padding:.25em .25em;color:var(--bs-btn-close-color);background:transparent var(--bs-btn-close-bg) center/1em auto no-repeat;filter:var(--bs-btn-close-filter);border:0;border-radius:.375rem;opacity:var(--bs-btn-close-opacity)}.btn-close:hover{color:var(--bs-btn-close-color);text-decoration:none;opacity:var(--bs-btn-close-hover-opacity)}.btn-close:focus{outline:0;box-shadow:var(--bs-btn-close-focus-shadow);opacity:var(--bs-btn-close-focus-opacity)}.btn-close.disabled,.btn-close:disabled{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;opacity:var(--bs-btn-close-disabled-opacity)}.btn-close-white{--bs-btn-close-filter:invert(1) grayscale(100%) brightness(200%)}:root,[data-bs-theme=light]{--bs-btn-close-filter: }[data-bs-theme=dark]{--bs-btn-close-filter:invert(1) grayscale(100%) brightness(200%)}.toast{--bs-toast-zindex:1090;--bs-toast-padding-x:0.75rem;--bs-toast-padding-y:0.5rem;--bs-toast-spacing:1.5rem;--bs-toast-max-width:350px;--bs-toast-font-size:0.875rem;--bs-toast-color: ;--bs-toast-bg:rgba(var(--bs-body-bg-rgb), 0.85);--bs-toast-border-width:var(--bs-border-width);--bs-toast-border-color:var(--bs-border-color-translucent);--bs-toast-border-radius:var(--bs-border-radius);--bs-toast-box-shadow:var(--bs-box-shadow);--bs-toast-header-color:var(--bs-secondary-color);--bs-toast-header-bg:rgba(var(--bs-body-bg-rgb), 0.85);--bs-toast-header-border-color:var(--bs-border-color-translucent);width:var(--bs-toast-max-width);max-width:100%;font-size:var(--bs-toast-font-size);color:var(--bs-toast-color);pointer-events:auto;background-color:var(--bs-toast-bg);background-clip:padding-box;border:var(--bs-toast-border-width) solid var(--bs-toast-border-color);box-shadow:var(--bs-toast-box-shadow);border-radius:var(--bs-toast-border-radius)}.toast.showing{opacity:0}.toast:not(.show){display:none}.toast-container{--bs-toast-zindex:1090;position:absolute;z-index:var(--bs-toast-zindex);width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:100%;pointer-events:none}.toast-container>:not(:last-child){margin-bottom:var(--bs-toast-spacing)}.toast-header{display:flex;align-items:center;padding:var(--bs-toast-padding-y) var(--bs-toast-padding-x);color:var(--bs-toast-header-color);background-color:var(--bs-toast-header-bg);background-clip:padding-box;border-bottom:var(--bs-toast-border-width) solid var(--bs-toast-header-border-color);border-top-left-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width));border-top-right-radius:calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width))}.toast-header .btn-close{margin-right:calc(-.5 * var(--bs-toast-padding-x));margin-left:var(--bs-toast-padding-x)}.toast-body{padding:var(--bs-toast-padding-x);word-wrap:break-word}.modal{--bs-modal-zindex:1055;--bs-modal-width:500px;--bs-modal-padding:1rem;--bs-modal-margin:0.5rem;--bs-modal-color:var(--bs-body-color);--bs-modal-bg:var(--bs-body-bg);--bs-modal-border-color:var(--bs-border-color-translucent);--bs-modal-border-width:var(--bs-border-width);--bs-modal-border-radius:var(--bs-border-radius-lg);--bs-modal-box-shadow:var(--bs-box-shadow-sm);--bs-modal-inner-border-radius:calc(var(--bs-border-radius-lg) - (var(--bs-border-width)));--bs-modal-header-padding-x:1rem;--bs-modal-header-padding-y:1rem;--bs-modal-header-padding:1rem 1rem;--bs-modal-header-border-color:var(--bs-border-color);--bs-modal-header-border-width:var(--bs-border-width);--bs-modal-title-line-height:1.5;--bs-modal-footer-gap:0.5rem;--bs-modal-footer-bg: ;--bs-modal-footer-border-color:var(--bs-border-color);--bs-modal-footer-border-width:var(--bs-border-width);position:fixed;top:0;left:0;z-index:var(--bs-modal-zindex);display:none;width:100%;height:100%;overflow-x:hidden;overflow-y:auto;outline:0}.modal-dialog{position:relative;width:auto;margin:var(--bs-modal-margin);pointer-events:none}.modal.fade .modal-dialog{transform:translate(0,-50px);transition:transform .3s ease-out}@media (prefers-reduced-motion:reduce){.modal.fade .modal-dialog{transition:none}}.modal.show .modal-dialog{transform:none}.modal.modal-static .modal-dialog{transform:scale(1.02)}.modal-dialog-scrollable{height:calc(100% - var(--bs-modal-margin) * 2)}.modal-dialog-scrollable .modal-content{max-height:100%;overflow:hidden}.modal-dialog-scrollable .modal-body{overflow-y:auto}.modal-dialog-centered{display:flex;align-items:center;min-height:calc(100% - var(--bs-modal-margin) * 2)}.modal-content{position:relative;display:flex;flex-direction:column;width:100%;color:var(--bs-modal-color);pointer-events:auto;background-color:var(--bs-modal-bg);background-clip:padding-box;border:var(--bs-modal-border-width) solid var(--bs-modal-border-color);border-radius:var(--bs-modal-border-radius);outline:0}.modal-backdrop{--bs-backdrop-zindex:1050;--bs-backdrop-bg:#000;--bs-backdrop-opacity:0.5;position:fixed;top:0;left:0;z-index:var(--bs-backdrop-zindex);width:100vw;height:100vh;background-color:var(--bs-backdrop-bg)}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:var(--bs-backdrop-opacity)}.modal-header{display:flex;flex-shrink:0;align-items:center;padding:var(--bs-modal-header-padding);border-bottom:var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color);border-top-left-radius:var(--bs-modal-inner-border-radius);border-top-right-radius:var(--bs-modal-inner-border-radius)}.modal-header .btn-close{padding:calc(var(--bs-modal-header-padding-y) * .5) calc(var(--bs-modal-header-padding-x) * .5);margin-top:calc(-.5 * var(--bs-modal-header-padding-y));margin-right:calc(-.5 * var(--bs-modal-header-padding-x));margin-bottom:calc(-.5 * var(--bs-modal-header-padding-y));margin-left:auto}.modal-title{margin-bottom:0;line-height:var(--bs-modal-title-line-height)}.modal-body{position:relative;flex:1 1 auto;padding:var(--bs-modal-padding)}.modal-footer{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap) * .5);background-color:var(--bs-modal-footer-bg);border-top:var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color);border-bottom-right-radius:var(--bs-modal-inner-border-radius);border-bottom-left-radius:var(--bs-modal-inner-border-radius)}.modal-footer>*{margin:calc(var(--bs-modal-footer-gap) * .5)}@media (min-width:576px){.modal{--bs-modal-margin:1.75rem;--bs-modal-box-shadow:var(--bs-box-shadow)}.modal-dialog{max-width:var(--bs-modal-width);margin-right:auto;margin-left:auto}.modal-sm{--bs-modal-width:300px}}@media (min-width:992px){.modal-lg,.modal-xl{--bs-modal-width:800px}}@media (min-width:1200px){.modal-xl{--bs-modal-width:1140px}}.modal-fullscreen{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen .modal-footer,.modal-fullscreen .modal-header{border-radius:0}.modal-fullscreen .modal-body{overflow-y:auto}@media (max-width:575.98px){.modal-fullscreen-sm-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-sm-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-sm-down .modal-footer,.modal-fullscreen-sm-down .modal-header{border-radius:0}.modal-fullscreen-sm-down .modal-body{overflow-y:auto}}@media (max-width:767.98px){.modal-fullscreen-md-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-md-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-md-down .modal-footer,.modal-fullscreen-md-down .modal-header{border-radius:0}.modal-fullscreen-md-down .modal-body{overflow-y:auto}}@media (max-width:991.98px){.modal-fullscreen-lg-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-lg-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-lg-down .modal-footer,.modal-fullscreen-lg-down .modal-header{border-radius:0}.modal-fullscreen-lg-down .modal-body{overflow-y:auto}}@media (max-width:1199.98px){.modal-fullscreen-xl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xl-down .modal-footer,.modal-fullscreen-xl-down .modal-header{border-radius:0}.modal-fullscreen-xl-down .modal-body{overflow-y:auto}}@media (max-width:1399.98px){.modal-fullscreen-xxl-down{width:100vw;max-width:none;height:100%;margin:0}.modal-fullscreen-xxl-down .modal-content{height:100%;border:0;border-radius:0}.modal-fullscreen-xxl-down .modal-footer,.modal-fullscreen-xxl-down .modal-header{border-radius:0}.modal-fullscreen-xxl-down .modal-body{overflow-y:auto}}.tooltip{--bs-tooltip-zindex:1080;--bs-tooltip-max-width:200px;--bs-tooltip-padding-x:0.5rem;--bs-tooltip-padding-y:0.25rem;--bs-tooltip-margin: ;--bs-tooltip-font-size:0.875rem;--bs-tooltip-color:var(--bs-body-bg);--bs-tooltip-bg:var(--bs-emphasis-color);--bs-tooltip-border-radius:var(--bs-border-radius);--bs-tooltip-opacity:0.9;--bs-tooltip-arrow-width:0.8rem;--bs-tooltip-arrow-height:0.4rem;z-index:var(--bs-tooltip-zindex);display:block;margin:var(--bs-tooltip-margin);font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-tooltip-font-size);word-wrap:break-word;opacity:0}.tooltip.show{opacity:var(--bs-tooltip-opacity)}.tooltip .tooltip-arrow{display:block;width:var(--bs-tooltip-arrow-width);height:var(--bs-tooltip-arrow-height)}.tooltip .tooltip-arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow,.bs-tooltip-top .tooltip-arrow{bottom:calc(-1 * var(--bs-tooltip-arrow-height))}.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before,.bs-tooltip-top .tooltip-arrow::before{top:-1px;border-width:var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * .5) 0;border-top-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow,.bs-tooltip-end .tooltip-arrow{left:calc(-1 * var(--bs-tooltip-arrow-height));width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before,.bs-tooltip-end .tooltip-arrow::before{right:-1px;border-width:calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * .5) 0;border-right-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow,.bs-tooltip-bottom .tooltip-arrow{top:calc(-1 * var(--bs-tooltip-arrow-height))}.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before,.bs-tooltip-bottom .tooltip-arrow::before{bottom:-1px;border-width:0 calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height);border-bottom-color:var(--bs-tooltip-bg)}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow,.bs-tooltip-start .tooltip-arrow{right:calc(-1 * var(--bs-tooltip-arrow-height));width:var(--bs-tooltip-arrow-height);height:var(--bs-tooltip-arrow-width)}.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before,.bs-tooltip-start .tooltip-arrow::before{left:-1px;border-width:calc(var(--bs-tooltip-arrow-width) * .5) 0 calc(var(--bs-tooltip-arrow-width) * .5) var(--bs-tooltip-arrow-height);border-left-color:var(--bs-tooltip-bg)}.tooltip-inner{max-width:var(--bs-tooltip-max-width);padding:var(--bs-tooltip-padding-y) var(--bs-tooltip-padding-x);color:var(--bs-tooltip-color);text-align:center;background-color:var(--bs-tooltip-bg);border-radius:var(--bs-tooltip-border-radius)}.popover{--bs-popover-zindex:1070;--bs-popover-max-width:276px;--bs-popover-font-size:0.875rem;--bs-popover-bg:var(--bs-body-bg);--bs-popover-border-width:var(--bs-border-width);--bs-popover-border-color:var(--bs-border-color-translucent);--bs-popover-border-radius:var(--bs-border-radius-lg);--bs-popover-inner-border-radius:calc(var(--bs-border-radius-lg) - var(--bs-border-width));--bs-popover-box-shadow:var(--bs-box-shadow);--bs-popover-header-padding-x:1rem;--bs-popover-header-padding-y:0.5rem;--bs-popover-header-font-size:1rem;--bs-popover-header-color:inherit;--bs-popover-header-bg:var(--bs-secondary-bg);--bs-popover-body-padding-x:1rem;--bs-popover-body-padding-y:1rem;--bs-popover-body-color:var(--bs-body-color);--bs-popover-arrow-width:1rem;--bs-popover-arrow-height:0.5rem;--bs-popover-arrow-border:var(--bs-popover-border-color);z-index:var(--bs-popover-zindex);display:block;max-width:var(--bs-popover-max-width);font-family:var(--bs-font-sans-serif);font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;white-space:normal;word-spacing:normal;line-break:auto;font-size:var(--bs-popover-font-size);word-wrap:break-word;background-color:var(--bs-popover-bg);background-clip:padding-box;border:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-radius:var(--bs-popover-border-radius)}.popover .popover-arrow{display:block;width:var(--bs-popover-arrow-width);height:var(--bs-popover-arrow-height)}.popover .popover-arrow::after,.popover .popover-arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid;border-width:0}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow,.bs-popover-top>.popover-arrow{bottom:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::after,.bs-popover-top>.popover-arrow::before{border-width:var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * .5) 0}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::before,.bs-popover-top>.popover-arrow::before{bottom:0;border-top-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=top]>.popover-arrow::after,.bs-popover-top>.popover-arrow::after{bottom:var(--bs-popover-border-width);border-top-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow,.bs-popover-end>.popover-arrow{left:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::after,.bs-popover-end>.popover-arrow::before{border-width:calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * .5) 0}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::before,.bs-popover-end>.popover-arrow::before{left:0;border-right-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=right]>.popover-arrow::after,.bs-popover-end>.popover-arrow::after{left:var(--bs-popover-border-width);border-right-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow,.bs-popover-bottom>.popover-arrow{top:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width))}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::after,.bs-popover-bottom>.popover-arrow::before{border-width:0 calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::before,.bs-popover-bottom>.popover-arrow::before{top:0;border-bottom-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=bottom]>.popover-arrow::after,.bs-popover-bottom>.popover-arrow::after{top:var(--bs-popover-border-width);border-bottom-color:var(--bs-popover-bg)}.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:var(--bs-popover-arrow-width);margin-left:calc(-.5 * var(--bs-popover-arrow-width));content:"";border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-header-bg)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow,.bs-popover-start>.popover-arrow{right:calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width));width:var(--bs-popover-arrow-height);height:var(--bs-popover-arrow-width)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after,.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::after,.bs-popover-start>.popover-arrow::before{border-width:calc(var(--bs-popover-arrow-width) * .5) 0 calc(var(--bs-popover-arrow-width) * .5) var(--bs-popover-arrow-height)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::before,.bs-popover-start>.popover-arrow::before{right:0;border-left-color:var(--bs-popover-arrow-border)}.bs-popover-auto[data-popper-placement^=left]>.popover-arrow::after,.bs-popover-start>.popover-arrow::after{right:var(--bs-popover-border-width);border-left-color:var(--bs-popover-bg)}.popover-header{padding:var(--bs-popover-header-padding-y) var(--bs-popover-header-padding-x);margin-bottom:0;font-size:var(--bs-popover-header-font-size);color:var(--bs-popover-header-color);background-color:var(--bs-popover-header-bg);border-bottom:var(--bs-popover-border-width) solid var(--bs-popover-border-color);border-top-left-radius:var(--bs-popover-inner-border-radius);border-top-right-radius:var(--bs-popover-inner-border-radius)}.popover-header:empty{display:none}.popover-body{padding:var(--bs-popover-body-padding-y) var(--bs-popover-body-padding-x);color:var(--bs-popover-body-color)}.carousel{position:relative}.carousel.pointer-event{touch-action:pan-y}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner::after{display:block;clear:both;content:""}.carousel-item{position:relative;display:none;float:left;width:100%;margin-right:-100%;-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:transform .6s ease-in-out}@media (prefers-reduced-motion:reduce){.carousel-item{transition:none}}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.active.carousel-item-end,.carousel-item-next:not(.carousel-item-start){transform:translateX(100%)}.active.carousel-item-start,.carousel-item-prev:not(.carousel-item-end){transform:translateX(-100%)}.carousel-fade .carousel-item{opacity:0;transition-property:opacity;transform:none}.carousel-fade .carousel-item-next.carousel-item-start,.carousel-fade .carousel-item-prev.carousel-item-end,.carousel-fade .carousel-item.active{z-index:1;opacity:1}.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{z-index:0;opacity:0;transition:opacity 0s .6s}@media (prefers-reduced-motion:reduce){.carousel-fade .active.carousel-item-end,.carousel-fade .active.carousel-item-start{transition:none}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;z-index:1;display:flex;align-items:center;justify-content:center;width:15%;padding:0;color:#fff;text-align:center;background:0 0;filter:var(--bs-carousel-control-icon-filter);border:0;opacity:.5;transition:opacity .15s ease}@media (prefers-reduced-motion:reduce){.carousel-control-next,.carousel-control-prev{transition:none}}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:2rem;height:2rem;background-repeat:no-repeat;background-position:50%;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0'/%3e%3c/svg%3e")}.carousel-control-next-icon{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708'/%3e%3c/svg%3e")}.carousel-indicators{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;justify-content:center;padding:0;margin-right:15%;margin-bottom:1rem;margin-left:15%}.carousel-indicators [data-bs-target]{box-sizing:content-box;flex:0 1 auto;width:30px;height:3px;padding:0;margin-right:3px;margin-left:3px;text-indent:-999px;cursor:pointer;background-color:var(--bs-carousel-indicator-active-bg);background-clip:padding-box;border:0;border-top:10px solid transparent;border-bottom:10px solid transparent;opacity:.5;transition:opacity .6s ease}@media (prefers-reduced-motion:reduce){.carousel-indicators [data-bs-target]{transition:none}}.carousel-indicators .active{opacity:1}.carousel-caption{position:absolute;right:15%;bottom:1.25rem;left:15%;padding-top:1.25rem;padding-bottom:1.25rem;color:var(--bs-carousel-caption-color);text-align:center}.carousel-dark{--bs-carousel-indicator-active-bg:#000;--bs-carousel-caption-color:#000;--bs-carousel-control-icon-filter:invert(1) grayscale(100)}:root,[data-bs-theme=light]{--bs-carousel-indicator-active-bg:#fff;--bs-carousel-caption-color:#fff;--bs-carousel-control-icon-filter: }[data-bs-theme=dark]{--bs-carousel-indicator-active-bg:#000;--bs-carousel-caption-color:#000;--bs-carousel-control-icon-filter:invert(1) grayscale(100)}.spinner-border,.spinner-grow{display:inline-block;width:var(--bs-spinner-width);height:var(--bs-spinner-height);vertical-align:var(--bs-spinner-vertical-align);border-radius:50%;animation:var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name)}@keyframes spinner-border{to{transform:rotate(360deg)}}.spinner-border{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-0.125em;--bs-spinner-border-width:0.25em;--bs-spinner-animation-speed:0.75s;--bs-spinner-animation-name:spinner-border;border:var(--bs-spinner-border-width) solid currentcolor;border-right-color:transparent}.spinner-border-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem;--bs-spinner-border-width:0.2em}@keyframes spinner-grow{0%{transform:scale(0)}50%{opacity:1;transform:none}}.spinner-grow{--bs-spinner-width:2rem;--bs-spinner-height:2rem;--bs-spinner-vertical-align:-0.125em;--bs-spinner-animation-speed:0.75s;--bs-spinner-animation-name:spinner-grow;background-color:currentcolor;opacity:0}.spinner-grow-sm{--bs-spinner-width:1rem;--bs-spinner-height:1rem}@media (prefers-reduced-motion:reduce){.spinner-border,.spinner-grow{--bs-spinner-animation-speed:1.5s}}.offcanvas,.offcanvas-lg,.offcanvas-md,.offcanvas-sm,.offcanvas-xl,.offcanvas-xxl{--bs-offcanvas-zindex:1045;--bs-offcanvas-width:400px;--bs-offcanvas-height:30vh;--bs-offcanvas-padding-x:1rem;--bs-offcanvas-padding-y:1rem;--bs-offcanvas-color:var(--bs-body-color);--bs-offcanvas-bg:var(--bs-body-bg);--bs-offcanvas-border-width:var(--bs-border-width);--bs-offcanvas-border-color:var(--bs-border-color-translucent);--bs-offcanvas-box-shadow:var(--bs-box-shadow-sm);--bs-offcanvas-transition:transform 0.3s ease-in-out;--bs-offcanvas-title-line-height:1.5}@media (max-width:575.98px){.offcanvas-sm{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:575.98px) and (prefers-reduced-motion:reduce){.offcanvas-sm{transition:none}}@media (max-width:575.98px){.offcanvas-sm.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-sm.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-sm.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-sm.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-sm.show:not(.hiding),.offcanvas-sm.showing{transform:none}.offcanvas-sm.hiding,.offcanvas-sm.show,.offcanvas-sm.showing{visibility:visible}}@media (min-width:576px){.offcanvas-sm{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-sm .offcanvas-header{display:none}.offcanvas-sm .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:767.98px){.offcanvas-md{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:767.98px) and (prefers-reduced-motion:reduce){.offcanvas-md{transition:none}}@media (max-width:767.98px){.offcanvas-md.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-md.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-md.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-md.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-md.show:not(.hiding),.offcanvas-md.showing{transform:none}.offcanvas-md.hiding,.offcanvas-md.show,.offcanvas-md.showing{visibility:visible}}@media (min-width:768px){.offcanvas-md{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-md .offcanvas-header{display:none}.offcanvas-md .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:991.98px){.offcanvas-lg{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:991.98px) and (prefers-reduced-motion:reduce){.offcanvas-lg{transition:none}}@media (max-width:991.98px){.offcanvas-lg.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-lg.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-lg.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-lg.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-lg.show:not(.hiding),.offcanvas-lg.showing{transform:none}.offcanvas-lg.hiding,.offcanvas-lg.show,.offcanvas-lg.showing{visibility:visible}}@media (min-width:992px){.offcanvas-lg{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-lg .offcanvas-header{display:none}.offcanvas-lg .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:1199.98px){.offcanvas-xl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:1199.98px) and (prefers-reduced-motion:reduce){.offcanvas-xl{transition:none}}@media (max-width:1199.98px){.offcanvas-xl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-xl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-xl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xl.show:not(.hiding),.offcanvas-xl.showing{transform:none}.offcanvas-xl.hiding,.offcanvas-xl.show,.offcanvas-xl.showing{visibility:visible}}@media (min-width:1200px){.offcanvas-xl{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-xl .offcanvas-header{display:none}.offcanvas-xl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}@media (max-width:1399.98px){.offcanvas-xxl{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}}@media (max-width:1399.98px) and (prefers-reduced-motion:reduce){.offcanvas-xxl{transition:none}}@media (max-width:1399.98px){.offcanvas-xxl.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas-xxl.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas-xxl.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas-xxl.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas-xxl.show:not(.hiding),.offcanvas-xxl.showing{transform:none}.offcanvas-xxl.hiding,.offcanvas-xxl.show,.offcanvas-xxl.showing{visibility:visible}}@media (min-width:1400px){.offcanvas-xxl{--bs-offcanvas-height:auto;--bs-offcanvas-border-width:0;background-color:transparent!important}.offcanvas-xxl .offcanvas-header{display:none}.offcanvas-xxl .offcanvas-body{display:flex;flex-grow:0;padding:0;overflow-y:visible;background-color:transparent!important}}.offcanvas{position:fixed;bottom:0;z-index:var(--bs-offcanvas-zindex);display:flex;flex-direction:column;max-width:100%;color:var(--bs-offcanvas-color);visibility:hidden;background-color:var(--bs-offcanvas-bg);background-clip:padding-box;outline:0;transition:var(--bs-offcanvas-transition)}@media (prefers-reduced-motion:reduce){.offcanvas{transition:none}}.offcanvas.offcanvas-start{top:0;left:0;width:var(--bs-offcanvas-width);border-right:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(-100%)}.offcanvas.offcanvas-end{top:0;right:0;width:var(--bs-offcanvas-width);border-left:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateX(100%)}.offcanvas.offcanvas-top{top:0;right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-bottom:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(-100%)}.offcanvas.offcanvas-bottom{right:0;left:0;height:var(--bs-offcanvas-height);max-height:100%;border-top:var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color);transform:translateY(100%)}.offcanvas.show:not(.hiding),.offcanvas.showing{transform:none}.offcanvas.hiding,.offcanvas.show,.offcanvas.showing{visibility:visible}.offcanvas-backdrop{position:fixed;top:0;left:0;z-index:1040;width:100vw;height:100vh;background-color:#000}.offcanvas-backdrop.fade{opacity:0}.offcanvas-backdrop.show{opacity:.5}.offcanvas-header{display:flex;align-items:center;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x)}.offcanvas-header .btn-close{padding:calc(var(--bs-offcanvas-padding-y) * .5) calc(var(--bs-offcanvas-padding-x) * .5);margin-top:calc(-.5 * var(--bs-offcanvas-padding-y));margin-right:calc(-.5 * var(--bs-offcanvas-padding-x));margin-bottom:calc(-.5 * var(--bs-offcanvas-padding-y));margin-left:auto}.offcanvas-title{margin-bottom:0;line-height:var(--bs-offcanvas-title-line-height)}.offcanvas-body{flex-grow:1;padding:var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);overflow-y:auto}.placeholder{display:inline-block;min-height:1em;vertical-align:middle;cursor:wait;background-color:currentcolor;opacity:.5}.placeholder.btn::before{display:inline-block;content:""}.placeholder-xs{min-height:.6em}.placeholder-sm{min-height:.8em}.placeholder-lg{min-height:1.2em}.placeholder-glow .placeholder{animation:placeholder-glow 2s ease-in-out infinite}@keyframes placeholder-glow{50%{opacity:.2}}.placeholder-wave{-webkit-mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,0.8) 75%,#000 95%);mask-image:linear-gradient(130deg,#000 55%,rgba(0,0,0,0.8) 75%,#000 95%);-webkit-mask-size:200% 100%;mask-size:200% 100%;animation:placeholder-wave 2s linear infinite}@keyframes placeholder-wave{100%{-webkit-mask-position:-200% 0%;mask-position:-200% 0%}}.clearfix::after{display:block;clear:both;content:""}.text-bg-primary{color:#fff!important;background-color:RGBA(var(--bs-primary-rgb),var(--bs-bg-opacity,1))!important}.text-bg-secondary{color:#fff!important;background-color:RGBA(var(--bs-secondary-rgb),var(--bs-bg-opacity,1))!important}.text-bg-success{color:#fff!important;background-color:RGBA(var(--bs-success-rgb),var(--bs-bg-opacity,1))!important}.text-bg-info{color:#000!important;background-color:RGBA(var(--bs-info-rgb),var(--bs-bg-opacity,1))!important}.text-bg-warning{color:#000!important;background-color:RGBA(var(--bs-warning-rgb),var(--bs-bg-opacity,1))!important}.text-bg-danger{color:#fff!important;background-color:RGBA(var(--bs-danger-rgb),var(--bs-bg-opacity,1))!important}.text-bg-light{color:#000!important;background-color:RGBA(var(--bs-light-rgb),var(--bs-bg-opacity,1))!important}.text-bg-dark{color:#fff!important;background-color:RGBA(var(--bs-dark-rgb),var(--bs-bg-opacity,1))!important}.link-primary{color:RGBA(var(--bs-primary-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-primary-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-primary-rgb),var(--bs-link-underline-opacity,1))!important}.link-primary:focus,.link-primary:hover{color:RGBA(10,88,202,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(10,88,202,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(10,88,202,var(--bs-link-underline-opacity,1))!important}.link-secondary{color:RGBA(var(--bs-secondary-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-secondary-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-secondary-rgb),var(--bs-link-underline-opacity,1))!important}.link-secondary:focus,.link-secondary:hover{color:RGBA(86,94,100,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(86,94,100,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(86,94,100,var(--bs-link-underline-opacity,1))!important}.link-success{color:RGBA(var(--bs-success-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-success-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-success-rgb),var(--bs-link-underline-opacity,1))!important}.link-success:focus,.link-success:hover{color:RGBA(20,108,67,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(20,108,67,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(20,108,67,var(--bs-link-underline-opacity,1))!important}.link-info{color:RGBA(var(--bs-info-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-info-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-info-rgb),var(--bs-link-underline-opacity,1))!important}.link-info:focus,.link-info:hover{color:RGBA(61,213,243,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(61,213,243,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(61,213,243,var(--bs-link-underline-opacity,1))!important}.link-warning{color:RGBA(var(--bs-warning-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-warning-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-warning-rgb),var(--bs-link-underline-opacity,1))!important}.link-warning:focus,.link-warning:hover{color:RGBA(255,205,57,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(255,205,57,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(255,205,57,var(--bs-link-underline-opacity,1))!important}.link-danger{color:RGBA(var(--bs-danger-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-danger-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-danger-rgb),var(--bs-link-underline-opacity,1))!important}.link-danger:focus,.link-danger:hover{color:RGBA(176,42,55,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(176,42,55,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(176,42,55,var(--bs-link-underline-opacity,1))!important}.link-light{color:RGBA(var(--bs-light-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-light-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-light-rgb),var(--bs-link-underline-opacity,1))!important}.link-light:focus,.link-light:hover{color:RGBA(249,250,251,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(249,250,251,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(249,250,251,var(--bs-link-underline-opacity,1))!important}.link-dark{color:RGBA(var(--bs-dark-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-dark-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-dark-rgb),var(--bs-link-underline-opacity,1))!important}.link-dark:focus,.link-dark:hover{color:RGBA(26,30,33,var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(26,30,33,var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(26,30,33,var(--bs-link-underline-opacity,1))!important}.link-body-emphasis{color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-opacity,1))!important;-webkit-text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,1))!important}.link-body-emphasis:focus,.link-body-emphasis:hover{color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-opacity,.75))!important;-webkit-text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,0.75))!important;text-decoration-color:RGBA(var(--bs-emphasis-color-rgb),var(--bs-link-underline-opacity,0.75))!important}.focus-ring:focus{outline:0;box-shadow:var(--bs-focus-ring-x,0) var(--bs-focus-ring-y,0) var(--bs-focus-ring-blur,0) var(--bs-focus-ring-width) var(--bs-focus-ring-color)}.icon-link{display:inline-flex;gap:.375rem;align-items:center;-webkit-text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,0.5));text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-opacity,0.5));text-underline-offset:0.25em;-webkit-backface-visibility:hidden;backface-visibility:hidden}.icon-link>.bi{flex-shrink:0;width:1em;height:1em;fill:currentcolor;transition:.2s ease-in-out transform}@media (prefers-reduced-motion:reduce){.icon-link>.bi{transition:none}}.icon-link-hover:focus-visible>.bi,.icon-link-hover:hover>.bi{transform:var(--bs-icon-link-transform,translate3d(.25em,0,0))}.ratio{position:relative;width:100%}.ratio::before{display:block;padding-top:var(--bs-aspect-ratio);content:""}.ratio>*{position:absolute;top:0;left:0;width:100%;height:100%}.ratio-1x1{--bs-aspect-ratio:100%}.ratio-4x3{--bs-aspect-ratio:75%}.ratio-16x9{--bs-aspect-ratio:56.25%}.ratio-21x9{--bs-aspect-ratio:42.8571428571%}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}@media (min-width:576px){.sticky-sm-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-sm-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:768px){.sticky-md-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-md-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:992px){.sticky-lg-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-lg-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:1200px){.sticky-xl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-xl-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}@media (min-width:1400px){.sticky-xxl-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}.sticky-xxl-bottom{position:-webkit-sticky;position:sticky;bottom:0;z-index:1020}}.hstack{display:flex;flex-direction:row;align-items:center;align-self:stretch}.vstack{display:flex;flex:1 1 auto;flex-direction:column;align-self:stretch}.visually-hidden,.visually-hidden-focusable:not(:focus):not(:focus-within){width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.visually-hidden-focusable:not(:focus):not(:focus-within):not(caption),.visually-hidden:not(caption){position:absolute!important}.visually-hidden *,.visually-hidden-focusable:not(:focus):not(:focus-within) *{overflow:hidden!important}.stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vr{display:inline-block;align-self:stretch;width:var(--bs-border-width);min-height:1em;background-color:currentcolor;opacity:.25}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.float-start{float:left!important}.float-end{float:right!important}.float-none{float:none!important}.object-fit-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-none{-o-object-fit:none!important;object-fit:none!important}.opacity-0{opacity:0!important}.opacity-25{opacity:.25!important}.opacity-50{opacity:.5!important}.opacity-75{opacity:.75!important}.opacity-100{opacity:1!important}.overflow-auto{overflow:auto!important}.overflow-hidden{overflow:hidden!important}.overflow-visible{overflow:visible!important}.overflow-scroll{overflow:scroll!important}.overflow-x-auto{overflow-x:auto!important}.overflow-x-hidden{overflow-x:hidden!important}.overflow-x-visible{overflow-x:visible!important}.overflow-x-scroll{overflow-x:scroll!important}.overflow-y-auto{overflow-y:auto!important}.overflow-y-hidden{overflow-y:hidden!important}.overflow-y-visible{overflow-y:visible!important}.overflow-y-scroll{overflow-y:scroll!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-grid{display:grid!important}.d-inline-grid{display:inline-grid!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:flex!important}.d-inline-flex{display:inline-flex!important}.d-none{display:none!important}.shadow{box-shadow:var(--bs-box-shadow)!important}.shadow-sm{box-shadow:var(--bs-box-shadow-sm)!important}.shadow-lg{box-shadow:var(--bs-box-shadow-lg)!important}.shadow-none{box-shadow:none!important}.focus-ring-primary{--bs-focus-ring-color:rgba(var(--bs-primary-rgb), var(--bs-focus-ring-opacity))}.focus-ring-secondary{--bs-focus-ring-color:rgba(var(--bs-secondary-rgb), var(--bs-focus-ring-opacity))}.focus-ring-success{--bs-focus-ring-color:rgba(var(--bs-success-rgb), var(--bs-focus-ring-opacity))}.focus-ring-info{--bs-focus-ring-color:rgba(var(--bs-info-rgb), var(--bs-focus-ring-opacity))}.focus-ring-warning{--bs-focus-ring-color:rgba(var(--bs-warning-rgb), var(--bs-focus-ring-opacity))}.focus-ring-danger{--bs-focus-ring-color:rgba(var(--bs-danger-rgb), var(--bs-focus-ring-opacity))}.focus-ring-light{--bs-focus-ring-color:rgba(var(--bs-light-rgb), var(--bs-focus-ring-opacity))}.focus-ring-dark{--bs-focus-ring-color:rgba(var(--bs-dark-rgb), var(--bs-focus-ring-opacity))}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.top-0{top:0!important}.top-50{top:50%!important}.top-100{top:100%!important}.bottom-0{bottom:0!important}.bottom-50{bottom:50%!important}.bottom-100{bottom:100%!important}.start-0{left:0!important}.start-50{left:50%!important}.start-100{left:100%!important}.end-0{right:0!important}.end-50{right:50%!important}.end-100{right:100%!important}.translate-middle{transform:translate(-50%,-50%)!important}.translate-middle-x{transform:translateX(-50%)!important}.translate-middle-y{transform:translateY(-50%)!important}.border{border:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-0{border:0!important}.border-top{border-top:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-top-0{border-top:0!important}.border-end{border-right:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-end-0{border-right:0!important}.border-bottom{border-bottom:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-bottom-0{border-bottom:0!important}.border-start{border-left:var(--bs-border-width) var(--bs-border-style) var(--bs-border-color)!important}.border-start-0{border-left:0!important}.border-primary{--bs-border-opacity:1;border-color:rgba(var(--bs-primary-rgb),var(--bs-border-opacity))!important}.border-secondary{--bs-border-opacity:1;border-color:rgba(var(--bs-secondary-rgb),var(--bs-border-opacity))!important}.border-success{--bs-border-opacity:1;border-color:rgba(var(--bs-success-rgb),var(--bs-border-opacity))!important}.border-info{--bs-border-opacity:1;border-color:rgba(var(--bs-info-rgb),var(--bs-border-opacity))!important}.border-warning{--bs-border-opacity:1;border-color:rgba(var(--bs-warning-rgb),var(--bs-border-opacity))!important}.border-danger{--bs-border-opacity:1;border-color:rgba(var(--bs-danger-rgb),var(--bs-border-opacity))!important}.border-light{--bs-border-opacity:1;border-color:rgba(var(--bs-light-rgb),var(--bs-border-opacity))!important}.border-dark{--bs-border-opacity:1;border-color:rgba(var(--bs-dark-rgb),var(--bs-border-opacity))!important}.border-black{--bs-border-opacity:1;border-color:rgba(var(--bs-black-rgb),var(--bs-border-opacity))!important}.border-white{--bs-border-opacity:1;border-color:rgba(var(--bs-white-rgb),var(--bs-border-opacity))!important}.border-primary-subtle{border-color:var(--bs-primary-border-subtle)!important}.border-secondary-subtle{border-color:var(--bs-secondary-border-subtle)!important}.border-success-subtle{border-color:var(--bs-success-border-subtle)!important}.border-info-subtle{border-color:var(--bs-info-border-subtle)!important}.border-warning-subtle{border-color:var(--bs-warning-border-subtle)!important}.border-danger-subtle{border-color:var(--bs-danger-border-subtle)!important}.border-light-subtle{border-color:var(--bs-light-border-subtle)!important}.border-dark-subtle{border-color:var(--bs-dark-border-subtle)!important}.border-1{border-width:1px!important}.border-2{border-width:2px!important}.border-3{border-width:3px!important}.border-4{border-width:4px!important}.border-5{border-width:5px!important}.border-opacity-10{--bs-border-opacity:0.1}.border-opacity-25{--bs-border-opacity:0.25}.border-opacity-50{--bs-border-opacity:0.5}.border-opacity-75{--bs-border-opacity:0.75}.border-opacity-100{--bs-border-opacity:1}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.w-auto{width:auto!important}.mw-100{max-width:100%!important}.vw-100{width:100vw!important}.min-vw-100{min-width:100vw!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.h-auto{height:auto!important}.mh-100{max-height:100%!important}.vh-100{height:100vh!important}.min-vh-100{min-height:100vh!important}.flex-fill{flex:1 1 auto!important}.flex-row{flex-direction:row!important}.flex-column{flex-direction:column!important}.flex-row-reverse{flex-direction:row-reverse!important}.flex-column-reverse{flex-direction:column-reverse!important}.flex-grow-0{flex-grow:0!important}.flex-grow-1{flex-grow:1!important}.flex-shrink-0{flex-shrink:0!important}.flex-shrink-1{flex-shrink:1!important}.flex-wrap{flex-wrap:wrap!important}.flex-nowrap{flex-wrap:nowrap!important}.flex-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-start{justify-content:flex-start!important}.justify-content-end{justify-content:flex-end!important}.justify-content-center{justify-content:center!important}.justify-content-between{justify-content:space-between!important}.justify-content-around{justify-content:space-around!important}.justify-content-evenly{justify-content:space-evenly!important}.align-items-start{align-items:flex-start!important}.align-items-end{align-items:flex-end!important}.align-items-center{align-items:center!important}.align-items-baseline{align-items:baseline!important}.align-items-stretch{align-items:stretch!important}.align-content-start{align-content:flex-start!important}.align-content-end{align-content:flex-end!important}.align-content-center{align-content:center!important}.align-content-between{align-content:space-between!important}.align-content-around{align-content:space-around!important}.align-content-stretch{align-content:stretch!important}.align-self-auto{align-self:auto!important}.align-self-start{align-self:flex-start!important}.align-self-end{align-self:flex-end!important}.align-self-center{align-self:center!important}.align-self-baseline{align-self:baseline!important}.align-self-stretch{align-self:stretch!important}.order-first{order:-1!important}.order-0{order:0!important}.order-1{order:1!important}.order-2{order:2!important}.order-3{order:3!important}.order-4{order:4!important}.order-5{order:5!important}.order-last{order:6!important}.m-0{margin:0!important}.m-1{margin:.25rem!important}.m-2{margin:.5rem!important}.m-3{margin:1rem!important}.m-4{margin:1.5rem!important}.m-5{margin:3rem!important}.m-auto{margin:auto!important}.mx-0{margin-right:0!important;margin-left:0!important}.mx-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-3{margin-right:1rem!important;margin-left:1rem!important}.mx-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-5{margin-right:3rem!important;margin-left:3rem!important}.mx-auto{margin-right:auto!important;margin-left:auto!important}.my-0{margin-top:0!important;margin-bottom:0!important}.my-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-0{margin-top:0!important}.mt-1{margin-top:.25rem!important}.mt-2{margin-top:.5rem!important}.mt-3{margin-top:1rem!important}.mt-4{margin-top:1.5rem!important}.mt-5{margin-top:3rem!important}.mt-auto{margin-top:auto!important}.me-0{margin-right:0!important}.me-1{margin-right:.25rem!important}.me-2{margin-right:.5rem!important}.me-3{margin-right:1rem!important}.me-4{margin-right:1.5rem!important}.me-5{margin-right:3rem!important}.me-auto{margin-right:auto!important}.mb-0{margin-bottom:0!important}.mb-1{margin-bottom:.25rem!important}.mb-2{margin-bottom:.5rem!important}.mb-3{margin-bottom:1rem!important}.mb-4{margin-bottom:1.5rem!important}.mb-5{margin-bottom:3rem!important}.mb-auto{margin-bottom:auto!important}.ms-0{margin-left:0!important}.ms-1{margin-left:.25rem!important}.ms-2{margin-left:.5rem!important}.ms-3{margin-left:1rem!important}.ms-4{margin-left:1.5rem!important}.ms-5{margin-left:3rem!important}.ms-auto{margin-left:auto!important}.p-0{padding:0!important}.p-1{padding:.25rem!important}.p-2{padding:.5rem!important}.p-3{padding:1rem!important}.p-4{padding:1.5rem!important}.p-5{padding:3rem!important}.px-0{padding-right:0!important;padding-left:0!important}.px-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-3{padding-right:1rem!important;padding-left:1rem!important}.px-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-5{padding-right:3rem!important;padding-left:3rem!important}.py-0{padding-top:0!important;padding-bottom:0!important}.py-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-0{padding-top:0!important}.pt-1{padding-top:.25rem!important}.pt-2{padding-top:.5rem!important}.pt-3{padding-top:1rem!important}.pt-4{padding-top:1.5rem!important}.pt-5{padding-top:3rem!important}.pe-0{padding-right:0!important}.pe-1{padding-right:.25rem!important}.pe-2{padding-right:.5rem!important}.pe-3{padding-right:1rem!important}.pe-4{padding-right:1.5rem!important}.pe-5{padding-right:3rem!important}.pb-0{padding-bottom:0!important}.pb-1{padding-bottom:.25rem!important}.pb-2{padding-bottom:.5rem!important}.pb-3{padding-bottom:1rem!important}.pb-4{padding-bottom:1.5rem!important}.pb-5{padding-bottom:3rem!important}.ps-0{padding-left:0!important}.ps-1{padding-left:.25rem!important}.ps-2{padding-left:.5rem!important}.ps-3{padding-left:1rem!important}.ps-4{padding-left:1.5rem!important}.ps-5{padding-left:3rem!important}.gap-0{gap:0!important}.gap-1{gap:.25rem!important}.gap-2{gap:.5rem!important}.gap-3{gap:1rem!important}.gap-4{gap:1.5rem!important}.gap-5{gap:3rem!important}.row-gap-0{row-gap:0!important}.row-gap-1{row-gap:.25rem!important}.row-gap-2{row-gap:.5rem!important}.row-gap-3{row-gap:1rem!important}.row-gap-4{row-gap:1.5rem!important}.row-gap-5{row-gap:3rem!important}.column-gap-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.font-monospace{font-family:var(--bs-font-monospace)!important}.fs-1{font-size:calc(1.375rem + 1.5vw)!important}.fs-2{font-size:calc(1.325rem + .9vw)!important}.fs-3{font-size:calc(1.3rem + .6vw)!important}.fs-4{font-size:calc(1.275rem + .3vw)!important}.fs-5{font-size:1.25rem!important}.fs-6{font-size:1rem!important}.fst-italic{font-style:italic!important}.fst-normal{font-style:normal!important}.fw-lighter{font-weight:lighter!important}.fw-light{font-weight:300!important}.fw-normal{font-weight:400!important}.fw-medium{font-weight:500!important}.fw-semibold{font-weight:600!important}.fw-bold{font-weight:700!important}.fw-bolder{font-weight:bolder!important}.lh-1{line-height:1!important}.lh-sm{line-height:1.25!important}.lh-base{line-height:1.5!important}.lh-lg{line-height:2!important}.text-start{text-align:left!important}.text-end{text-align:right!important}.text-center{text-align:center!important}.text-decoration-none{text-decoration:none!important}.text-decoration-underline{text-decoration:underline!important}.text-decoration-line-through{text-decoration:line-through!important}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.text-wrap{white-space:normal!important}.text-nowrap{white-space:nowrap!important}.text-break{word-wrap:break-word!important;word-break:break-word!important}.text-primary{--bs-text-opacity:1;color:rgba(var(--bs-primary-rgb),var(--bs-text-opacity))!important}.text-secondary{--bs-text-opacity:1;color:rgba(var(--bs-secondary-rgb),var(--bs-text-opacity))!important}.text-success{--bs-text-opacity:1;color:rgba(var(--bs-success-rgb),var(--bs-text-opacity))!important}.text-info{--bs-text-opacity:1;color:rgba(var(--bs-info-rgb),var(--bs-text-opacity))!important}.text-warning{--bs-text-opacity:1;color:rgba(var(--bs-warning-rgb),var(--bs-text-opacity))!important}.text-danger{--bs-text-opacity:1;color:rgba(var(--bs-danger-rgb),var(--bs-text-opacity))!important}.text-light{--bs-text-opacity:1;color:rgba(var(--bs-light-rgb),var(--bs-text-opacity))!important}.text-dark{--bs-text-opacity:1;color:rgba(var(--bs-dark-rgb),var(--bs-text-opacity))!important}.text-black{--bs-text-opacity:1;color:rgba(var(--bs-black-rgb),var(--bs-text-opacity))!important}.text-white{--bs-text-opacity:1;color:rgba(var(--bs-white-rgb),var(--bs-text-opacity))!important}.text-body{--bs-text-opacity:1;color:rgba(var(--bs-body-color-rgb),var(--bs-text-opacity))!important}.text-muted{--bs-text-opacity:1;color:var(--bs-secondary-color)!important}.text-black-50{--bs-text-opacity:1;color:rgba(0,0,0,.5)!important}.text-white-50{--bs-text-opacity:1;color:rgba(255,255,255,.5)!important}.text-body-secondary{--bs-text-opacity:1;color:var(--bs-secondary-color)!important}.text-body-tertiary{--bs-text-opacity:1;color:var(--bs-tertiary-color)!important}.text-body-emphasis{--bs-text-opacity:1;color:var(--bs-emphasis-color)!important}.text-reset{--bs-text-opacity:1;color:inherit!important}.text-opacity-25{--bs-text-opacity:0.25}.text-opacity-50{--bs-text-opacity:0.5}.text-opacity-75{--bs-text-opacity:0.75}.text-opacity-100{--bs-text-opacity:1}.text-primary-emphasis{color:var(--bs-primary-text-emphasis)!important}.text-secondary-emphasis{color:var(--bs-secondary-text-emphasis)!important}.text-success-emphasis{color:var(--bs-success-text-emphasis)!important}.text-info-emphasis{color:var(--bs-info-text-emphasis)!important}.text-warning-emphasis{color:var(--bs-warning-text-emphasis)!important}.text-danger-emphasis{color:var(--bs-danger-text-emphasis)!important}.text-light-emphasis{color:var(--bs-light-text-emphasis)!important}.text-dark-emphasis{color:var(--bs-dark-text-emphasis)!important}.link-opacity-10{--bs-link-opacity:0.1}.link-opacity-10-hover:hover{--bs-link-opacity:0.1}.link-opacity-25{--bs-link-opacity:0.25}.link-opacity-25-hover:hover{--bs-link-opacity:0.25}.link-opacity-50{--bs-link-opacity:0.5}.link-opacity-50-hover:hover{--bs-link-opacity:0.5}.link-opacity-75{--bs-link-opacity:0.75}.link-opacity-75-hover:hover{--bs-link-opacity:0.75}.link-opacity-100{--bs-link-opacity:1}.link-opacity-100-hover:hover{--bs-link-opacity:1}.link-offset-1{text-underline-offset:0.125em!important}.link-offset-1-hover:hover{text-underline-offset:0.125em!important}.link-offset-2{text-underline-offset:0.25em!important}.link-offset-2-hover:hover{text-underline-offset:0.25em!important}.link-offset-3{text-underline-offset:0.375em!important}.link-offset-3-hover:hover{text-underline-offset:0.375em!important}.link-underline-primary{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-primary-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-primary-rgb),var(--bs-link-underline-opacity))!important}.link-underline-secondary{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-secondary-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-secondary-rgb),var(--bs-link-underline-opacity))!important}.link-underline-success{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-success-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-success-rgb),var(--bs-link-underline-opacity))!important}.link-underline-info{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-info-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-info-rgb),var(--bs-link-underline-opacity))!important}.link-underline-warning{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-warning-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-warning-rgb),var(--bs-link-underline-opacity))!important}.link-underline-danger{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-danger-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-danger-rgb),var(--bs-link-underline-opacity))!important}.link-underline-light{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-light-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-light-rgb),var(--bs-link-underline-opacity))!important}.link-underline-dark{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-dark-rgb),var(--bs-link-underline-opacity))!important;text-decoration-color:rgba(var(--bs-dark-rgb),var(--bs-link-underline-opacity))!important}.link-underline{--bs-link-underline-opacity:1;-webkit-text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-underline-opacity,1))!important;text-decoration-color:rgba(var(--bs-link-color-rgb),var(--bs-link-underline-opacity,1))!important}.link-underline-opacity-0{--bs-link-underline-opacity:0}.link-underline-opacity-0-hover:hover{--bs-link-underline-opacity:0}.link-underline-opacity-10{--bs-link-underline-opacity:0.1}.link-underline-opacity-10-hover:hover{--bs-link-underline-opacity:0.1}.link-underline-opacity-25{--bs-link-underline-opacity:0.25}.link-underline-opacity-25-hover:hover{--bs-link-underline-opacity:0.25}.link-underline-opacity-50{--bs-link-underline-opacity:0.5}.link-underline-opacity-50-hover:hover{--bs-link-underline-opacity:0.5}.link-underline-opacity-75{--bs-link-underline-opacity:0.75}.link-underline-opacity-75-hover:hover{--bs-link-underline-opacity:0.75}.link-underline-opacity-100{--bs-link-underline-opacity:1}.link-underline-opacity-100-hover:hover{--bs-link-underline-opacity:1}.bg-primary{--bs-bg-opacity:1;background-color:rgba(var(--bs-primary-rgb),var(--bs-bg-opacity))!important}.bg-secondary{--bs-bg-opacity:1;background-color:rgba(var(--bs-secondary-rgb),var(--bs-bg-opacity))!important}.bg-success{--bs-bg-opacity:1;background-color:rgba(var(--bs-success-rgb),var(--bs-bg-opacity))!important}.bg-info{--bs-bg-opacity:1;background-color:rgba(var(--bs-info-rgb),var(--bs-bg-opacity))!important}.bg-warning{--bs-bg-opacity:1;background-color:rgba(var(--bs-warning-rgb),var(--bs-bg-opacity))!important}.bg-danger{--bs-bg-opacity:1;background-color:rgba(var(--bs-danger-rgb),var(--bs-bg-opacity))!important}.bg-light{--bs-bg-opacity:1;background-color:rgba(var(--bs-light-rgb),var(--bs-bg-opacity))!important}.bg-dark{--bs-bg-opacity:1;background-color:rgba(var(--bs-dark-rgb),var(--bs-bg-opacity))!important}.bg-black{--bs-bg-opacity:1;background-color:rgba(var(--bs-black-rgb),var(--bs-bg-opacity))!important}.bg-white{--bs-bg-opacity:1;background-color:rgba(var(--bs-white-rgb),var(--bs-bg-opacity))!important}.bg-body{--bs-bg-opacity:1;background-color:rgba(var(--bs-body-bg-rgb),var(--bs-bg-opacity))!important}.bg-transparent{--bs-bg-opacity:1;background-color:transparent!important}.bg-body-secondary{--bs-bg-opacity:1;background-color:rgba(var(--bs-secondary-bg-rgb),var(--bs-bg-opacity))!important}.bg-body-tertiary{--bs-bg-opacity:1;background-color:rgba(var(--bs-tertiary-bg-rgb),var(--bs-bg-opacity))!important}.bg-opacity-10{--bs-bg-opacity:0.1}.bg-opacity-25{--bs-bg-opacity:0.25}.bg-opacity-50{--bs-bg-opacity:0.5}.bg-opacity-75{--bs-bg-opacity:0.75}.bg-opacity-100{--bs-bg-opacity:1}.bg-primary-subtle{background-color:var(--bs-primary-bg-subtle)!important}.bg-secondary-subtle{background-color:var(--bs-secondary-bg-subtle)!important}.bg-success-subtle{background-color:var(--bs-success-bg-subtle)!important}.bg-info-subtle{background-color:var(--bs-info-bg-subtle)!important}.bg-warning-subtle{background-color:var(--bs-warning-bg-subtle)!important}.bg-danger-subtle{background-color:var(--bs-danger-bg-subtle)!important}.bg-light-subtle{background-color:var(--bs-light-bg-subtle)!important}.bg-dark-subtle{background-color:var(--bs-dark-bg-subtle)!important}.bg-gradient{background-image:var(--bs-gradient)!important}.user-select-all{-webkit-user-select:all!important;-moz-user-select:all!important;user-select:all!important}.user-select-auto{-webkit-user-select:auto!important;-moz-user-select:auto!important;user-select:auto!important}.user-select-none{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}.pe-none{pointer-events:none!important}.pe-auto{pointer-events:auto!important}.rounded{border-radius:var(--bs-border-radius)!important}.rounded-0{border-radius:0!important}.rounded-1{border-radius:var(--bs-border-radius-sm)!important}.rounded-2{border-radius:var(--bs-border-radius)!important}.rounded-3{border-radius:var(--bs-border-radius-lg)!important}.rounded-4{border-radius:var(--bs-border-radius-xl)!important}.rounded-5{border-radius:var(--bs-border-radius-xxl)!important}.rounded-circle{border-radius:50%!important}.rounded-pill{border-radius:var(--bs-border-radius-pill)!important}.rounded-top{border-top-left-radius:var(--bs-border-radius)!important;border-top-right-radius:var(--bs-border-radius)!important}.rounded-top-0{border-top-left-radius:0!important;border-top-right-radius:0!important}.rounded-top-1{border-top-left-radius:var(--bs-border-radius-sm)!important;border-top-right-radius:var(--bs-border-radius-sm)!important}.rounded-top-2{border-top-left-radius:var(--bs-border-radius)!important;border-top-right-radius:var(--bs-border-radius)!important}.rounded-top-3{border-top-left-radius:var(--bs-border-radius-lg)!important;border-top-right-radius:var(--bs-border-radius-lg)!important}.rounded-top-4{border-top-left-radius:var(--bs-border-radius-xl)!important;border-top-right-radius:var(--bs-border-radius-xl)!important}.rounded-top-5{border-top-left-radius:var(--bs-border-radius-xxl)!important;border-top-right-radius:var(--bs-border-radius-xxl)!important}.rounded-top-circle{border-top-left-radius:50%!important;border-top-right-radius:50%!important}.rounded-top-pill{border-top-left-radius:var(--bs-border-radius-pill)!important;border-top-right-radius:var(--bs-border-radius-pill)!important}.rounded-end{border-top-right-radius:var(--bs-border-radius)!important;border-bottom-right-radius:var(--bs-border-radius)!important}.rounded-end-0{border-top-right-radius:0!important;border-bottom-right-radius:0!important}.rounded-end-1{border-top-right-radius:var(--bs-border-radius-sm)!important;border-bottom-right-radius:var(--bs-border-radius-sm)!important}.rounded-end-2{border-top-right-radius:var(--bs-border-radius)!important;border-bottom-right-radius:var(--bs-border-radius)!important}.rounded-end-3{border-top-right-radius:var(--bs-border-radius-lg)!important;border-bottom-right-radius:var(--bs-border-radius-lg)!important}.rounded-end-4{border-top-right-radius:var(--bs-border-radius-xl)!important;border-bottom-right-radius:var(--bs-border-radius-xl)!important}.rounded-end-5{border-top-right-radius:var(--bs-border-radius-xxl)!important;border-bottom-right-radius:var(--bs-border-radius-xxl)!important}.rounded-end-circle{border-top-right-radius:50%!important;border-bottom-right-radius:50%!important}.rounded-end-pill{border-top-right-radius:var(--bs-border-radius-pill)!important;border-bottom-right-radius:var(--bs-border-radius-pill)!important}.rounded-bottom{border-bottom-right-radius:var(--bs-border-radius)!important;border-bottom-left-radius:var(--bs-border-radius)!important}.rounded-bottom-0{border-bottom-right-radius:0!important;border-bottom-left-radius:0!important}.rounded-bottom-1{border-bottom-right-radius:var(--bs-border-radius-sm)!important;border-bottom-left-radius:var(--bs-border-radius-sm)!important}.rounded-bottom-2{border-bottom-right-radius:var(--bs-border-radius)!important;border-bottom-left-radius:var(--bs-border-radius)!important}.rounded-bottom-3{border-bottom-right-radius:var(--bs-border-radius-lg)!important;border-bottom-left-radius:var(--bs-border-radius-lg)!important}.rounded-bottom-4{border-bottom-right-radius:var(--bs-border-radius-xl)!important;border-bottom-left-radius:var(--bs-border-radius-xl)!important}.rounded-bottom-5{border-bottom-right-radius:var(--bs-border-radius-xxl)!important;border-bottom-left-radius:var(--bs-border-radius-xxl)!important}.rounded-bottom-circle{border-bottom-right-radius:50%!important;border-bottom-left-radius:50%!important}.rounded-bottom-pill{border-bottom-right-radius:var(--bs-border-radius-pill)!important;border-bottom-left-radius:var(--bs-border-radius-pill)!important}.rounded-start{border-bottom-left-radius:var(--bs-border-radius)!important;border-top-left-radius:var(--bs-border-radius)!important}.rounded-start-0{border-bottom-left-radius:0!important;border-top-left-radius:0!important}.rounded-start-1{border-bottom-left-radius:var(--bs-border-radius-sm)!important;border-top-left-radius:var(--bs-border-radius-sm)!important}.rounded-start-2{border-bottom-left-radius:var(--bs-border-radius)!important;border-top-left-radius:var(--bs-border-radius)!important}.rounded-start-3{border-bottom-left-radius:var(--bs-border-radius-lg)!important;border-top-left-radius:var(--bs-border-radius-lg)!important}.rounded-start-4{border-bottom-left-radius:var(--bs-border-radius-xl)!important;border-top-left-radius:var(--bs-border-radius-xl)!important}.rounded-start-5{border-bottom-left-radius:var(--bs-border-radius-xxl)!important;border-top-left-radius:var(--bs-border-radius-xxl)!important}.rounded-start-circle{border-bottom-left-radius:50%!important;border-top-left-radius:50%!important}.rounded-start-pill{border-bottom-left-radius:var(--bs-border-radius-pill)!important;border-top-left-radius:var(--bs-border-radius-pill)!important}.visible{visibility:visible!important}.invisible{visibility:hidden!important}.z-n1{z-index:-1!important}.z-0{z-index:0!important}.z-1{z-index:1!important}.z-2{z-index:2!important}.z-3{z-index:3!important}@media (min-width:576px){.float-sm-start{float:left!important}.float-sm-end{float:right!important}.float-sm-none{float:none!important}.object-fit-sm-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-sm-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-sm-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-sm-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-sm-none{-o-object-fit:none!important;object-fit:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-grid{display:grid!important}.d-sm-inline-grid{display:inline-grid!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:flex!important}.d-sm-inline-flex{display:inline-flex!important}.d-sm-none{display:none!important}.flex-sm-fill{flex:1 1 auto!important}.flex-sm-row{flex-direction:row!important}.flex-sm-column{flex-direction:column!important}.flex-sm-row-reverse{flex-direction:row-reverse!important}.flex-sm-column-reverse{flex-direction:column-reverse!important}.flex-sm-grow-0{flex-grow:0!important}.flex-sm-grow-1{flex-grow:1!important}.flex-sm-shrink-0{flex-shrink:0!important}.flex-sm-shrink-1{flex-shrink:1!important}.flex-sm-wrap{flex-wrap:wrap!important}.flex-sm-nowrap{flex-wrap:nowrap!important}.flex-sm-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-sm-start{justify-content:flex-start!important}.justify-content-sm-end{justify-content:flex-end!important}.justify-content-sm-center{justify-content:center!important}.justify-content-sm-between{justify-content:space-between!important}.justify-content-sm-around{justify-content:space-around!important}.justify-content-sm-evenly{justify-content:space-evenly!important}.align-items-sm-start{align-items:flex-start!important}.align-items-sm-end{align-items:flex-end!important}.align-items-sm-center{align-items:center!important}.align-items-sm-baseline{align-items:baseline!important}.align-items-sm-stretch{align-items:stretch!important}.align-content-sm-start{align-content:flex-start!important}.align-content-sm-end{align-content:flex-end!important}.align-content-sm-center{align-content:center!important}.align-content-sm-between{align-content:space-between!important}.align-content-sm-around{align-content:space-around!important}.align-content-sm-stretch{align-content:stretch!important}.align-self-sm-auto{align-self:auto!important}.align-self-sm-start{align-self:flex-start!important}.align-self-sm-end{align-self:flex-end!important}.align-self-sm-center{align-self:center!important}.align-self-sm-baseline{align-self:baseline!important}.align-self-sm-stretch{align-self:stretch!important}.order-sm-first{order:-1!important}.order-sm-0{order:0!important}.order-sm-1{order:1!important}.order-sm-2{order:2!important}.order-sm-3{order:3!important}.order-sm-4{order:4!important}.order-sm-5{order:5!important}.order-sm-last{order:6!important}.m-sm-0{margin:0!important}.m-sm-1{margin:.25rem!important}.m-sm-2{margin:.5rem!important}.m-sm-3{margin:1rem!important}.m-sm-4{margin:1.5rem!important}.m-sm-5{margin:3rem!important}.m-sm-auto{margin:auto!important}.mx-sm-0{margin-right:0!important;margin-left:0!important}.mx-sm-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-sm-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-sm-3{margin-right:1rem!important;margin-left:1rem!important}.mx-sm-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-sm-5{margin-right:3rem!important;margin-left:3rem!important}.mx-sm-auto{margin-right:auto!important;margin-left:auto!important}.my-sm-0{margin-top:0!important;margin-bottom:0!important}.my-sm-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-sm-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-sm-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-sm-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-sm-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-sm-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-sm-0{margin-top:0!important}.mt-sm-1{margin-top:.25rem!important}.mt-sm-2{margin-top:.5rem!important}.mt-sm-3{margin-top:1rem!important}.mt-sm-4{margin-top:1.5rem!important}.mt-sm-5{margin-top:3rem!important}.mt-sm-auto{margin-top:auto!important}.me-sm-0{margin-right:0!important}.me-sm-1{margin-right:.25rem!important}.me-sm-2{margin-right:.5rem!important}.me-sm-3{margin-right:1rem!important}.me-sm-4{margin-right:1.5rem!important}.me-sm-5{margin-right:3rem!important}.me-sm-auto{margin-right:auto!important}.mb-sm-0{margin-bottom:0!important}.mb-sm-1{margin-bottom:.25rem!important}.mb-sm-2{margin-bottom:.5rem!important}.mb-sm-3{margin-bottom:1rem!important}.mb-sm-4{margin-bottom:1.5rem!important}.mb-sm-5{margin-bottom:3rem!important}.mb-sm-auto{margin-bottom:auto!important}.ms-sm-0{margin-left:0!important}.ms-sm-1{margin-left:.25rem!important}.ms-sm-2{margin-left:.5rem!important}.ms-sm-3{margin-left:1rem!important}.ms-sm-4{margin-left:1.5rem!important}.ms-sm-5{margin-left:3rem!important}.ms-sm-auto{margin-left:auto!important}.p-sm-0{padding:0!important}.p-sm-1{padding:.25rem!important}.p-sm-2{padding:.5rem!important}.p-sm-3{padding:1rem!important}.p-sm-4{padding:1.5rem!important}.p-sm-5{padding:3rem!important}.px-sm-0{padding-right:0!important;padding-left:0!important}.px-sm-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-sm-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-sm-3{padding-right:1rem!important;padding-left:1rem!important}.px-sm-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-sm-5{padding-right:3rem!important;padding-left:3rem!important}.py-sm-0{padding-top:0!important;padding-bottom:0!important}.py-sm-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-sm-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-sm-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-sm-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-sm-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-sm-0{padding-top:0!important}.pt-sm-1{padding-top:.25rem!important}.pt-sm-2{padding-top:.5rem!important}.pt-sm-3{padding-top:1rem!important}.pt-sm-4{padding-top:1.5rem!important}.pt-sm-5{padding-top:3rem!important}.pe-sm-0{padding-right:0!important}.pe-sm-1{padding-right:.25rem!important}.pe-sm-2{padding-right:.5rem!important}.pe-sm-3{padding-right:1rem!important}.pe-sm-4{padding-right:1.5rem!important}.pe-sm-5{padding-right:3rem!important}.pb-sm-0{padding-bottom:0!important}.pb-sm-1{padding-bottom:.25rem!important}.pb-sm-2{padding-bottom:.5rem!important}.pb-sm-3{padding-bottom:1rem!important}.pb-sm-4{padding-bottom:1.5rem!important}.pb-sm-5{padding-bottom:3rem!important}.ps-sm-0{padding-left:0!important}.ps-sm-1{padding-left:.25rem!important}.ps-sm-2{padding-left:.5rem!important}.ps-sm-3{padding-left:1rem!important}.ps-sm-4{padding-left:1.5rem!important}.ps-sm-5{padding-left:3rem!important}.gap-sm-0{gap:0!important}.gap-sm-1{gap:.25rem!important}.gap-sm-2{gap:.5rem!important}.gap-sm-3{gap:1rem!important}.gap-sm-4{gap:1.5rem!important}.gap-sm-5{gap:3rem!important}.row-gap-sm-0{row-gap:0!important}.row-gap-sm-1{row-gap:.25rem!important}.row-gap-sm-2{row-gap:.5rem!important}.row-gap-sm-3{row-gap:1rem!important}.row-gap-sm-4{row-gap:1.5rem!important}.row-gap-sm-5{row-gap:3rem!important}.column-gap-sm-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-sm-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-sm-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-sm-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-sm-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-sm-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-sm-start{text-align:left!important}.text-sm-end{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.float-md-start{float:left!important}.float-md-end{float:right!important}.float-md-none{float:none!important}.object-fit-md-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-md-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-md-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-md-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-md-none{-o-object-fit:none!important;object-fit:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-grid{display:grid!important}.d-md-inline-grid{display:inline-grid!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:flex!important}.d-md-inline-flex{display:inline-flex!important}.d-md-none{display:none!important}.flex-md-fill{flex:1 1 auto!important}.flex-md-row{flex-direction:row!important}.flex-md-column{flex-direction:column!important}.flex-md-row-reverse{flex-direction:row-reverse!important}.flex-md-column-reverse{flex-direction:column-reverse!important}.flex-md-grow-0{flex-grow:0!important}.flex-md-grow-1{flex-grow:1!important}.flex-md-shrink-0{flex-shrink:0!important}.flex-md-shrink-1{flex-shrink:1!important}.flex-md-wrap{flex-wrap:wrap!important}.flex-md-nowrap{flex-wrap:nowrap!important}.flex-md-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-md-start{justify-content:flex-start!important}.justify-content-md-end{justify-content:flex-end!important}.justify-content-md-center{justify-content:center!important}.justify-content-md-between{justify-content:space-between!important}.justify-content-md-around{justify-content:space-around!important}.justify-content-md-evenly{justify-content:space-evenly!important}.align-items-md-start{align-items:flex-start!important}.align-items-md-end{align-items:flex-end!important}.align-items-md-center{align-items:center!important}.align-items-md-baseline{align-items:baseline!important}.align-items-md-stretch{align-items:stretch!important}.align-content-md-start{align-content:flex-start!important}.align-content-md-end{align-content:flex-end!important}.align-content-md-center{align-content:center!important}.align-content-md-between{align-content:space-between!important}.align-content-md-around{align-content:space-around!important}.align-content-md-stretch{align-content:stretch!important}.align-self-md-auto{align-self:auto!important}.align-self-md-start{align-self:flex-start!important}.align-self-md-end{align-self:flex-end!important}.align-self-md-center{align-self:center!important}.align-self-md-baseline{align-self:baseline!important}.align-self-md-stretch{align-self:stretch!important}.order-md-first{order:-1!important}.order-md-0{order:0!important}.order-md-1{order:1!important}.order-md-2{order:2!important}.order-md-3{order:3!important}.order-md-4{order:4!important}.order-md-5{order:5!important}.order-md-last{order:6!important}.m-md-0{margin:0!important}.m-md-1{margin:.25rem!important}.m-md-2{margin:.5rem!important}.m-md-3{margin:1rem!important}.m-md-4{margin:1.5rem!important}.m-md-5{margin:3rem!important}.m-md-auto{margin:auto!important}.mx-md-0{margin-right:0!important;margin-left:0!important}.mx-md-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-md-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-md-3{margin-right:1rem!important;margin-left:1rem!important}.mx-md-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-md-5{margin-right:3rem!important;margin-left:3rem!important}.mx-md-auto{margin-right:auto!important;margin-left:auto!important}.my-md-0{margin-top:0!important;margin-bottom:0!important}.my-md-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-md-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-md-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-md-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-md-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-md-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-md-0{margin-top:0!important}.mt-md-1{margin-top:.25rem!important}.mt-md-2{margin-top:.5rem!important}.mt-md-3{margin-top:1rem!important}.mt-md-4{margin-top:1.5rem!important}.mt-md-5{margin-top:3rem!important}.mt-md-auto{margin-top:auto!important}.me-md-0{margin-right:0!important}.me-md-1{margin-right:.25rem!important}.me-md-2{margin-right:.5rem!important}.me-md-3{margin-right:1rem!important}.me-md-4{margin-right:1.5rem!important}.me-md-5{margin-right:3rem!important}.me-md-auto{margin-right:auto!important}.mb-md-0{margin-bottom:0!important}.mb-md-1{margin-bottom:.25rem!important}.mb-md-2{margin-bottom:.5rem!important}.mb-md-3{margin-bottom:1rem!important}.mb-md-4{margin-bottom:1.5rem!important}.mb-md-5{margin-bottom:3rem!important}.mb-md-auto{margin-bottom:auto!important}.ms-md-0{margin-left:0!important}.ms-md-1{margin-left:.25rem!important}.ms-md-2{margin-left:.5rem!important}.ms-md-3{margin-left:1rem!important}.ms-md-4{margin-left:1.5rem!important}.ms-md-5{margin-left:3rem!important}.ms-md-auto{margin-left:auto!important}.p-md-0{padding:0!important}.p-md-1{padding:.25rem!important}.p-md-2{padding:.5rem!important}.p-md-3{padding:1rem!important}.p-md-4{padding:1.5rem!important}.p-md-5{padding:3rem!important}.px-md-0{padding-right:0!important;padding-left:0!important}.px-md-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-md-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-md-3{padding-right:1rem!important;padding-left:1rem!important}.px-md-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-md-5{padding-right:3rem!important;padding-left:3rem!important}.py-md-0{padding-top:0!important;padding-bottom:0!important}.py-md-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-md-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-md-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-md-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-md-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-md-0{padding-top:0!important}.pt-md-1{padding-top:.25rem!important}.pt-md-2{padding-top:.5rem!important}.pt-md-3{padding-top:1rem!important}.pt-md-4{padding-top:1.5rem!important}.pt-md-5{padding-top:3rem!important}.pe-md-0{padding-right:0!important}.pe-md-1{padding-right:.25rem!important}.pe-md-2{padding-right:.5rem!important}.pe-md-3{padding-right:1rem!important}.pe-md-4{padding-right:1.5rem!important}.pe-md-5{padding-right:3rem!important}.pb-md-0{padding-bottom:0!important}.pb-md-1{padding-bottom:.25rem!important}.pb-md-2{padding-bottom:.5rem!important}.pb-md-3{padding-bottom:1rem!important}.pb-md-4{padding-bottom:1.5rem!important}.pb-md-5{padding-bottom:3rem!important}.ps-md-0{padding-left:0!important}.ps-md-1{padding-left:.25rem!important}.ps-md-2{padding-left:.5rem!important}.ps-md-3{padding-left:1rem!important}.ps-md-4{padding-left:1.5rem!important}.ps-md-5{padding-left:3rem!important}.gap-md-0{gap:0!important}.gap-md-1{gap:.25rem!important}.gap-md-2{gap:.5rem!important}.gap-md-3{gap:1rem!important}.gap-md-4{gap:1.5rem!important}.gap-md-5{gap:3rem!important}.row-gap-md-0{row-gap:0!important}.row-gap-md-1{row-gap:.25rem!important}.row-gap-md-2{row-gap:.5rem!important}.row-gap-md-3{row-gap:1rem!important}.row-gap-md-4{row-gap:1.5rem!important}.row-gap-md-5{row-gap:3rem!important}.column-gap-md-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-md-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-md-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-md-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-md-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-md-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-md-start{text-align:left!important}.text-md-end{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.float-lg-start{float:left!important}.float-lg-end{float:right!important}.float-lg-none{float:none!important}.object-fit-lg-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-lg-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-lg-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-lg-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-lg-none{-o-object-fit:none!important;object-fit:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-grid{display:grid!important}.d-lg-inline-grid{display:inline-grid!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:flex!important}.d-lg-inline-flex{display:inline-flex!important}.d-lg-none{display:none!important}.flex-lg-fill{flex:1 1 auto!important}.flex-lg-row{flex-direction:row!important}.flex-lg-column{flex-direction:column!important}.flex-lg-row-reverse{flex-direction:row-reverse!important}.flex-lg-column-reverse{flex-direction:column-reverse!important}.flex-lg-grow-0{flex-grow:0!important}.flex-lg-grow-1{flex-grow:1!important}.flex-lg-shrink-0{flex-shrink:0!important}.flex-lg-shrink-1{flex-shrink:1!important}.flex-lg-wrap{flex-wrap:wrap!important}.flex-lg-nowrap{flex-wrap:nowrap!important}.flex-lg-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-lg-start{justify-content:flex-start!important}.justify-content-lg-end{justify-content:flex-end!important}.justify-content-lg-center{justify-content:center!important}.justify-content-lg-between{justify-content:space-between!important}.justify-content-lg-around{justify-content:space-around!important}.justify-content-lg-evenly{justify-content:space-evenly!important}.align-items-lg-start{align-items:flex-start!important}.align-items-lg-end{align-items:flex-end!important}.align-items-lg-center{align-items:center!important}.align-items-lg-baseline{align-items:baseline!important}.align-items-lg-stretch{align-items:stretch!important}.align-content-lg-start{align-content:flex-start!important}.align-content-lg-end{align-content:flex-end!important}.align-content-lg-center{align-content:center!important}.align-content-lg-between{align-content:space-between!important}.align-content-lg-around{align-content:space-around!important}.align-content-lg-stretch{align-content:stretch!important}.align-self-lg-auto{align-self:auto!important}.align-self-lg-start{align-self:flex-start!important}.align-self-lg-end{align-self:flex-end!important}.align-self-lg-center{align-self:center!important}.align-self-lg-baseline{align-self:baseline!important}.align-self-lg-stretch{align-self:stretch!important}.order-lg-first{order:-1!important}.order-lg-0{order:0!important}.order-lg-1{order:1!important}.order-lg-2{order:2!important}.order-lg-3{order:3!important}.order-lg-4{order:4!important}.order-lg-5{order:5!important}.order-lg-last{order:6!important}.m-lg-0{margin:0!important}.m-lg-1{margin:.25rem!important}.m-lg-2{margin:.5rem!important}.m-lg-3{margin:1rem!important}.m-lg-4{margin:1.5rem!important}.m-lg-5{margin:3rem!important}.m-lg-auto{margin:auto!important}.mx-lg-0{margin-right:0!important;margin-left:0!important}.mx-lg-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-lg-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-lg-3{margin-right:1rem!important;margin-left:1rem!important}.mx-lg-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-lg-5{margin-right:3rem!important;margin-left:3rem!important}.mx-lg-auto{margin-right:auto!important;margin-left:auto!important}.my-lg-0{margin-top:0!important;margin-bottom:0!important}.my-lg-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-lg-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-lg-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-lg-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-lg-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-lg-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-lg-0{margin-top:0!important}.mt-lg-1{margin-top:.25rem!important}.mt-lg-2{margin-top:.5rem!important}.mt-lg-3{margin-top:1rem!important}.mt-lg-4{margin-top:1.5rem!important}.mt-lg-5{margin-top:3rem!important}.mt-lg-auto{margin-top:auto!important}.me-lg-0{margin-right:0!important}.me-lg-1{margin-right:.25rem!important}.me-lg-2{margin-right:.5rem!important}.me-lg-3{margin-right:1rem!important}.me-lg-4{margin-right:1.5rem!important}.me-lg-5{margin-right:3rem!important}.me-lg-auto{margin-right:auto!important}.mb-lg-0{margin-bottom:0!important}.mb-lg-1{margin-bottom:.25rem!important}.mb-lg-2{margin-bottom:.5rem!important}.mb-lg-3{margin-bottom:1rem!important}.mb-lg-4{margin-bottom:1.5rem!important}.mb-lg-5{margin-bottom:3rem!important}.mb-lg-auto{margin-bottom:auto!important}.ms-lg-0{margin-left:0!important}.ms-lg-1{margin-left:.25rem!important}.ms-lg-2{margin-left:.5rem!important}.ms-lg-3{margin-left:1rem!important}.ms-lg-4{margin-left:1.5rem!important}.ms-lg-5{margin-left:3rem!important}.ms-lg-auto{margin-left:auto!important}.p-lg-0{padding:0!important}.p-lg-1{padding:.25rem!important}.p-lg-2{padding:.5rem!important}.p-lg-3{padding:1rem!important}.p-lg-4{padding:1.5rem!important}.p-lg-5{padding:3rem!important}.px-lg-0{padding-right:0!important;padding-left:0!important}.px-lg-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-lg-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-lg-3{padding-right:1rem!important;padding-left:1rem!important}.px-lg-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-lg-5{padding-right:3rem!important;padding-left:3rem!important}.py-lg-0{padding-top:0!important;padding-bottom:0!important}.py-lg-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-lg-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-lg-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-lg-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-lg-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-lg-0{padding-top:0!important}.pt-lg-1{padding-top:.25rem!important}.pt-lg-2{padding-top:.5rem!important}.pt-lg-3{padding-top:1rem!important}.pt-lg-4{padding-top:1.5rem!important}.pt-lg-5{padding-top:3rem!important}.pe-lg-0{padding-right:0!important}.pe-lg-1{padding-right:.25rem!important}.pe-lg-2{padding-right:.5rem!important}.pe-lg-3{padding-right:1rem!important}.pe-lg-4{padding-right:1.5rem!important}.pe-lg-5{padding-right:3rem!important}.pb-lg-0{padding-bottom:0!important}.pb-lg-1{padding-bottom:.25rem!important}.pb-lg-2{padding-bottom:.5rem!important}.pb-lg-3{padding-bottom:1rem!important}.pb-lg-4{padding-bottom:1.5rem!important}.pb-lg-5{padding-bottom:3rem!important}.ps-lg-0{padding-left:0!important}.ps-lg-1{padding-left:.25rem!important}.ps-lg-2{padding-left:.5rem!important}.ps-lg-3{padding-left:1rem!important}.ps-lg-4{padding-left:1.5rem!important}.ps-lg-5{padding-left:3rem!important}.gap-lg-0{gap:0!important}.gap-lg-1{gap:.25rem!important}.gap-lg-2{gap:.5rem!important}.gap-lg-3{gap:1rem!important}.gap-lg-4{gap:1.5rem!important}.gap-lg-5{gap:3rem!important}.row-gap-lg-0{row-gap:0!important}.row-gap-lg-1{row-gap:.25rem!important}.row-gap-lg-2{row-gap:.5rem!important}.row-gap-lg-3{row-gap:1rem!important}.row-gap-lg-4{row-gap:1.5rem!important}.row-gap-lg-5{row-gap:3rem!important}.column-gap-lg-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-lg-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-lg-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-lg-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-lg-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-lg-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-lg-start{text-align:left!important}.text-lg-end{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.float-xl-start{float:left!important}.float-xl-end{float:right!important}.float-xl-none{float:none!important}.object-fit-xl-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-xl-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-xl-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-xl-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-xl-none{-o-object-fit:none!important;object-fit:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-grid{display:grid!important}.d-xl-inline-grid{display:inline-grid!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:flex!important}.d-xl-inline-flex{display:inline-flex!important}.d-xl-none{display:none!important}.flex-xl-fill{flex:1 1 auto!important}.flex-xl-row{flex-direction:row!important}.flex-xl-column{flex-direction:column!important}.flex-xl-row-reverse{flex-direction:row-reverse!important}.flex-xl-column-reverse{flex-direction:column-reverse!important}.flex-xl-grow-0{flex-grow:0!important}.flex-xl-grow-1{flex-grow:1!important}.flex-xl-shrink-0{flex-shrink:0!important}.flex-xl-shrink-1{flex-shrink:1!important}.flex-xl-wrap{flex-wrap:wrap!important}.flex-xl-nowrap{flex-wrap:nowrap!important}.flex-xl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xl-start{justify-content:flex-start!important}.justify-content-xl-end{justify-content:flex-end!important}.justify-content-xl-center{justify-content:center!important}.justify-content-xl-between{justify-content:space-between!important}.justify-content-xl-around{justify-content:space-around!important}.justify-content-xl-evenly{justify-content:space-evenly!important}.align-items-xl-start{align-items:flex-start!important}.align-items-xl-end{align-items:flex-end!important}.align-items-xl-center{align-items:center!important}.align-items-xl-baseline{align-items:baseline!important}.align-items-xl-stretch{align-items:stretch!important}.align-content-xl-start{align-content:flex-start!important}.align-content-xl-end{align-content:flex-end!important}.align-content-xl-center{align-content:center!important}.align-content-xl-between{align-content:space-between!important}.align-content-xl-around{align-content:space-around!important}.align-content-xl-stretch{align-content:stretch!important}.align-self-xl-auto{align-self:auto!important}.align-self-xl-start{align-self:flex-start!important}.align-self-xl-end{align-self:flex-end!important}.align-self-xl-center{align-self:center!important}.align-self-xl-baseline{align-self:baseline!important}.align-self-xl-stretch{align-self:stretch!important}.order-xl-first{order:-1!important}.order-xl-0{order:0!important}.order-xl-1{order:1!important}.order-xl-2{order:2!important}.order-xl-3{order:3!important}.order-xl-4{order:4!important}.order-xl-5{order:5!important}.order-xl-last{order:6!important}.m-xl-0{margin:0!important}.m-xl-1{margin:.25rem!important}.m-xl-2{margin:.5rem!important}.m-xl-3{margin:1rem!important}.m-xl-4{margin:1.5rem!important}.m-xl-5{margin:3rem!important}.m-xl-auto{margin:auto!important}.mx-xl-0{margin-right:0!important;margin-left:0!important}.mx-xl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xl-auto{margin-right:auto!important;margin-left:auto!important}.my-xl-0{margin-top:0!important;margin-bottom:0!important}.my-xl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xl-0{margin-top:0!important}.mt-xl-1{margin-top:.25rem!important}.mt-xl-2{margin-top:.5rem!important}.mt-xl-3{margin-top:1rem!important}.mt-xl-4{margin-top:1.5rem!important}.mt-xl-5{margin-top:3rem!important}.mt-xl-auto{margin-top:auto!important}.me-xl-0{margin-right:0!important}.me-xl-1{margin-right:.25rem!important}.me-xl-2{margin-right:.5rem!important}.me-xl-3{margin-right:1rem!important}.me-xl-4{margin-right:1.5rem!important}.me-xl-5{margin-right:3rem!important}.me-xl-auto{margin-right:auto!important}.mb-xl-0{margin-bottom:0!important}.mb-xl-1{margin-bottom:.25rem!important}.mb-xl-2{margin-bottom:.5rem!important}.mb-xl-3{margin-bottom:1rem!important}.mb-xl-4{margin-bottom:1.5rem!important}.mb-xl-5{margin-bottom:3rem!important}.mb-xl-auto{margin-bottom:auto!important}.ms-xl-0{margin-left:0!important}.ms-xl-1{margin-left:.25rem!important}.ms-xl-2{margin-left:.5rem!important}.ms-xl-3{margin-left:1rem!important}.ms-xl-4{margin-left:1.5rem!important}.ms-xl-5{margin-left:3rem!important}.ms-xl-auto{margin-left:auto!important}.p-xl-0{padding:0!important}.p-xl-1{padding:.25rem!important}.p-xl-2{padding:.5rem!important}.p-xl-3{padding:1rem!important}.p-xl-4{padding:1.5rem!important}.p-xl-5{padding:3rem!important}.px-xl-0{padding-right:0!important;padding-left:0!important}.px-xl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xl-0{padding-top:0!important;padding-bottom:0!important}.py-xl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xl-0{padding-top:0!important}.pt-xl-1{padding-top:.25rem!important}.pt-xl-2{padding-top:.5rem!important}.pt-xl-3{padding-top:1rem!important}.pt-xl-4{padding-top:1.5rem!important}.pt-xl-5{padding-top:3rem!important}.pe-xl-0{padding-right:0!important}.pe-xl-1{padding-right:.25rem!important}.pe-xl-2{padding-right:.5rem!important}.pe-xl-3{padding-right:1rem!important}.pe-xl-4{padding-right:1.5rem!important}.pe-xl-5{padding-right:3rem!important}.pb-xl-0{padding-bottom:0!important}.pb-xl-1{padding-bottom:.25rem!important}.pb-xl-2{padding-bottom:.5rem!important}.pb-xl-3{padding-bottom:1rem!important}.pb-xl-4{padding-bottom:1.5rem!important}.pb-xl-5{padding-bottom:3rem!important}.ps-xl-0{padding-left:0!important}.ps-xl-1{padding-left:.25rem!important}.ps-xl-2{padding-left:.5rem!important}.ps-xl-3{padding-left:1rem!important}.ps-xl-4{padding-left:1.5rem!important}.ps-xl-5{padding-left:3rem!important}.gap-xl-0{gap:0!important}.gap-xl-1{gap:.25rem!important}.gap-xl-2{gap:.5rem!important}.gap-xl-3{gap:1rem!important}.gap-xl-4{gap:1.5rem!important}.gap-xl-5{gap:3rem!important}.row-gap-xl-0{row-gap:0!important}.row-gap-xl-1{row-gap:.25rem!important}.row-gap-xl-2{row-gap:.5rem!important}.row-gap-xl-3{row-gap:1rem!important}.row-gap-xl-4{row-gap:1.5rem!important}.row-gap-xl-5{row-gap:3rem!important}.column-gap-xl-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-xl-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-xl-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-xl-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-xl-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-xl-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-xl-start{text-align:left!important}.text-xl-end{text-align:right!important}.text-xl-center{text-align:center!important}}@media (min-width:1400px){.float-xxl-start{float:left!important}.float-xxl-end{float:right!important}.float-xxl-none{float:none!important}.object-fit-xxl-contain{-o-object-fit:contain!important;object-fit:contain!important}.object-fit-xxl-cover{-o-object-fit:cover!important;object-fit:cover!important}.object-fit-xxl-fill{-o-object-fit:fill!important;object-fit:fill!important}.object-fit-xxl-scale{-o-object-fit:scale-down!important;object-fit:scale-down!important}.object-fit-xxl-none{-o-object-fit:none!important;object-fit:none!important}.d-xxl-inline{display:inline!important}.d-xxl-inline-block{display:inline-block!important}.d-xxl-block{display:block!important}.d-xxl-grid{display:grid!important}.d-xxl-inline-grid{display:inline-grid!important}.d-xxl-table{display:table!important}.d-xxl-table-row{display:table-row!important}.d-xxl-table-cell{display:table-cell!important}.d-xxl-flex{display:flex!important}.d-xxl-inline-flex{display:inline-flex!important}.d-xxl-none{display:none!important}.flex-xxl-fill{flex:1 1 auto!important}.flex-xxl-row{flex-direction:row!important}.flex-xxl-column{flex-direction:column!important}.flex-xxl-row-reverse{flex-direction:row-reverse!important}.flex-xxl-column-reverse{flex-direction:column-reverse!important}.flex-xxl-grow-0{flex-grow:0!important}.flex-xxl-grow-1{flex-grow:1!important}.flex-xxl-shrink-0{flex-shrink:0!important}.flex-xxl-shrink-1{flex-shrink:1!important}.flex-xxl-wrap{flex-wrap:wrap!important}.flex-xxl-nowrap{flex-wrap:nowrap!important}.flex-xxl-wrap-reverse{flex-wrap:wrap-reverse!important}.justify-content-xxl-start{justify-content:flex-start!important}.justify-content-xxl-end{justify-content:flex-end!important}.justify-content-xxl-center{justify-content:center!important}.justify-content-xxl-between{justify-content:space-between!important}.justify-content-xxl-around{justify-content:space-around!important}.justify-content-xxl-evenly{justify-content:space-evenly!important}.align-items-xxl-start{align-items:flex-start!important}.align-items-xxl-end{align-items:flex-end!important}.align-items-xxl-center{align-items:center!important}.align-items-xxl-baseline{align-items:baseline!important}.align-items-xxl-stretch{align-items:stretch!important}.align-content-xxl-start{align-content:flex-start!important}.align-content-xxl-end{align-content:flex-end!important}.align-content-xxl-center{align-content:center!important}.align-content-xxl-between{align-content:space-between!important}.align-content-xxl-around{align-content:space-around!important}.align-content-xxl-stretch{align-content:stretch!important}.align-self-xxl-auto{align-self:auto!important}.align-self-xxl-start{align-self:flex-start!important}.align-self-xxl-end{align-self:flex-end!important}.align-self-xxl-center{align-self:center!important}.align-self-xxl-baseline{align-self:baseline!important}.align-self-xxl-stretch{align-self:stretch!important}.order-xxl-first{order:-1!important}.order-xxl-0{order:0!important}.order-xxl-1{order:1!important}.order-xxl-2{order:2!important}.order-xxl-3{order:3!important}.order-xxl-4{order:4!important}.order-xxl-5{order:5!important}.order-xxl-last{order:6!important}.m-xxl-0{margin:0!important}.m-xxl-1{margin:.25rem!important}.m-xxl-2{margin:.5rem!important}.m-xxl-3{margin:1rem!important}.m-xxl-4{margin:1.5rem!important}.m-xxl-5{margin:3rem!important}.m-xxl-auto{margin:auto!important}.mx-xxl-0{margin-right:0!important;margin-left:0!important}.mx-xxl-1{margin-right:.25rem!important;margin-left:.25rem!important}.mx-xxl-2{margin-right:.5rem!important;margin-left:.5rem!important}.mx-xxl-3{margin-right:1rem!important;margin-left:1rem!important}.mx-xxl-4{margin-right:1.5rem!important;margin-left:1.5rem!important}.mx-xxl-5{margin-right:3rem!important;margin-left:3rem!important}.mx-xxl-auto{margin-right:auto!important;margin-left:auto!important}.my-xxl-0{margin-top:0!important;margin-bottom:0!important}.my-xxl-1{margin-top:.25rem!important;margin-bottom:.25rem!important}.my-xxl-2{margin-top:.5rem!important;margin-bottom:.5rem!important}.my-xxl-3{margin-top:1rem!important;margin-bottom:1rem!important}.my-xxl-4{margin-top:1.5rem!important;margin-bottom:1.5rem!important}.my-xxl-5{margin-top:3rem!important;margin-bottom:3rem!important}.my-xxl-auto{margin-top:auto!important;margin-bottom:auto!important}.mt-xxl-0{margin-top:0!important}.mt-xxl-1{margin-top:.25rem!important}.mt-xxl-2{margin-top:.5rem!important}.mt-xxl-3{margin-top:1rem!important}.mt-xxl-4{margin-top:1.5rem!important}.mt-xxl-5{margin-top:3rem!important}.mt-xxl-auto{margin-top:auto!important}.me-xxl-0{margin-right:0!important}.me-xxl-1{margin-right:.25rem!important}.me-xxl-2{margin-right:.5rem!important}.me-xxl-3{margin-right:1rem!important}.me-xxl-4{margin-right:1.5rem!important}.me-xxl-5{margin-right:3rem!important}.me-xxl-auto{margin-right:auto!important}.mb-xxl-0{margin-bottom:0!important}.mb-xxl-1{margin-bottom:.25rem!important}.mb-xxl-2{margin-bottom:.5rem!important}.mb-xxl-3{margin-bottom:1rem!important}.mb-xxl-4{margin-bottom:1.5rem!important}.mb-xxl-5{margin-bottom:3rem!important}.mb-xxl-auto{margin-bottom:auto!important}.ms-xxl-0{margin-left:0!important}.ms-xxl-1{margin-left:.25rem!important}.ms-xxl-2{margin-left:.5rem!important}.ms-xxl-3{margin-left:1rem!important}.ms-xxl-4{margin-left:1.5rem!important}.ms-xxl-5{margin-left:3rem!important}.ms-xxl-auto{margin-left:auto!important}.p-xxl-0{padding:0!important}.p-xxl-1{padding:.25rem!important}.p-xxl-2{padding:.5rem!important}.p-xxl-3{padding:1rem!important}.p-xxl-4{padding:1.5rem!important}.p-xxl-5{padding:3rem!important}.px-xxl-0{padding-right:0!important;padding-left:0!important}.px-xxl-1{padding-right:.25rem!important;padding-left:.25rem!important}.px-xxl-2{padding-right:.5rem!important;padding-left:.5rem!important}.px-xxl-3{padding-right:1rem!important;padding-left:1rem!important}.px-xxl-4{padding-right:1.5rem!important;padding-left:1.5rem!important}.px-xxl-5{padding-right:3rem!important;padding-left:3rem!important}.py-xxl-0{padding-top:0!important;padding-bottom:0!important}.py-xxl-1{padding-top:.25rem!important;padding-bottom:.25rem!important}.py-xxl-2{padding-top:.5rem!important;padding-bottom:.5rem!important}.py-xxl-3{padding-top:1rem!important;padding-bottom:1rem!important}.py-xxl-4{padding-top:1.5rem!important;padding-bottom:1.5rem!important}.py-xxl-5{padding-top:3rem!important;padding-bottom:3rem!important}.pt-xxl-0{padding-top:0!important}.pt-xxl-1{padding-top:.25rem!important}.pt-xxl-2{padding-top:.5rem!important}.pt-xxl-3{padding-top:1rem!important}.pt-xxl-4{padding-top:1.5rem!important}.pt-xxl-5{padding-top:3rem!important}.pe-xxl-0{padding-right:0!important}.pe-xxl-1{padding-right:.25rem!important}.pe-xxl-2{padding-right:.5rem!important}.pe-xxl-3{padding-right:1rem!important}.pe-xxl-4{padding-right:1.5rem!important}.pe-xxl-5{padding-right:3rem!important}.pb-xxl-0{padding-bottom:0!important}.pb-xxl-1{padding-bottom:.25rem!important}.pb-xxl-2{padding-bottom:.5rem!important}.pb-xxl-3{padding-bottom:1rem!important}.pb-xxl-4{padding-bottom:1.5rem!important}.pb-xxl-5{padding-bottom:3rem!important}.ps-xxl-0{padding-left:0!important}.ps-xxl-1{padding-left:.25rem!important}.ps-xxl-2{padding-left:.5rem!important}.ps-xxl-3{padding-left:1rem!important}.ps-xxl-4{padding-left:1.5rem!important}.ps-xxl-5{padding-left:3rem!important}.gap-xxl-0{gap:0!important}.gap-xxl-1{gap:.25rem!important}.gap-xxl-2{gap:.5rem!important}.gap-xxl-3{gap:1rem!important}.gap-xxl-4{gap:1.5rem!important}.gap-xxl-5{gap:3rem!important}.row-gap-xxl-0{row-gap:0!important}.row-gap-xxl-1{row-gap:.25rem!important}.row-gap-xxl-2{row-gap:.5rem!important}.row-gap-xxl-3{row-gap:1rem!important}.row-gap-xxl-4{row-gap:1.5rem!important}.row-gap-xxl-5{row-gap:3rem!important}.column-gap-xxl-0{-moz-column-gap:0!important;column-gap:0!important}.column-gap-xxl-1{-moz-column-gap:0.25rem!important;column-gap:.25rem!important}.column-gap-xxl-2{-moz-column-gap:0.5rem!important;column-gap:.5rem!important}.column-gap-xxl-3{-moz-column-gap:1rem!important;column-gap:1rem!important}.column-gap-xxl-4{-moz-column-gap:1.5rem!important;column-gap:1.5rem!important}.column-gap-xxl-5{-moz-column-gap:3rem!important;column-gap:3rem!important}.text-xxl-start{text-align:left!important}.text-xxl-end{text-align:right!important}.text-xxl-center{text-align:center!important}}@media (min-width:1200px){.fs-1{font-size:2.5rem!important}.fs-2{font-size:2rem!important}.fs-3{font-size:1.75rem!important}.fs-4{font-size:1.5rem!important}}@media print{.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-grid{display:grid!important}.d-print-inline-grid{display:inline-grid!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:flex!important}.d-print-inline-flex{display:inline-flex!important}.d-print-none{display:none!important}} diff --git a/src/main/webapp/static/css/Bold-BS4-Full-Page-Image-Header.css b/src/main/webapp/static/css/Bold-BS4-Full-Page-Image-Header.css new file mode 100644 index 0000000..8c5b721 --- /dev/null +++ b/src/main/webapp/static/css/Bold-BS4-Full-Page-Image-Header.css @@ -0,0 +1,9 @@ +.masthead { + height: 100vh; + min-height: 500px; + background-image: url('https://source.unsplash.com/BtbjCFUvBXs/1920x1080'); + background-size: cover; + background-position: center; + background-repeat: no-repeat; +} + diff --git a/src/main/webapp/static/css/Hero-Features-icons.css b/src/main/webapp/static/css/Hero-Features-icons.css new file mode 100644 index 0000000..b6e79a3 --- /dev/null +++ b/src/main/webapp/static/css/Hero-Features-icons.css @@ -0,0 +1,57 @@ +.bs-icon { + --bs-icon-size: .75rem; + display: flex; + flex-shrink: 0; + justify-content: center; + align-items: center; + font-size: var(--bs-icon-size); + width: calc(var(--bs-icon-size) * 2); + height: calc(var(--bs-icon-size) * 2); + color: var(--bs-primary); +} + +.bs-icon-xs { + --bs-icon-size: 1rem; + width: calc(var(--bs-icon-size) * 1.5); + height: calc(var(--bs-icon-size) * 1.5); +} + +.bs-icon-sm { + --bs-icon-size: 1rem; +} + +.bs-icon-md { + --bs-icon-size: 1.5rem; +} + +.bs-icon-lg { + --bs-icon-size: 2rem; +} + +.bs-icon-xl { + --bs-icon-size: 2.5rem; +} + +.bs-icon.bs-icon-primary { + color: var(--bs-white); + background: var(--bs-primary); +} + +.bs-icon.bs-icon-primary-light { + color: var(--bs-primary); + background: rgba(var(--bs-primary-rgb), .2); +} + +.bs-icon.bs-icon-semi-white { + color: var(--bs-primary); + background: rgba(255, 255, 255, .5); +} + +.bs-icon.bs-icon-rounded { + border-radius: .5rem; +} + +.bs-icon.bs-icon-circle { + border-radius: 50%; +} + From 4b99552159f13d7dfd50eaee179ac4e6329dbde2 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Fri, 23 Jan 2026 14:50:21 +0500 Subject: [PATCH 14/65] CHANGE json --- src/main/resources/quest-1.json | 1 + src/main/resources/quest-2.json | 3 +- src/main/resources/quest-3.json | 3 +- src/main/webapp/WEB-INF/quest-page.jsp | 9 +- src/main/webapp/static/json/quest-1.json | 63 --- src/main/webapp/static/json/quest-2.json | 526 ----------------------- src/main/webapp/static/json/quest-3.json | 455 -------------------- 7 files changed, 12 insertions(+), 1048 deletions(-) delete mode 100644 src/main/webapp/static/json/quest-1.json delete mode 100644 src/main/webapp/static/json/quest-2.json delete mode 100644 src/main/webapp/static/json/quest-3.json diff --git a/src/main/resources/quest-1.json b/src/main/resources/quest-1.json index bb1f0e4..0b6f57a 100644 --- a/src/main/resources/quest-1.json +++ b/src/main/resources/quest-1.json @@ -1,6 +1,7 @@ { "title": "Космическое приключение", "description": "Про приключения в космосе", + "text": "Про приключения в космосе", "questions": [ { "label": "1", diff --git a/src/main/resources/quest-2.json b/src/main/resources/quest-2.json index 7a7e498..cc70b9b 100644 --- a/src/main/resources/quest-2.json +++ b/src/main/resources/quest-2.json @@ -1,6 +1,7 @@ { "title": "Тайна Забытого Подземелья", - "description": "Много веков назад дракон Вельдан, хранитель древних знаний, скрылся в недрах горы с Сердцем Дракона — артефактом невообразимой силы, спрятав его в лабиринте, известном как Забытое Подземелье. Тысячи смельчаков отправлялись на поиски реликвии, но никто не вернулся; легенды гласят, что лишь тот, кто проявит мудрость, отвагу и хладнокровие, сможет завладеть Сердцем. Теперь вы — один из искателей: с факелом и мечом перед массивной дверью с драконьей пастью, за которой таятся тьма, сырость и нечто древнее. Дверь медленно приоткрывается — готовы ли вы бросить вызов подземелью?", + "description": "Много веков назад дракон Вельдан, хранитель древних знаний, скрылся в недрах горы с Сердцем Дракона — артефактом невообразимой силы...", + "text": "Много веков назад дракон Вельдан, хранитель древних знаний, скрылся в недрах горы с Сердцем Дракона — артефактом невообразимой силы, спрятав его в лабиринте, известном как Забытое Подземелье. Тысячи смельчаков отправлялись на поиски реликвии, но никто не вернулся; легенды гласят, что лишь тот, кто проявит мудрость, отвагу и хладнокровие, сможет завладеть Сердцем. Теперь вы — один из искателей: с факелом и мечом перед массивной дверью с драконьей пастью, за которой таятся тьма, сырость и нечто древнее. Дверь медленно приоткрывается — готовы ли вы бросить вызов подземелью?", "questions": [ { "label": "1", diff --git a/src/main/resources/quest-3.json b/src/main/resources/quest-3.json index 97d6445..099b7c7 100644 --- a/src/main/resources/quest-3.json +++ b/src/main/resources/quest-3.json @@ -1,6 +1,7 @@ { "title": "Автостопом по здравому смыслу (или Не паникуй)", - "description": "Добро пожаловать в квест, который начинается с конца света и быстро переходит к вопросам посложнее. Землю сносят ради гиперпространственной магистрали, предупреждения были вывешены (где-то далеко и давно), а у вас есть лишь выбор, полотенце и крайне смутное представление о происходящем. Впереди — вогоны, сомнительный чай, философские размышления и шанс узнать ответ на Главный вопрос жизни, Вселенной и всего такого. Главное — не паникуйте: Вселенная всё равно делает вид, что всё под контролем.", + "description": "По мотивам «Автостопом по Галактике»", + "text": "Добро пожаловать в квест, который начинается с конца света и быстро переходит к вопросам посложнее. Землю сносят ради гиперпространственной магистрали, предупреждения были вывешены (где-то далеко и давно), а у вас есть лишь выбор, полотенце и крайне смутное представление о происходящем. Впереди — вогоны, сомнительный чай, философские размышления и шанс узнать ответ на Главный вопрос жизни, Вселенной и всего такого. Главное — не паникуйте: Вселенная всё равно делает вид, что всё под контролем.", "questions": [ { "label": "1", diff --git a/src/main/webapp/WEB-INF/quest-page.jsp b/src/main/webapp/WEB-INF/quest-page.jsp index b43cb8f..843dd76 100644 --- a/src/main/webapp/WEB-INF/quest-page.jsp +++ b/src/main/webapp/WEB-INF/quest-page.jsp @@ -1,15 +1,20 @@ <%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@include file="header.jsp" %> - +<%----%> + + + New Quest +

${requestScope.quest.title}

-

${requestScope.quest.description}

+

${requestScope.quest.text}

diff --git a/src/main/webapp/static/json/quest-1.json b/src/main/webapp/static/json/quest-1.json deleted file mode 100644 index a0db71f..0000000 --- a/src/main/webapp/static/json/quest-1.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "title": "Космическое приключение", - "description": "Про приключения в космосе", - "questions": [ - { - "label": "1", - "text": "Принять вызов НЛО?", - "answers": [ - { - "nextQuestionLabel": "2", - "text": "Принять вызов" - }, - { - "nextQuestionLabel": "910", - "text": "Отклонить вызов" - } - ] - }, - { - "label": "2", - "text": "Поднимешься на мостик к капитану?", - "answers": [ - { - "nextQuestionLabel": "3", - "text": "Подняться на мостик" - }, - { - "nextQuestionLabel": "910", - "text": "Отказаться подниматься на мостик" - } - ] - }, - { - "label": "3", - "text": "Ты поднялся на мостик. Ты кто?", - "answers": [ - { - "nextQuestionLabel": "810", - "text": "Рассказать правду о себе" - }, - { - "nextQuestionLabel": "911", - "text": "Солгать о себе" - } - ] - }, - { - "label": "810", - "text": "Тебя вернули домой, победа", - "answers": null - }, - { - "label": "910", - "text": "Ты отклонил вызов, поражение", - "answers": null - }, - { - "label": "911", - "text": "Твою ложь разоблачили, поражение", - "answers": null - } - ] -} diff --git a/src/main/webapp/static/json/quest-2.json b/src/main/webapp/static/json/quest-2.json deleted file mode 100644 index 7a7e498..0000000 --- a/src/main/webapp/static/json/quest-2.json +++ /dev/null @@ -1,526 +0,0 @@ -{ - "title": "Тайна Забытого Подземелья", - "description": "Много веков назад дракон Вельдан, хранитель древних знаний, скрылся в недрах горы с Сердцем Дракона — артефактом невообразимой силы, спрятав его в лабиринте, известном как Забытое Подземелье. Тысячи смельчаков отправлялись на поиски реликвии, но никто не вернулся; легенды гласят, что лишь тот, кто проявит мудрость, отвагу и хладнокровие, сможет завладеть Сердцем. Теперь вы — один из искателей: с факелом и мечом перед массивной дверью с драконьей пастью, за которой таятся тьма, сырость и нечто древнее. Дверь медленно приоткрывается — готовы ли вы бросить вызов подземелью?", - "questions": [ - { - "label": "1", - "text": "Вы входите в тёмный коридор. Впереди слышен шорох.", - "answers": [ - { - "nextQuestionLabel": "2", - "text": "Достанете факел и осторожно продвинетесь вперёд.", - "description": "" - }, - { - "nextQuestionLabel": "2", - "text": "Бросите камень в сторону шума, чтобы проверить.", - "description": "Вы пугаете крысу. Путь свободен." - }, - { - "nextQuestionLabel": "910", - "text": "Повернётесь и пойдёте назад.", - "description": "Попадаете в тупик." - }, - { - "nextQuestionLabel": "910", - "text": "Закричите, чтобы отпугнуть возможного врага.", - "description": "Шум привлекает монстров." - } - ] - }, - { - "label": "2", - "text": "Факел осветил три двери. На каждой — символ: огонь, вода, луна. Какую выберете?", - "answers": [ - { - "nextQuestionLabel": "3", - "text": "С символом огня (рискованно, но может вести к сокровищам).", - "description": "В комнате лава. Нужно найти мост." - }, - { - "nextQuestionLabel": "8", - "text": "С символом воды (кажется безопасной).", - "description": "Подземный ручей." - }, - { - "nextQuestionLabel": "910", - "text": "С символом луны (загадочно, возможно, ловушка).", - "description": "Ловушка: пол проваливается." - } - ] - }, - { - "label": "3", - "text": "За дверью — комната с ямой посередине. На стене рычаг. Ваши действия?", - "answers": [ - { - "nextQuestionLabel": "910", - "text": "Дёрнете рычаг сразу.", - "description": "Яма расширяется." - }, - { - "nextQuestionLabel": "4", - "text": "Поищете другой путь, минуя яму.", - "description": "Находите скрытый проход." - }, - { - "nextQuestionLabel": "910", - "text": "Попытаетесь перепрыгнуть яму.", - "description": "Падение." - }, - { - "nextQuestionLabel": "4", - "text": "Кинете камень на противоположную сторону, проверяя пол.", - "description": "Пол безопасен. Переходите." - } - ] - }, - { - "label": "4", - "text": "Рычаг активировал механизм: из стен выдвинулись шипы. Как спастись?", - "answers": [ - { - "nextQuestionLabel": "5", - "text": "Прижмётесь к стене и медленно пройдёте.", - "description": "Успешно проходите." - }, - { - "nextQuestionLabel": "5", - "text": "Побежите напролом, уклоняясь.", - "description": "Ранение. Здоровье снижается." - }, - { - "nextQuestionLabel": "5", - "text": "Найдёте кнопку отключения механизмов.", - "description": "Находите механизм." - }, - { - "nextQuestionLabel": "910", - "text": "Вернётесь назад.", - "description": "Путь заблокирован. " - } - ] - }, - { - "label": "5", - "text": "В этой комнате — статуя дракона. На постаменте надпись: «Скажи имя древнего бога».", - "answers": [ - { - "nextQuestionLabel": "910", - "text": "Азраэль.", - "description": "Статуя атакует." - }, - { - "nextQuestionLabel": "6", - "text": "Таргон.", - "description": "Верно! Статуя пропускает." - }, - { - "nextQuestionLabel": "910", - "text": "Вельдан.", - "description": "Ошибка. Ловушка." - }, - { - "nextQuestionLabel": "5", - "text": "Промолчите и осмотрите комнату ещё раз.", - "description": "Находите надпись с именем: Таргон" - } - ] - }, - { - "label": "6", - "text": "Статуя оживает! Как поступить?", - "answers": [ - { - "nextQuestionLabel": "7", - "text": "Попробуете заговорить с ней.", - "description": "Дракон даёт подсказку." - }, - { - "nextQuestionLabel": "910", - "text": "Атакуете первым.", - "description": "Проигрываете бой." - }, - { - "nextQuestionLabel": "7", - "text": "Бросите в неё магический свиток.", - "description": "Оглушаете дракона." - }, - { - "nextQuestionLabel": "7", - "text": "Спрячетесь за колонну.", - "description": "Дракон уходит. " - } - ] - }, - { - "label": "7", - "text": "Дракон пропускает вас, но предупреждает: «Следующий — не человек». В коридоре два пути:", - "answers": [ - { - "nextQuestionLabel": "8", - "text": "Левый — пахнет сыростью (возможно, вода).", - "description": "Вы вышли к ручью." - }, - { - "nextQuestionLabel": "9", - "text": "Правый — слышны голоса (люди или монстры?).", - "description": "Вы вступили в бой с бандитами и победили их." - }, - { - "nextQuestionLabel": "910", - "text": "Вернётесь к статуе за советом.", - "description": "Статуя исчезла." - } - ] - }, - { - "label": "8", - "text": "В левом коридоре — подземный ручей. Как перебраться?", - "answers": [ - { - "nextQuestionLabel": "910", - "text": "Попытаетесь проплыть.", - "description": "Вас уносит течением." - }, - { - "nextQuestionLabel": "9", - "text": "Найдете упавшее бревно и используете его как мост.", - "description": "Мост готов." - }, - { - "nextQuestionLabel": "8", - "text": "Используете верёвку, чтобы перемахнуть.", - "description": "Не хватает длины." - }, - { - "nextQuestionLabel": "910", - "text": "Поищете обходной путь.", - "description": "Вы заблудились и вас съел дракон." - } - ] - }, - { - "label": "9", - "text": "На другом берегу — дверь с замком. Как вы поступите?", - "answers": [ - { - "nextQuestionLabel": "10", - "text": "Взломаете замок отмычкой.", - "description": "У вас получилось взломать замок." - }, - { - "nextQuestionLabel": "11", - "text": "Ударите по нему мечом.", - "description": "Замок ломается, но шум привлекает врагов." - }, - { - "nextQuestionLabel": "10", - "text": "Поищете ключ поблизости.", - "description": "Вы находите ключ в соседней комнате." - }, - { - "nextQuestionLabel": "910", - "text": "Попробуете выбить дверь плечом.", - "description": "Дверь не поддаётся." - } - ] - }, - { - "label": "10", - "text": "За дверью — зал с четырьмя алтарями. На каждом — предмет: меч, книга, череп, кристалл. Какой возьмёте?", - "answers": [ - { - "nextQuestionLabel": "11", - "text": "Меч (для защиты).", - "description": "Активирует ловушку." - }, - { - "nextQuestionLabel": "14", - "text": "Книгу (возможно, подсказка).", - "description": "Подсказка к загадке. " - }, - { - "nextQuestionLabel": "12", - "text": "Череп (опасно, но магически).", - "description": "Вызывает духа. Вам приходится вступить с ним в бой." - }, - { - "nextQuestionLabel": "13", - "text": "Кристалл (светится, может быть артефактом).", - "description": "Светит в темноте." - } - ] - }, - { - "label": "11", - "text": "Статуя оживает! Как поступить?", - "answers": [ - { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" - } - ] - }, - { - "label": "12", - "text": "Статуя оживает! Как поступить?", - "answers": [ - { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" - } - ] - }, - { - "label": "13", - "text": "Статуя оживает! Как поступить?", - "answers": [ - { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" - } - ] - }, - { - "label": "14", - "text": "Статуя оживает! Как поступить?", - "answers": [ - { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" - } - ] - }, - { - "label": "15", - "text": "Статуя оживает! Как поступить?", - "answers": [ - { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" - } - ] - }, - { - "label": "16", - "text": "Статуя оживает! Как поступить?", - "answers": [ - { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" - } - ] - }, - { - "label": "17", - "text": "Статуя оживает! Как поступить?", - "answers": [ - { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" - } - ] - }, - { - "label": "18", - "text": "Статуя оживает! Как поступить?", - "answers": [ - { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" - } - ] - }, - { - "label": "19", - "text": "Статуя оживает! Как поступить?", - "answers": [ - { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" - } - ] - }, - { - "label": "20", - "text": "Статуя оживает! Как поступить?", - "answers": [ - { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" - }, - { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" - } - ] - }, - { - "label": "810", - "text": "Тебя вернули домой, победа", - "answers": null - }, - { - "label": "910", - "text": "Проигрыш", - "answers": null - } - ] -} diff --git a/src/main/webapp/static/json/quest-3.json b/src/main/webapp/static/json/quest-3.json deleted file mode 100644 index 97d6445..0000000 --- a/src/main/webapp/static/json/quest-3.json +++ /dev/null @@ -1,455 +0,0 @@ -{ - "title": "Автостопом по здравому смыслу (или Не паникуй)", - "description": "Добро пожаловать в квест, который начинается с конца света и быстро переходит к вопросам посложнее. Землю сносят ради гиперпространственной магистрали, предупреждения были вывешены (где-то далеко и давно), а у вас есть лишь выбор, полотенце и крайне смутное представление о происходящем. Впереди — вогоны, сомнительный чай, философские размышления и шанс узнать ответ на Главный вопрос жизни, Вселенной и всего такого. Главное — не паникуйте: Вселенная всё равно делает вид, что всё под контролем.", - "questions": [ - { - "label": "1", - "text": "Вы просыпаетесь и узнаёте, что Землю демонтируют ради гиперпространственной магистрали. Что будете делать?", - "answers": [ - { - "nextQuestionLabel": "2", - "text": "Вы возмущённо требуете документы, разрешения и хотя бы подпись ответственного лица. Вселенная равнодушно зевает." - }, - { - "nextQuestionLabel": "3", - "text": "Вы вспоминаете главное правило галактического путешественника и лихорадочно ищете полотенце. Это внушает необъяснимое спокойствие." - }, - { - "nextQuestionLabel": "4", - "text": "Вы уточняете, будет ли обед до конца света, потому что на голодный желудок апокалипсис переносится хуже." - }, - { - "nextQuestionLabel": "5", - "text": "Вы решаете, что это сон, и пробуете снова уснуть, пока Вселенная не передумала." - } - ] - }, - { - "label": "2", - "text": "Перед вами стоит вогон, держащий папку подозрительно толстых стихов.", - "answers": [ - { - "nextQuestionLabel": "6", - "text": "Вы пытаетесь убежать, но быстро понимаете, что в условиях вакуума это не лучшая стратегия." - }, - { - "nextQuestionLabel": "7", - "text": "Вы представляете себя галактическим юристом и начинаете говорить словами, смысл которых неизвестен даже вам." - }, - { - "nextQuestionLabel": "8", - "text": "Вы вежливо просите почитать стихи вслух, подозревая, что хуже уже не будет." - }, - { - "nextQuestionLabel": "9", - "text": "Вы начинаете плакать заранее, экономя время на эмоциональной реакции." - } - ] - }, - { - "label": "3", - "text": "Полотенце найдено. Оно слегка влажное, но внушает доверие.", - "answers": [ - { - "nextQuestionLabel": "6", - "text": "Вы используете его как универсальное средство защиты от всего непонятного." - }, - { - "nextQuestionLabel": "10", - "text": "Вы накидываете его как плащ и чувствуете себя героем космооперы." - }, - { - "nextQuestionLabel": "5", - "text": "Вы обнимаете полотенце, потому что оно единственное, что сейчас вас понимает." - }, - { - "nextQuestionLabel": "9", - "text": "Вы тут же его теряете, подтверждая законы Вселенной." - } - ] - }, - { - "label": "4", - "text": "Мысли о еде не покидают вас даже в момент уничтожения планеты.", - "answers": [ - { - "nextQuestionLabel": "11", - "text": "Вы решаете сделать бутерброд, игнорируя катастрофу как нечто второстепенное." - }, - { - "nextQuestionLabel": "12", - "text": "Вы жалуетесь Вселенной на несвоевременность происходящего." - }, - { - "nextQuestionLabel": "5", - "text": "Вы смиряетесь с судьбой и принимаете происходящее как должное." - }, - { - "nextQuestionLabel": "13", - "text": "Вы спрашиваете, где чай, потому что без него цивилизация не имеет смысла." - } - ] - }, - { - "label": "5", - "text": "Вы понимаете: это не сон, а реальность, причём весьма навязчивая.", - "answers": [ - { - "nextQuestionLabel": "9", - "text": "Вы начинаете паниковать, громко и без системы." - }, - { - "nextQuestionLabel": "10", - "text": "Вы вспоминаете надпись «DON’T PANIC» и стараетесь выглядеть уверенно." - }, - { - "nextQuestionLabel": "12", - "text": "Вы философски принимаете происходящее, как будто читали об этом раньше.", - "description": "" - }, - { - "nextQuestionLabel": "14", - "text": "Вы выкрикиваете «42!» без всякой причины, но с чувством." - } - ] - }, - { - "label": "6", - "text": "Вас без особых церемоний выбрасывают в открытый космос. Он холодный, бесконечный и явно не собирается извиняться.", - "answers": [ - { - "nextQuestionLabel": "15", - "text": "Вы задерживаете дыхание, словно космос обязан это заметить и проявить такт." - }, - { - "nextQuestionLabel": "9", - "text": "Вы начинаете кричать, несмотря на смутное подозрение, что звук здесь не работает." - }, - { - "nextQuestionLabel": "16", - "text": "Вы решаете положиться на сюжетную броню главного героя, даже если не уверены, что вы главный." - }, - { - "nextQuestionLabel": "12", - "text": "Вы вежливо извиняетесь перед космосом за возможные неудобства. Космос впечатлён." - } - ] - }, - { - "label": "7", - "text": "Вы представились галактическим юристом, и теперь все ждут продолжения.", - "answers": [ - { - "nextQuestionLabel": "8", - "text": "Вы требуете апелляцию, не уточняя, к чему именно. Звучит убедительно." - }, - { - "nextQuestionLabel": "9", - "text": "Вы начинаете путаться в терминах и случайно признаётесь во всех преступлениях сразу." - }, - { - "nextQuestionLabel": "10", - "text": "Против всех законов логики вы выигрываете дело. Вогон выглядит озадаченным." - }, - { - "nextQuestionLabel": "8", - "text": "В качестве «компромисса» вам предлагают послушать стихи." - } - ] - }, - { - "label": "8", - "text": "Поэзия начинается. Это заметно сразу.", - "answers": [ - { - "nextQuestionLabel": "15", - "text": "Вы теряете сознание, руководствуясь инстинктом самосохранения." - }, - { - "nextQuestionLabel": "6", - "text": "Вы хвалите рифму, чем пугаете всех присутствующих, включая автора." - }, - { - "nextQuestionLabel": "9", - "text": "Вы записываете цитаты, чтобы пугать ими знакомых.", - "description": "Не хватает длины." - }, - { - "nextQuestionLabel": "15", - "text": "Вы просите ещё. Реальность слегка трескается." - } - ] - }, - { - "label": "9", - "text": "Ситуация становится заметно хуже, чем была мгновение назад.", - "answers": [ - { - "nextQuestionLabel": "5", - "text": "Вы решаете сдаться и начать всё сначала." - }, - { - "nextQuestionLabel": "12", - "text": "Вы делаете вид, что так и было задумано." - }, - { - "nextQuestionLabel": "14", - "text": "Вы задаёте главный философский вопрос: «В чём вообще смысл?»" - }, - { - "nextQuestionLabel": "3", - "text": "Вы снова начинаете искать полотенце, потому что оно вас ещё ни разу не подводило." - } - ] - }, - { - "label": "10", - "text": "Вас подбирает корабль, который выглядит надёжным ровно настолько, насколько это возможно в галактике.", - "answers": [ - { - "nextQuestionLabel": "16", - "text": "Вы радуетесь спасению и решаете не задавать лишних вопросов." - }, - { - "nextQuestionLabel": "17", - "text": "Вы внимательно разглядываете экипаж, подозревая худшее." - }, - { - "nextQuestionLabel": "9", - "text": "Вы прячетесь за ближайшим ящиком. На всякий случай." - }, - { - "nextQuestionLabel": "11", - "text": "Вы спрашиваете, куда летит корабль, и сразу жалеете об этом." - } - ] - }, - { - "label": "11", - "text": "На борту обсуждают еду, и это внезапно кажется важным.", - "answers": [ - { - "nextQuestionLabel": "13", - "text": "Вы заказываете чай, надеясь, что в этот раз всё будет иначе." - }, - { - "nextQuestionLabel": "14", - "text": "Вы снова поднимаете тему смысла жизни. Не вовремя, но искренне." - }, - { - "nextQuestionLabel": "9", - "text": "Вы пробуете что-то странное, светящееся и, возможно, разумное." - }, - { - "nextQuestionLabel": "12", - "text": "Вы решаете ничего не есть и просто подумать." - } - ] - }, - { - "label": "12", - "text": "Вы внезапно ловите себя на том, что задумались. Это опасно, но уже поздно.", - "answers": [ - { - "nextQuestionLabel": "14", - "text": "Вы размышляете о жизни: зачем она дана, почему всё так странно и кто вообще всё это придумал." - }, - { - "nextQuestionLabel": "14", - "text": "Вы думаете о Вселенной — бесконечной, равнодушной и удивительно хорошо организованной для хаоса." - }, - { - "nextQuestionLabel": "14", - "text": "Вы пытаетесь осмыслить всё сразу: жизнь, Вселенную и остальное, но мысль ускользает." - }, - { - "nextQuestionLabel": "5", - "text": "Вы решаете, что думать — занятие переоценённое, и возвращаетесь к реальности." - } - ] - }, - { - "label": "13", - "text": "Вам приносят чай. Он снова не такой, как надо.", - "answers": [ - { - "nextQuestionLabel": "9", - "text": "Вы возмущаетесь, потому что чай — это вопрос принципа, а не вкуса." - }, - { - "nextQuestionLabel": "17", - "text": "Вы пытаетесь улучшить напиток научным методом, добавляя ингредиенты сомнительного происхождения." - }, - { - "nextQuestionLabel": "12", - "text": "Вы философски принимаете чай как символ несовершенства Вселенной." - }, - { - "nextQuestionLabel": "3", - "text": "Вы отвлекаетесь и спрашиваете, где ваше полотенце." - } - ] - }, - { - "label": "14", - "text": "Наступает торжественный момент. Вам задают Главный вопрос жизни, Вселенной и всего такого. Все замолкают. Даже космос делает вид, что слушает.", - "answers": [ - { - "nextQuestionLabel": "9", - "text": "Вы отвечаете: «Любовь». Это звучит красиво, но Вселенная выглядит разочарованной." - }, - { - "nextQuestionLabel": "9", - "text": "Вы честно говорите: «Деньги». Вселенная вздыхает и делает пометку." - }, - { - "nextQuestionLabel": "20", - "text": "Вы уверенно и без лишних слов произносите: 42. Вселенная одобрительно молчит. Это хороший знак." - }, - { - "nextQuestionLabel": "9", - "text": "Вы заявляете, что вопрос сформулирован некорректно. Вселенная кивает, но продолжает эксперимент." - } - ] - }, - { - "label": "15", - "text": "Вы обнаруживаете, что каким-то образом всё ещё существуете.", - "answers": [ - { - "nextQuestionLabel": "16", - "text": "Вы благодарите Вселенную за то, что она сегодня в хорошем настроении." - }, - { - "nextQuestionLabel": "12", - "text": "Вы долго и искренне удивляетесь происходящему." - }, - { - "nextQuestionLabel": "5", - "text": "Вы проверяете, действительно ли вы живы, на всякий случай." - }, - { - "nextQuestionLabel": "17", - "text": "Вы решаете, что это странно, но, вероятно, нормально." - } - ] - }, - { - "label": "16", - "text": "У вас появляется ощущение, что вы близки к истине. Это тревожит.", - "answers": [ - { - "nextQuestionLabel": "20", - "text": "Вы решаете продолжить путешествие, не вдаваясь в детали." - }, - { - "nextQuestionLabel": "14", - "text": "Вы задаёте ещё один вопрос, потому что не умеете останавливаться." - }, - { - "nextQuestionLabel": "12", - "text": "Вы расслабляетесь и позволяете событиям происходить." - }, - { - "nextQuestionLabel": "3", - "text": "Вы автоматически проверяете, при вас ли полотенце." - } - ] - }, - { - "label": "17", - "text": "Перед вами андроид с крайне пессимистичным взглядом на бытие.", - "answers": [ - { - "nextQuestionLabel": "12", - "text": "Вы искренне сочувствуете ему. Андроид растерян: такого он не ожидал." - }, - { - "nextQuestionLabel": "9", - "text": "Вы позволяете ему высказаться. Через некоторое время жалеете об этом." - }, - { - "nextQuestionLabel": "14", - "text": "Вы спрашиваете его о смысле жизни. Он подтверждает, что всё плохо." - }, - { - "nextQuestionLabel": "16", - "text": "Вы медленно отходите, стараясь не привлекать внимания." - } - ] - }, - { - "label": "18", - "text": "Вселенная смотрит на вас с плохо скрываемым интересом.", - "answers": [ - { - "nextQuestionLabel": "12", - "text": "Вы почтительно кланяетесь, считая это уместным." - }, - { - "nextQuestionLabel": "16", - "text": "Вы улыбаетесь, демонстрируя уверенность, которой у вас нет." - }, - { - "nextQuestionLabel": "20", - "text": "Вы прямо спрашиваете: «Ну и что дальше?»" - }, - { - "nextQuestionLabel": "9", - "text": "Вы решаете убежать, пока всё снова не усложнилось." - } - ] - }, - { - "label": "19", - "text": "Вы чувствуете, что ответ уже близко, но всё ещё сомневаетесь.", - "answers": [ - { - "nextQuestionLabel": "20", - "text": "Вы делаете вывод и принимаете его без проверки.", - "description": "" - }, - { - "nextQuestionLabel": "9", - "text": "Вы решаете всё усложнить, потому что слишком просто не бывает.", - "description": "" - }, - { - "nextQuestionLabel": "14", - "text": "Вы спрашиваете ещё раз, на всякий случай." - }, - { - "nextQuestionLabel": "16", - "text": "Вы напоминаете себе главное правило — не паниковать." - } - ] - }, - { - "label": "20", - "text": "После всего пережитого вы наконец понимаете главное.", - "answers": [ - { - "nextQuestionLabel": "810", - "text": "Всегда носи полотенце" - }, - { - "nextQuestionLabel": "810", - "text": "Не паникуй" - }, - { - "nextQuestionLabel": "810", - "text": "Ответ — 42" - }, - { - "nextQuestionLabel": "810", - "text": "Всё вышеперечисленное" - } - ] - }, - { - "label": "810", - "text": "Поздравляем! Вы прошли квест, не сломали Вселенную и, возможно, даже стали немного мудрее.", - "answers": null - } - ] -} From 39e6c4eb9c2e88bffba224e104b1efee92b843a1 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Fri, 23 Jan 2026 15:07:23 +0500 Subject: [PATCH 15/65] minor fixes --- src/main/webapp/WEB-INF/home.jsp | 2 +- src/main/webapp/images/background-main.png | Bin 0 -> 239360 bytes src/main/webapp/images/cat.png | Bin 98607 -> 0 bytes src/main/webapp/static/css/style.css | 1 - 4 files changed, 1 insertion(+), 2 deletions(-) create mode 100644 src/main/webapp/images/background-main.png delete mode 100644 src/main/webapp/images/cat.png diff --git a/src/main/webapp/WEB-INF/home.jsp b/src/main/webapp/WEB-INF/home.jsp index 108a039..cb98ba8 100644 --- a/src/main/webapp/WEB-INF/home.jsp +++ b/src/main/webapp/WEB-INF/home.jsp @@ -18,7 +18,7 @@
-
+

Квесты

diff --git a/src/main/webapp/images/background-main.png b/src/main/webapp/images/background-main.png new file mode 100644 index 0000000000000000000000000000000000000000..e96fe706d097374a2dab0683def1128e762fc259 GIT binary patch literal 239360 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�m&obI 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 C;*L_zkBHJ$139{;aA)iB4Z-|)R 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%0Aj+deS- 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 Date: Fri, 23 Jan 2026 15:43:31 +0500 Subject: [PATCH 16/65] ADD html/css for quest page --- src/main/resources/quest-1.json | 4 +-- src/main/webapp/WEB-INF/quest-page.jsp | 38 ++++++++++++++++++-------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/main/resources/quest-1.json b/src/main/resources/quest-1.json index 0b6f57a..8827a3f 100644 --- a/src/main/resources/quest-1.json +++ b/src/main/resources/quest-1.json @@ -1,7 +1,7 @@ { "title": "Космическое приключение", - "description": "Про приключения в космосе", - "text": "Про приключения в космосе", + "description": "Ты — космический путешественник, чей корабль внезапно получает загадочный сигнал от неопознанного объекта...", + "text": "Ты — космический путешественник, чей корабль внезапно получает загадочный сигнал от неопознанного объекта на границе изученной галактики. Впереди — неизвестность, за каждым поворотом таятся тайны космоса, а каждое решение может стать судьбоносным. Готов ли ты принять вызов Вселенной и отправиться в путешествие, где правда и ложь, смелость и осторожность, судьба и случай переплетутся в одну невероятную историю?", "questions": [ { "label": "1", diff --git a/src/main/webapp/WEB-INF/quest-page.jsp b/src/main/webapp/WEB-INF/quest-page.jsp index 843dd76..6d2fbb8 100644 --- a/src/main/webapp/WEB-INF/quest-page.jsp +++ b/src/main/webapp/WEB-INF/quest-page.jsp @@ -11,18 +11,32 @@ New Quest - -

${requestScope.quest.title}

- -

${requestScope.quest.text}

- -
- - - - - - +
+
+
+
+
+
+
+
+
+

${requestScope.quest.title}

+

${requestScope.quest.text}

+ + + + + + +
+
+
+
+
+
+
+
+
From ea524d8968291b20fa14aee5730960554bf46f15 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Sun, 25 Jan 2026 16:50:55 +0500 Subject: [PATCH 17/65] MOVE quest info block to play-game page --- .../com/javarush/vasileva/cmd/PlayGame.java | 4 + .../com/javarush/vasileva/cmd/QuestPage.java | 22 --- src/main/webapp/WEB-INF/home.jsp | 4 +- src/main/webapp/WEB-INF/play-game.jsp | 146 ++++++++++-------- src/main/webapp/WEB-INF/quest-page.jsp | 42 ----- .../css/Bold-BS4-Full-Page-Image-Header.css | 13 ++ 6 files changed, 100 insertions(+), 131 deletions(-) delete mode 100644 src/main/java/com/javarush/vasileva/cmd/QuestPage.java delete mode 100644 src/main/webapp/WEB-INF/quest-page.jsp diff --git a/src/main/java/com/javarush/vasileva/cmd/PlayGame.java b/src/main/java/com/javarush/vasileva/cmd/PlayGame.java index ab9f6c7..99551eb 100644 --- a/src/main/java/com/javarush/vasileva/cmd/PlayGame.java +++ b/src/main/java/com/javarush/vasileva/cmd/PlayGame.java @@ -29,6 +29,10 @@ public String doGet(HttpServletRequest req) { .orElseThrow(() -> new IllegalArgumentException("Quest is not found: id=" + questIdStr)); req.setAttribute("quest", quest); + if (questionIdStr == null || questionIdStr.isEmpty()) { + return getView(); + } + Optional currentQuestion = questionService.findCurrentQuestion(questionIdStr, quest); if (currentQuestion.isPresent()) { req.setAttribute("question", currentQuestion.get()); diff --git a/src/main/java/com/javarush/vasileva/cmd/QuestPage.java b/src/main/java/com/javarush/vasileva/cmd/QuestPage.java deleted file mode 100644 index 03b145c..0000000 --- a/src/main/java/com/javarush/vasileva/cmd/QuestPage.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.javarush.vasileva.cmd; - -import com.javarush.vasileva.entity.Quest; -import com.javarush.vasileva.service.QuestService; -import jakarta.servlet.http.HttpServletRequest; - -public class QuestPage implements Command { - private final QuestService questService; - - public QuestPage(QuestService questService) { - this.questService = questService; - } - - @Override - public String doGet(HttpServletRequest req) { - String strId = req.getParameter("id"); - Quest quest = questService.getValidatedQuest(strId) - .orElseThrow(() -> new IllegalArgumentException("Quest is not found: id=" + strId)); - req.setAttribute("quest", quest); - return getView(); - } -} diff --git a/src/main/webapp/WEB-INF/home.jsp b/src/main/webapp/WEB-INF/home.jsp index cb98ba8..bbd582b 100644 --- a/src/main/webapp/WEB-INF/home.jsp +++ b/src/main/webapp/WEB-INF/home.jsp @@ -19,7 +19,7 @@
-

Квесты

+<%--

Квесты

--%>
@@ -29,7 +29,7 @@

${quest.title}

${quest.description}

-
diff --git a/src/main/webapp/WEB-INF/update-quest.jsp b/src/main/webapp/WEB-INF/update-quest.jsp deleted file mode 100644 index f357ab1..0000000 --- a/src/main/webapp/WEB-INF/update-quest.jsp +++ /dev/null @@ -1,42 +0,0 @@ -<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" %> -<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> -<%@include file="header.jsp" %> - - - - - - - - Title - - -
-
-
-
-
-
-

Выберите квест

- - - -
-
- - -
- -
-
-
-
-
-
-
- - From 83a791f9cc4965625de60c47ee08fa36a886c789 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Mon, 26 Jan 2026 16:06:42 +0500 Subject: [PATCH 23/65] minor fixes --- .../vasileva/controller/FrontController.java | 2 +- .../javarush/vasileva/mapper/QuestMapper.java | 31 +------------------ src/main/webapp/WEB-INF/edit-quest.jsp | 9 ------ src/main/webapp/WEB-INF/home.jsp | 3 -- src/main/webapp/WEB-INF/play-game.jsp | 2 -- 5 files changed, 2 insertions(+), 45 deletions(-) diff --git a/src/main/java/com/javarush/vasileva/controller/FrontController.java b/src/main/java/com/javarush/vasileva/controller/FrontController.java index a22b0f2..fea1135 100644 --- a/src/main/java/com/javarush/vasileva/controller/FrontController.java +++ b/src/main/java/com/javarush/vasileva/controller/FrontController.java @@ -13,7 +13,7 @@ import java.io.IOException; -@WebServlet({"", "/home", "/list-user", "/edit-user", "/quest-page", "/play-game", "/create-quest", "/update-quest", "/edit-quest"}) +@WebServlet({"", "/home", "/list-user", "/edit-user", "/play-game", "/edit-quest"}) public class FrontController extends HttpServlet { private final HttpResolver httpResolver = Winter.find(HttpResolver.class); diff --git a/src/main/java/com/javarush/vasileva/mapper/QuestMapper.java b/src/main/java/com/javarush/vasileva/mapper/QuestMapper.java index 306e5eb..7b85ab3 100644 --- a/src/main/java/com/javarush/vasileva/mapper/QuestMapper.java +++ b/src/main/java/com/javarush/vasileva/mapper/QuestMapper.java @@ -14,53 +14,24 @@ public QuestMapper() { this.objectMapper = new ObjectMapper(); } - /** - * Читает JSON файл и преобразует в объект Quest. - * @param filePath Путь к JSON файлу - * @return Объект Quest - * @throws IOException Если файл не найден или ошибка парсинга - */ public Quest readFromJson(String filePath) throws IOException { -// File file = new File(filePath); -// return objectMapper.readValue(file, Quest.class); - InputStream inputStream = getClass().getResourceAsStream(filePath); - if (inputStream == null) { throw new IOException("Ресурс не найден: " + filePath); } - - try (inputStream) { // try-with-resources для автоматического закрытия + try (inputStream) { return objectMapper.readValue(inputStream, Quest.class); } } - /** - * Сохраняет объект Quest в JSON файл. - * @param quest Объект квеста - * @param filePath Путь для сохранения - * @throws IOException Если ошибка записи - */ public void writeToJson(Quest quest, String filePath) throws IOException { objectMapper.writeValue(new File(filePath), quest); } - /** - * Преобразует JSON строку в объект Quest. - * @param jsonString JSON в виде строки - * @return Объект Quest - * @throws IOException Если ошибка парсинга - */ public Quest fromJsonString(String jsonString) throws IOException { return objectMapper.readValue(jsonString, Quest.class); } - /** - * Преобразует объект Quest в JSON строку. - * @param quest Объект квеста - * @return JSON строка - * @throws IOException Если ошибка преобразования - */ public String toJsonString(Quest quest) throws IOException { return objectMapper.writeValueAsString(quest); } diff --git a/src/main/webapp/WEB-INF/edit-quest.jsp b/src/main/webapp/WEB-INF/edit-quest.jsp index 4690eb4..41144c9 100644 --- a/src/main/webapp/WEB-INF/edit-quest.jsp +++ b/src/main/webapp/WEB-INF/edit-quest.jsp @@ -23,15 +23,6 @@ ${requestScope.edit ? 'Редактирование квеста' : 'Новый квест'} -<%-- --%> -<%--
--%> -<%--
Выберите квест для редактирования:
--%> -<%-- --%> -<%-- ${quest.title}--%> -<%-- --%> -<%--
--%> -<%--
--%> -
+ placeholder="Введите JSON квеста">${not empty sessionScope.questJson ? sessionScope.questJson : requestScope.questJson} +
diff --git a/src/main/webapp/WEB-INF/edit-user.jsp b/src/main/webapp/WEB-INF/edit-user.jsp index 8874fb4..5edcc32 100644 --- a/src/main/webapp/WEB-INF/edit-user.jsp +++ b/src/main/webapp/WEB-INF/edit-user.jsp @@ -23,7 +23,9 @@ value="${requestScope.user.login}" placeholder="Логин не менее 3-х символов" class="form-control input-md" - required=""> + required + maxlength="15" + minlength="3">
@@ -37,7 +39,7 @@ value="${requestScope.user.email}" placeholder="Электронная почта" class="form-control input-md" - required=""> + required>
@@ -50,7 +52,9 @@ value="${requestScope.user.password}" placeholder="Пароль не менее 4 символов" class="form-control input-md" - required=""> + required + maxlength="15" + minlength="4">
diff --git a/src/main/webapp/WEB-INF/error-page.jsp b/src/main/webapp/WEB-INF/error-page.jsp index 476cfd8..96ff32c 100644 --- a/src/main/webapp/WEB-INF/error-page.jsp +++ b/src/main/webapp/WEB-INF/error-page.jsp @@ -23,28 +23,17 @@
-
-
-
- -
- -
- -
diff --git a/src/main/webapp/WEB-INF/home.jsp b/src/main/webapp/WEB-INF/home.jsp index 3b1223a..f3470b3 100644 --- a/src/main/webapp/WEB-INF/home.jsp +++ b/src/main/webapp/WEB-INF/home.jsp @@ -2,16 +2,17 @@ <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@include file="header.jsp" %> + - + Home - +
-
+
@@ -27,15 +28,16 @@

${quest.description}

-
+
-
+
@@ -55,6 +57,7 @@
+
diff --git a/src/main/webapp/WEB-INF/register.jsp b/src/main/webapp/WEB-INF/register.jsp index b08dd3d..074517d 100644 --- a/src/main/webapp/WEB-INF/register.jsp +++ b/src/main/webapp/WEB-INF/register.jsp @@ -18,10 +18,6 @@
- -
${error}
-
-
@@ -29,7 +25,9 @@ class="form-control" id="login" name="login" - required> + required + maxlength="15" + minlength="3">
@@ -45,7 +43,9 @@ class="form-control" id="password" name="password" - required> + required + maxlength="15" + minlength="4">
diff --git a/src/main/webapp/WEB-INF/stats.jsp b/src/main/webapp/WEB-INF/stats.jsp index 152393e..298c217 100644 --- a/src/main/webapp/WEB-INF/stats.jsp +++ b/src/main/webapp/WEB-INF/stats.jsp @@ -11,7 +11,7 @@ Statistics - +

Статистика игрока

diff --git a/src/main/webapp/static/css/Bold-BS4-Full-Page-Image-Header.css b/src/main/webapp/static/css/Bold-BS4-Full-Page-Image-Header.css index 606fac8..808140b 100644 --- a/src/main/webapp/static/css/Bold-BS4-Full-Page-Image-Header.css +++ b/src/main/webapp/static/css/Bold-BS4-Full-Page-Image-Header.css @@ -30,11 +30,6 @@ box-sizing: border-box; } -/*.text-white {*/ -/* width: 100%;*/ -/* margin: 0 auto;*/ -/*}*/ - @media (max-width: 768px) { .text-white { width: 95%; From db4d95a2bcbf6be2e20b868d7d4b1287aa2c5201 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Mon, 2 Feb 2026 14:43:24 +0500 Subject: [PATCH 48/65] ADD Game --- .../com/javarush/vasileva/cmd/EditQuest.java | 2 +- .../com/javarush/vasileva/cmd/EditUser.java | 2 +- .../java/com/javarush/vasileva/cmd/Home.java | 2 +- .../com/javarush/vasileva/cmd/PlayGame.java | 91 +++++-------- .../com/javarush/vasileva/cmd/UserList.java | 2 +- .../com/javarush/vasileva/config/Winter.java | 2 +- .../com/javarush/vasileva/entity/Game.java | 19 +++ .../javarush/vasileva/game/GameEngine.java | 41 ++++++ .../com/javarush/vasileva/game/GameState.java | 18 +++ .../vasileva/repository/GameRepository.java | 14 ++ .../repository/InMemoryGameRepository.java | 35 +++++ .../vasileva/service/GameService.java | 55 ++++++++ .../vasileva/service/QuestService.java | 8 +- .../vasileva/service/QuestionService.java | 24 +--- .../vasileva/service/UserService.java | 8 +- .../java/com/javarush/vasileva/util/Key.java | 9 +- .../com/javarush/vasileva/util/Value.java | 17 ++- src/main/resources/quest-1.json | 12 +- src/main/resources/quest-3.json | 10 +- src/main/webapp/WEB-INF/play-game.jsp | 123 +++++++----------- 20 files changed, 307 insertions(+), 187 deletions(-) create mode 100644 src/main/java/com/javarush/vasileva/entity/Game.java create mode 100644 src/main/java/com/javarush/vasileva/game/GameEngine.java create mode 100644 src/main/java/com/javarush/vasileva/game/GameState.java create mode 100644 src/main/java/com/javarush/vasileva/repository/GameRepository.java create mode 100644 src/main/java/com/javarush/vasileva/repository/InMemoryGameRepository.java create mode 100644 src/main/java/com/javarush/vasileva/service/GameService.java diff --git a/src/main/java/com/javarush/vasileva/cmd/EditQuest.java b/src/main/java/com/javarush/vasileva/cmd/EditQuest.java index 0b18cc5..453cf4f 100644 --- a/src/main/java/com/javarush/vasileva/cmd/EditQuest.java +++ b/src/main/java/com/javarush/vasileva/cmd/EditQuest.java @@ -37,7 +37,7 @@ public String doGet(HttpServletRequest req) { String questIdStr = req.getParameter(QUEST_ID); if (questIdStr != null && !questIdStr.isEmpty()) { - Quest quest = questService.findById(questIdStr) + Quest quest = questService.getValidatedQuest(questIdStr) .orElseThrow(() -> new AppException(QUEST_NOT_FOUND + questIdStr)); req.setAttribute(EDIT, true); try { diff --git a/src/main/java/com/javarush/vasileva/cmd/EditUser.java b/src/main/java/com/javarush/vasileva/cmd/EditUser.java index 4a0bd86..e694259 100644 --- a/src/main/java/com/javarush/vasileva/cmd/EditUser.java +++ b/src/main/java/com/javarush/vasileva/cmd/EditUser.java @@ -22,7 +22,7 @@ public EditUser(UserService userService) { @Override public String doGet(HttpServletRequest req) { String stringId = req.getParameter("id"); - Optional optionalUser = userService.findById(stringId); + Optional optionalUser = userService.getValidatedUser(stringId); optionalUser.ifPresent(user -> req.setAttribute("user", user)); return getView(); } diff --git a/src/main/java/com/javarush/vasileva/cmd/Home.java b/src/main/java/com/javarush/vasileva/cmd/Home.java index 82758e8..ad1921a 100644 --- a/src/main/java/com/javarush/vasileva/cmd/Home.java +++ b/src/main/java/com/javarush/vasileva/cmd/Home.java @@ -29,7 +29,7 @@ public String doGet(HttpServletRequest req) { public String doDelete(HttpServletRequest req) { Helpers.checkAdminAuthorization(req, DELETE_QUEST_AUTH_ERROR); String questIdStr = req.getParameter(QUEST_ID); - Quest quest = questService.findById(questIdStr) + Quest quest = questService.getValidatedQuest(questIdStr) .orElseThrow(() -> new IllegalArgumentException(QUEST_NOT_FOUND + questIdStr)); req.setAttribute(QUEST, quest); questService.delete(quest); diff --git a/src/main/java/com/javarush/vasileva/cmd/PlayGame.java b/src/main/java/com/javarush/vasileva/cmd/PlayGame.java index 7c07c59..b044557 100644 --- a/src/main/java/com/javarush/vasileva/cmd/PlayGame.java +++ b/src/main/java/com/javarush/vasileva/cmd/PlayGame.java @@ -2,93 +2,64 @@ import com.javarush.vasileva.entity.*; import com.javarush.vasileva.exception.AppException; -import com.javarush.vasileva.repository.UserRepository; -import com.javarush.vasileva.service.AnswerService; -import com.javarush.vasileva.service.QuestService; -import com.javarush.vasileva.service.QuestionService; +import com.javarush.vasileva.service.GameService; import com.javarush.vasileva.util.Helpers; -import com.javarush.vasileva.util.Value; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; -import java.util.List; -import java.util.Optional; - import static com.javarush.vasileva.util.Key.*; +import static com.javarush.vasileva.util.Value.*; @SuppressWarnings("unused") public class PlayGame implements Command { - private final QuestService questService; - private final QuestionService questionService; - private final AnswerService answerService; - private final UserRepository userRepository; - - public PlayGame(QuestService questService, - QuestionService questionService, - AnswerService answerService, - UserRepository userRepository) { - this.questService = questService; - this.questionService = questionService; - this.answerService = answerService; - this.userRepository = userRepository; + + private final GameService gameService; + + public PlayGame(GameService gameService) { + this.gameService = gameService; } @Override public String doGet(HttpServletRequest req) { HttpSession session = req.getSession(); - User user = (User) session.getAttribute("user"); + User user = (User) session.getAttribute(USER); if (user == null) { - throw new AppException("Необходимо авторизоваться"); + throw new AppException(AUTH_ERROR); } - String questIdStr = req.getParameter(QUEST_ID); - String questionIdStr = req.getParameter(QUESTION_ID); - - Quest quest = questService.findById(questIdStr) - .orElseThrow(() -> new AppException(Value.QUEST_NOT_FOUND + questIdStr)); - req.setAttribute(QUEST, quest); - - if (questionIdStr == null || questionIdStr.isEmpty()) { - return getView(); - } + Long questId = Helpers.parseStringToLong(req.getParameter(QUEST_ID)); + Long gameId = req.getParameter(GAME_ID) != null + ? Helpers.parseStringToLong(req.getParameter(GAME_ID)) + : null; - Optional currentQuestion = questionService.findCurrentQuestion(questionIdStr, quest); - if (currentQuestion.isPresent()) { - req.setAttribute(QUESTION, currentQuestion.get()); - List answers = currentQuestion.get().getAnswers(); - if (answers == null || answers.isEmpty()) { - req.setAttribute(NO_ANSWERS, true); - user.setGameNumber(user.getGameNumber() + 1); - userRepository.update(user); - session.setAttribute(USER, user); - System.out.println(user); - } else { - req.setAttribute(ANSWERS, answers); - } + Game game; + if (gameId == null) { + game = gameService.startNewGame(questId, user.getId()); } else { - req.setAttribute(GAME_OVER, true); + game = gameService.getGameById(gameId).orElseThrow(() -> new AppException(GAME_NOT_FOUND)); } + + req.setAttribute(GAME, game); + req.setAttribute(STATE, game.getGameState().isCompleted()); + req.setAttribute(QUEST, game.getGameState().getCurrentQuest()); + return getView(); } @Override public String doPost(HttpServletRequest req) throws AppException { - String questIdStr = req.getParameter(QUEST_ID); - String answerIdStr = req.getParameter(SELECTED_ANSWER_ID); + HttpSession session = req.getSession(); + User user = (User) session.getAttribute(USER); - if (questIdStr == null || answerIdStr == null) { - return getView() + "?" + QUEST_ID + "=" + questIdStr; // Return to the same page - } + Long gameId = Helpers.parseStringToLong(req.getParameter(GAME_ID)); + Long answerId = Helpers.parseStringToLong(req.getParameter(SELECTED_ANSWER_ID)); - long questId = Helpers.parseStringToLong(questIdStr); - long answerId = Helpers.parseStringToLong(answerIdStr); + Game updatedGame = gameService.advanceGame(gameId, answerId); - Optional answer = answerService.findById(answerId); - if (answer.isEmpty()) { - return getView() + "?" + QUEST_ID + "=" + questId; - } - long nextQuestionId = questionService.findNextQuestionId(questId, answer.get()); - return getView() + "?" + QUEST_ID + "=" + questId + "&" + QUESTION_ID + "=" + nextQuestionId; + req.setAttribute(GAME, updatedGame); + req.setAttribute(USER, user); + + return getView() + "?" + GAME_ID + "=" + updatedGame.getId() + "&" + QUEST_ID + "=" + updatedGame.getGameState().getCurrentQuest().getId(); } } diff --git a/src/main/java/com/javarush/vasileva/cmd/UserList.java b/src/main/java/com/javarush/vasileva/cmd/UserList.java index a80bb00..7b95dac 100644 --- a/src/main/java/com/javarush/vasileva/cmd/UserList.java +++ b/src/main/java/com/javarush/vasileva/cmd/UserList.java @@ -33,7 +33,7 @@ public String doGet(HttpServletRequest request) { @Override public String doDelete(HttpServletRequest req) { String userIdStr = req.getParameter(USER_ID); - User user = userService.findById(userIdStr) + User user = userService.getValidatedUser(userIdStr) .orElseThrow(() -> new AppException(USER_NOT_FOUND + userIdStr)); req.setAttribute(USER, user); userService.delete(user); diff --git a/src/main/java/com/javarush/vasileva/config/Winter.java b/src/main/java/com/javarush/vasileva/config/Winter.java index 9f18661..53de644 100644 --- a/src/main/java/com/javarush/vasileva/config/Winter.java +++ b/src/main/java/com/javarush/vasileva/config/Winter.java @@ -15,7 +15,7 @@ public class Winter { public static T find(Class aClass) { Object component = components.get(aClass); if (component == null) { - Constructor constructor = aClass.getDeclaredConstructors()[0]; + Constructor constructor = aClass.getConstructors()[0]; Class[] parameterTypes = constructor.getParameterTypes(); Object[] parameters = new Object[parameterTypes.length]; for (int i = 0; i < parameters.length; i++) { diff --git a/src/main/java/com/javarush/vasileva/entity/Game.java b/src/main/java/com/javarush/vasileva/entity/Game.java new file mode 100644 index 0000000..4df0145 --- /dev/null +++ b/src/main/java/com/javarush/vasileva/entity/Game.java @@ -0,0 +1,19 @@ +package com.javarush.vasileva.entity; + +import com.javarush.vasileva.game.GameState; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class Game { + private Long id; + private Long questId; + private Long userId; + private Long currentQuestionId; + private GameState gameState; +} diff --git a/src/main/java/com/javarush/vasileva/game/GameEngine.java b/src/main/java/com/javarush/vasileva/game/GameEngine.java new file mode 100644 index 0000000..5bc5552 --- /dev/null +++ b/src/main/java/com/javarush/vasileva/game/GameEngine.java @@ -0,0 +1,41 @@ +package com.javarush.vasileva.game; + +import com.javarush.vasileva.entity.Answer; +import com.javarush.vasileva.entity.Quest; +import com.javarush.vasileva.entity.Question; +import com.javarush.vasileva.entity.User; +import com.javarush.vasileva.exception.AppException; +import com.javarush.vasileva.service.AnswerService; +import com.javarush.vasileva.service.QuestionService; +import com.javarush.vasileva.util.Value; + + +import static com.javarush.vasileva.util.Value.ANSWER_NOT_FOUND; +import static com.javarush.vasileva.util.Value.QUESTION_NOT_FOUND; + +public class GameEngine { + private final QuestionService questionService; + private final AnswerService answerService; + + public GameEngine(QuestionService questionService, AnswerService answerService) { + this.questionService = questionService; + this.answerService = answerService; + } + + public GameState startGame(User user, Quest quest) { + Question startQuestion = questionService.findById(quest.getStartQuestionId()) + .orElseThrow(() -> new AppException(QUESTION_NOT_FOUND)); + boolean isFinalQuestion = questionService.isFinalQuestion(startQuestion); + + return new GameState(quest, startQuestion, user, isFinalQuestion); + } + + public GameState advanceGame(GameState currentState, Long answerId) { + Answer answer = answerService.findById(answerId).orElseThrow(() -> new AppException(ANSWER_NOT_FOUND)); + String nextQuestionLabel = answer.getNextQuestionLabel(); + Question nextQuestion = questionService.getByQuestionLabelAndQuestId(nextQuestionLabel, currentState.getCurrentQuest().getId()) + .orElseThrow(() -> new AppException(Value.QUESTION_NOT_FOUND + nextQuestionLabel)); + boolean isFinalQuestion = questionService.isFinalQuestion(nextQuestion); + return new GameState(currentState.getCurrentQuest(), nextQuestion, currentState.getUser(), isFinalQuestion); + } +} diff --git a/src/main/java/com/javarush/vasileva/game/GameState.java b/src/main/java/com/javarush/vasileva/game/GameState.java new file mode 100644 index 0000000..91ada86 --- /dev/null +++ b/src/main/java/com/javarush/vasileva/game/GameState.java @@ -0,0 +1,18 @@ +package com.javarush.vasileva.game; + +import com.javarush.vasileva.entity.Quest; +import com.javarush.vasileva.entity.Question; +import com.javarush.vasileva.entity.User; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class GameState { + private Quest currentQuest; + private Question currentQuestion; + private User user; + private boolean isCompleted; +} diff --git a/src/main/java/com/javarush/vasileva/repository/GameRepository.java b/src/main/java/com/javarush/vasileva/repository/GameRepository.java new file mode 100644 index 0000000..bc33e31 --- /dev/null +++ b/src/main/java/com/javarush/vasileva/repository/GameRepository.java @@ -0,0 +1,14 @@ +package com.javarush.vasileva.repository; + +import com.javarush.vasileva.entity.Game; + +import java.util.Optional; + +public interface GameRepository { + + Game save(Game game); + + Optional findById(long id); + + void delete(Game game); +} diff --git a/src/main/java/com/javarush/vasileva/repository/InMemoryGameRepository.java b/src/main/java/com/javarush/vasileva/repository/InMemoryGameRepository.java new file mode 100644 index 0000000..d3db2f6 --- /dev/null +++ b/src/main/java/com/javarush/vasileva/repository/InMemoryGameRepository.java @@ -0,0 +1,35 @@ +package com.javarush.vasileva.repository; + +import com.javarush.vasileva.entity.Game; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + +public class InMemoryGameRepository implements GameRepository { + + private final Map map = new ConcurrentHashMap<>(); + private final AtomicLong generatedId = new AtomicLong(0); + + @Override + public Game save(Game game) { + if (game.getId() == null) { + game.setId(generatedId.incrementAndGet()); + } + map.put(game.getId(), game); + return game; + } + + @Override + public Optional findById(long id) { + return Optional.ofNullable(map.get(id)); + } + + @Override + public void delete(Game game) { + if (game != null && game.getId() != null) { + map.remove(game.getId()); + } + } +} diff --git a/src/main/java/com/javarush/vasileva/service/GameService.java b/src/main/java/com/javarush/vasileva/service/GameService.java new file mode 100644 index 0000000..9a442b3 --- /dev/null +++ b/src/main/java/com/javarush/vasileva/service/GameService.java @@ -0,0 +1,55 @@ +package com.javarush.vasileva.service; + +import com.javarush.vasileva.entity.Game; +import com.javarush.vasileva.entity.Quest; +import com.javarush.vasileva.entity.User; +import com.javarush.vasileva.exception.AppException; +import com.javarush.vasileva.game.GameEngine; +import com.javarush.vasileva.game.GameState; +import com.javarush.vasileva.repository.InMemoryGameRepository; + +import java.util.Optional; + +import static com.javarush.vasileva.util.Value.*; + +public class GameService { + private final InMemoryGameRepository gameRepository; + private final UserService userService; + private final QuestService questService; + private final GameEngine gameEngine; + + public GameService(InMemoryGameRepository gameRepository, + UserService userService, + QuestService questService, + GameEngine gameEngine) { + this.gameRepository = gameRepository; + this.userService = userService; + this.questService = questService; + this.gameEngine = gameEngine; + } + + public Game startNewGame(Long questId, Long userId) { + User user = userService.findById(userId).orElseThrow(() -> new AppException(USER_NOT_FOUND)); + Quest quest = questService.findById(questId).orElseThrow(() -> new AppException(QUEST_NOT_FOUND)); + GameState initialState = gameEngine.startGame(user, quest); + Game game = Game.builder() + .questId(questId) + .userId(userId) + .currentQuestionId(initialState.getCurrentQuestion().getGeneratedId()) + .gameState(initialState) + .build(); + return gameRepository.save(game); + } + + public Game advanceGame(Long gameId, Long answerId) { + Game game = gameRepository.findById(gameId).orElseThrow(() -> new AppException("Game not found")); + GameState nextState = gameEngine.advanceGame(game.getGameState(), answerId); + game.setCurrentQuestionId(nextState.getCurrentQuestion().getGeneratedId()); + game.setGameState(nextState); + return gameRepository.save(game); + } + + public Optional getGameById(Long gameId) { + return gameRepository.findById(gameId); + } +} diff --git a/src/main/java/com/javarush/vasileva/service/QuestService.java b/src/main/java/com/javarush/vasileva/service/QuestService.java index 0473520..837fcf1 100644 --- a/src/main/java/com/javarush/vasileva/service/QuestService.java +++ b/src/main/java/com/javarush/vasileva/service/QuestService.java @@ -19,8 +19,8 @@ public List getAll() { return questRepository.getAll(); } - public Optional findById(String questIdStr) { - return getValidatedQuest(questIdStr); + public Optional findById(Long questId) { + return questRepository.findById(questId); } public void create(Quest quest) { @@ -35,11 +35,11 @@ public void delete(Quest quest) { questRepository.delete(quest); } - private Optional getValidatedQuest(String questIdStr) { + public Optional getValidatedQuest(String questIdStr) { if (questIdStr == null || questIdStr.isEmpty()) { return Optional.empty(); } Long questId = Helpers.parseStringToLong(questIdStr); - return questRepository.findById(questId); + return findById(questId); } } diff --git a/src/main/java/com/javarush/vasileva/service/QuestionService.java b/src/main/java/com/javarush/vasileva/service/QuestionService.java index 8d32e53..aa44766 100644 --- a/src/main/java/com/javarush/vasileva/service/QuestionService.java +++ b/src/main/java/com/javarush/vasileva/service/QuestionService.java @@ -1,12 +1,8 @@ package com.javarush.vasileva.service; import com.javarush.vasileva.entity.Answer; -import com.javarush.vasileva.entity.Quest; import com.javarush.vasileva.entity.Question; -import com.javarush.vasileva.exception.AppException; import com.javarush.vasileva.repository.QuestionRepository; -import com.javarush.vasileva.util.Helpers; -import com.javarush.vasileva.util.Value; import java.util.List; import java.util.Optional; @@ -27,7 +23,7 @@ public List getAll() { return questionRepository.getAll(); } - public Optional get(Long id) { + public Optional findById(Long id) { return questionRepository.findById(id); } @@ -35,20 +31,8 @@ public Optional getByQuestionLabelAndQuestId(String questionLabel, lon return questionRepository.getByQuestionLabelAndQuestId(questionLabel, questId); } - public Optional findCurrentQuestion(String questionIdStr, Quest quest) { - Long currentQuestionId; - if (questionIdStr != null && !questionIdStr.isEmpty()) { - currentQuestionId = Helpers.parseStringToLong(questionIdStr); - } else { - currentQuestionId = quest.getStartQuestionId(); - } - return get(currentQuestionId); - } - - public long findNextQuestionId(long questId, Answer answer) { - String nextQuestionLabelStr = answer.getNextQuestionLabel(); - Question nextQuestion = getByQuestionLabelAndQuestId(nextQuestionLabelStr, questId) - .orElseThrow(() -> new AppException(Value.QUESTION_NOT_FOUND + nextQuestionLabelStr)); - return nextQuestion.getGeneratedId(); + public boolean isFinalQuestion(Question question) { + List answers = question.getAnswers(); + return answers == null || answers.isEmpty(); } } diff --git a/src/main/java/com/javarush/vasileva/service/UserService.java b/src/main/java/com/javarush/vasileva/service/UserService.java index a550125..59045fe 100644 --- a/src/main/java/com/javarush/vasileva/service/UserService.java +++ b/src/main/java/com/javarush/vasileva/service/UserService.java @@ -32,8 +32,8 @@ public List getAll() { return userRepository.getAll(); } - public Optional findById(String userIdStr) { - return getValidatedUser(userIdStr); + public Optional findById(Long userId) { + return userRepository.findById(userId); } public void register(String login, String email, String password) { @@ -51,12 +51,12 @@ public Optional login(String email, String password) { .filter(user -> user.getPassword().equals(password)); } - private Optional getValidatedUser(String userIdStr) { + public Optional getValidatedUser(String userIdStr) { if (userIdStr == null || userIdStr.isEmpty()) { return Optional.empty(); } Long questId = Helpers.parseStringToLong(userIdStr); - return userRepository.findById(questId); + return findById(questId); } } diff --git a/src/main/java/com/javarush/vasileva/util/Key.java b/src/main/java/com/javarush/vasileva/util/Key.java index 6ef3e91..de27df9 100644 --- a/src/main/java/com/javarush/vasileva/util/Key.java +++ b/src/main/java/com/javarush/vasileva/util/Key.java @@ -9,18 +9,15 @@ public class Key { public static final String QUESTS = "quests"; public static final String QUEST_ID = "questId"; public static final String QUEST = "quest"; + public static final String GAME = "game"; + public static final String GAME_ID = "gameId"; public static final String EDIT = "edit"; public static final String QUEST_JSON = "questJson"; - public static final String QUESTION = "question"; - public static final String QUESTION_ID = "questionId"; - public static final String ANSWERS = "answers"; - public static final String NO_ANSWERS = "noAnswers"; public static final String SELECTED_ANSWER_ID= "selectedAnswerId"; + public static final String STATE= "state"; public static final String ERROR = "error"; - public static final String GAME_OVER = "gameOver"; - public static final String QUEST_FILE_NAME_1 = "/quest-1.json"; public static final String QUEST_FILE_NAME_2 = "/quest-2.json"; public static final String QUEST_FILE_NAME_3 = "/quest-3.json"; diff --git a/src/main/java/com/javarush/vasileva/util/Value.java b/src/main/java/com/javarush/vasileva/util/Value.java index ee74a13..fb057a6 100644 --- a/src/main/java/com/javarush/vasileva/util/Value.java +++ b/src/main/java/com/javarush/vasileva/util/Value.java @@ -12,10 +12,22 @@ public class Value { "text": "Вопрос 1", "answers": [ { - "nextQuestionLabel": "2", + "nextQuestionLabel": "+810", "text": "Вариант ответа 1" + }, + { + "nextQuestionLabel": "-910", + "text": "Вариант ответа 2" } ] + }, + { + "label": "+810", + "text": "Победа!" + }, + { + "label": "-910", + "text": "Поражение..." } ] }"""; @@ -23,6 +35,8 @@ public class Value { public static final String JSON_SAVE_ERROR = "Ошибка при сохранении квеста"; public static final String QUEST_NOT_FOUND = "Квест не найден: id="; public static final String QUESTION_NOT_FOUND = "Вопрос не найден: label="; + public static final String GAME_NOT_FOUND = "Игра не найдена"; + public static final String ANSWER_NOT_FOUND = "Ответ не найден"; public static final String QUEST_SERIALIZATION_ERROR = "Ошибка сериализации квеста"; public static final String EDIT_QUEST_AUTH_ERROR = "Редактировать квесты могут только пользователи с правами ADMIN"; public static final String DELETE_QUEST_AUTH_ERROR = "Удалять квесты могут только пользователи с правами ADMIN"; @@ -30,4 +44,5 @@ public class Value { public static final String USER_NOT_FOUND = "Пользователь не найден: id="; public static final String EMPTY_DATA_ERROR = "Необходимо ввести данные"; public static final String INVALID_DATA_ERROR = "Неверный email или пароль"; + public static final String AUTH_ERROR = "Необходимо авторизоваться"; } diff --git a/src/main/resources/quest-1.json b/src/main/resources/quest-1.json index fecbe7c..9f4ea67 100644 --- a/src/main/resources/quest-1.json +++ b/src/main/resources/quest-1.json @@ -12,7 +12,7 @@ "text": "Принять вызов" }, { - "nextQuestionLabel": "910", + "nextQuestionLabel": "-910", "text": "Отклонить вызов" } ] @@ -26,7 +26,7 @@ "text": "Подняться на мостик" }, { - "nextQuestionLabel": "910", + "nextQuestionLabel": "-910", "text": "Отказаться подниматься на мостик" } ] @@ -36,21 +36,21 @@ "text": "Ты поднялся на мостик. Ты кто?", "answers": [ { - "nextQuestionLabel": "810", + "nextQuestionLabel": "+810", "text": "Рассказать правду о себе" }, { - "nextQuestionLabel": "911", + "nextQuestionLabel": "-911", "text": "Солгать о себе" } ] }, { - "label": "810", + "label": "+810", "text": "Победа! Тебя вернули домой." }, { - "label": "910", + "label": "-910", "text": "Поражение... Ты отклонил вызов" }, { diff --git a/src/main/resources/quest-3.json b/src/main/resources/quest-3.json index 099b7c7..2535cc8 100644 --- a/src/main/resources/quest-3.json +++ b/src/main/resources/quest-3.json @@ -430,25 +430,25 @@ "text": "После всего пережитого вы наконец понимаете главное.", "answers": [ { - "nextQuestionLabel": "810", + "nextQuestionLabel": "+810", "text": "Всегда носи полотенце" }, { - "nextQuestionLabel": "810", + "nextQuestionLabel": "+810", "text": "Не паникуй" }, { - "nextQuestionLabel": "810", + "nextQuestionLabel": "+810", "text": "Ответ — 42" }, { - "nextQuestionLabel": "810", + "nextQuestionLabel": "+810", "text": "Всё вышеперечисленное" } ] }, { - "label": "810", + "label": "+810", "text": "Поздравляем! Вы прошли квест, не сломали Вселенную и, возможно, даже стали немного мудрее.", "answers": null } diff --git a/src/main/webapp/WEB-INF/play-game.jsp b/src/main/webapp/WEB-INF/play-game.jsp index 53458dd..9f681da 100644 --- a/src/main/webapp/WEB-INF/play-game.jsp +++ b/src/main/webapp/WEB-INF/play-game.jsp @@ -12,98 +12,69 @@
-
space
+
+ space +

${requestScope.quest.title}

${requestScope.quest.text}

- - - - - - -
-

Игра завершена! Спасибо за участие.

- Вернуться на главную -
-
- - - - -
- ${requestScope.question.text} -
-
-
- - -
+ + +
+

${requestScope.game.gameState.currentQuestion.text}

+ Главная + Начать заново +
+
-
- -
-
-
+ +
+ + - - - -
- Вопрос +
+ Текущий вопрос -
- -
- -
- - -
-
-
+
+ +
+ + +
+ + +
+
+
+ + +
+ + + - -
- -
-
-
-
${sessionScope.error}
+
${sessionScope.error}
+ <% session.removeAttribute("error"); %>
<%@include file="footer.jsp" %> - From 47f33ccd25f069bbf9803bf24ffb10a5cc4cf154 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Mon, 2 Feb 2026 16:48:26 +0500 Subject: [PATCH 49/65] ADD statistics --- .../java/com/javarush/vasileva/cmd/Login.java | 9 ++++- .../com/javarush/vasileva/cmd/PlayGame.java | 1 + .../java/com/javarush/vasileva/cmd/Stats.java | 3 +- .../com/javarush/vasileva/entity/Game.java | 1 - .../vasileva/{game => entity}/GameState.java | 5 +-- .../javarush/vasileva/entity/UserStats.java | 7 ++-- .../javarush/vasileva/game/GameEngine.java | 21 ++++++----- .../repository/UserStatsRepository.java | 36 +++++++++++++++++++ .../vasileva/service/GameService.java | 2 +- .../vasileva/service/UserStatsService.java | 35 ++++++++++++++---- .../java/com/javarush/vasileva/util/Key.java | 1 + .../com/javarush/vasileva/util/Value.java | 4 +++ src/main/resources/quest-1.json | 2 +- src/main/webapp/WEB-INF/home.jsp | 2 +- src/main/webapp/WEB-INF/play-game.jsp | 15 ++++---- src/main/webapp/WEB-INF/stats.jsp | 8 +++-- 16 files changed, 117 insertions(+), 35 deletions(-) rename src/main/java/com/javarush/vasileva/{game => entity}/GameState.java (63%) create mode 100644 src/main/java/com/javarush/vasileva/repository/UserStatsRepository.java diff --git a/src/main/java/com/javarush/vasileva/cmd/Login.java b/src/main/java/com/javarush/vasileva/cmd/Login.java index 58d4eb0..ec86dd8 100644 --- a/src/main/java/com/javarush/vasileva/cmd/Login.java +++ b/src/main/java/com/javarush/vasileva/cmd/Login.java @@ -1,7 +1,9 @@ package com.javarush.vasileva.cmd; import com.javarush.vasileva.entity.User; +import com.javarush.vasileva.entity.UserStats; import com.javarush.vasileva.service.UserService; +import com.javarush.vasileva.service.UserStatsService; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; @@ -14,9 +16,11 @@ @SuppressWarnings("unused") public class Login implements Command { private final UserService userService; + private final UserStatsService userStatsService; - public Login(UserService userService) { + public Login(UserService userService, UserStatsService userStatsService) { this.userService = userService; + this.userStatsService = userStatsService; } @Override @@ -29,7 +33,10 @@ public String doPost(HttpServletRequest request) { Optional optionalUser = userService.login(email, password); if (optionalUser.isPresent()) { HttpSession session = request.getSession(); + UserStats stats = userStatsService.getUserStats(optionalUser.get().getId()) + .orElse(userStatsService.createUserStats(optionalUser.get().getId())); session.setAttribute(USER, optionalUser.get()); + session.setAttribute("stats", stats); } else { request.getSession().setAttribute(ERROR, INVALID_DATA_ERROR); return getView(); diff --git a/src/main/java/com/javarush/vasileva/cmd/PlayGame.java b/src/main/java/com/javarush/vasileva/cmd/PlayGame.java index b044557..e66c661 100644 --- a/src/main/java/com/javarush/vasileva/cmd/PlayGame.java +++ b/src/main/java/com/javarush/vasileva/cmd/PlayGame.java @@ -43,6 +43,7 @@ public String doGet(HttpServletRequest req) { req.setAttribute(GAME, game); req.setAttribute(STATE, game.getGameState().isCompleted()); req.setAttribute(QUEST, game.getGameState().getCurrentQuest()); + req.setAttribute(WINNING, game.getGameState().getCurrentQuestion().getLabel().contains(WIN)); return getView(); } diff --git a/src/main/java/com/javarush/vasileva/cmd/Stats.java b/src/main/java/com/javarush/vasileva/cmd/Stats.java index cf3d128..e0a3e42 100644 --- a/src/main/java/com/javarush/vasileva/cmd/Stats.java +++ b/src/main/java/com/javarush/vasileva/cmd/Stats.java @@ -4,6 +4,7 @@ import com.javarush.vasileva.entity.UserStats; import com.javarush.vasileva.exception.AppException; import com.javarush.vasileva.service.UserStatsService; +import com.javarush.vasileva.util.Value; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; @@ -24,7 +25,7 @@ public String doGet(HttpServletRequest req) { throw new AppException("Необходимо авторизоваться"); } - UserStats stats = statsService.getStatsByUser(user); + UserStats stats = statsService.getUserStats(user.getId()).orElseThrow(() -> new AppException(Value.STATS_NOT_FOUND)); req.setAttribute("stats", stats); return getView(); } diff --git a/src/main/java/com/javarush/vasileva/entity/Game.java b/src/main/java/com/javarush/vasileva/entity/Game.java index 4df0145..a9f5cb2 100644 --- a/src/main/java/com/javarush/vasileva/entity/Game.java +++ b/src/main/java/com/javarush/vasileva/entity/Game.java @@ -1,6 +1,5 @@ package com.javarush.vasileva.entity; -import com.javarush.vasileva.game.GameState; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/src/main/java/com/javarush/vasileva/game/GameState.java b/src/main/java/com/javarush/vasileva/entity/GameState.java similarity index 63% rename from src/main/java/com/javarush/vasileva/game/GameState.java rename to src/main/java/com/javarush/vasileva/entity/GameState.java index 91ada86..4b9309f 100644 --- a/src/main/java/com/javarush/vasileva/game/GameState.java +++ b/src/main/java/com/javarush/vasileva/entity/GameState.java @@ -1,8 +1,5 @@ -package com.javarush.vasileva.game; +package com.javarush.vasileva.entity; -import com.javarush.vasileva.entity.Quest; -import com.javarush.vasileva.entity.Question; -import com.javarush.vasileva.entity.User; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; diff --git a/src/main/java/com/javarush/vasileva/entity/UserStats.java b/src/main/java/com/javarush/vasileva/entity/UserStats.java index 7b4eb7b..cd23711 100644 --- a/src/main/java/com/javarush/vasileva/entity/UserStats.java +++ b/src/main/java/com/javarush/vasileva/entity/UserStats.java @@ -10,6 +10,9 @@ @AllArgsConstructor @Builder public class UserStats { - private User user; - private int completedQuests; + private long id; + private long userId; + private int total; + private int wins; + private int losses; } diff --git a/src/main/java/com/javarush/vasileva/game/GameEngine.java b/src/main/java/com/javarush/vasileva/game/GameEngine.java index 5bc5552..4ecd7db 100644 --- a/src/main/java/com/javarush/vasileva/game/GameEngine.java +++ b/src/main/java/com/javarush/vasileva/game/GameEngine.java @@ -1,25 +1,23 @@ package com.javarush.vasileva.game; -import com.javarush.vasileva.entity.Answer; -import com.javarush.vasileva.entity.Quest; -import com.javarush.vasileva.entity.Question; -import com.javarush.vasileva.entity.User; +import com.javarush.vasileva.entity.*; import com.javarush.vasileva.exception.AppException; import com.javarush.vasileva.service.AnswerService; import com.javarush.vasileva.service.QuestionService; +import com.javarush.vasileva.service.UserStatsService; import com.javarush.vasileva.util.Value; - -import static com.javarush.vasileva.util.Value.ANSWER_NOT_FOUND; -import static com.javarush.vasileva.util.Value.QUESTION_NOT_FOUND; +import static com.javarush.vasileva.util.Value.*; public class GameEngine { private final QuestionService questionService; private final AnswerService answerService; + private final UserStatsService userStatsService; - public GameEngine(QuestionService questionService, AnswerService answerService) { + public GameEngine(QuestionService questionService, AnswerService answerService, UserStatsService userStatsService) { this.questionService = questionService; this.answerService = answerService; + this.userStatsService = userStatsService; } public GameState startGame(User user, Quest quest) { @@ -36,6 +34,13 @@ public GameState advanceGame(GameState currentState, Long answerId) { Question nextQuestion = questionService.getByQuestionLabelAndQuestId(nextQuestionLabel, currentState.getCurrentQuest().getId()) .orElseThrow(() -> new AppException(Value.QUESTION_NOT_FOUND + nextQuestionLabel)); boolean isFinalQuestion = questionService.isFinalQuestion(nextQuestion); + + if (isFinalQuestion) { + UserStats stats = userStatsService.getUserStats(currentState.getUser().getId()) + .orElseThrow(() -> new AppException(STATS_NOT_FOUND)); + userStatsService.updateUserStats(nextQuestion, stats); + } + return new GameState(currentState.getCurrentQuest(), nextQuestion, currentState.getUser(), isFinalQuestion); } } diff --git a/src/main/java/com/javarush/vasileva/repository/UserStatsRepository.java b/src/main/java/com/javarush/vasileva/repository/UserStatsRepository.java new file mode 100644 index 0000000..a5efd5d --- /dev/null +++ b/src/main/java/com/javarush/vasileva/repository/UserStatsRepository.java @@ -0,0 +1,36 @@ +package com.javarush.vasileva.repository; + +import com.javarush.vasileva.entity.UserStats; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + +public class UserStatsRepository { + private final Map map = new ConcurrentHashMap<>(); + private final AtomicLong generatedId = new AtomicLong(0); + + public UserStats createUserStats(long userId) { + UserStats userStats = UserStats.builder() + .id(generatedId.incrementAndGet()) + .userId(userId) + .wins(0) + .losses(0) + .build(); + map.put(userStats.getId(), userStats); + return userStats; + } + + public Optional getUserStats(long userId) { + UserStats stats = map.values().stream() + .filter(userStats -> userStats.getUserId() == userId) + .findFirst() + .orElse(null); + return Optional.ofNullable(stats); + } + + public void updateUserStats(UserStats userStats) { + map.put(userStats.getId(), userStats); + } +} diff --git a/src/main/java/com/javarush/vasileva/service/GameService.java b/src/main/java/com/javarush/vasileva/service/GameService.java index 9a442b3..3535ae6 100644 --- a/src/main/java/com/javarush/vasileva/service/GameService.java +++ b/src/main/java/com/javarush/vasileva/service/GameService.java @@ -5,7 +5,7 @@ import com.javarush.vasileva.entity.User; import com.javarush.vasileva.exception.AppException; import com.javarush.vasileva.game.GameEngine; -import com.javarush.vasileva.game.GameState; +import com.javarush.vasileva.entity.GameState; import com.javarush.vasileva.repository.InMemoryGameRepository; import java.util.Optional; diff --git a/src/main/java/com/javarush/vasileva/service/UserStatsService.java b/src/main/java/com/javarush/vasileva/service/UserStatsService.java index b0ed988..558797b 100644 --- a/src/main/java/com/javarush/vasileva/service/UserStatsService.java +++ b/src/main/java/com/javarush/vasileva/service/UserStatsService.java @@ -1,14 +1,37 @@ package com.javarush.vasileva.service; -import com.javarush.vasileva.entity.User; +import com.javarush.vasileva.entity.Question; import com.javarush.vasileva.entity.UserStats; +import com.javarush.vasileva.repository.UserStatsRepository; + +import java.util.Optional; + +import static com.javarush.vasileva.util.Value.LOSS; +import static com.javarush.vasileva.util.Value.WIN; public class UserStatsService { + private final UserStatsRepository userStatsRepository; - public UserStats getStatsByUser(User user) { - UserStats stats = new UserStats(); - stats.setUser(user); - stats.setCompletedQuests(user.getGameNumber()); - return stats; + public UserStatsService(UserStatsRepository userStatsRepository) { + this.userStatsRepository = userStatsRepository; } + + public UserStats createUserStats(long userId) { + return userStatsRepository.createUserStats(userId); + } + + public Optional getUserStats(long userId) { + return userStatsRepository.getUserStats(userId); + } + + public void updateUserStats(Question question, UserStats userStats) { + userStats.setTotal(userStats.getTotal() + 1); + if (question.getLabel().contains(WIN)) { + userStats.setWins(userStats.getWins() + 1); + } else if (question.getLabel().contains(LOSS)) { + userStats.setLosses(userStats.getLosses() + 1); + } + userStatsRepository.updateUserStats(userStats); + } + } diff --git a/src/main/java/com/javarush/vasileva/util/Key.java b/src/main/java/com/javarush/vasileva/util/Key.java index de27df9..b51fd0e 100644 --- a/src/main/java/com/javarush/vasileva/util/Key.java +++ b/src/main/java/com/javarush/vasileva/util/Key.java @@ -15,6 +15,7 @@ public class Key { public static final String QUEST_JSON = "questJson"; public static final String SELECTED_ANSWER_ID= "selectedAnswerId"; public static final String STATE= "state"; + public static final String WINNING= "winning"; public static final String ERROR = "error"; diff --git a/src/main/java/com/javarush/vasileva/util/Value.java b/src/main/java/com/javarush/vasileva/util/Value.java index fb057a6..fd6f6cd 100644 --- a/src/main/java/com/javarush/vasileva/util/Value.java +++ b/src/main/java/com/javarush/vasileva/util/Value.java @@ -32,11 +32,15 @@ public class Value { ] }"""; + public static final String WIN = "+"; + public static final String LOSS = "-"; + public static final String JSON_SAVE_ERROR = "Ошибка при сохранении квеста"; public static final String QUEST_NOT_FOUND = "Квест не найден: id="; public static final String QUESTION_NOT_FOUND = "Вопрос не найден: label="; public static final String GAME_NOT_FOUND = "Игра не найдена"; public static final String ANSWER_NOT_FOUND = "Ответ не найден"; + public static final String STATS_NOT_FOUND = "Статистика не найдена"; public static final String QUEST_SERIALIZATION_ERROR = "Ошибка сериализации квеста"; public static final String EDIT_QUEST_AUTH_ERROR = "Редактировать квесты могут только пользователи с правами ADMIN"; public static final String DELETE_QUEST_AUTH_ERROR = "Удалять квесты могут только пользователи с правами ADMIN"; diff --git a/src/main/resources/quest-1.json b/src/main/resources/quest-1.json index 9f4ea67..1b269e5 100644 --- a/src/main/resources/quest-1.json +++ b/src/main/resources/quest-1.json @@ -54,7 +54,7 @@ "text": "Поражение... Ты отклонил вызов" }, { - "label": "911", + "label": "-911", "text": "Поражение... Твою ложь разоблачили" } ] diff --git a/src/main/webapp/WEB-INF/home.jsp b/src/main/webapp/WEB-INF/home.jsp index f3470b3..e098b8b 100644 --- a/src/main/webapp/WEB-INF/home.jsp +++ b/src/main/webapp/WEB-INF/home.jsp @@ -32,7 +32,7 @@
diff --git a/src/main/webapp/WEB-INF/play-game.jsp b/src/main/webapp/WEB-INF/play-game.jsp index 9f681da..e59dc55 100644 --- a/src/main/webapp/WEB-INF/play-game.jsp +++ b/src/main/webapp/WEB-INF/play-game.jsp @@ -1,5 +1,6 @@ <%@ page contentType="text/html;charset=UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> <%@include file="header.jsp" %> @@ -22,11 +23,12 @@ -
-

${requestScope.game.gameState.currentQuestion.text}

- Главная - Начать заново -
+
+

${requestScope.game.gameState.currentQuestion.text}

+ Главная + Начать заново +
@@ -43,7 +45,8 @@
- +

Статистика игрока

- +
-
Игрок: ${requestScope.stats.user.login}
+
Игрок: ${sessionScope.user.login}

- Пройдено квестов: ${requestScope.stats.completedQuests}
+ Пройдено квестов: ${sessionScope.stats.total}
+ Победы: ${sessionScope.stats.wins}
+ Поражения: ${sessionScope.stats.losses}

From 124cd37000e7520d165a0546e96cb41248b76a1b Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Mon, 2 Feb 2026 23:21:42 +0500 Subject: [PATCH 50/65] ADD logging for commands --- pom.xml | 17 ++++++++++ .../com/javarush/vasileva/cmd/EditQuest.java | 20 ++++++++++++ .../com/javarush/vasileva/cmd/EditUser.java | 25 ++++++++++++++- .../java/com/javarush/vasileva/cmd/Home.java | 15 +++++++++ .../java/com/javarush/vasileva/cmd/Login.java | 32 ++++++++++++++++--- .../com/javarush/vasileva/cmd/Logout.java | 9 ++++++ .../com/javarush/vasileva/cmd/PlayGame.java | 24 +++++++++++++- .../com/javarush/vasileva/cmd/Register.java | 14 ++++++++ .../java/com/javarush/vasileva/cmd/Stats.java | 19 +++++++++-- .../com/javarush/vasileva/cmd/UserList.java | 20 ++++++++++++ .../vasileva/service/QuestService.java | 6 ++++ .../java/com/javarush/vasileva/util/Key.java | 13 ++++---- src/main/resources/{ => json}/quest-1.json | 0 src/main/resources/{ => json}/quest-2.json | 0 src/main/resources/{ => json}/quest-3.json | 0 src/main/resources/log4j2.xml | 31 ++++++++++++++++++ 16 files changed, 230 insertions(+), 15 deletions(-) rename src/main/resources/{ => json}/quest-1.json (100%) rename src/main/resources/{ => json}/quest-2.json (100%) rename src/main/resources/{ => json}/quest-3.json (100%) create mode 100644 src/main/resources/log4j2.xml diff --git a/pom.xml b/pom.xml index dd6a0bb..844dec6 100644 --- a/pom.xml +++ b/pom.xml @@ -36,6 +36,21 @@ + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + jakarta.servlet jakarta.servlet-api @@ -70,6 +85,8 @@ com.fasterxml.jackson.dataformat jackson-dataformat-yaml + + diff --git a/src/main/java/com/javarush/vasileva/cmd/EditQuest.java b/src/main/java/com/javarush/vasileva/cmd/EditQuest.java index 453cf4f..3e74522 100644 --- a/src/main/java/com/javarush/vasileva/cmd/EditQuest.java +++ b/src/main/java/com/javarush/vasileva/cmd/EditQuest.java @@ -8,6 +8,8 @@ import com.javarush.vasileva.service.QuestService; import com.javarush.vasileva.util.Helpers; import jakarta.servlet.http.HttpServletRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.List; @@ -18,6 +20,9 @@ @SuppressWarnings("unused") public class EditQuest implements Command { + + private static final Logger LOGGER = LoggerFactory.getLogger(EditQuest.class.getName()); + private final QuestService questService; private final QuestMapper questMapper = Winter.find(QuestMapper.class); private final Config config; @@ -30,24 +35,32 @@ public EditQuest(QuestService questService, Config config) { @Override public String doGet(HttpServletRequest req) { + LOGGER.info("Received GET request to edit quests"); + Helpers.checkAdminAuthorization(req, EDIT_QUEST_AUTH_ERROR); List quests = questService.getAll(); req.setAttribute(QUESTS, quests); + LOGGER.debug("Loaded quests: {}", quests.size()); String questIdStr = req.getParameter(QUEST_ID); if (questIdStr != null && !questIdStr.isEmpty()) { + LOGGER.info("Editing quest with id: {}", questIdStr); Quest quest = questService.getValidatedQuest(questIdStr) .orElseThrow(() -> new AppException(QUEST_NOT_FOUND + questIdStr)); req.setAttribute(EDIT, true); try { String questJson = questMapper.toJsonString(quest); req.setAttribute(QUEST_JSON, questJson); + LOGGER.debug("Quest is mapped to JSON. ID: {}", quest.getId()); } catch (IOException e) { + LOGGER.error(QUEST_SERIALIZATION_ERROR + ". ID: {}. Cause: {}", + questIdStr, e.getMessage()); req.getSession().setAttribute(ERROR, QUEST_SERIALIZATION_ERROR); return getView(); } } else { + LOGGER.info("Creating quest"); req.setAttribute(EDIT, false); req.setAttribute(QUEST_JSON, JSON_SAMPLE); } @@ -56,17 +69,24 @@ public String doGet(HttpServletRequest req) { @Override public String doPost(HttpServletRequest req) { + LOGGER.info("Processing POST-request for saving quest. Параметры: {}", req.getParameterMap()); String questJson = req.getParameter(QUEST_JSON); try { Quest quest = questMapper.fromJsonString(questJson); + LOGGER.debug("Quest is successfully received from JSON. Title: {}", quest.getTitle()); if (quest.getId() != null) { + LOGGER.info("Updating quest with ID: {}", quest.getId()); questService.update(quest); } else { + LOGGER.info("Creating new quest"); questService.create(quest); } config.setQuestParameters(quest); + LOGGER.info("Quest is successfully saved. ID: {}", quest.getId()); return HOME; } catch (IOException e) { + LOGGER.error(JSON_SAVE_ERROR + ". JSON: {}. Cause: {}", + questJson, e.getMessage(), e); req.getSession().setAttribute(QUEST_JSON, questJson); req.getSession().setAttribute(ERROR, JSON_SAVE_ERROR); return getView(); diff --git a/src/main/java/com/javarush/vasileva/cmd/EditUser.java b/src/main/java/com/javarush/vasileva/cmd/EditUser.java index e694259..f2de5d7 100644 --- a/src/main/java/com/javarush/vasileva/cmd/EditUser.java +++ b/src/main/java/com/javarush/vasileva/cmd/EditUser.java @@ -6,6 +6,8 @@ import com.javarush.vasileva.util.Link; import com.javarush.vasileva.util.Helpers; import jakarta.servlet.http.HttpServletRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Optional; @@ -13,6 +15,8 @@ @SuppressWarnings("unused") public class EditUser implements Command { + private static final Logger LOGGER = LoggerFactory.getLogger(EditUser.class.getName()); + private final UserService userService; public EditUser(UserService userService) { @@ -22,25 +26,44 @@ public EditUser(UserService userService) { @Override public String doGet(HttpServletRequest req) { String stringId = req.getParameter("id"); + LOGGER.info("Received GET request to edit user with id: {}", stringId); + Optional optionalUser = userService.getValidatedUser(stringId); - optionalUser.ifPresent(user -> req.setAttribute("user", user)); + + if (optionalUser.isPresent()) { + User user = optionalUser.get(); + req.setAttribute("user", user); + LOGGER.debug("User found and set as request attribute: {}", user.getLogin()); + } else { + LOGGER.warn("User with id {} not found", stringId); + } + return getView(); } @Override public String doPost(HttpServletRequest req) { + LOGGER.info("Received POST request to process user data"); + User user = User.builder() .login(req.getParameter("login")) .email(req.getParameter("email")) .password(req.getParameter("password")) .role(Role.valueOf(req.getParameter("role"))) .build(); + + LOGGER.debug("Constructed user object: login={}, email={}, role={}", + user.getLogin(), user.getEmail(), user.getRole()); + if (req.getParameter("create") != null) { + LOGGER.info("Creating new user with login: {}", user.getLogin()); userService.create(user); } else if (req.getParameter("update") != null) { user.setId(Helpers.parseStringToLong(req.getParameter("id"))); + LOGGER.info("Updating user with id: {}, login: {}", user.getId(), user.getLogin()); userService.update(user); } + LOGGER.info("Redirecting to user list page"); return Link.USER_LIST; } } \ No newline at end of file diff --git a/src/main/java/com/javarush/vasileva/cmd/Home.java b/src/main/java/com/javarush/vasileva/cmd/Home.java index ad1921a..f728cbc 100644 --- a/src/main/java/com/javarush/vasileva/cmd/Home.java +++ b/src/main/java/com/javarush/vasileva/cmd/Home.java @@ -4,6 +4,8 @@ import com.javarush.vasileva.service.QuestService; import com.javarush.vasileva.util.Helpers; import jakarta.servlet.http.HttpServletRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.List; @@ -12,6 +14,9 @@ @SuppressWarnings("unused") public class Home implements Command { + + private static final Logger LOGGER = LoggerFactory.getLogger(Home.class.getName()); + private final QuestService questService; public Home(QuestService questService) { @@ -20,19 +25,29 @@ public Home(QuestService questService) { @Override public String doGet(HttpServletRequest req) { + LOGGER.info("Received GET request to display all quests"); List quests = questService.getAll(); req.setAttribute(QUESTS, quests); + LOGGER.debug("Retrieved {} quests from service", quests.size()); return getView(); } @Override public String doDelete(HttpServletRequest req) { + LOGGER.info("Received DELETE request for quest"); + Helpers.checkAdminAuthorization(req, DELETE_QUEST_AUTH_ERROR); + LOGGER.debug("Admin authorization successful"); + String questIdStr = req.getParameter(QUEST_ID); + LOGGER.debug("Attempting to delete quest with ID: {}", questIdStr); + Quest quest = questService.getValidatedQuest(questIdStr) .orElseThrow(() -> new IllegalArgumentException(QUEST_NOT_FOUND + questIdStr)); req.setAttribute(QUEST, quest); questService.delete(quest); + LOGGER.info("Quest with ID {} successfully deleted", questIdStr); + return getView(); } } diff --git a/src/main/java/com/javarush/vasileva/cmd/Login.java b/src/main/java/com/javarush/vasileva/cmd/Login.java index ec86dd8..fe1ea13 100644 --- a/src/main/java/com/javarush/vasileva/cmd/Login.java +++ b/src/main/java/com/javarush/vasileva/cmd/Login.java @@ -4,17 +4,24 @@ import com.javarush.vasileva.entity.UserStats; import com.javarush.vasileva.service.UserService; import com.javarush.vasileva.service.UserStatsService; +import com.javarush.vasileva.util.Key; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Optional; import static com.javarush.vasileva.util.Key.*; -import static com.javarush.vasileva.util.Link.HOME; +import static com.javarush.vasileva.util.Key.ERROR; +import static com.javarush.vasileva.util.Link.*; import static com.javarush.vasileva.util.Value.*; @SuppressWarnings("unused") public class Login implements Command { + + private static final Logger LOGGER = LoggerFactory.getLogger(Login.class.getName()); + private final UserService userService; private final UserStatsService userStatsService; @@ -25,19 +32,34 @@ public Login(UserService userService, UserStatsService userStatsService) { @Override public String doPost(HttpServletRequest request) { + LOGGER.info("Received POST request for user login"); + String email = request.getParameter(EMAIL); String password = request.getParameter(PASSWORD); + + LOGGER.debug("Login attempt with email: {}, password: {}", email, password); + if (email.isEmpty() || password.isEmpty()) { - request.getSession().setAttribute(ERROR, EMPTY_DATA_ERROR); + LOGGER.warn("Empty email or password provided"); + request.getSession().setAttribute(Key.ERROR, EMPTY_DATA_ERROR); + } + Optional optionalUser = userService.login(email, password); if (optionalUser.isPresent()) { + User user = optionalUser.get(); + LOGGER.info("User authenticated successfully: {}", user.getEmail()); + HttpSession session = request.getSession(); - UserStats stats = userStatsService.getUserStats(optionalUser.get().getId()) - .orElse(userStatsService.createUserStats(optionalUser.get().getId())); + UserStats stats = userStatsService.getUserStats(user.getId()) + .orElse(userStatsService.createUserStats(user.getId())); + session.setAttribute(USER, optionalUser.get()); - session.setAttribute("stats", stats); + session.setAttribute(Key.STATS, stats); + + LOGGER.debug("User stats loaded/created and stored in session for user ID: {}", user.getId()); } else { + LOGGER.error(INVALID_DATA_ERROR); request.getSession().setAttribute(ERROR, INVALID_DATA_ERROR); return getView(); } diff --git a/src/main/java/com/javarush/vasileva/cmd/Logout.java b/src/main/java/com/javarush/vasileva/cmd/Logout.java index 6110ad1..a5714a4 100644 --- a/src/main/java/com/javarush/vasileva/cmd/Logout.java +++ b/src/main/java/com/javarush/vasileva/cmd/Logout.java @@ -2,18 +2,27 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import static com.javarush.vasileva.util.Link.LOGIN; @SuppressWarnings("unused") public class Logout implements Command { + private static final Logger LOGGER = LoggerFactory.getLogger(Logout.class.getName()); @Override public String doGet(HttpServletRequest request) { + LOGGER.info("Received GET request for user logout"); + HttpSession session = request.getSession(false); if (session != null) { + LOGGER.debug("User session found. Session ID: {}", session.getId()); session.invalidate(); + LOGGER.info("User session invalidated successfully"); } + + LOGGER.info("Redirecting user to login page"); return LOGIN; } } diff --git a/src/main/java/com/javarush/vasileva/cmd/PlayGame.java b/src/main/java/com/javarush/vasileva/cmd/PlayGame.java index e66c661..3a5590b 100644 --- a/src/main/java/com/javarush/vasileva/cmd/PlayGame.java +++ b/src/main/java/com/javarush/vasileva/cmd/PlayGame.java @@ -6,6 +6,8 @@ import com.javarush.vasileva.util.Helpers; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import static com.javarush.vasileva.util.Key.*; import static com.javarush.vasileva.util.Value.*; @@ -13,6 +15,8 @@ @SuppressWarnings("unused") public class PlayGame implements Command { + private static final Logger LOGGER = LoggerFactory.getLogger(PlayGame.class.getName()); + private final GameService gameService; public PlayGame(GameService gameService) { @@ -21,22 +25,30 @@ public PlayGame(GameService gameService) { @Override public String doGet(HttpServletRequest req) { + LOGGER.info("Received GET request to play game"); + HttpSession session = req.getSession(); User user = (User) session.getAttribute(USER); if (user == null) { + LOGGER.error("User not authenticated. Throwing AppException: {}", AUTH_ERROR); throw new AppException(AUTH_ERROR); } + LOGGER.debug("Authenticated user: id={}, login={}", user.getId(), user.getLogin()); Long questId = Helpers.parseStringToLong(req.getParameter(QUEST_ID)); Long gameId = req.getParameter(GAME_ID) != null ? Helpers.parseStringToLong(req.getParameter(GAME_ID)) : null; + LOGGER.debug("Quest ID: {}, Game ID: {}", questId, gameId); + Game game; if (gameId == null) { + LOGGER.info("Starting new game for quest ID: {}", questId); game = gameService.startNewGame(questId, user.getId()); } else { + LOGGER.info("Retrieving existing game by ID: {}", gameId); game = gameService.getGameById(gameId).orElseThrow(() -> new AppException(GAME_NOT_FOUND)); } @@ -45,22 +57,32 @@ public String doGet(HttpServletRequest req) { req.setAttribute(QUEST, game.getGameState().getCurrentQuest()); req.setAttribute(WINNING, game.getGameState().getCurrentQuestion().getLabel().contains(WIN)); + LOGGER.debug("Game attributes set in request: gameId={}, completed={}, questId={}", + game.getId(), game.getGameState().isCompleted(), game.getGameState().getCurrentQuest().getId()); + return getView(); } @Override public String doPost(HttpServletRequest req) throws AppException { + LOGGER.info("Received POST request to advance game"); + HttpSession session = req.getSession(); User user = (User) session.getAttribute(USER); Long gameId = Helpers.parseStringToLong(req.getParameter(GAME_ID)); Long answerId = Helpers.parseStringToLong(req.getParameter(SELECTED_ANSWER_ID)); + LOGGER.debug("Advancing game ID: {} with answer ID: {}", gameId, answerId); Game updatedGame = gameService.advanceGame(gameId, answerId); req.setAttribute(GAME, updatedGame); req.setAttribute(USER, user); - return getView() + "?" + GAME_ID + "=" + updatedGame.getId() + "&" + QUEST_ID + "=" + updatedGame.getGameState().getCurrentQuest().getId(); + String redirectUrl = getView() + "?" + GAME_ID + "=" + updatedGame.getId() + + "&" + QUEST_ID + "=" + updatedGame.getGameState().getCurrentQuest().getId(); + LOGGER.info("Game advanced successfully. Redirecting to: {}", redirectUrl); + + return redirectUrl; } } diff --git a/src/main/java/com/javarush/vasileva/cmd/Register.java b/src/main/java/com/javarush/vasileva/cmd/Register.java index dc8f89f..882e0b0 100644 --- a/src/main/java/com/javarush/vasileva/cmd/Register.java +++ b/src/main/java/com/javarush/vasileva/cmd/Register.java @@ -5,12 +5,17 @@ import com.javarush.vasileva.util.Key; import com.javarush.vasileva.util.Link; import jakarta.servlet.http.HttpServletRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import static com.javarush.vasileva.util.Key.*; import static com.javarush.vasileva.util.Value.*; @SuppressWarnings("unused") public class Register implements Command { + + private static final Logger LOGGER = LoggerFactory.getLogger(Register.class.getName()); + private final UserService userService; public Register(UserService userService) { @@ -19,15 +24,24 @@ public Register(UserService userService) { @Override public String doPost(HttpServletRequest request) { + LOGGER.info("Received POST request for user registration"); + String login = request.getParameter(Key.LOGIN); String email = request.getParameter(EMAIL); String password = request.getParameter(PASSWORD); + LOGGER.debug("Registration attempt with login: {}, email: {}", login, email); + if (login == null || login.isEmpty() || email == null || email.isEmpty() || password == null || password.isEmpty()) { + LOGGER.warn(EMPTY_DATA_ERROR + ". Missing: login={}, email={}, password={}", + login == null || login.isEmpty(), email == null || email.isEmpty(), password == null || password.isEmpty()); throw new AppException(EMPTY_DATA_ERROR); } + LOGGER.info("Registering new user with login: {} and email: {}", login, email); userService.register(login, email, password); + + LOGGER.info("User successfully registered. Redirecting to login page"); return Link.LOGIN; } } diff --git a/src/main/java/com/javarush/vasileva/cmd/Stats.java b/src/main/java/com/javarush/vasileva/cmd/Stats.java index e0a3e42..0af9739 100644 --- a/src/main/java/com/javarush/vasileva/cmd/Stats.java +++ b/src/main/java/com/javarush/vasileva/cmd/Stats.java @@ -4,12 +4,20 @@ import com.javarush.vasileva.entity.UserStats; import com.javarush.vasileva.exception.AppException; import com.javarush.vasileva.service.UserStatsService; +import com.javarush.vasileva.util.Key; import com.javarush.vasileva.util.Value; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static com.javarush.vasileva.util.Value.AUTH_ERROR; @SuppressWarnings("unused") public class Stats implements Command { + + private static final Logger LOGGER = LoggerFactory.getLogger(Stats.class.getName()); + private final UserStatsService statsService; public Stats(UserStatsService statsService) { @@ -18,15 +26,22 @@ public Stats(UserStatsService statsService) { @Override public String doGet(HttpServletRequest req) { + LOGGER.info("Received GET request to view user statistics"); + HttpSession session = req.getSession(); User user = (User) session.getAttribute("user"); if (user == null) { - throw new AppException("Необходимо авторизоваться"); + LOGGER.error("User not authenticated. Throwing AppException: {}", AUTH_ERROR); + throw new AppException(AUTH_ERROR); } + LOGGER.debug("Authenticated user: id={}, login={}", user.getId(), user.getLogin()); + UserStats stats = statsService.getUserStats(user.getId()).orElseThrow(() -> new AppException(Value.STATS_NOT_FOUND)); - req.setAttribute("stats", stats); + req.setAttribute(Key.STATS, stats); + LOGGER.info("Statistics loaded successfully for user ID: {}", user.getId()); + return getView(); } } diff --git a/src/main/java/com/javarush/vasileva/cmd/UserList.java b/src/main/java/com/javarush/vasileva/cmd/UserList.java index 7b95dac..cb705b7 100644 --- a/src/main/java/com/javarush/vasileva/cmd/UserList.java +++ b/src/main/java/com/javarush/vasileva/cmd/UserList.java @@ -6,6 +6,8 @@ import com.javarush.vasileva.service.UserService; import com.javarush.vasileva.util.Helpers; import jakarta.servlet.http.HttpServletRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Collection; @@ -15,6 +17,8 @@ @SuppressWarnings("unused") public class UserList implements Command { + private static final Logger LOGGER = LoggerFactory.getLogger(UserList.class.getName()); + private final UserService userService; public UserList(UserService userService) { @@ -23,20 +27,36 @@ public UserList(UserService userService) { @Override public String doGet(HttpServletRequest request) { + LOGGER.info("Received GET request to view user list"); + Helpers.checkAdminAuthorization(request, USER_LIST_AUTH_ERROR); + LOGGER.debug("Admin authorization successful"); + Collection users = userService.getAll(); + LOGGER.info("Retrieved {} users from database", users.size()); + request.setAttribute("users", users); request.getSession().setAttribute("ADMIN_ROLE", Role.ADMIN); + LOGGER.debug("Users and admin role set in request attributes"); + return getView(); } @Override public String doDelete(HttpServletRequest req) { + LOGGER.info("Received DELETE request to remove user"); + String userIdStr = req.getParameter(USER_ID); + LOGGER.debug("Attempting to delete user with ID: {}", userIdStr); + User user = userService.getValidatedUser(userIdStr) .orElseThrow(() -> new AppException(USER_NOT_FOUND + userIdStr)); + LOGGER.info("User found for deletion: id={}, login={}", user.getId(), user.getLogin()); + req.setAttribute(USER, user); userService.delete(user); + LOGGER.info("User with ID {} successfully deleted", user.getId()); + return getView(); } } \ No newline at end of file diff --git a/src/main/java/com/javarush/vasileva/service/QuestService.java b/src/main/java/com/javarush/vasileva/service/QuestService.java index 837fcf1..2b106fe 100644 --- a/src/main/java/com/javarush/vasileva/service/QuestService.java +++ b/src/main/java/com/javarush/vasileva/service/QuestService.java @@ -4,11 +4,16 @@ import com.javarush.vasileva.repository.QuestRepository; import com.javarush.vasileva.repository.Repository; import com.javarush.vasileva.util.Helpers; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.List; import java.util.Optional; public class QuestService { + + private static final Logger LOGGER = LoggerFactory.getLogger(QuestService.class.getName()); + private final Repository questRepository; public QuestService(QuestRepository questRepository) { @@ -37,6 +42,7 @@ public void delete(Quest quest) { public Optional getValidatedQuest(String questIdStr) { if (questIdStr == null || questIdStr.isEmpty()) { + LOGGER.warn("Missing quest ID in DELETE request"); return Optional.empty(); } Long questId = Helpers.parseStringToLong(questIdStr); diff --git a/src/main/java/com/javarush/vasileva/util/Key.java b/src/main/java/com/javarush/vasileva/util/Key.java index b51fd0e..35a6d53 100644 --- a/src/main/java/com/javarush/vasileva/util/Key.java +++ b/src/main/java/com/javarush/vasileva/util/Key.java @@ -13,13 +13,14 @@ public class Key { public static final String GAME_ID = "gameId"; public static final String EDIT = "edit"; public static final String QUEST_JSON = "questJson"; - public static final String SELECTED_ANSWER_ID= "selectedAnswerId"; - public static final String STATE= "state"; - public static final String WINNING= "winning"; + public static final String SELECTED_ANSWER_ID = "selectedAnswerId"; + public static final String STATE = "state"; + public static final String STATS = "stats"; + public static final String WINNING = "winning"; public static final String ERROR = "error"; - public static final String QUEST_FILE_NAME_1 = "/quest-1.json"; - public static final String QUEST_FILE_NAME_2 = "/quest-2.json"; - public static final String QUEST_FILE_NAME_3 = "/quest-3.json"; + public static final String QUEST_FILE_NAME_1 = "/json/quest-1.json"; + public static final String QUEST_FILE_NAME_2 = "/json/quest-2.json"; + public static final String QUEST_FILE_NAME_3 = "/json/quest-3.json"; } diff --git a/src/main/resources/quest-1.json b/src/main/resources/json/quest-1.json similarity index 100% rename from src/main/resources/quest-1.json rename to src/main/resources/json/quest-1.json diff --git a/src/main/resources/quest-2.json b/src/main/resources/json/quest-2.json similarity index 100% rename from src/main/resources/quest-2.json rename to src/main/resources/json/quest-2.json diff --git a/src/main/resources/quest-3.json b/src/main/resources/json/quest-3.json similarity index 100% rename from src/main/resources/quest-3.json rename to src/main/resources/json/quest-3.json diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml new file mode 100644 index 0000000..b261a23 --- /dev/null +++ b/src/main/resources/log4j2.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 6a65e8def8bcf364c97bc227baa9edd253bebf77 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Mon, 2 Feb 2026 23:52:12 +0500 Subject: [PATCH 51/65] ADD json --- src/main/resources/json/quest-2.json | 441 +++++++++++---------------- src/main/resources/json/quest-3.json | 431 +++++--------------------- 2 files changed, 256 insertions(+), 616 deletions(-) diff --git a/src/main/resources/json/quest-2.json b/src/main/resources/json/quest-2.json index 4419541..2535cc8 100644 --- a/src/main/resources/json/quest-2.json +++ b/src/main/resources/json/quest-2.json @@ -1,526 +1,455 @@ { - "title": "Тайна Забытого Подземелья", - "description": "Много веков назад дракон Вельдан, хранитель древних знаний, скрылся в недрах горы с Сердцем Дракона — артефактом невообразимой силы...", - "text": "Много веков назад дракон Вельдан, хранитель древних знаний, скрылся в недрах горы с Сердцем Дракона — артефактом невообразимой силы, спрятав его в лабиринте, известном как Забытое Подземелье. Тысячи смельчаков отправлялись на поиски реликвии, но никто не вернулся; легенды гласят, что лишь тот, кто проявит мудрость, отвагу и хладнокровие, сможет завладеть Сердцем. Теперь вы — один из искателей: с факелом и мечом перед массивной дверью с драконьей пастью, за которой таятся тьма, сырость и нечто древнее. Дверь медленно приоткрывается — готовы ли вы бросить вызов подземелью?", + "title": "Автостопом по здравому смыслу (или Не паникуй)", + "description": "По мотивам «Автостопом по Галактике»", + "text": "Добро пожаловать в квест, который начинается с конца света и быстро переходит к вопросам посложнее. Землю сносят ради гиперпространственной магистрали, предупреждения были вывешены (где-то далеко и давно), а у вас есть лишь выбор, полотенце и крайне смутное представление о происходящем. Впереди — вогоны, сомнительный чай, философские размышления и шанс узнать ответ на Главный вопрос жизни, Вселенной и всего такого. Главное — не паникуйте: Вселенная всё равно делает вид, что всё под контролем.", "questions": [ { "label": "1", - "text": "Вы входите в тёмный коридор. Впереди слышен шорох.", + "text": "Вы просыпаетесь и узнаёте, что Землю демонтируют ради гиперпространственной магистрали. Что будете делать?", "answers": [ { "nextQuestionLabel": "2", - "text": "Достанете факел и осторожно продвинетесь вперёд.", - "description": "" + "text": "Вы возмущённо требуете документы, разрешения и хотя бы подпись ответственного лица. Вселенная равнодушно зевает." }, { - "nextQuestionLabel": "2", - "text": "Бросите камень в сторону шума, чтобы проверить.", - "description": "Вы пугаете крысу. Путь свободен." + "nextQuestionLabel": "3", + "text": "Вы вспоминаете главное правило галактического путешественника и лихорадочно ищете полотенце. Это внушает необъяснимое спокойствие." }, { - "nextQuestionLabel": "910", - "text": "Повернётесь и пойдёте назад.", - "description": "Попадаете в тупик." + "nextQuestionLabel": "4", + "text": "Вы уточняете, будет ли обед до конца света, потому что на голодный желудок апокалипсис переносится хуже." }, { - "nextQuestionLabel": "910", - "text": "Закричите, чтобы отпугнуть возможного врага.", - "description": "Шум привлекает монстров." + "nextQuestionLabel": "5", + "text": "Вы решаете, что это сон, и пробуете снова уснуть, пока Вселенная не передумала." } ] }, { "label": "2", - "text": "Факел осветил три двери. На каждой — символ: огонь, вода, луна. Какую выберете?", + "text": "Перед вами стоит вогон, держащий папку подозрительно толстых стихов.", "answers": [ { - "nextQuestionLabel": "3", - "text": "С символом огня (рискованно, но может вести к сокровищам).", - "description": "В комнате лава. Нужно найти мост." + "nextQuestionLabel": "6", + "text": "Вы пытаетесь убежать, но быстро понимаете, что в условиях вакуума это не лучшая стратегия." + }, + { + "nextQuestionLabel": "7", + "text": "Вы представляете себя галактическим юристом и начинаете говорить словами, смысл которых неизвестен даже вам." }, { "nextQuestionLabel": "8", - "text": "С символом воды (кажется безопасной).", - "description": "Подземный ручей." + "text": "Вы вежливо просите почитать стихи вслух, подозревая, что хуже уже не будет." }, { - "nextQuestionLabel": "910", - "text": "С символом луны (загадочно, возможно, ловушка).", - "description": "Ловушка: пол проваливается." + "nextQuestionLabel": "9", + "text": "Вы начинаете плакать заранее, экономя время на эмоциональной реакции." } ] }, { "label": "3", - "text": "За дверью — комната с ямой посередине. На стене рычаг. Ваши действия?", + "text": "Полотенце найдено. Оно слегка влажное, но внушает доверие.", "answers": [ { - "nextQuestionLabel": "910", - "text": "Дёрнете рычаг сразу.", - "description": "Яма расширяется." + "nextQuestionLabel": "6", + "text": "Вы используете его как универсальное средство защиты от всего непонятного." }, { - "nextQuestionLabel": "4", - "text": "Поищете другой путь, минуя яму.", - "description": "Находите скрытый проход." + "nextQuestionLabel": "10", + "text": "Вы накидываете его как плащ и чувствуете себя героем космооперы." }, { - "nextQuestionLabel": "910", - "text": "Попытаетесь перепрыгнуть яму.", - "description": "Падение." + "nextQuestionLabel": "5", + "text": "Вы обнимаете полотенце, потому что оно единственное, что сейчас вас понимает." }, { - "nextQuestionLabel": "4", - "text": "Кинете камень на противоположную сторону, проверяя пол.", - "description": "Пол безопасен. Переходите." + "nextQuestionLabel": "9", + "text": "Вы тут же его теряете, подтверждая законы Вселенной." } ] }, { "label": "4", - "text": "Рычаг активировал механизм: из стен выдвинулись шипы. Как спастись?", + "text": "Мысли о еде не покидают вас даже в момент уничтожения планеты.", "answers": [ { - "nextQuestionLabel": "5", - "text": "Прижмётесь к стене и медленно пройдёте.", - "description": "Успешно проходите." + "nextQuestionLabel": "11", + "text": "Вы решаете сделать бутерброд, игнорируя катастрофу как нечто второстепенное." }, { - "nextQuestionLabel": "5", - "text": "Побежите напролом, уклоняясь.", - "description": "Ранение. Здоровье снижается." + "nextQuestionLabel": "12", + "text": "Вы жалуетесь Вселенной на несвоевременность происходящего." }, { "nextQuestionLabel": "5", - "text": "Найдёте кнопку отключения механизмов.", - "description": "Находите механизм." + "text": "Вы смиряетесь с судьбой и принимаете происходящее как должное." }, { - "nextQuestionLabel": "910", - "text": "Вернётесь назад.", - "description": "Путь заблокирован. " + "nextQuestionLabel": "13", + "text": "Вы спрашиваете, где чай, потому что без него цивилизация не имеет смысла." } ] }, { "label": "5", - "text": "В этой комнате — статуя дракона. На постаменте надпись: «Скажи имя древнего бога».", + "text": "Вы понимаете: это не сон, а реальность, причём весьма навязчивая.", "answers": [ { - "nextQuestionLabel": "910", - "text": "Азраэль.", - "description": "Статуя атакует." + "nextQuestionLabel": "9", + "text": "Вы начинаете паниковать, громко и без системы." }, { - "nextQuestionLabel": "6", - "text": "Таргон.", - "description": "Верно! Статуя пропускает." + "nextQuestionLabel": "10", + "text": "Вы вспоминаете надпись «DON’T PANIC» и стараетесь выглядеть уверенно." }, { - "nextQuestionLabel": "910", - "text": "Вельдан.", - "description": "Ошибка. Ловушка." + "nextQuestionLabel": "12", + "text": "Вы философски принимаете происходящее, как будто читали об этом раньше.", + "description": "" }, { - "nextQuestionLabel": "5", - "text": "Промолчите и осмотрите комнату ещё раз.", - "description": "Находите надпись с именем: Таргон" + "nextQuestionLabel": "14", + "text": "Вы выкрикиваете «42!» без всякой причины, но с чувством." } ] }, { "label": "6", - "text": "Статуя оживает! Как поступить?", + "text": "Вас без особых церемоний выбрасывают в открытый космос. Он холодный, бесконечный и явно не собирается извиняться.", "answers": [ { - "nextQuestionLabel": "7", - "text": "Попробуете заговорить с ней.", - "description": "Дракон даёт подсказку." + "nextQuestionLabel": "15", + "text": "Вы задерживаете дыхание, словно космос обязан это заметить и проявить такт." }, { - "nextQuestionLabel": "910", - "text": "Атакуете первым.", - "description": "Проигрываете бой." + "nextQuestionLabel": "9", + "text": "Вы начинаете кричать, несмотря на смутное подозрение, что звук здесь не работает." }, { - "nextQuestionLabel": "7", - "text": "Бросите в неё магический свиток.", - "description": "Оглушаете дракона." + "nextQuestionLabel": "16", + "text": "Вы решаете положиться на сюжетную броню главного героя, даже если не уверены, что вы главный." }, { - "nextQuestionLabel": "7", - "text": "Спрячетесь за колонну.", - "description": "Дракон уходит. " + "nextQuestionLabel": "12", + "text": "Вы вежливо извиняетесь перед космосом за возможные неудобства. Космос впечатлён." } ] }, { "label": "7", - "text": "Дракон пропускает вас, но предупреждает: «Следующий — не человек». В коридоре два пути:", + "text": "Вы представились галактическим юристом, и теперь все ждут продолжения.", "answers": [ { "nextQuestionLabel": "8", - "text": "Левый — пахнет сыростью (возможно, вода).", - "description": "Вы вышли к ручью." + "text": "Вы требуете апелляцию, не уточняя, к чему именно. Звучит убедительно." }, { "nextQuestionLabel": "9", - "text": "Правый — слышны голоса (люди или монстры?).", - "description": "Вы вступили в бой с бандитами и победили их." + "text": "Вы начинаете путаться в терминах и случайно признаётесь во всех преступлениях сразу." + }, + { + "nextQuestionLabel": "10", + "text": "Против всех законов логики вы выигрываете дело. Вогон выглядит озадаченным." }, { - "nextQuestionLabel": "910", - "text": "Вернётесь к статуе за советом.", - "description": "Статуя исчезла." + "nextQuestionLabel": "8", + "text": "В качестве «компромисса» вам предлагают послушать стихи." } ] }, { "label": "8", - "text": "В левом коридоре — подземный ручей. Как перебраться?", + "text": "Поэзия начинается. Это заметно сразу.", "answers": [ { - "nextQuestionLabel": "910", - "text": "Попытаетесь проплыть.", - "description": "Вас уносит течением." + "nextQuestionLabel": "15", + "text": "Вы теряете сознание, руководствуясь инстинктом самосохранения." }, { - "nextQuestionLabel": "9", - "text": "Найдете упавшее бревно и используете его как мост.", - "description": "Мост готов." + "nextQuestionLabel": "6", + "text": "Вы хвалите рифму, чем пугаете всех присутствующих, включая автора." }, { - "nextQuestionLabel": "8", - "text": "Используете верёвку, чтобы перемахнуть.", + "nextQuestionLabel": "9", + "text": "Вы записываете цитаты, чтобы пугать ими знакомых.", "description": "Не хватает длины." }, { - "nextQuestionLabel": "910", - "text": "Поищете обходной путь.", - "description": "Вы заблудились и вас съел дракон." + "nextQuestionLabel": "15", + "text": "Вы просите ещё. Реальность слегка трескается." } ] }, { "label": "9", - "text": "На другом берегу — дверь с замком. Как вы поступите?", + "text": "Ситуация становится заметно хуже, чем была мгновение назад.", "answers": [ { - "nextQuestionLabel": "10", - "text": "Взломаете замок отмычкой.", - "description": "У вас получилось взломать замок." + "nextQuestionLabel": "5", + "text": "Вы решаете сдаться и начать всё сначала." }, { - "nextQuestionLabel": "11", - "text": "Ударите по нему мечом.", - "description": "Замок ломается, но шум привлекает врагов." + "nextQuestionLabel": "12", + "text": "Вы делаете вид, что так и было задумано." }, { - "nextQuestionLabel": "10", - "text": "Поищете ключ поблизости.", - "description": "Вы находите ключ в соседней комнате." + "nextQuestionLabel": "14", + "text": "Вы задаёте главный философский вопрос: «В чём вообще смысл?»" }, { - "nextQuestionLabel": "910", - "text": "Попробуете выбить дверь плечом.", - "description": "Дверь не поддаётся." + "nextQuestionLabel": "3", + "text": "Вы снова начинаете искать полотенце, потому что оно вас ещё ни разу не подводило." } ] }, { "label": "10", - "text": "За дверью — зал с четырьмя алтарями. На каждом — предмет: меч, книга, череп, кристалл. Какой возьмёте?", + "text": "Вас подбирает корабль, который выглядит надёжным ровно настолько, насколько это возможно в галактике.", "answers": [ { - "nextQuestionLabel": "11", - "text": "Меч (для защиты).", - "description": "Активирует ловушку." + "nextQuestionLabel": "16", + "text": "Вы радуетесь спасению и решаете не задавать лишних вопросов." }, { - "nextQuestionLabel": "14", - "text": "Книгу (возможно, подсказка).", - "description": "Подсказка к загадке. " + "nextQuestionLabel": "17", + "text": "Вы внимательно разглядываете экипаж, подозревая худшее." }, { - "nextQuestionLabel": "12", - "text": "Череп (опасно, но магически).", - "description": "Вызывает духа. Вам приходится вступить с ним в бой." + "nextQuestionLabel": "9", + "text": "Вы прячетесь за ближайшим ящиком. На всякий случай." }, { - "nextQuestionLabel": "13", - "text": "Кристалл (светится, может быть артефактом).", - "description": "Светит в темноте." + "nextQuestionLabel": "11", + "text": "Вы спрашиваете, куда летит корабль, и сразу жалеете об этом." } ] }, { "label": "11", - "text": "Статуя оживает! Как поступить?", + "text": "На борту обсуждают еду, и это внезапно кажется важным.", "answers": [ { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" + "nextQuestionLabel": "13", + "text": "Вы заказываете чай, надеясь, что в этот раз всё будет иначе." }, { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" + "nextQuestionLabel": "14", + "text": "Вы снова поднимаете тему смысла жизни. Не вовремя, но искренне." }, { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" + "nextQuestionLabel": "9", + "text": "Вы пробуете что-то странное, светящееся и, возможно, разумное." }, { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" + "nextQuestionLabel": "12", + "text": "Вы решаете ничего не есть и просто подумать." } ] }, { "label": "12", - "text": "Статуя оживает! Как поступить?", + "text": "Вы внезапно ловите себя на том, что задумались. Это опасно, но уже поздно.", "answers": [ { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" + "nextQuestionLabel": "14", + "text": "Вы размышляете о жизни: зачем она дана, почему всё так странно и кто вообще всё это придумал." }, { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" + "nextQuestionLabel": "14", + "text": "Вы думаете о Вселенной — бесконечной, равнодушной и удивительно хорошо организованной для хаоса." }, { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" + "nextQuestionLabel": "14", + "text": "Вы пытаетесь осмыслить всё сразу: жизнь, Вселенную и остальное, но мысль ускользает." }, { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" + "nextQuestionLabel": "5", + "text": "Вы решаете, что думать — занятие переоценённое, и возвращаетесь к реальности." } ] }, { "label": "13", - "text": "Статуя оживает! Как поступить?", + "text": "Вам приносят чай. Он снова не такой, как надо.", "answers": [ { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" + "nextQuestionLabel": "9", + "text": "Вы возмущаетесь, потому что чай — это вопрос принципа, а не вкуса." }, { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" + "nextQuestionLabel": "17", + "text": "Вы пытаетесь улучшить напиток научным методом, добавляя ингредиенты сомнительного происхождения." }, { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" + "nextQuestionLabel": "12", + "text": "Вы философски принимаете чай как символ несовершенства Вселенной." }, { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" + "nextQuestionLabel": "3", + "text": "Вы отвлекаетесь и спрашиваете, где ваше полотенце." } ] }, { "label": "14", - "text": "Статуя оживает! Как поступить?", + "text": "Наступает торжественный момент. Вам задают Главный вопрос жизни, Вселенной и всего такого. Все замолкают. Даже космос делает вид, что слушает.", "answers": [ { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" + "nextQuestionLabel": "9", + "text": "Вы отвечаете: «Любовь». Это звучит красиво, но Вселенная выглядит разочарованной." }, { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" + "nextQuestionLabel": "9", + "text": "Вы честно говорите: «Деньги». Вселенная вздыхает и делает пометку." }, { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" + "nextQuestionLabel": "20", + "text": "Вы уверенно и без лишних слов произносите: 42. Вселенная одобрительно молчит. Это хороший знак." }, { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" + "nextQuestionLabel": "9", + "text": "Вы заявляете, что вопрос сформулирован некорректно. Вселенная кивает, но продолжает эксперимент." } ] }, { "label": "15", - "text": "Статуя оживает! Как поступить?", + "text": "Вы обнаруживаете, что каким-то образом всё ещё существуете.", "answers": [ { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" + "nextQuestionLabel": "16", + "text": "Вы благодарите Вселенную за то, что она сегодня в хорошем настроении." }, { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" + "nextQuestionLabel": "12", + "text": "Вы долго и искренне удивляетесь происходящему." }, { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" + "nextQuestionLabel": "5", + "text": "Вы проверяете, действительно ли вы живы, на всякий случай." }, { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" + "nextQuestionLabel": "17", + "text": "Вы решаете, что это странно, но, вероятно, нормально." } ] }, { "label": "16", - "text": "Статуя оживает! Как поступить?", + "text": "У вас появляется ощущение, что вы близки к истине. Это тревожит.", "answers": [ { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" + "nextQuestionLabel": "20", + "text": "Вы решаете продолжить путешествие, не вдаваясь в детали." }, { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" + "nextQuestionLabel": "14", + "text": "Вы задаёте ещё один вопрос, потому что не умеете останавливаться." }, { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" + "nextQuestionLabel": "12", + "text": "Вы расслабляетесь и позволяете событиям происходить." }, { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" + "nextQuestionLabel": "3", + "text": "Вы автоматически проверяете, при вас ли полотенце." } ] }, { "label": "17", - "text": "Статуя оживает! Как поступить?", + "text": "Перед вами андроид с крайне пессимистичным взглядом на бытие.", "answers": [ { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" + "nextQuestionLabel": "12", + "text": "Вы искренне сочувствуете ему. Андроид растерян: такого он не ожидал." }, { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" + "nextQuestionLabel": "9", + "text": "Вы позволяете ему высказаться. Через некоторое время жалеете об этом." }, { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" + "nextQuestionLabel": "14", + "text": "Вы спрашиваете его о смысле жизни. Он подтверждает, что всё плохо." }, { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" + "nextQuestionLabel": "16", + "text": "Вы медленно отходите, стараясь не привлекать внимания." } ] }, { "label": "18", - "text": "Статуя оживает! Как поступить?", + "text": "Вселенная смотрит на вас с плохо скрываемым интересом.", "answers": [ { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" + "nextQuestionLabel": "12", + "text": "Вы почтительно кланяетесь, считая это уместным." }, { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" + "nextQuestionLabel": "16", + "text": "Вы улыбаетесь, демонстрируя уверенность, которой у вас нет." }, { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" + "nextQuestionLabel": "20", + "text": "Вы прямо спрашиваете: «Ну и что дальше?»" }, { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" + "nextQuestionLabel": "9", + "text": "Вы решаете убежать, пока всё снова не усложнилось." } ] }, { "label": "19", - "text": "Статуя оживает! Как поступить?", + "text": "Вы чувствуете, что ответ уже близко, но всё ещё сомневаетесь.", "answers": [ { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", + "nextQuestionLabel": "20", + "text": "Вы делаете вывод и принимаете его без проверки.", "description": "" }, { - "nextQuestionLabel": "", - "text": "Атакуете первым.", + "nextQuestionLabel": "9", + "text": "Вы решаете всё усложнить, потому что слишком просто не бывает.", "description": "" }, { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" + "nextQuestionLabel": "14", + "text": "Вы спрашиваете ещё раз, на всякий случай." }, { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" + "nextQuestionLabel": "16", + "text": "Вы напоминаете себе главное правило — не паниковать." } ] }, { "label": "20", - "text": "Статуя оживает! Как поступить?", + "text": "После всего пережитого вы наконец понимаете главное.", "answers": [ { - "nextQuestionLabel": "", - "text": "Попробуете заговорить с ней.", - "description": "" + "nextQuestionLabel": "+810", + "text": "Всегда носи полотенце" }, { - "nextQuestionLabel": "", - "text": "Атакуете первым.", - "description": "" + "nextQuestionLabel": "+810", + "text": "Не паникуй" }, { - "nextQuestionLabel": "", - "text": "Бросите в неё магический свиток.", - "description": "" + "nextQuestionLabel": "+810", + "text": "Ответ — 42" }, { - "nextQuestionLabel": "", - "text": "Спрячетесь за колонну.", - "description": "" + "nextQuestionLabel": "+810", + "text": "Всё вышеперечисленное" } ] }, { - "label": "810", - "text": "Победа!", - "answers": null - }, - { - "label": "910", - "text": "Поражение...", + "label": "+810", + "text": "Поздравляем! Вы прошли квест, не сломали Вселенную и, возможно, даже стали немного мудрее.", "answers": null } ] diff --git a/src/main/resources/json/quest-3.json b/src/main/resources/json/quest-3.json index 2535cc8..0e8c7ff 100644 --- a/src/main/resources/json/quest-3.json +++ b/src/main/resources/json/quest-3.json @@ -1,456 +1,167 @@ { - "title": "Автостопом по здравому смыслу (или Не паникуй)", - "description": "По мотивам «Автостопом по Галактике»", - "text": "Добро пожаловать в квест, который начинается с конца света и быстро переходит к вопросам посложнее. Землю сносят ради гиперпространственной магистрали, предупреждения были вывешены (где-то далеко и давно), а у вас есть лишь выбор, полотенце и крайне смутное представление о происходящем. Впереди — вогоны, сомнительный чай, философские размышления и шанс узнать ответ на Главный вопрос жизни, Вселенной и всего такого. Главное — не паникуйте: Вселенная всё равно делает вид, что всё под контролем.", + "title": "Знаешь ли ты английский достаточно для того, чтобы играть в игры?", + "description": "Проверь свой базовый игровой словарный запас и понимание типичных фраз из англоязычных видеоигр", + "text": "Ты собираешься запустить новую RPG на английском, но не уверен, поймёшь ли диалоги и интерфейс. Давай проверим! На каждый вопрос — 3–4 варианта. Выбери один. Ошибёшься — игра «завершится».", "questions": [ { "label": "1", - "text": "Вы просыпаетесь и узнаёте, что Землю демонтируют ради гиперпространственной магистрали. Что будете делать?", + "text": "Что означает кнопка «Continue» в меню игры?", "answers": [ { - "nextQuestionLabel": "2", - "text": "Вы возмущённо требуете документы, разрешения и хотя бы подпись ответственного лица. Вселенная равнодушно зевает." + "nextQuestionLabel": "-910", + "text": "Начать заново" }, { - "nextQuestionLabel": "3", - "text": "Вы вспоминаете главное правило галактического путешественника и лихорадочно ищете полотенце. Это внушает необъяснимое спокойствие." + "nextQuestionLabel": "-910", + "text": "Сохранить игру" }, { - "nextQuestionLabel": "4", - "text": "Вы уточняете, будет ли обед до конца света, потому что на голодный желудок апокалипсис переносится хуже." + "nextQuestionLabel": "2", + "text": "Продолжить" }, { - "nextQuestionLabel": "5", - "text": "Вы решаете, что это сон, и пробуете снова уснуть, пока Вселенная не передумала." + "nextQuestionLabel": "-910", + "text": "Выйти" } ] }, { "label": "2", - "text": "Перед вами стоит вогон, держащий папку подозрительно толстых стихов.", + "text": "Как перевести «Quest accepted»?", "answers": [ { - "nextQuestionLabel": "6", - "text": "Вы пытаетесь убежать, но быстро понимаете, что в условиях вакуума это не лучшая стратегия." + "nextQuestionLabel": "-911", + "text": "Квест завершён" }, { - "nextQuestionLabel": "7", - "text": "Вы представляете себя галактическим юристом и начинаете говорить словами, смысл которых неизвестен даже вам." + "nextQuestionLabel": "3", + "text": "Квест принят" }, { - "nextQuestionLabel": "8", - "text": "Вы вежливо просите почитать стихи вслух, подозревая, что хуже уже не будет." + "nextQuestionLabel": "-911", + "text": "Квест провалился»" }, { - "nextQuestionLabel": "9", - "text": "Вы начинаете плакать заранее, экономя время на эмоциональной реакции." + "nextQuestionLabel": "-911", + "text": "Квест недоступен" } ] }, { "label": "3", - "text": "Полотенце найдено. Оно слегка влажное, но внушает доверие.", + "text": "Что значит «HP at critical level!»?", "answers": [ { - "nextQuestionLabel": "6", - "text": "Вы используете его как универсальное средство защиты от всего непонятного." + "nextQuestionLabel": "4", + "text": "Здоровье на критическом уровне!" }, { - "nextQuestionLabel": "10", - "text": "Вы накидываете его как плащ и чувствуете себя героем космооперы." + "nextQuestionLabel": "-912", + "text": "Мана на критическом уровне!" }, { - "nextQuestionLabel": "5", - "text": "Вы обнимаете полотенце, потому что оно единственное, что сейчас вас понимает." + "nextQuestionLabel": "-912", + "text": "Энергия на нуле!" }, { - "nextQuestionLabel": "9", - "text": "Вы тут же его теряете, подтверждая законы Вселенной." + "nextQuestionLabel": "-912", + "text": "Время истекает!" } ] }, { "label": "4", - "text": "Мысли о еде не покидают вас даже в момент уничтожения планеты.", + "text": "Какой вариант означает «Сохранить игру»?", "answers": [ { - "nextQuestionLabel": "11", - "text": "Вы решаете сделать бутерброд, игнорируя катастрофу как нечто второстепенное." - }, - { - "nextQuestionLabel": "12", - "text": "Вы жалуетесь Вселенной на несвоевременность происходящего." + "nextQuestionLabel": "-913", + "text": "Load game" }, { "nextQuestionLabel": "5", - "text": "Вы смиряетесь с судьбой и принимаете происходящее как должное." - }, - { - "nextQuestionLabel": "13", - "text": "Вы спрашиваете, где чай, потому что без него цивилизация не имеет смысла." - } - ] - }, - { - "label": "5", - "text": "Вы понимаете: это не сон, а реальность, причём весьма навязчивая.", - "answers": [ - { - "nextQuestionLabel": "9", - "text": "Вы начинаете паниковать, громко и без системы." - }, - { - "nextQuestionLabel": "10", - "text": "Вы вспоминаете надпись «DON’T PANIC» и стараетесь выглядеть уверенно." - }, - { - "nextQuestionLabel": "12", - "text": "Вы философски принимаете происходящее, как будто читали об этом раньше.", - "description": "" - }, - { - "nextQuestionLabel": "14", - "text": "Вы выкрикиваете «42!» без всякой причины, но с чувством." - } - ] - }, - { - "label": "6", - "text": "Вас без особых церемоний выбрасывают в открытый космос. Он холодный, бесконечный и явно не собирается извиняться.", - "answers": [ - { - "nextQuestionLabel": "15", - "text": "Вы задерживаете дыхание, словно космос обязан это заметить и проявить такт." - }, - { - "nextQuestionLabel": "9", - "text": "Вы начинаете кричать, несмотря на смутное подозрение, что звук здесь не работает." - }, - { - "nextQuestionLabel": "16", - "text": "Вы решаете положиться на сюжетную броню главного героя, даже если не уверены, что вы главный." - }, - { - "nextQuestionLabel": "12", - "text": "Вы вежливо извиняетесь перед космосом за возможные неудобства. Космос впечатлён." - } - ] - }, - { - "label": "7", - "text": "Вы представились галактическим юристом, и теперь все ждут продолжения.", - "answers": [ - { - "nextQuestionLabel": "8", - "text": "Вы требуете апелляцию, не уточняя, к чему именно. Звучит убедительно." + "text": "Save game" }, { - "nextQuestionLabel": "9", - "text": "Вы начинаете путаться в терминах и случайно признаётесь во всех преступлениях сразу." + "nextQuestionLabel": "-913", + "text": "Delete game" }, { - "nextQuestionLabel": "10", - "text": "Против всех законов логики вы выигрываете дело. Вогон выглядит озадаченным." - }, - { - "nextQuestionLabel": "8", - "text": "В качестве «компромисса» вам предлагают послушать стихи." + "nextQuestionLabel": "-913", + "text": "Start game" } ] }, { - "label": "8", - "text": "Поэзия начинается. Это заметно сразу.", + "label": "5", + "text": "Ты видишь диалог: «I’ll meet you at the crossroads. Be wary of bandits.» Что это значит?", "answers": [ - { - "nextQuestionLabel": "15", - "text": "Вы теряете сознание, руководствуясь инстинктом самосохранения." - }, { "nextQuestionLabel": "6", - "text": "Вы хвалите рифму, чем пугаете всех присутствующих, включая автора." - }, - { - "nextQuestionLabel": "9", - "text": "Вы записываете цитаты, чтобы пугать ими знакомых.", - "description": "Не хватает длины." - }, - { - "nextQuestionLabel": "15", - "text": "Вы просите ещё. Реальность слегка трескается." - } - ] - }, - { - "label": "9", - "text": "Ситуация становится заметно хуже, чем была мгновение назад.", - "answers": [ - { - "nextQuestionLabel": "5", - "text": "Вы решаете сдаться и начать всё сначала." - }, - { - "nextQuestionLabel": "12", - "text": "Вы делаете вид, что так и было задумано." - }, - { - "nextQuestionLabel": "14", - "text": "Вы задаёте главный философский вопрос: «В чём вообще смысл?»" - }, - { - "nextQuestionLabel": "3", - "text": "Вы снова начинаете искать полотенце, потому что оно вас ещё ни разу не подводило." - } - ] - }, - { - "label": "10", - "text": "Вас подбирает корабль, который выглядит надёжным ровно настолько, насколько это возможно в галактике.", - "answers": [ - { - "nextQuestionLabel": "16", - "text": "Вы радуетесь спасению и решаете не задавать лишних вопросов." + "text": "Я встречу тебя у перекрёстка. Остерегайся бандитов.»" }, { - "nextQuestionLabel": "17", - "text": "Вы внимательно разглядываете экипаж, подозревая худшее." + "nextQuestionLabel": "-914", + "text": "Я жду тебя у реки. Будь осторожен с волками." }, { - "nextQuestionLabel": "9", - "text": "Вы прячетесь за ближайшим ящиком. На всякий случай." + "nextQuestionLabel": "-914", + "text": "Встретимся в таверне. Не доверяй незнакомцам." }, { - "nextQuestionLabel": "11", - "text": "Вы спрашиваете, куда летит корабль, и сразу жалеете об этом." + "nextQuestionLabel": "-914", + "text": "Иди на север. Там безопасно." } ] }, { - "label": "11", - "text": "На борту обсуждают еду, и это внезапно кажется важным.", - "answers": [ - { - "nextQuestionLabel": "13", - "text": "Вы заказываете чай, надеясь, что в этот раз всё будет иначе." - }, - { - "nextQuestionLabel": "14", - "text": "Вы снова поднимаете тему смысла жизни. Не вовремя, но искренне." - }, - { - "nextQuestionLabel": "9", - "text": "Вы пробуете что-то странное, светящееся и, возможно, разумное." - }, - { - "nextQuestionLabel": "12", - "text": "Вы решаете ничего не есть и просто подумать." - } - ] - }, - { - "label": "12", - "text": "Вы внезапно ловите себя на том, что задумались. Это опасно, но уже поздно.", - "answers": [ - { - "nextQuestionLabel": "14", - "text": "Вы размышляете о жизни: зачем она дана, почему всё так странно и кто вообще всё это придумал." - }, - { - "nextQuestionLabel": "14", - "text": "Вы думаете о Вселенной — бесконечной, равнодушной и удивительно хорошо организованной для хаоса." - }, - { - "nextQuestionLabel": "14", - "text": "Вы пытаетесь осмыслить всё сразу: жизнь, Вселенную и остальное, но мысль ускользает." - }, - { - "nextQuestionLabel": "5", - "text": "Вы решаете, что думать — занятие переоценённое, и возвращаетесь к реальности." - } - ] - }, - { - "label": "13", - "text": "Вам приносят чай. Он снова не такой, как надо.", + "label": "6", + "text": "В инвентаре написано: «Rusted sword (Durability: 20/100)». Что это значит?", "answers": [ { - "nextQuestionLabel": "9", - "text": "Вы возмущаетесь, потому что чай — это вопрос принципа, а не вкуса." + "nextQuestionLabel": "-915", + "text": "Старый меч (Урон: 20/100)" }, { - "nextQuestionLabel": "17", - "text": "Вы пытаетесь улучшить напиток научным методом, добавляя ингредиенты сомнительного происхождения." + "nextQuestionLabel": "-915", + "text": "Сломанный меч (Вес: 20/100)" }, { - "nextQuestionLabel": "12", - "text": "Вы философски принимаете чай как символ несовершенства Вселенной." + "nextQuestionLabel": "+810", + "text": "Ржавый меч (Прочность: 20/100)" }, { - "nextQuestionLabel": "3", - "text": "Вы отвлекаетесь и спрашиваете, где ваше полотенце." + "nextQuestionLabel": "-915", + "text": "Меч с руной (Заряды: 20/100)" } ] }, { - "label": "14", - "text": "Наступает торжественный момент. Вам задают Главный вопрос жизни, Вселенной и всего такого. Все замолкают. Даже космос делает вид, что слушает.", - "answers": [ - { - "nextQuestionLabel": "9", - "text": "Вы отвечаете: «Любовь». Это звучит красиво, но Вселенная выглядит разочарованной." - }, - { - "nextQuestionLabel": "9", - "text": "Вы честно говорите: «Деньги». Вселенная вздыхает и делает пометку." - }, - { - "nextQuestionLabel": "20", - "text": "Вы уверенно и без лишних слов произносите: 42. Вселенная одобрительно молчит. Это хороший знак." - }, - { - "nextQuestionLabel": "9", - "text": "Вы заявляете, что вопрос сформулирован некорректно. Вселенная кивает, но продолжает эксперимент." - } - ] + "label": "+810", + "text": "Ты прошёл квест! Твой английский достаточно хорош, чтобы разбираться в интерфейсе, квестах и диалогах англоязычных игр." }, { - "label": "15", - "text": "Вы обнаруживаете, что каким-то образом всё ещё существуете.", - "answers": [ - { - "nextQuestionLabel": "16", - "text": "Вы благодарите Вселенную за то, что она сегодня в хорошем настроении." - }, - { - "nextQuestionLabel": "12", - "text": "Вы долго и искренне удивляетесь происходящему." - }, - { - "nextQuestionLabel": "5", - "text": "Вы проверяете, действительно ли вы живы, на всякий случай." - }, - { - "nextQuestionLabel": "17", - "text": "Вы решаете, что это странно, но, вероятно, нормально." - } - ] + "label": "-910", + "text": "«Continue» — это «продолжить», а не «выйти» или «начать заново». Игра завершена. Попробуй ещё!" }, { - "label": "16", - "text": "У вас появляется ощущение, что вы близки к истине. Это тревожит.", - "answers": [ - { - "nextQuestionLabel": "20", - "text": "Вы решаете продолжить путешествие, не вдаваясь в детали." - }, - { - "nextQuestionLabel": "14", - "text": "Вы задаёте ещё один вопрос, потому что не умеете останавливаться." - }, - { - "nextQuestionLabel": "12", - "text": "Вы расслабляетесь и позволяете событиям происходить." - }, - { - "nextQuestionLabel": "3", - "text": "Вы автоматически проверяете, при вас ли полотенце." - } - ] + "label": "-911", + "text": "«Quest accepted» значит «Квест принят». Без понимания квестов далеко не уйдёшь. Игра завершена." }, { - "label": "17", - "text": "Перед вами андроид с крайне пессимистичным взглядом на бытие.", - "answers": [ - { - "nextQuestionLabel": "12", - "text": "Вы искренне сочувствуете ему. Андроид растерян: такого он не ожидал." - }, - { - "nextQuestionLabel": "9", - "text": "Вы позволяете ему высказаться. Через некоторое время жалеете об этом." - }, - { - "nextQuestionLabel": "14", - "text": "Вы спрашиваете его о смысле жизни. Он подтверждает, что всё плохо." - }, - { - "nextQuestionLabel": "16", - "text": "Вы медленно отходите, стараясь не привлекать внимания." - } - ] + "label": "-912", + "text": "«HP» = Health Points («здоровье»). Критический уровень HP — пора лечиться. Игра завершена." }, { - "label": "18", - "text": "Вселенная смотрит на вас с плохо скрываемым интересом.", - "answers": [ - { - "nextQuestionLabel": "12", - "text": "Вы почтительно кланяетесь, считая это уместным." - }, - { - "nextQuestionLabel": "16", - "text": "Вы улыбаетесь, демонстрируя уверенность, которой у вас нет." - }, - { - "nextQuestionLabel": "20", - "text": "Вы прямо спрашиваете: «Ну и что дальше?»" - }, - { - "nextQuestionLabel": "9", - "text": "Вы решаете убежать, пока всё снова не усложнилось." - } - ] + "label": "-913", + "text": "«Save game» — «Сохранить игру». «Load» — загрузить, «Delete» — удалить. Игра завершена." }, { - "label": "19", - "text": "Вы чувствуете, что ответ уже близко, но всё ещё сомневаетесь.", - "answers": [ - { - "nextQuestionLabel": "20", - "text": "Вы делаете вывод и принимаете его без проверки.", - "description": "" - }, - { - "nextQuestionLabel": "9", - "text": "Вы решаете всё усложнить, потому что слишком просто не бывает.", - "description": "" - }, - { - "nextQuestionLabel": "14", - "text": "Вы спрашиваете ещё раз, на всякий случай." - }, - { - "nextQuestionLabel": "16", - "text": "Вы напоминаете себе главное правило — не паниковать." - } - ] - }, - { - "label": "20", - "text": "После всего пережитого вы наконец понимаете главное.", - "answers": [ - { - "nextQuestionLabel": "+810", - "text": "Всегда носи полотенце" - }, - { - "nextQuestionLabel": "+810", - "text": "Не паникуй" - }, - { - "nextQuestionLabel": "+810", - "text": "Ответ — 42" - }, - { - "nextQuestionLabel": "+810", - "text": "Всё вышеперечисленное" - } - ] + "label": "-914", + "text": "Правильный перевод: «Я встречу тебя у перекрёстка. Остерегайся бандитов». Без понимания диалогов не пройти сюжет. Игра завершена." }, { - "label": "+810", - "text": "Поздравляем! Вы прошли квест, не сломали Вселенную и, возможно, даже стали немного мудрее.", - "answers": null + "label": "-915", + "text": "«Durability» = «прочность». Без понимания параметров инвентаря сложно выжить. Игра завершена." } ] } From 0b57b867f391e8a9b963368376030a927b45870b Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Tue, 3 Feb 2026 16:20:11 +0500 Subject: [PATCH 52/65] ADD unit tests for UserService and integration tests for Login --- pom.xml | 20 ++ .../java/com/javarush/vasileva/cmd/Login.java | 2 +- .../com/javarush/vasileva/entity/User.java | 2 - .../java/com/javarush/vasileva/BaseIT.java | 67 +++++++ .../com/javarush/vasileva/cmd/LoginIT.java | 111 +++++++++++ .../vasileva/service/UserServiceTest.java | 185 ++++++++++++++++++ 6 files changed, 384 insertions(+), 3 deletions(-) create mode 100644 src/test/java/com/javarush/vasileva/BaseIT.java create mode 100644 src/test/java/com/javarush/vasileva/cmd/LoginIT.java create mode 100644 src/test/java/com/javarush/vasileva/service/UserServiceTest.java diff --git a/pom.xml b/pom.xml index 844dec6..4614946 100644 --- a/pom.xml +++ b/pom.xml @@ -70,6 +70,7 @@ lombok provided + org.junit.jupiter junit-jupiter-api @@ -80,6 +81,17 @@ junit-jupiter-engine test + + org.mockito + mockito-junit-jupiter + test + + + org.jetbrains + annotations + 17.0.0 + test + com.fasterxml.jackson.dataformat @@ -109,6 +121,14 @@ + + org.apache.maven.plugins + maven-surefire-plugin + 3.1.2 + + false + + diff --git a/src/main/java/com/javarush/vasileva/cmd/Login.java b/src/main/java/com/javarush/vasileva/cmd/Login.java index fe1ea13..3e79450 100644 --- a/src/main/java/com/javarush/vasileva/cmd/Login.java +++ b/src/main/java/com/javarush/vasileva/cmd/Login.java @@ -42,7 +42,7 @@ public String doPost(HttpServletRequest request) { if (email.isEmpty() || password.isEmpty()) { LOGGER.warn("Empty email or password provided"); request.getSession().setAttribute(Key.ERROR, EMPTY_DATA_ERROR); - + return getView(); } Optional optionalUser = userService.login(email, password); diff --git a/src/main/java/com/javarush/vasileva/entity/User.java b/src/main/java/com/javarush/vasileva/entity/User.java index 168c5d9..65c778b 100644 --- a/src/main/java/com/javarush/vasileva/entity/User.java +++ b/src/main/java/com/javarush/vasileva/entity/User.java @@ -21,8 +21,6 @@ public class User { private Role role; - private int gameNumber; - @SuppressWarnings("unused") public boolean isAdmin() { return role != null && role.equals(Role.ADMIN); diff --git a/src/test/java/com/javarush/vasileva/BaseIT.java b/src/test/java/com/javarush/vasileva/BaseIT.java new file mode 100644 index 0000000..7e0efaa --- /dev/null +++ b/src/test/java/com/javarush/vasileva/BaseIT.java @@ -0,0 +1,67 @@ +package com.javarush.vasileva; + +import com.javarush.vasileva.config.Config; +import com.javarush.vasileva.config.Winter; +import com.javarush.vasileva.entity.Role; +import com.javarush.vasileva.entity.User; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletContext; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import org.mockito.Mockito; + +import static org.mockito.Mockito.when; + +public class BaseIT { + protected final HttpServletRequest req; + protected final HttpServletResponse resp; + protected final HttpSession session; + protected final Config config; + protected final ServletConfig servletConfig; + protected final ServletContext servletContext; + + protected User testAdmin; + protected User testUser; + protected User testGuest; + + public BaseIT() { + config = Winter.find(Config.class); + config.fillRepository(); + + servletConfig = Mockito.mock(ServletConfig.class); + servletContext = Mockito.mock(ServletContext.class); + when(servletConfig.getServletContext()).thenReturn(servletContext); + + req = Mockito.mock(HttpServletRequest.class); + resp = Mockito.mock(HttpServletResponse.class); + session = Mockito.mock(HttpSession.class); + when(req.getSession()).thenReturn(session); + + testAdmin = User.builder() + .id(1L) + .login("testAdmin") + .email("admin@test.com") + .password("testAdmin") + .role(Role.ADMIN) + .build(); + + testUser = User.builder() + .id(2L) + .login("testUser") + .email("user@test.com") + .password("testUser") + .role(Role.USER) + .build(); + + testGuest = User.builder() + .id(3L) + .login("testGuest") + .email("guest@test.com") + .password("testGuest") + .role(Role.GUEST) + .build(); + } + + +} diff --git a/src/test/java/com/javarush/vasileva/cmd/LoginIT.java b/src/test/java/com/javarush/vasileva/cmd/LoginIT.java new file mode 100644 index 0000000..e27a505 --- /dev/null +++ b/src/test/java/com/javarush/vasileva/cmd/LoginIT.java @@ -0,0 +1,111 @@ +package com.javarush.vasileva.cmd; + +import com.javarush.vasileva.BaseIT; +import com.javarush.vasileva.entity.UserStats; +import com.javarush.vasileva.service.UserService; +import com.javarush.vasileva.service.UserStatsService; +import com.javarush.vasileva.util.Key; +import com.javarush.vasileva.util.Link; +import com.javarush.vasileva.util.Value; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.Optional; + +import static com.javarush.vasileva.util.Key.USER; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +public class LoginIT extends BaseIT { + + private final UserService userService = Mockito.mock(UserService.class); + private final UserStatsService userStatsService = Mockito.mock(UserStatsService.class); + + private final Login login = new Login(userService, userStatsService); + + @Test + @DisplayName("when valid credentials then redirect to HOME and set session attributes") + void whenValidCredentialsThenRedirectToHomeAndSetSessionAttributes() { + when(req.getParameter(Key.EMAIL)).thenReturn(testAdmin.getEmail()); + when(req.getParameter(Key.PASSWORD)).thenReturn(testAdmin.getPassword()); + + when(userService.login(testAdmin.getEmail(), testAdmin.getPassword())) + .thenReturn(Optional.of(testAdmin)); + + UserStats stats = new UserStats(); + stats.setUserId(testAdmin.getId()); + when(userStatsService.getUserStats(testAdmin.getId())).thenReturn(Optional.of(stats)); + + String redirect = login.doPost(req); + + assertEquals(Link.HOME, redirect); + + verify(session).setAttribute(USER, testAdmin); + verify(session).setAttribute(Key.STATS, stats); + + verify(userService).login(testAdmin.getEmail(), testAdmin.getPassword()); + verify(userStatsService).getUserStats(testAdmin.getId()); + } + + @Test + @DisplayName("when invalid credentials then set error end return view") + void whenInvalidCredentials_ThenSetErrorEndReturnView() { + String invalidPassword = "wrongPassword"; + when(req.getParameter(Key.EMAIL)).thenReturn(testAdmin.getEmail()); + when(req.getParameter(Key.PASSWORD)).thenReturn(invalidPassword); + + when(userService.login(testAdmin.getEmail(), invalidPassword)) + .thenReturn(Optional.empty()); + + String redirect = login.doPost(req); + + assertEquals(login.getView(), redirect); + verify(session).setAttribute(Key.ERROR, Value.INVALID_DATA_ERROR); + verify(userService).login(testAdmin.getEmail(), invalidPassword); + verifyNoMoreInteractions(userStatsService); + } + + @Test + @DisplayName("when empty email or password then set error and return view") + void whenEmptyEmailOrPassword_ThenSetErrorAndReturnView() { + String emptyEmail = ""; + String emptyPassword = ""; + when(req.getParameter(Key.EMAIL)).thenReturn(emptyEmail); + when(req.getParameter(Key.PASSWORD)).thenReturn(emptyPassword); + + String redirect = login.doPost(req); + + assertEquals(login.getView(), redirect); + verify(session).setAttribute(Key.ERROR, Value.EMPTY_DATA_ERROR); + verifyNoInteractions(userService); + verifyNoInteractions(userStatsService); + } + + @Test + @DisplayName("when user has no stats then create new stats") + void whenUserHasNoStats_ThenCreateNewStats() { + when(req.getParameter(Key.EMAIL)).thenReturn(testAdmin.getEmail()); + when(req.getParameter(Key.PASSWORD)).thenReturn(testAdmin.getPassword()); + + when(userService.login(testAdmin.getEmail(), testAdmin.getPassword())) + .thenReturn(Optional.of(testAdmin)); + + UserStats stats = new UserStats(); + stats.setUserId(testAdmin.getId()); + when(userStatsService.getUserStats(testAdmin.getId())) + .thenReturn(Optional.empty()); + when(userStatsService.createUserStats(testAdmin.getId())) + .thenReturn(stats); + + String redirect = login.doPost(req); + + assertEquals(Link.HOME, redirect); + verify(session).setAttribute(Key.USER, testAdmin); + verify(session).setAttribute(Key.STATS, stats); + verify(userStatsService).createUserStats(testAdmin.getId()); + + } + + +} diff --git a/src/test/java/com/javarush/vasileva/service/UserServiceTest.java b/src/test/java/com/javarush/vasileva/service/UserServiceTest.java new file mode 100644 index 0000000..c67b650 --- /dev/null +++ b/src/test/java/com/javarush/vasileva/service/UserServiceTest.java @@ -0,0 +1,185 @@ +package com.javarush.vasileva.service; + +import com.javarush.vasileva.entity.Role; +import com.javarush.vasileva.entity.User; +import com.javarush.vasileva.repository.UserRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class UserServiceTest { + + @Mock + private UserRepository userRepository; + + @InjectMocks + private UserService userService; + + private User testUser; + + @BeforeEach + public void setUp() { + testUser = User.builder() + .id(1L) + .login("testuser") + .email("test@gmail.com") + .password("password123") + .role(Role.USER) + .build(); + } + + @Test + @DisplayName("given user when create then repository create called") + void givenUser_whenCreate_ThenRepositoryCreateCalled() { + userRepository.create(testUser); + verify(userRepository, times(1)).create(testUser); + } + + @Test + @DisplayName("given user when update then repository update called") + void givenUser_whenUpdate_ThenRepositoryUpdateCalled() { + userRepository.update(testUser); + verify(userRepository, times(1)).update(testUser); + } + + @Test + @DisplayName("given user when delete then repository delete called") + void givenUser_whenDelete_ThenRepositoryDeleteCalled() { + userRepository.delete(testUser); + verify(userRepository, times(1)).delete(testUser); + } + + @Test + @DisplayName("given users in repo when get all then return list") + void givenUsersInRepo_whenGetAll_thenReturnList() { + List users = Collections.singletonList(testUser); + when(userRepository.getAll()).thenReturn(users); + + List result = userService.getAll(); + + assertEquals(1, result.size()); + assertEquals(testUser.getId(), result.get(0).getId()); + verify(userRepository, times(1)).getAll(); + } + + @Test + @DisplayName("given user id exists when find by id then return user") + void givenUserIdExists_WhenFindById_ThenReturnUser() { + long userId = testUser.getId(); + when(userRepository.findById(userId)).thenReturn(Optional.of(testUser)); + + Optional result = userService.findById(userId); + + assertTrue(result.isPresent()); + assertEquals(testUser.getId(), result.get().getId()); + verify(userRepository, times(1)).findById(userId); + } + + @Test + @DisplayName("given user id not found when find by id then return empty") + void givenUserIdNotFound_WhenFindById_ThenReturnEmpty() { + long absentUserId = -1L; + when(userRepository.findById(absentUserId)).thenReturn(Optional.empty()); + + Optional result = userService.findById(absentUserId); + + assertFalse(result.isPresent()); + verify(userRepository, times(1)).findById(absentUserId); + } + + @Test + @DisplayName("given login email password when register then repository create user with user role") + void givenLoginEmailPassword_WhenRegister_ThenRepositoryCreateUser() { + String regName = "newuser"; + String regEmail = "new@email.com"; + String regPassword = "password123"; + userService.register(regName, regEmail, regPassword); + + User expectedUser = User.builder() + .login(regName) + .email(regEmail) + .password(regPassword) + .role(Role.USER) + .build(); + + assertEquals(expectedUser.getRole(), Role.USER); + verify(userRepository, times(1)).create(expectedUser); + } + + @Test + @DisplayName("given valid email and password when login then return user") + void givenValidEmailAndPassword_WhenLogin_ThenReturnUser() { + String validEmail = "test@gmail.com"; + String validPassword = "password123"; + when(userRepository.findByEmail(validEmail)).thenReturn(Optional.of(testUser)); + + Optional result = userService.login(validEmail, validPassword); + + assertTrue(result.isPresent()); + assertEquals(testUser.getId(), result.get().getId()); + verify(userRepository, times(1)).findByEmail(validEmail); + } + + @Test + @DisplayName("given wrong password when login then return empty") + void givenWrongPassword_WhenLogin_ThenReturnEmpty() { + String validEmail = "test@gmail.com"; + String invalidPassword = "password"; + when(userRepository.findByEmail(validEmail)).thenReturn(Optional.of(testUser)); + + Optional result = userService.login(validEmail, invalidPassword); + + assertFalse(result.isPresent()); + verify(userRepository, times(1)).findByEmail(validEmail); + } + + @Test + @DisplayName("given wrong email when login then return empty") + void givenWrongLogin_WhenLogin_ThenReturnEmpty() { + String invalidEmail = "test2@gmail.com"; + String validPassword = "password123"; + when(userRepository.findByEmail(invalidEmail)).thenReturn(Optional.empty()); + + Optional result = userService.login(invalidEmail, validPassword); + + assertFalse(result.isPresent()); + verify(userRepository, times(1)).findByEmail(invalidEmail); + } + + @Test + @DisplayName("given valid user id string when get validated user then return user") + void givenValidUserIdString_WhenGetValidatedUser_ThenReturnUser() { + when(userRepository.findById(1L)).thenReturn(Optional.of(testUser)); + + Optional result = userService.getValidatedUser("1"); + + assertTrue(result.isPresent()); + assertEquals(testUser.getId(), result.get().getId()); + } + + @Test + @DisplayName("given empty user id string when get validated user then return empty") + void givenEmptyUserIdString_whenGetValidatedUser_thenReturnEmpty() { + Optional result = userService.getValidatedUser(""); + assertFalse(result.isPresent()); + } + + @Test + @DisplayName("given null user when get validated user then return empty") + void givenNullUserIdString_whenGetValidatedUser_thenReturnEmpty() { + Optional result = userService.getValidatedUser(null); + assertFalse(result.isPresent()); + } +} From c90bd02d0a21e94b6cf19aef30111c069919a742 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Tue, 3 Feb 2026 18:47:46 +0500 Subject: [PATCH 53/65] ADD integration tests for Register and Home --- .../com/javarush/vasileva/cmd/EditQuest.java | 8 +- .../java/com/javarush/vasileva/cmd/Home.java | 11 +- .../com/javarush/vasileva/cmd/UserList.java | 8 +- .../vasileva/service/AuthService.java | 20 +++ .../vasileva/service/UserService.java | 1 - .../com/javarush/vasileva/util/Helpers.java | 16 --- .../java/com/javarush/vasileva/BaseIT.java | 58 ++++++++- .../com/javarush/vasileva/cmd/HomeIT.java | 99 +++++++++++++++ .../com/javarush/vasileva/cmd/RegisterIT.java | 116 ++++++++++++++++++ 9 files changed, 307 insertions(+), 30 deletions(-) create mode 100644 src/main/java/com/javarush/vasileva/service/AuthService.java create mode 100644 src/test/java/com/javarush/vasileva/cmd/HomeIT.java create mode 100644 src/test/java/com/javarush/vasileva/cmd/RegisterIT.java diff --git a/src/main/java/com/javarush/vasileva/cmd/EditQuest.java b/src/main/java/com/javarush/vasileva/cmd/EditQuest.java index 3e74522..559ab66 100644 --- a/src/main/java/com/javarush/vasileva/cmd/EditQuest.java +++ b/src/main/java/com/javarush/vasileva/cmd/EditQuest.java @@ -5,8 +5,8 @@ import com.javarush.vasileva.entity.Quest; import com.javarush.vasileva.exception.AppException; import com.javarush.vasileva.mapper.QuestMapper; +import com.javarush.vasileva.service.AuthService; import com.javarush.vasileva.service.QuestService; -import com.javarush.vasileva.util.Helpers; import jakarta.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,12 +24,14 @@ public class EditQuest implements Command { private static final Logger LOGGER = LoggerFactory.getLogger(EditQuest.class.getName()); private final QuestService questService; + private final AuthService authService; private final QuestMapper questMapper = Winter.find(QuestMapper.class); private final Config config; @SuppressWarnings("unused") - public EditQuest(QuestService questService, Config config) { + public EditQuest(QuestService questService, AuthService authService, Config config) { this.questService = questService; + this.authService = authService; this.config = config; } @@ -37,7 +39,7 @@ public EditQuest(QuestService questService, Config config) { public String doGet(HttpServletRequest req) { LOGGER.info("Received GET request to edit quests"); - Helpers.checkAdminAuthorization(req, EDIT_QUEST_AUTH_ERROR); + authService.checkAdminAuthorization(req, EDIT_QUEST_AUTH_ERROR); List quests = questService.getAll(); req.setAttribute(QUESTS, quests); diff --git a/src/main/java/com/javarush/vasileva/cmd/Home.java b/src/main/java/com/javarush/vasileva/cmd/Home.java index f728cbc..15cb48c 100644 --- a/src/main/java/com/javarush/vasileva/cmd/Home.java +++ b/src/main/java/com/javarush/vasileva/cmd/Home.java @@ -1,8 +1,9 @@ package com.javarush.vasileva.cmd; import com.javarush.vasileva.entity.Quest; +import com.javarush.vasileva.exception.AppException; +import com.javarush.vasileva.service.AuthService; import com.javarush.vasileva.service.QuestService; -import com.javarush.vasileva.util.Helpers; import jakarta.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,9 +19,11 @@ public class Home implements Command { private static final Logger LOGGER = LoggerFactory.getLogger(Home.class.getName()); private final QuestService questService; + private final AuthService authService; - public Home(QuestService questService) { + public Home(QuestService questService, AuthService authService) { this.questService = questService; + this.authService = authService; } @Override @@ -36,14 +39,14 @@ public String doGet(HttpServletRequest req) { public String doDelete(HttpServletRequest req) { LOGGER.info("Received DELETE request for quest"); - Helpers.checkAdminAuthorization(req, DELETE_QUEST_AUTH_ERROR); + authService.checkAdminAuthorization(req, DELETE_QUEST_AUTH_ERROR); LOGGER.debug("Admin authorization successful"); String questIdStr = req.getParameter(QUEST_ID); LOGGER.debug("Attempting to delete quest with ID: {}", questIdStr); Quest quest = questService.getValidatedQuest(questIdStr) - .orElseThrow(() -> new IllegalArgumentException(QUEST_NOT_FOUND + questIdStr)); + .orElseThrow(() -> new AppException(QUEST_NOT_FOUND + questIdStr)); req.setAttribute(QUEST, quest); questService.delete(quest); LOGGER.info("Quest with ID {} successfully deleted", questIdStr); diff --git a/src/main/java/com/javarush/vasileva/cmd/UserList.java b/src/main/java/com/javarush/vasileva/cmd/UserList.java index cb705b7..bc692eb 100644 --- a/src/main/java/com/javarush/vasileva/cmd/UserList.java +++ b/src/main/java/com/javarush/vasileva/cmd/UserList.java @@ -3,8 +3,8 @@ import com.javarush.vasileva.entity.Role; import com.javarush.vasileva.entity.User; import com.javarush.vasileva.exception.AppException; +import com.javarush.vasileva.service.AuthService; import com.javarush.vasileva.service.UserService; -import com.javarush.vasileva.util.Helpers; import jakarta.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,16 +20,18 @@ public class UserList implements Command { private static final Logger LOGGER = LoggerFactory.getLogger(UserList.class.getName()); private final UserService userService; + private final AuthService authService; - public UserList(UserService userService) { + public UserList(UserService userService, AuthService authService) { this.userService = userService; + this.authService = authService; } @Override public String doGet(HttpServletRequest request) { LOGGER.info("Received GET request to view user list"); - Helpers.checkAdminAuthorization(request, USER_LIST_AUTH_ERROR); + authService.checkAdminAuthorization(request, USER_LIST_AUTH_ERROR); LOGGER.debug("Admin authorization successful"); Collection users = userService.getAll(); diff --git a/src/main/java/com/javarush/vasileva/service/AuthService.java b/src/main/java/com/javarush/vasileva/service/AuthService.java new file mode 100644 index 0000000..2bae593 --- /dev/null +++ b/src/main/java/com/javarush/vasileva/service/AuthService.java @@ -0,0 +1,20 @@ +package com.javarush.vasileva.service; + +import com.javarush.vasileva.entity.Role; +import com.javarush.vasileva.entity.User; +import com.javarush.vasileva.exception.AppException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpSession; + +import static com.javarush.vasileva.util.Key.USER; + +public class AuthService { + + public void checkAdminAuthorization(HttpServletRequest req, String message) { + HttpSession session = req.getSession(false); + User user = (User) session.getAttribute(USER); + if (user == null || user.getRole() == Role.GUEST || user.getRole() == Role.USER) { + throw new AppException(message); + } + } +} diff --git a/src/main/java/com/javarush/vasileva/service/UserService.java b/src/main/java/com/javarush/vasileva/service/UserService.java index 59045fe..43d3fa0 100644 --- a/src/main/java/com/javarush/vasileva/service/UserService.java +++ b/src/main/java/com/javarush/vasileva/service/UserService.java @@ -58,5 +58,4 @@ public Optional getValidatedUser(String userIdStr) { Long questId = Helpers.parseStringToLong(userIdStr); return findById(questId); } - } diff --git a/src/main/java/com/javarush/vasileva/util/Helpers.java b/src/main/java/com/javarush/vasileva/util/Helpers.java index 5ae129e..b2768de 100644 --- a/src/main/java/com/javarush/vasileva/util/Helpers.java +++ b/src/main/java/com/javarush/vasileva/util/Helpers.java @@ -1,26 +1,10 @@ package com.javarush.vasileva.util; -import com.javarush.vasileva.entity.Role; -import com.javarush.vasileva.entity.User; -import com.javarush.vasileva.exception.AppException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpSession; - -import static com.javarush.vasileva.util.Key.USER; - public class Helpers { private Helpers() { } - public static void checkAdminAuthorization(HttpServletRequest req, String message) { - HttpSession session = req.getSession(false); - User user = (User) session.getAttribute(USER); - if (user == null || user.getRole() == Role.GUEST || user.getRole() == Role.USER) { - throw new AppException(message); - } - } - public static Long parseStringToLong(String str) { try { return Long.parseLong(str); diff --git a/src/test/java/com/javarush/vasileva/BaseIT.java b/src/test/java/com/javarush/vasileva/BaseIT.java index 7e0efaa..ef63dd9 100644 --- a/src/test/java/com/javarush/vasileva/BaseIT.java +++ b/src/test/java/com/javarush/vasileva/BaseIT.java @@ -2,8 +2,7 @@ import com.javarush.vasileva.config.Config; import com.javarush.vasileva.config.Winter; -import com.javarush.vasileva.entity.Role; -import com.javarush.vasileva.entity.User; +import com.javarush.vasileva.entity.*; import jakarta.servlet.ServletConfig; import jakarta.servlet.ServletContext; import jakarta.servlet.http.HttpServletRequest; @@ -11,6 +10,8 @@ import jakarta.servlet.http.HttpSession; import org.mockito.Mockito; +import java.util.List; + import static org.mockito.Mockito.when; public class BaseIT { @@ -25,6 +26,15 @@ public class BaseIT { protected User testUser; protected User testGuest; + protected Quest testQuest; + + protected Question testQuestion1; + protected Question testQuestion2; + protected Question testQuestion3; + + protected Answer testAnswer1; + protected Answer testAnswer2; + public BaseIT() { config = Winter.find(Config.class); config.fillRepository(); @@ -61,7 +71,49 @@ public BaseIT() { .password("testGuest") .role(Role.GUEST) .build(); - } + testAnswer1 = Answer.builder() + .id(1L) + .questionId(1L) + .text("testAnswer1") + .nextQuestionLabel("+8") + .build(); + + testAnswer2 = Answer.builder() + .id(2L) + .questionId(1L) + .text("testAnswer2") + .nextQuestionLabel("-9") + .build(); + + testQuestion1 = Question.builder() + .generatedId(1L) + .questId(1L) + .label("1") + .text("testQuestion1") + .answers(List.of(testAnswer1, testAnswer2)) + .build(); + + testQuestion2 = Question.builder() + .generatedId(2L) + .label("+8") + .text("testQuestion2") + .build(); + + testQuestion3 = Question.builder() + .generatedId(3L) + .label("-9") + .text("testQuestion3") + .build(); + testQuest = Quest.builder() + .id(1L) + .title("testQuest1") + .description("testQuest1") + .text("testQuest1") + .startQuestionId(1L) + .questions(List.of(testQuestion1, testQuestion2, testQuestion3)) + .build(); + + } } diff --git a/src/test/java/com/javarush/vasileva/cmd/HomeIT.java b/src/test/java/com/javarush/vasileva/cmd/HomeIT.java new file mode 100644 index 0000000..9c8074d --- /dev/null +++ b/src/test/java/com/javarush/vasileva/cmd/HomeIT.java @@ -0,0 +1,99 @@ +package com.javarush.vasileva.cmd; + +import com.javarush.vasileva.BaseIT; +import com.javarush.vasileva.entity.Quest; +import com.javarush.vasileva.entity.Role; +import com.javarush.vasileva.exception.AppException; +import com.javarush.vasileva.service.AuthService; +import com.javarush.vasileva.service.QuestService; +import com.javarush.vasileva.util.Key; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import static com.javarush.vasileva.util.Key.QUEST_ID; +import static com.javarush.vasileva.util.Value.DELETE_QUEST_AUTH_ERROR; +import static com.javarush.vasileva.util.Value.QUEST_NOT_FOUND; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class HomeIT extends BaseIT { + + private final QuestService questService = mock(QuestService.class); + private final AuthService authService = mock(AuthService.class); + + private final Home home = new Home(questService, authService); + + @Test + @DisplayName("When GET request then retrieve all quests and set attribute") + void whenGetRequest_ThenRetrieveAllQuestsAndSetAttribute() { + List quests = Collections.singletonList(testQuest); + + when(questService.getAll()).thenReturn(quests); + + String view = home.doGet(req); + + assertEquals(home.getView(), view); + verify(req).setAttribute(Key.QUESTS, quests); + verify(questService).getAll(); + } + + @Test + @DisplayName("When DELETE request and admin authorized then delete quest and return view") + void whenDeleteRequestAndAdminAuthorized_ThenDeleteQuestAndReturnView() { + String questIdStr = String.valueOf(testQuest.getId()); + when(req.getParameter(QUEST_ID)).thenReturn(questIdStr); + when(questService.getValidatedQuest(questIdStr)).thenReturn(Optional.of(testQuest)); + when(session.getAttribute("role")).thenReturn(Role.ADMIN); + + doNothing().when(authService).checkAdminAuthorization(req, DELETE_QUEST_AUTH_ERROR); + + String view = home.doDelete(req); + + assertEquals(home.getView(), view); + verify(authService).checkAdminAuthorization(req, DELETE_QUEST_AUTH_ERROR); + verify(questService).getValidatedQuest(questIdStr); + verify(questService).delete(testQuest); + verify(req).setAttribute(Key.QUEST, testQuest); + } + + @Test + @DisplayName("When DELETE request but quest not found then throw IllegalArgumentException") + void whenDeleteRequestButQuestNotFound_ThenThrowIllegalArgumentException() { + String questIdStr = "999"; + when(req.getParameter(QUEST_ID)).thenReturn(questIdStr); + when(questService.getValidatedQuest(questIdStr)).thenReturn(Optional.empty()); + + doNothing().when(authService).checkAdminAuthorization(req, DELETE_QUEST_AUTH_ERROR); + + AppException exception = assertThrows(AppException.class, () -> home.doDelete(req)); + + assertTrue(exception.getMessage().contains(QUEST_NOT_FOUND + questIdStr)); + verify(authService).checkAdminAuthorization(req, DELETE_QUEST_AUTH_ERROR); + verify(questService).getValidatedQuest(questIdStr); + verifyNoMoreInteractions(questService); + } + + @Test + @DisplayName("When DELETE request but unauthorized then throw AppException") + void whenDeleteRequestButUnauthorized_ThenThrowAppException() { + String questIdStr = String.valueOf(testQuest.getId()); + when(req.getParameter(QUEST_ID)).thenReturn(questIdStr); + + doThrow(new AppException(DELETE_QUEST_AUTH_ERROR)) + .when(authService) + .checkAdminAuthorization(req, DELETE_QUEST_AUTH_ERROR); + + AppException exception = assertThrows(AppException.class, () -> home.doDelete(req)); + + assertEquals(DELETE_QUEST_AUTH_ERROR, exception.getMessage()); + verify(authService).checkAdminAuthorization(req, DELETE_QUEST_AUTH_ERROR); + verifyNoInteractions(questService); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/vasileva/cmd/RegisterIT.java b/src/test/java/com/javarush/vasileva/cmd/RegisterIT.java new file mode 100644 index 0000000..12a8daa --- /dev/null +++ b/src/test/java/com/javarush/vasileva/cmd/RegisterIT.java @@ -0,0 +1,116 @@ +package com.javarush.vasileva.cmd; + +import com.javarush.vasileva.BaseIT; +import com.javarush.vasileva.exception.AppException; +import com.javarush.vasileva.service.UserService; +import com.javarush.vasileva.util.Key; +import com.javarush.vasileva.util.Link; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static com.javarush.vasileva.util.Value.EMPTY_DATA_ERROR; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +public class RegisterIT extends BaseIT { + + private final UserService userService = mock(UserService.class); + + private final Register register = new Register(userService); + + @Test + @DisplayName("when valid data then register user and redirect to login") + void whenValidData_ThenRegisterUserAndRedirectToLogin() { + + when(req.getParameter(com.javarush.vasileva.util.Key.LOGIN)).thenReturn(testGuest.getLogin()); + when(req.getParameter(Key.EMAIL)).thenReturn(testGuest.getEmail()); + when(req.getParameter(Key.PASSWORD)).thenReturn(testGuest.getPassword()); + + String redirect = register.doPost(req); + + assertEquals(Link.LOGIN, redirect); + verify(userService).register(testGuest.getLogin(), testGuest.getEmail(), testGuest.getPassword()); + } + + @Test + @DisplayName("when empty login then throw AppException") + void whenEmptyLogin_ThenThrowAppException() { + String emptyLogin = ""; + when(req.getParameter(Key.LOGIN)).thenReturn(emptyLogin); + when(req.getParameter(Key.EMAIL)).thenReturn(testGuest.getEmail()); + when(req.getParameter(Key.PASSWORD)).thenReturn(testGuest.getPassword()); + + AppException exception = assertThrows(AppException.class, () -> register.doPost(req)); + + assertEquals(EMPTY_DATA_ERROR, exception.getMessage()); + verifyNoInteractions(userService); + } + + @Test + @DisplayName("when empty email then throw AppException") + void whenEmptyEmailThenThrowAppException() { + String emptyEmail = ""; + when(req.getParameter(Key.LOGIN)).thenReturn(testGuest.getLogin()); + when(req.getParameter(Key.EMAIL)).thenReturn(emptyEmail); + when(req.getParameter(Key.PASSWORD)).thenReturn(testGuest.getPassword()); + + AppException exception = assertThrows(AppException.class, () -> register.doPost(req)); + + assertEquals(EMPTY_DATA_ERROR, exception.getMessage()); + verifyNoInteractions(userService); + } + + @Test + @DisplayName("when empty password then throw AppException") + void whenEmptyPasswordThenThrowAppException() { + String emptyPassword = ""; + when(req.getParameter(Key.LOGIN)).thenReturn(testGuest.getLogin()); + when(req.getParameter(Key.EMAIL)).thenReturn(testGuest.getEmail()); + when(req.getParameter(Key.PASSWORD)).thenReturn(emptyPassword); + + AppException exception = assertThrows(AppException.class, () -> register.doPost(req)); + + assertEquals(EMPTY_DATA_ERROR, exception.getMessage()); + verifyNoInteractions(userService); + } + + @Test + @DisplayName("when null login then throw AppException") + void whenNullLogin_ThenThrowAppException() { + when(req.getParameter(Key.LOGIN)).thenReturn(null); + when(req.getParameter(Key.EMAIL)).thenReturn(testGuest.getEmail()); + when(req.getParameter(Key.PASSWORD)).thenReturn(testGuest.getPassword()); + + AppException exception = assertThrows(AppException.class, () -> register.doPost(req)); + + assertEquals(EMPTY_DATA_ERROR, exception.getMessage()); + verifyNoInteractions(userService); + } + + @Test + @DisplayName("when null email then throw AppException") + void whenNullEmail_ThenThrowAppException() { + when(req.getParameter(Key.LOGIN)).thenReturn(testGuest.getLogin()); + when(req.getParameter(Key.EMAIL)).thenReturn(null); + when(req.getParameter(Key.PASSWORD)).thenReturn(testGuest.getPassword()); + + AppException exception = assertThrows(AppException.class, () -> register.doPost(req)); + + assertEquals(EMPTY_DATA_ERROR, exception.getMessage()); + verifyNoInteractions(userService); + } + + @Test + @DisplayName("when null password then throw AppException") + void whenNullPasswordThenThrowAppException() { + when(req.getParameter(Key.LOGIN)).thenReturn(testGuest.getLogin()); + when(req.getParameter(Key.EMAIL)).thenReturn(testGuest.getEmail()); + when(req.getParameter(Key.PASSWORD)).thenReturn(null); + + AppException exception = assertThrows(AppException.class, () -> register.doPost(req)); + + assertEquals(EMPTY_DATA_ERROR, exception.getMessage()); + verifyNoInteractions(userService); + } +} From 69e14e58db0c2658213df8bf714699a23d411ce2 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Tue, 3 Feb 2026 23:12:31 +0500 Subject: [PATCH 54/65] ADD integration tests for PlayGame --- .../javarush/vasileva/entity/GameState.java | 2 + .../java/com/javarush/vasileva/BaseIT.java | 19 +++ .../com/javarush/vasileva/cmd/PlayGameIT.java | 116 ++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 src/test/java/com/javarush/vasileva/cmd/PlayGameIT.java diff --git a/src/main/java/com/javarush/vasileva/entity/GameState.java b/src/main/java/com/javarush/vasileva/entity/GameState.java index 4b9309f..4dc3605 100644 --- a/src/main/java/com/javarush/vasileva/entity/GameState.java +++ b/src/main/java/com/javarush/vasileva/entity/GameState.java @@ -1,12 +1,14 @@ package com.javarush.vasileva.entity; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor +@Builder public class GameState { private Quest currentQuest; private Question currentQuestion; diff --git a/src/test/java/com/javarush/vasileva/BaseIT.java b/src/test/java/com/javarush/vasileva/BaseIT.java index ef63dd9..c2b3505 100644 --- a/src/test/java/com/javarush/vasileva/BaseIT.java +++ b/src/test/java/com/javarush/vasileva/BaseIT.java @@ -26,6 +26,9 @@ public class BaseIT { protected User testUser; protected User testGuest; + protected Game testGame; + protected GameState testGameState; + protected Quest testQuest; protected Question testQuestion1; @@ -115,5 +118,21 @@ public BaseIT() { .questions(List.of(testQuestion1, testQuestion2, testQuestion3)) .build(); + testGameState = GameState.builder() + .currentQuest(testQuest) + .currentQuestion(testQuestion1) + .user(testUser) + .isCompleted(false) + .build(); + + testGame = Game.builder() + .id(1L) + .questId(testQuest.getId()) + .userId(testUser.getId()) + .currentQuestionId(testQuestion1.getGeneratedId()) + .gameState(testGameState) + .build(); + + } } diff --git a/src/test/java/com/javarush/vasileva/cmd/PlayGameIT.java b/src/test/java/com/javarush/vasileva/cmd/PlayGameIT.java new file mode 100644 index 0000000..36f1f1a --- /dev/null +++ b/src/test/java/com/javarush/vasileva/cmd/PlayGameIT.java @@ -0,0 +1,116 @@ +package com.javarush.vasileva.cmd; + +import com.javarush.vasileva.BaseIT; +import com.javarush.vasileva.exception.AppException; +import com.javarush.vasileva.service.GameService; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Optional; + +import static com.javarush.vasileva.util.Key.*; +import static com.javarush.vasileva.util.Value.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +public class PlayGameIT extends BaseIT { + + private final GameService gameService = mock(GameService.class); + + private final PlayGame playGame = new PlayGame(gameService); + + @Test + @DisplayName("When GET request with new game then start new game and set attributes") + void whenGetRequestWithNewGame_ThenStartNewGameAndSetAttributes() { + Long questId = testQuest.getId(); + + when(req.getParameter(QUEST_ID)).thenReturn(String.valueOf(questId)); + when(req.getParameter(GAME_ID)).thenReturn(null); + + when(session.getAttribute(USER)).thenReturn(testUser); + when(gameService.startNewGame(questId, testUser.getId())).thenReturn(testGame); + + String view = playGame.doGet(req); + + assertEquals(playGame.getView(), view); + + verify(req).setAttribute(GAME, testGame); + verify(req).setAttribute(STATE, testGame.getGameState().isCompleted()); + verify(req).setAttribute(QUEST, testGame.getGameState().getCurrentQuest()); + verify(req).setAttribute(WINNING, + testGame.getGameState().getCurrentQuestion().getLabel().contains(WIN)); + + verify(gameService).startNewGame(questId, testUser.getId()); + } + + @Test + @DisplayName("When GET request with existing game then retrieve game and set attributes") + void whenGetRequestWithExistingGame_ThenRetrieveGameAndSetAttributes() { + when(req.getParameter(QUEST_ID)).thenReturn(String.valueOf(testQuest.getId())); + when(req.getParameter(GAME_ID)).thenReturn(String.valueOf(testGame.getId())); + + when(session.getAttribute(USER)).thenReturn(testUser); + when(gameService.getGameById(testGame.getId())).thenReturn(Optional.of(testGame)); + + String view = playGame.doGet(req); + + assertEquals(playGame.getView(), view); + verify(req).setAttribute(GAME, testGame); + verify(req).setAttribute(STATE, testGame.getGameState().isCompleted()); + verify(req).setAttribute(QUEST, testGame.getGameState().getCurrentQuest()); + verify(req).setAttribute(WINNING, + testGame.getGameState().getCurrentQuestion().getLabel().contains(WIN)); + verify(gameService).getGameById(testGame.getId()); + } + + @Test + @DisplayName("When GET request but user not authenticated then throw AppException") + void whenGetRequestButUserNotAuthenticated_ThenThrowAppException() { + when(req.getParameter(QUEST_ID)).thenReturn(String.valueOf(testQuest.getId())); + when(req.getParameter(GAME_ID)).thenReturn(null); + + when(session.getAttribute(USER)).thenReturn(null); + + AppException exception = assertThrows(AppException.class, () -> playGame.doGet(req)); + + assertEquals(AUTH_ERROR, exception.getMessage()); + verify(gameService, never()).startNewGame(anyLong(), anyLong()); + verify(gameService, never()).getGameById(anyLong()); + } + + @Test + @DisplayName("When GET request but game not found then throw AppException") + void whenGetRequestButGameNotFound_ThenThrowAppException() { + Long gameId = 999L; + when(req.getParameter(QUEST_ID)).thenReturn(String.valueOf(testQuest.getId())); + when(req.getParameter(GAME_ID)).thenReturn(String.valueOf(gameId)); + + when(session.getAttribute(USER)).thenReturn(testUser); + when(gameService.getGameById(gameId)).thenReturn(Optional.empty()); + + AppException exception = assertThrows(AppException.class, () -> playGame.doGet(req)); + + assertEquals(GAME_NOT_FOUND, exception.getMessage()); + verify(gameService).getGameById(gameId); + } + + @Test + @DisplayName("When POST request then advance game and return redirect URL") + void whenPostRequest_ThenAdvanceGameAndReturnRedirectUrl() throws AppException { + when(req.getParameter(GAME_ID)).thenReturn(String.valueOf(testGame.getId())); + when(req.getParameter(SELECTED_ANSWER_ID)).thenReturn(String.valueOf(testAnswer1.getId())); + + when(session.getAttribute(USER)).thenReturn(testUser); + when(gameService.advanceGame(testGame.getId(), testAnswer1.getId())).thenReturn(testGame); + + String redirectUrl = playGame.doPost(req); + String expectedUrl = playGame.getView() + "?" + GAME_ID + "=" + testGame.getId() + + "&" + QUEST_ID + "=" + testGame.getGameState().getCurrentQuest().getId(); + + assertEquals(expectedUrl, redirectUrl); + verify(req).setAttribute(GAME, testGame); + verify(req).setAttribute(USER, testUser); + verify(gameService).advanceGame(testGame.getId(), testAnswer1.getId()); + } +} From 4985c6637fbd45cc40dfd6461f5464b5c6c60c39 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Tue, 3 Feb 2026 23:38:33 +0500 Subject: [PATCH 55/65] ADD integration tests for EditUser --- .../com/javarush/vasileva/cmd/EditUser.java | 13 +- .../java/com/javarush/vasileva/util/Key.java | 3 + .../com/javarush/vasileva/cmd/EditUserIT.java | 116 ++++++++++++++++++ 3 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 src/test/java/com/javarush/vasileva/cmd/EditUserIT.java diff --git a/src/main/java/com/javarush/vasileva/cmd/EditUser.java b/src/main/java/com/javarush/vasileva/cmd/EditUser.java index f2de5d7..394c4a2 100644 --- a/src/main/java/com/javarush/vasileva/cmd/EditUser.java +++ b/src/main/java/com/javarush/vasileva/cmd/EditUser.java @@ -3,6 +3,7 @@ import com.javarush.vasileva.entity.Role; import com.javarush.vasileva.entity.User; import com.javarush.vasileva.service.UserService; +import com.javarush.vasileva.util.Key; import com.javarush.vasileva.util.Link; import com.javarush.vasileva.util.Helpers; import jakarta.servlet.http.HttpServletRequest; @@ -46,19 +47,19 @@ public String doPost(HttpServletRequest req) { LOGGER.info("Received POST request to process user data"); User user = User.builder() - .login(req.getParameter("login")) - .email(req.getParameter("email")) - .password(req.getParameter("password")) - .role(Role.valueOf(req.getParameter("role"))) + .login(req.getParameter(Key.LOGIN)) + .email(req.getParameter(Key.EMAIL)) + .password(req.getParameter(Key.PASSWORD)) + .role(Role.valueOf(req.getParameter(Key.ROLE))) .build(); LOGGER.debug("Constructed user object: login={}, email={}, role={}", user.getLogin(), user.getEmail(), user.getRole()); - if (req.getParameter("create") != null) { + if (req.getParameter(Key.CREATE) != null) { LOGGER.info("Creating new user with login: {}", user.getLogin()); userService.create(user); - } else if (req.getParameter("update") != null) { + } else if (req.getParameter(Key.UPDATE) != null) { user.setId(Helpers.parseStringToLong(req.getParameter("id"))); LOGGER.info("Updating user with id: {}, login: {}", user.getId(), user.getLogin()); userService.update(user); diff --git a/src/main/java/com/javarush/vasileva/util/Key.java b/src/main/java/com/javarush/vasileva/util/Key.java index 35a6d53..640cd73 100644 --- a/src/main/java/com/javarush/vasileva/util/Key.java +++ b/src/main/java/com/javarush/vasileva/util/Key.java @@ -6,6 +6,7 @@ public class Key { public static final String LOGIN = "login"; public static final String EMAIL = "email"; public static final String PASSWORD = "password"; + public static final String ROLE = "role"; public static final String QUESTS = "quests"; public static final String QUEST_ID = "questId"; public static final String QUEST = "quest"; @@ -17,6 +18,8 @@ public class Key { public static final String STATE = "state"; public static final String STATS = "stats"; public static final String WINNING = "winning"; + public static final String CREATE = "create"; + public static final String UPDATE = "update"; public static final String ERROR = "error"; diff --git a/src/test/java/com/javarush/vasileva/cmd/EditUserIT.java b/src/test/java/com/javarush/vasileva/cmd/EditUserIT.java new file mode 100644 index 0000000..0291d02 --- /dev/null +++ b/src/test/java/com/javarush/vasileva/cmd/EditUserIT.java @@ -0,0 +1,116 @@ +package com.javarush.vasileva.cmd; + +import com.javarush.vasileva.BaseIT; +import com.javarush.vasileva.entity.Role; +import com.javarush.vasileva.entity.User; +import com.javarush.vasileva.service.UserService; +import com.javarush.vasileva.util.Key; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.util.Optional; + +import static com.javarush.vasileva.util.Link.USER_LIST; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.*; + +public class EditUserIT extends BaseIT { + + private final UserService userService = mock(UserService.class); + + private final EditUser editUser = new EditUser(userService); + + @Test + @DisplayName("When GET request with existing user then set user attribute") + void whenGetRequestWithExistingUser_ThenSetUserAttribute() { + String userIdStr = String.valueOf(testUser.getId()); + when(req.getParameter(Key.USER_ID)).thenReturn(userIdStr); + when(userService.getValidatedUser(userIdStr)).thenReturn(Optional.of(testUser)); + + String view = editUser.doGet(req); + + assertEquals(editUser.getView(), view); + verify(req).setAttribute(Key.USER, testUser); + verify(userService).getValidatedUser(userIdStr); + } + + @Test + @DisplayName("When GET request but user not found then do not set attribute") + void whenGetRequestButUserNotFound_ThenDoNotSetAttribute() { + String userIdStr = "999"; + when(req.getParameter(Key.USER_ID)).thenReturn(userIdStr); + when(userService.getValidatedUser(userIdStr)).thenReturn(Optional.empty()); + + String view = editUser.doGet(req); + + assertEquals(editUser.getView(), view); + verify(req, never()).setAttribute(eq(Key.USER), any()); + verify(userService).getValidatedUser(userIdStr); + } + + @Test + @DisplayName("When POST request to create user then call create and redirect") + void whenPostRequestToCreateUser_ThenCallCreateAndRedirect() { + when(req.getParameter(Key.CREATE)).thenReturn("true"); + when(req.getParameter(Key.LOGIN)).thenReturn(testUser.getLogin()); + when(req.getParameter(Key.EMAIL)).thenReturn(testUser.getEmail()); + when(req.getParameter(Key.PASSWORD)).thenReturn(testUser.getPassword()); + when(req.getParameter(Key.ROLE)).thenReturn(Role.USER.toString()); + + String redirect = editUser.doPost(req); + + assertEquals(USER_LIST, redirect); + + ArgumentCaptor userCaptor = ArgumentCaptor.forClass(User.class); + verify(userService).create(userCaptor.capture()); + + User createdUser = userCaptor.getValue(); + assertEquals(testUser.getLogin(), createdUser.getLogin()); + assertEquals(testUser.getEmail(), createdUser.getEmail()); + assertEquals(testUser.getPassword(), createdUser.getPassword()); + assertEquals(testUser.getRole(), createdUser.getRole()); + assertNull(createdUser.getId()); + } + + @Test + @DisplayName("When POST request to update user then call update and redirect") + void whenPostRequestToUpdateUser_ThenCallUpdateAndRedirect() { + when(req.getParameter(Key.UPDATE)).thenReturn("true"); + when(req.getParameter(Key.USER_ID)).thenReturn(String.valueOf(testUser.getId())); + when(req.getParameter(Key.LOGIN)).thenReturn(testUser.getLogin()); + when(req.getParameter(Key.EMAIL)).thenReturn(testUser.getEmail()); + when(req.getParameter(Key.PASSWORD)).thenReturn(testUser.getPassword()); + when(req.getParameter(Key.ROLE)).thenReturn(Role.USER.toString()); + + String redirect = editUser.doPost(req); + + assertEquals(USER_LIST, redirect); + + ArgumentCaptor userCaptor = ArgumentCaptor.forClass(User.class); + verify(userService).update(userCaptor.capture()); + + User updatedUser = userCaptor.getValue(); + assertEquals(testUser.getId(), updatedUser.getId()); + assertEquals(testUser.getLogin(), updatedUser.getLogin()); + assertEquals(testUser.getEmail(), updatedUser.getEmail()); + assertEquals(testUser.getPassword(), updatedUser.getPassword()); + assertEquals(Role.USER, updatedUser.getRole()); + } + + @Test + @DisplayName("When POST request without create/update params then do nothing and redirect") + void whenPostRequestWithoutCreateOrUpdate_ThenDoNothingAndRedirect() { + when(req.getParameter(Key.CREATE)).thenReturn(null); + when(req.getParameter(Key.UPDATE)).thenReturn(null); + when(req.getParameter(Key.ROLE)).thenReturn(Role.USER.toString()); + + String redirect = editUser.doPost(req); + + assertEquals(USER_LIST, redirect); + verify(userService, never()).create(any()); + verify(userService, never()).update(any()); + } + +} From 94d3194ddebb1c0beb528c5a1221c46b27d03aa9 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Wed, 4 Feb 2026 00:07:34 +0500 Subject: [PATCH 56/65] ADD integration tests for UserList --- .../com/javarush/vasileva/cmd/UserList.java | 5 +- .../java/com/javarush/vasileva/util/Key.java | 1 + src/main/webapp/WEB-INF/user-list.jsp | 114 +++++++++--------- .../com/javarush/vasileva/cmd/UserListIT.java | 99 +++++++++++++++ 4 files changed, 156 insertions(+), 63 deletions(-) create mode 100644 src/test/java/com/javarush/vasileva/cmd/UserListIT.java diff --git a/src/main/java/com/javarush/vasileva/cmd/UserList.java b/src/main/java/com/javarush/vasileva/cmd/UserList.java index bc692eb..1a6906b 100644 --- a/src/main/java/com/javarush/vasileva/cmd/UserList.java +++ b/src/main/java/com/javarush/vasileva/cmd/UserList.java @@ -1,6 +1,5 @@ package com.javarush.vasileva.cmd; -import com.javarush.vasileva.entity.Role; import com.javarush.vasileva.entity.User; import com.javarush.vasileva.exception.AppException; import com.javarush.vasileva.service.AuthService; @@ -37,8 +36,7 @@ public String doGet(HttpServletRequest request) { Collection users = userService.getAll(); LOGGER.info("Retrieved {} users from database", users.size()); - request.setAttribute("users", users); - request.getSession().setAttribute("ADMIN_ROLE", Role.ADMIN); + request.setAttribute(USERS, users); LOGGER.debug("Users and admin role set in request attributes"); return getView(); @@ -55,7 +53,6 @@ public String doDelete(HttpServletRequest req) { .orElseThrow(() -> new AppException(USER_NOT_FOUND + userIdStr)); LOGGER.info("User found for deletion: id={}, login={}", user.getId(), user.getLogin()); - req.setAttribute(USER, user); userService.delete(user); LOGGER.info("User with ID {} successfully deleted", user.getId()); diff --git a/src/main/java/com/javarush/vasileva/util/Key.java b/src/main/java/com/javarush/vasileva/util/Key.java index 640cd73..a9fdf99 100644 --- a/src/main/java/com/javarush/vasileva/util/Key.java +++ b/src/main/java/com/javarush/vasileva/util/Key.java @@ -3,6 +3,7 @@ public class Key { public static final String USER_ID = "id"; public static final String USER = "user"; + public static final String USERS = "users"; public static final String LOGIN = "login"; public static final String EMAIL = "email"; public static final String PASSWORD = "password"; diff --git a/src/main/webapp/WEB-INF/user-list.jsp b/src/main/webapp/WEB-INF/user-list.jsp index 3dab8f5..b687644 100644 --- a/src/main/webapp/WEB-INF/user-list.jsp +++ b/src/main/webapp/WEB-INF/user-list.jsp @@ -1,69 +1,65 @@ - <%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" %> - <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> - <%@include file="header.jsp" %> +<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@include file="header.jsp" %> - - - + + + - + - - - - + + + + -
-

Список пользователей

+
+

Список пользователей

- - - - - - - - - - +
IDИмяEmailРольДействия
+ + + + + + + + + - - - - - - - - + + + + + + + - - - -
IDИмяEmailРольДействия
${user.id}${user.login}${user.email}${user.role} - - Редактировать - +
${user.id}${user.login}${user.email}${user.role} + + Редактировать + - -
- - - -
-
-
+
+ + + +
+ + + + + - - - Добавить пользователя - - -
- + + Добавить пользователя + +
+ diff --git a/src/test/java/com/javarush/vasileva/cmd/UserListIT.java b/src/test/java/com/javarush/vasileva/cmd/UserListIT.java new file mode 100644 index 0000000..10064e7 --- /dev/null +++ b/src/test/java/com/javarush/vasileva/cmd/UserListIT.java @@ -0,0 +1,99 @@ +package com.javarush.vasileva.cmd; + +import com.javarush.vasileva.BaseIT; +import com.javarush.vasileva.entity.User; +import com.javarush.vasileva.exception.AppException; +import com.javarush.vasileva.service.AuthService; +import com.javarush.vasileva.service.UserService; +import com.javarush.vasileva.util.Key; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +import static com.javarush.vasileva.util.Key.USER_ID; +import static com.javarush.vasileva.util.Value.USER_LIST_AUTH_ERROR; +import static com.javarush.vasileva.util.Value.USER_NOT_FOUND; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +public class UserListIT extends BaseIT { + + private final UserService userService = mock(UserService.class); + private final AuthService authService = mock(AuthService.class); + + private final UserList userList = new UserList(userService, authService); + + @Test + @DisplayName("When GET request and admin authorized then retrieve users and set attributes") + void whenGetRequestAndAdminAuthorized_ThenRetrieveUsersAndSetAttributes() { + List users = Arrays.asList(testAdmin, testUser, testGuest); + when(userService.getAll()).thenReturn(users); + + doNothing().when(authService).checkAdminAuthorization(req, USER_LIST_AUTH_ERROR); + + String view = userList.doGet(req); + assertEquals(userList.getView(), view); + verify(authService).checkAdminAuthorization(req, USER_LIST_AUTH_ERROR); + verify(userService).getAll(); + verify(req).setAttribute(Key.USERS, users); + } + + @Test + @DisplayName("When GET request but unauthorized then throw AppException") + void whenGetRequestButUnauthorized_ThenThrowAppException() { + doThrow(new AppException(USER_LIST_AUTH_ERROR)) + .when(authService) + .checkAdminAuthorization(req, USER_LIST_AUTH_ERROR); + + AppException exception = assertThrows(AppException.class, () -> userList.doGet(req)); + + assertEquals(USER_LIST_AUTH_ERROR, exception.getMessage()); + verify(authService).checkAdminAuthorization(req, USER_LIST_AUTH_ERROR); + verifyNoInteractions(userService); + } + + @Test + @DisplayName("When DELETE request and user exists then delete user and return view") + void whenDeleteRequestAndUserExistsThenDeleteUserAndReturnView() { + String userIdStr = String.valueOf(testUser.getId()); + + when(req.getParameter(USER_ID)).thenReturn(userIdStr); + when(userService.getValidatedUser(userIdStr)).thenReturn(Optional.of(testUser)); + + String view = userList.doDelete(req); + + assertEquals(userList.getView(), view); + + verify(userService).getValidatedUser(userIdStr); + verify(userService).delete(testUser); + } + + @Test + @DisplayName("When DELETE request but user not found then throw AppException") + void whenDeleteRequestButUserNotFound_ThenThrowAppException() { + String userIdStr = "999"; + when(req.getParameter(USER_ID)).thenReturn(userIdStr); + when(userService.getValidatedUser(userIdStr)).thenReturn(Optional.empty()); + + AppException exception = assertThrows(AppException.class, () -> userList.doDelete(req)); + + assertEquals(USER_NOT_FOUND + userIdStr, exception.getMessage()); + + verify(userService).getValidatedUser(userIdStr); + verifyNoMoreInteractions(userService); + } + + @Test + @DisplayName("When DELETE request with null userId then throw AppException") + void whenDeleteRequestWithNullUserId_ThenThrowAppException() { + when(req.getParameter(USER_ID)).thenReturn(null); + AppException exception = assertThrows(AppException.class, () -> userList.doDelete(req)); + + assertTrue(exception.getMessage().startsWith(USER_NOT_FOUND)); + verify(userService).getValidatedUser(null); + verifyNoMoreInteractions(userService); + } +} From 4f54aa9bd5398cb2e54cdf1be16fa648cccca4f3 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Wed, 4 Feb 2026 14:20:05 +0500 Subject: [PATCH 57/65] ADD integration tests for EditQuest --- .../com/javarush/vasileva/cmd/EditQuest.java | 10 +- .../java/com/javarush/vasileva/BaseIT.java | 85 ++++++++- .../javarush/vasileva/cmd/EditQuestIT.java | 175 ++++++++++++++++++ 3 files changed, 263 insertions(+), 7 deletions(-) create mode 100644 src/test/java/com/javarush/vasileva/cmd/EditQuestIT.java diff --git a/src/main/java/com/javarush/vasileva/cmd/EditQuest.java b/src/main/java/com/javarush/vasileva/cmd/EditQuest.java index 559ab66..1d69dde 100644 --- a/src/main/java/com/javarush/vasileva/cmd/EditQuest.java +++ b/src/main/java/com/javarush/vasileva/cmd/EditQuest.java @@ -56,9 +56,6 @@ public String doGet(HttpServletRequest req) { req.setAttribute(QUEST_JSON, questJson); LOGGER.debug("Quest is mapped to JSON. ID: {}", quest.getId()); } catch (IOException e) { - LOGGER.error(QUEST_SERIALIZATION_ERROR + ". ID: {}. Cause: {}", - questIdStr, e.getMessage()); - req.getSession().setAttribute(ERROR, QUEST_SERIALIZATION_ERROR); return getView(); } } else { @@ -73,6 +70,13 @@ public String doGet(HttpServletRequest req) { public String doPost(HttpServletRequest req) { LOGGER.info("Processing POST-request for saving quest. Параметры: {}", req.getParameterMap()); String questJson = req.getParameter(QUEST_JSON); + + if (questJson == null || questJson.isEmpty()) { + LOGGER.error(JSON_SAVE_ERROR + ". JSON parameter is missing or empty"); + req.getSession().setAttribute(ERROR, JSON_SAVE_ERROR); + return getView(); + } + try { Quest quest = questMapper.fromJsonString(questJson); LOGGER.debug("Quest is successfully received from JSON. Title: {}", quest.getTitle()); diff --git a/src/test/java/com/javarush/vasileva/BaseIT.java b/src/test/java/com/javarush/vasileva/BaseIT.java index c2b3505..2217832 100644 --- a/src/test/java/com/javarush/vasileva/BaseIT.java +++ b/src/test/java/com/javarush/vasileva/BaseIT.java @@ -9,6 +9,7 @@ import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import org.mockito.Mockito; +import org.slf4j.Logger; import java.util.List; @@ -21,6 +22,7 @@ public class BaseIT { protected final Config config; protected final ServletConfig servletConfig; protected final ServletContext servletContext; + protected final Logger LOGGER; protected User testAdmin; protected User testUser; @@ -30,6 +32,7 @@ public class BaseIT { protected GameState testGameState; protected Quest testQuest; + protected Quest testQuestWithoutId; protected Question testQuestion1; protected Question testQuestion2; @@ -38,6 +41,9 @@ public class BaseIT { protected Answer testAnswer1; protected Answer testAnswer2; + protected String testJson; + protected String testJsonWithoutId; + public BaseIT() { config = Winter.find(Config.class); config.fillRepository(); @@ -51,6 +57,8 @@ public BaseIT() { session = Mockito.mock(HttpSession.class); when(req.getSession()).thenReturn(session); + LOGGER = Mockito.mock(Logger.class); + testAdmin = User.builder() .id(1L) .login("testAdmin") @@ -111,9 +119,17 @@ public BaseIT() { testQuest = Quest.builder() .id(1L) - .title("testQuest1") - .description("testQuest1") - .text("testQuest1") + .title("testQuest") + .description("testQuest") + .text("testQuest") + .startQuestionId(1L) + .questions(List.of(testQuestion1, testQuestion2, testQuestion3)) + .build(); + + testQuestWithoutId = Quest.builder() + .title("testQuest") + .description("testQuest") + .text("testQuest") .startQuestionId(1L) .questions(List.of(testQuestion1, testQuestion2, testQuestion3)) .build(); @@ -133,6 +149,67 @@ public BaseIT() { .gameState(testGameState) .build(); - + testJson = """ + { + "id": 1, + "title": "testQuest", + "description": "testQuest", + "text": "testQuest", + "questions": [ + { + "label": "1", + "text": "testQuestion1", + "answers": [ + { + "nextQuestionLabel": "+8", + "text": "testAnswer1" + }, + { + "nextQuestionLabel": "-9", + "text": "testAnswer2" + } + ] + }, + { + "label": "+8", + "text": "testQuestion2" + }, + { + "label": "-9", + "text": "testQuestion2" + } + ] + }"""; + + testJsonWithoutId = """ + { + "title": "testQuest", + "description": "testQuest", + "text": "testQuest", + "questions": [ + { + "label": "1", + "text": "testQuestion1", + "answers": [ + { + "nextQuestionLabel": "+8", + "text": "testAnswer1" + }, + { + "nextQuestionLabel": "-9", + "text": "testAnswer2" + } + ] + }, + { + "label": "+8", + "text": "testQuestion2" + }, + { + "label": "-9", + "text": "testQuestion2" + } + ] + }"""; } } diff --git a/src/test/java/com/javarush/vasileva/cmd/EditQuestIT.java b/src/test/java/com/javarush/vasileva/cmd/EditQuestIT.java new file mode 100644 index 0000000..87a8d4f --- /dev/null +++ b/src/test/java/com/javarush/vasileva/cmd/EditQuestIT.java @@ -0,0 +1,175 @@ +package com.javarush.vasileva.cmd; + +import com.javarush.vasileva.BaseIT; +import com.javarush.vasileva.entity.Quest; +import com.javarush.vasileva.exception.AppException; +import com.javarush.vasileva.mapper.QuestMapper; +import com.javarush.vasileva.service.AuthService; +import com.javarush.vasileva.service.QuestService; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import static com.javarush.vasileva.util.Key.*; +import static com.javarush.vasileva.util.Link.HOME; +import static com.javarush.vasileva.util.Value.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +public class EditQuestIT extends BaseIT { + + private final QuestService questService = mock(QuestService.class); + private final AuthService authService = mock(AuthService.class); + private final QuestMapper questMapper = mock(QuestMapper.class); + + private final EditQuest editQuest = new EditQuest(questService, authService, config); + + @Test + @DisplayName("when GET request admin authorized no questId then set edit false and default JSON") + void whenGetNoQuestId_ThenSetEditFalseAndDefaultJson() { + doNothing().when(authService).checkAdminAuthorization(req, EDIT_QUEST_AUTH_ERROR); + when(req.getParameter(QUEST_ID)).thenReturn(null); + when(questService.getAll()).thenReturn(Collections.singletonList(testQuest)); + + String view = editQuest.doGet(req); + + assertEquals(editQuest.getView(), view); + verify(authService).checkAdminAuthorization(req, EDIT_QUEST_AUTH_ERROR); + verify(req).setAttribute(eq(QUESTS), anyList()); + verify(req).setAttribute(eq(EDIT), eq(false)); + verify(req).setAttribute(eq(QUEST_JSON), eq(JSON_SAMPLE)); + } + + @Test + @DisplayName("when POST request with null JSON parameter then set error in session") + void whenPostNullJsonParameterThenSetErrorInSession() { + when(req.getParameter(QUEST_JSON)).thenReturn(null); + + String view = editQuest.doPost(req); + + assertEquals(editQuest.getView(), view); + verify(session).setAttribute(eq(ERROR), eq(JSON_SAVE_ERROR)); + verify(session, never()).setAttribute(eq(QUEST_JSON), any()); + + verifyNoInteractions(questMapper); + verifyNoInteractions(questService); + } + + @Test + @DisplayName("when JSON serialization fails in doGet then return view") + void whenJsonSerializationFailsInDoGet_ThenReturnViewAndLogError() throws Exception { + doNothing().when(authService).checkAdminAuthorization(req, EDIT_QUEST_AUTH_ERROR); + + when(req.getParameter(QUEST_ID)).thenReturn(String.valueOf(testQuest.getId())); + when(questService.getValidatedQuest(String.valueOf(testQuest.getId()))) + .thenReturn(Optional.of(testQuest)); + + when(questMapper.toJsonString(testQuest)) + .thenThrow(new IOException("Serialization failed")); + + String resultView = editQuest.doGet(req); + + assertEquals(editQuest.getView(), resultView); + verify(req).setAttribute(eq(EDIT), eq(true)); + assertNull(req.getAttribute(QUEST_JSON)); + assertThrows(IOException.class, () -> questMapper.toJsonString(testQuest)); + } + + @Test + @DisplayName("when GET request but quest not found then throw AppException") + void whenGetQuestNotFound_ThenThrowAppException() { + String questIdStr = "999"; + doNothing().when(authService).checkAdminAuthorization(req, EDIT_QUEST_AUTH_ERROR); + when(req.getParameter(QUEST_ID)).thenReturn(questIdStr); + when(questService.getValidatedQuest(questIdStr)).thenReturn(Optional.empty()); + + when(questService.getAll()).thenReturn(List.of()); + + AppException exception = assertThrows(AppException.class, () -> editQuest.doGet(req)); + + assertEquals(QUEST_NOT_FOUND + questIdStr, exception.getMessage()); + verify(questService).getValidatedQuest(questIdStr); + } + + @Test + @DisplayName("when GET request but serialization fails then set error in session") + void whenGetSerializationFails_ThenSetErrorInSession() throws Exception { + doNothing().when(authService).checkAdminAuthorization(req, EDIT_QUEST_AUTH_ERROR); + when(req.getParameter(QUEST_ID)).thenReturn(String.valueOf(testQuest.getId())); + when(questService.getValidatedQuest(String.valueOf(testQuest.getId()))) + .thenReturn(Optional.of(testQuest)); + when(questMapper.toJsonString(testQuest)).thenThrow(new IOException("Serialization failed")); + when(questService.getAll()).thenReturn(Collections.singletonList(testQuest)); + + String view = editQuest.doGet(req); + + assertEquals(editQuest.getView(), view); + } + + @Test + @DisplayName("when POST request and JSON valid then save quest and redirect to HOME") + void whenPostValidJson_ThenSaveQuestAndRedirect() throws Exception { + when(req.getParameter(QUEST_JSON)).thenReturn(testJsonWithoutId); + when(questMapper.fromJsonString(testJson)).thenReturn(testQuestWithoutId); + + String redirect = editQuest.doPost(req); + + assertEquals(HOME, redirect); + verify(questService).create(any(Quest.class)); + + ArgumentCaptor questCaptor = ArgumentCaptor.forClass(Quest.class); + verify(questService).create(questCaptor.capture()); + } + + @Test + @DisplayName("when POST request with existing quest ID then update quest") + void whenPostWithExistingId_ThenUpdateQuest() throws Exception { + when(req.getParameter(QUEST_JSON)).thenReturn(testJson); + when(questMapper.fromJsonString(testJson)).thenReturn(testQuest); + + String redirect = editQuest.doPost(req); + + assertEquals(HOME, redirect); + verify(questService).update(any(Quest.class)); + + ArgumentCaptor questCaptor = ArgumentCaptor.forClass(Quest.class); + verify(questService).update(questCaptor.capture()); + } + + @Test + @DisplayName("when POST request but JSON invalid then set error in session") + void whenPostInvalidJson_ThenSetErrorInSession() throws Exception { + String questJson = "invalid json"; + when(req.getParameter(QUEST_JSON)).thenReturn(questJson); + when(questMapper.fromJsonString(questJson)) + .thenThrow(new IOException("Parse failed")); + + String view = editQuest.doPost(req); + + assertEquals(editQuest.getView(), view); + + verify(session).setAttribute(eq(QUEST_JSON), eq(questJson)); + verify(session).setAttribute(eq(ERROR), eq(JSON_SAVE_ERROR)); + } + + + @Test + @DisplayName("When GET request but admin authorization fails then throw AppException") + void whenGetAdminAuthorizationFails_ThenThrowAppException() { + doThrow(new AppException(EDIT_QUEST_AUTH_ERROR)) + .when(authService) + .checkAdminAuthorization(req, EDIT_QUEST_AUTH_ERROR); + + AppException exception = assertThrows(AppException.class, () -> editQuest.doGet(req)); + + assertEquals(EDIT_QUEST_AUTH_ERROR, exception.getMessage()); + verify(authService).checkAdminAuthorization(req, EDIT_QUEST_AUTH_ERROR); + verifyNoInteractions(questService); + verifyNoInteractions(req); + } +} From 754add9bad972a9dfc271fedc965789123a48ee4 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Wed, 4 Feb 2026 14:40:10 +0500 Subject: [PATCH 58/65] ADD integration tests for Stats and Logout --- .../java/com/javarush/vasileva/BaseIT.java | 10 +++ .../com/javarush/vasileva/cmd/LogoutIT.java | 40 +++++++++++ .../com/javarush/vasileva/cmd/StatsIT.java | 68 +++++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 src/test/java/com/javarush/vasileva/cmd/LogoutIT.java create mode 100644 src/test/java/com/javarush/vasileva/cmd/StatsIT.java diff --git a/src/test/java/com/javarush/vasileva/BaseIT.java b/src/test/java/com/javarush/vasileva/BaseIT.java index 2217832..8dd5c21 100644 --- a/src/test/java/com/javarush/vasileva/BaseIT.java +++ b/src/test/java/com/javarush/vasileva/BaseIT.java @@ -44,6 +44,8 @@ public class BaseIT { protected String testJson; protected String testJsonWithoutId; + protected UserStats testUserStats; + public BaseIT() { config = Winter.find(Config.class); config.fillRepository(); @@ -211,5 +213,13 @@ public BaseIT() { } ] }"""; + + testUserStats = UserStats.builder() + .id(1L) + .userId(testUser.getId()) + .total(3) + .wins(2) + .losses(1) + .build(); } } diff --git a/src/test/java/com/javarush/vasileva/cmd/LogoutIT.java b/src/test/java/com/javarush/vasileva/cmd/LogoutIT.java new file mode 100644 index 0000000..018966b --- /dev/null +++ b/src/test/java/com/javarush/vasileva/cmd/LogoutIT.java @@ -0,0 +1,40 @@ +package com.javarush.vasileva.cmd; + +import com.javarush.vasileva.BaseIT; +import com.javarush.vasileva.util.Link; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static com.javarush.vasileva.util.Link.LOGIN; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +public class LogoutIT extends BaseIT { + + private final Logout logout = new Logout(); + + @Test + @DisplayName("when session exists then invalidate it and redirect to LOGIN") + void whenSessionExists_ThenInvalidateAndRedirect() { + when(req.getSession(false)).thenReturn(session); + when(session.getId()).thenReturn("test-session-id"); + + String redirect = logout.doGet(req); + + assertEquals(Link.LOGIN, redirect); + verify(req).getSession(false); + verify(session).invalidate(); + } + + @Test + @DisplayName("when no session exists then skip invalidation and redirect to LOGIN") + void whenNoSessionExists_ThenSkipInvalidationAndRedirect() { + when(req.getSession(false)).thenReturn(null); + + String redirect = logout.doGet(req); + + assertEquals(LOGIN, redirect); + verify(req).getSession(false); + verify(session, never()).invalidate(); + } +} diff --git a/src/test/java/com/javarush/vasileva/cmd/StatsIT.java b/src/test/java/com/javarush/vasileva/cmd/StatsIT.java new file mode 100644 index 0000000..6b35913 --- /dev/null +++ b/src/test/java/com/javarush/vasileva/cmd/StatsIT.java @@ -0,0 +1,68 @@ +package com.javarush.vasileva.cmd; + +import com.javarush.vasileva.BaseIT; +import com.javarush.vasileva.exception.AppException; +import com.javarush.vasileva.service.UserStatsService; +import com.javarush.vasileva.util.Key; +import com.javarush.vasileva.util.Value; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +public class StatsIT extends BaseIT { + + private final UserStatsService statsService = mock(UserStatsService.class); + + private final Stats stats = new Stats(statsService); + + @Test + @DisplayName("when user is authenticated then load stats and return view") + void whenUserAuthenticated_ThenLoadStatsAndReturnView() { + when(session.getAttribute(Key.USER)).thenReturn(testUser); + when(statsService.getUserStats(testUser.getId())).thenReturn(Optional.of(testUserStats)); + + String view = stats.doGet(req); + + assertEquals(stats.getView(), view); + + verify(req).getSession(); + verify(session).getAttribute(Key.USER); + verify(statsService).getUserStats(testUser.getId()); + verify(req).setAttribute(eq(Key.STATS), eq(testUserStats)); + } + + @Test + @DisplayName("when user not authenticated then throw AppException") + void whenUserNotAuthenticated_ThenThrowAppException() { + when(session.getAttribute(Key.USER)).thenReturn(null); + + AppException exception = assertThrows(AppException.class, () -> stats.doGet(req)); + + assertEquals(Value.AUTH_ERROR, exception.getMessage()); + verify(req).getSession(); + verify(session).getAttribute(Key.USER); + verify(statsService, never()).getUserStats(anyLong()); + } + + @Test + @DisplayName("when stats not found then throw AppException") + void whenStatsNotFound_ThenThrowAppException() { + when(session.getAttribute(Key.USER)).thenReturn(testUser); + when(statsService.getUserStats(testUser.getId())).thenReturn(Optional.empty()); + + AppException exception = assertThrows(AppException.class, () -> stats.doGet(req)); + + assertEquals(Value.STATS_NOT_FOUND, exception.getMessage()); + + verify(req).getSession(); + verify(session).getAttribute(Key.USER); + verify(statsService).getUserStats(testUser.getId()); + verify(req, never()).setAttribute(eq(Key.STATS), any()); + } + +} From d3cd7246108773e5d490566370210b502a29f681 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Wed, 4 Feb 2026 15:33:02 +0500 Subject: [PATCH 59/65] ADD test data for unit tests and unit tests for QuestService --- .../vasileva/service/QuestServiceTest.java | 138 ++++++++++++++++++ .../javarush/vasileva/service/TestData.java | 58 ++++++++ .../vasileva/service/UserServiceTest.java | 54 +++---- 3 files changed, 216 insertions(+), 34 deletions(-) create mode 100644 src/test/java/com/javarush/vasileva/service/QuestServiceTest.java create mode 100644 src/test/java/com/javarush/vasileva/service/TestData.java diff --git a/src/test/java/com/javarush/vasileva/service/QuestServiceTest.java b/src/test/java/com/javarush/vasileva/service/QuestServiceTest.java new file mode 100644 index 0000000..9dbd094 --- /dev/null +++ b/src/test/java/com/javarush/vasileva/service/QuestServiceTest.java @@ -0,0 +1,138 @@ +package com.javarush.vasileva.service; + +import com.javarush.vasileva.entity.Quest; +import com.javarush.vasileva.repository.QuestRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.Optional; + +import static com.javarush.vasileva.service.TestData.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class QuestServiceTest { + + @Mock + private QuestRepository questRepository; + + @InjectMocks + private QuestService questService; + + private Quest quest; + + @BeforeEach + public void setUp() { + quest = createValidQuest(); + } + + @Test + @DisplayName("when getAll() then return all quests from repository") + void whenGetAll_thenReturnAllQuestsFromRepository() { + List quests = createMultipleQuests(); + when(questRepository.getAll()).thenReturn(quests); + + List result = questService.getAll(); + + assertEquals(quests, result); + verify(questRepository).getAll(); + } + + @Test + @DisplayName("when findById() then return quest by ID") + void whenFindById_ThenFindById() { + long questId = quest.getId(); + when(questRepository.findById(questId)).thenReturn(Optional.of(quest)); + + Optional result = questService.findById(questId); + + assertTrue(result.isPresent()); + assertEquals(quest, result.get()); + verify(questRepository).findById(questId); + } + + @Test + @DisplayName("when findById() then return empty Optional if quest not found") + void whenFindById_ThenNotFound() { + long questId = NON_EXISTENT_QUEST_ID; + when(questRepository.findById(questId)).thenReturn(Optional.empty()); + + Optional result = questService.findById(questId); + + assertFalse(result.isPresent()); + verify(questRepository).findById(questId); + } + + @Test + @DisplayName("when create() then delegate to repository") + void testCreate() { + questService.create(quest); + verify(questRepository).create(quest); + } + + @Test + @DisplayName("when update() than delegate to repository") + void testUpdate() { + questService.update(quest); + verify(questRepository).update(quest); + } + + @Test + @DisplayName("when delete() then delegate to repository") + void testDelete() { + questService.delete(quest); + verify(questRepository).delete(quest); + } + + @Test + @DisplayName("when getValidatedQuest() then return empty when questIdStr is null") + void givenQuestIdNull_whenGetValidatedQuest_ThenReturnEmpty() { + Optional result = questService.getValidatedQuest(NULL_QUEST_ID_STR); + assertFalse(result.isPresent()); + verify(questRepository, never()).findById(anyLong()); + } + + @Test + @DisplayName("when getValidatedQuest() then return empty when questIdStr is empty") + void givenEmptyQuestId_WhenGetValidatedQuest_ThenReturnEmpty() { + Optional result = questService.getValidatedQuest(EMPTY_QUEST_ID_STR); + assertFalse(result.isPresent()); + verify(questRepository, never()).findById(anyLong()); + } + + @Test + @DisplayName("when getValidatedQuest() then parse string to long and find quest") + void whenGetValidatedQuest_ThenReturnQuest() { + String questIdStr = String.valueOf(quest.getId()); + long questId = Long.parseLong(questIdStr); + + when(questRepository.findById(questId)).thenReturn(Optional.of(quest)); + + Optional result = questService.getValidatedQuest(questIdStr); + + assertTrue(result.isPresent()); + assertEquals(quest, result.get()); + verify(questRepository).findById(questId); + } + + @Test + @DisplayName("when getValidatedQuest() then return empty if quest not found by parsed ID") + void whenGetValidatedQuest_thenQuestNotFound() { + String questIdStr = NON_EXISTENT_QUEST_ID_STR; + long questId = Long.parseLong(questIdStr); + + when(questRepository.findById(questId)).thenReturn(Optional.empty()); + + Optional result = questService.getValidatedQuest(questIdStr); + + assertFalse(result.isPresent()); + verify(questRepository).findById(questId); + } +} diff --git a/src/test/java/com/javarush/vasileva/service/TestData.java b/src/test/java/com/javarush/vasileva/service/TestData.java new file mode 100644 index 0000000..c911cfa --- /dev/null +++ b/src/test/java/com/javarush/vasileva/service/TestData.java @@ -0,0 +1,58 @@ +package com.javarush.vasileva.service; + +import com.javarush.vasileva.entity.Quest; +import com.javarush.vasileva.entity.Role; +import com.javarush.vasileva.entity.User; + +import java.util.List; + +public final class TestData { + private TestData() {} + + public static final Long VALID_QUEST_ID = 1L; + public static final Long NON_EXISTENT_QUEST_ID = 999L; + public static final String NON_EXISTENT_QUEST_ID_STR = "999"; + public static final String NULL_QUEST_ID_STR = null; + public static final String EMPTY_QUEST_ID_STR = ""; + public static final Long NON_EXISTENT_USER_ID = 999L; + public static final String VALID_USER_LOGIN = "testUser"; + public static final String VALID_USER_EMAIL = "test@email.com"; + public static final String VALID_USER_PASSWORD = "testPassword"; + public static final String INVALID_USER_EMAIL = "invalid@email.com"; + public static final String INVALID_USER_PASSWORD = "invalidPassword"; + public static final String EMPTY_USER_ID_STR = ""; + public static final String NULL_USER_ID_STR = null; + + public static User createValidUser() { + return User.builder() + .id(1L) + .login("testuser") + .email("test@gmail.com") + .password("password123") + .role(Role.USER) + .build(); + } + + public static Quest createValidQuest() { + return Quest.builder() + .id(VALID_QUEST_ID) + .title("Test Quest Title") + .description("Test Quest Description") + .build(); + } + + public static Quest createQuestWithId(Long id) { + return Quest.builder() + .id(id) + .title("Quest #" + id) + .build(); + } + + public static List createMultipleQuests() { + return List.of( + createQuestWithId(1L), + createQuestWithId(2L), + createQuestWithId(3L) + ); + } +} diff --git a/src/test/java/com/javarush/vasileva/service/UserServiceTest.java b/src/test/java/com/javarush/vasileva/service/UserServiceTest.java index c67b650..eecfa42 100644 --- a/src/test/java/com/javarush/vasileva/service/UserServiceTest.java +++ b/src/test/java/com/javarush/vasileva/service/UserServiceTest.java @@ -15,6 +15,7 @@ import java.util.List; import java.util.Optional; +import static com.javarush.vasileva.service.TestData.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @@ -31,13 +32,7 @@ public class UserServiceTest { @BeforeEach public void setUp() { - testUser = User.builder() - .id(1L) - .login("testuser") - .email("test@gmail.com") - .password("password123") - .role(Role.USER) - .build(); + testUser = createValidUser(); } @Test @@ -90,7 +85,7 @@ void givenUserIdExists_WhenFindById_ThenReturnUser() { @Test @DisplayName("given user id not found when find by id then return empty") void givenUserIdNotFound_WhenFindById_ThenReturnEmpty() { - long absentUserId = -1L; + long absentUserId = NON_EXISTENT_USER_ID; when(userRepository.findById(absentUserId)).thenReturn(Optional.empty()); Optional result = userService.findById(absentUserId); @@ -102,15 +97,12 @@ void givenUserIdNotFound_WhenFindById_ThenReturnEmpty() { @Test @DisplayName("given login email password when register then repository create user with user role") void givenLoginEmailPassword_WhenRegister_ThenRepositoryCreateUser() { - String regName = "newuser"; - String regEmail = "new@email.com"; - String regPassword = "password123"; - userService.register(regName, regEmail, regPassword); + userService.register(VALID_USER_LOGIN, VALID_USER_EMAIL, VALID_USER_PASSWORD); User expectedUser = User.builder() - .login(regName) - .email(regEmail) - .password(regPassword) + .login(VALID_USER_LOGIN) + .email(VALID_USER_EMAIL) + .password(VALID_USER_PASSWORD) .role(Role.USER) .build(); @@ -121,49 +113,43 @@ void givenLoginEmailPassword_WhenRegister_ThenRepositoryCreateUser() { @Test @DisplayName("given valid email and password when login then return user") void givenValidEmailAndPassword_WhenLogin_ThenReturnUser() { - String validEmail = "test@gmail.com"; - String validPassword = "password123"; - when(userRepository.findByEmail(validEmail)).thenReturn(Optional.of(testUser)); + when(userRepository.findByEmail(testUser.getEmail())).thenReturn(Optional.of(testUser)); - Optional result = userService.login(validEmail, validPassword); + Optional result = userService.login(testUser.getEmail(), testUser.getPassword()); assertTrue(result.isPresent()); assertEquals(testUser.getId(), result.get().getId()); - verify(userRepository, times(1)).findByEmail(validEmail); + verify(userRepository, times(1)).findByEmail(testUser.getEmail()); } @Test @DisplayName("given wrong password when login then return empty") void givenWrongPassword_WhenLogin_ThenReturnEmpty() { - String validEmail = "test@gmail.com"; - String invalidPassword = "password"; - when(userRepository.findByEmail(validEmail)).thenReturn(Optional.of(testUser)); + when(userRepository.findByEmail(VALID_USER_EMAIL)).thenReturn(Optional.of(testUser)); - Optional result = userService.login(validEmail, invalidPassword); + Optional result = userService.login(VALID_USER_EMAIL, INVALID_USER_PASSWORD); assertFalse(result.isPresent()); - verify(userRepository, times(1)).findByEmail(validEmail); + verify(userRepository, times(1)).findByEmail(VALID_USER_EMAIL); } @Test @DisplayName("given wrong email when login then return empty") void givenWrongLogin_WhenLogin_ThenReturnEmpty() { - String invalidEmail = "test2@gmail.com"; - String validPassword = "password123"; - when(userRepository.findByEmail(invalidEmail)).thenReturn(Optional.empty()); + when(userRepository.findByEmail(INVALID_USER_EMAIL)).thenReturn(Optional.empty()); - Optional result = userService.login(invalidEmail, validPassword); + Optional result = userService.login(INVALID_USER_EMAIL, VALID_USER_PASSWORD); assertFalse(result.isPresent()); - verify(userRepository, times(1)).findByEmail(invalidEmail); + verify(userRepository, times(1)).findByEmail(INVALID_USER_EMAIL); } @Test @DisplayName("given valid user id string when get validated user then return user") void givenValidUserIdString_WhenGetValidatedUser_ThenReturnUser() { - when(userRepository.findById(1L)).thenReturn(Optional.of(testUser)); + when(userRepository.findById(testUser.getId())).thenReturn(Optional.of(testUser)); - Optional result = userService.getValidatedUser("1"); + Optional result = userService.getValidatedUser(String.valueOf(testUser.getId())); assertTrue(result.isPresent()); assertEquals(testUser.getId(), result.get().getId()); @@ -172,14 +158,14 @@ void givenValidUserIdString_WhenGetValidatedUser_ThenReturnUser() { @Test @DisplayName("given empty user id string when get validated user then return empty") void givenEmptyUserIdString_whenGetValidatedUser_thenReturnEmpty() { - Optional result = userService.getValidatedUser(""); + Optional result = userService.getValidatedUser(EMPTY_USER_ID_STR); assertFalse(result.isPresent()); } @Test @DisplayName("given null user when get validated user then return empty") void givenNullUserIdString_whenGetValidatedUser_thenReturnEmpty() { - Optional result = userService.getValidatedUser(null); + Optional result = userService.getValidatedUser(NULL_USER_ID_STR); assertFalse(result.isPresent()); } } From d1b4ed35eeb6c0d941bb07273a9bfa858113f14a Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Wed, 4 Feb 2026 15:58:24 +0500 Subject: [PATCH 60/65] ADD test data and unit tests for QuestionService --- .../vasileva/service/QuestionServiceTest.java | 139 ++++++++++++++++++ .../javarush/vasileva/service/TestData.java | 61 +++++++- 2 files changed, 196 insertions(+), 4 deletions(-) create mode 100644 src/test/java/com/javarush/vasileva/service/QuestionServiceTest.java diff --git a/src/test/java/com/javarush/vasileva/service/QuestionServiceTest.java b/src/test/java/com/javarush/vasileva/service/QuestionServiceTest.java new file mode 100644 index 0000000..a7020ff --- /dev/null +++ b/src/test/java/com/javarush/vasileva/service/QuestionServiceTest.java @@ -0,0 +1,139 @@ +package com.javarush.vasileva.service; + +import com.javarush.vasileva.entity.Question; +import com.javarush.vasileva.repository.QuestionRepository; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.Optional; + +import static com.javarush.vasileva.service.TestData.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class QuestionServiceTest { + + @Mock + private QuestionRepository questionRepository; + + @InjectMocks + private QuestionService questionService; + + @Test + @DisplayName("when create() then delegate to repository") + void testCreate() { + Question question = createSimpleQuestion(); + questionService.create(question); + verify(questionRepository).create(question); + } + + @Test + @DisplayName("when getAll() then return all questions from repository") + void testGetAll() { + List questions = createMultipleQuestions(); + when(questionRepository.getAll()).thenReturn(questions); + + List result = questionService.getAll(); + + assertEquals(questions, result); + verify(questionRepository).getAll(); + } + + @Test + @DisplayName("when findById() then return question by ID") + void testFindById() { + Question expected = createQuestionWithAnswers(); + when(questionRepository.findById(VALID_QUESTION_ID)) + .thenReturn(Optional.of(expected)); + + Optional result = questionService.findById(VALID_QUESTION_ID); + + assertTrue(result.isPresent()); + assertEquals(expected, result.get()); + verify(questionRepository).findById(VALID_QUESTION_ID); + } + + @Test + @DisplayName("when findById() then return empty Optional if question not found") + void whenFindById_ThenQuestionNotFound() { + when(questionRepository.findById(NON_EXISTENT_QUESTION_ID)) + .thenReturn(Optional.empty()); + + Optional result = questionService.findById(NON_EXISTENT_QUESTION_ID); + + assertFalse(result.isPresent()); + verify(questionRepository).findById(NON_EXISTENT_QUESTION_ID); + } + + @Test + @DisplayName("when getByQuestionLabelAndQuestId() then return question by label and quest ID") + void testGetByQuestionLabelAndQuestId() { + Question expected = createQuestionWithAnswers(); + when(questionRepository.getByQuestionLabelAndQuestId( + VALID_LABEL, VALID_QUEST_ID)) + .thenReturn(Optional.of(expected)); + + Optional result = questionService.getByQuestionLabelAndQuestId( + VALID_LABEL, VALID_QUEST_ID); + + assertTrue(result.isPresent()); + assertEquals(expected, result.get()); + verify(questionRepository).getByQuestionLabelAndQuestId( + VALID_LABEL, VALID_QUEST_ID); + } + + @Test + @DisplayName("when getByQuestionLabelAndQuestId() then return empty if not found") + void whenGetByQuestionLabelAndQuestId_ThenQuestionNotFound() { + when(questionRepository.getByQuestionLabelAndQuestId( + INVALID_LABEL, VALID_QUEST_ID)) + .thenReturn(Optional.empty()); + + Optional result = questionService.getByQuestionLabelAndQuestId( + INVALID_LABEL, VALID_QUEST_ID); + + assertFalse(result.isPresent()); + verify(questionRepository).getByQuestionLabelAndQuestId( + INVALID_LABEL, VALID_QUEST_ID); + } + + @Test + @DisplayName("when isFinalQuestion() then return true for question with null answers") + void whenIsFinalQuestion_ThenNullAnswers() { + Question question = createFinalQuestion(); + + boolean result = questionService.isFinalQuestion(question); + + assertTrue(result); + } + + @Test + @DisplayName("when isFinalQuestion() then return true for question with empty answers list") + void whenIsFinalQuestion_EmptyAnswers() { + Question question = createSimpleQuestion(); + question.setAnswers(List.of()); + + boolean result = questionService.isFinalQuestion(question); + + assertTrue(result, "Question is final if answer list is empty"); + assertEquals(List.of(), question.getAnswers()); + } + + @Test + @DisplayName("when isFinalQuestion() then return false for question with non‑empty answers list") + void whenIsNotFinalQuestion_thenNonEmptyAnswers() { + Question question = createQuestionWithAnswers(); + assertFalse(question.getAnswers().isEmpty()); + + boolean result = questionService.isFinalQuestion(question); + + assertFalse(result, "Question is not final if it has answers"); + } +} diff --git a/src/test/java/com/javarush/vasileva/service/TestData.java b/src/test/java/com/javarush/vasileva/service/TestData.java index c911cfa..db09ac4 100644 --- a/src/test/java/com/javarush/vasileva/service/TestData.java +++ b/src/test/java/com/javarush/vasileva/service/TestData.java @@ -1,19 +1,19 @@ package com.javarush.vasileva.service; -import com.javarush.vasileva.entity.Quest; -import com.javarush.vasileva.entity.Role; -import com.javarush.vasileva.entity.User; +import com.javarush.vasileva.entity.*; import java.util.List; public final class TestData { - private TestData() {} + private TestData() { + } public static final Long VALID_QUEST_ID = 1L; public static final Long NON_EXISTENT_QUEST_ID = 999L; public static final String NON_EXISTENT_QUEST_ID_STR = "999"; public static final String NULL_QUEST_ID_STR = null; public static final String EMPTY_QUEST_ID_STR = ""; + public static final Long NON_EXISTENT_USER_ID = 999L; public static final String VALID_USER_LOGIN = "testUser"; public static final String VALID_USER_EMAIL = "test@email.com"; @@ -23,6 +23,11 @@ private TestData() {} public static final String EMPTY_USER_ID_STR = ""; public static final String NULL_USER_ID_STR = null; + public static final Long VALID_QUESTION_ID = 1L; + public static final Long NON_EXISTENT_QUESTION_ID = 999L; + public static final String VALID_LABEL = "Q1"; + public static final String INVALID_LABEL = "XYZ"; + public static User createValidUser() { return User.builder() .id(1L) @@ -55,4 +60,52 @@ public static List createMultipleQuests() { createQuestWithId(3L) ); } + + public static Question createQuestionWithAnswers() { + Question question = Question.builder() + .generatedId(VALID_QUESTION_ID) + .label(VALID_LABEL) + .questId(VALID_QUEST_ID) + .text("Какой цвет неба?") + .build(); + List answers = List.of( + createAnswer(1L, "Синий"), + createAnswer(2L, "Голубой")); + question.setAnswers(answers); + return question; + } + + public static Question createFinalQuestion() { + return Question.builder() + .generatedId(2L) + .label("END") + .questId(VALID_QUEST_ID) + .text("Это финальный вопрос.") + .answers(null) + .build(); + } + + public static Question createSimpleQuestion() { + return Question.builder() + .generatedId(3L) + .label("Q3") + .questId(VALID_QUEST_ID) + .text("Простой вопрос.") + .build(); + } + + public static Answer createAnswer(Long id, String text) { + return Answer.builder() + .id(id) + .text(text) + .build(); + } + + public static List createMultipleQuestions() { + return List.of( + createQuestionWithAnswers(), + createFinalQuestion(), + createSimpleQuestion() + ); + } } From fbb3dc5f47759a1939e49a68c5953a073f16fcab Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Wed, 4 Feb 2026 16:59:40 +0500 Subject: [PATCH 61/65] ADD test data and unit tests for AnswerService, GameService --- .../vasileva/service/AnswerService.java | 1 - .../vasileva/service/AnswerServiceTest.java | 73 ++++++++ .../vasileva/service/GameServiceTest.java | 163 ++++++++++++++++++ .../javarush/vasileva/service/TestData.java | 93 +++++++++- .../vasileva/service/UserServiceTest.java | 6 +- 5 files changed, 323 insertions(+), 13 deletions(-) create mode 100644 src/test/java/com/javarush/vasileva/service/AnswerServiceTest.java create mode 100644 src/test/java/com/javarush/vasileva/service/GameServiceTest.java diff --git a/src/main/java/com/javarush/vasileva/service/AnswerService.java b/src/main/java/com/javarush/vasileva/service/AnswerService.java index d04ae2a..9e4514f 100644 --- a/src/main/java/com/javarush/vasileva/service/AnswerService.java +++ b/src/main/java/com/javarush/vasileva/service/AnswerService.java @@ -25,5 +25,4 @@ public Optional findById(Long id) { public void create(Answer answer) { answerRepository.create(answer); } - } diff --git a/src/test/java/com/javarush/vasileva/service/AnswerServiceTest.java b/src/test/java/com/javarush/vasileva/service/AnswerServiceTest.java new file mode 100644 index 0000000..7fe3faa --- /dev/null +++ b/src/test/java/com/javarush/vasileva/service/AnswerServiceTest.java @@ -0,0 +1,73 @@ +package com.javarush.vasileva.service; + +import com.javarush.vasileva.entity.Answer; +import com.javarush.vasileva.repository.AnswerRepository; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.Optional; + +import static com.javarush.vasileva.service.TestData.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +public class AnswerServiceTest { + @Mock + private AnswerRepository answerRepository; + + @InjectMocks + private AnswerService answerService; + + @Test + @DisplayName("when getAll() then return all answers from repository") + void testGetAll() { + List answers = createMultipleAnswers(); + when(answerRepository.getAll()).thenReturn(answers); + + List result = answerService.getAll(); + + assertEquals(answers, result); + verify(answerRepository).getAll(); + } + + @Test + @DisplayName("when findById() then return answer by ID if it exists") + void whenFindById_thenExisting() { + Answer expected = createValidAnswer(); + when(answerRepository.findById(VALID_ANSWER_ID)) + .thenReturn(Optional.of(expected)); + + Optional result = answerService.findById(VALID_ANSWER_ID); + + assertTrue(result.isPresent()); + assertEquals(expected, result.get()); + verify(answerRepository).findById(VALID_ANSWER_ID); + } + + @Test + @DisplayName("when findById() then return empty Optional if answer is not found") + void whenFindById_ThenNonExisting() { + when(answerRepository.findById(NON_EXISTENT_ANSWER_ID)) + .thenReturn(Optional.empty()); + + Optional result = answerService.findById(NON_EXISTENT_ANSWER_ID); + + assertFalse(result.isPresent()); + verify(answerRepository).findById(NON_EXISTENT_ANSWER_ID); + } + + @Test + @DisplayName("when create() then delegate saving answer to repository") + void testCreate() { + Answer newAnswer = createValidAnswer(); + answerService.create(newAnswer); + verify(answerRepository).create(newAnswer); + } +} diff --git a/src/test/java/com/javarush/vasileva/service/GameServiceTest.java b/src/test/java/com/javarush/vasileva/service/GameServiceTest.java new file mode 100644 index 0000000..ace7cd5 --- /dev/null +++ b/src/test/java/com/javarush/vasileva/service/GameServiceTest.java @@ -0,0 +1,163 @@ +package com.javarush.vasileva.service; + +import com.javarush.vasileva.entity.Game; +import com.javarush.vasileva.entity.GameState; +import com.javarush.vasileva.entity.Quest; +import com.javarush.vasileva.entity.User; +import com.javarush.vasileva.exception.AppException; +import com.javarush.vasileva.game.GameEngine; +import com.javarush.vasileva.repository.InMemoryGameRepository; +import com.javarush.vasileva.util.Value; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Optional; + +import static com.javarush.vasileva.service.TestData.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class GameServiceTest { + @Mock + private InMemoryGameRepository gameRepository; + @Mock + private UserService userService; + @Mock + private QuestService questService; + @Mock + private GameEngine gameEngine; + + @InjectMocks + private GameService gameService; + + private User user; + + @BeforeEach + public void setUp() { + user = createValidUser(); + } + + @Test + @DisplayName("when startNewGame() then create and save new game when user and quest exist") + void whenStartNewGame_ThenSuccess() { + Quest quest = createValidQuest(); + GameState initialState = createInitialGameState(); + Game expectedGame = createGame( + VALID_QUEST_ID, + VALID_USER_ID, + initialState.getCurrentQuestion().getGeneratedId(), + initialState + ); + + when(userService.findById(VALID_USER_ID)).thenReturn(Optional.of(user)); + when(questService.findById(VALID_QUEST_ID)).thenReturn(Optional.of(quest)); + when(gameEngine.startGame(user, quest)).thenReturn(initialState); + when(gameRepository.save(any(Game.class))).thenReturn(expectedGame); + + Game result = gameService.startNewGame(VALID_QUEST_ID, VALID_USER_ID); + + assertEquals(expectedGame, result); + verify(userService).findById(VALID_USER_ID); + verify(questService).findById(VALID_QUEST_ID); + verify(gameEngine).startGame(user, quest); + verify(gameRepository).save(expectedGame); + } + + @Test + @DisplayName("when startNewGame() then throw AppException if user not found") + void whenStartNewGame_ThenUserNotFound() { + when(userService.findById(NON_EXISTENT_USER_ID)) + .thenReturn(Optional.empty()); + + AppException exception = assertThrows(AppException.class, + () -> gameService.startNewGame(VALID_QUEST_ID, NON_EXISTENT_USER_ID)); + + assertEquals(Value.USER_NOT_FOUND, exception.getMessage()); + verify(userService).findById(NON_EXISTENT_USER_ID); + verify(questService, never()).findById(anyLong()); + verify(gameEngine, never()).startGame(any(), any()); + verify(gameRepository, never()).save(any()); + } + + @Test + @DisplayName("when startNewGame() then throw AppException if quest not found") + void whenStartNewGame_ThenQuestNotFound() { + when(userService.findById(VALID_USER_ID)).thenReturn(Optional.of(user)); + when(questService.findById(NON_EXISTENT_QUEST_ID)) + .thenReturn(Optional.empty()); + + AppException exception = assertThrows(AppException.class, + () -> gameService.startNewGame(NON_EXISTENT_QUEST_ID, VALID_USER_ID)); + + assertEquals(Value.QUEST_NOT_FOUND, exception.getMessage()); + verify(userService).findById(VALID_USER_ID); + verify(questService).findById(NON_EXISTENT_QUEST_ID); + verify(gameEngine, never()).startGame(any(), any()); + verify(gameRepository, never()).save(any()); + } + + @Test + @DisplayName("advanceGame() should update game state when game exists") + void testAdvanceGame_Success() { + Game existingGame = createSavedGame(); + GameState nextState = createNextGameState(); + + when(gameRepository.findById(VALID_GAME_ID)) + .thenReturn(Optional.of(existingGame)); + when(gameEngine.advanceGame(existingGame.getGameState(), VALID_ANSWER_ID)) + .thenReturn(nextState); + when(gameRepository.save(any(Game.class))).thenAnswer(invocation -> { + Game updatedGame = invocation.getArgument(0); + updatedGame.setId(VALID_GAME_ID); + return updatedGame; + }); + + Game result = gameService.advanceGame(VALID_GAME_ID, VALID_ANSWER_ID); + + assertNotNull(result); + assertEquals(VALID_GAME_ID, result.getId()); + assertEquals(nextState.getCurrentQuestion().getGeneratedId(), result.getCurrentQuestionId()); + assertEquals(nextState, result.getGameState()); + + verify(gameEngine).advanceGame( + argThat(state -> state.getCurrentQuestion().getGeneratedId().equals(1L)), + eq(TestData.VALID_ANSWER_ID) + ); + verify(gameRepository).save(result); + } + + @Test + @DisplayName("when getGameById() then return game if exists") + void testGetGameById_Found() { + Game expectedGame = createSavedGame(); + when(gameRepository.findById(VALID_GAME_ID)) + .thenReturn(Optional.of(expectedGame)); + + Optional result = gameService.getGameById(VALID_GAME_ID); + + assertTrue(result.isPresent()); + assertEquals(expectedGame, result.get()); + verify(gameRepository).findById(VALID_GAME_ID); + } + + @Test + @DisplayName("when getGameById() then return empty Optional if game not found") + void whenGetGameById_ThenNotFound() { + when(gameRepository.findById(NON_EXISTENT_GAME_ID)) + .thenReturn(Optional.empty()); + + Optional result = gameService.getGameById(NON_EXISTENT_GAME_ID); + + assertFalse(result.isPresent()); + verify(gameRepository).findById(NON_EXISTENT_GAME_ID); + } + + +} diff --git a/src/test/java/com/javarush/vasileva/service/TestData.java b/src/test/java/com/javarush/vasileva/service/TestData.java index db09ac4..e7f7f4d 100644 --- a/src/test/java/com/javarush/vasileva/service/TestData.java +++ b/src/test/java/com/javarush/vasileva/service/TestData.java @@ -8,13 +8,17 @@ public final class TestData { private TestData() { } + // QUEST public static final Long VALID_QUEST_ID = 1L; public static final Long NON_EXISTENT_QUEST_ID = 999L; public static final String NON_EXISTENT_QUEST_ID_STR = "999"; public static final String NULL_QUEST_ID_STR = null; public static final String EMPTY_QUEST_ID_STR = ""; + public static final String QUEST_TITLE = "Test Quest"; + // USER public static final Long NON_EXISTENT_USER_ID = 999L; + public static final Long VALID_USER_ID = 1L; public static final String VALID_USER_LOGIN = "testUser"; public static final String VALID_USER_EMAIL = "test@email.com"; public static final String VALID_USER_PASSWORD = "testPassword"; @@ -23,25 +27,38 @@ private TestData() { public static final String EMPTY_USER_ID_STR = ""; public static final String NULL_USER_ID_STR = null; + // QUESTION public static final Long VALID_QUESTION_ID = 1L; public static final Long NON_EXISTENT_QUESTION_ID = 999L; public static final String VALID_LABEL = "Q1"; public static final String INVALID_LABEL = "XYZ"; + // GAME + public static final Long VALID_GAME_ID = 100L; + public static final Long NON_EXISTENT_GAME_ID = 99999L; + + // ANSWER + public static final Long VALID_ANSWER_ID = 1L; + public static final Long NON_EXISTENT_ANSWER_ID = 999L; + public static final String VALID_ANSWER_TEXT = "Правильный ответ"; + + /* ======================================= USER =================================== */ public static User createValidUser() { return User.builder() - .id(1L) - .login("testuser") - .email("test@gmail.com") - .password("password123") + .id(VALID_USER_ID) + .login(VALID_USER_LOGIN) + .email(VALID_USER_EMAIL) + .password(VALID_USER_PASSWORD) .role(Role.USER) .build(); } + /* ======================================= QUEST =================================== */ + public static Quest createValidQuest() { return Quest.builder() .id(VALID_QUEST_ID) - .title("Test Quest Title") + .title(QUEST_TITLE) .description("Test Quest Description") .build(); } @@ -61,6 +78,8 @@ public static List createMultipleQuests() { ); } + /* ======================================= QUESTION =================================== */ + public static Question createQuestionWithAnswers() { Question question = Question.builder() .generatedId(VALID_QUESTION_ID) @@ -94,6 +113,16 @@ public static Question createSimpleQuestion() { .build(); } + public static List createMultipleQuestions() { + return List.of( + createQuestionWithAnswers(), + createFinalQuestion(), + createSimpleQuestion() + ); + } + + /* ======================================= ANSWER =================================== */ + public static Answer createAnswer(Long id, String text) { return Answer.builder() .id(id) @@ -101,11 +130,57 @@ public static Answer createAnswer(Long id, String text) { .build(); } - public static List createMultipleQuestions() { + public static Answer createValidAnswer() { + return Answer.builder() + .id(VALID_ANSWER_ID) + .text(VALID_ANSWER_TEXT) + .build(); + } + + public static List createMultipleAnswers() { return List.of( - createQuestionWithAnswers(), - createFinalQuestion(), - createSimpleQuestion() + createValidAnswer(), + createAnswer(2L, "Второй ответ"), + createAnswer(3L, "Третий ответ") ); } + + /* ======================================= GAME =================================== */ + + public static GameState createInitialGameState() { + Question currentQuestion = Question.builder() + .generatedId(VALID_QUESTION_ID) + .text("Первый вопрос квеста?") + .build(); + return GameState.builder() + .currentQuestion(currentQuestion) + .isCompleted(false) + .build(); + } + + public static GameState createNextGameState() { + Question nextQuestion = Question.builder() + .generatedId(2L) + .text("Следующий вопрос?") + .build(); + return GameState.builder() + .currentQuestion(nextQuestion) + .isCompleted(false) + .build(); + } + + public static Game createGame(Long questId, Long userId, Long currentQuestionId, GameState state) { + return Game.builder() + .questId(questId) + .userId(userId) + .currentQuestionId(currentQuestionId) + .gameState(state) + .build(); + } + + public static Game createSavedGame() { + Game game = createGame(VALID_QUEST_ID, VALID_USER_ID, 1L, createInitialGameState()); + game.setId(VALID_GAME_ID); + return game; + } } diff --git a/src/test/java/com/javarush/vasileva/service/UserServiceTest.java b/src/test/java/com/javarush/vasileva/service/UserServiceTest.java index eecfa42..1556f13 100644 --- a/src/test/java/com/javarush/vasileva/service/UserServiceTest.java +++ b/src/test/java/com/javarush/vasileva/service/UserServiceTest.java @@ -38,21 +38,21 @@ public void setUp() { @Test @DisplayName("given user when create then repository create called") void givenUser_whenCreate_ThenRepositoryCreateCalled() { - userRepository.create(testUser); + userService.create(testUser); verify(userRepository, times(1)).create(testUser); } @Test @DisplayName("given user when update then repository update called") void givenUser_whenUpdate_ThenRepositoryUpdateCalled() { - userRepository.update(testUser); + userService.update(testUser); verify(userRepository, times(1)).update(testUser); } @Test @DisplayName("given user when delete then repository delete called") void givenUser_whenDelete_ThenRepositoryDeleteCalled() { - userRepository.delete(testUser); + userService.delete(testUser); verify(userRepository, times(1)).delete(testUser); } From d27278062c47a16f082b3405bf94992f344e4fe3 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Wed, 4 Feb 2026 17:19:22 +0500 Subject: [PATCH 62/65] ADD test data and unit tests for UserStats --- .../javarush/vasileva/service/TestData.java | 37 +++++++ .../service/UserStatsServiceTest.java | 102 ++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 src/test/java/com/javarush/vasileva/service/UserStatsServiceTest.java diff --git a/src/test/java/com/javarush/vasileva/service/TestData.java b/src/test/java/com/javarush/vasileva/service/TestData.java index e7f7f4d..1b7c7d1 100644 --- a/src/test/java/com/javarush/vasileva/service/TestData.java +++ b/src/test/java/com/javarush/vasileva/service/TestData.java @@ -1,6 +1,7 @@ package com.javarush.vasileva.service; import com.javarush.vasileva.entity.*; +import com.javarush.vasileva.util.Value; import java.util.List; @@ -42,6 +43,10 @@ private TestData() { public static final Long NON_EXISTENT_ANSWER_ID = 999L; public static final String VALID_ANSWER_TEXT = "Правильный ответ"; + // STATS + public static final String WIN_LABEL = "Q1" + Value.WIN; + public static final String LOSS_LABEL = "Q2" + Value.LOSS; + /* ======================================= USER =================================== */ public static User createValidUser() { return User.builder() @@ -183,4 +188,36 @@ public static Game createSavedGame() { game.setId(VALID_GAME_ID); return game; } + + /* ======================================= STATS =================================== */ + + public static UserStats createDefaultUserStats() { + return UserStats.builder() + .userId(VALID_USER_ID) + .total(0) + .wins(0) + .losses(0) + .build(); + } + + public static UserStats createFilledUserStats() { + return UserStats.builder() + .userId(VALID_USER_ID) + .total(5) + .wins(3) + .losses(2) + .build(); + } + + public static Question createWinQuestion() { + return Question.builder() + .label(WIN_LABEL) + .build(); + } + + public static Question createLossQuestion() { + return Question.builder() + .label(LOSS_LABEL) + .build(); + } } diff --git a/src/test/java/com/javarush/vasileva/service/UserStatsServiceTest.java b/src/test/java/com/javarush/vasileva/service/UserStatsServiceTest.java new file mode 100644 index 0000000..b759c16 --- /dev/null +++ b/src/test/java/com/javarush/vasileva/service/UserStatsServiceTest.java @@ -0,0 +1,102 @@ +package com.javarush.vasileva.service; + +import com.javarush.vasileva.entity.Question; +import com.javarush.vasileva.entity.UserStats; +import com.javarush.vasileva.repository.UserStatsRepository; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Optional; + +import static com.javarush.vasileva.service.TestData.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class UserStatsServiceTest { + + @Mock + private UserStatsRepository userStatsRepository; + + @InjectMocks + private UserStatsService userStatsService; + + @Test + @DisplayName("when createUserStats() then delegate stats creation to repository") + void testCreateUserStats() { + UserStats expectedStats = createDefaultUserStats(); + when(userStatsRepository.createUserStats(VALID_USER_ID)) + .thenReturn(expectedStats); + + UserStats result = userStatsService.createUserStats(VALID_USER_ID); + + assertEquals(expectedStats, result); + verify(userStatsRepository).createUserStats(VALID_USER_ID); + } + + @Test + @DisplayName("when getUserStats() then return user stats if it exists") + void whenGetUserStats_thenExisting() { + UserStats expectedStats = createFilledUserStats(); + when(userStatsRepository.getUserStats(VALID_USER_ID)) + .thenReturn(Optional.of(expectedStats)); + + Optional result = userStatsService.getUserStats(VALID_USER_ID); + + assertTrue(result.isPresent()); + assertEquals(expectedStats, result.get()); + verify(userStatsRepository).getUserStats(VALID_USER_ID); + } + + @Test + @DisplayName("when getUserStats() then return empty Optional if stats is not found") + void whenGetUserStats_ThenNonExisting() { + when(userStatsRepository.getUserStats(NON_EXISTENT_USER_ID)) + .thenReturn(Optional.empty()); + + Optional result = userStatsService.getUserStats(NON_EXISTENT_USER_ID); + + assertFalse(result.isPresent()); + verify(userStatsRepository).getUserStats(NON_EXISTENT_USER_ID); + } + + @Test + @DisplayName("when updateUserStats() then increase total и wins if WIN-question") + void testUpdateUserStats_WinQuestion() { + UserStats stats = createDefaultUserStats(); + Question winQuestion = createWinQuestion(); + + doAnswer(invocation -> { + invocation.getArgument(0); + return null; + }).when(userStatsRepository).updateUserStats(any(UserStats.class)); + + userStatsService.updateUserStats(winQuestion, stats); + + assertEquals(1, stats.getTotal()); + assertEquals(1, stats.getWins()); + assertEquals(0, stats.getLosses()); + verify(userStatsRepository).updateUserStats(stats); + } + + @Test + @DisplayName("when updateUserStats() then increase total и losses if LOSS-question") + void testUpdateUserStats_LossQuestion() { + UserStats stats = createDefaultUserStats(); + Question lossQuestion = createLossQuestion(); + + doAnswer(invocation -> null) + .when(userStatsRepository).updateUserStats(any(UserStats.class)); + + userStatsService.updateUserStats(lossQuestion, stats); + + assertEquals(1, stats.getTotal()); + assertEquals(0, stats.getWins()); + assertEquals(1, stats.getLosses()); + verify(userStatsRepository).updateUserStats(stats); + } +} From e881283a97aac72aa49f3fcba99cd788bc300197 Mon Sep 17 00:00:00 2001 From: KatiaVasileva Date: Thu, 5 Feb 2026 00:43:43 +0500 Subject: [PATCH 63/65] ADD tests for AuthService + img for quests --- .../vasileva/controller/FrontController.java | 2 +- .../com/javarush/vasileva/entity/Quest.java | 1 + .../com/javarush/vasileva/util/Value.java | 2 +- src/main/resources/json/quest-1.json | 1 + src/main/resources/json/quest-2.json | 1 + src/main/resources/json/quest-3.json | 1 + src/main/webapp/WEB-INF/home.jsp | 8 +- src/main/webapp/WEB-INF/play-game.jsp | 13 ++- .../vasileva/service/AuthServiceTest.java | 86 +++++++++++++++++++ .../javarush/vasileva/service/TestData.java | 28 ++++++ 10 files changed, 131 insertions(+), 12 deletions(-) create mode 100644 src/test/java/com/javarush/vasileva/service/AuthServiceTest.java diff --git a/src/main/java/com/javarush/vasileva/controller/FrontController.java b/src/main/java/com/javarush/vasileva/controller/FrontController.java index facf519..86290d4 100644 --- a/src/main/java/com/javarush/vasileva/controller/FrontController.java +++ b/src/main/java/com/javarush/vasileva/controller/FrontController.java @@ -37,7 +37,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se } private static String getJsp(String view) { - return "/WEB-INF/" + view + ".jsp"; + return "WEB-INF/" + view + ".jsp"; } @Override diff --git a/src/main/java/com/javarush/vasileva/entity/Quest.java b/src/main/java/com/javarush/vasileva/entity/Quest.java index bcf6eba..8973bec 100644 --- a/src/main/java/com/javarush/vasileva/entity/Quest.java +++ b/src/main/java/com/javarush/vasileva/entity/Quest.java @@ -18,4 +18,5 @@ public class Quest { private String text; private Long startQuestionId; private List questions; + private String image; } diff --git a/src/main/java/com/javarush/vasileva/util/Value.java b/src/main/java/com/javarush/vasileva/util/Value.java index fd6f6cd..7960c8f 100644 --- a/src/main/java/com/javarush/vasileva/util/Value.java +++ b/src/main/java/com/javarush/vasileva/util/Value.java @@ -6,6 +6,7 @@ public class Value { "title": "Название", "description": "Краткое описание", "text": "Текст", + "image": "background-main.png", "questions": [ { "label": "1", @@ -41,7 +42,6 @@ public class Value { public static final String GAME_NOT_FOUND = "Игра не найдена"; public static final String ANSWER_NOT_FOUND = "Ответ не найден"; public static final String STATS_NOT_FOUND = "Статистика не найдена"; - public static final String QUEST_SERIALIZATION_ERROR = "Ошибка сериализации квеста"; public static final String EDIT_QUEST_AUTH_ERROR = "Редактировать квесты могут только пользователи с правами ADMIN"; public static final String DELETE_QUEST_AUTH_ERROR = "Удалять квесты могут только пользователи с правами ADMIN"; public static final String USER_LIST_AUTH_ERROR = "Получить список пользователей могут только пользователи с правами ADMIN"; diff --git a/src/main/resources/json/quest-1.json b/src/main/resources/json/quest-1.json index 1b269e5..1526205 100644 --- a/src/main/resources/json/quest-1.json +++ b/src/main/resources/json/quest-1.json @@ -2,6 +2,7 @@ "title": "Космическое приключение", "description": "Ты — космический путешественник, чей корабль внезапно получает загадочный сигнал от неопознанного объекта...", "text": "Ты — космический путешественник, чей корабль внезапно получает загадочный сигнал от неопознанного объекта на границе изученной галактики. Впереди — неизвестность, за каждым поворотом таятся тайны космоса, а каждое решение может стать судьбоносным. Готов ли ты принять вызов Вселенной и отправиться в путешествие, где правда и ложь, смелость и осторожность, судьба и случай переплетутся в одну невероятную историю?", + "image": "quest-1.png", "questions": [ { "label": "1", diff --git a/src/main/resources/json/quest-2.json b/src/main/resources/json/quest-2.json index 2535cc8..6e3b1cc 100644 --- a/src/main/resources/json/quest-2.json +++ b/src/main/resources/json/quest-2.json @@ -2,6 +2,7 @@ "title": "Автостопом по здравому смыслу (или Не паникуй)", "description": "По мотивам «Автостопом по Галактике»", "text": "Добро пожаловать в квест, который начинается с конца света и быстро переходит к вопросам посложнее. Землю сносят ради гиперпространственной магистрали, предупреждения были вывешены (где-то далеко и давно), а у вас есть лишь выбор, полотенце и крайне смутное представление о происходящем. Впереди — вогоны, сомнительный чай, философские размышления и шанс узнать ответ на Главный вопрос жизни, Вселенной и всего такого. Главное — не паникуйте: Вселенная всё равно делает вид, что всё под контролем.", + "image": "quest-2.png", "questions": [ { "label": "1", diff --git a/src/main/resources/json/quest-3.json b/src/main/resources/json/quest-3.json index 0e8c7ff..af016e3 100644 --- a/src/main/resources/json/quest-3.json +++ b/src/main/resources/json/quest-3.json @@ -2,6 +2,7 @@ "title": "Знаешь ли ты английский достаточно для того, чтобы играть в игры?", "description": "Проверь свой базовый игровой словарный запас и понимание типичных фраз из англоязычных видеоигр", "text": "Ты собираешься запустить новую RPG на английском, но не уверен, поймёшь ли диалоги и интерфейс. Давай проверим! На каждый вопрос — 3–4 варианта. Выбери один. Ошибёшься — игра «завершится».", + "image": "quest-3.png", "questions": [ { "label": "1", diff --git a/src/main/webapp/WEB-INF/home.jsp b/src/main/webapp/WEB-INF/home.jsp index e098b8b..72c92a5 100644 --- a/src/main/webapp/WEB-INF/home.jsp +++ b/src/main/webapp/WEB-INF/home.jsp @@ -12,12 +12,14 @@
-
+
-
-
+
+ background +
+
diff --git a/src/main/webapp/WEB-INF/play-game.jsp b/src/main/webapp/WEB-INF/play-game.jsp index e59dc55..31d4b08 100644 --- a/src/main/webapp/WEB-INF/play-game.jsp +++ b/src/main/webapp/WEB-INF/play-game.jsp @@ -11,10 +11,10 @@ ${requestScope.quest.title} -
-
-
- space +
+
+
+ space

${requestScope.quest.title}

@@ -40,11 +40,10 @@ Текущий вопрос
-