Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
653d4e8
3.0 ADD Bootstrap template Superhero
akhmelev Jan 12, 2026
f8750ea
3.0 REF Restore home (start page)
akhmelev Jan 12, 2026
a09b884
3.0 ADD ImageService for edit-user
akhmelev Jan 12, 2026
63f6474
3.0 ADD Signup, Login, Logout, Profile
akhmelev Jan 12, 2026
6c9d46b
3.1 ADD JS-dummy and CreateQuest.java
akhmelev Jan 15, 2026
474e404
3.1 ADD entities
akhmelev Jan 15, 2026
873418d
3.1 ADD all repo + config
akhmelev Jan 15, 2026
203a7dc
3.1 ADD Quest (cmd+view+service+edit)
akhmelev Jan 15, 2026
5088463
3.1 ADD QUESTS + images (start demo content)
akhmelev Jan 15, 2026
537f588
3.1 ADD play game (draft)
akhmelev Jan 15, 2026
909b0ce
3.2 ADD support errors
akhmelev Jan 19, 2026
0e3ef4b
3.2 ADD AuthorizationFilter + Fix Title
akhmelev Jan 19, 2026
798858e
3.2 FIX Design gamepage + Universal ImageService
akhmelev Jan 19, 2026
95e26a1
3.3 ADD IT tests + one unit
akhmelev Jan 22, 2026
b958f14
3.3 ADD Statistics
akhmelev Jan 22, 2026
bf1c4a5
3.3 ADD Jacoco
akhmelev Jan 22, 2026
7c89bb9
3.3 FIX Winter->NanoSpring
akhmelev Jan 22, 2026
2e3c16f
init
GDGo Jan 24, 2026
b491dfd
del tests
GDGo Jan 24, 2026
878768d
commit
GDGo Jan 24, 2026
201a8e6
add image service
GDGo Jan 24, 2026
26f78e8
add contact us
GDGo Jan 25, 2026
c90437c
commit
GDGo Jan 25, 2026
abde3de
add auth service
GDGo Jan 25, 2026
e3afbf7
edit auth service, edit storage, edit jsp
GDGo Jan 26, 2026
15ff812
add list-users
GDGo Jan 27, 2026
5653c35
add list users
GDGo Jan 27, 2026
cbb4bac
edit auth service
GDGo Jan 28, 2026
126c0f0
complete auth service
GDGo Jan 28, 2026
f697eb4
add email in User model
GDGo Jan 30, 2026
7f0590f
add logic delete user
GDGo Jan 30, 2026
98c2c0e
modify logic delete user, add page delete user
GDGo Jan 31, 2026
588dacf
add logic work with arrived message
GDGo Jan 31, 2026
7b3928d
edit logic delete and completed arrive messages
GDGo Feb 1, 2026
bad384f
completed work with aiive messages
GDGo Feb 2, 2026
fcf4489
start add logic create quest
GDGo Feb 3, 2026
0c4303c
add logic create quest
GDGo Feb 4, 2026
d4aad79
add logic create quest, add question repo, add question service
GDGo Feb 4, 2026
1e221d7
add logic create quest, add question repo, add question service #2
GDGo Feb 5, 2026
7d21e6c
add logic create quest, add question repo, add question service #3
GDGo Feb 5, 2026
8c85123
add ServletContextListener, refactoring init services
GDGo Feb 5, 2026
a2f79d5
start add logic playing in quest
GDGo Feb 8, 2026
1f0dadb
complete logic create and playing quest
GDGo Feb 10, 2026
258f233
add Statistic
GDGo Feb 11, 2026
c8052e2
fix: Added logic for handling empty responses in the quest
GDGo Feb 11, 2026
ad344ad
add Exception, log
GDGo Feb 12, 2026
bb9bb48
add delete quest
GDGo Feb 13, 2026
28cb64f
start add tests
GDGo Feb 14, 2026
b136bae
refactoring and add new test
GDGo Feb 15, 2026
47036b6
complete
GDGo Feb 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Quest Pantera

### Ребята и девчата, всем привет!

На этот раз у нас более сложный проект, который будет трудно объединить в один общий проект со всем зависимостями.
Поэтому поступим просто. Тут первоначально лежит наш учебный проект.
Заготовка, такая же как может быть сгенерирована в IDEA.
Договоримся, что Java у нас будет 21-я. У всех. Привыкайте использовать только LTS.
Из зависимостей есть jakarta.servlet-api + jstl, JUnit5 и Lombok,
так что POM.xml возможно надо будет заменить на свой.

### Что нужно сделать.

1. Сделайте форк и затем клон этого репозитория.
2. **СРАЗУ** создайте в нем ветку со своей фамилией, например, ivanov.
3. Размещайте в своей ветке свое решение (если мои примеры мешают их можно просто удалить - ветвление же).
4. В конце вам нужно будет сделать **Pull Request** из своей ветки (в своем форке) в такую же точно ветку (в этом удаленном
репозитории), если вы не найдете - тогда в **main** ну и затем ОБЯЗАТЕЛЬНО заполнить форму проектов.
5. Я положу в ветку **khmelov** тот пример, который буду параллельно с вами разрабатывать на факультативах. Полезнее будет
не копипастить, смотрите видео, разбирайтесь, что, почему, где и как сделано. Не копируйте, нужно ВАШЕ решение. Но мы уже и
не совсем зеленые, правда ведь ;).
6. Проверять проекты по итогам третьего модуля я буду с **code review**, и скорее всего быстро не получится, так что за
сроки сдачи можно не волноваться.
7. Планируйте время так, первые три консультации - основной функционал. Последняя консультация - плюшки, рефакторинг,
тесты, красоты.
8. Если будут какие-то моменты - я обновлю это README. Поглядывайте периодически.

#### _2026 JRU Pantera, Александр Хмелев._
111 changes: 87 additions & 24 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,39 @@
<modelVersion>4.0.0</modelVersion>

<groupId>com.javarush.khmelov</groupId>
<artifactId>project-ledzeppelin</artifactId>
<artifactId>project-Pantera</artifactId>
<version>1.0-SNAPSHOT</version>
<name>ProjectLedzeppelin</name>
<name>ProjectPantera</name>
<packaging>war</packaging>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>21</maven.compiler.target>
<maven.compiler.source>21</maven.compiler.source>
<junit.version>5.10.2</junit.version>
</properties>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
</parent>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.3.4</version>
<type>pom</type>
<scope>import</scope>
<version>3.3.5</version>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
Expand All @@ -49,12 +51,20 @@
<groupId>org.glassfish.web</groupId>
<artifactId>jakarta.servlet.jsp.jstl</artifactId>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>


<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
Expand All @@ -65,6 +75,17 @@
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>


</dependencies>

Expand All @@ -73,22 +94,64 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.4.0</version>
<version>3.3.2</version>
</plugin>
<!-- Surefire Plugin for running unit tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.5</version>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
</path>
</annotationProcessorPaths>
<excludes>
<exclude>**/*IT.java</exclude>
</excludes>
</configuration>
</plugin>
<!-- Failsafe Plugin for integration tests in verify phase -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.2.5</version>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>**/*IT.java</include>
</includes>
</configuration>
</plugin>
<!-- Jacoco plugin for generate report in verify phase -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>

</build>
</project>
48 changes: 48 additions & 0 deletions src/main/java/com/javarush/goncharov/controller/AppConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.javarush.goncharov.controller;

import com.javarush.goncharov.repository.*;
import com.javarush.goncharov.service.*;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Getter
@FieldDefaults(level = AccessLevel.PRIVATE)
public class AppConfig {
final Storage storage = Storage.getInstance();
final UserService userService;
final MessageService messageService;
final QuestService questService;
final QuestionService questionService;
final GameService gameService;
final AnswerRepository answerRepository;
final StatisticService statisticService;

public AppConfig() {
log.info("Init MessageService..");
messageService = new MessageService(new MessageRepository(storage));
log.info("Init UserService..");
userService = new UserService(new UserRepository(storage));
log.info("Init QuestionService..");
questionService = new QuestionService(new QuestionRepository(storage));
log.info("Init QuestionService..");
answerRepository = new AnswerRepository(storage);
log.info("Init QuestService..");
questService = new QuestService(answerRepository,
questionService,
userService,
new QuestRepository(storage));
log.info("Init GameService..");
gameService = new GameService(new GameRepository(storage),
questService,
questionService,
userService,
answerRepository);
log.info("Init StatisticService..");
statisticService = new StatisticService(new GameRepository(storage),
new UserRepository(storage));

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.javarush.goncharov.controller;

import com.javarush.goncharov.model.Message;
import com.javarush.goncharov.model.Topic;
import com.javarush.goncharov.model.User;
import com.javarush.goncharov.repository.MessageRepository;
import com.javarush.goncharov.repository.Storage;
import com.javarush.goncharov.service.MessageService;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import java.io.IOException;
import java.util.Collection;
import java.util.Optional;

@WebServlet("/completed-messages")
public class CompletedMessages extends DefaultServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Collection<Message> messages = messageService.getAll().values();
HttpSession session = req.getSession();
User user = (User) session.getAttribute("user");
req.setAttribute("messages", messages);
req.setAttribute("user", user);
req.getRequestDispatcher("/WEB-INF/completed-messages.jsp").forward(req, resp);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if (req.getParameter("action").equals("GoMessages")) {
resp.sendRedirect("/messages");
return;
}
Long idMessage = Long.parseLong(req.getParameter("id"));
Optional<Message> message = messageService.get(idMessage);
if (req.getParameter("action").equals("delete")) {
messageService.delete(message.get());
resp.sendRedirect("/completed-messages");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.javarush.goncharov.controller;

import com.javarush.goncharov.model.Role;
import com.javarush.goncharov.model.Topic;
import com.javarush.goncharov.service.*;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import jakarta.servlet.annotation.WebListener;

@WebListener
public class ConfigAppInitializer implements ServletContextListener {

@Override
public void contextInitialized(ServletContextEvent sce) {
AppConfig appConfig = new AppConfig();

ServletContext servletContext = sce.getServletContext();
servletContext.setAttribute("userService", appConfig.getUserService());
servletContext.setAttribute("messageService", appConfig.getMessageService());
servletContext.setAttribute("questService", appConfig.getQuestService());
servletContext.setAttribute("questionService", appConfig.getQuestionService());
servletContext.setAttribute("gameService", appConfig.getGameService());
servletContext.setAttribute("answerRepository", appConfig.getAnswerRepository());
servletContext.setAttribute("statisticService", appConfig.getStatisticService());
servletContext.setAttribute("topics", Topic.values());
servletContext.setAttribute("roles", Role.values());
}
}
53 changes: 53 additions & 0 deletions src/main/java/com/javarush/goncharov/controller/ContactUs.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.javarush.goncharov.controller;

import com.javarush.goncharov.model.Message;
import com.javarush.goncharov.model.Topic;
import com.javarush.goncharov.repository.MessageRepository;
import com.javarush.goncharov.repository.Storage;
import com.javarush.goncharov.service.MessageService;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

import java.io.IOException;

@WebServlet("/contact")
public class ContactUs extends DefaultServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/WEB-INF/contact.jsp").forward(req, resp);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
if (req.getParameter("name").isEmpty() ||
req.getParameter("email").isEmpty() ||
req.getParameter("message").isEmpty()){
session.setAttribute("alertType", "danger");
session.setAttribute("alertMessage",
"Не заполнены все обязательные поля, попробуйте снова!");
resp.sendRedirect("/contact");
return;
}
String name = req.getParameter("name");
Message message = Message.builder()
.name(req.getParameter("name"))
.email(req.getParameter("email"))
.message(req.getParameter("message"))
.topic(Topic.valueOf(req.getParameter("topic")))
.Completed(false)
.build();
messageService.post(message);
session.setAttribute("alertType", "success");
session.setAttribute("alertMessage",
"Спасибо, " + name + "! Ваше сообщение успешно отправлено.");
resp.sendRedirect("/contact");
}
}
Loading