diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..1bf1eca --- /dev/null +++ b/README.MD @@ -0,0 +1,28 @@ +# Quest Pantera + +### Ребята и девчата, всем привет! + +На этот раз у нас более сложный проект, который будет трудно объединить в один общий проект со всем зависимостями. +Поэтому поступим просто. Тут первоначально лежит наш учебный проект. +Заготовка, такая же как может быть сгенерирована в IDEA. +Договоримся, что Java у нас будет 21-я. У всех. Привыкайте использовать только LTS. +Из зависимостей есть jakarta.servlet-api + jstl, JUnit5 и Lombok, +так что POM.xml возможно надо будет заменить на свой. + +### Что нужно сделать. + +1. Сделайте форк и затем клон этого репозитория. +2. **СРАЗУ** создайте в нем ветку со своей фамилией, например, ivanov. +3. Размещайте в своей ветке свое решение (если мои примеры мешают их можно просто удалить - ветвление же). +4. В конце вам нужно будет сделать **Pull Request** из своей ветки (в своем форке) в такую же точно ветку (в этом удаленном + репозитории), если вы не найдете - тогда в **main** ну и затем ОБЯЗАТЕЛЬНО заполнить форму проектов. +5. Я положу в ветку **khmelov** тот пример, который буду параллельно с вами разрабатывать на факультативах. Полезнее будет + не копипастить, смотрите видео, разбирайтесь, что, почему, где и как сделано. Не копируйте, нужно ВАШЕ решение. Но мы уже и + не совсем зеленые, правда ведь ;). +6. Проверять проекты по итогам третьего модуля я буду с **code review**, и скорее всего быстро не получится, так что за + сроки сдачи можно не волноваться. +7. Планируйте время так, первые три консультации - основной функционал. Последняя консультация - плюшки, рефакторинг, + тесты, красоты. +8. Если будут какие-то моменты - я обновлю это README. Поглядывайте периодически. + +#### _2026 JRU Pantera, Александр Хмелев._ diff --git a/pom.xml b/pom.xml index 78ee59d..2483f05 100644 --- a/pom.xml +++ b/pom.xml @@ -5,37 +5,39 @@ 4.0.0 com.javarush.khmelov - project-ledzeppelin + project-Pantera 1.0-SNAPSHOT - ProjectLedzeppelin + ProjectPantera war UTF-8 21 21 - 5.10.2 - - org.springframework.boot - spring-boot-starter-parent - 3.3.5 - - org.springframework.boot spring-boot-dependencies + 3.3.4 pom import - 3.3.5 + + org.projectlombok + lombok + provided + + + com.fasterxml.jackson.core + jackson-databind + jakarta.servlet jakarta.servlet-api @@ -49,12 +51,20 @@ org.glassfish.web jakarta.servlet.jsp.jstl - - org.projectlombok - lombok - provided + org.slf4j + slf4j-api + + + org.apache.logging.log4j + log4j-slf4j2-impl + + org.apache.logging.log4j + log4j-core + + + org.junit.jupiter junit-jupiter-api @@ -65,6 +75,17 @@ junit-jupiter-engine test + + org.mockito + mockito-core + test + + + org.mockito + mockito-junit-jupiter + test + + @@ -73,22 +94,64 @@ org.apache.maven.plugins maven-war-plugin - 3.4.0 + 3.3.2 + org.apache.maven.plugins - maven-compiler-plugin + maven-surefire-plugin + 3.2.5 - - - org.projectlombok - lombok - 1.18.34 - - + + **/*IT.java + + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.2.5 + + + integration-test + + integration-test + + + + verify + + verify + + + + + + **/*IT.java + + + + + + org.jacoco + jacoco-maven-plugin + 0.8.11 + + + + prepare-agent + + + + report + verify + + report + + + + - \ No newline at end of file diff --git a/src/main/java/com/javarush/goncharov/controller/AppConfig.java b/src/main/java/com/javarush/goncharov/controller/AppConfig.java new file mode 100644 index 0000000..b575b7a --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/AppConfig.java @@ -0,0 +1,48 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.repository.*; +import com.javarush.goncharov.service.*; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.FieldDefaults; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Getter +@FieldDefaults(level = AccessLevel.PRIVATE) +public class AppConfig { + final Storage storage = Storage.getInstance(); + final UserService userService; + final MessageService messageService; + final QuestService questService; + final QuestionService questionService; + final GameService gameService; + final AnswerRepository answerRepository; + final StatisticService statisticService; + + public AppConfig() { + log.info("Init MessageService.."); + messageService = new MessageService(new MessageRepository(storage)); + log.info("Init UserService.."); + userService = new UserService(new UserRepository(storage)); + log.info("Init QuestionService.."); + questionService = new QuestionService(new QuestionRepository(storage)); + log.info("Init QuestionService.."); + answerRepository = new AnswerRepository(storage); + log.info("Init QuestService.."); + questService = new QuestService(answerRepository, + questionService, + userService, + new QuestRepository(storage)); + log.info("Init GameService.."); + gameService = new GameService(new GameRepository(storage), + questService, + questionService, + userService, + answerRepository); + log.info("Init StatisticService.."); + statisticService = new StatisticService(new GameRepository(storage), + new UserRepository(storage)); + + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/CompletedMessages.java b/src/main/java/com/javarush/goncharov/controller/CompletedMessages.java new file mode 100644 index 0000000..1153937 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/CompletedMessages.java @@ -0,0 +1,48 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.Message; +import com.javarush.goncharov.model.Topic; +import com.javarush.goncharov.model.User; +import com.javarush.goncharov.repository.MessageRepository; +import com.javarush.goncharov.repository.Storage; +import com.javarush.goncharov.service.MessageService; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import java.io.IOException; +import java.util.Collection; +import java.util.Optional; + +@WebServlet("/completed-messages") +public class CompletedMessages extends DefaultServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + Collection messages = messageService.getAll().values(); + HttpSession session = req.getSession(); + User user = (User) session.getAttribute("user"); + req.setAttribute("messages", messages); + req.setAttribute("user", user); + req.getRequestDispatcher("/WEB-INF/completed-messages.jsp").forward(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + if (req.getParameter("action").equals("GoMessages")) { + resp.sendRedirect("/messages"); + return; + } + Long idMessage = Long.parseLong(req.getParameter("id")); + Optional message = messageService.get(idMessage); + if (req.getParameter("action").equals("delete")) { + messageService.delete(message.get()); + resp.sendRedirect("/completed-messages"); + } + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/ConfigAppInitializer.java b/src/main/java/com/javarush/goncharov/controller/ConfigAppInitializer.java new file mode 100644 index 0000000..ce780d7 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/ConfigAppInitializer.java @@ -0,0 +1,29 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.Role; +import com.javarush.goncharov.model.Topic; +import com.javarush.goncharov.service.*; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletContextEvent; +import jakarta.servlet.ServletContextListener; +import jakarta.servlet.annotation.WebListener; + +@WebListener +public class ConfigAppInitializer implements ServletContextListener { + + @Override + public void contextInitialized(ServletContextEvent sce) { + AppConfig appConfig = new AppConfig(); + + ServletContext servletContext = sce.getServletContext(); + servletContext.setAttribute("userService", appConfig.getUserService()); + servletContext.setAttribute("messageService", appConfig.getMessageService()); + servletContext.setAttribute("questService", appConfig.getQuestService()); + servletContext.setAttribute("questionService", appConfig.getQuestionService()); + servletContext.setAttribute("gameService", appConfig.getGameService()); + servletContext.setAttribute("answerRepository", appConfig.getAnswerRepository()); + servletContext.setAttribute("statisticService", appConfig.getStatisticService()); + servletContext.setAttribute("topics", Topic.values()); + servletContext.setAttribute("roles", Role.values()); + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/ContactUs.java b/src/main/java/com/javarush/goncharov/controller/ContactUs.java new file mode 100644 index 0000000..537576c --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/ContactUs.java @@ -0,0 +1,53 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.Message; +import com.javarush.goncharov.model.Topic; +import com.javarush.goncharov.repository.MessageRepository; +import com.javarush.goncharov.repository.Storage; +import com.javarush.goncharov.service.MessageService; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import java.io.IOException; + +@WebServlet("/contact") +public class ContactUs extends DefaultServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + req.getRequestDispatcher("/WEB-INF/contact.jsp").forward(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + HttpSession session = req.getSession(); + if (req.getParameter("name").isEmpty() || + req.getParameter("email").isEmpty() || + req.getParameter("message").isEmpty()){ + session.setAttribute("alertType", "danger"); + session.setAttribute("alertMessage", + "Не заполнены все обязательные поля, попробуйте снова!"); + resp.sendRedirect("/contact"); + return; + } + String name = req.getParameter("name"); + Message message = Message.builder() + .name(req.getParameter("name")) + .email(req.getParameter("email")) + .message(req.getParameter("message")) + .topic(Topic.valueOf(req.getParameter("topic"))) + .Completed(false) + .build(); + messageService.post(message); + session.setAttribute("alertType", "success"); + session.setAttribute("alertMessage", + "Спасибо, " + name + "! Ваше сообщение успешно отправлено."); + resp.sendRedirect("/contact"); + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/CreateGame.java b/src/main/java/com/javarush/goncharov/controller/CreateGame.java new file mode 100644 index 0000000..5d0af1b --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/CreateGame.java @@ -0,0 +1,31 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.User; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import java.io.IOException; +import java.util.Optional; + +@WebServlet("/create-quest") +public class CreateGame extends DefaultServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + req.getRequestDispatcher("/WEB-INF/create-quest.jsp").forward(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + HttpSession session = req.getSession(); + User userSession = (User) session.getAttribute("user"); + Optional userFind = userService.get(userSession.getId()); + String name = req.getParameter("name"); + String text = req.getParameter("text"); + questService.create(name, text, userFind.get().getId(), userFind.get().getLogin()); + resp.sendRedirect("/list-quests"); + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/DefaultServlet.java b/src/main/java/com/javarush/goncharov/controller/DefaultServlet.java new file mode 100644 index 0000000..914d498 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/DefaultServlet.java @@ -0,0 +1,41 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.Topic; +import com.javarush.goncharov.repository.AnswerRepository; +import com.javarush.goncharov.service.*; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.experimental.FieldDefaults; + +@Getter +@FieldDefaults(level = AccessLevel.PROTECTED) +public class DefaultServlet extends HttpServlet { + UserService userService; + MessageService messageService; + QuestService questService; + QuestionService questionService; + GameService gameService; + AnswerRepository answerRepository; + StatisticService statisticService; + Topic topics; + + @Override + public void init() throws ServletException { + super.init(); + initializeSpecificServices(); + } + + protected void initializeSpecificServices(){ + ServletContext servletContext = getServletContext(); + messageService = (MessageService) servletContext.getAttribute("messageService"); + userService = (UserService) servletContext.getAttribute("userService"); + questService = (QuestService) servletContext.getAttribute("questService"); + questionService = (QuestionService) servletContext.getAttribute("questionService"); + gameService = (GameService) servletContext.getAttribute("gameService"); + answerRepository = (AnswerRepository) servletContext.getAttribute("answerRepository"); + statisticService = (StatisticService) servletContext.getAttribute("statisticService"); + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/DeleteQuest.java b/src/main/java/com/javarush/goncharov/controller/DeleteQuest.java new file mode 100644 index 0000000..ec8ecbb --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/DeleteQuest.java @@ -0,0 +1,31 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.Quest; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; +import java.util.Optional; + +@WebServlet("/delete-quest") +public class DeleteQuest extends DefaultServlet { + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + Long idQuest = Long.parseLong(req.getParameter("id")); + Optional userFind = questService.get(idQuest); + if (req.getParameter("action").equals("delete")) { + userFind.ifPresent(questService::delete); + } + resp.sendRedirect("/list-quests"); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + Long idQuest = Long.parseLong(req.getParameter("id")); + questService.get(idQuest).ifPresent(quest -> req.setAttribute("quest", quest)); + req.getRequestDispatcher("/WEB-INF/delete-quest.jsp").forward(req, resp); + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/DeleteUser.java b/src/main/java/com/javarush/goncharov/controller/DeleteUser.java new file mode 100644 index 0000000..8fbca30 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/DeleteUser.java @@ -0,0 +1,35 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.User; +import com.javarush.goncharov.repository.Storage; +import com.javarush.goncharov.repository.UserRepository; +import com.javarush.goncharov.service.UserService; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; +import java.util.Optional; + +@WebServlet("/delete-user") +public class DeleteUser extends DefaultServlet { + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + Long idUser = Long.parseLong(req.getParameter("id")); + Optional userFind = userService.get(idUser); + if (req.getParameter("action").equals("delete")) { + userFind.ifPresent(userService::delete); + } + resp.sendRedirect("/list-users"); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + Long idUser = Long.parseLong(req.getParameter("id")); + userService.get(idUser).ifPresent(user -> req.setAttribute("user", user)); + req.getRequestDispatcher("/WEB-INF/delete-user.jsp").forward(req, resp); + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/EditUser.java b/src/main/java/com/javarush/goncharov/controller/EditUser.java new file mode 100644 index 0000000..fcfbb4c --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/EditUser.java @@ -0,0 +1,60 @@ +package com.javarush.goncharov.controller; + + +import com.javarush.goncharov.model.Role; +import com.javarush.goncharov.model.User; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import java.io.IOException; +import java.util.Optional; + +@WebServlet("/edit-user") +public class EditUser extends DefaultServlet { + private String role; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + Long idUser = Long.parseLong(req.getParameter("id")); + userService.get(idUser).ifPresent(user -> req.setAttribute("user", user)); + req.getRequestDispatcher("/WEB-INF/edit-user.jsp").forward(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + HttpSession session = req.getSession(); + User userSession = (User) session.getAttribute("user"); + Long idUser = Long.parseLong(req.getParameter("id")); + Optional userFind = userService.get(idUser); + if (req.getParameter("action").equals("cancel")) { + if (userSession.getLogin().equals(userFind.get().getLogin())) { + resp.sendRedirect("/profile"); + return; + } else if (userSession.getRole().name().equals("ADMIN")) { + resp.sendRedirect("/list-users"); + return; + } + } + if (userFind.isPresent() && req.getParameter("role") == null) { + role = userFind.get().getRole().toString(); + } else { + role = req.getParameter("role"); + } + User user = User.builder() + .id(idUser) + .login(req.getParameter("login")) + .password(req.getParameter("password")) + .role(Role.valueOf(role)) + .email(req.getParameter("email")) + .build(); + userService.update(user); + if (userSession.getLogin().equals(userFind.get().getLogin())) { + resp.sendRedirect("/profile"); + } else { + resp.sendRedirect("/list-users"); + } + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/ImageController.java b/src/main/java/com/javarush/goncharov/controller/ImageController.java new file mode 100644 index 0000000..3fbd118 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/ImageController.java @@ -0,0 +1,28 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.service.ImageService; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.SneakyThrows; + +import java.nio.file.Files; +import java.nio.file.Path; + +@WebServlet("/images/*") +public class ImageController extends HttpServlet { + + + private final ImageService imageService = new ImageService(); + + @Override + @SneakyThrows + protected void doGet(HttpServletRequest req, HttpServletResponse resp) { + String requestURI = req.getRequestURI(); // /images/qa, /images/analytic, /images/developer, /images/architector это прописано в jsp в src до каждой картинки + String target = req.getContextPath() + "/images/"; // /images/ + String nameImage = requestURI.replace(target, ""); // qa + Path path = imageService.getImagePath(nameImage); // "C:\Users\Puh\IdeaProjects\ProjectPantera_3Module\target\project-Pantera-1.0-SNAPSHOT\WEB-INF\images\qa.jpg" + Files.copy(path, resp.getOutputStream()); + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/ListQuests.java b/src/main/java/com/javarush/goncharov/controller/ListQuests.java new file mode 100644 index 0000000..dda777a --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/ListQuests.java @@ -0,0 +1,30 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.Quest; +import com.javarush.goncharov.model.User; +import com.javarush.goncharov.repository.QuestRepository; +import com.javarush.goncharov.repository.Storage; +import com.javarush.goncharov.service.QuestService; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import java.io.IOException; +import java.util.Collection; + +@WebServlet("/list-quests") +public class ListQuests extends DefaultServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + Collection quests = questService.getAll().values(); + HttpSession session = req.getSession(); + User user = (User) session.getAttribute("user"); + req.setAttribute("quests", quests); + req.setAttribute("user", user); + req.getRequestDispatcher("/WEB-INF/home.jsp").forward(req, resp); + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/ListUsers.java b/src/main/java/com/javarush/goncharov/controller/ListUsers.java new file mode 100644 index 0000000..0442989 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/ListUsers.java @@ -0,0 +1,29 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.User; +import com.javarush.goncharov.repository.Storage; +import com.javarush.goncharov.repository.UserRepository; +import com.javarush.goncharov.service.UserService; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import java.io.IOException; +import java.util.Collection; + +@WebServlet("/list-users") +public class ListUsers extends DefaultServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + Collection users = userService.getAll().values(); + HttpSession session = req.getSession(); + User user = (User) session.getAttribute("user"); + req.setAttribute("users", users); + req.setAttribute("user", user); + req.getRequestDispatcher("/WEB-INF/list-user.jsp").forward(req, resp); + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/Login.java b/src/main/java/com/javarush/goncharov/controller/Login.java new file mode 100644 index 0000000..0519bdb --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/Login.java @@ -0,0 +1,39 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.User; +import com.javarush.goncharov.repository.Storage; +import com.javarush.goncharov.repository.UserRepository; +import com.javarush.goncharov.service.UserService; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import java.io.IOException; +import java.util.Optional; + +@WebServlet("/login") +public class Login extends DefaultServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + req.getRequestDispatcher("/WEB-INF/login.jsp").forward(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + String login = req.getParameter("login"); + String password = req.getParameter("password"); + Optional user = userService.find(login, password); + if (user.isPresent()){ + HttpSession session = req.getSession(); + session.setAttribute("user", user.get()); + req.setAttribute("user", user.get()); + resp.sendRedirect("/"); + } else { + resp.sendRedirect("/login"); + } + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/Logout.java b/src/main/java/com/javarush/goncharov/controller/Logout.java new file mode 100644 index 0000000..4fe73f6 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/Logout.java @@ -0,0 +1,20 @@ +package com.javarush.goncharov.controller; + +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import java.io.IOException; + +@WebServlet("/logout") +public class Logout extends DefaultServlet { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + HttpSession session = req.getSession(); + session.invalidate(); + req.getRequestDispatcher("/WEB-INF/login.jsp").forward(req, resp); + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/Messages.java b/src/main/java/com/javarush/goncharov/controller/Messages.java new file mode 100644 index 0000000..723ac13 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/Messages.java @@ -0,0 +1,45 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.Message; +import com.javarush.goncharov.model.Topic; +import com.javarush.goncharov.model.User; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import java.io.IOException; +import java.util.Collection; +import java.util.Optional; + +@WebServlet("/messages") +public class Messages extends DefaultServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + Collection messages = messageService.getAll().values(); + HttpSession session = req.getSession(); + User user = (User) session.getAttribute("user"); + req.setAttribute("messages", messages); + req.setAttribute("user", user); + req.getRequestDispatcher("/WEB-INF/messages.jsp").forward(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + if (req.getParameter("action").equals("GoArchive")) { + resp.sendRedirect("/completed-messages"); + return; + } + Long idMessage = Long.parseLong(req.getParameter("id")); + Optional message = messageService.get(idMessage); + String rememberMe = req.getParameter("rememberMe"); + if (rememberMe != null && (rememberMe.equals("on") || rememberMe.equals("off"))) { + message.ifPresent(value -> value.setCompleted(true)); + } + message.ifPresent(value -> value.setTopic(Topic.valueOf(req.getParameter("topic")))); + messageService.update(message.get()); + resp.sendRedirect("/messages"); + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/PlayGame.java b/src/main/java/com/javarush/goncharov/controller/PlayGame.java new file mode 100644 index 0000000..ea8169e --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/PlayGame.java @@ -0,0 +1,80 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.Game; +import com.javarush.goncharov.model.Question; +import com.javarush.goncharov.model.User; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import java.io.IOException; +import java.util.Optional; + +@WebServlet("/play-game") +public class PlayGame extends DefaultServlet { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + HttpSession session = req.getSession(); + Long questId = 0L; + User userSession = (User) session.getAttribute("user"); + if (req.getParameter("questId") != null){ + questId = Long.parseLong(req.getParameter("questId")); + } else { + questId = (Long)session.getAttribute("questId"); + } + Optional user = userService.get(userSession.getId()); + if (user.isPresent()) { + Optional game = gameService.getGame(questId, userSession.getId()); + if (game.isPresent()) { + showOneQuestion(req, game.get()); + req.getRequestDispatcher("/WEB-INF/play-game.jsp").forward(req, resp); + return; + } else { + String message = "Нет незавершенной игры"; + req.getRequestDispatcher("/WEB-INF/home.jsp").forward(req, resp); + return; + } + } else { + String message = "Сначала нужно войти в аккаунт"; + req.getRequestDispatcher("/WEB-INF/login.jsp").forward(req, resp); + return; + } + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + HttpSession session = req.getSession(); + Long gameId = Long.parseLong(req.getParameter("id")); + Long answerId = 0L; + String answerIdStr = req.getParameter("answer"); + if (answerIdStr != null){ + answerId = Long.parseLong(req.getParameter("answer")); + } + Optional game = gameService.processOneStep(gameId, answerId); + if (game.isPresent()) { + if (answerId == 0 && req.getParameter("game") != null) { + session.setAttribute("alertType", "danger"); + session.setAttribute("alertMessage", + "Нужно выбрать какой-то ответ!"); + session.setAttribute("questId", game.get().getQuestId()); + resp.sendRedirect("/play-game"); + return; + } + Game currentGame = game.get(); + resp.sendRedirect("/play-game?questId=%d&id=%d".formatted(game.get().getQuestId(), game.get().getId())); + return; + } else { + String message = "Нет такой игры"; + resp.sendRedirect("/list-quests"); + return; + } + } + + private void showOneQuestion(HttpServletRequest request, Game game) { + request.setAttribute("game", game); + Optional question = questionService.get(game.getCurrentQuestionId()); + request.setAttribute("question", question.orElseThrow()); + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/Profile.java b/src/main/java/com/javarush/goncharov/controller/Profile.java new file mode 100644 index 0000000..0bbb572 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/Profile.java @@ -0,0 +1,38 @@ +package com.javarush.goncharov.controller; + + +import com.javarush.goncharov.model.User; +import com.javarush.goncharov.repository.Storage; +import com.javarush.goncharov.repository.UserRepository; +import com.javarush.goncharov.service.UserService; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import java.io.IOException; + +@WebServlet("/profile") +public class Profile extends DefaultServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + req.getRequestDispatcher("/WEB-INF/profile.jsp").forward(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + HttpSession session = req.getSession(); + User user = (User) session.getAttribute("user"); + if (req.getParameter("action").equals("edit")) { + resp.sendRedirect("/edit-user" + "?id=" + user.getId()); + } else if (req.getParameter("action").equals("delete")) { + userService.delete(user); + resp.sendRedirect("/logout"); + } else { + resp.sendRedirect("/logout"); + } + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/SignUp.java b/src/main/java/com/javarush/goncharov/controller/SignUp.java new file mode 100644 index 0000000..59698c6 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/SignUp.java @@ -0,0 +1,40 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.Role; +import com.javarush.goncharov.model.User; +import com.javarush.goncharov.repository.Storage; +import com.javarush.goncharov.repository.UserRepository; +import com.javarush.goncharov.service.UserService; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import java.io.IOException; + + +@WebServlet("/signup") +public class SignUp extends DefaultServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + req.getRequestDispatcher("/WEB-INF/signup.jsp").forward(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + User user = User.builder() + .login(req.getParameter("login")) + .password(req.getParameter("password")) + .role(Role.USER) + .email("test@test.ru") + .build(); + userService.post(user); + HttpSession session = req.getSession(); + session.setAttribute("user", user); + req.setAttribute("user", user); + resp.sendRedirect("/"); + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/StartPage.java b/src/main/java/com/javarush/goncharov/controller/StartPage.java new file mode 100644 index 0000000..853a233 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/StartPage.java @@ -0,0 +1,21 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.Role; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; + +@WebServlet("/") +public class StartPage extends DefaultServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + req.getRequestDispatcher("/WEB-INF/home_new.jsp").forward(req, resp); + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/Statistics.java b/src/main/java/com/javarush/goncharov/controller/Statistics.java new file mode 100644 index 0000000..199ce60 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/Statistics.java @@ -0,0 +1,22 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.User; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; + +import java.io.IOException; + +@WebServlet("/statistics") +public class Statistics extends DefaultServlet { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + HttpSession session = req.getSession(); + User userSession = (User) session.getAttribute("user"); + req.setAttribute("userStatistics", statisticService.getUserStat(userSession)); + req.setAttribute("usersStatistics", statisticService.getAllUserStat()); + req.getRequestDispatcher("/WEB-INF/statistics.jsp").forward(req, resp); + } +} diff --git a/src/main/java/com/javarush/goncharov/controller/TeamController.java b/src/main/java/com/javarush/goncharov/controller/TeamController.java new file mode 100644 index 0000000..b9145f4 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/controller/TeamController.java @@ -0,0 +1,17 @@ +package com.javarush.goncharov.controller; + +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; + +@WebServlet("/our-team") +public class TeamController extends DefaultServlet { + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + req.getRequestDispatcher("/WEB-INF/our-team.jsp").forward(req, resp); + } +} diff --git a/src/main/java/com/javarush/goncharov/exception/AppException.java b/src/main/java/com/javarush/goncharov/exception/AppException.java new file mode 100644 index 0000000..d6bc0a2 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/exception/AppException.java @@ -0,0 +1,19 @@ +package com.javarush.goncharov.exception; + +public class AppException extends RuntimeException { + + public AppException() { + } + + public AppException(String message) { + super(message); + } + + public AppException(String message, Throwable cause) { + super(message, cause); + } + + public AppException(Throwable cause) { + super(cause); + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/goncharov/model/Answer.java b/src/main/java/com/javarush/goncharov/model/Answer.java new file mode 100644 index 0000000..3bf9bbd --- /dev/null +++ b/src/main/java/com/javarush/goncharov/model/Answer.java @@ -0,0 +1,17 @@ +package com.javarush.goncharov.model; + +import lombok.*; +import lombok.experimental.FieldDefaults; + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Builder +@FieldDefaults(level = AccessLevel.PRIVATE) +public class Answer { + Long id; + Long questionId; + String text; + String questName; + Long nextQuestionId; +} diff --git a/src/main/java/com/javarush/goncharov/model/Game.java b/src/main/java/com/javarush/goncharov/model/Game.java new file mode 100644 index 0000000..e7f1260 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/model/Game.java @@ -0,0 +1,19 @@ +package com.javarush.goncharov.model; + +import lombok.*; +import lombok.experimental.FieldDefaults; + +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +public class Game { + Long id; + Long questId; + String questName; + Long userId; + String userName; + Long currentQuestionId; + GameState gameState; +} diff --git a/src/main/java/com/javarush/goncharov/model/GameState.java b/src/main/java/com/javarush/goncharov/model/GameState.java new file mode 100644 index 0000000..92c12e8 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/model/GameState.java @@ -0,0 +1,5 @@ +package com.javarush.goncharov.model; + +public enum GameState { + WIN, LOSE, PLAY +} diff --git a/src/main/java/com/javarush/goncharov/model/Message.java b/src/main/java/com/javarush/goncharov/model/Message.java new file mode 100644 index 0000000..0bd3df5 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/model/Message.java @@ -0,0 +1,18 @@ +package com.javarush.goncharov.model; + +import lombok.*; +import lombok.experimental.FieldDefaults; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@FieldDefaults(level = AccessLevel.PRIVATE) +public class Message{ + Long id; + String name; + String email; + Topic topic; + String message; + Boolean Completed; +} diff --git a/src/main/java/com/javarush/goncharov/model/Quest.java b/src/main/java/com/javarush/goncharov/model/Quest.java new file mode 100644 index 0000000..a7706bd --- /dev/null +++ b/src/main/java/com/javarush/goncharov/model/Quest.java @@ -0,0 +1,22 @@ +package com.javarush.goncharov.model; + +import lombok.*; +import lombok.experimental.FieldDefaults; + +import java.util.ArrayList; +import java.util.Collection; + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Builder +@FieldDefaults(level = AccessLevel.PRIVATE) +public class Quest{ + Long id; + String name; + String authorName; + String text; + Long developerId; + Long startQuestionId; + final Collection questions = new ArrayList<>(); +} diff --git a/src/main/java/com/javarush/goncharov/model/Question.java b/src/main/java/com/javarush/goncharov/model/Question.java new file mode 100644 index 0000000..c257520 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/model/Question.java @@ -0,0 +1,21 @@ +package com.javarush.goncharov.model; + +import java.util.ArrayList; +import java.util.Collection; + +import lombok.*; +import lombok.experimental.FieldDefaults; + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Builder +@FieldDefaults(level = AccessLevel.PRIVATE) +public class Question { + Long id; + Long questId; + String questName; + String text; + GameState gameState; + final Collection answers = new ArrayList<>(); +} diff --git a/src/main/java/com/javarush/goncharov/model/Role.java b/src/main/java/com/javarush/goncharov/model/Role.java new file mode 100644 index 0000000..34eb786 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/model/Role.java @@ -0,0 +1,9 @@ +package com.javarush.goncharov.model; + +public enum Role { + USER, + ADMIN, + MODERATOR, + GAMEDEV, + GUEST +} diff --git a/src/main/java/com/javarush/goncharov/model/Statistic.java b/src/main/java/com/javarush/goncharov/model/Statistic.java new file mode 100644 index 0000000..4322443 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/model/Statistic.java @@ -0,0 +1,17 @@ +package com.javarush.goncharov.model; + +import lombok.*; +import lombok.experimental.FieldDefaults; + +@NoArgsConstructor +@AllArgsConstructor +@Data +@Builder +@FieldDefaults(level = AccessLevel.PRIVATE) +public class Statistic { + String login; + long win; + long lost; + long play; + long total; +} diff --git a/src/main/java/com/javarush/goncharov/model/Topic.java b/src/main/java/com/javarush/goncharov/model/Topic.java new file mode 100644 index 0000000..3ca8748 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/model/Topic.java @@ -0,0 +1,9 @@ +package com.javarush.goncharov.model; + +public enum Topic { + EDUCATION, + TRAVEL, + FOOD, + SPORTS, + COMMUNITY; +} diff --git a/src/main/java/com/javarush/goncharov/model/User.java b/src/main/java/com/javarush/goncharov/model/User.java new file mode 100644 index 0000000..a760993 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/model/User.java @@ -0,0 +1,22 @@ +package com.javarush.goncharov.model; + +import lombok.*; +import lombok.experimental.FieldDefaults; + +import java.util.ArrayList; +import java.util.Collection; + +@NoArgsConstructor +@AllArgsConstructor +@Data +@Builder +@FieldDefaults(level = AccessLevel.PRIVATE) +public class User{ + Long id; + String login; + String password; + Role role; + String email; + final Collection quests = new ArrayList<>(); + final Collection games = new ArrayList<>(); +} diff --git a/src/main/java/com/javarush/goncharov/repository/AnswerRepository.java b/src/main/java/com/javarush/goncharov/repository/AnswerRepository.java new file mode 100644 index 0000000..b5a5bdc --- /dev/null +++ b/src/main/java/com/javarush/goncharov/repository/AnswerRepository.java @@ -0,0 +1,57 @@ +package com.javarush.goncharov.repository; + +import com.javarush.goncharov.model.Answer; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicLong; + +public class AnswerRepository implements Repository{ + private final Map map; + public static final AtomicLong id = new AtomicLong(); + + public AnswerRepository(Storage answerStorage) { + this.map = answerStorage.getAnswers(); + } + + @Override + public Optional get(long id) { + return Optional.ofNullable(map.get(id)); + } + + @Override + public Optional findBy(String questName, String text) { + return map.values() + .stream() + .filter(u -> u.getQuestName().equals(questName)) + .filter(u -> u.getText().equals(text)) + .findAny(); + } + + @Override + public Map getAll() { + return map; + } + + @Override + public Optional create(Answer answer) { + answer.setId(id.incrementAndGet()); + update(answer); + return Optional.of(answer); + } + + @Override + public Boolean delete(Answer answer) { + int sizeBeforeDelete = map.size(); + map.remove(answer.getId()); + int sizeAfterDelete = map.size(); + return sizeBeforeDelete > sizeAfterDelete ? Boolean.TRUE : Boolean.FALSE; + } + + @Override + public Optional update(Answer answer) { + map.put(answer.getId(), answer); + return Optional.of(answer); + } +} + diff --git a/src/main/java/com/javarush/goncharov/repository/GameRepository.java b/src/main/java/com/javarush/goncharov/repository/GameRepository.java new file mode 100644 index 0000000..de3c3c0 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/repository/GameRepository.java @@ -0,0 +1,69 @@ +package com.javarush.goncharov.repository; + +import com.javarush.goncharov.model.Game; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Stream; + +public class GameRepository implements Repository{ + private final Map map; + public static final AtomicLong id = new AtomicLong(); + + public GameRepository(Storage gameStorage) { + this.map = gameStorage.getGames(); + } + + @Override + public Optional get(long id) { + return Optional.ofNullable(map.get(id)); + } + + @Override + public Optional findBy(String questName, String userName) { + return map.values() + .stream() + .filter(u -> u.getQuestName().equals(questName)) + .filter(u -> u.getUserName().equals(userName)) + .findAny(); + } + + @Override + public Map getAll() { + return map; + } + + public Stream findByQuestId(Long pattern) { + return map.values() + .stream() + .filter(u -> u.getQuestId().equals(pattern)); + } + + public Stream findByUserId(Long pattern) { + return map.values() + .stream() + .filter(u -> u.getUserId().equals(pattern)); + } + + @Override + public Optional create(Game game) { + game.setId(id.incrementAndGet()); + update(game); + return Optional.of(game); + } + + @Override + public Boolean delete(Game game) { + int sizeBeforeDelete = map.size(); + map.remove(game.getId()); + int sizeAfterDelete = map.size(); + return sizeBeforeDelete > sizeAfterDelete ? Boolean.TRUE : Boolean.FALSE; + } + + @Override + public Optional update(Game game) { + map.put(game.getId(), game); + return Optional.of(game); + } +} diff --git a/src/main/java/com/javarush/goncharov/repository/MessageRepository.java b/src/main/java/com/javarush/goncharov/repository/MessageRepository.java new file mode 100644 index 0000000..f1b0901 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/repository/MessageRepository.java @@ -0,0 +1,60 @@ +package com.javarush.goncharov.repository; + +import com.javarush.goncharov.model.Message; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicLong; + +public class MessageRepository implements Repository{ + private final Map map; + public static final AtomicLong id = new AtomicLong(); + + public MessageRepository(Storage messageStorage) { + this.map = messageStorage.getMessages(); + } + + @Override + public Optional get(long id) { + return Optional.ofNullable(map.get(id)); + } + + @Override + public Optional findBy(String name, String email) { + return map.values() + .stream() + .filter(u -> u.getName().equals(name)) + .filter(u -> u.getEmail().equals(email)) + .findAny(); + } + + @Override + public Map getAll() { + return map; + } + + @Override + public Optional create(Message message) { + if (!map.containsKey(message.getId())) { + message.setId(id.incrementAndGet()); + } + map.put(message.getId(), message); + return Optional.of(message); + } + + @Override + public Boolean delete(Message message) { + int sizeBeforeDelete = map.size(); + map.remove(message.getId()); + int sizeAfterDelete = map.size(); + return sizeBeforeDelete > sizeAfterDelete ? Boolean.TRUE : Boolean.FALSE; + } + + @Override + public Optional update(Message message) { + message.setName(message.getName()); + message.setEmail(message.getEmail()); + message.setMessage(message.getMessage()); + return Optional.of(message); + } +} diff --git a/src/main/java/com/javarush/goncharov/repository/QuestRepository.java b/src/main/java/com/javarush/goncharov/repository/QuestRepository.java new file mode 100644 index 0000000..b7a369f --- /dev/null +++ b/src/main/java/com/javarush/goncharov/repository/QuestRepository.java @@ -0,0 +1,56 @@ +package com.javarush.goncharov.repository; + +import com.javarush.goncharov.model.Quest; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicLong; + +public class QuestRepository implements Repository{ + private final Map map; + public static final AtomicLong id = new AtomicLong(); + + public QuestRepository(Storage questStorage) { + this.map = questStorage.getQuests(); + } + + @Override + public Optional get(long id) { + return Optional.ofNullable(map.get(id)); + } + + @Override + public Optional findBy(String name, String authorName) { + return map.values() + .stream() + .filter(u -> u.getName().equals(name)) + .filter(u -> u.getAuthorName().equals(authorName)) + .findAny(); + } + + @Override + public Map getAll() { + return map; + } + + @Override + public Optional create(Quest quest) { + quest.setId(id.incrementAndGet()); + update(quest); + return Optional.of(quest); + } + + @Override + public Boolean delete(Quest quest) { + int sizeBeforeDelete = map.size(); + map.remove(quest.getId()); + int sizeAfterDelete = map.size(); + return sizeBeforeDelete > sizeAfterDelete ? Boolean.TRUE : Boolean.FALSE; + } + + @Override + public Optional update(Quest quest) { + map.put(quest.getId(), quest); + return Optional.of(quest); + } +} diff --git a/src/main/java/com/javarush/goncharov/repository/QuestionRepository.java b/src/main/java/com/javarush/goncharov/repository/QuestionRepository.java new file mode 100644 index 0000000..2e9e316 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/repository/QuestionRepository.java @@ -0,0 +1,56 @@ +package com.javarush.goncharov.repository; + +import com.javarush.goncharov.model.Question; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicLong; + +public class QuestionRepository implements Repository{ + private final Map map; + public static final AtomicLong id = new AtomicLong(); + + public QuestionRepository(Storage questionStorage) { + this.map = questionStorage.getQuestions(); + } + + @Override + public Optional get(long id) { + return Optional.ofNullable(map.get(id)); + } + + @Override + public Optional findBy(String questName, String text) { + return map.values() + .stream() + .filter(u -> u.getQuestName().equals(questName)) + .filter(u -> u.getText().equals(text)) + .findAny(); + } + + @Override + public Map getAll() { + return map; + } + + @Override + public Optional create(Question question) { + question.setId(id.incrementAndGet()); + update(question); + return Optional.of(question); + } + + @Override + public Boolean delete(Question question) { + int sizeBeforeDelete = map.size(); + map.remove(question.getId()); + int sizeAfterDelete = map.size(); + return sizeBeforeDelete > sizeAfterDelete ? Boolean.TRUE : Boolean.FALSE; + } + + @Override + public Optional update(Question question) { + map.put(question.getId(), question); + return Optional.of(question); + } +} diff --git a/src/main/java/com/javarush/goncharov/repository/Repository.java b/src/main/java/com/javarush/goncharov/repository/Repository.java new file mode 100644 index 0000000..c8ee391 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/repository/Repository.java @@ -0,0 +1,19 @@ +package com.javarush.goncharov.repository; + +import java.util.Map; +import java.util.Optional; + +public interface Repository { + + Optional get(long id); + + Optional findBy(String value1, String valiue2); + + Map getAll(); + + Optional create(T entity); + + Optional update(T entity); + + Boolean delete(T entity); +} diff --git a/src/main/java/com/javarush/goncharov/repository/Storage.java b/src/main/java/com/javarush/goncharov/repository/Storage.java new file mode 100644 index 0000000..838a146 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/repository/Storage.java @@ -0,0 +1,42 @@ +package com.javarush.goncharov.repository; + +import com.javarush.goncharov.model.*; +import lombok.Getter; + +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; + +@Getter +public class Storage { + private static Storage instance; + private final Map users = new ConcurrentHashMap<>(); + private final Map messages = new ConcurrentHashMap<>(); + private final Map quests = new ConcurrentHashMap<>(); + private final Map questions = new ConcurrentHashMap<>(); + private final Map answers = new ConcurrentHashMap<>(); + private final Map games = new ConcurrentHashMap<>(); +// private final Map games = new TreeMap<>(); + + private Storage() { + users.put(1L, new User(1L, "Admin", "123", Role.ADMIN, "admin@test.ru")); + users.put(2L, new User(2L, "Dima", "123", Role.MODERATOR, "dima@test.ru")); + users.put(3L, new User(3L, "Lex", "123", Role.GAMEDEV, "lexus@test.ru")); + messages.put(1L, new Message(1L, "Дмитрий Гончаров", "dimagoncharov21@gmail.com", + Topic.EDUCATION, "1 Клиент-серверная архитектура На заре появления интернета распространение получила клиент-серверная архитектура, хотя существовали и другие. Смысл ее заключается в том, что все участники сети делятся на две логические части: клиент и сервер. Задача сервера (server, от serve — служить) — обслуживать запросы клиентов. Сервер делает большую часть работы, хранит все нужные данные и следит за их целостностью. И хотя есть компьютеры, которые называют серверы, обычно под понятиями “клиент” и “сервер” подразумевается ПО. Задача клиента — жить в свое удовольствие. Когда клиенту нужны какие-нибудь данные от сервера, он отправляет ему запрос. Через некоторое время он получает ответ от сервера и может делать с полученными данными что-то важное. Инициатором запросов всегда выступает клиент. Режим общения всегда проходит в виде запрос-ответ. Это в каком-то смысле синоним понятия “клиент-сервер”. А какие же бывают альтернативы? Ну, во-первых, одноранговые сети, где все участники равны (их еще называют peer-to-peer сетями). Если вы со своим другом переписывайтесь в чате или с помощью СМС, то это как раз пример одноранговой сети. В чем же отличие? Вы можете написать сообщение и не получить на него ответа, а затем отправить новое, и так далее. Ваш друг может быть инициатором диалога. Любая из сторон может написать первой. Вся информация о диалоге храниться у обеих сторон, никто не обязан отвечать.", false)); + messages.put(2L, new Message(2L, "Дмитрий Гончаров", "dimagoncharov21@gmail.com", + Topic.SPORTS, "Преимущества клиент-серверной архитектуры:\n" + + "Надежность. Клиенты могут находиться где угодно, даже на ненадежных платформах. Windows на вашем компьютере может “слететь”, iPhone могут украсть, а данные, которые хранятся в облаке, никуда не денутся.\n" + + "\n" + + "Слабые и дешевые клиенты. Если вам нужно сделать монтаж видео на телефоне, то вы загружаете его на сервер и выполняете на серверных мощностях. Клиент может быть дешевым инструментом.\n" + + "\n" + + "Сбалансированная нагрузка. Каждый клиент имеет индивидуальный график использования, который может быть очень скачкообразным. На сервер приходят запросы от тысяч клиентов, его нагрузка усредняется и поэтому лучше прогнозируема.", false)); + } + + public static Storage getInstance() { + if (instance == null) { + instance = new Storage(); + } + return instance; + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/goncharov/repository/UserRepository.java b/src/main/java/com/javarush/goncharov/repository/UserRepository.java new file mode 100644 index 0000000..50869c7 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/repository/UserRepository.java @@ -0,0 +1,62 @@ +package com.javarush.goncharov.repository; + +import com.javarush.goncharov.model.User; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicLong; + +public class UserRepository implements Repository{ + + private final Map map; + public static final AtomicLong id = new AtomicLong(2); + + public UserRepository(Storage userStorage) { + this.map = userStorage.getUsers(); + } + + @Override + public Optional get(long id) { + return Optional.ofNullable(map.get(id)); + } + + @Override + public Optional findBy(String login, String password) { + return map.values() + .stream() + .filter(u -> u.getLogin().equals(login)) + .filter(u -> u.getPassword().equals(password)) + .findAny(); + } + + @Override + public Map getAll() { + return map; + } + + @Override + public Optional create(User user) { + if (!map.containsKey(user.getId())) { + user.setId(id.incrementAndGet()); + } + map.put(user.getId(), user); + return Optional.of(user); + } + + @Override + public Boolean delete(User user) { + int sizeBeforeDelete = map.size(); + map.remove(user.getId()); + int sizeAfterDelete = map.size(); + return sizeBeforeDelete > sizeAfterDelete ? Boolean.TRUE : Boolean.FALSE; + } + + @Override + public Optional update(User user) { + map.get(user.getId()).setLogin(user.getLogin()); + map.get(user.getId()).setPassword(user.getPassword()); + map.get(user.getId()).setRole(user.getRole()); + map.get(user.getId()).setEmail(user.getEmail()); + return Optional.of(user); + } +} diff --git a/src/main/java/com/javarush/goncharov/service/GameService.java b/src/main/java/com/javarush/goncharov/service/GameService.java new file mode 100644 index 0000000..b6960d1 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/service/GameService.java @@ -0,0 +1,105 @@ +package com.javarush.goncharov.service; + +import com.javarush.goncharov.model.*; +import com.javarush.goncharov.repository.*; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; + +import java.util.Comparator; +import java.util.Map; +import java.util.Optional; + +@FieldDefaults(level = AccessLevel.PRIVATE) +public class GameService { + final GameRepository gameRepository; + final QuestService questService; + final QuestionService questionService; + final AnswerRepository answerRepository; + final UserService userService; + + public GameService(GameRepository gameRepository, + QuestService questService, + QuestionService questionService, + UserService userService, + AnswerRepository answerRepository) { + this.gameRepository = gameRepository; + this.questService = questService; + this.questionService = questionService; + this.userService = userService; + this.answerRepository = answerRepository; + } + + public Optional get(Long id){ + return gameRepository.get(id); + } + + public Optional getGame(Long questId, Long userId) { + if (gameRepository.getAll().containsKey(questId)){ + Optional game = gameRepository.findByQuestId(questId).max(Comparator.comparingLong(Game::getId)); + if (game.isPresent() && + game.get().getUserId().equals(userId)){ + return game; + } + } + return getNewGame(questId, userId); + } + + private Optional getNewGame(Long questId, Long userId) { + User user = userService.get(userId).get(); + Quest quest = questService.get(questId).get(); + Long startQuestionId = quest.getStartQuestionId(); + Question firstQuestion = questionService.get(startQuestionId).get(); + Game newGame = Game.builder() + .questId(questId) + .questName(quest.getName()) + .currentQuestionId(startQuestionId) + .gameState(firstQuestion.getGameState()) + .userId(userId) + .userName(user.getLogin()) + .build(); + userService.get(userId).get().getGames().add(newGame); + gameRepository.create(newGame); + return Optional.of(newGame); + } + + public Optional find(String questName, String userName){ + return gameRepository.findBy(questName, userName); + } + + public void post(Game game){ + game.setId(0L); + gameRepository.create(game); + } + + public void delete(Game game){ + gameRepository.delete(game); + } + + public void update(Game game){ + gameRepository.update(game); + } + + public Map getAll(){ + return gameRepository.getAll(); + } + + public Optional processOneStep(Long gameId, Long answerId) { + Long nextQuestionId = 0L; + Game game = gameRepository.get(gameId).get(); + if (game.getGameState() == GameState.PLAY) { + if (answerRepository.get(answerId).isPresent()){ + Answer answer = answerRepository.get(answerId).get(); + nextQuestionId = answer.getNextQuestionId(); + } else { + nextQuestionId = game.getCurrentQuestionId(); + } + game.setCurrentQuestionId(nextQuestionId); + Question question = questionService.get(nextQuestionId).get(); + game.setGameState(question.getGameState()); + gameRepository.update(game); + } else { + game = getNewGame(game.getQuestId(), game.getUserId()).get(); + } + return Optional.ofNullable(game); + } +} diff --git a/src/main/java/com/javarush/goncharov/service/ImageService.java b/src/main/java/com/javarush/goncharov/service/ImageService.java new file mode 100644 index 0000000..ede774d --- /dev/null +++ b/src/main/java/com/javarush/goncharov/service/ImageService.java @@ -0,0 +1,46 @@ +package com.javarush.goncharov.service; + +import lombok.AccessLevel; +import lombok.SneakyThrows; +import lombok.experimental.FieldDefaults; + +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Objects; + +@FieldDefaults(level = AccessLevel.PRIVATE) +public class ImageService { + + static final String IMAGES_FOLDER = "images"; + static final String PART_NAME = "image"; + static final String NO_IMAGE_PNG = "no-image.png"; + static final List EXTENSIONS = List.of( + ".jpg", ".jpeg", ".png", ".bmp", ".gif", ".webp" + ); + + private final Path imagesFolder; + + @SneakyThrows + public ImageService() { + URL url = ImageService.class.getResource("/"); //"file:/C:/Users/Puh/IdeaProjects/ProjectPantera_3Module/target/project-Pantera-1.0-SNAPSHOT/WEB-INF/classes/" + Path startPath = Paths.get(Objects.requireNonNull(url).toURI()); + String webInf = "WEB-INF"; + Path webPath = startPath.getParent().endsWith(webInf) + ? startPath.getParent() //run in tomcat (webapp/WEB-INF) + : startPath.resolve(webInf); //embedded tomcat (resources/WEB-INF) + imagesFolder = webPath.resolve(IMAGES_FOLDER); + Files.createDirectories(imagesFolder); + } + + @SneakyThrows + public Path getImagePath(String filename) { + return EXTENSIONS.stream() + .map(ext -> imagesFolder.resolve(filename + ext))// resolve возвращает Path, преобразуем stream >> stream + .filter(Files::exists)// фильтруем результат + .findAny() // находим любое совпадение + .orElse(imagesFolder.resolve(NO_IMAGE_PNG)); // возврщаем найденное значение или если ничего неашлось то вернем no-image.png + } +} diff --git a/src/main/java/com/javarush/goncharov/service/MessageService.java b/src/main/java/com/javarush/goncharov/service/MessageService.java new file mode 100644 index 0000000..0ff8620 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/service/MessageService.java @@ -0,0 +1,43 @@ +package com.javarush.goncharov.service; + +import com.javarush.goncharov.model.Message; +import com.javarush.goncharov.repository.Repository; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; + +import java.util.Map; +import java.util.Optional; + +@FieldDefaults(level = AccessLevel.PRIVATE) +public class MessageService { + final Repository messageRepository; + + public MessageService(Repository messageRepository) { + this.messageRepository = messageRepository; + } + + public Optional get(Long id){ + return messageRepository.get(id); + } + + public Optional find(String name, String email){ + return messageRepository.findBy(name, email); + } + + public void post(Message message){ + message.setId(0L); + messageRepository.create(message); + } + + public void delete(Message message){ + messageRepository.delete(message); + } + + public void update(Message message){ + messageRepository.update(message); + } + + public Map getAll(){ + return messageRepository.getAll(); + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/goncharov/service/QuestService.java b/src/main/java/com/javarush/goncharov/service/QuestService.java new file mode 100644 index 0000000..e28622e --- /dev/null +++ b/src/main/java/com/javarush/goncharov/service/QuestService.java @@ -0,0 +1,127 @@ +package com.javarush.goncharov.service; + +import com.javarush.goncharov.model.*; +import com.javarush.goncharov.repository.*; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; + +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +@FieldDefaults(level = AccessLevel.PRIVATE) +public class QuestService { + final AnswerRepository answerRepository; + final QuestionService questionService; + final UserService userService; + final Repository questRepository; + + public QuestService(AnswerRepository answerRepository, QuestionService questionService, + UserService userService, + Repository questRepository) { + this.answerRepository = answerRepository; + this.questionService = questionService; + this.userService = userService; + this.questRepository = questRepository; + } + + public Optional get(Long id){ + return questRepository.get(id); + } + + public Optional find(String name, String authorName){ + return questRepository.findBy(name, authorName); + } + + public void create(String name, String text, Long idAuthor, String nameAuthor){ + Quest quest = Quest.builder() + .name(name) + .authorName(nameAuthor) + .text(text) + .developerId(idAuthor) + .startQuestionId(0L) + .build(); + questRepository.create(quest); + getQuestions(quest); + Optional userFind = userService.get(idAuthor); + Collection quests = userFind.get().getQuests(); + quests.add(quest); + getQuestions(quest); + questRepository.update(quest); + } + + private void getQuestions(Quest quest) { + Matcher matcher = getMatcher(quest); + Question question = new Question(); + while (matcher.find()) { + Long idQuestion = Long.parseLong(matcher.group(1)); + String symbolQuestion = matcher.group(2); + String text = matcher.group(3); + Optional newQuestion = extracted(quest, symbolQuestion, text, question, idQuestion); + if (newQuestion.isPresent()){ + question = newQuestion.get(); + question.setQuestId(quest.getId()); + question.setQuestName(quest.getName()); + questionService.post(question); + question.setId(idQuestion); + questionService.update(question); + quest.getQuestions().add(question); + if (question.getId().equals(1L)){ + quest.setStartQuestionId(question.getId()); + } + } + } + questRepository.update(quest); + } + + private Optional extracted(Quest quest, String symbolQuestion, String text, + Question question, Long idQuestion) { + question = switch (symbolQuestion) { + case ":" -> Question.builder() + .text(text) + .gameState(GameState.PLAY) + .build(); + case "+" -> Question.builder() + .text(text) + .gameState(GameState.WIN) + .build(); + case "-" -> Question.builder() + .text(text) + .gameState(GameState.LOSE) + .build(); + case "<" -> { + Answer answer = Answer.builder() + .questionId(question.getId()) + .nextQuestionId(idQuestion) + .text(text) + .questName(quest.getName()) + .build(); + answerRepository.create(answer); + question.getAnswers().add(answer); + yield null; + } + default -> throw new RuntimeException("incorrect parsing"); + }; + return Optional.ofNullable(question); + } + + private static Matcher getMatcher(Quest quest) { + String patternQ = "(\\d+)\\s*([:<\\-+])\\s*(.*)"; + Pattern pattern = Pattern.compile(patternQ); + return pattern.matcher(quest.getText()); + } + + public void delete(Quest quest){ + questRepository.delete(quest); + } + + public void update(Quest quest){ + questRepository.update(quest); + } + + public Map getAll(){ + return questRepository.getAll(); + } +} diff --git a/src/main/java/com/javarush/goncharov/service/QuestionService.java b/src/main/java/com/javarush/goncharov/service/QuestionService.java new file mode 100644 index 0000000..7eb9e9b --- /dev/null +++ b/src/main/java/com/javarush/goncharov/service/QuestionService.java @@ -0,0 +1,43 @@ +package com.javarush.goncharov.service; + +import com.javarush.goncharov.model.Question; +import com.javarush.goncharov.repository.Repository; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; + +import java.util.Map; +import java.util.Optional; + +@FieldDefaults(level = AccessLevel.PRIVATE) +public class QuestionService { + final Repository questionRepository; + + public QuestionService(Repository questionRepository) { + this.questionRepository = questionRepository; + } + + public Optional get(Long id){ + return questionRepository.get(id); + } + + public Optional find(String nameQuest, String text){ + return questionRepository.findBy(nameQuest, text); + } + + public void post(Question question){ + question.setId(0L); + questionRepository.create(question); + } + + public void delete(Question question){ + questionRepository.delete(question); + } + + public void update(Question question){ + questionRepository.update(question); + } + + public Map getAll(){ + return questionRepository.getAll(); + } +} diff --git a/src/main/java/com/javarush/goncharov/service/StatisticService.java b/src/main/java/com/javarush/goncharov/service/StatisticService.java new file mode 100644 index 0000000..3b8b8c7 --- /dev/null +++ b/src/main/java/com/javarush/goncharov/service/StatisticService.java @@ -0,0 +1,46 @@ +package com.javarush.goncharov.service; + +import com.javarush.goncharov.model.Game; +import com.javarush.goncharov.model.GameState; +import com.javarush.goncharov.model.Statistic; +import com.javarush.goncharov.model.User; +import com.javarush.goncharov.repository.GameRepository; +import com.javarush.goncharov.repository.UserRepository; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; + +import java.util.Collection; +import java.util.List; + +@FieldDefaults(level = AccessLevel.PRIVATE) +public class StatisticService { + final GameRepository gameRepository; + final UserRepository userRepository; + + public StatisticService(GameRepository gameRepository, UserRepository userRepository) { + this.gameRepository = gameRepository; + this.userRepository = userRepository; + } + + public Statistic getUserStat(User user) { + List games = gameRepository.findByUserId(user.getId()).toList(); + long win = games.stream().filter(game -> game.getGameState().equals(GameState.WIN)).count(); + long lose = games.stream().filter(game -> game.getGameState().equals(GameState.LOSE)).count(); + long play = games.stream().filter(game -> game.getGameState().equals(GameState.PLAY)).count(); + return Statistic.builder() + .login(user.getLogin()) + .win(win) + .lost(lose) + .play(play) + .total(win + lose + play) + .build(); + } + + public Collection getAllUserStat() { + return userRepository.getAll() + .values() + .stream() + .map(this::getUserStat) + .toList(); + } +} diff --git a/src/main/java/com/javarush/goncharov/service/UserService.java b/src/main/java/com/javarush/goncharov/service/UserService.java new file mode 100644 index 0000000..9df971b --- /dev/null +++ b/src/main/java/com/javarush/goncharov/service/UserService.java @@ -0,0 +1,46 @@ +package com.javarush.goncharov.service; + + +import com.javarush.goncharov.model.User; +import com.javarush.goncharov.repository.Repository; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; + +import java.util.Map; +import java.util.Optional; + +@FieldDefaults(level = AccessLevel.PRIVATE) +public class UserService { + final Repository userRepository; + + public UserService(Repository userRepository) { + this.userRepository = userRepository; + } + + public Optional get(Long id){ + return userRepository.get(id); + } + + public Optional find(String login, String password){ + return userRepository.findBy(login, password); + } + + public Optional post(User user){ + user.setId(0L); + userRepository.create(user); + return Optional.of(user); + } + + public Boolean delete(User user){ + return userRepository.delete(user); + } + + public Optional update(User user){ + userRepository.update(user); + return Optional.of(user); + } + + public Map getAll(){ + return userRepository.getAll(); + } +} diff --git a/src/main/java/com/javarush/khmelov/cmd/Command.java b/src/main/java/com/javarush/khmelov/cmd/Command.java deleted file mode 100644 index fd4035b..0000000 --- a/src/main/java/com/javarush/khmelov/cmd/Command.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.javarush.khmelov.cmd; - -import jakarta.servlet.http.HttpServletRequest; - -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public interface Command { - - default String doGet(HttpServletRequest request) { - return getView(); - } - - default String doPost(HttpServletRequest request) { - return getView(); - } - - default String getView() { - String simpleName = this.getClass().getSimpleName(); - return convertCamelCaseToKebabStyle(simpleName); - } - - private static String convertCamelCaseToKebabStyle(String string) { - String snakeName = string.chars() - .mapToObj(s -> String.valueOf((char) s)) - .flatMap(s -> s.matches("[A-Z]") - ? Stream.of("-", s) - : Stream.of(s)) - .collect(Collectors.joining()) - .toLowerCase(); - return snakeName.startsWith("-") - ? snakeName.substring(1) - : snakeName; - } - - -} diff --git a/src/main/java/com/javarush/khmelov/cmd/EditUser.java b/src/main/java/com/javarush/khmelov/cmd/EditUser.java deleted file mode 100644 index ae191b4..0000000 --- a/src/main/java/com/javarush/khmelov/cmd/EditUser.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.javarush.khmelov.cmd; - -import com.javarush.khmelov.entity.Role; -import com.javarush.khmelov.entity.User; -import com.javarush.khmelov.service.UserService; -import jakarta.servlet.http.HttpServletRequest; - -import java.util.Optional; - - -@SuppressWarnings("unused") -public class EditUser implements Command { - - private final UserService userService; - - public EditUser(UserService userService) { - this.userService = userService; - } - - - @Override - public String doGet(HttpServletRequest req) { - String stringId = req.getParameter("id"); - if (stringId != null) { - long id = Long.parseLong(stringId); - Optional optionalUser = userService.get(id); - if (optionalUser.isPresent()) { - User user = optionalUser.get(); - req.setAttribute("user", user); - } - } - return getView(); - } - - @Override - public String doPost(HttpServletRequest req) { - User user = User.builder() - .login(req.getParameter("login")) - .password(req.getParameter("password")) - .role(Role.valueOf(req.getParameter("role"))) - .build(); - if (req.getParameter("create") != null) { - userService.create(user); - } else if (req.getParameter("update") != null) { - user.setId(Long.parseLong(req.getParameter("id"))); - userService.update(user); - } - return getView() + "?id=" + user.getId(); - } - - -} \ No newline at end of file diff --git a/src/main/java/com/javarush/khmelov/cmd/ListUser.java b/src/main/java/com/javarush/khmelov/cmd/ListUser.java deleted file mode 100644 index 9257917..0000000 --- a/src/main/java/com/javarush/khmelov/cmd/ListUser.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.javarush.khmelov.cmd; - -import com.javarush.khmelov.entity.User; -import com.javarush.khmelov.service.UserService; -import jakarta.servlet.http.HttpServletRequest; - -import java.util.Collection; - -@SuppressWarnings("unused") -public class ListUser implements Command { - - private final UserService userService; - - public ListUser(UserService userService) { - this.userService = userService; - } - - @Override - public String doGet(HttpServletRequest request) { - Collection users = userService.getAll(); - request.setAttribute("users", users); - return getView(); - } - - -} \ No newline at end of file diff --git a/src/main/java/com/javarush/khmelov/cmd/StartPage.java b/src/main/java/com/javarush/khmelov/cmd/StartPage.java deleted file mode 100644 index d268f93..0000000 --- a/src/main/java/com/javarush/khmelov/cmd/StartPage.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.javarush.khmelov.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/khmelov/config/Winter.java deleted file mode 100644 index 48bd8a7..0000000 --- a/src/main/java/com/javarush/khmelov/config/Winter.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.javarush.khmelov.config; - -import lombok.SneakyThrows; - -import java.lang.reflect.Constructor; -import java.util.concurrent.ConcurrentHashMap; - -public class Winter { - - public static ConcurrentHashMap, Object> components = new ConcurrentHashMap<>(); - - - @SuppressWarnings("unchecked") - @SneakyThrows - public static T find(Class aClass) { - Object component = components.get(aClass); - if (component == null) { - Constructor constructor = aClass.getConstructors()[0]; - Class[] parameterTypes = constructor.getParameterTypes(); - Object[] parameters = new Object[parameterTypes.length]; - for (int i = 0; i < parameters.length; i++) { - parameters[i] = Winter.find(parameterTypes[i]); - } - Object newInstance = constructor.newInstance(parameters); - components.put(aClass, newInstance); - } - return (T) components.get(aClass); - } -} diff --git a/src/main/java/com/javarush/khmelov/controller/FrontController.java b/src/main/java/com/javarush/khmelov/controller/FrontController.java deleted file mode 100644 index 33242b2..0000000 --- a/src/main/java/com/javarush/khmelov/controller/FrontController.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.javarush.khmelov.controller; - -import com.javarush.khmelov.cmd.Command; -import com.javarush.khmelov.config.Winter; -import com.javarush.khmelov.entity.Role; -import jakarta.servlet.ServletConfig; -import jakarta.servlet.ServletException; -import jakarta.servlet.annotation.WebServlet; -import jakarta.servlet.http.HttpServlet; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - -import java.io.IOException; - -@WebServlet({"", "/home", "/list-user", "/edit-user"}) -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()); - } - - private static String getJsp(String view) { - return "/WEB-INF/" + view + ".jsp"; - } - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, 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/khmelov/controller/HttpResolver.java deleted file mode 100644 index 18bb761..0000000 --- a/src/main/java/com/javarush/khmelov/controller/HttpResolver.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.javarush.khmelov.controller; - -import com.javarush.khmelov.cmd.Command; -import com.javarush.khmelov.config.Winter; -import jakarta.servlet.http.HttpServletRequest; - -public class HttpResolver { - - public Command resolve(HttpServletRequest request) { - // /cmd-example - try { - String requestURI = request.getRequestURI(); - requestURI = requestURI.equals("/") ? "/start-page" : requestURI; - String kebabName = requestURI.split("[?#/]")[1]; - String simpleName = convertKebabStyleToCamelCase(kebabName); - String fullName = Command.class.getPackageName() + "." + simpleName; - Class aClass = Class.forName(fullName); - return (Command) Winter.find(aClass); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - private String convertKebabStyleToCamelCase(String input) { - StringBuilder result = new StringBuilder(); - boolean capitalizeNext = true; - for (char c : input.toCharArray()) { - if (c == '-') { - capitalizeNext = true; - } else { - if (capitalizeNext) { - result.append(Character.toUpperCase(c)); - capitalizeNext = false; - } else { - result.append(Character.toLowerCase(c)); - } - } - } - return result.toString(); - } -} diff --git a/src/main/java/com/javarush/khmelov/entity/Role.java b/src/main/java/com/javarush/khmelov/entity/Role.java deleted file mode 100644 index 5ae365f..0000000 --- a/src/main/java/com/javarush/khmelov/entity/Role.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.javarush.khmelov.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/khmelov/entity/User.java deleted file mode 100644 index f7fa2d6..0000000 --- a/src/main/java/com/javarush/khmelov/entity/User.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.javarush.khmelov.entity; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class User { - - private Long id; - - private String login; - - private String password; - - private Role role; - - public String getImage() { //TODO move to DTO - return "image-" + id; - } - -} diff --git a/src/main/java/com/javarush/khmelov/repository/Repository.java b/src/main/java/com/javarush/khmelov/repository/Repository.java deleted file mode 100644 index f1abdac..0000000 --- a/src/main/java/com/javarush/khmelov/repository/Repository.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.javarush.khmelov.repository; - -import com.javarush.khmelov.entity.User; - -import java.util.Collection; -import java.util.Optional; - -public interface Repository { - - Collection getAll(); - - Optional get(long id); - - void create(T entity); - - void update(T entity); - - void delete(T entity); -} diff --git a/src/main/java/com/javarush/khmelov/repository/UserRepository.java b/src/main/java/com/javarush/khmelov/repository/UserRepository.java deleted file mode 100644 index 58b32ea..0000000 --- a/src/main/java/com/javarush/khmelov/repository/UserRepository.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.javarush.khmelov.repository; - -import com.javarush.khmelov.entity.Role; -import com.javarush.khmelov.entity.User; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicLong; - -public class UserRepository implements Repository { - - private final Map map = new HashMap<>(); - - public static final AtomicLong id = new AtomicLong(System.currentTimeMillis()); - - public UserRepository() { - map.put(1L, new User(1L, "Alisa", "qwerty", Role.USER)); - map.put(2L, new User(2L, "Bob", "", Role.GUEST)); - map.put(3L, new User(3L, "Carl", "admin", Role.ADMIN)); - map.put(4L, new User(4L, "Khmelov", "admin", Role.ADMIN)); - } - - @Override - public Collection getAll() { - return map.values(); - } - - @Override - public Optional get(long id) { - return Optional.ofNullable(map.get(id)); - } - - @Override - public void create(User entity) { - entity.setId(id.incrementAndGet()); - update(entity); - } - - @Override - public void update(User entity) { - map.put(entity.getId(), entity); - } - - @Override - public void delete(User entity) { - map.remove(entity.getId()); - } -} diff --git a/src/main/java/com/javarush/khmelov/service/UserService.java b/src/main/java/com/javarush/khmelov/service/UserService.java deleted file mode 100644 index b17527c..0000000 --- a/src/main/java/com/javarush/khmelov/service/UserService.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.javarush.khmelov.service; - -import com.javarush.khmelov.entity.User; -import com.javarush.khmelov.repository.UserRepository; - -import java.util.Collection; -import java.util.Optional; - -public class UserService { - - private final UserRepository userRepository; - - public UserService(UserRepository userRepository) { - this.userRepository = userRepository; - } - - public void create(User user) { - userRepository.create(user); - } - - public void update(User user) { - userRepository.update(user); - } - - public void delete(User user) { - userRepository.delete(user); - } - - public Collection getAll() { - return userRepository.getAll(); - } - - public Optional get(long id) { - return userRepository.get(id); - } -} diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml new file mode 100644 index 0000000..1dbb067 --- /dev/null +++ b/src/main/resources/log4j2.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/completed-messages.jsp b/src/main/webapp/WEB-INF/completed-messages.jsp new file mode 100644 index 0000000..0732078 --- /dev/null +++ b/src/main/webapp/WEB-INF/completed-messages.jsp @@ -0,0 +1,53 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@include file="parts/header.jsp" %> + + +
+
+
+

Обработанные сообщения полученные через форму обратной связи

+
+
+
+ + + +
+ <%--
--%> +
+
+ + + +
+
+ +

${message.topic}

+

${message.message}

+
+ checked> + +
+
+ +
+

${message.name} - ${message.email}

+
+
+
+
+ + +
+ +
+ + +
+ + +<%@include file="parts/footer.jsp" %> diff --git a/src/main/webapp/WEB-INF/contact.jsp b/src/main/webapp/WEB-INF/contact.jsp new file mode 100644 index 0000000..8a5e421 --- /dev/null +++ b/src/main/webapp/WEB-INF/contact.jsp @@ -0,0 +1,104 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@include file="parts/header.jsp" %> + + +
+ + + + + +
+
+
+
+

Связаться с нами

+

Задать вопрос или оставить обратную связь можно заполнив форму ниже.

+
+
+
+
+
+
+
+ + + +
+
+
Телефон
+

+123456789

+
+
+
+
+ + + +
+
+
Email
+

dimagoncharov21@gmail.com

+
+
+
+
+ + + +
+
+
Расположение
+

1401 N Shoreline Blvd, Mountain View, CA 94043, Соединенные Штаты, + Музей компьютерной истории

+
+
+
+
+
+
+
+
+
+
+<%-- --%> +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+ + + + + +<%@include file="parts/footer.jsp" %> \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/create-quest.jsp b/src/main/webapp/WEB-INF/create-quest.jsp new file mode 100644 index 0000000..5fff8b9 --- /dev/null +++ b/src/main/webapp/WEB-INF/create-quest.jsp @@ -0,0 +1,44 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ page contentType="text/html;charset=UTF-8" %> + + +
+
+ +
+ + +
+ +
+ + +
+ +
+ +
+ + +
+
+
+
+ + + + diff --git a/src/main/webapp/WEB-INF/delete-quest.jsp b/src/main/webapp/WEB-INF/delete-quest.jsp new file mode 100644 index 0000000..eee5f27 --- /dev/null +++ b/src/main/webapp/WEB-INF/delete-quest.jsp @@ -0,0 +1,26 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@include file="parts/header.jsp" %> + + + +
+
+
+
+
+

Удалить квест "${requestScope.quest.name}"?

+
+
+ + +
+
+
+
+
+
+ +<%@include file="parts/footer.jsp" %> + diff --git a/src/main/webapp/WEB-INF/delete-user.jsp b/src/main/webapp/WEB-INF/delete-user.jsp new file mode 100644 index 0000000..4a7dece --- /dev/null +++ b/src/main/webapp/WEB-INF/delete-user.jsp @@ -0,0 +1,27 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@include file="parts/header.jsp" %> + + + + +
+
+
+
+
+

Удалить пользователя "${requestScope.user.login}"?

+
+
+ + +
+
+
+
+
+
+ +<%@include file="parts/footer.jsp" %> diff --git a/src/main/webapp/WEB-INF/edit-user.jsp b/src/main/webapp/WEB-INF/edit-user.jsp index f274104..d267b0c 100644 --- a/src/main/webapp/WEB-INF/edit-user.jsp +++ b/src/main/webapp/WEB-INF/edit-user.jsp @@ -1,14 +1,14 @@ <%@ page contentType="text/html;charset=UTF-8" language="java" %> -<%@include file="head.jsp" %> +<%@include file="parts/header.jsp" %> +
Edit user: - -
@@ -35,39 +35,58 @@ placeholder="your password" class="form-control input-md" required=""> - min 8 symb + min 8 symbols
- -
- +
- +
+ + +
+ +
+ +
+
+
+
- - - - - + + <%----%> + + + <%-- --%> + + +
- +<%@include file="parts/footer.jsp" %> + diff --git a/src/main/webapp/WEB-INF/home.jsp b/src/main/webapp/WEB-INF/home.jsp new file mode 100644 index 0000000..54fa5be --- /dev/null +++ b/src/main/webapp/WEB-INF/home.jsp @@ -0,0 +1,32 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@include file="parts/header.jsp" %> + +
+ +

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

+ +
+<%@include file="parts/footer.jsp" %> diff --git a/src/main/webapp/WEB-INF/home_new.jsp b/src/main/webapp/WEB-INF/home_new.jsp new file mode 100644 index 0000000..c0e4a83 --- /dev/null +++ b/src/main/webapp/WEB-INF/home_new.jsp @@ -0,0 +1,8 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@include file="parts/header.jsp" %> + +
+
+
+ +<%@include file="parts/footer.jsp" %> \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/images/analytic.png b/src/main/webapp/WEB-INF/images/analytic.png new file mode 100644 index 0000000..8a30bb0 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/analytic.png differ diff --git a/src/main/webapp/WEB-INF/images/architecor.png b/src/main/webapp/WEB-INF/images/architecor.png new file mode 100644 index 0000000..8f48eac Binary files /dev/null and b/src/main/webapp/WEB-INF/images/architecor.png differ diff --git a/src/main/webapp/WEB-INF/images/developer.png b/src/main/webapp/WEB-INF/images/developer.png new file mode 100644 index 0000000..e7ea636 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/developer.png differ diff --git a/src/main/webapp/WEB-INF/images/edit-icon.png b/src/main/webapp/WEB-INF/images/edit-icon.png new file mode 100644 index 0000000..0a87dfc Binary files /dev/null and b/src/main/webapp/WEB-INF/images/edit-icon.png differ diff --git a/src/main/webapp/WEB-INF/images/edit2-icon.png b/src/main/webapp/WEB-INF/images/edit2-icon.png new file mode 100644 index 0000000..eee01f1 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/edit2-icon.png differ diff --git a/src/main/webapp/WEB-INF/images/kwa.jpg b/src/main/webapp/WEB-INF/images/kwa.jpg new file mode 100644 index 0000000..dc35d21 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/kwa.jpg differ diff --git a/src/main/webapp/WEB-INF/images/no-image.png b/src/main/webapp/WEB-INF/images/no-image.png new file mode 100644 index 0000000..9fdc684 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/no-image.png differ diff --git a/src/main/webapp/WEB-INF/images/qa.jpg b/src/main/webapp/WEB-INF/images/qa.jpg new file mode 100644 index 0000000..08b76f0 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/qa.jpg differ diff --git a/src/main/webapp/WEB-INF/images/question-1.jpg b/src/main/webapp/WEB-INF/images/question-1.jpg new file mode 100644 index 0000000..c291515 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-1.jpg differ diff --git a/src/main/webapp/WEB-INF/images/question-10.jpeg b/src/main/webapp/WEB-INF/images/question-10.jpeg new file mode 100644 index 0000000..6f849aa Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-10.jpeg differ diff --git a/src/main/webapp/WEB-INF/images/question-11.jpeg b/src/main/webapp/WEB-INF/images/question-11.jpeg new file mode 100644 index 0000000..92483f8 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-11.jpeg differ diff --git a/src/main/webapp/WEB-INF/images/question-12.jpeg b/src/main/webapp/WEB-INF/images/question-12.jpeg new file mode 100644 index 0000000..6984811 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-12.jpeg differ diff --git a/src/main/webapp/WEB-INF/images/question-13.webp b/src/main/webapp/WEB-INF/images/question-13.webp new file mode 100644 index 0000000..99bfbde Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-13.webp differ diff --git a/src/main/webapp/WEB-INF/images/question-14.jpeg b/src/main/webapp/WEB-INF/images/question-14.jpeg new file mode 100644 index 0000000..a3e5988 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-14.jpeg differ diff --git a/src/main/webapp/WEB-INF/images/question-15.jpg b/src/main/webapp/WEB-INF/images/question-15.jpg new file mode 100644 index 0000000..128318a Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-15.jpg differ diff --git a/src/main/webapp/WEB-INF/images/question-16.jpeg b/src/main/webapp/WEB-INF/images/question-16.jpeg new file mode 100644 index 0000000..9f192f7 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-16.jpeg differ diff --git a/src/main/webapp/WEB-INF/images/question-17.jpg b/src/main/webapp/WEB-INF/images/question-17.jpg new file mode 100644 index 0000000..28961cc Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-17.jpg differ diff --git a/src/main/webapp/WEB-INF/images/question-18.jpeg b/src/main/webapp/WEB-INF/images/question-18.jpeg new file mode 100644 index 0000000..5fb49bd Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-18.jpeg differ diff --git a/src/main/webapp/WEB-INF/images/question-19.jpeg b/src/main/webapp/WEB-INF/images/question-19.jpeg new file mode 100644 index 0000000..4d7e9a2 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-19.jpeg differ diff --git a/src/main/webapp/WEB-INF/images/question-2.webp b/src/main/webapp/WEB-INF/images/question-2.webp new file mode 100644 index 0000000..2823839 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-2.webp differ diff --git a/src/main/webapp/WEB-INF/images/question-20.jpg b/src/main/webapp/WEB-INF/images/question-20.jpg new file mode 100644 index 0000000..bbd15cd Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-20.jpg differ diff --git a/src/main/webapp/WEB-INF/images/question-21.jpg b/src/main/webapp/WEB-INF/images/question-21.jpg new file mode 100644 index 0000000..a14749d Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-21.jpg differ diff --git a/src/main/webapp/WEB-INF/images/question-22.jpg b/src/main/webapp/WEB-INF/images/question-22.jpg new file mode 100644 index 0000000..55ff413 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-22.jpg differ diff --git a/src/main/webapp/WEB-INF/images/question-23.jpg b/src/main/webapp/WEB-INF/images/question-23.jpg new file mode 100644 index 0000000..a3151f8 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-23.jpg differ diff --git a/src/main/webapp/WEB-INF/images/question-3.jpg b/src/main/webapp/WEB-INF/images/question-3.jpg new file mode 100644 index 0000000..61c10e8 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-3.jpg differ diff --git a/src/main/webapp/WEB-INF/images/question-4.jpg b/src/main/webapp/WEB-INF/images/question-4.jpg new file mode 100644 index 0000000..55ff413 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-4.jpg differ diff --git a/src/main/webapp/WEB-INF/images/question-5.jpg b/src/main/webapp/WEB-INF/images/question-5.jpg new file mode 100644 index 0000000..55ff413 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-5.jpg differ diff --git a/src/main/webapp/WEB-INF/images/question-6.jpg b/src/main/webapp/WEB-INF/images/question-6.jpg new file mode 100644 index 0000000..55ff413 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-6.jpg differ diff --git a/src/main/webapp/WEB-INF/images/question-7.jpg b/src/main/webapp/WEB-INF/images/question-7.jpg new file mode 100644 index 0000000..a3151f8 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-7.jpg differ diff --git a/src/main/webapp/WEB-INF/images/question-7.png b/src/main/webapp/WEB-INF/images/question-7.png new file mode 100644 index 0000000..1aee3b9 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-7.png differ diff --git a/src/main/webapp/WEB-INF/images/question-8.webp b/src/main/webapp/WEB-INF/images/question-8.webp new file mode 100644 index 0000000..365b629 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-8.webp differ diff --git a/src/main/webapp/WEB-INF/images/question-9.webp b/src/main/webapp/WEB-INF/images/question-9.webp new file mode 100644 index 0000000..e38c040 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/question-9.webp differ diff --git a/src/main/webapp/WEB-INF/images/trash-icon.png b/src/main/webapp/WEB-INF/images/trash-icon.png new file mode 100644 index 0000000..a12f2a5 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/trash-icon.png differ diff --git a/src/main/webapp/WEB-INF/images/trash2-icon.png b/src/main/webapp/WEB-INF/images/trash2-icon.png new file mode 100644 index 0000000..b910818 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/trash2-icon.png differ diff --git a/src/main/webapp/WEB-INF/images/user-1.png b/src/main/webapp/WEB-INF/images/user-1.png new file mode 100644 index 0000000..e0e77ab Binary files /dev/null and b/src/main/webapp/WEB-INF/images/user-1.png differ diff --git a/src/main/webapp/WEB-INF/images/user-2.jpg b/src/main/webapp/WEB-INF/images/user-2.jpg new file mode 100644 index 0000000..6fd8d32 Binary files /dev/null and b/src/main/webapp/WEB-INF/images/user-2.jpg differ diff --git a/src/main/webapp/WEB-INF/images/user-3.webp b/src/main/webapp/WEB-INF/images/user-3.webp new file mode 100644 index 0000000..9bdd2ff Binary files /dev/null and b/src/main/webapp/WEB-INF/images/user-3.webp differ diff --git a/src/main/webapp/WEB-INF/list-user.jsp b/src/main/webapp/WEB-INF/list-user.jsp index dd52c55..b57b374 100644 --- a/src/main/webapp/WEB-INF/list-user.jsp +++ b/src/main/webapp/WEB-INF/list-user.jsp @@ -1,9 +1,55 @@ <%@ page contentType="text/html;charset=UTF-8" language="java" %> -<%@include file="head.jsp"%> +<%@include file="parts/header.jsp" %> - - ${user.login} - - + +
+
+
+

Пользователи

+
+
+
+ + +
+
+
+
${user.login}
+
+
+ + + Удалить + + + + Редактировать + +
+
+
+
+
+ + +
+
+
+
${user.login}

+
+
+
+
+
+
+
+
+ +<%@include file="parts/footer.jsp" %> diff --git a/src/main/webapp/WEB-INF/login.jsp b/src/main/webapp/WEB-INF/login.jsp new file mode 100644 index 0000000..cbe3ba0 --- /dev/null +++ b/src/main/webapp/WEB-INF/login.jsp @@ -0,0 +1,22 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@include file="parts/header.jsp" %> +
+
+
+
+
+
+

Login

+
+

Укажите данные для входа

+
+
+
+
+
+
+
+
+
+
+<%@include file="parts/footer.jsp" %> diff --git a/src/main/webapp/WEB-INF/messages.jsp b/src/main/webapp/WEB-INF/messages.jsp new file mode 100644 index 0000000..1a040ab --- /dev/null +++ b/src/main/webapp/WEB-INF/messages.jsp @@ -0,0 +1,60 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@include file="parts/header.jsp" %> + + +
+
+
+

Сообщения полученные через форму обратной связи

+
+
+
+ + + +
+ <%--
--%> +
+
+ + + +
+
+ +
+ +
+

${message.message}

+
+ checked> + +
+
+ + +
+

${message.name} - ${message.email}

+
+
+
+
+ + +
+ +
+ + +
+ + +<%@include file="parts/footer.jsp" %> diff --git a/src/main/webapp/WEB-INF/our-team.jsp b/src/main/webapp/WEB-INF/our-team.jsp new file mode 100644 index 0000000..9e16571 --- /dev/null +++ b/src/main/webapp/WEB-INF/our-team.jsp @@ -0,0 +1,48 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@include file="parts/header.jsp" %> + +
+
+
+

Команда мечты

+

Над проектом работали:

+
+
+
+
+
+
+
Дмитрий Гончаров
+

Аналитика

+
+
+
+
+
+
+
Дмитрий Гончаров
+

Разработка

+
+
+
+
+
+
+
Дмитрий Гончаров
+

Архитектура

+
+
+
+
+
+
+
Дмитрий Гончаров
+

Тестирование

+
+
+
+
+
+ + +<%@include file="parts/footer.jsp" %> \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/parts/footer.jsp b/src/main/webapp/WEB-INF/parts/footer.jsp new file mode 100644 index 0000000..ee38dc6 --- /dev/null +++ b/src/main/webapp/WEB-INF/parts/footer.jsp @@ -0,0 +1,20 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + + +
+ +
${sessionScope.errorMessage}
+
+
+ +

Copyright   © 2026 JRU Company, Inc. Pantera Group. 

+
+
+ + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/parts/header.jsp b/src/main/webapp/WEB-INF/parts/header.jsp new file mode 100644 index 0000000..7a4ead1 --- /dev/null +++ b/src/main/webapp/WEB-INF/parts/header.jsp @@ -0,0 +1,86 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + + + + + + + Pantera + + + + + + + +
+
+ +
\ No newline at end of file diff --git a/src/main/webapp/WEB-INF/parts/quest-demo.jsp b/src/main/webapp/WEB-INF/parts/quest-demo.jsp new file mode 100644 index 0000000..c5791a5 --- /dev/null +++ b/src/main/webapp/WEB-INF/parts/quest-demo.jsp @@ -0,0 +1,24 @@ +<%@ page contentType="text/html;charset=UTF-8" +%> +Тут введите структуру вашего квеста в формате +[Метка]: Вопрос, где [Метка] - это уникальный числовой номер вопроса +[Метка]< Ответ, где [Метка] - номер, куда перейти при выборе этого ответа +[Метка]+ Сообщение о победе, где [Метка] - это уникальный номер сообщения +[Метка]- Сообщение о поражении, где [Метка] - это уникальный номер сообщения + +Пример: + +1: Вы знаете арифметику? +2< Да, конечно +99< А что это такое? + +2: Сколько будет дважды два? +99< Один +99< Два +99< Три +100< Четыре + +99- Вы проиграли + +100+ Вы выиграли + diff --git a/src/main/webapp/WEB-INF/parts/quest-jru.txt b/src/main/webapp/WEB-INF/parts/quest-jru.txt new file mode 100644 index 0000000..72c56c3 --- /dev/null +++ b/src/main/webapp/WEB-INF/parts/quest-jru.txt @@ -0,0 +1,16 @@ +<%@ page contentType="text/html;charset=UTF-8"%>02< Принять вызов +91< Отклонить вызов + +02: Ты принял вызов. Подняться на мостик к капитану? +92< Отказаться подниматься на мостик +03< Подняться на мостик + +03: Ты поднялся на мостик. Ты кто? +93< Солгать о себе +99< Рассказать правду + +91- Ты отклонил вызов. Поражение. +92- Ты не пошел на переговоры. Поражение. +93- Твою ложь разоблачили. Поражение. + +99+ Вы выиграли \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/parts/quest-math.txt b/src/main/webapp/WEB-INF/parts/quest-math.txt new file mode 100644 index 0000000..a5eed4e --- /dev/null +++ b/src/main/webapp/WEB-INF/parts/quest-math.txt @@ -0,0 +1,13 @@ +<%@ page contentType="text/html;charset=UTF-8"%>1: Вы знаете арифметику? +2< Да, конечно +99< А что это такое? + +2: Сколько будет дважды два? +99< Один +99< Два +99< Три +100< Четыре + +99- Вы проиграли + +100+ Вы выиграли \ No newline at end of file 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..9e8cdb3 --- /dev/null +++ b/src/main/webapp/WEB-INF/play-game.jsp @@ -0,0 +1,56 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ page contentType="text/html;charset=UTF-8" %> + + + + +<%----%> + + + +
+ + + + + +
+
+
+
+

${question.text}

+

Выберите вариант ответа

+
    + +
    + + +
    +
    +
+ + + + + + + + + + + +
+
+
+
+
+ + + + diff --git a/src/main/webapp/WEB-INF/profile.jsp b/src/main/webapp/WEB-INF/profile.jsp new file mode 100644 index 0000000..d1513c8 --- /dev/null +++ b/src/main/webapp/WEB-INF/profile.jsp @@ -0,0 +1,31 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ page contentType="text/html;charset=UTF-8" %> + +
+ + +
+

+

Login: ${user.login}

+

Role: ${user.role}

+

Email: ${user.email}

+
+
+
+ + + + + +
+
+
+
+
+ + diff --git a/src/main/webapp/WEB-INF/quest.jsp b/src/main/webapp/WEB-INF/quest.jsp new file mode 100644 index 0000000..9b9ee30 --- /dev/null +++ b/src/main/webapp/WEB-INF/quest.jsp @@ -0,0 +1,23 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ page contentType="text/html;charset=UTF-8" %> + + +
+
${requestScope.quest.name}
+ + +
+ + ${question.text} + + + + +
+
+
+ + diff --git a/src/main/webapp/WEB-INF/send-message.jsp b/src/main/webapp/WEB-INF/send-message.jsp new file mode 100644 index 0000000..d7bf158 --- /dev/null +++ b/src/main/webapp/WEB-INF/send-message.jsp @@ -0,0 +1,6 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@include file="parts/header.jsp" %> + +

Сообщение отправлено!

+ +<%@include file="parts/footer.jsp" %> \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/signup.jsp b/src/main/webapp/WEB-INF/signup.jsp new file mode 100644 index 0000000..d36b5eb --- /dev/null +++ b/src/main/webapp/WEB-INF/signup.jsp @@ -0,0 +1,28 @@ +<%@ page contentType="text/html;charset=UTF-8" %> +<%@include file="parts/header.jsp" %> +
+
+
+
+
+
+
+

Signup

+
+

Укажите данные для регистрации

+
+
+
+
+ +
+
+
+
+
+
+
+
+
+<%@include file="parts/footer.jsp" %> diff --git a/src/main/webapp/WEB-INF/start-page.jsp b/src/main/webapp/WEB-INF/start-page.jsp index 0531c1c..fee54be 100644 --- a/src/main/webapp/WEB-INF/start-page.jsp +++ b/src/main/webapp/WEB-INF/start-page.jsp @@ -1,8 +1,8 @@ <%@ page contentType="text/html;charset=UTF-8" language="java" %> -<%@include file="head.jsp"%> +<%@include file="parts/header.jsp" %>

<%= "Hello World!" %>


List Users - +<%@include file="parts/footer.jsp" %> diff --git a/src/main/webapp/WEB-INF/statistics.jsp b/src/main/webapp/WEB-INF/statistics.jsp new file mode 100644 index 0000000..72e33f6 --- /dev/null +++ b/src/main/webapp/WEB-INF/statistics.jsp @@ -0,0 +1,110 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ page contentType="text/html;charset=UTF-8" %> + + + +
+
+

Статистика

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ЛогинВ процессеПобедаПоражениеВсего
${stat.login}${stat.play}${stat.win}${stat.lost}${stat.total}
+
+
+ + +
+
+
+
+
+ + + +
+
+

${requestScope.userStatistics.play}

+

В процессе

+
+
+
+
+
+
+ + + + +
+
+

${requestScope.userStatistics.win}

+

Победа

+
+
+
+
+
+
+ + + +
+
+

${requestScope.userStatistics.lost}

+

Поражение

+
+
+
+
+
+
+ + + +
+
+

${requestScope.userStatistics.total}

+

Всего

+
+
+
+
+
+ + +
+ + diff --git a/src/main/webapp/assets/css/Team-icons.css b/src/main/webapp/assets/css/Team-icons.css new file mode 100644 index 0000000..c0cd08e --- /dev/null +++ b/src/main/webapp/assets/css/Team-icons.css @@ -0,0 +1,56 @@ +.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%; +} \ No newline at end of file diff --git a/src/main/webapp/assets/css/Team-images.css b/src/main/webapp/assets/css/Team-images.css new file mode 100644 index 0000000..d698cb4 --- /dev/null +++ b/src/main/webapp/assets/css/Team-images.css @@ -0,0 +1,3 @@ +.fit-cover { + object-fit: cover; +} \ No newline at end of file diff --git a/src/main/webapp/assets/css/styles.min.css b/src/main/webapp/assets/css/styles.min.css new file mode 100644 index 0000000..320a7ad --- /dev/null +++ b/src/main/webapp/assets/css/styles.min.css @@ -0,0 +1 @@ +.fit-cover{object-fit:cover}.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%} \ No newline at end of file diff --git a/src/main/webapp/assets/img/analytic.png b/src/main/webapp/assets/img/analytic.png new file mode 100644 index 0000000..8a30bb0 Binary files /dev/null and b/src/main/webapp/assets/img/analytic.png differ diff --git a/src/main/webapp/assets/img/architecor.png b/src/main/webapp/assets/img/architecor.png new file mode 100644 index 0000000..8f48eac Binary files /dev/null and b/src/main/webapp/assets/img/architecor.png differ diff --git a/src/main/webapp/assets/img/blank-photo.png b/src/main/webapp/assets/img/blank-photo.png new file mode 100644 index 0000000..dc2bb45 Binary files /dev/null and b/src/main/webapp/assets/img/blank-photo.png differ diff --git a/src/main/webapp/assets/img/developer.png b/src/main/webapp/assets/img/developer.png new file mode 100644 index 0000000..e7ea636 Binary files /dev/null and b/src/main/webapp/assets/img/developer.png differ diff --git a/src/main/webapp/assets/img/kwa.jpg b/src/main/webapp/assets/img/kwa.jpg new file mode 100644 index 0000000..dc35d21 Binary files /dev/null and b/src/main/webapp/assets/img/kwa.jpg differ diff --git a/src/main/webapp/assets/img/qa.jpg b/src/main/webapp/assets/img/qa.jpg new file mode 100644 index 0000000..08b76f0 Binary files /dev/null and b/src/main/webapp/assets/img/qa.jpg differ diff --git a/src/main/webapp/img/blank-photo.png b/src/main/webapp/img/blank-photo.png new file mode 100644 index 0000000..dc2bb45 Binary files /dev/null and b/src/main/webapp/img/blank-photo.png differ diff --git a/src/test/java/com/javarush/goncharov/controller/BaseTest.java b/src/test/java/com/javarush/goncharov/controller/BaseTest.java new file mode 100644 index 0000000..ab03609 --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/BaseTest.java @@ -0,0 +1,54 @@ +package com.javarush.goncharov.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.SneakyThrows; +import org.junit.jupiter.api.BeforeAll; + +import java.io.IOException; +import java.net.CookieManager; +import java.net.CookiePolicy; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.time.temporal.ChronoUnit; +import java.util.Arrays; + +public abstract class BaseTest { + public static final String ROOT = "http://localhost:8088"; + protected static ObjectMapper mapper; + protected static HttpClient httpClient; + + @SneakyThrows + @BeforeAll + static void init() { + CookieManager cookieManager = new CookieManager(); + cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL); + mapper = new ObjectMapper(); + httpClient = HttpClient.newBuilder() + .cookieHandler(cookieManager) + .version(HttpClient.Version.HTTP_1_1) + .connectTimeout(Duration.of(2, ChronoUnit.SECONDS)) + .build(); + HttpRequest indexProbe = HttpRequest.newBuilder() + .uri(URI.create(ROOT)) + .GET() + .build(); + try { + httpClient.send(indexProbe, HttpResponse.BodyHandlers.ofString()); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(Arrays.toString(e.getStackTrace())); + } + } + protected void createSession() throws IOException, InterruptedException { + String loginForm = "login=Admin&password=123"; + HttpRequest loginRequest = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/login")) + .header("Content-Type", "application/x-www-form-urlencoded") + .POST(HttpRequest.BodyPublishers.ofString(loginForm)) + .build(); + + httpClient.send(loginRequest, HttpResponse.BodyHandlers.ofString()); + } +} diff --git a/src/test/java/com/javarush/goncharov/controller/CompletedMessagesTest.java b/src/test/java/com/javarush/goncharov/controller/CompletedMessagesTest.java new file mode 100644 index 0000000..c0690c2 --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/CompletedMessagesTest.java @@ -0,0 +1,33 @@ +package com.javarush.goncharov.controller; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import static org.junit.jupiter.api.Assertions.*; + +class CompletedMessagesTest extends BaseTest{ + @Test + @Tag("http-client") + @DisplayName("When open completed message page then body contains close tag") + void whenOpenCompletedMessagePageThenBodyContainsCloseTag() throws IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/completed-messages")) + .GET() + .build(); + HttpResponse response = httpClient.send( + request, + HttpResponse.BodyHandlers.ofString() + ); + assertEquals(HttpURLConnection.HTTP_OK, response.statusCode()); + assertTrue(response.body().contains("")); + } + +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/controller/ContactUsTest.java b/src/test/java/com/javarush/goncharov/controller/ContactUsTest.java new file mode 100644 index 0000000..02d8058 --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/ContactUsTest.java @@ -0,0 +1,32 @@ +package com.javarush.goncharov.controller; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import static org.junit.jupiter.api.Assertions.*; + +class ContactUsTest extends BaseTest{ + @Test + @Tag("http-client") + @DisplayName("When open completed message page then body contains close tag") + void whenOpenCompletedMessagePageThenBodyContainsCloseTag() throws IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/contact")) + .GET() + .build(); + HttpResponse response = httpClient.send( + request, + HttpResponse.BodyHandlers.ofString() + ); + assertEquals(HttpURLConnection.HTTP_OK, response.statusCode()); + assertTrue(response.body().contains("")); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/controller/CreateGameTest.java b/src/test/java/com/javarush/goncharov/controller/CreateGameTest.java new file mode 100644 index 0000000..2c95f2d --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/CreateGameTest.java @@ -0,0 +1,32 @@ +package com.javarush.goncharov.controller; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import static org.junit.jupiter.api.Assertions.*; + +class CreateGameTest extends BaseTest { + @Test + @Tag("http-client") + @DisplayName("When open create game users page then body contains se tag") + void whenOpenCreateGamePageThenBodyContainsSeTag() throws IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/create-quest")) + .GET() + .build(); + HttpResponse response = httpClient.send( + request, + HttpResponse.BodyHandlers.ofString() + ); + assertEquals(HttpURLConnection.HTTP_OK, response.statusCode()); + assertTrue(response.body().contains("")); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/controller/DeleteQuestTest.java b/src/test/java/com/javarush/goncharov/controller/DeleteQuestTest.java new file mode 100644 index 0000000..ce24da0 --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/DeleteQuestTest.java @@ -0,0 +1,83 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.Quest; +import com.javarush.goncharov.service.QuestService; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mockito.*; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.Optional; + +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; + +@FieldDefaults(level = AccessLevel.PRIVATE) +@ExtendWith(MockitoExtension.class) +class DeleteQuestTest extends BaseTest { + @Mock + HttpServletRequest request; + @Mock + HttpServletResponse response; + @Mock + RequestDispatcher requestDispatcher; + @Mock + Quest quest; + @Mock + QuestService questService; + @InjectMocks + DeleteQuest servlet; + + static final Long TEST_QUEST_ID = 123L; + static final String JSP_PATH = "/WEB-INF/delete-quest.jsp"; + + @Test + @DisplayName("Should set quest attribute and forward to JSP when quest exists") + void shouldSetQuestAttributeAndForwardToJspWhenQuestExists() throws ServletException, IOException { + quest.setId(TEST_QUEST_ID); + quest.setName("Test Quest"); + + when(request.getParameter("id")).thenReturn(String.valueOf(TEST_QUEST_ID)); + when(questService.get(TEST_QUEST_ID)).thenReturn(Optional.of(quest)); + when(request.getRequestDispatcher(JSP_PATH)).thenReturn(requestDispatcher); + + servlet.doGet(request, response); + + verify(request).setAttribute("quest", quest); + verify(request).getRequestDispatcher(JSP_PATH); + verify(requestDispatcher).forward(request, response); + verifyNoMoreInteractions(response); + } + + @Test + @Tag("http-client") + @DisplayName("When open delete quest page then body contains close tag") + void whenOpenDeleteQuestPageThenBodyContainsSeTagIT() throws IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/delete-quest" + "?id=" + TEST_QUEST_ID)) + .GET() + .build(); + HttpResponse response = httpClient.send( + request, + HttpResponse.BodyHandlers.ofString() + ); + assertEquals(HttpURLConnection.HTTP_OK, response.statusCode()); + assertTrue(response.body().contains("")); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/controller/DeleteUserTest.java b/src/test/java/com/javarush/goncharov/controller/DeleteUserTest.java new file mode 100644 index 0000000..4c3eeb5 --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/DeleteUserTest.java @@ -0,0 +1,83 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.User; +import com.javarush.goncharov.service.UserService; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +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.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.Optional; + +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; + +@FieldDefaults(level = AccessLevel.PRIVATE) +@ExtendWith(MockitoExtension.class) +class DeleteUserTest extends BaseTest{ + @Mock + HttpServletRequest request; + @Mock + HttpServletResponse response; + @Mock + RequestDispatcher requestDispatcher; + @Mock + UserService userService; + @Mock + User user; + @InjectMocks + DeleteUser servlet; + + final Long TEST_USER_ID = 123L; + final String JSP_PATH = "/WEB-INF/delete-user.jsp"; + + @Test + @DisplayName("Should set user attribute and forward to JSP when user exists") + void shouldSetUserAttributeAndForwardToJspWhenUserExists() throws ServletException, IOException { + user.setId(TEST_USER_ID); + user.setLogin("TestUser"); + + when(request.getParameter("id")).thenReturn(String.valueOf(TEST_USER_ID)); + when(userService.get(TEST_USER_ID)).thenReturn(Optional.of(user)); + when(request.getRequestDispatcher(JSP_PATH)).thenReturn(requestDispatcher); + + servlet.doGet(request, response); + + verify(request).setAttribute("user", user); + verify(request).getRequestDispatcher(JSP_PATH); + verify(requestDispatcher).forward(request, response); + verifyNoInteractions(response); + } + + @Test + @Tag("http-client") + @DisplayName("When open delete user page then body contains close tag") + void whenOpenDeleteUserPageThenBodyContainsCloseTag() throws IOException, InterruptedException { + createSession(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/delete-user" + "?id=" + TEST_USER_ID)) + .GET() + .build(); + HttpResponse response = httpClient.send( + request, + HttpResponse.BodyHandlers.ofString() + ); + assertEquals(HttpURLConnection.HTTP_OK, response.statusCode()); + assertTrue(response.body().contains("")); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/controller/EditUserTest.java b/src/test/java/com/javarush/goncharov/controller/EditUserTest.java new file mode 100644 index 0000000..ac2019b --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/EditUserTest.java @@ -0,0 +1,80 @@ +package com.javarush.goncharov.controller; + +import com.javarush.goncharov.model.User; +import com.javarush.goncharov.service.UserService; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +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.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.Optional; + +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.*; + +@ExtendWith(MockitoExtension.class) +class EditUserTest extends BaseTest { + @Mock + private HttpServletRequest request; + @Mock + private HttpServletResponse response; + @Mock + private RequestDispatcher requestDispatcher; + @Mock + private UserService userService; + @Mock + private User user; + @InjectMocks + private EditUser servlet; + + private final Long TEST_USER_ID = 123L; + private final String JSP_PATH = "/WEB-INF/edit-user.jsp"; + + @Test + @DisplayName("Should set user attribute and forward to JSP when user exists") + void shouldSetUserAttributeAndForwardToJspWhenUserExists() throws ServletException, IOException { + user.setId(TEST_USER_ID); + user.setLogin("TestUser"); + + when(request.getParameter("id")).thenReturn(String.valueOf(TEST_USER_ID)); + when(userService.get(TEST_USER_ID)).thenReturn(Optional.of(user)); + when(request.getRequestDispatcher(JSP_PATH)).thenReturn(requestDispatcher); + + servlet.doGet(request, response); + + verify(request).setAttribute("user", user); + verify(request).getRequestDispatcher(JSP_PATH); + verify(requestDispatcher).forward(request, response); + verifyNoInteractions(response); + } + + @Test + @Tag("http-client") + @DisplayName("When open edit user page then body contains close tag") + void whenOpenEditUserPageThenBodyContainsCloseTag() throws IOException, InterruptedException { + createSession(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/edit-user" + "?id=" + TEST_USER_ID)) + .GET() + .build(); + HttpResponse response = httpClient.send( + request, + HttpResponse.BodyHandlers.ofString() + ); + assertEquals(HttpURLConnection.HTTP_OK, response.statusCode()); + assertTrue(response.body().contains("")); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/controller/ListQuestsTest.java b/src/test/java/com/javarush/goncharov/controller/ListQuestsTest.java new file mode 100644 index 0000000..9003134 --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/ListQuestsTest.java @@ -0,0 +1,32 @@ +package com.javarush.goncharov.controller; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import static org.junit.jupiter.api.Assertions.*; + +class ListQuestsTest extends BaseTest { + @Test + @Tag("http-client") + @DisplayName("When open index page then body contains close tag") + void whenOpenIndexPageThenBodyContainsCloseTag() throws IOException, InterruptedException { + HttpRequest indexReq = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/list-quests")) + .GET() + .build(); + HttpResponse indexResponse = httpClient.send( + indexReq, + HttpResponse.BodyHandlers.ofString() + ); + assertEquals(HttpURLConnection.HTTP_OK, indexResponse.statusCode()); + assertTrue(indexResponse.body().contains("")); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/controller/ListUsersTest.java b/src/test/java/com/javarush/goncharov/controller/ListUsersTest.java new file mode 100644 index 0000000..0a438a8 --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/ListUsersTest.java @@ -0,0 +1,33 @@ +package com.javarush.goncharov.controller; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import static org.junit.jupiter.api.Assertions.*; + +class ListUsersTest extends BaseTest { + @Test + @Tag("http-client") + @DisplayName("When open list users page then body contains se tag") + void whenOpenListUsersPageThenBodyContainsSeTag() throws IOException, InterruptedException { + createSession(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/list-users")) + .GET() + .build(); + HttpResponse response = httpClient.send( + request, + HttpResponse.BodyHandlers.ofString() + ); + assertEquals(HttpURLConnection.HTTP_OK, response.statusCode()); + assertTrue(response.body().contains("")); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/controller/LoginTest.java b/src/test/java/com/javarush/goncharov/controller/LoginTest.java new file mode 100644 index 0000000..bec9291 --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/LoginTest.java @@ -0,0 +1,32 @@ +package com.javarush.goncharov.controller; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import static org.junit.jupiter.api.Assertions.*; + +class LoginTest extends BaseTest { + @Test + @Tag("http-client") + @DisplayName("When open login page then body contains se tag") + void whenOpenLoginPageThenBodyContainsSeTag() throws IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/login")) + .GET() + .build(); + HttpResponse response = httpClient.send( + request, + HttpResponse.BodyHandlers.ofString() + ); + assertEquals(HttpURLConnection.HTTP_OK, response.statusCode()); + assertTrue(response.body().contains("")); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/controller/LogoutTest.java b/src/test/java/com/javarush/goncharov/controller/LogoutTest.java new file mode 100644 index 0000000..ffa7a79 --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/LogoutTest.java @@ -0,0 +1,33 @@ +package com.javarush.goncharov.controller; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import static org.junit.jupiter.api.Assertions.*; + +class LogoutTest extends BaseTest { + @Test + @Tag("http-client") + @DisplayName("When open logout page then body contains se tag") + void whenOpenLogoutPageThenBodyContainsSeTag() throws IOException, InterruptedException { + createSession(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/logout")) + .GET() + .build(); + HttpResponse response = httpClient.send( + request, + HttpResponse.BodyHandlers.ofString() + ); + assertEquals(HttpURLConnection.HTTP_OK, response.statusCode()); + assertTrue(response.body().contains("")); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/controller/MessagesTest.java b/src/test/java/com/javarush/goncharov/controller/MessagesTest.java new file mode 100644 index 0000000..43b7617 --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/MessagesTest.java @@ -0,0 +1,32 @@ +package com.javarush.goncharov.controller; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import static org.junit.jupiter.api.Assertions.*; + +class MessagesTest extends BaseTest { + @Test + @Tag("http-client") + @DisplayName("When open message page then body contains close tag") + void whenOpenMessagePageThenBodyContainsCloseTag() throws IOException, InterruptedException { + HttpRequest indexReq = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/messages")) + .GET() + .build(); + HttpResponse indexResponse = httpClient.send( + indexReq, + HttpResponse.BodyHandlers.ofString() + ); + assertEquals(HttpURLConnection.HTTP_OK, indexResponse.statusCode()); + assertTrue(indexResponse.body().contains("")); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/controller/ProfileTest.java b/src/test/java/com/javarush/goncharov/controller/ProfileTest.java new file mode 100644 index 0000000..500f29d --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/ProfileTest.java @@ -0,0 +1,30 @@ +package com.javarush.goncharov.controller; + +import org.junit.jupiter.api.*; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import static org.junit.jupiter.api.Assertions.*; + +class ProfileTest extends BaseTest{ + @Test + @Tag("http-client") + @DisplayName("When open profile page then body contains se tag") + void whenOpenProfilePageThenBodyContainsSeTag() throws IOException, InterruptedException { + createSession(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/profile")) + .GET() + .build(); + HttpResponse response = httpClient.send( + request, + HttpResponse.BodyHandlers.ofString() + ); + assertEquals(HttpURLConnection.HTTP_OK, response.statusCode()); + assertTrue(response.body().contains("")); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/controller/SignUpTest.java b/src/test/java/com/javarush/goncharov/controller/SignUpTest.java new file mode 100644 index 0000000..e1b2c8e --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/SignUpTest.java @@ -0,0 +1,32 @@ +package com.javarush.goncharov.controller; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import static org.junit.jupiter.api.Assertions.*; + +class SignUpTest extends BaseTest { + @Test + @Tag("http-client") + @DisplayName("When open sign up page then body contains close tag") + void whenOpenSignUpPageThenBodyContainsCloseTag() throws IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/signup")) + .GET() + .build(); + HttpResponse response = httpClient.send( + request, + HttpResponse.BodyHandlers.ofString() + ); + assertEquals(HttpURLConnection.HTTP_OK, response.statusCode()); + assertTrue(response.body().contains("")); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/controller/StartPageTest.java b/src/test/java/com/javarush/goncharov/controller/StartPageTest.java new file mode 100644 index 0000000..39475ba --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/StartPageTest.java @@ -0,0 +1,32 @@ +package com.javarush.goncharov.controller; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import static org.junit.jupiter.api.Assertions.*; + +class StartPageTest extends BaseTest { + @Test + @Tag("http-client") + @DisplayName("When open start page then body contains close tag") + void whenOpenStartPageThenBodyContainsCloseTag() throws IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/")) + .GET() + .build(); + HttpResponse response = httpClient.send( + request, + HttpResponse.BodyHandlers.ofString() + ); + assertEquals(HttpURLConnection.HTTP_OK, response.statusCode()); + assertTrue(response.body().contains("")); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/controller/StatisticsTest.java b/src/test/java/com/javarush/goncharov/controller/StatisticsTest.java new file mode 100644 index 0000000..e63315a --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/StatisticsTest.java @@ -0,0 +1,33 @@ +package com.javarush.goncharov.controller; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import static org.junit.jupiter.api.Assertions.*; + +class StatisticsTest extends BaseTest { + @Test + @Tag("http-client") + @DisplayName("When open statistics page then body contains close tag") + void whenOpenStatisticsPageThenBodyContainsCloseTag() throws IOException, InterruptedException { + createSession(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/statistics")) + .GET() + .build(); + HttpResponse response = httpClient.send( + request, + HttpResponse.BodyHandlers.ofString() + ); + assertEquals(HttpURLConnection.HTTP_OK, response.statusCode()); + assertTrue(response.body().contains("")); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/controller/TeamControllerTest.java b/src/test/java/com/javarush/goncharov/controller/TeamControllerTest.java new file mode 100644 index 0000000..8e69cb4 --- /dev/null +++ b/src/test/java/com/javarush/goncharov/controller/TeamControllerTest.java @@ -0,0 +1,32 @@ +package com.javarush.goncharov.controller; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import static org.junit.jupiter.api.Assertions.*; + +class TeamControllerTest extends BaseTest{ + @Test + @Tag("http-client") + @DisplayName("When open contactUs page then body conrains close tag") + void whenOpenContactUsPageThenBodyConrainsCloseTag() throws IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(ROOT + "/our-team")) + .GET() + .build(); + HttpResponse response = httpClient.send( + request, + HttpResponse.BodyHandlers.ofString() + ); + assertEquals(HttpURLConnection.HTTP_OK, response.statusCode()); + assertTrue(response.body().contains("")); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/service/StatisticServiceTest.java b/src/test/java/com/javarush/goncharov/service/StatisticServiceTest.java new file mode 100644 index 0000000..b734c8e --- /dev/null +++ b/src/test/java/com/javarush/goncharov/service/StatisticServiceTest.java @@ -0,0 +1,68 @@ +package com.javarush.goncharov.service; + +import com.javarush.goncharov.model.Game; +import com.javarush.goncharov.model.GameState; +import com.javarush.goncharov.model.Statistic; +import com.javarush.goncharov.model.User; +import com.javarush.goncharov.repository.GameRepository; +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 static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class StatisticServiceTest { + @Mock + GameRepository gameRepository; + @InjectMocks + StatisticService statisticService; + + User user1; + Game winGame; + Game loseGame; + Game playGame; + final Long TEST_USER_ID = 2L; + + @BeforeEach + void setup() { + user1 = User.builder().id(TEST_USER_ID).login("Dima").build(); + winGame = Game.builder() + .id(1L) + .userId(user1.getId()) + .gameState(GameState.WIN) + .build(); + loseGame = Game.builder() + .id(2L) + .userId(user1.getId()) + .gameState(GameState.LOSE) + .build(); + playGame = Game.builder() + .id(3L) + .userId(user1.getId()) + .gameState(GameState.PLAY) + .build(); + } + + @Test + @DisplayName("Get user statistic") + void getUserStatistic() { + List games = List.of(winGame, winGame, loseGame, playGame); + when(gameRepository.findByUserId(TEST_USER_ID)).thenReturn(games.stream()); + + Statistic result = statisticService.getUserStat(user1); + + assertEquals("Dima", result.getLogin()); + assertEquals(2, result.getWin()); + assertEquals(1, result.getLost()); + assertEquals(1, result.getPlay()); + assertEquals(4, result.getTotal()); + } +} \ No newline at end of file diff --git a/src/test/java/com/javarush/goncharov/service/UserServiceTest.java b/src/test/java/com/javarush/goncharov/service/UserServiceTest.java new file mode 100644 index 0000000..b02f327 --- /dev/null +++ b/src/test/java/com/javarush/goncharov/service/UserServiceTest.java @@ -0,0 +1,98 @@ +package com.javarush.goncharov.service; + +import com.javarush.goncharov.model.User; +import com.javarush.goncharov.repository.Repository; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; +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.Map; +import java.util.Optional; + +import static java.lang.Boolean.TRUE; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + + +@FieldDefaults(level = AccessLevel.PRIVATE) +@ExtendWith(MockitoExtension.class) +class UserServiceTest { + @Mock + Repository repository; + @InjectMocks + UserService userService; + + User user1; + User user2; + Map getAllMap; + + final Long TEST_USER_ID = 2L; + + @BeforeEach + void setup() { + user1 = User.builder().id(null).login("Dima").password("123").build(); + user2 = User.builder().id(null).login("Dima").password("123").build(); + getAllMap = Map.of(1L, user1, 2L, user2); + } + + @Test + @DisplayName("Create user") + void createUser() { + User createdUser = User.builder().id(TEST_USER_ID).login("Dima").password("123").build(); + when(repository.create(user1)).thenReturn(Optional.of(createdUser)); + + userService.post(user1); + + assertEquals(TEST_USER_ID, createdUser.getId()); + verify(repository).create(user1); + } + + @Test + @DisplayName("Get all users") + void getAllUsers() { + when(repository.getAll()).thenReturn(getAllMap); + + userService.getAll(); + + assertEquals(2, getAllMap.size()); + } + + @Test + @DisplayName("Update user") + void updateUser() { + User updatesUser = User.builder().id(124L).login("DimaNew").password("123").build(); + when(repository.update(user1)).thenReturn(Optional.of(updatesUser)); + + userService.update(user1); + + assertEquals(124L, updatesUser.getId()); + } + + @Test + @DisplayName("Delete user") + void deleteUser() { + Map getAllMapAfterDelete = Map.of(1L, user1); + when(repository.delete(user1)).thenReturn(TRUE); + + userService.delete(user1); + + assertEquals(1, getAllMapAfterDelete.size()); + } + + @Test + @DisplayName("Get one user") + void getOneUser() { + User getUser = User.builder().id(1111L).login("Nick").password("123").build(); + when(repository.get(1111L)).thenReturn(Optional.of(getUser)); + + userService.get(1111L); + + assertEquals(1111L, getUser.getId()); + } +} \ No newline at end of file