From b3e3039c53042e69064f08b047d55962e342e7aa Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 15 Jan 2026 14:27:39 +0300 Subject: [PATCH 1/8] Added a complex implementation of the project. No tests. --- pom.xml | 78 +++----- .../com/javarush/golikov/quest/auth/Role.java | 5 + .../golikov/quest/loader/TxtQuestLoader.java | 93 +++++++++ .../quest/logging/logger/AdminService.java | 5 + .../javarush/golikov/quest/model/Choice.java | 4 + .../javarush/golikov/quest/model/Quest.java | 31 +++ .../golikov/quest/model/QuestNode.java | 6 + .../golikov/quest/model/QuestSession.java | 62 ++++++ .../javarush/golikov/quest/model/Step.java | 4 + .../javarush/golikov/quest/model/User.java | 6 + .../quest/repository/QuestRepository.java | 62 ++++++ .../quest/repository/UserRepository.java | 38 ++++ .../golikov/quest/service/AdminService.java | 48 +++++ .../golikov/quest/service/AuthService.java | 20 ++ .../golikov/quest/service/QuestService.java | 62 ++++++ .../golikov/quest/web/AdminController.java | 28 +++ .../quest/web/AdminQuestDeleteController.java | 27 +++ .../quest/web/AdminQuestSaveController.java | 39 ++++ .../quest/web/AdminQuestsController.java | 38 ++++ .../quest/web/AdminUserDeleteController.java | 27 +++ .../quest/web/AdminUserEditController.java | 45 +++++ .../quest/web/AdminUserSaveController.java | 33 ++++ .../quest/web/AdminUsersController.java | 38 ++++ .../golikov/quest/web/AppInitController.java | 18 ++ .../golikov/quest/web/AppInitializer.java | 21 +++ .../quest/web/ExitQuestController.java | 36 ++++ .../golikov/quest/web/LoginController.java | 58 ++++++ .../golikov/quest/web/LogoutController.java | 29 +++ .../golikov/quest/web/QuestController.java | 81 ++++++++ .../quest/web/QuestListController.java | 29 +++ .../quest/web/StartQuestController.java | 30 +++ .../quest/web/UploadQuestController.java | 56 ++++++ .../com/javarush/khmelov/cmd/Command.java | 37 ---- .../com/javarush/khmelov/cmd/EditUser.java | 52 ----- .../com/javarush/khmelov/cmd/ListUser.java | 26 --- .../com/javarush/khmelov/cmd/StartPage.java | 6 - .../com/javarush/khmelov/config/Winter.java | 29 --- .../khmelov/controller/FrontController.java | 43 ----- .../khmelov/controller/HttpResolver.java | 41 ---- .../com/javarush/khmelov/entity/Role.java | 5 - .../com/javarush/khmelov/entity/User.java | 26 --- .../khmelov/repository/Repository.java | 19 -- .../khmelov/repository/UserRepository.java | 50 ----- .../javarush/khmelov/service/UserService.java | 36 ---- src/main/resources/quests/farm.txt | 18 ++ src/main/resources/quests/ufo.txt | 26 +++ src/main/webapp/WEB-INF/edit-user.jsp | 73 ------- src/main/webapp/WEB-INF/head.jsp | 11 -- src/main/webapp/WEB-INF/jsp/admin-quests.jsp | 159 ++++++++++++++++ src/main/webapp/WEB-INF/jsp/admin-users.jsp | 172 +++++++++++++++++ src/main/webapp/WEB-INF/jsp/admin.jsp | 22 +++ src/main/webapp/WEB-INF/jsp/login.jsp | 21 +++ src/main/webapp/WEB-INF/jsp/play.jsp | 38 ++++ src/main/webapp/WEB-INF/jsp/quest-view.jsp | 57 ++++++ src/main/webapp/WEB-INF/jsp/quests.jsp | 14 ++ src/main/webapp/WEB-INF/jsp/result.jsp | 34 ++++ src/main/webapp/WEB-INF/list-user.jsp | 9 - src/main/webapp/WEB-INF/start-page.jsp | 8 - src/main/webapp/index.jsp | 91 +++++++++ src/main/webapp/style.css | 178 ++++++++++++++++++ 60 files changed, 1936 insertions(+), 522 deletions(-) create mode 100644 src/main/java/com/javarush/golikov/quest/auth/Role.java create mode 100644 src/main/java/com/javarush/golikov/quest/loader/TxtQuestLoader.java create mode 100644 src/main/java/com/javarush/golikov/quest/logging/logger/AdminService.java create mode 100644 src/main/java/com/javarush/golikov/quest/model/Choice.java create mode 100644 src/main/java/com/javarush/golikov/quest/model/Quest.java create mode 100644 src/main/java/com/javarush/golikov/quest/model/QuestNode.java create mode 100644 src/main/java/com/javarush/golikov/quest/model/QuestSession.java create mode 100644 src/main/java/com/javarush/golikov/quest/model/Step.java create mode 100644 src/main/java/com/javarush/golikov/quest/model/User.java create mode 100644 src/main/java/com/javarush/golikov/quest/repository/QuestRepository.java create mode 100644 src/main/java/com/javarush/golikov/quest/repository/UserRepository.java create mode 100644 src/main/java/com/javarush/golikov/quest/service/AdminService.java create mode 100644 src/main/java/com/javarush/golikov/quest/service/AuthService.java create mode 100644 src/main/java/com/javarush/golikov/quest/service/QuestService.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/AdminController.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/AdminQuestDeleteController.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/AdminQuestSaveController.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/AdminQuestsController.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/AdminUserDeleteController.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/AdminUserEditController.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/AdminUserSaveController.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/AdminUsersController.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/AppInitController.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/AppInitializer.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/ExitQuestController.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/LoginController.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/LogoutController.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/QuestController.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/QuestListController.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/StartQuestController.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/UploadQuestController.java delete mode 100644 src/main/java/com/javarush/khmelov/cmd/Command.java delete mode 100644 src/main/java/com/javarush/khmelov/cmd/EditUser.java delete mode 100644 src/main/java/com/javarush/khmelov/cmd/ListUser.java delete mode 100644 src/main/java/com/javarush/khmelov/cmd/StartPage.java delete mode 100644 src/main/java/com/javarush/khmelov/config/Winter.java delete mode 100644 src/main/java/com/javarush/khmelov/controller/FrontController.java delete mode 100644 src/main/java/com/javarush/khmelov/controller/HttpResolver.java delete mode 100644 src/main/java/com/javarush/khmelov/entity/Role.java delete mode 100644 src/main/java/com/javarush/khmelov/entity/User.java delete mode 100644 src/main/java/com/javarush/khmelov/repository/Repository.java delete mode 100644 src/main/java/com/javarush/khmelov/repository/UserRepository.java delete mode 100644 src/main/java/com/javarush/khmelov/service/UserService.java create mode 100644 src/main/resources/quests/farm.txt create mode 100644 src/main/resources/quests/ufo.txt delete mode 100644 src/main/webapp/WEB-INF/edit-user.jsp delete mode 100644 src/main/webapp/WEB-INF/head.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/admin-quests.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/admin-users.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/admin.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/login.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/play.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/quest-view.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/quests.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/result.jsp delete mode 100644 src/main/webapp/WEB-INF/list-user.jsp delete mode 100644 src/main/webapp/WEB-INF/start-page.jsp create mode 100644 src/main/webapp/index.jsp create mode 100644 src/main/webapp/style.css diff --git a/pom.xml b/pom.xml index 78ee59d..7f3a053 100644 --- a/pom.xml +++ b/pom.xml @@ -1,94 +1,70 @@ - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 + https://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - com.javarush.khmelov - project-ledzeppelin - 1.0-SNAPSHOT - ProjectLedzeppelin + com.javarush.golikov + project-pantera + 1.0 war - UTF-8 - 21 - 21 - 5.10.2 + 17 + 17 - - org.springframework.boot - spring-boot-starter-parent - 3.3.5 - - - - - - org.springframework.boot - spring-boot-dependencies - pom - import - 3.3.5 - - - - + + jakarta.servlet jakarta.servlet-api + 6.0.0 provided + + jakarta.servlet.jsp.jstl jakarta.servlet.jsp.jstl-api + 3.0.0 + + org.glassfish.web jakarta.servlet.jsp.jstl - - - - org.projectlombok - lombok - provided - - - org.junit.jupiter - junit-jupiter-api - test - - - org.junit.jupiter - junit-jupiter-engine - test + 3.0.1 + project-pantera + org.apache.maven.plugins maven-war-plugin 3.4.0 + + false + + org.apache.maven.plugins maven-compiler-plugin + 3.11.0 - - - org.projectlombok - lombok - 1.18.34 - - + 17 + 17 + \ No newline at end of file diff --git a/src/main/java/com/javarush/golikov/quest/auth/Role.java b/src/main/java/com/javarush/golikov/quest/auth/Role.java new file mode 100644 index 0000000..60b3a19 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/auth/Role.java @@ -0,0 +1,5 @@ +package com.javarush.golikov.quest.auth; + +public enum Role { + ADMIN, USER +} diff --git a/src/main/java/com/javarush/golikov/quest/loader/TxtQuestLoader.java b/src/main/java/com/javarush/golikov/quest/loader/TxtQuestLoader.java new file mode 100644 index 0000000..3b99924 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/loader/TxtQuestLoader.java @@ -0,0 +1,93 @@ +package com.javarush.golikov.quest.loader; + +import com.javarush.golikov.quest.model.Choice; +import com.javarush.golikov.quest.model.Quest; +import com.javarush.golikov.quest.model.QuestNode; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.*; + +public class TxtQuestLoader { + + public static Quest load(InputStream in, String questId, String title) throws Exception { + + BufferedReader br = new BufferedReader( + new InputStreamReader(in) + ); + + Map nodes = new LinkedHashMap<>(); + + String line; + String currentId = null; + String currentText = null; + List choices = new ArrayList<>(); + + while ((line = br.readLine()) != null) { + line = line.trim(); + if (line.isEmpty()) continue; + + // ===== ОБЪЯВЛЕНИЕ УЗЛА ===== + if (line.startsWith("? ") && !line.substring(2).contains(" ")) { + + // сохраняем предыдущий узел + if (currentId != null) { + nodes.put(currentId, + new QuestNode(currentId, currentText, choices)); + } + + currentId = line.substring(2).trim(); + currentText = null; + choices = new ArrayList<>(); + } + + // ===== ТЕКСТ УЗЛА ===== + else if (line.startsWith("?")) { + + if (currentId == null) { + throw new RuntimeException( + "Node text without node id: " + line); + } + + currentText = line.substring(1).trim(); + } + + // ===== ВАРИАНТЫ ===== + else if (line.startsWith("+") || line.startsWith("-")) { + + if (currentId == null) { + throw new RuntimeException( + "Choice without node id: " + line); + } + + String body = line.substring(1).trim(); + String[] parts = body.split("->"); + + if (parts.length != 2) { + throw new RuntimeException( + "Invalid choice format: " + line); + } + + String text = parts[0].trim(); + String next = parts[1].trim(); + boolean positive = line.startsWith("+"); + + choices.add(new Choice(text, next, positive)); + } + } + + // сохраняем последний узел + if (currentId != null) { + nodes.put(currentId, + new QuestNode(currentId, currentText, choices)); + } + + // проверка обязательного старта + if (!nodes.containsKey("start")) { + throw new RuntimeException("Quest has no 'start' node"); + } + + return new Quest(questId, title, "start", nodes); + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/golikov/quest/logging/logger/AdminService.java b/src/main/java/com/javarush/golikov/quest/logging/logger/AdminService.java new file mode 100644 index 0000000..a08ad22 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/logging/logger/AdminService.java @@ -0,0 +1,5 @@ +package com.javarush.golikov.quest.logging.logger; + +public class AdminService { + +} diff --git a/src/main/java/com/javarush/golikov/quest/model/Choice.java b/src/main/java/com/javarush/golikov/quest/model/Choice.java new file mode 100644 index 0000000..f97d831 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/model/Choice.java @@ -0,0 +1,4 @@ +package com.javarush.golikov.quest.model; + +public record Choice(String text, String next, boolean positive) { +} \ No newline at end of file diff --git a/src/main/java/com/javarush/golikov/quest/model/Quest.java b/src/main/java/com/javarush/golikov/quest/model/Quest.java new file mode 100644 index 0000000..c60db7f --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/model/Quest.java @@ -0,0 +1,31 @@ +package com.javarush.golikov.quest.model; + +import java.util.Map; + +public class Quest { + private final String id; + private final String title; + private final String startNode; + private final Map nodes; + + public Quest(String id, String title, String startNode, Map nodes) { + this.id = id; + this.title = title; + this.startNode = startNode; + this.nodes = nodes; + } + + public QuestNode getStart() { + return nodes.get(startNode); + } + + public QuestNode getNode(String id) { + return nodes.get(id); + } + + public String getTitle() { return title; } + + public String getId() { + return id; + } +} diff --git a/src/main/java/com/javarush/golikov/quest/model/QuestNode.java b/src/main/java/com/javarush/golikov/quest/model/QuestNode.java new file mode 100644 index 0000000..0294f95 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/model/QuestNode.java @@ -0,0 +1,6 @@ +package com.javarush.golikov.quest.model; + +import java.util.List; + +public record QuestNode(String id, String text, List choices) { +} diff --git a/src/main/java/com/javarush/golikov/quest/model/QuestSession.java b/src/main/java/com/javarush/golikov/quest/model/QuestSession.java new file mode 100644 index 0000000..ec881e5 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/model/QuestSession.java @@ -0,0 +1,62 @@ +package com.javarush.golikov.quest.model; + +import java.util.ArrayList; +import java.util.List; + +public class QuestSession { + + private final String questId; + private String currentNode; + + // история шагов + private final List history = new ArrayList<>(); + + // состояние завершения + private boolean finished = false; + private boolean win = false; + + public QuestSession(String questId, String startNode) { + this.questId = questId; + this.currentNode = startNode; + } + + public String getQuestId() { + return questId; + } + + public String getCurrentNode() { + return currentNode; + } + + public void setCurrentNode(String currentNode) { + this.currentNode = currentNode; + } + + public List getHistory() { + return history; + } + + //добавить шаг в историю + public void addStep(String questionText, String answerText, boolean positive) { + history.add(new Step(questionText, answerText, positive)); + } + + //завершение + public void win() { + finished = true; + win = true; + } + + public void lose() { + finished = true; + win = false; + } + + public boolean isFinished() { + return finished; + } + + public boolean isWin() { + return win; + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/golikov/quest/model/Step.java b/src/main/java/com/javarush/golikov/quest/model/Step.java new file mode 100644 index 0000000..83eb091 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/model/Step.java @@ -0,0 +1,4 @@ +package com.javarush.golikov.quest.model; + +public record Step(String questionText, String answerText, boolean positive) { +} diff --git a/src/main/java/com/javarush/golikov/quest/model/User.java b/src/main/java/com/javarush/golikov/quest/model/User.java new file mode 100644 index 0000000..1e6588e --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/model/User.java @@ -0,0 +1,6 @@ +package com.javarush.golikov.quest.model; + +import com.javarush.golikov.quest.auth.Role; + +public record User(String login, String password, Role role) { +} \ No newline at end of file diff --git a/src/main/java/com/javarush/golikov/quest/repository/QuestRepository.java b/src/main/java/com/javarush/golikov/quest/repository/QuestRepository.java new file mode 100644 index 0000000..1866fc7 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/repository/QuestRepository.java @@ -0,0 +1,62 @@ +package com.javarush.golikov.quest.repository; + +import com.javarush.golikov.quest.model.Quest; +import com.javarush.golikov.quest.loader.TxtQuestLoader; +import jakarta.servlet.ServletContext; + +import java.io.InputStream; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class QuestRepository { + + private static final Map quests = new HashMap<>(); + + public static Collection all() { + return quests.values(); + } + + public static Quest get(String id) { + return quests.get(id); + } + + public static void clear() { + quests.clear(); + } + + public static void loadTxt(InputStream in, String id, String title) throws Exception { + Quest quest = TxtQuestLoader.load(in, id, title); + quests.put(id, quest); + } + + public static void loadAll(ServletContext ctx) { + try { + clear(); + + Set files = ctx.getResourcePaths("/WEB-INF/classes/quests/"); + + if (files == null) return; + + for (String path : files) { + if (!path.endsWith(".txt")) continue; + + String fileName = path.substring(path.lastIndexOf("/") + 1); + String questId = fileName.replace(".txt", ""); + String title = questId.substring(0,1).toUpperCase() + questId.substring(1); + + InputStream in = ctx.getResourceAsStream(path); + loadTxt(in, questId, title); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void remove(String id) { + quests.remove(id); + } +} + diff --git a/src/main/java/com/javarush/golikov/quest/repository/UserRepository.java b/src/main/java/com/javarush/golikov/quest/repository/UserRepository.java new file mode 100644 index 0000000..920e4f0 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/repository/UserRepository.java @@ -0,0 +1,38 @@ +package com.javarush.golikov.quest.repository; + +import com.javarush.golikov.quest.auth.Role; +import com.javarush.golikov.quest.model.User; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public class UserRepository { + + private static final Map users = new HashMap<>(); + + static { + users.put("admin", new User("admin", "admin", Role.ADMIN)); + } + + // 🔹 НАЙТИ пользователя (НУЖНО для логина) + public static User find(String login) { + return users.get(login); + } + + // 🔹 ВСЕ пользователи (для админки) + public static Collection all() { + return users.values(); + } + + // 🔹 СОХРАНИТЬ / ОБНОВИТЬ + public static void save(User u) { + users.put(u.login(), u); + } + + // 🔹 УДАЛИТЬ + public static void delete(String login) { + users.remove(login); + } +} + diff --git a/src/main/java/com/javarush/golikov/quest/service/AdminService.java b/src/main/java/com/javarush/golikov/quest/service/AdminService.java new file mode 100644 index 0000000..f5d3221 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/service/AdminService.java @@ -0,0 +1,48 @@ +package com.javarush.golikov.quest.service; + +import com.javarush.golikov.quest.model.User; +import com.javarush.golikov.quest.model.Quest; +import com.javarush.golikov.quest.repository.UserRepository; +import com.javarush.golikov.quest.repository.QuestRepository; + +import java.io.InputStream; +import java.util.Collection; + +public class AdminService { + + /* ===== USERS ===== */ + + public Collection getAllUsers() { + return UserRepository.all(); + } + + public void saveUser(User user) { + UserRepository.save(user); + } + + public void deleteUser(String login) { + UserRepository.delete(login); + } + + /* ===== QUESTS ===== */ + + public Collection getAllQuests() { + return QuestRepository.all(); + } + + public void loadQuestFromTxt(String id, String title, InputStream is) { + try { + QuestRepository.loadTxt(is, id, title); + } catch (Exception e) { + throw new IllegalStateException("Ошибка загрузки квеста: " + id, e); + } + } + + public void deleteQuest(String id) { + QuestRepository.remove(id); + } + + public User findUser(String login) { + return UserRepository.find(login); + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/golikov/quest/service/AuthService.java b/src/main/java/com/javarush/golikov/quest/service/AuthService.java new file mode 100644 index 0000000..6a12d16 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/service/AuthService.java @@ -0,0 +1,20 @@ +package com.javarush.golikov.quest.service; + +import com.javarush.golikov.quest.model.User; +import com.javarush.golikov.quest.repository.UserRepository; +import jakarta.servlet.http.HttpSession; + +public class AuthService { + + public User login(String login, String password) { + User user = UserRepository.find(login); + if (user != null && user.password().equals(password)) { + return user; + } + return null; + } + + public void logout(HttpSession session) { + session.invalidate(); + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/golikov/quest/service/QuestService.java b/src/main/java/com/javarush/golikov/quest/service/QuestService.java new file mode 100644 index 0000000..072073f --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/service/QuestService.java @@ -0,0 +1,62 @@ +package com.javarush.golikov.quest.service; + +import com.javarush.golikov.quest.model.*; +import com.javarush.golikov.quest.repository.QuestRepository; + +import java.util.Collection; + +public class QuestService { + + public QuestSession startQuest(String questId) { + Quest quest = QuestRepository.get(questId); + + if (quest == null) { + throw new IllegalArgumentException("Quest not found: " + questId); + } + + return new QuestSession(questId, quest.getStart().id()); + } + + public QuestNode getCurrentNode(QuestSession session) { + Quest quest = QuestRepository.get(session.getQuestId()); + return quest.getNode(session.getCurrentNode()); + } + + public boolean isFinalNode(QuestNode node) { + return node.choices().isEmpty(); + } + + public boolean isWinNode(QuestNode node) { + return node.text().toLowerCase().contains("победа"); + } + + public void applyChoice(QuestSession session, String next, String answer) { + + QuestNode node = getCurrentNode(session); + + Choice choice = node.choices().stream() + .filter(c -> c.next().equals(next)) + .findFirst() + .orElseThrow(); + + session.addStep( + node.text(), // ❓ текст вопроса + answer, // ➜ текст ответа + choice.positive() // ✔ / ✖ + ); + + session.setCurrentNode(next); + } + + public Collection getAllQuests() { + return QuestRepository.all(); + } + + public void exitQuest(QuestSession session) { + session.lose(); + } + + public String getQuestTitle(QuestSession qs) { + return QuestRepository.get(qs.getQuestId()).getTitle(); + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/golikov/quest/web/AdminController.java b/src/main/java/com/javarush/golikov/quest/web/AdminController.java new file mode 100644 index 0000000..6b849c6 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/AdminController.java @@ -0,0 +1,28 @@ +package com.javarush.golikov.quest.web; + +import jakarta.servlet.*; +import jakarta.servlet.http.*; +import jakarta.servlet.annotation.*; +import java.io.*; + +import com.javarush.golikov.quest.model.User; +import com.javarush.golikov.quest.auth.Role; + +@WebServlet("/admin") +public class AdminController extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws IOException, ServletException { + + User user = (User) req.getSession().getAttribute("user"); + if (user == null || user.role() != Role.ADMIN) { + resp.sendRedirect(req.getContextPath() + "/"); + return; + } + + req.setAttribute("view", "/WEB-INF/jsp/admin.jsp"); + req.getRequestDispatcher("/index.jsp").forward(req, resp); + } +} + diff --git a/src/main/java/com/javarush/golikov/quest/web/AdminQuestDeleteController.java b/src/main/java/com/javarush/golikov/quest/web/AdminQuestDeleteController.java new file mode 100644 index 0000000..14ba248 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/AdminQuestDeleteController.java @@ -0,0 +1,27 @@ +package com.javarush.golikov.quest.web; + +import com.javarush.golikov.quest.service.AdminService; +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("/admin-quest-delete") +public class AdminQuestDeleteController extends HttpServlet { + private AdminService adminService; + + @Override + public void init() { + adminService = (AdminService) getServletContext().getAttribute("adminService"); + } + + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws IOException { + + adminService.deleteQuest(req.getParameter("id")); + resp.sendRedirect(req.getContextPath() + "/admin-quests"); + } +} + diff --git a/src/main/java/com/javarush/golikov/quest/web/AdminQuestSaveController.java b/src/main/java/com/javarush/golikov/quest/web/AdminQuestSaveController.java new file mode 100644 index 0000000..ddb1f30 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/AdminQuestSaveController.java @@ -0,0 +1,39 @@ +package com.javarush.golikov.quest.web; + +import com.javarush.golikov.quest.service.AdminService; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.MultipartConfig; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.Part; + +import java.io.IOException; +import java.io.InputStream; + +@WebServlet("/admin-quest-save") +@MultipartConfig +public class AdminQuestSaveController extends HttpServlet { + private AdminService adminService; + + @Override + public void init() { + adminService = (AdminService) getServletContext().getAttribute("adminService"); + } + + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws IOException, ServletException { + + Part file = req.getPart("file"); + String id = req.getParameter("id"); + String title = req.getParameter("title"); + + try (InputStream is = file.getInputStream()) { + adminService.loadQuestFromTxt(id, title, is); + } + + resp.sendRedirect(req.getContextPath() + "/admin-quests"); + } +} + diff --git a/src/main/java/com/javarush/golikov/quest/web/AdminQuestsController.java b/src/main/java/com/javarush/golikov/quest/web/AdminQuestsController.java new file mode 100644 index 0000000..f8321ae --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/AdminQuestsController.java @@ -0,0 +1,38 @@ +package com.javarush.golikov.quest.web; + +import com.javarush.golikov.quest.auth.Role; +import com.javarush.golikov.quest.model.User; +import com.javarush.golikov.quest.service.AdminService; +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("/admin-quests") +public class AdminQuestsController extends HttpServlet { + private AdminService adminService; + + @Override + public void init() { + adminService = (AdminService) getServletContext().getAttribute("adminService"); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws IOException, ServletException { + + User user = (User) req.getSession().getAttribute("user"); + if (user == null || user.role() != Role.ADMIN) { + resp.sendRedirect(req.getContextPath() + "/"); + return; + } + + req.setAttribute("quests", adminService.getAllQuests()); + req.setAttribute("view", "/WEB-INF/jsp/admin-quests.jsp"); + req.getRequestDispatcher("/index.jsp").forward(req, resp); + } +} + diff --git a/src/main/java/com/javarush/golikov/quest/web/AdminUserDeleteController.java b/src/main/java/com/javarush/golikov/quest/web/AdminUserDeleteController.java new file mode 100644 index 0000000..ff3562f --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/AdminUserDeleteController.java @@ -0,0 +1,27 @@ +package com.javarush.golikov.quest.web; + +import com.javarush.golikov.quest.service.AdminService; +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("/admin-user-delete") +public class AdminUserDeleteController extends HttpServlet { + private AdminService adminService; + + @Override + public void init() { + adminService = (AdminService) getServletContext().getAttribute("adminService"); + } + + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws IOException { + + adminService.deleteUser(req.getParameter("login")); + resp.sendRedirect(req.getContextPath() + "/admin-users"); + } +} + diff --git a/src/main/java/com/javarush/golikov/quest/web/AdminUserEditController.java b/src/main/java/com/javarush/golikov/quest/web/AdminUserEditController.java new file mode 100644 index 0000000..5557f90 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/AdminUserEditController.java @@ -0,0 +1,45 @@ +package com.javarush.golikov.quest.web; + +import com.javarush.golikov.quest.auth.Role; +import com.javarush.golikov.quest.model.User; +import com.javarush.golikov.quest.service.AdminService; +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("/admin-user-edit") +public class AdminUserEditController extends HttpServlet { + + private AdminService adminService; + + @Override + public void init() { + adminService = (AdminService) getServletContext().getAttribute("adminService"); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws IOException, ServletException { + + // ===== ПРОВЕРКА АДМИНА ===== + User current = (User) req.getSession().getAttribute("user"); + if (current == null || current.role() != Role.ADMIN) { + resp.sendRedirect(req.getContextPath() + "/"); + return; + } + + // ===== ДАННЫЕ ===== + User editUser = adminService.findUser(req.getParameter("login")); + + req.setAttribute("editUser", editUser); + req.setAttribute("users", adminService.getAllUsers()); + + // ===== VIEW ===== + req.setAttribute("view", "/WEB-INF/jsp/admin-users.jsp"); + req.getRequestDispatcher("/index.jsp").forward(req, resp); + } +} diff --git a/src/main/java/com/javarush/golikov/quest/web/AdminUserSaveController.java b/src/main/java/com/javarush/golikov/quest/web/AdminUserSaveController.java new file mode 100644 index 0000000..952d658 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/AdminUserSaveController.java @@ -0,0 +1,33 @@ +package com.javarush.golikov.quest.web; + +import com.javarush.golikov.quest.auth.Role; +import com.javarush.golikov.quest.model.User; +import com.javarush.golikov.quest.service.AdminService; +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("/admin-user-save") +public class AdminUserSaveController extends HttpServlet { + private AdminService adminService; + + @Override + public void init() { + adminService = (AdminService) getServletContext().getAttribute("adminService"); + } + + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws IOException { + + String login = req.getParameter("login"); + String pass = req.getParameter("password"); + Role role = Role.valueOf(req.getParameter("role")); + + adminService.saveUser(new User(login, pass, role)); + resp.sendRedirect(req.getContextPath() + "/admin-users"); + } +} + diff --git a/src/main/java/com/javarush/golikov/quest/web/AdminUsersController.java b/src/main/java/com/javarush/golikov/quest/web/AdminUsersController.java new file mode 100644 index 0000000..003a0f7 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/AdminUsersController.java @@ -0,0 +1,38 @@ +package com.javarush.golikov.quest.web; + +import com.javarush.golikov.quest.auth.Role; +import com.javarush.golikov.quest.model.User; +import com.javarush.golikov.quest.service.AdminService; +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("/admin-users") +public class AdminUsersController extends HttpServlet { + private AdminService adminService; + + @Override + public void init() { + adminService = (AdminService) getServletContext().getAttribute("adminService"); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws IOException, ServletException { + + User user = (User) req.getSession().getAttribute("user"); + if (user == null || user.role() != Role.ADMIN) { + resp.sendRedirect("index.jsp"); + return; + } + + req.setAttribute("users", adminService.getAllUsers()); + req.setAttribute("view", "/WEB-INF/jsp/admin-users.jsp"); + req.getRequestDispatcher("/index.jsp").forward(req, resp); + } +} + diff --git a/src/main/java/com/javarush/golikov/quest/web/AppInitController.java b/src/main/java/com/javarush/golikov/quest/web/AppInitController.java new file mode 100644 index 0000000..ac23dbc --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/AppInitController.java @@ -0,0 +1,18 @@ +package com.javarush.golikov.quest.web; + +import jakarta.servlet.annotation.*; + +import com.javarush.golikov.quest.repository.QuestRepository; +import jakarta.servlet.http.HttpServlet; + + +@WebServlet(urlPatterns = "/init", loadOnStartup = 1) +public class AppInitController extends HttpServlet { + + public void init() { + QuestRepository.loadAll(getServletContext()); + } +} + + + diff --git a/src/main/java/com/javarush/golikov/quest/web/AppInitializer.java b/src/main/java/com/javarush/golikov/quest/web/AppInitializer.java new file mode 100644 index 0000000..5952994 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/AppInitializer.java @@ -0,0 +1,21 @@ +package com.javarush.golikov.quest.web; + +import com.javarush.golikov.quest.service.AuthService; +import com.javarush.golikov.quest.service.QuestService; +import com.javarush.golikov.quest.service.AdminService; + +import jakarta.servlet.ServletContextEvent; +import jakarta.servlet.ServletContextListener; +import jakarta.servlet.annotation.WebListener; + +@WebListener +public class AppInitializer implements ServletContextListener { + + @Override + public void contextInitialized(ServletContextEvent sce) { + + sce.getServletContext().setAttribute("authService", new AuthService()); + sce.getServletContext().setAttribute("questService", new QuestService()); + sce.getServletContext().setAttribute("adminService", new AdminService()); + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/golikov/quest/web/ExitQuestController.java b/src/main/java/com/javarush/golikov/quest/web/ExitQuestController.java new file mode 100644 index 0000000..0ad9453 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/ExitQuestController.java @@ -0,0 +1,36 @@ +package com.javarush.golikov.quest.web; + +import com.javarush.golikov.quest.model.QuestSession; +import com.javarush.golikov.quest.service.QuestService; +import jakarta.servlet.*; +import jakarta.servlet.http.*; +import jakarta.servlet.annotation.*; +import java.io.*; + +@WebServlet("/exitQuest") +public class ExitQuestController extends HttpServlet { + private QuestService questService; + + @Override + public void init() { + questService = (QuestService) getServletContext().getAttribute("questService"); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws IOException, ServletException { + + QuestSession qs = (QuestSession) req.getSession().getAttribute("quest"); + + if (qs != null) { + questService.exitQuest(qs); + req.setAttribute("result", "lose"); + req.getSession().removeAttribute("quest"); + } + + // показываем экран результата + req.setAttribute("view", "/WEB-INF/jsp/result.jsp"); + req.getRequestDispatcher("/index.jsp").forward(req, resp); + } +} + diff --git a/src/main/java/com/javarush/golikov/quest/web/LoginController.java b/src/main/java/com/javarush/golikov/quest/web/LoginController.java new file mode 100644 index 0000000..d03d376 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/LoginController.java @@ -0,0 +1,58 @@ +package com.javarush.golikov.quest.web; + +import com.javarush.golikov.quest.model.User; +import com.javarush.golikov.quest.service.AuthService; + +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("/login") +public class LoginController extends HttpServlet { + + private AuthService authService; + + @Override + public void init() { + authService = (AuthService) getServletContext().getAttribute("authService"); + } + + /** + * GET — показать форму логина + */ + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + + req.setAttribute("view", "/WEB-INF/jsp/login.jsp"); + req.getRequestDispatcher("/index.jsp").forward(req, resp); + } + + /** + * POST — обработка логина + */ + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + + String login = req.getParameter("login"); + String password = req.getParameter("password"); + + User user = authService.login(login, password); + + if (user != null) { + req.getSession().setAttribute("user", user); + + // redirect на контроллер, а не JSP + resp.sendRedirect(req.getContextPath() + "/"); + } else { + req.setAttribute("error", true); + req.setAttribute("view", "/WEB-INF/jsp/login.jsp"); + req.getRequestDispatcher("/index.jsp").forward(req, resp); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/golikov/quest/web/LogoutController.java b/src/main/java/com/javarush/golikov/quest/web/LogoutController.java new file mode 100644 index 0000000..e75dbf3 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/LogoutController.java @@ -0,0 +1,29 @@ +package com.javarush.golikov.quest.web; + +import com.javarush.golikov.quest.service.AuthService; + +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("/logout") +public class LogoutController extends HttpServlet { + + private AuthService authService; + + @Override + public void init() { + authService = (AuthService) getServletContext().getAttribute("authService"); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws IOException { + + authService.logout(req.getSession()); + resp.sendRedirect(req.getContextPath() + "/"); + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/golikov/quest/web/QuestController.java b/src/main/java/com/javarush/golikov/quest/web/QuestController.java new file mode 100644 index 0000000..e51010f --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/QuestController.java @@ -0,0 +1,81 @@ +package com.javarush.golikov.quest.web; + +import com.javarush.golikov.quest.model.QuestNode; +import com.javarush.golikov.quest.model.QuestSession; +import com.javarush.golikov.quest.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 java.io.IOException; + +@WebServlet("/play") +public class QuestController extends HttpServlet { + + private QuestService questService; + + @Override + public void init() { + questService = (QuestService) getServletContext().getAttribute("questService"); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws IOException, ServletException { + + QuestSession qs = (QuestSession) req.getSession().getAttribute("quest"); + + if (qs == null) { + resp.sendRedirect(req.getContextPath() + "/"); + return; + } + + QuestNode node = questService.getCurrentNode(qs); + + // ===== ФИНАЛ КВЕСТА ===== + if (questService.isFinalNode(node)) { + + if (questService.isWinNode(node)) { + qs.win(); + req.setAttribute("result", "win"); + } else { + qs.lose(); + req.setAttribute("result", "lose"); + } + + req.getSession().removeAttribute("quest"); + + req.setAttribute("view", "/WEB-INF/jsp/result.jsp"); + req.getRequestDispatcher("/index.jsp").forward(req, resp); + return; + } + + // ===== ОБЫЧНЫЙ ШАГ КВЕСТА ===== + req.setAttribute("node", node); + req.setAttribute("questSession", qs); + req.setAttribute("questTitle", questService.getQuestTitle(qs)); + + req.setAttribute("view", "/WEB-INF/jsp/quest-view.jsp"); + req.getRequestDispatcher("/index.jsp").forward(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws IOException { + + QuestSession qs = (QuestSession) req.getSession().getAttribute("quest"); + if (qs == null) { + resp.sendRedirect(req.getContextPath() + "/"); + return; + } + + String next = req.getParameter("next"); + String answer = req.getParameter("answer"); + + questService.applyChoice(qs, next, answer); + + resp.sendRedirect(req.getContextPath() +"/play"); + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/golikov/quest/web/QuestListController.java b/src/main/java/com/javarush/golikov/quest/web/QuestListController.java new file mode 100644 index 0000000..05e73d0 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/QuestListController.java @@ -0,0 +1,29 @@ +package com.javarush.golikov.quest.web; + +import com.javarush.golikov.quest.service.QuestService; +import jakarta.servlet.*; +import jakarta.servlet.http.*; +import jakarta.servlet.annotation.*; +import java.io.*; + +@WebServlet("/quests") +public class QuestListController extends HttpServlet { + private QuestService questService; + + @Override + public void init() { + questService = (QuestService) getServletContext().getAttribute("questService"); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws IOException, ServletException { + + req.setAttribute("quests", questService.getAllQuests()); + + // говорим index.jsp, что нужно показать список квестов + req.setAttribute("view", "/WEB-INF/jsp/quests.jsp"); + + req.getRequestDispatcher("/index.jsp").forward(req, resp); + } +} diff --git a/src/main/java/com/javarush/golikov/quest/web/StartQuestController.java b/src/main/java/com/javarush/golikov/quest/web/StartQuestController.java new file mode 100644 index 0000000..e948f65 --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/StartQuestController.java @@ -0,0 +1,30 @@ +package com.javarush.golikov.quest.web; + +import com.javarush.golikov.quest.service.QuestService; +import jakarta.servlet.http.*; +import jakarta.servlet.annotation.*; +import java.io.*; + +import com.javarush.golikov.quest.model.*; + +@WebServlet("/start") +public class StartQuestController extends HttpServlet { + private QuestService questService; + + @Override + public void init() { + questService = (QuestService) getServletContext().getAttribute("questService"); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws IOException { + + String id = req.getParameter("id"); + + QuestSession qs = questService.startQuest(id); + + req.getSession().setAttribute("quest", qs); + resp.sendRedirect(req.getContextPath() + "/play"); + } +} \ No newline at end of file diff --git a/src/main/java/com/javarush/golikov/quest/web/UploadQuestController.java b/src/main/java/com/javarush/golikov/quest/web/UploadQuestController.java new file mode 100644 index 0000000..f2eeb5b --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/UploadQuestController.java @@ -0,0 +1,56 @@ +package com.javarush.golikov.quest.web; + +import com.javarush.golikov.quest.auth.Role; +import com.javarush.golikov.quest.model.User; +import com.javarush.golikov.quest.service.AdminService; +import jakarta.servlet.*; +import jakarta.servlet.http.*; +import jakarta.servlet.annotation.*; +import java.io.*; +import java.util.logging.Logger; + +@WebServlet("/upload") +@MultipartConfig +public class UploadQuestController extends HttpServlet { + + private static final Logger log = + Logger.getLogger(UploadQuestController.class.getName()); + + private AdminService adminService; + + @Override + public void init() { + adminService = (AdminService) getServletContext().getAttribute("adminService"); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws IOException, ServletException { + + // ===== ПРОВЕРКА АДМИНА ===== + User user = (User) req.getSession().getAttribute("user"); + if (user == null || user.role() != Role.ADMIN) { + resp.sendRedirect(req.getContextPath() + "/"); + return; + } + + Part file = req.getPart("file"); + String id = req.getParameter("id"); + String title = req.getParameter("title"); + + try (InputStream is = file.getInputStream()) { + + adminService.loadQuestFromTxt(id, title, is); + + // redirect НА КОНТРОЛЛЕР АДМИН-КВЕСТОВ + resp.sendRedirect(req.getContextPath() + "/admin-quests"); + + } catch (Exception e) { + + log.severe("Ошибка загрузки квеста '" + id + "': " + e.getMessage()); + + resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + resp.getWriter().println("Load error"); + } + } +} 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/quests/farm.txt b/src/main/resources/quests/farm.txt new file mode 100644 index 0000000..d544fe0 --- /dev/null +++ b/src/main/resources/quests/farm.txt @@ -0,0 +1,18 @@ +? start +? Ты попал на ферму. Ты стоишь перед сараем. Открыть его? ++ Да, открыть сарай -> barn +- Нет, уйти -> lose_leave + +? barn +? Ты вошёл в сарай. Перед тобой свинья. Погладить её? ++ Погладить свинью -> pig_happy +- Не трогать -> pig_angry + +? pig_happy +? Свинья довольна и находит для тебя золото. Победа! + +? pig_angry +? Свинья укусила тебя. Поражение. + +? lose_leave +? Ты ушёл с фермы и потерял шанс. Поражение. \ No newline at end of file diff --git a/src/main/resources/quests/ufo.txt b/src/main/resources/quests/ufo.txt new file mode 100644 index 0000000..48c6d9c --- /dev/null +++ b/src/main/resources/quests/ufo.txt @@ -0,0 +1,26 @@ +? start +? Ты потерял память. Принять вызов НЛО? ++ Принять вызов -> accept +- Отклонить вызов -> lose_call + +? accept +? Ты принял вызов. Поднимаешься на мостик к капитану? ++ Подняться на мостик -> bridge +- Отказаться подниматься на мостик -> lose_talk + +? bridge +? Ты поднялся на мостик. Ты кто? ++ Рассказать правду о себе -> win +- Солгать о себе -> lose_lie + +? win +? Тебя вернули домой. Победа! + +? lose_call +? Ты отклонил вызов. Поражение. + +? lose_talk +? Ты не пошёл на переговоры. Поражение. + +? lose_lie +? Твоя ложь разоблачена. Поражение. \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/edit-user.jsp b/src/main/webapp/WEB-INF/edit-user.jsp deleted file mode 100644 index f274104..0000000 --- a/src/main/webapp/WEB-INF/edit-user.jsp +++ /dev/null @@ -1,73 +0,0 @@ -<%@ page contentType="text/html;charset=UTF-8" language="java" %> -<%@include file="head.jsp" %> - -
-
-
- - - Edit user: - - -
- -
- - min 3 symbols -
-
- - -
- -
- - min 8 symb -
-
- - - -
- -
- -
-
- - -
- -
- - - - - - - -
-
- -
-
-
- - diff --git a/src/main/webapp/WEB-INF/head.jsp b/src/main/webapp/WEB-INF/head.jsp deleted file mode 100644 index 2f7b9f2..0000000 --- a/src/main/webapp/WEB-INF/head.jsp +++ /dev/null @@ -1,11 +0,0 @@ -<%@ page contentType="text/html;charset=UTF-8" language="java" %> -<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> - - - Title - - - \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/admin-quests.jsp b/src/main/webapp/WEB-INF/jsp/admin-quests.jsp new file mode 100644 index 0000000..6b7f91d --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/admin-quests.jsp @@ -0,0 +1,159 @@ +<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> +<%@ taglib prefix="c" uri="jakarta.tags.core" %> + + + + + + Управление квестами + + + + + +

Управление квестами

+ + + + + + + + + + + + + + + +
IDНазваниеДействия
${q.id}${q.title} + + +
+ +
+ + + + +
+ +
+ + + + + + +
+ +← Вернуться в админ-панель + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/admin-users.jsp b/src/main/webapp/WEB-INF/jsp/admin-users.jsp new file mode 100644 index 0000000..65b7ee6 --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/admin-users.jsp @@ -0,0 +1,172 @@ +<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> +<%@ taglib prefix="c" uri="jakarta.tags.core" %> + + + + + + Управление пользователями + + + + + +

Управление пользователями

+ + + + + + + + + + + + + + + +
ЛогинРольДействия
${u.login()}${u.role()} + + +
+ +
+ + + + +
+ +
+ + + + + + +
+ +← Вернуться в админ-панель + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/admin.jsp b/src/main/webapp/WEB-INF/jsp/admin.jsp new file mode 100644 index 0000000..5da7794 --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/admin.jsp @@ -0,0 +1,22 @@ +<%@ page contentType="text/html;charset=UTF-8" %> + + + + + Админ-панель + + + +

Админ-панель

+ + + +
+ +← Вернуться на стартовую страницу + + + diff --git a/src/main/webapp/WEB-INF/jsp/login.jsp b/src/main/webapp/WEB-INF/jsp/login.jsp new file mode 100644 index 0000000..26c1e89 --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/login.jsp @@ -0,0 +1,21 @@ +<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> + +

Вход

+ +<% if (request.getAttribute("error") != null) { %> +

Неверный логин или пароль

+<% } %> + +
+

+ +

+ + +
\ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/play.jsp b/src/main/webapp/WEB-INF/jsp/play.jsp new file mode 100644 index 0000000..5d0d284 --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/play.jsp @@ -0,0 +1,38 @@ +<%@ page contentType="text/html;charset=UTF-8" %> +<%@ page import="com.javarush.golikov.quest.model.*" %> + +<% + QuestNode node = (QuestNode) request.getAttribute("node"); +%> + + + + + Квест + + + +

<%= node.text() %>

+ + +<% for (Choice c : node.choices()) { %> +
+ + +
+<% } %> + +
+ + +
+ +
+ + +
+ +
+ + + diff --git a/src/main/webapp/WEB-INF/jsp/quest-view.jsp b/src/main/webapp/WEB-INF/jsp/quest-view.jsp new file mode 100644 index 0000000..d5569b3 --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/quest-view.jsp @@ -0,0 +1,57 @@ +<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> +<%@ page import="com.javarush.golikov.quest.model.*" %> + +<% + QuestSession qs = (QuestSession) session.getAttribute("quest"); + QuestNode node = (QuestNode) request.getAttribute("node"); +%> + + +

+ ${requestScope.questTitle} +

+ +
+ + +
+ <% for (Step step : qs.getHistory()) { %> +
+
<%= step.questionText() %>
+
+ Вы выбрали: <%= step.answerText() %> +
+
+ <% } %> +
+ + +
+ <%= node.text() %> +
+ +
+ + <% for (Choice c : node.choices()) { %> + + + + <% } %> +
+ + +
+ +
+ +
\ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/quests.jsp b/src/main/webapp/WEB-INF/jsp/quests.jsp new file mode 100644 index 0000000..29f6270 --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/quests.jsp @@ -0,0 +1,14 @@ +<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> +<%@ taglib prefix="c" uri="jakarta.tags.core" %> + +

Доступные квесты

+ + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/result.jsp b/src/main/webapp/WEB-INF/jsp/result.jsp new file mode 100644 index 0000000..878f7aa --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/result.jsp @@ -0,0 +1,34 @@ +<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> +<%@ taglib prefix="c" uri="jakarta.tags.core" %> + +
+ +

+ + + Победа! + + + Поражение + + +

+ +

+ + + Квест успешно завершён + + + Квест завершён досрочно + + +

+ +

Возврат к выбору квеста...

+ +
+ + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/list-user.jsp b/src/main/webapp/WEB-INF/list-user.jsp deleted file mode 100644 index dd52c55..0000000 --- a/src/main/webapp/WEB-INF/list-user.jsp +++ /dev/null @@ -1,9 +0,0 @@ -<%@ page contentType="text/html;charset=UTF-8" language="java" %> -<%@include file="head.jsp"%> - - - ${user.login} - - - - diff --git a/src/main/webapp/WEB-INF/start-page.jsp b/src/main/webapp/WEB-INF/start-page.jsp deleted file mode 100644 index 0531c1c..0000000 --- a/src/main/webapp/WEB-INF/start-page.jsp +++ /dev/null @@ -1,8 +0,0 @@ -<%@ page contentType="text/html;charset=UTF-8" language="java" %> -<%@include file="head.jsp"%> - -

<%= "Hello World!" %> -

-
-List Users - diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp new file mode 100644 index 0000000..75b3bf7 --- /dev/null +++ b/src/main/webapp/index.jsp @@ -0,0 +1,91 @@ +<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> +<%@ taglib prefix="c" uri="jakarta.tags.core" %> +<%@ taglib prefix="fn" uri="jakarta.tags.functions" %> + + + + + + Текстовые квесты + + + + +
+ + + + + +
+ + + + + + + +

Добро пожаловать в текстовые квесты

+ Выбрать квест +
+
+ +
+ +
+ + + \ No newline at end of file diff --git a/src/main/webapp/style.css b/src/main/webapp/style.css new file mode 100644 index 0000000..5f2c583 --- /dev/null +++ b/src/main/webapp/style.css @@ -0,0 +1,178 @@ +/* ===== ОСНОВНАЯ РАЗМЕТКА ===== */ +body { + margin: 0; + font-family: Arial, sans-serif; +} + +.layout { + display: flex; + min-height: 100vh; +} + +/* ===== ЛЕВОЕ МЕНЮ ===== */ +.menu { + width: 220px; + padding: 15px; + background: #f2f2f2; + border-right: 2px solid #ccc; +} + +.menu h3 { + margin-top: 0; +} + +.menu a { + display: block; + margin-bottom: 10px; + text-decoration: none; + color: #000; +} + +.menu a:hover { + text-decoration: underline; +} + +/* ===== ЦЕНТР ===== */ +.content { + flex: 1; + padding: 30px; +} + +/* ============================= + ОФОРМЛЕНИЕ КВЕСТА (СХЕМА) + ============================= */ + +.quest-header { + text-align: center; + margin-bottom: 30px; +} + +/* ВОПРОС */ +.flow-question { + margin: 0 auto 40px; + max-width: 700px; + padding: 20px 30px; + + border: 2px solid #2b2b2b; + border-radius: 4px; + + background: #38d9a9; + color: #000; + + font-size: 18px; + text-align: center; + font-weight: 500; +} + +/* ОТВЕТЫ */ +.flow-answers { + display: flex; + justify-content: center; + gap: 80px; +} + +.flow-form { + margin: 0; +} + +/* КНОПКИ-КВАДРАТЫ */ +.flow-answer { + min-width: 220px; + padding: 15px 20px; + + border: 2px solid #2b2b2b; + border-radius: 4px; + + font-size: 16px; + font-weight: 500; + cursor: pointer; +} + +/* ДА */ +.flow-answer.yes { + background: #38d9a9; +} + +/* НЕТ */ +.flow-answer.no { + background: #ff9f7a; +} + +.flow-answer:hover { + filter: brightness(0.95); +} + +.flow-question.old { + background: #e6e6e6; + color: #444; + border-style: dashed; + margin-bottom: 20px; +} + +.flow-question.old .chosen { + margin-top: 10px; + font-size: 14px; +} + +/* ===== ИСТОРИЯ КВЕСТА ===== */ + +.flow-history .answer-text { + font-size: 14px; + font-weight: 500; +} + +.flow-history .answer-text.yes { + color: #2f9e44; /* зелёный текст */ +} + +.flow-history .answer-text.no { + color: #d9480f; /* оранжевый текст */ +} + +/* ===== ВСПОМОГАТЕЛЬНЫЕ КЛАССЫ (ДЛЯ JSP, БЕЗ inline-style) ===== */ + +.hidden { + display: none; +} + +.inline { + display: inline; +} + +.margin-top { + margin-top: 15px; +} + +/* ===== ТАБЛИЦЫ АДМИНКИ ===== */ + +.admin-table { + border-collapse: collapse; + width: 100%; +} + +.admin-table th, +.admin-table td { + border: 1px solid #2b2b2b; + padding: 5px; + text-align: left; +} + +.admin-table th { + background-color: #f2f2f2; + font-weight: bold; +} + +/* ===== РЕЗУЛЬТАТ КВЕСТА ===== */ + +.result-box { + text-align: center; + margin-top: 50px; +} + +.result-win { + color: green; +} + +.result-lose { + color: red; +} \ No newline at end of file From 0fe291808680f0454ce01b0f326951d613a53808 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 15 Jan 2026 17:13:31 +0300 Subject: [PATCH 2/8] Corrected Admin's logic. Added AbstractAdminController. Fixed the display of the Admin Panel. No tests. --- .../javarush/golikov/quest/model/User.java | 12 +++ .../golikov/quest/web/AdminController.java | 10 +- .../quest/web/AdminQuestDeleteController.java | 14 ++- .../quest/web/AdminQuestSaveController.java | 14 ++- .../quest/web/AdminQuestsController.java | 16 +-- .../quest/web/AdminUserDeleteController.java | 16 ++- .../quest/web/AdminUserEditController.java | 45 --------- .../quest/web/AdminUserSaveController.java | 15 ++- .../quest/web/AdminUsersController.java | 19 +--- .../web/admin/AbstractAdminController.java | 32 ++++++ src/main/webapp/WEB-INF/jsp/admin-users.jsp | 98 ++++++++++++------- src/main/webapp/index.jsp | 80 ++++++--------- src/main/webapp/style.css | 10 ++ 13 files changed, 182 insertions(+), 199 deletions(-) delete mode 100644 src/main/java/com/javarush/golikov/quest/web/AdminUserEditController.java create mode 100644 src/main/java/com/javarush/golikov/quest/web/admin/AbstractAdminController.java diff --git a/src/main/java/com/javarush/golikov/quest/model/User.java b/src/main/java/com/javarush/golikov/quest/model/User.java index 1e6588e..9e0b80f 100644 --- a/src/main/java/com/javarush/golikov/quest/model/User.java +++ b/src/main/java/com/javarush/golikov/quest/model/User.java @@ -3,4 +3,16 @@ import com.javarush.golikov.quest.auth.Role; public record User(String login, String password, Role role) { + // ДЛЯ JSP EL + public String getLogin() { + return login; + } + + public Role getRole() { + return role; + } + + public boolean isAdmin() { + return role == Role.ADMIN; + } } \ No newline at end of file diff --git a/src/main/java/com/javarush/golikov/quest/web/AdminController.java b/src/main/java/com/javarush/golikov/quest/web/AdminController.java index 6b849c6..87f12d8 100644 --- a/src/main/java/com/javarush/golikov/quest/web/AdminController.java +++ b/src/main/java/com/javarush/golikov/quest/web/AdminController.java @@ -1,23 +1,19 @@ package com.javarush.golikov.quest.web; +import com.javarush.golikov.quest.web.admin.AbstractAdminController; import jakarta.servlet.*; import jakarta.servlet.http.*; import jakarta.servlet.annotation.*; import java.io.*; -import com.javarush.golikov.quest.model.User; -import com.javarush.golikov.quest.auth.Role; - @WebServlet("/admin") -public class AdminController extends HttpServlet { +public class AdminController extends AbstractAdminController { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { - User user = (User) req.getSession().getAttribute("user"); - if (user == null || user.role() != Role.ADMIN) { - resp.sendRedirect(req.getContextPath() + "/"); + if (checkAdmin(req, resp)) { return; } diff --git a/src/main/java/com/javarush/golikov/quest/web/AdminQuestDeleteController.java b/src/main/java/com/javarush/golikov/quest/web/AdminQuestDeleteController.java index 14ba248..af698da 100644 --- a/src/main/java/com/javarush/golikov/quest/web/AdminQuestDeleteController.java +++ b/src/main/java/com/javarush/golikov/quest/web/AdminQuestDeleteController.java @@ -1,25 +1,23 @@ package com.javarush.golikov.quest.web; import com.javarush.golikov.quest.service.AdminService; +import com.javarush.golikov.quest.web.admin.AbstractAdminController; 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("/admin-quest-delete") -public class AdminQuestDeleteController extends HttpServlet { - private AdminService adminService; - - @Override - public void init() { - adminService = (AdminService) getServletContext().getAttribute("adminService"); - } +public class AdminQuestDeleteController extends AbstractAdminController { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + if (checkAdmin(req, resp)) { + return; + } + adminService.deleteQuest(req.getParameter("id")); resp.sendRedirect(req.getContextPath() + "/admin-quests"); } diff --git a/src/main/java/com/javarush/golikov/quest/web/AdminQuestSaveController.java b/src/main/java/com/javarush/golikov/quest/web/AdminQuestSaveController.java index ddb1f30..5f13bfc 100644 --- a/src/main/java/com/javarush/golikov/quest/web/AdminQuestSaveController.java +++ b/src/main/java/com/javarush/golikov/quest/web/AdminQuestSaveController.java @@ -1,10 +1,10 @@ package com.javarush.golikov.quest.web; import com.javarush.golikov.quest.service.AdminService; +import com.javarush.golikov.quest.web.admin.AbstractAdminController; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.MultipartConfig; import jakarta.servlet.annotation.WebServlet; -import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.Part; @@ -14,17 +14,15 @@ @WebServlet("/admin-quest-save") @MultipartConfig -public class AdminQuestSaveController extends HttpServlet { - private AdminService adminService; - - @Override - public void init() { - adminService = (AdminService) getServletContext().getAttribute("adminService"); - } +public class AdminQuestSaveController extends AbstractAdminController { protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + if (checkAdmin(req, resp)) { + return; + } + Part file = req.getPart("file"); String id = req.getParameter("id"); String title = req.getParameter("title"); diff --git a/src/main/java/com/javarush/golikov/quest/web/AdminQuestsController.java b/src/main/java/com/javarush/golikov/quest/web/AdminQuestsController.java index f8321ae..89be26d 100644 --- a/src/main/java/com/javarush/golikov/quest/web/AdminQuestsController.java +++ b/src/main/java/com/javarush/golikov/quest/web/AdminQuestsController.java @@ -1,32 +1,22 @@ package com.javarush.golikov.quest.web; -import com.javarush.golikov.quest.auth.Role; -import com.javarush.golikov.quest.model.User; import com.javarush.golikov.quest.service.AdminService; +import com.javarush.golikov.quest.web.admin.AbstractAdminController; 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("/admin-quests") -public class AdminQuestsController extends HttpServlet { - private AdminService adminService; - - @Override - public void init() { - adminService = (AdminService) getServletContext().getAttribute("adminService"); - } +public class AdminQuestsController extends AbstractAdminController { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { - User user = (User) req.getSession().getAttribute("user"); - if (user == null || user.role() != Role.ADMIN) { - resp.sendRedirect(req.getContextPath() + "/"); + if (checkAdmin(req, resp)) { return; } diff --git a/src/main/java/com/javarush/golikov/quest/web/AdminUserDeleteController.java b/src/main/java/com/javarush/golikov/quest/web/AdminUserDeleteController.java index ff3562f..28c608b 100644 --- a/src/main/java/com/javarush/golikov/quest/web/AdminUserDeleteController.java +++ b/src/main/java/com/javarush/golikov/quest/web/AdminUserDeleteController.java @@ -1,27 +1,23 @@ package com.javarush.golikov.quest.web; -import com.javarush.golikov.quest.service.AdminService; +import com.javarush.golikov.quest.web.admin.AbstractAdminController; 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("/admin-user-delete") -public class AdminUserDeleteController extends HttpServlet { - private AdminService adminService; - - @Override - public void init() { - adminService = (AdminService) getServletContext().getAttribute("adminService"); - } +public class AdminUserDeleteController extends AbstractAdminController { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + if (checkAdmin(req, resp)) { + return; + } + adminService.deleteUser(req.getParameter("login")); resp.sendRedirect(req.getContextPath() + "/admin-users"); } } - diff --git a/src/main/java/com/javarush/golikov/quest/web/AdminUserEditController.java b/src/main/java/com/javarush/golikov/quest/web/AdminUserEditController.java deleted file mode 100644 index 5557f90..0000000 --- a/src/main/java/com/javarush/golikov/quest/web/AdminUserEditController.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.javarush.golikov.quest.web; - -import com.javarush.golikov.quest.auth.Role; -import com.javarush.golikov.quest.model.User; -import com.javarush.golikov.quest.service.AdminService; -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("/admin-user-edit") -public class AdminUserEditController extends HttpServlet { - - private AdminService adminService; - - @Override - public void init() { - adminService = (AdminService) getServletContext().getAttribute("adminService"); - } - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws IOException, ServletException { - - // ===== ПРОВЕРКА АДМИНА ===== - User current = (User) req.getSession().getAttribute("user"); - if (current == null || current.role() != Role.ADMIN) { - resp.sendRedirect(req.getContextPath() + "/"); - return; - } - - // ===== ДАННЫЕ ===== - User editUser = adminService.findUser(req.getParameter("login")); - - req.setAttribute("editUser", editUser); - req.setAttribute("users", adminService.getAllUsers()); - - // ===== VIEW ===== - req.setAttribute("view", "/WEB-INF/jsp/admin-users.jsp"); - req.getRequestDispatcher("/index.jsp").forward(req, resp); - } -} diff --git a/src/main/java/com/javarush/golikov/quest/web/AdminUserSaveController.java b/src/main/java/com/javarush/golikov/quest/web/AdminUserSaveController.java index 952d658..3c3efd4 100644 --- a/src/main/java/com/javarush/golikov/quest/web/AdminUserSaveController.java +++ b/src/main/java/com/javarush/golikov/quest/web/AdminUserSaveController.java @@ -2,26 +2,23 @@ import com.javarush.golikov.quest.auth.Role; import com.javarush.golikov.quest.model.User; -import com.javarush.golikov.quest.service.AdminService; +import com.javarush.golikov.quest.web.admin.AbstractAdminController; 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("/admin-user-save") -public class AdminUserSaveController extends HttpServlet { - private AdminService adminService; - - @Override - public void init() { - adminService = (AdminService) getServletContext().getAttribute("adminService"); - } +public class AdminUserSaveController extends AbstractAdminController { protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { + if (checkAdmin(req, resp)) { + return; + } + String login = req.getParameter("login"); String pass = req.getParameter("password"); Role role = Role.valueOf(req.getParameter("role")); diff --git a/src/main/java/com/javarush/golikov/quest/web/AdminUsersController.java b/src/main/java/com/javarush/golikov/quest/web/AdminUsersController.java index 003a0f7..188ae29 100644 --- a/src/main/java/com/javarush/golikov/quest/web/AdminUsersController.java +++ b/src/main/java/com/javarush/golikov/quest/web/AdminUsersController.java @@ -1,32 +1,21 @@ package com.javarush.golikov.quest.web; -import com.javarush.golikov.quest.auth.Role; -import com.javarush.golikov.quest.model.User; -import com.javarush.golikov.quest.service.AdminService; +import com.javarush.golikov.quest.web.admin.AbstractAdminController; import jakarta.servlet.ServletException; -import jakarta.servlet.annotation.WebServlet; -import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.annotation.WebServlet;; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/admin-users") -public class AdminUsersController extends HttpServlet { - private AdminService adminService; - - @Override - public void init() { - adminService = (AdminService) getServletContext().getAttribute("adminService"); - } +public class AdminUsersController extends AbstractAdminController { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { - User user = (User) req.getSession().getAttribute("user"); - if (user == null || user.role() != Role.ADMIN) { - resp.sendRedirect("index.jsp"); + if (checkAdmin(req, resp)) { return; } diff --git a/src/main/java/com/javarush/golikov/quest/web/admin/AbstractAdminController.java b/src/main/java/com/javarush/golikov/quest/web/admin/AbstractAdminController.java new file mode 100644 index 0000000..79fb8ff --- /dev/null +++ b/src/main/java/com/javarush/golikov/quest/web/admin/AbstractAdminController.java @@ -0,0 +1,32 @@ +package com.javarush.golikov.quest.web.admin; + +import com.javarush.golikov.quest.auth.Role; +import com.javarush.golikov.quest.model.User; +import com.javarush.golikov.quest.service.AdminService; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; + +public abstract class AbstractAdminController extends HttpServlet { + + protected AdminService adminService; + + @Override + public void init() { + adminService = (AdminService) getServletContext().getAttribute("adminService"); + } + + protected boolean checkAdmin(HttpServletRequest req, HttpServletResponse resp) + throws IOException { + + User user = (User) req.getSession().getAttribute("user"); + + if (user == null || user.role() != Role.ADMIN) { + resp.sendRedirect(req.getContextPath() + "/"); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/admin-users.jsp b/src/main/webapp/WEB-INF/jsp/admin-users.jsp index 65b7ee6..c399e3c 100644 --- a/src/main/webapp/WEB-INF/jsp/admin-users.jsp +++ b/src/main/webapp/WEB-INF/jsp/admin-users.jsp @@ -15,6 +15,9 @@ document.querySelectorAll("[id^='view-']").forEach(e => e.classList.remove("hidden") ); + document.querySelectorAll(".saveBtn").forEach(b => + b.classList.add("hidden") + ); } function disableAddButton(disable) { @@ -33,15 +36,31 @@ } function cancelRowEdit(login) { + const row = document.getElementById("edit-" + login); + + // сброс значений + row.querySelectorAll("input, select").forEach(el => { + if (el.dataset.original !== undefined) { + el.value = el.dataset.original; + } + }); + + row.querySelector(".saveBtn").classList.add("hidden"); + document.getElementById("edit-" + login).classList.add("hidden"); document.getElementById("view-" + login).classList.remove("hidden"); disableAddButton(false); } + function onUserFieldChange(login) { + document + .querySelector("#edit-" + login + " .saveBtn") + .classList.remove("hidden"); + } + function showAddForm() { resetAllRows(); - document.querySelectorAll(".editBtn").forEach(b => b.disabled = true); document.getElementById("addBtn").classList.add("hidden"); @@ -83,44 +102,51 @@ -