Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
9 changes: 9 additions & 0 deletions .idea/libraries/gson_2_9_0.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

168 changes: 136 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,147 @@
# java-kanban
### Основа для менеджера задач
# Java Kanban - Менеджер задач

---
## Содержание
- #### Main - пример добавления задачи
- #### TaskManager - основные методы работы программы
- #### Task - родитель всех задач
- #### Epic - задача, способная хранить другие задачи
- #### SubTask - задача, принадлежащая эпику
- #### Status - статусы задач
## Описание проекта

---
**Java Kanban** - это бэкенд-система для управления задачами, реализующая менеджер задач и HTTP-сервер.

## Особенности задач
### Каждая задача обладает:
Система поддерживает три типа задач: обычные задачи(Task), эпики(Epic) и подзадачи(SubTask).

- #### уникальным id
- #### названием
- #### описанием
- #### статусом
## Функциональные возможности

#### Эпик хранит каждую подзадачу, которая в него входит
#### Подзадача хранит id эпика, которому принадлежит
### Управление задачами
- Создание, обновление и удаление задач всех типов
- Хранение истории просмотров задач
- Очистка всей истории просмотров
- Обработка ошибок при создании и обновлении задач

---
### Получение информации
- Получение списков всех задач/эпиков/подзадач
- Поиск задач по ID
- Получение всех подзадач конкретного эпика
- Получение задач в порядке приоритета (по времени начала)

## TaskManager
Здесь хранятся основным методы работы с задачами и сами задачи
в таблицах (id=задача)
## Технологический стек
- **Java** - основной язык программирования
- **JUnit 5** - фреймворк для модульного тестирования
- **Gson** - библиотека для работы с JSON

- Добавление задачи в таблицу
- Получение задачи по id
- Удаление задачи из таблицы
- Удаление всех задач или всех задач из определенной задачи
- Печать задач в разных форматах
- Обновление задачи (задача меняет свое название или описание)
## API

Пользователь способен обновить статус задачи, обновив саму задачу.
При это обновление статуса эпика происходит независимо от пользователя,
а благодаря вычислениям
### Поддерживаемые форматы времени

Система поддерживает следующие форматы для полей `startTime`:

- `DateTimeFormatter.ISO_LOCAL_DATE_TIME` - `2023-10-15T14:30:00`
- `DateTimeFormatter.ISO_DATE_TIME` - `2023-10-15T14:30:00.000+03:00`
- `yyyy-MM-dd HH:mm:ss.SSS` - `2023-10-15 14:30:00.000`
- `yyyy-MM-dd HH:mm:ss` - `2023-10-15 14:30:00`
- `dd.MM.yyyy HH:mm:ss` - `15.10.2023 14:30:00`

### Коды состояния HTTP

Система использует следующие HTTP коды состояния для обработки запросов:

| Код | Описание |
|---------|-----------------------------------------------------------------------------------------------------------|
| **200** | Успешный запрос (GET, HEAD, DELETE, OPTIONS) |
| **201** | Успешное создание или обновление ресурса (POST) |
| **400** | Неверный формат JSON или отсутствуют обязательные поля, неверный формат времени, id не число или меньше 0 |
| **404** | Задача не найдена или неверный путь |
| **405** | Метод не разрешен для ресурса |
| **406** | Пересечение временных интервалов с существующими задачами |
| **500** | Внутренняя ошибка сервера |

### Задачи (Tasks)

| Метод | Путь | Действие | Коды ответа |
|-------|------|----------|-------------|
| HEAD | `/tasks` или `/tasks/{id}` | Получить заголовки | 200, 404 |
| GET | `/tasks` | Получить все задачи | 200 |
| GET | `/tasks/{id}` | Получить задачу по ID | 200, 404 |
| POST | `/tasks` | Создать новую задачу | 201, 400, 406 |
| DELETE | `/tasks` | Удалить все задачи | 200 |
| DELETE | `/tasks/{id}` | Удалить задачу по ID | 200, 404 |
| OPTIONS | `/tasks` или `/tasks/{id}` | Получить разрешенные методы | 200 |

#### Формат JSON для задачи
```json
{
"taskId": 0, // 0 - для создания, >0 - для обновления (обязательное)
"title": "string", // обязательное поле
"description": "string", // обязательное поле
"status": "NEW|IN_PROGRESS|DONE", // обязательное поле
"duration": 10, // продолжительность в минутах (опционально)
"startTime": "1970-01-01T00:00:00.000" // дата и время ISO (опционально)
}
```

### Эпики (Epics)

| Метод | Путь | Действие | Коды ответа |
|-------|------|----------|-------------|
| HEAD | любой путь | Получить заголовки | 200, 404 |
| GET | `/epics` | Получить все эпики | 200 |
| GET | `/epics/{id}` | Получить эпик по ID | 200, 404 |
| GET | `/epics/{id}/subtasks` | Получить все подзадачи эпика | 200, 404 |
| POST | `/epics` | Создать новый эпик | 201, 400, 406 |
| DELETE | `/epics` | Удалить все эпики | 200 |
| DELETE | `/epics/{id}` | Удалить эпик по ID | 200, 404 |
| DELETE | `/epics/{id}/subtasks` | Удалить все подзадачи эпика | 200, 404 |
| OPTIONS | любой путь | Получить разрешенные методы | 200 |

#### Формат JSON для эпика
```json
{
"taskId": 0, //0 - для создания, >0 - для обновления (обязательное)
"title": "string", // обязательное поле
"description": "string", // обязательное поле
"status": "NEW|IN_PROGRESS|DONE", // только для чтения
"subtasks": [1, 2, 3], // только для чтения
"duration": 10, // только для чтения
"startTime": "1970-01-01T00:00:00.000" // только для чтения
}
```

### Подзадачи (Subtasks)

| Метод | Путь | Действие | Коды ответа |
|-------|------|----------|-------------|
| HEAD | `/subtasks` или `/subtasks/{id}` | Получить заголовки | 200, 404 |
| GET | `/subtasks` | Получить все подзадачи | 200 |
| GET | `/subtasks/{id}` | Получить подзадачу по ID | 200, 404 |
| POST | `/subtasks` | Создать новую подзадачу | 201, 400, 406 |
| DELETE | `/subtasks` | Удалить все подзадачи | 200 |
| DELETE | `/subtasks/{id}` | Удалить подзадачу по ID | 200, 404 |

#### Формат JSON для подзадачи
```json
{
"taskId": 0, // 0 - для создания, >0 - для обновления (обязательное)
"title": "string", // обязательное поле
"description": "string", // обязательное поле
"status": "NEW|IN_PROGRESS|DONE", // обязательное поле
"epicId": 123, // обязательное поле - ID родительского эпика
"duration": 10, // продолжительность в минутах (опционально)
"startTime": "1970-01-01T00:00:00.000" // дата и время ISO (опционально)
}
```

## История просмотров (History)

| Метод | Путь | Действие | Коды ответа |
|-------|------|----------|-------------|
| HEAD | `/history` | Получить заголовки | 200 |
| GET | `/history` | Получить историю просмотров | 200 |
| OPTIONS | `/history` | Получить разрешенные методы | 200 |

## Список приоритетов (Prioritized)

| Метод | Путь | Действие | Коды ответа |
|-------|------|----------|-------------|
| HEAD | `/prioritized` | Получить заголовки | 200 |
| GET | `/prioritized` | Получить отсортированный список задач | 200 |
| OPTIONS | `/prioritized` | Получить разрешенные методы | 200 |

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

Проект включает модульные тесты с использованием JUnit 5 для проверки функциональности менеджера задач и HTTP-сервера.
1 change: 1 addition & 0 deletions java-kanban.iml
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@
<SOURCES />
</library>
</orderEntry>
<orderEntry type="library" name="gson-2.9.0" level="project" />
</component>
</module>
67 changes: 67 additions & 0 deletions src/http/HttpTaskServer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package http;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.sun.net.httpserver.HttpServer;
import http.handlers.*;
import managers.InMemoryTaskManager;
import managers.TaskManager;
import util.gsonadapters.DurationAdapter;
import util.gsonadapters.LocalDateTimeAdapter;
import util.http.JsonBuilder;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.time.Duration;
import java.time.LocalDateTime;

public class HttpTaskServer {
private final int port = 8080;
private HttpServer httpServer;
private final TaskManager manager;

private final Gson gson;
private final JsonBuilder jsonBuilder;

public static void main(String[] args) {
new HttpTaskServer(new InMemoryTaskManager()).start();
}

public HttpTaskServer(TaskManager manager) {
this.manager = manager;
this.gson = new GsonBuilder()
.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter())
.registerTypeAdapter(Duration.class, new DurationAdapter())
.create();
this.jsonBuilder = new JsonBuilder(gson);
createServer();
}

private void createServer() {
try {
httpServer = HttpServer.create(new InetSocketAddress(port), 0);
httpServer.createContext("/tasks", new TaskHandler(manager, gson, jsonBuilder));
httpServer.createContext("/epics", new EpicsHandler(manager, gson, jsonBuilder));
httpServer.createContext("/subtasks", new SubTasksHandler(manager, gson, jsonBuilder));
httpServer.createContext("/history", new HistoryHandler(manager, gson, jsonBuilder));
httpServer.createContext("/prioritized", new PrioritizedHandler(manager, gson, jsonBuilder));

} catch (IOException e) {
e.printStackTrace();
}
}

public void start() {
try {
httpServer.start();
System.out.println("Server is running: " + httpServer.getAddress().getPort());
} catch (IllegalStateException e) {
System.err.println("Server is already running");
}
}

public void stop() {
httpServer.stop(0);
System.out.println("Server has been stopped");
}
}
Loading