From 375ff96303dba63285edb4a15aca975666f4fbc9 Mon Sep 17 00:00:00 2001 From: Denys Date: Sun, 22 Jun 2025 20:03:40 +0300 Subject: [PATCH 1/9] Test page created --- .../src/main/java/controller/QuizServlet.java | 27 +++++++- .../src/main/webapp/index.jsp | 9 ++- Oleksandr-JR-Example/src/main/webapp/quiz.jsp | 65 ++++++++++++++----- .../src/main/webapp/result.jsp | 18 +++++ 4 files changed, 95 insertions(+), 24 deletions(-) create mode 100644 Oleksandr-JR-Example/src/main/webapp/result.jsp diff --git a/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java b/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java index ae63a3d..bebf9a4 100644 --- a/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java +++ b/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java @@ -23,13 +23,34 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se req.getSession().setAttribute("questions", questions); - // Forwarding to the JSP page getServletContext().getRequestDispatcher("/quiz.jsp").forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - // Placeholder for POST handling logic - resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "POST method is not supported."); + ArrayList questions = (ArrayList) req.getSession().getAttribute("questions"); + + if (questions == null) { + resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "No questions found in session."); + return; + } + + int score = 0; + for (int i = 0; i < questions.size(); i++) { + String paramName = "q" + i; + String answerStr = req.getParameter(paramName); + if (answerStr != null) { + int selectedAnswer = Integer.parseInt(answerStr); + if (selectedAnswer == questions.get(i).getCorrectAnswer()) { + score++; + } + } + } + + req.setAttribute("score", score); + req.setAttribute("total", questions.size()); + + getServletContext().getRequestDispatcher("/result.jsp").forward(req, resp); } + } diff --git a/Oleksandr-JR-Example/src/main/webapp/index.jsp b/Oleksandr-JR-Example/src/main/webapp/index.jsp index c38169b..01645dd 100644 --- a/Oleksandr-JR-Example/src/main/webapp/index.jsp +++ b/Oleksandr-JR-Example/src/main/webapp/index.jsp @@ -1,5 +1,4 @@ - - -

Hello World!

- - +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<% + response.sendRedirect("quiz"); +%> diff --git a/Oleksandr-JR-Example/src/main/webapp/quiz.jsp b/Oleksandr-JR-Example/src/main/webapp/quiz.jsp index 95a7681..715ce59 100644 --- a/Oleksandr-JR-Example/src/main/webapp/quiz.jsp +++ b/Oleksandr-JR-Example/src/main/webapp/quiz.jsp @@ -1,31 +1,64 @@ <%@ page contentType="text/html;charset=UTF-8" language="java" %> -<%@ page contentType="text/html;charset=UTF-8" %> - +<%@ page import="model.Question" %> +<%@ page import="java.util.ArrayList" %> - - FQ HTML - - + Quiz - - +

Mini Quiz

-<%= request.getSession().getAttribute("questions") %> +<% + ArrayList questions = (ArrayList) request.getSession().getAttribute("questions"); + if (questions == null) { +%> +

No questions available.

+<% +} else { +%> +
+ <% + for (int i = 0; i < questions.size(); i++) { + Question q = questions.get(i); + %> +
+
+ <%= (i + 1) %>. <%= q.getText() %> +
+ <% + for (int j = 0; j < q.getAnswers().size(); j++) { + String answer = q.getAnswers().get(j); + %> +
+ +
+ <% + } + %> +
+ <% + } + %> + +
- +<% + } +%> - + + \ No newline at end of file diff --git a/Oleksandr-JR-Example/src/main/webapp/result.jsp b/Oleksandr-JR-Example/src/main/webapp/result.jsp new file mode 100644 index 0000000..c4b916a --- /dev/null +++ b/Oleksandr-JR-Example/src/main/webapp/result.jsp @@ -0,0 +1,18 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + + + + Quiz Result + + + +

Quiz Result

+ +

You scored <%= request.getAttribute("score") %> out of <%= request.getAttribute("total") %>.

+ +Try Again + + + From b258fb2fc9fc84c047bb0819390e7a682d82bc7b Mon Sep 17 00:00:00 2001 From: Denys Date: Mon, 23 Jun 2025 03:04:55 +0300 Subject: [PATCH 2/9] Added test plot and styles. Improved relation between jsp and css --- .../src/main/java/controller/QuizServlet.java | 41 ++++-------- .../src/main/java/model/Question.java | 7 +- .../java/repository/QuestionRepository.java | 53 ++++++++++++--- .../src/main/webapp/css/style.css | 50 ++++++++++++++ .../src/main/webapp/index.jsp | 17 ++++- Oleksandr-JR-Example/src/main/webapp/quiz.jsp | 66 +++++-------------- 6 files changed, 141 insertions(+), 93 deletions(-) create mode 100644 Oleksandr-JR-Example/src/main/webapp/css/style.css diff --git a/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java b/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java index bebf9a4..c557183 100644 --- a/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java +++ b/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java @@ -17,40 +17,25 @@ public class QuizServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + String questionIndexStr = req.getParameter("q"); + int questionIndex = questionIndexStr != null ? Integer.parseInt(questionIndexStr) : 0; - ArrayList questions = questionRepository.getAll(); - - - req.getSession().setAttribute("questions", questions); + Question question = questionRepository.getAll().get(questionIndex); + req.setAttribute("question", question); + req.setAttribute("qIndex", questionIndex); getServletContext().getRequestDispatcher("/quiz.jsp").forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - ArrayList questions = (ArrayList) req.getSession().getAttribute("questions"); - - if (questions == null) { - resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "No questions found in session."); - return; - } - - int score = 0; - for (int i = 0; i < questions.size(); i++) { - String paramName = "q" + i; - String answerStr = req.getParameter(paramName); - if (answerStr != null) { - int selectedAnswer = Integer.parseInt(answerStr); - if (selectedAnswer == questions.get(i).getCorrectAnswer()) { - score++; - } - } - } - - req.setAttribute("score", score); - req.setAttribute("total", questions.size()); - - getServletContext().getRequestDispatcher("/result.jsp").forward(req, resp); - } + int currentIndex = Integer.parseInt(req.getParameter("qIndex")); + int answerIndex = Integer.parseInt(req.getParameter("answerIndex")); + Question currentQuestion = questionRepository.getAll().get(currentIndex); + int nextIndex = currentQuestion.getNextQuestions().get(answerIndex); + + resp.sendRedirect("quiz?q=" + nextIndex); + } } + diff --git a/Oleksandr-JR-Example/src/main/java/model/Question.java b/Oleksandr-JR-Example/src/main/java/model/Question.java index 17b3279..1ec2848 100644 --- a/Oleksandr-JR-Example/src/main/java/model/Question.java +++ b/Oleksandr-JR-Example/src/main/java/model/Question.java @@ -9,8 +9,7 @@ @Builder public class Question { private String text; - private ArrayList answers; - - private int correctAnswer; -} + private ArrayList nextQuestions; + private Integer correctAnswer; +} \ No newline at end of file diff --git a/Oleksandr-JR-Example/src/main/java/repository/QuestionRepository.java b/Oleksandr-JR-Example/src/main/java/repository/QuestionRepository.java index c64ac92..a0b7b6c 100644 --- a/Oleksandr-JR-Example/src/main/java/repository/QuestionRepository.java +++ b/Oleksandr-JR-Example/src/main/java/repository/QuestionRepository.java @@ -3,6 +3,7 @@ import model.Question; import java.util.ArrayList; +import java.util.List; public class QuestionRepository { private static QuestionRepository INSTANCE; @@ -11,16 +12,52 @@ public class QuestionRepository { private QuestionRepository() { - ArrayList answers = new ArrayList<>(); - answers.add("A"); - answers.add("B"); - answers.add("C"); - answers.add("Programming language"); + questions.add(Question.builder() + .text("Ви втрачаєте пам'ять. Прийняти виклик НЛО?") + .answers(new ArrayList<>(List.of("Прийняти виклик", "Відхилити виклик"))) + .nextQuestions(new ArrayList<>(List.of(1, 5))) + .build()); + + questions.add(Question.builder() + .text("Ви прийняли виклик. Піднятися на капітанський місток?") + .answers(new ArrayList<>(List.of("Піднятися на місток", "Відмовитися"))) + .nextQuestions(new ArrayList<>(List.of(2, 4))) + .build()); + + questions.add(Question.builder() + .text("Ви піднялися на місток. Хто ви?") + .answers(new ArrayList<>(List.of("Розповісти правду", "Збрехати"))) + .nextQuestions(new ArrayList<>(List.of(6, 7))) + .build()); + + questions.add(Question.builder() + .text("Якийсь інший варіант?") + .answers(new ArrayList<>(List.of("Тест1", "Тест2"))) + .nextQuestions(new ArrayList<>(List.of(0, 0))) + .build()); + + questions.add(Question.builder() + .text("Ви не пішли на переговори. Поразка.") + .answers(new ArrayList<>()) + .nextQuestions(new ArrayList<>()) + .build()); + + questions.add(Question.builder() + .text("Ви відхилили виклик. Поразка.") + .answers(new ArrayList<>()) + .nextQuestions(new ArrayList<>()) + .build()); + + questions.add(Question.builder() + .text("Вас повернули додому. Перемога!") + .answers(new ArrayList<>()) + .nextQuestions(new ArrayList<>()) + .build()); questions.add(Question.builder() - .text("What is java") - .answers(answers) - .correctAnswer(3) + .text("Ваша брехня була викрита. Поразка.") + .answers(new ArrayList<>()) + .nextQuestions(new ArrayList<>()) .build()); } diff --git a/Oleksandr-JR-Example/src/main/webapp/css/style.css b/Oleksandr-JR-Example/src/main/webapp/css/style.css new file mode 100644 index 0000000..0e4dc01 --- /dev/null +++ b/Oleksandr-JR-Example/src/main/webapp/css/style.css @@ -0,0 +1,50 @@ +body { + margin: 0; + font-family: 'Segoe UI', sans-serif; + background: radial-gradient(circle, #0f2027, #203a43, #2c5364); + color: #fff; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 100vh; +} + +h1, h2 { + font-size: 3em; + margin-bottom: 10px; + text-align: center; + text-shadow: 0 0 10px #00ffff; +} + +p { + font-size: 1.5em; + text-align: center; + margin-bottom: 30px; +} + +a.button, button { + text-decoration: none; + background: #00ffff; + color: #000; + padding: 12px 25px; + border-radius: 10px; + font-weight: bold; + font-size: 1.2em; + border: none; + cursor: pointer; + transition: 0.3s; +} + +a.button:hover, button:hover { + background: #00cccc; + box-shadow: 0 0 10px #00ffff; +} + +form { + display: flex; + flex-direction: column; + align-items: center; + gap: 15px; + margin-top: 30px; +} diff --git a/Oleksandr-JR-Example/src/main/webapp/index.jsp b/Oleksandr-JR-Example/src/main/webapp/index.jsp index 01645dd..3f392ed 100644 --- a/Oleksandr-JR-Example/src/main/webapp/index.jsp +++ b/Oleksandr-JR-Example/src/main/webapp/index.jsp @@ -1,4 +1,15 @@ <%@ page contentType="text/html;charset=UTF-8" language="java" %> -<% - response.sendRedirect("quiz"); -%> + + + + + + Коллайдер + + + +

Коллайдер

+

Вітаємо в інтерактивному квесті!
Почни своє проходження прямо зараз!

+Почати гру + + \ No newline at end of file diff --git a/Oleksandr-JR-Example/src/main/webapp/quiz.jsp b/Oleksandr-JR-Example/src/main/webapp/quiz.jsp index 715ce59..6600f78 100644 --- a/Oleksandr-JR-Example/src/main/webapp/quiz.jsp +++ b/Oleksandr-JR-Example/src/main/webapp/quiz.jsp @@ -1,64 +1,30 @@ <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import="model.Question" %> -<%@ page import="java.util.ArrayList" %> - +<%@ page import="java.util.*" %> +<% + Question question = (Question) request.getAttribute("question"); + int qIndex = (Integer) request.getAttribute("qIndex"); +%> - + - Quiz - + Квест + - -

Mini Quiz

- -<% - ArrayList questions = (ArrayList) request.getSession().getAttribute("questions"); - if (questions == null) { -%> -

No questions available.

-<% -} else { -%> - -
+

<%= question.getText() %>

+ + <% - for (int i = 0; i < questions.size(); i++) { - Question q = questions.get(i); + List answers = question.getAnswers(); + for (int i = 0; i < answers.size(); i++) { %> -
-
- <%= (i + 1) %>. <%= q.getText() %> -
- <% - for (int j = 0; j < q.getAnswers().size(); j++) { - String answer = q.getAnswers().get(j); - %> -
- -
- <% - } - %> -
+ <% } %> - - -<% - } -%> - - \ No newline at end of file + + From 809a0086e3a9e0bc9e9fff7cc38cf660f98ffc03 Mon Sep 17 00:00:00 2001 From: Denys Date: Mon, 23 Jun 2025 19:16:34 +0300 Subject: [PATCH 3/9] Restart button added --- .../src/main/webapp/css/style.css | 1 - Oleksandr-JR-Example/src/main/webapp/quiz.jsp | 19 +++++++++++++++++-- .../src/main/webapp/result.jsp | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Oleksandr-JR-Example/src/main/webapp/css/style.css b/Oleksandr-JR-Example/src/main/webapp/css/style.css index 0e4dc01..606735f 100644 --- a/Oleksandr-JR-Example/src/main/webapp/css/style.css +++ b/Oleksandr-JR-Example/src/main/webapp/css/style.css @@ -24,7 +24,6 @@ p { } a.button, button { - text-decoration: none; background: #00ffff; color: #000; padding: 12px 25px; diff --git a/Oleksandr-JR-Example/src/main/webapp/quiz.jsp b/Oleksandr-JR-Example/src/main/webapp/quiz.jsp index 6600f78..b9793b2 100644 --- a/Oleksandr-JR-Example/src/main/webapp/quiz.jsp +++ b/Oleksandr-JR-Example/src/main/webapp/quiz.jsp @@ -6,25 +6,40 @@ int qIndex = (Integer) request.getAttribute("qIndex"); %> - + Квест +

<%= question.getText() %>

+ +<% + String text = question.getText().toLowerCase(); + boolean isEnding = text.contains("поразка") || text.contains("перемога"); +%> + +<% if (isEnding) { %> +Почати заново +<% } else { %>
<% List answers = question.getAnswers(); for (int i = 0; i < answers.size(); i++) { %> - + <% } %> +<% } %> + + diff --git a/Oleksandr-JR-Example/src/main/webapp/result.jsp b/Oleksandr-JR-Example/src/main/webapp/result.jsp index c4b916a..cb6a679 100644 --- a/Oleksandr-JR-Example/src/main/webapp/result.jsp +++ b/Oleksandr-JR-Example/src/main/webapp/result.jsp @@ -12,7 +12,7 @@

You scored <%= request.getAttribute("score") %> out of <%= request.getAttribute("total") %>.

-Try Again +Почати заново From c31d1d7dd1e5130e737ad218b241db2689e692c5 Mon Sep 17 00:00:00 2001 From: Denys Date: Mon, 23 Jun 2025 19:39:16 +0300 Subject: [PATCH 4/9] added score --- .../src/main/java/controller/QuizServlet.java | 40 +++++++++++++++---- .../src/main/webapp/index.jsp | 5 +-- Oleksandr-JR-Example/src/main/webapp/quiz.jsp | 10 +++-- .../src/main/webapp/result.jsp | 11 ++--- 4 files changed, 46 insertions(+), 20 deletions(-) diff --git a/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java b/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java index c557183..dece817 100644 --- a/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java +++ b/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java @@ -8,6 +8,7 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; import java.io.IOException; import java.util.ArrayList; @@ -17,25 +18,48 @@ public class QuizServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - String questionIndexStr = req.getParameter("q"); - int questionIndex = questionIndexStr != null ? Integer.parseInt(questionIndexStr) : 0; + HttpSession session = req.getSession(); - Question question = questionRepository.getAll().get(questionIndex); + if ("true".equals(req.getParameter("restart"))) { + session.removeAttribute("currentIndex"); + + Integer games = (Integer) session.getAttribute("gamesPlayed"); + if (games == null) games = 0; + session.setAttribute("gamesPlayed", games + 1); + } + + Integer currentIndex = (Integer) session.getAttribute("currentIndex"); + if (currentIndex == null) { + currentIndex = 0; + session.setAttribute("currentIndex", currentIndex); + } + + Question question = questionRepository.getAll().get(currentIndex); req.setAttribute("question", question); - req.setAttribute("qIndex", questionIndex); + req.setAttribute("qIndex", currentIndex); getServletContext().getRequestDispatcher("/quiz.jsp").forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - int currentIndex = Integer.parseInt(req.getParameter("qIndex")); + HttpSession session = req.getSession(); + + int qIndex = Integer.parseInt(req.getParameter("qIndex")); int answerIndex = Integer.parseInt(req.getParameter("answerIndex")); - Question currentQuestion = questionRepository.getAll().get(currentIndex); - int nextIndex = currentQuestion.getNextQuestions().get(answerIndex); + Question question = questionRepository.getAll().get(qIndex); - resp.sendRedirect("quiz?q=" + nextIndex); + if (question.getNextQuestions() == null || question.getNextQuestions().isEmpty()) { + getServletContext().getRequestDispatcher("/result.jsp").forward(req, resp); + return; + } + + int nextIndex = question.getNextQuestions().get(answerIndex); + session.setAttribute("currentIndex", nextIndex); + + resp.sendRedirect("quiz"); } } + diff --git a/Oleksandr-JR-Example/src/main/webapp/index.jsp b/Oleksandr-JR-Example/src/main/webapp/index.jsp index 3f392ed..bc7fe2e 100644 --- a/Oleksandr-JR-Example/src/main/webapp/index.jsp +++ b/Oleksandr-JR-Example/src/main/webapp/index.jsp @@ -1,15 +1,14 @@ <%@ page contentType="text/html;charset=UTF-8" language="java" %> - Коллайдер - +

Коллайдер

Вітаємо в інтерактивному квесті!
Почни своє проходження прямо зараз!

Почати гру - \ No newline at end of file + diff --git a/Oleksandr-JR-Example/src/main/webapp/quiz.jsp b/Oleksandr-JR-Example/src/main/webapp/quiz.jsp index b9793b2..e8c28c2 100644 --- a/Oleksandr-JR-Example/src/main/webapp/quiz.jsp +++ b/Oleksandr-JR-Example/src/main/webapp/quiz.jsp @@ -4,6 +4,11 @@ <% Question question = (Question) request.getAttribute("question"); int qIndex = (Integer) request.getAttribute("qIndex"); + Integer gamesPlayed = (Integer) session.getAttribute("gamesPlayed"); + if (gamesPlayed == null) gamesPlayed = 0; + + String text = question.getText().toLowerCase(); + boolean isEnding = text.contains("поразка") || text.contains("перемога"); %> @@ -16,10 +21,7 @@

<%= question.getText() %>

-<% - String text = question.getText().toLowerCase(); - boolean isEnding = text.contains("поразка") || text.contains("перемога"); -%> +

Кількість пройдених ігор: <%= gamesPlayed %>

<% if (isEnding) { %> Почати заново diff --git a/Oleksandr-JR-Example/src/main/webapp/result.jsp b/Oleksandr-JR-Example/src/main/webapp/result.jsp index cb6a679..2f6d7d0 100644 --- a/Oleksandr-JR-Example/src/main/webapp/result.jsp +++ b/Oleksandr-JR-Example/src/main/webapp/result.jsp @@ -1,16 +1,17 @@ <%@ page contentType="text/html;charset=UTF-8" language="java" %> - - + - Quiz Result + Результат + -

Quiz Result

+

Гра завершена!

-

You scored <%= request.getAttribute("score") %> out of <%= request.getAttribute("total") %>.

+

Дякуємо за гру!

+

Ви вже зіграли <%= session.getAttribute("gamesPlayed") != null ? session.getAttribute("gamesPlayed") : 1 %> раз(ів).

Почати заново From 1d73292a23b8fbe99c7615d9e5428137d1e9ab09 Mon Sep 17 00:00:00 2001 From: Denys Date: Wed, 25 Jun 2025 01:43:39 +0300 Subject: [PATCH 5/9] added tests ana changed plot --- Oleksandr-JR-Example/pom.xml | 18 ++++ .../src/main/java/controller/QuizServlet.java | 1 - .../java/repository/QuestionRepository.java | 49 ++++++----- .../test/java/controller/QuizServletTest.java | 88 +++++++++++++++++++ .../java/model/QuestionRepositoryTest.java | 74 ++++++++++++++++ 5 files changed, 208 insertions(+), 22 deletions(-) create mode 100644 Oleksandr-JR-Example/src/test/java/controller/QuizServletTest.java create mode 100644 Oleksandr-JR-Example/src/test/java/model/QuestionRepositoryTest.java diff --git a/Oleksandr-JR-Example/pom.xml b/Oleksandr-JR-Example/pom.xml index e89780d..b06508b 100644 --- a/Oleksandr-JR-Example/pom.xml +++ b/Oleksandr-JR-Example/pom.xml @@ -50,6 +50,13 @@ test + + org.mockito + mockito-inline + 5.2.0 + test + + javax.servlet javax.servlet-api @@ -87,6 +94,17 @@ ${commons-lang3.version} + + jakarta.servlet.jsp.jstl + jakarta.servlet.jsp.jstl-api + 2.0.0 + + + org.glassfish.web + jakarta.servlet.jsp.jstl + 2.0.0 + + Oleksandr-JR-Example diff --git a/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java b/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java index dece817..766e792 100644 --- a/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java +++ b/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java @@ -10,7 +10,6 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; -import java.util.ArrayList; @WebServlet(name = "QuizServlet", value = "/quiz") public class QuizServlet extends HttpServlet { diff --git a/Oleksandr-JR-Example/src/main/java/repository/QuestionRepository.java b/Oleksandr-JR-Example/src/main/java/repository/QuestionRepository.java index a0b7b6c..f6a64b6 100644 --- a/Oleksandr-JR-Example/src/main/java/repository/QuestionRepository.java +++ b/Oleksandr-JR-Example/src/main/java/repository/QuestionRepository.java @@ -10,52 +10,63 @@ public class QuestionRepository { private final ArrayList questions = new ArrayList<>(); - private QuestionRepository() { questions.add(Question.builder() - .text("Ви втрачаєте пам'ять. Прийняти виклик НЛО?") - .answers(new ArrayList<>(List.of("Прийняти виклик", "Відхилити виклик"))) - .nextQuestions(new ArrayList<>(List.of(1, 5))) + .text("Вам пропонують почати дослідження всесвіту. Прийняти пропозицію?") + .answers(new ArrayList<>(List.of("Прийняти", "Відхилити"))) + .nextQuestions(new ArrayList<>(List.of(1, 2))) .build()); questions.add(Question.builder() - .text("Ви прийняли виклик. Піднятися на капітанський місток?") - .answers(new ArrayList<>(List.of("Піднятися на місток", "Відмовитися"))) - .nextQuestions(new ArrayList<>(List.of(2, 4))) + .text("Штовхнути темну матерію?") + .answers(new ArrayList<>(List.of("Так", "Ні"))) + .nextQuestions(new ArrayList<>(List.of(3, 5))) .build()); questions.add(Question.builder() - .text("Ви піднялися на місток. Хто ви?") - .answers(new ArrayList<>(List.of("Розповісти правду", "Збрехати"))) - .nextQuestions(new ArrayList<>(List.of(6, 7))) + .text("У результаті вашого відказу, дослідження було перенесене на великий термін. Поразка") + .answers(new ArrayList<>()) + .nextQuestions(new ArrayList<>()) .build()); questions.add(Question.builder() - .text("Якийсь інший варіант?") - .answers(new ArrayList<>(List.of("Тест1", "Тест2"))) - .nextQuestions(new ArrayList<>(List.of(0, 0))) + .text("Випарувалася невелика чорна діра, та залишився новий елемент під назвою — частка Бога! Що робимо далі?") + .answers(new ArrayList<>(List.of("Збільшити навантаження!", "Дослідити частку"))) + .nextQuestions(new ArrayList<>(List.of(4, 9))) .build()); questions.add(Question.builder() - .text("Ви не пішли на переговори. Поразка.") + .text("Чорна діра вбила все живе! Поразка.") .answers(new ArrayList<>()) .nextQuestions(new ArrayList<>()) .build()); questions.add(Question.builder() - .text("Ви відхилили виклик. Поразка.") + .text("Що будете робити?") + .answers(new ArrayList<>(List.of("Розвинути проект світлої матерії", "До дому."))) + .nextQuestions(new ArrayList<>(List.of(6, 2))) + .build()); + + questions.add(Question.builder() + .text("Скільки матерії додати до коллайдеру?") + .answers(new ArrayList<>(List.of("6 ммоль", "100 ммоль"))) + .nextQuestions(new ArrayList<>(List.of(7, 8))) + .build()); + + questions.add(Question.builder() + .text("Людство позбулося енергетичної кризи. Перемога!") .answers(new ArrayList<>()) .nextQuestions(new ArrayList<>()) .build()); questions.add(Question.builder() - .text("Вас повернули додому. Перемога!") + .text("Нейтронна бомба вбила все живе! Поразка!") .answers(new ArrayList<>()) .nextQuestions(new ArrayList<>()) .build()); questions.add(Question.builder() - .text("Ваша брехня була викрита. Поразка.") + .text("Людство позбулося енергетичної кризи. Перемога!") .answers(new ArrayList<>()) .nextQuestions(new ArrayList<>()) .build()); @@ -67,13 +78,9 @@ public static QuestionRepository getInstance() { } return INSTANCE; - } - public ArrayList getAll() { return questions; } - - } diff --git a/Oleksandr-JR-Example/src/test/java/controller/QuizServletTest.java b/Oleksandr-JR-Example/src/test/java/controller/QuizServletTest.java new file mode 100644 index 0000000..a14f766 --- /dev/null +++ b/Oleksandr-JR-Example/src/test/java/controller/QuizServletTest.java @@ -0,0 +1,88 @@ +package controller; + +import model.Question; +import repository.QuestionRepository; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.Mockito.*; + +public class QuizServletTest { + + @InjectMocks + private QuizServlet realServlet; + + private QuizServlet servlet; + + @Mock + private HttpServletRequest request; + + @Mock + private HttpServletResponse response; + + @Mock + private HttpSession session; + + @Mock + private ServletContext servletContext; + + @Mock + private RequestDispatcher dispatcher; + + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + + servlet = spy(realServlet); + when(request.getSession()).thenReturn(session); + when(request.getServletContext()).thenReturn(servletContext); + doReturn(servletContext).when(servlet).getServletContext(); + } + + @Test + public void testDoGet_NewGame_ShouldStartAtIndexZero() throws Exception { + when(session.getAttribute("currentIndex")).thenReturn(null); + when(servletContext.getRequestDispatcher("/quiz.jsp")).thenReturn(dispatcher); + + servlet.doGet(request, response); + + verify(session).setAttribute("currentIndex", 0); + verify(dispatcher).forward(request, response); + } + + @Test + public void testDoPost_ValidAnswer_RedirectsToNextQuestion() throws Exception { + QuestionRepository repo = QuestionRepository.getInstance(); + repo.getAll().clear(); + repo.getAll().add( + Question.builder() + .text("Test?") + .answers(new ArrayList<>(List.of("Yes", "No"))) + .nextQuestions(new ArrayList<>(List.of(1, 2))) + .build() + ); + + when(request.getParameter("qIndex")).thenReturn("0"); + when(request.getParameter("answerIndex")).thenReturn("1"); + when(request.getSession()).thenReturn(session); + + servlet.doPost(request, response); + + verify(session).setAttribute("currentIndex", 2); + verify(response).sendRedirect("quiz"); + } +} + diff --git a/Oleksandr-JR-Example/src/test/java/model/QuestionRepositoryTest.java b/Oleksandr-JR-Example/src/test/java/model/QuestionRepositoryTest.java new file mode 100644 index 0000000..2a12719 --- /dev/null +++ b/Oleksandr-JR-Example/src/test/java/model/QuestionRepositoryTest.java @@ -0,0 +1,74 @@ +package model; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import repository.QuestionRepository; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class QuestionRepositoryTest { + + private QuestionRepository repository; + + @BeforeEach + public void setup() { + repository = QuestionRepository.getInstance(); + repository.getAll().clear(); + + repository.getAll().add( + Question.builder() + .text("Question 0?") + .answers(new ArrayList<>(List.of("Answer 1", "Answer 2"))) + .nextQuestions(new ArrayList<>(List.of(1, 2))) + .build() + ); + + repository.getAll().add( + Question.builder() + .text("Question 1?") + .answers(new ArrayList<>()) + .nextQuestions(new ArrayList<>()) + .build() + ); + + repository.getAll().add( + Question.builder() + .text("Question 2?") + .answers(new ArrayList<>()) + .nextQuestions(new ArrayList<>()) + .build() + ); + } + + @Test + public void testQuestionsAreLoaded() { + ArrayList questions = repository.getAll(); + assertFalse(questions.isEmpty(), "Questions should be loaded"); + } + + @Test + public void testTwoAnswers() { + Question q0 = repository.getAll().get(0); + assertEquals(2, q0.getAnswers().size(), "First question should have two answers"); + } + + @Test + public void testNavigation() { + Question q0 = repository.getAll().get(0); + int next = q0.getNextQuestions().get(0); + Question q1 = repository.getAll().get(next); + assertNotNull(q1, "Should navigate to next question"); + } + + @Test + public void testHaveNoNext() { + for (Question q : repository.getAll()) { + if (q.getAnswers().isEmpty()) { + assertTrue(q.getNextQuestions().isEmpty(), "Terminal questions should not have next steps"); + } + } + } +} From 5dcfc58d2d0e4203a65dd655e7317c4e1754dad3 Mon Sep 17 00:00:00 2001 From: Denys Date: Wed, 25 Jun 2025 02:27:18 +0300 Subject: [PATCH 6/9] Added Readme --- README.md | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d8f5056..dd0326b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,37 @@ -# M3-Quest-NEW +# QuestGame -Do not edit this file, please create a readme file in your module \ No newline at end of file +## Overview + +QuestGame is an interactive web-based quiz game implemented as a Java web application. +Players answer a series of questions, branching the story depending on their choices. + +--- + +## Technologies Used + +- **Java 17** — main programming language +- **Servlet API 4.0** — to handle HTTP requests and sessions +- **JSP** — for server-side page rendering +- **JUnit 5** — unit testing framework +- **Mockito** — for mocking in tests +- **Maven** — build and dependency management +- **Apache Tomcat 9** — servlet container to deploy the web application + +--- + +## Project Structure + +- `src/main/java` — Java servlet controllers and business logic +- `src/main/webapp` — JSP pages, static resources (CSS) +- `src/test/java` — unit tests +- `pom.xml` — Maven configuration + +--- + +## How to Build and Run + +### Prerequisites + +- Java 17 installed +- Maven installed +- Docker installed (optional, for containerized run) \ No newline at end of file From fd278c6e3a221f6364816ec76161de9525cda4f1 Mon Sep 17 00:00:00 2001 From: Denys Date: Wed, 25 Jun 2025 02:59:37 +0300 Subject: [PATCH 7/9] checked project --- Denys/Dockerfile | 13 ++ Denys/docker-compose.yml | 5 + Denys/pom.xml | 138 ++++++++++++++++++ .../src/main/java/controller/QuizServlet.java | 64 ++++++++ Denys/src/main/java/model/Question.java | 15 ++ .../java/repository/QuestionRepository.java | 86 +++++++++++ Denys/src/main/webapp/WEB-INF/web.xml | 7 + Denys/src/main/webapp/css/style.css | 49 +++++++ Denys/src/main/webapp/index.jsp | 14 ++ Denys/src/main/webapp/quiz.jsp | 47 ++++++ Denys/src/main/webapp/result.jsp | 19 +++ .../test/java/controller/QuizServletTest.java | 88 +++++++++++ .../java/model/QuestionRepositoryTest.java | 74 ++++++++++ 13 files changed, 619 insertions(+) create mode 100644 Denys/Dockerfile create mode 100644 Denys/docker-compose.yml create mode 100644 Denys/pom.xml create mode 100644 Denys/src/main/java/controller/QuizServlet.java create mode 100644 Denys/src/main/java/model/Question.java create mode 100644 Denys/src/main/java/repository/QuestionRepository.java create mode 100644 Denys/src/main/webapp/WEB-INF/web.xml create mode 100644 Denys/src/main/webapp/css/style.css create mode 100644 Denys/src/main/webapp/index.jsp create mode 100644 Denys/src/main/webapp/quiz.jsp create mode 100644 Denys/src/main/webapp/result.jsp create mode 100644 Denys/src/test/java/controller/QuizServletTest.java create mode 100644 Denys/src/test/java/model/QuestionRepositoryTest.java diff --git a/Denys/Dockerfile b/Denys/Dockerfile new file mode 100644 index 0000000..27415c9 --- /dev/null +++ b/Denys/Dockerfile @@ -0,0 +1,13 @@ +FROM maven:3.8.5-openjdk-17 AS build +WORKDIR /app +COPY pom.xml . +COPY src ./src +RUN mvn clean package -DskipTests + + +FROM tomcat:9.0-jdk17 + +# @TODO Replace Oleksandr-JR-Example.war with your app name +COPY --from=build /app/target/Oleksandr-JR-Example.war /usr/local/tomcat/webapps/ROOT.war +EXPOSE 8080 +CMD ["catalina.sh", "run"] diff --git a/Denys/docker-compose.yml b/Denys/docker-compose.yml new file mode 100644 index 0000000..26f6aad --- /dev/null +++ b/Denys/docker-compose.yml @@ -0,0 +1,5 @@ +services: + web: + build: . + ports: + - "8080:8080" \ No newline at end of file diff --git a/Denys/pom.xml b/Denys/pom.xml new file mode 100644 index 0000000..2113d10 --- /dev/null +++ b/Denys/pom.xml @@ -0,0 +1,138 @@ + + 4.0.0 + ua.com.javarush.gnew + Denys + war + 1.0-SNAPSHOT + Denys Maven Webapp + http://maven.apache.org + + + 17 + + 1.18.36 + 3.12.0 + + 5.15.2 + 5.12.0 + + 4.0.1 + 3.0.1 + 1.2 + + ${java.version} + ${java.version} + 3.3.2 + + + + + + + org.junit.jupiter + junit-jupiter-engine + ${junit-jupiter-engine.version} + test + + + + org.mockito + mockito-core + ${mockito-core.version} + test + + + + org.mockito + mockito-junit-jupiter + ${mockito-core.version} + test + + + + org.mockito + mockito-inline + 5.2.0 + test + + + + javax.servlet + javax.servlet-api + ${javax.servlet-api.version} + provided + + + + javax.servlet + jstl + ${jstl.version} + + + + org.projectlombok + lombok + ${lombok.version} + + + + org.glassfish.web + jakarta.servlet.jsp.jstl + ${jakarta.servlet.jsp.jstl.version} + + + + jakarta.servlet.jsp.jstl + jakarta.servlet.jsp.jstl-api + ${jakarta.servlet.jsp.jstl.version} + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + jakarta.servlet.jsp.jstl + jakarta.servlet.jsp.jstl-api + 2.0.0 + + + org.glassfish.web + jakarta.servlet.jsp.jstl + 2.0.0 + + + + + Denys + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.9.0 + + ${java.version} + ${java.version} + + + org.projectlombok + lombok + ${lombok.version} + + + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + + + + diff --git a/Denys/src/main/java/controller/QuizServlet.java b/Denys/src/main/java/controller/QuizServlet.java new file mode 100644 index 0000000..766e792 --- /dev/null +++ b/Denys/src/main/java/controller/QuizServlet.java @@ -0,0 +1,64 @@ +package controller; + +import model.Question; +import repository.QuestionRepository; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.IOException; + +@WebServlet(name = "QuizServlet", value = "/quiz") +public class QuizServlet extends HttpServlet { + private static final QuestionRepository questionRepository = QuestionRepository.getInstance(); + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + HttpSession session = req.getSession(); + + if ("true".equals(req.getParameter("restart"))) { + session.removeAttribute("currentIndex"); + + Integer games = (Integer) session.getAttribute("gamesPlayed"); + if (games == null) games = 0; + session.setAttribute("gamesPlayed", games + 1); + } + + Integer currentIndex = (Integer) session.getAttribute("currentIndex"); + if (currentIndex == null) { + currentIndex = 0; + session.setAttribute("currentIndex", currentIndex); + } + + Question question = questionRepository.getAll().get(currentIndex); + req.setAttribute("question", question); + req.setAttribute("qIndex", currentIndex); + + getServletContext().getRequestDispatcher("/quiz.jsp").forward(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + HttpSession session = req.getSession(); + + int qIndex = Integer.parseInt(req.getParameter("qIndex")); + int answerIndex = Integer.parseInt(req.getParameter("answerIndex")); + + Question question = questionRepository.getAll().get(qIndex); + + if (question.getNextQuestions() == null || question.getNextQuestions().isEmpty()) { + getServletContext().getRequestDispatcher("/result.jsp").forward(req, resp); + return; + } + + int nextIndex = question.getNextQuestions().get(answerIndex); + session.setAttribute("currentIndex", nextIndex); + + resp.sendRedirect("quiz"); + } +} + + diff --git a/Denys/src/main/java/model/Question.java b/Denys/src/main/java/model/Question.java new file mode 100644 index 0000000..1ec2848 --- /dev/null +++ b/Denys/src/main/java/model/Question.java @@ -0,0 +1,15 @@ +package model; + +import lombok.Builder; +import lombok.Data; + +import java.util.ArrayList; + +@Data +@Builder +public class Question { + private String text; + private ArrayList answers; + private ArrayList nextQuestions; + private Integer correctAnswer; +} \ No newline at end of file diff --git a/Denys/src/main/java/repository/QuestionRepository.java b/Denys/src/main/java/repository/QuestionRepository.java new file mode 100644 index 0000000..f6a64b6 --- /dev/null +++ b/Denys/src/main/java/repository/QuestionRepository.java @@ -0,0 +1,86 @@ +package repository; + +import model.Question; + +import java.util.ArrayList; +import java.util.List; + +public class QuestionRepository { + private static QuestionRepository INSTANCE; + + private final ArrayList questions = new ArrayList<>(); + + private QuestionRepository() { + questions.add(Question.builder() + .text("Вам пропонують почати дослідження всесвіту. Прийняти пропозицію?") + .answers(new ArrayList<>(List.of("Прийняти", "Відхилити"))) + .nextQuestions(new ArrayList<>(List.of(1, 2))) + .build()); + + questions.add(Question.builder() + .text("Штовхнути темну матерію?") + .answers(new ArrayList<>(List.of("Так", "Ні"))) + .nextQuestions(new ArrayList<>(List.of(3, 5))) + .build()); + + questions.add(Question.builder() + .text("У результаті вашого відказу, дослідження було перенесене на великий термін. Поразка") + .answers(new ArrayList<>()) + .nextQuestions(new ArrayList<>()) + .build()); + + questions.add(Question.builder() + .text("Випарувалася невелика чорна діра, та залишився новий елемент під назвою — частка Бога! Що робимо далі?") + .answers(new ArrayList<>(List.of("Збільшити навантаження!", "Дослідити частку"))) + .nextQuestions(new ArrayList<>(List.of(4, 9))) + .build()); + + questions.add(Question.builder() + .text("Чорна діра вбила все живе! Поразка.") + .answers(new ArrayList<>()) + .nextQuestions(new ArrayList<>()) + .build()); + + questions.add(Question.builder() + .text("Що будете робити?") + .answers(new ArrayList<>(List.of("Розвинути проект світлої матерії", "До дому."))) + .nextQuestions(new ArrayList<>(List.of(6, 2))) + .build()); + + questions.add(Question.builder() + .text("Скільки матерії додати до коллайдеру?") + .answers(new ArrayList<>(List.of("6 ммоль", "100 ммоль"))) + .nextQuestions(new ArrayList<>(List.of(7, 8))) + .build()); + + questions.add(Question.builder() + .text("Людство позбулося енергетичної кризи. Перемога!") + .answers(new ArrayList<>()) + .nextQuestions(new ArrayList<>()) + .build()); + + questions.add(Question.builder() + .text("Нейтронна бомба вбила все живе! Поразка!") + .answers(new ArrayList<>()) + .nextQuestions(new ArrayList<>()) + .build()); + + questions.add(Question.builder() + .text("Людство позбулося енергетичної кризи. Перемога!") + .answers(new ArrayList<>()) + .nextQuestions(new ArrayList<>()) + .build()); + } + + public static QuestionRepository getInstance() { + if (INSTANCE == null) { + INSTANCE = new QuestionRepository(); + } + + return INSTANCE; + } + + public ArrayList getAll() { + return questions; + } +} diff --git a/Denys/src/main/webapp/WEB-INF/web.xml b/Denys/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..9f88c1f --- /dev/null +++ b/Denys/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + Archetype Created Web Application + diff --git a/Denys/src/main/webapp/css/style.css b/Denys/src/main/webapp/css/style.css new file mode 100644 index 0000000..606735f --- /dev/null +++ b/Denys/src/main/webapp/css/style.css @@ -0,0 +1,49 @@ +body { + margin: 0; + font-family: 'Segoe UI', sans-serif; + background: radial-gradient(circle, #0f2027, #203a43, #2c5364); + color: #fff; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + min-height: 100vh; +} + +h1, h2 { + font-size: 3em; + margin-bottom: 10px; + text-align: center; + text-shadow: 0 0 10px #00ffff; +} + +p { + font-size: 1.5em; + text-align: center; + margin-bottom: 30px; +} + +a.button, button { + background: #00ffff; + color: #000; + padding: 12px 25px; + border-radius: 10px; + font-weight: bold; + font-size: 1.2em; + border: none; + cursor: pointer; + transition: 0.3s; +} + +a.button:hover, button:hover { + background: #00cccc; + box-shadow: 0 0 10px #00ffff; +} + +form { + display: flex; + flex-direction: column; + align-items: center; + gap: 15px; + margin-top: 30px; +} diff --git a/Denys/src/main/webapp/index.jsp b/Denys/src/main/webapp/index.jsp new file mode 100644 index 0000000..bc7fe2e --- /dev/null +++ b/Denys/src/main/webapp/index.jsp @@ -0,0 +1,14 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + + + Коллайдер + + + +

Коллайдер

+

Вітаємо в інтерактивному квесті!
Почни своє проходження прямо зараз!

+Почати гру + + diff --git a/Denys/src/main/webapp/quiz.jsp b/Denys/src/main/webapp/quiz.jsp new file mode 100644 index 0000000..e8c28c2 --- /dev/null +++ b/Denys/src/main/webapp/quiz.jsp @@ -0,0 +1,47 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ page import="model.Question" %> +<%@ page import="java.util.*" %> +<% + Question question = (Question) request.getAttribute("question"); + int qIndex = (Integer) request.getAttribute("qIndex"); + Integer gamesPlayed = (Integer) session.getAttribute("gamesPlayed"); + if (gamesPlayed == null) gamesPlayed = 0; + + String text = question.getText().toLowerCase(); + boolean isEnding = text.contains("поразка") || text.contains("перемога"); +%> + + + + + Квест + + + + +

<%= question.getText() %>

+ +

Кількість пройдених ігор: <%= gamesPlayed %>

+ +<% if (isEnding) { %> +Почати заново +<% } else { %> +
+ + <% + List answers = question.getAnswers(); + for (int i = 0; i < answers.size(); i++) { + %> + + <% + } + %> + +<% } %> + + + + + diff --git a/Denys/src/main/webapp/result.jsp b/Denys/src/main/webapp/result.jsp new file mode 100644 index 0000000..2f6d7d0 --- /dev/null +++ b/Denys/src/main/webapp/result.jsp @@ -0,0 +1,19 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + + + Результат + + + + +

Гра завершена!

+ +

Дякуємо за гру!

+

Ви вже зіграли <%= session.getAttribute("gamesPlayed") != null ? session.getAttribute("gamesPlayed") : 1 %> раз(ів).

+ +Почати заново + + + diff --git a/Denys/src/test/java/controller/QuizServletTest.java b/Denys/src/test/java/controller/QuizServletTest.java new file mode 100644 index 0000000..a14f766 --- /dev/null +++ b/Denys/src/test/java/controller/QuizServletTest.java @@ -0,0 +1,88 @@ +package controller; + +import model.Question; +import repository.QuestionRepository; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.Mockito.*; + +public class QuizServletTest { + + @InjectMocks + private QuizServlet realServlet; + + private QuizServlet servlet; + + @Mock + private HttpServletRequest request; + + @Mock + private HttpServletResponse response; + + @Mock + private HttpSession session; + + @Mock + private ServletContext servletContext; + + @Mock + private RequestDispatcher dispatcher; + + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + + servlet = spy(realServlet); + when(request.getSession()).thenReturn(session); + when(request.getServletContext()).thenReturn(servletContext); + doReturn(servletContext).when(servlet).getServletContext(); + } + + @Test + public void testDoGet_NewGame_ShouldStartAtIndexZero() throws Exception { + when(session.getAttribute("currentIndex")).thenReturn(null); + when(servletContext.getRequestDispatcher("/quiz.jsp")).thenReturn(dispatcher); + + servlet.doGet(request, response); + + verify(session).setAttribute("currentIndex", 0); + verify(dispatcher).forward(request, response); + } + + @Test + public void testDoPost_ValidAnswer_RedirectsToNextQuestion() throws Exception { + QuestionRepository repo = QuestionRepository.getInstance(); + repo.getAll().clear(); + repo.getAll().add( + Question.builder() + .text("Test?") + .answers(new ArrayList<>(List.of("Yes", "No"))) + .nextQuestions(new ArrayList<>(List.of(1, 2))) + .build() + ); + + when(request.getParameter("qIndex")).thenReturn("0"); + when(request.getParameter("answerIndex")).thenReturn("1"); + when(request.getSession()).thenReturn(session); + + servlet.doPost(request, response); + + verify(session).setAttribute("currentIndex", 2); + verify(response).sendRedirect("quiz"); + } +} + diff --git a/Denys/src/test/java/model/QuestionRepositoryTest.java b/Denys/src/test/java/model/QuestionRepositoryTest.java new file mode 100644 index 0000000..2a12719 --- /dev/null +++ b/Denys/src/test/java/model/QuestionRepositoryTest.java @@ -0,0 +1,74 @@ +package model; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import repository.QuestionRepository; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class QuestionRepositoryTest { + + private QuestionRepository repository; + + @BeforeEach + public void setup() { + repository = QuestionRepository.getInstance(); + repository.getAll().clear(); + + repository.getAll().add( + Question.builder() + .text("Question 0?") + .answers(new ArrayList<>(List.of("Answer 1", "Answer 2"))) + .nextQuestions(new ArrayList<>(List.of(1, 2))) + .build() + ); + + repository.getAll().add( + Question.builder() + .text("Question 1?") + .answers(new ArrayList<>()) + .nextQuestions(new ArrayList<>()) + .build() + ); + + repository.getAll().add( + Question.builder() + .text("Question 2?") + .answers(new ArrayList<>()) + .nextQuestions(new ArrayList<>()) + .build() + ); + } + + @Test + public void testQuestionsAreLoaded() { + ArrayList questions = repository.getAll(); + assertFalse(questions.isEmpty(), "Questions should be loaded"); + } + + @Test + public void testTwoAnswers() { + Question q0 = repository.getAll().get(0); + assertEquals(2, q0.getAnswers().size(), "First question should have two answers"); + } + + @Test + public void testNavigation() { + Question q0 = repository.getAll().get(0); + int next = q0.getNextQuestions().get(0); + Question q1 = repository.getAll().get(next); + assertNotNull(q1, "Should navigate to next question"); + } + + @Test + public void testHaveNoNext() { + for (Question q : repository.getAll()) { + if (q.getAnswers().isEmpty()) { + assertTrue(q.getNextQuestions().isEmpty(), "Terminal questions should not have next steps"); + } + } + } +} From 321b79daa2524313eb203ae52a17b0f9b946afbf Mon Sep 17 00:00:00 2001 From: Denys Date: Wed, 25 Jun 2025 03:01:17 +0300 Subject: [PATCH 8/9] Dockerfile changed --- Denys/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Denys/Dockerfile b/Denys/Dockerfile index 27415c9..7990aa4 100644 --- a/Denys/Dockerfile +++ b/Denys/Dockerfile @@ -7,7 +7,7 @@ RUN mvn clean package -DskipTests FROM tomcat:9.0-jdk17 -# @TODO Replace Oleksandr-JR-Example.war with your app name -COPY --from=build /app/target/Oleksandr-JR-Example.war /usr/local/tomcat/webapps/ROOT.war + +COPY --from=build /app/target/Denys.war /usr/local/tomcat/webapps/ROOT.war EXPOSE 8080 CMD ["catalina.sh", "run"] From 8048cc4b5318be289ccad298f1d263918871ac2c Mon Sep 17 00:00:00 2001 From: Denys Date: Wed, 25 Jun 2025 03:03:10 +0300 Subject: [PATCH 9/9] removed some data --- Oleksandr-JR-Example/Dockerfile | 13 -- Oleksandr-JR-Example/docker-compose.yml | 5 - Oleksandr-JR-Example/pom.xml | 138 ------------------ .../src/main/java/controller/QuizServlet.java | 64 -------- .../src/main/java/model/Question.java | 15 -- .../java/repository/QuestionRepository.java | 86 ----------- .../src/main/webapp/WEB-INF/web.xml | 7 - .../src/main/webapp/css/style.css | 49 ------- .../src/main/webapp/index.jsp | 14 -- Oleksandr-JR-Example/src/main/webapp/quiz.jsp | 47 ------ .../src/main/webapp/result.jsp | 19 --- .../test/java/controller/QuizServletTest.java | 88 ----------- .../java/model/QuestionRepositoryTest.java | 74 ---------- 13 files changed, 619 deletions(-) delete mode 100644 Oleksandr-JR-Example/Dockerfile delete mode 100644 Oleksandr-JR-Example/docker-compose.yml delete mode 100644 Oleksandr-JR-Example/pom.xml delete mode 100644 Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java delete mode 100644 Oleksandr-JR-Example/src/main/java/model/Question.java delete mode 100644 Oleksandr-JR-Example/src/main/java/repository/QuestionRepository.java delete mode 100644 Oleksandr-JR-Example/src/main/webapp/WEB-INF/web.xml delete mode 100644 Oleksandr-JR-Example/src/main/webapp/css/style.css delete mode 100644 Oleksandr-JR-Example/src/main/webapp/index.jsp delete mode 100644 Oleksandr-JR-Example/src/main/webapp/quiz.jsp delete mode 100644 Oleksandr-JR-Example/src/main/webapp/result.jsp delete mode 100644 Oleksandr-JR-Example/src/test/java/controller/QuizServletTest.java delete mode 100644 Oleksandr-JR-Example/src/test/java/model/QuestionRepositoryTest.java diff --git a/Oleksandr-JR-Example/Dockerfile b/Oleksandr-JR-Example/Dockerfile deleted file mode 100644 index 27415c9..0000000 --- a/Oleksandr-JR-Example/Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM maven:3.8.5-openjdk-17 AS build -WORKDIR /app -COPY pom.xml . -COPY src ./src -RUN mvn clean package -DskipTests - - -FROM tomcat:9.0-jdk17 - -# @TODO Replace Oleksandr-JR-Example.war with your app name -COPY --from=build /app/target/Oleksandr-JR-Example.war /usr/local/tomcat/webapps/ROOT.war -EXPOSE 8080 -CMD ["catalina.sh", "run"] diff --git a/Oleksandr-JR-Example/docker-compose.yml b/Oleksandr-JR-Example/docker-compose.yml deleted file mode 100644 index 26f6aad..0000000 --- a/Oleksandr-JR-Example/docker-compose.yml +++ /dev/null @@ -1,5 +0,0 @@ -services: - web: - build: . - ports: - - "8080:8080" \ No newline at end of file diff --git a/Oleksandr-JR-Example/pom.xml b/Oleksandr-JR-Example/pom.xml deleted file mode 100644 index b06508b..0000000 --- a/Oleksandr-JR-Example/pom.xml +++ /dev/null @@ -1,138 +0,0 @@ - - 4.0.0 - ua.com.javarush.gnew - Oleksandr-JR-Example - war - 1.0-SNAPSHOT - Oleksandr-JR-Example Maven Webapp - http://maven.apache.org - - - 17 - - 1.18.36 - 3.12.0 - - 5.15.2 - 5.12.0 - - 4.0.1 - 3.0.1 - 1.2 - - ${java.version} - ${java.version} - 3.3.2 - - - - - - - org.junit.jupiter - junit-jupiter-engine - ${junit-jupiter-engine.version} - test - - - - org.mockito - mockito-core - ${mockito-core.version} - test - - - - org.mockito - mockito-junit-jupiter - ${mockito-core.version} - test - - - - org.mockito - mockito-inline - 5.2.0 - test - - - - javax.servlet - javax.servlet-api - ${javax.servlet-api.version} - provided - - - - javax.servlet - jstl - ${jstl.version} - - - - org.projectlombok - lombok - ${lombok.version} - - - - org.glassfish.web - jakarta.servlet.jsp.jstl - ${jakarta.servlet.jsp.jstl.version} - - - - jakarta.servlet.jsp.jstl - jakarta.servlet.jsp.jstl-api - ${jakarta.servlet.jsp.jstl.version} - - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - - jakarta.servlet.jsp.jstl - jakarta.servlet.jsp.jstl-api - 2.0.0 - - - org.glassfish.web - jakarta.servlet.jsp.jstl - 2.0.0 - - - - - Oleksandr-JR-Example - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.9.0 - - ${java.version} - ${java.version} - - - org.projectlombok - lombok - ${lombok.version} - - - - - - - org.apache.maven.plugins - maven-war-plugin - ${maven-war-plugin.version} - - - - - diff --git a/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java b/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java deleted file mode 100644 index 766e792..0000000 --- a/Oleksandr-JR-Example/src/main/java/controller/QuizServlet.java +++ /dev/null @@ -1,64 +0,0 @@ -package controller; - -import model.Question; -import repository.QuestionRepository; - -import javax.servlet.ServletException; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.io.IOException; - -@WebServlet(name = "QuizServlet", value = "/quiz") -public class QuizServlet extends HttpServlet { - private static final QuestionRepository questionRepository = QuestionRepository.getInstance(); - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - HttpSession session = req.getSession(); - - if ("true".equals(req.getParameter("restart"))) { - session.removeAttribute("currentIndex"); - - Integer games = (Integer) session.getAttribute("gamesPlayed"); - if (games == null) games = 0; - session.setAttribute("gamesPlayed", games + 1); - } - - Integer currentIndex = (Integer) session.getAttribute("currentIndex"); - if (currentIndex == null) { - currentIndex = 0; - session.setAttribute("currentIndex", currentIndex); - } - - Question question = questionRepository.getAll().get(currentIndex); - req.setAttribute("question", question); - req.setAttribute("qIndex", currentIndex); - - getServletContext().getRequestDispatcher("/quiz.jsp").forward(req, resp); - } - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - HttpSession session = req.getSession(); - - int qIndex = Integer.parseInt(req.getParameter("qIndex")); - int answerIndex = Integer.parseInt(req.getParameter("answerIndex")); - - Question question = questionRepository.getAll().get(qIndex); - - if (question.getNextQuestions() == null || question.getNextQuestions().isEmpty()) { - getServletContext().getRequestDispatcher("/result.jsp").forward(req, resp); - return; - } - - int nextIndex = question.getNextQuestions().get(answerIndex); - session.setAttribute("currentIndex", nextIndex); - - resp.sendRedirect("quiz"); - } -} - - diff --git a/Oleksandr-JR-Example/src/main/java/model/Question.java b/Oleksandr-JR-Example/src/main/java/model/Question.java deleted file mode 100644 index 1ec2848..0000000 --- a/Oleksandr-JR-Example/src/main/java/model/Question.java +++ /dev/null @@ -1,15 +0,0 @@ -package model; - -import lombok.Builder; -import lombok.Data; - -import java.util.ArrayList; - -@Data -@Builder -public class Question { - private String text; - private ArrayList answers; - private ArrayList nextQuestions; - private Integer correctAnswer; -} \ No newline at end of file diff --git a/Oleksandr-JR-Example/src/main/java/repository/QuestionRepository.java b/Oleksandr-JR-Example/src/main/java/repository/QuestionRepository.java deleted file mode 100644 index f6a64b6..0000000 --- a/Oleksandr-JR-Example/src/main/java/repository/QuestionRepository.java +++ /dev/null @@ -1,86 +0,0 @@ -package repository; - -import model.Question; - -import java.util.ArrayList; -import java.util.List; - -public class QuestionRepository { - private static QuestionRepository INSTANCE; - - private final ArrayList questions = new ArrayList<>(); - - private QuestionRepository() { - questions.add(Question.builder() - .text("Вам пропонують почати дослідження всесвіту. Прийняти пропозицію?") - .answers(new ArrayList<>(List.of("Прийняти", "Відхилити"))) - .nextQuestions(new ArrayList<>(List.of(1, 2))) - .build()); - - questions.add(Question.builder() - .text("Штовхнути темну матерію?") - .answers(new ArrayList<>(List.of("Так", "Ні"))) - .nextQuestions(new ArrayList<>(List.of(3, 5))) - .build()); - - questions.add(Question.builder() - .text("У результаті вашого відказу, дослідження було перенесене на великий термін. Поразка") - .answers(new ArrayList<>()) - .nextQuestions(new ArrayList<>()) - .build()); - - questions.add(Question.builder() - .text("Випарувалася невелика чорна діра, та залишився новий елемент під назвою — частка Бога! Що робимо далі?") - .answers(new ArrayList<>(List.of("Збільшити навантаження!", "Дослідити частку"))) - .nextQuestions(new ArrayList<>(List.of(4, 9))) - .build()); - - questions.add(Question.builder() - .text("Чорна діра вбила все живе! Поразка.") - .answers(new ArrayList<>()) - .nextQuestions(new ArrayList<>()) - .build()); - - questions.add(Question.builder() - .text("Що будете робити?") - .answers(new ArrayList<>(List.of("Розвинути проект світлої матерії", "До дому."))) - .nextQuestions(new ArrayList<>(List.of(6, 2))) - .build()); - - questions.add(Question.builder() - .text("Скільки матерії додати до коллайдеру?") - .answers(new ArrayList<>(List.of("6 ммоль", "100 ммоль"))) - .nextQuestions(new ArrayList<>(List.of(7, 8))) - .build()); - - questions.add(Question.builder() - .text("Людство позбулося енергетичної кризи. Перемога!") - .answers(new ArrayList<>()) - .nextQuestions(new ArrayList<>()) - .build()); - - questions.add(Question.builder() - .text("Нейтронна бомба вбила все живе! Поразка!") - .answers(new ArrayList<>()) - .nextQuestions(new ArrayList<>()) - .build()); - - questions.add(Question.builder() - .text("Людство позбулося енергетичної кризи. Перемога!") - .answers(new ArrayList<>()) - .nextQuestions(new ArrayList<>()) - .build()); - } - - public static QuestionRepository getInstance() { - if (INSTANCE == null) { - INSTANCE = new QuestionRepository(); - } - - return INSTANCE; - } - - public ArrayList getAll() { - return questions; - } -} diff --git a/Oleksandr-JR-Example/src/main/webapp/WEB-INF/web.xml b/Oleksandr-JR-Example/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 9f88c1f..0000000 --- a/Oleksandr-JR-Example/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - Archetype Created Web Application - diff --git a/Oleksandr-JR-Example/src/main/webapp/css/style.css b/Oleksandr-JR-Example/src/main/webapp/css/style.css deleted file mode 100644 index 606735f..0000000 --- a/Oleksandr-JR-Example/src/main/webapp/css/style.css +++ /dev/null @@ -1,49 +0,0 @@ -body { - margin: 0; - font-family: 'Segoe UI', sans-serif; - background: radial-gradient(circle, #0f2027, #203a43, #2c5364); - color: #fff; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - min-height: 100vh; -} - -h1, h2 { - font-size: 3em; - margin-bottom: 10px; - text-align: center; - text-shadow: 0 0 10px #00ffff; -} - -p { - font-size: 1.5em; - text-align: center; - margin-bottom: 30px; -} - -a.button, button { - background: #00ffff; - color: #000; - padding: 12px 25px; - border-radius: 10px; - font-weight: bold; - font-size: 1.2em; - border: none; - cursor: pointer; - transition: 0.3s; -} - -a.button:hover, button:hover { - background: #00cccc; - box-shadow: 0 0 10px #00ffff; -} - -form { - display: flex; - flex-direction: column; - align-items: center; - gap: 15px; - margin-top: 30px; -} diff --git a/Oleksandr-JR-Example/src/main/webapp/index.jsp b/Oleksandr-JR-Example/src/main/webapp/index.jsp deleted file mode 100644 index bc7fe2e..0000000 --- a/Oleksandr-JR-Example/src/main/webapp/index.jsp +++ /dev/null @@ -1,14 +0,0 @@ -<%@ page contentType="text/html;charset=UTF-8" language="java" %> - - - - - Коллайдер - - - -

Коллайдер

-

Вітаємо в інтерактивному квесті!
Почни своє проходження прямо зараз!

-Почати гру - - diff --git a/Oleksandr-JR-Example/src/main/webapp/quiz.jsp b/Oleksandr-JR-Example/src/main/webapp/quiz.jsp deleted file mode 100644 index e8c28c2..0000000 --- a/Oleksandr-JR-Example/src/main/webapp/quiz.jsp +++ /dev/null @@ -1,47 +0,0 @@ -<%@ page contentType="text/html;charset=UTF-8" language="java" %> -<%@ page import="model.Question" %> -<%@ page import="java.util.*" %> -<% - Question question = (Question) request.getAttribute("question"); - int qIndex = (Integer) request.getAttribute("qIndex"); - Integer gamesPlayed = (Integer) session.getAttribute("gamesPlayed"); - if (gamesPlayed == null) gamesPlayed = 0; - - String text = question.getText().toLowerCase(); - boolean isEnding = text.contains("поразка") || text.contains("перемога"); -%> - - - - - Квест - - - - -

<%= question.getText() %>

- -

Кількість пройдених ігор: <%= gamesPlayed %>

- -<% if (isEnding) { %> -Почати заново -<% } else { %> -
- - <% - List answers = question.getAnswers(); - for (int i = 0; i < answers.size(); i++) { - %> - - <% - } - %> - -<% } %> - - - - - diff --git a/Oleksandr-JR-Example/src/main/webapp/result.jsp b/Oleksandr-JR-Example/src/main/webapp/result.jsp deleted file mode 100644 index 2f6d7d0..0000000 --- a/Oleksandr-JR-Example/src/main/webapp/result.jsp +++ /dev/null @@ -1,19 +0,0 @@ -<%@ page contentType="text/html;charset=UTF-8" language="java" %> - - - - - Результат - - - - -

Гра завершена!

- -

Дякуємо за гру!

-

Ви вже зіграли <%= session.getAttribute("gamesPlayed") != null ? session.getAttribute("gamesPlayed") : 1 %> раз(ів).

- -Почати заново - - - diff --git a/Oleksandr-JR-Example/src/test/java/controller/QuizServletTest.java b/Oleksandr-JR-Example/src/test/java/controller/QuizServletTest.java deleted file mode 100644 index a14f766..0000000 --- a/Oleksandr-JR-Example/src/test/java/controller/QuizServletTest.java +++ /dev/null @@ -1,88 +0,0 @@ -package controller; - -import model.Question; -import repository.QuestionRepository; - -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.List; - -import static org.mockito.Mockito.*; - -public class QuizServletTest { - - @InjectMocks - private QuizServlet realServlet; - - private QuizServlet servlet; - - @Mock - private HttpServletRequest request; - - @Mock - private HttpServletResponse response; - - @Mock - private HttpSession session; - - @Mock - private ServletContext servletContext; - - @Mock - private RequestDispatcher dispatcher; - - @BeforeEach - public void setup() { - MockitoAnnotations.openMocks(this); - - servlet = spy(realServlet); - when(request.getSession()).thenReturn(session); - when(request.getServletContext()).thenReturn(servletContext); - doReturn(servletContext).when(servlet).getServletContext(); - } - - @Test - public void testDoGet_NewGame_ShouldStartAtIndexZero() throws Exception { - when(session.getAttribute("currentIndex")).thenReturn(null); - when(servletContext.getRequestDispatcher("/quiz.jsp")).thenReturn(dispatcher); - - servlet.doGet(request, response); - - verify(session).setAttribute("currentIndex", 0); - verify(dispatcher).forward(request, response); - } - - @Test - public void testDoPost_ValidAnswer_RedirectsToNextQuestion() throws Exception { - QuestionRepository repo = QuestionRepository.getInstance(); - repo.getAll().clear(); - repo.getAll().add( - Question.builder() - .text("Test?") - .answers(new ArrayList<>(List.of("Yes", "No"))) - .nextQuestions(new ArrayList<>(List.of(1, 2))) - .build() - ); - - when(request.getParameter("qIndex")).thenReturn("0"); - when(request.getParameter("answerIndex")).thenReturn("1"); - when(request.getSession()).thenReturn(session); - - servlet.doPost(request, response); - - verify(session).setAttribute("currentIndex", 2); - verify(response).sendRedirect("quiz"); - } -} - diff --git a/Oleksandr-JR-Example/src/test/java/model/QuestionRepositoryTest.java b/Oleksandr-JR-Example/src/test/java/model/QuestionRepositoryTest.java deleted file mode 100644 index 2a12719..0000000 --- a/Oleksandr-JR-Example/src/test/java/model/QuestionRepositoryTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package model; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import repository.QuestionRepository; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -public class QuestionRepositoryTest { - - private QuestionRepository repository; - - @BeforeEach - public void setup() { - repository = QuestionRepository.getInstance(); - repository.getAll().clear(); - - repository.getAll().add( - Question.builder() - .text("Question 0?") - .answers(new ArrayList<>(List.of("Answer 1", "Answer 2"))) - .nextQuestions(new ArrayList<>(List.of(1, 2))) - .build() - ); - - repository.getAll().add( - Question.builder() - .text("Question 1?") - .answers(new ArrayList<>()) - .nextQuestions(new ArrayList<>()) - .build() - ); - - repository.getAll().add( - Question.builder() - .text("Question 2?") - .answers(new ArrayList<>()) - .nextQuestions(new ArrayList<>()) - .build() - ); - } - - @Test - public void testQuestionsAreLoaded() { - ArrayList questions = repository.getAll(); - assertFalse(questions.isEmpty(), "Questions should be loaded"); - } - - @Test - public void testTwoAnswers() { - Question q0 = repository.getAll().get(0); - assertEquals(2, q0.getAnswers().size(), "First question should have two answers"); - } - - @Test - public void testNavigation() { - Question q0 = repository.getAll().get(0); - int next = q0.getNextQuestions().get(0); - Question q1 = repository.getAll().get(next); - assertNotNull(q1, "Should navigate to next question"); - } - - @Test - public void testHaveNoNext() { - for (Question q : repository.getAll()) { - if (q.getAnswers().isEmpty()) { - assertTrue(q.getNextQuestions().isEmpty(), "Terminal questions should not have next steps"); - } - } - } -}