diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..323c3d3 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..c0ee0d5 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/.idea/libraries/google_code_gson.xml b/.idea/libraries/google_code_gson.xml new file mode 100644 index 0000000..b8c8e54 --- /dev/null +++ b/.idea/libraries/google_code_gson.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/gson_2_9_0.xml b/.idea/libraries/gson_2_9_0.xml new file mode 100644 index 0000000..2377008 --- /dev/null +++ b/.idea/libraries/gson_2_9_0.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/junit_jupiter_api.xml b/.idea/libraries/junit_jupiter_api.xml new file mode 100644 index 0000000..f72d723 --- /dev/null +++ b/.idea/libraries/junit_jupiter_api.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 684cd49..e0844bc 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..35eb1dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/Tracker.iml b/Tracker.iml index bed5a81..93e3756 100644 --- a/Tracker.iml +++ b/Tracker.iml @@ -1,76 +1,22 @@ - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + \ No newline at end of file diff --git a/lib/gson-2.9.0.jar b/lib/gson-2.9.0.jar new file mode 100644 index 0000000..fb62e05 Binary files /dev/null and b/lib/gson-2.9.0.jar differ diff --git a/lib/junit-jupiter-api-5.11.4.jar b/lib/junit-jupiter-api-5.11.4.jar new file mode 100644 index 0000000..035c0a4 Binary files /dev/null and b/lib/junit-jupiter-api-5.11.4.jar differ diff --git a/lib/junit-platform-commons-1.11.4.jar b/lib/junit-platform-commons-1.11.4.jar new file mode 100644 index 0000000..c9ed1eb Binary files /dev/null and b/lib/junit-platform-commons-1.11.4.jar differ diff --git a/lib/opentest4j-1.3.0.jar b/lib/opentest4j-1.3.0.jar new file mode 100644 index 0000000..7ec7bc5 Binary files /dev/null and b/lib/opentest4j-1.3.0.jar differ diff --git a/src/Main.java b/src/Main.java index 9afb99b..d4afb42 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,34 +1,20 @@ import tracker.*; -import java.io.File; +import java.io.IOException; import java.time.Duration; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.List; import java.util.Scanner; -import java.util.TreeSet; public class Main { - public static void main(String[] args) { - Scanner scanner = new Scanner(System.in); - int id; - String heading; - String description; - - HashMap tasks = new HashMap<>(); - HashMap epicTasks = new HashMap<>(); - HashMap> subTasks = new HashMap<>(); + public static void main(String[] args) throws IOException { + new KVServer().start(); - String fileName = "tasks.csv"; - File file = new File(fileName); + HttpTaskManager httpManager = (HttpTaskManager) Managers.getDefault("http://localhost:8078"); + new HttpTaskServer(httpManager).start(); - FileBackedTaskManager manager; - if (file.exists()) { - manager = FileBackedTaskManager.loadFromFile(file); - } else { - manager = new FileBackedTaskManager(tasks, epicTasks, subTasks, fileName); - } + Scanner scanner = new Scanner(System.in); while (true) { printMenu(); @@ -36,11 +22,13 @@ public static void main(String[] args) { scanner.nextLine(); switch (command) { - case 1: + case 1: // Создать задачу System.out.println("Введите название задачи:"); - heading = scanner.nextLine(); + String heading = scanner.nextLine(); System.out.println("Введите описание задачи:"); - description = scanner.nextLine(); + String description = scanner.nextLine(); + System.out.println("Введите идентификатор задачи:"); + int id = scanner.nextInt(); System.out.println("Введите продолжительность задачи (в минутах):"); long durationMinutes = scanner.nextLong(); Duration duration = Duration.ofMinutes(durationMinutes); @@ -48,185 +36,92 @@ public static void main(String[] args) { String startTimeInput = scanner.next(); LocalDateTime startTime = LocalDateTime.parse(startTimeInput); - int index = manager.getTaskIndex(heading, description, "task"); - - if (index != -1) { - System.out.println("Такая задача уже есть! Ее индекс: " + tasks.get(index).getId()); - } else { - Task newTask = new Task(heading, description, index, duration, startTime); - manager.createTask(newTask); - System.out.println("Задача успешно создана! Ее индекс: " + newTask.getId()); - } + Task newTask = new Task(heading, description, id, duration, startTime); + httpManager.addTask(newTask); + System.out.println("Задача успешно создана! Ее идентификатор: " + newTask.getId()); break; - case 2: + case 2: // Обновить задачу System.out.println("Введите идентификатор задачи, которую хотите отредактировать: "); id = scanner.nextInt(); - if (manager.checkTaskId(id) || manager.checkEpicTaskId(id)) { - while (true) { - System.out.println("Выберите нужное действие:"); - System.out.println("1 - Редактировать название"); - System.out.println("2 - Редактировать описание"); - System.out.println("0 - Закончить редактирование"); - int comm = scanner.nextInt(); - scanner.nextLine(); - - if (comm == 1) { - System.out.println("Введите новое название:"); - String newHeading = scanner.nextLine(); - manager.updateTask(id, comm, newHeading); - System.out.println("Новое название сохранено!"); - } else if (comm == 2) { - System.out.println("Введите новое описание:"); - String newDescription = scanner.nextLine(); - manager.updateTask(id, comm, newDescription); - System.out.println("Новое описание сохранено!"); - } else if (comm == 0) { - break; - } else { - System.out.println("Такой команды нет!"); - } + if (httpManager.getTaskById(id) != null) { + System.out.println("Выберите нужное действие:"); + System.out.println("1 - Редактировать название"); + System.out.println("2 - Редактировать описание"); + int comm = scanner.nextInt(); + scanner.nextLine(); + + if (comm == 1) { + System.out.println("Введите новое название:"); + String newHeading = scanner.nextLine(); + httpManager.updateTaskName(id, newHeading); + System.out.println("Новое название сохранено!"); + } else if (comm == 2) { + System.out.println("Введите новое описание:"); + String newDescription = scanner.nextLine(); + httpManager.updateTaskDescription(id, newDescription); + System.out.println("Новое описание сохранено!"); + } else { + System.out.println("Такой команды нет!"); } } else { System.out.println("Задачи с таким id пока что нет"); } break; - case 3: + case 3: // Вывести задачу по id System.out.println("Введите идентификатор задачи, которую хотите посмотреть:"); id = scanner.nextInt(); - - String taskType = manager.getTaskTypeById(id); - if (taskType != null) { - switch (taskType) { - case "TASK": - Task task = manager.getTaskById(id); - System.out.println("Задача: " + task); - break; - case "EPIC": - EpicTask epic = manager.getEpicTaskById(id); - System.out.println("Эпик: " + epic); - break; - case "SUB": - Subtask subtask = manager.getSubTaskById(id); - System.out.println("Подзадача: " + subtask); - break; - default: - System.out.println("Неизвестный тип задачи."); - break; - } + Task task = httpManager.getTaskById(id); + if (task != null) { + System.out.println("Задача: " + task); } else { System.out.println("Задача с ID " + id + " не найдена."); } break; - case 4: + + case 4: // Удалить все задачи System.out.println("Уверены, что хотите удалить все задачи?"); System.out.println("1 - да"); System.out.println("2 - нет"); int answer = scanner.nextInt(); if (answer == 1) { - manager.removeAllTasks(); - manager.removeAllEpicTasks(); - manager.removeAllSubTasks(); + httpManager.removeAllTasks(); System.out.println("Все задачи удалены!"); - } else { - break; } break; - case 5: + + case 5: // Удалить задачу по id System.out.println("Введите идентификатор задачи, которую хотите удалить:"); id = scanner.nextInt(); - if (manager.removeTaskById(id)) { + if (httpManager.removeTaskById(id)) { System.out.println("Задача успешно удалена!"); } else { System.out.println("Задачи с таким идентификатором пока что нет"); } break; - case 6: - System.out.println("== Список обычных задач: =="); - System.out.println(manager.getAllTasks()); - System.out.println(); - System.out.println("== Список глобальных задач: =="); - System.out.println(manager.getAllEpicTasks()); - System.out.println(); - System.out.println("== Список подзадач: =="); - System.out.println(manager.getAllSubTasks()); - System.out.println(); - break; - case 7: - System.out.println("Введите идентификатор эпика"); - id = scanner.nextInt(); - System.out.println(manager.getSubtasks(id)); - break; - - case 8: - System.out.println("Введите название эпика:"); - heading = scanner.nextLine(); - System.out.println("Введите описание эпика:"); - description = scanner.nextLine(); - - - int epicIndex = manager.getTaskIndex(heading, description, "epic task"); - - if (epicIndex != -1) { - System.out.println("Такой глобальной задачи уже есть! Ее идентификатор - " + epicTasks.get(epicIndex).getId()); - } else { - EpicTask newEpicTask = new EpicTask(heading, description, epicIndex); - manager.createEpicTask(newEpicTask); - System.out.println("Глобальная задача успешно создана! Ее идентификатор: " + newEpicTask.getId()); - } - break; - case 9: - System.out.println("Укажите идентификатор эпика:"); - int epicId = scanner.nextInt(); - scanner.nextLine(); - if (!manager.checkEpicTaskId(epicId)) { - System.out.println("Эпика с таким индексом нет"); - break; + case 6: // Вывести все задачи + System.out.println("== Список задач: =="); + List allTasks = httpManager.getAllTasks(); + for (Task t : allTasks) { + System.out.println(t); } - System.out.println("Введите заголовок подзадачи"); - heading = scanner.nextLine(); - System.out.println("Введите описание подзадачи:"); - description = scanner.nextLine(); - - System.out.println("Введите продолжительность задачи (в минутах):"); - durationMinutes = scanner.nextLong(); - duration = Duration.ofMinutes(durationMinutes); - System.out.println("Введите дату и время начала выполнения эпика (в формате YYYY-MM-DDTHH:MM):"); - startTimeInput = scanner.next(); - startTime = LocalDateTime.parse(startTimeInput); - - Subtask newSubtask = new Subtask(heading, description, 0, epicId, duration, startTime); - Subtask createdSubtask = manager.createSubTask(newSubtask); - System.out.println("Подзадача успешно создана! Ее идентификатор - " + createdSubtask.getId()); break; - case 10: - System.out.println("Введите идентификатор задачи"); - id = scanner.nextInt(); - int status = 0; - if (!epicTasks.containsKey(id)) { - System.out.println("Укажите статус задачи:"); - System.out.println("1 - в процессе"); - System.out.println("2 - сделана"); - status = scanner.nextInt(); - } - System.out.println(manager.checkStatus(id, status)); - System.out.println("Статус изменен!"); - break; - case 11: - System.out.println(Managers.getDefaultHistory().getHistory()); - break; - case 12: // Например, добавим новый пункт в меню для получения приоритезированных задач + case 7: // Вывести приоритезированные задачи System.out.println("== Приоритезированные задачи: =="); - TreeSet prioritizedTasks = manager.getPrioritizedTasks(); - for (Task task : prioritizedTasks) { - System.out.println(task); + List prioritizedTasks = httpManager.getPrioritizedTasks(); + for (Task prioritizedTask : prioritizedTasks) { + System.out.println(prioritizedTask); } break; - case 13: + + case 8: return; + + default: + System.out.println("Неизвестная команда. Попробуйте снова."); } } } @@ -239,12 +134,7 @@ private static void printMenu() { System.out.println("4 - Удалить все задачи"); System.out.println("5 - Удалить задачу по id"); System.out.println("6 - Вывести все задачи"); - System.out.println("7 - Вывести подзадачи эпика"); - System.out.println("8 - Создать эпик"); - System.out.println("9 - Добавить подзадачи в эпик"); - System.out.println("10 - Отметить сделанную задачу"); - System.out.println("11 - Показать историю просмотров"); - System.out.println("12 - Вывести задачи приотизировано"); - System.out.println("13 - Выход"); + System.out.println("7 - Вывести приоритезированные задачи"); + System.out.println("8 - Выход"); } } \ No newline at end of file diff --git a/src/tracker/Endpoint.java b/src/tracker/Endpoint.java new file mode 100644 index 0000000..753d9a8 --- /dev/null +++ b/src/tracker/Endpoint.java @@ -0,0 +1,12 @@ +package tracker; + +public enum Endpoint { + GET_TASKS, + GET_PRIORITIZED, + GET_HISTORY, + GET_BY_ID, + DELETE_TASKS, + DELETE_BY_ID, + POST_TASK, + UNKNOWN +} diff --git a/src/tracker/EpicTask.java b/src/tracker/EpicTask.java index 2104501..b7d4d82 100644 --- a/src/tracker/EpicTask.java +++ b/src/tracker/EpicTask.java @@ -3,36 +3,40 @@ import java.time.Duration; import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; public class EpicTask extends Task { - private ArrayList subtasks; + private List subtasksIds; public EpicTask(String heading, String description, int id) { - super(heading, description, id, Duration.ZERO, null); // Устанавливаем нулевую продолжительность и null для startTime - this.subtasks = new ArrayList<>(); + super(heading, description, id, Duration.ZERO, null); + this.subtasksIds = new ArrayList<>(); } - public void addSubtask(Subtask subtask) { - subtasks.add(subtask); - calculateEpicDetails(); + public List getSubtasksIds() { + return subtasksIds; } - public ArrayList getSubtasks() { - return subtasks; + public void setSubtasksIds(int subtaskId) { + subtasksIds.add(subtaskId); } - private void calculateEpicDetails() { + private void calculateEpicDetails(HashMap subtasks) { Duration totalDuration = Duration.ZERO; LocalDateTime earliestStartTime = null; LocalDateTime latestEndTime = null; - for (Subtask subtask : subtasks) { - totalDuration = totalDuration.plus(subtask.getDuration()); - if (earliestStartTime == null || (subtask.getStartTime() != null && subtask.getStartTime().isBefore(earliestStartTime))) { - earliestStartTime = subtask.getStartTime(); - } - if (latestEndTime == null || (subtask.getEndTime() != null && subtask.getEndTime().isAfter(latestEndTime))) { - latestEndTime = subtask.getEndTime(); + for (Integer subtaskId : subtasksIds) { + Subtask subtask = subtasks.get(subtaskId); // Получаем подзадачу по идентификатору + if (subtask != null) { // Проверяем, что подзадача существует + totalDuration = totalDuration.plus(subtask.getDuration()); + if (earliestStartTime == null || (subtask.getStartTime() != null && subtask.getStartTime().isBefore(earliestStartTime))) { + earliestStartTime = subtask.getStartTime(); + } + if (latestEndTime == null || (subtask.getEndTime() != null && subtask.getEndTime().isAfter(latestEndTime))) { + latestEndTime = subtask.getEndTime(); + } } } @@ -83,9 +87,11 @@ public static EpicTask fromString(String value) { // Инициализация пустого списка подзадач, если у эпика нет подзадач if (duration.isZero() && startTime == null) { - epicTask.subtasks = new ArrayList<>(); // Инициализируем пустой список подзадач + epicTask.subtasksIds = new ArrayList<>(); // Инициализируем пустой список подзадач } return epicTask; } -} \ No newline at end of file +} + + diff --git a/src/tracker/FileBackedTaskManager.java b/src/tracker/FileBackedTaskManager.java index c3de901..3a5f1d0 100644 --- a/src/tracker/FileBackedTaskManager.java +++ b/src/tracker/FileBackedTaskManager.java @@ -1,243 +1,211 @@ package tracker; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.*; +import java.io.*; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; -public class FileBackedTaskManager extends InMemoryTaskManager { - private final String filePath; - private int lastId; - - public FileBackedTaskManager(HashMap tasks, HashMap epicTasks, HashMap> subTasks, String filePath) { - super(tasks, epicTasks, subTasks); - this.filePath = filePath; - this.lastId = 0; - } - - public void load() { - try { - List lines = Files.readAllLines(Path.of(filePath)); - for (String line : lines.subList(1, lines.size())) { - String[] parts = line.split(","); - switch (parts[1]) { - case "TASK": - Task task = Task.fromString(line); - if (!tasks.containsKey(task.getId())) { - tasks.put(task.getId(), task); - lastId = Math.max(lastId, task.getId()); - } - break; - case "EPIC": - EpicTask epic = EpicTask.fromString(line); - if (!epicTasks.containsKey(epic.getId())) { - epicTasks.put(epic.getId(), epic); - lastId = Math.max(lastId, epic.getId()); - } - break; - case "SUB": - Subtask subtask = Subtask.fromString(line); - if (!subTasks.containsKey(subtask.epicId)) { - subTasks.put(subtask.epicId, new ArrayList<>()); - } - ArrayList epicSubtasks = subTasks.get(subtask.epicId); - if (!epicSubtasks.contains(subtask)) { - epicSubtasks.add(subtask); - lastId = Math.max(lastId, subtask.getId()); - } - // Добавляем подзадачу в соответствующий эпик - if (epicTasks.containsKey(subtask.epicId)) { - EpicTask associatedEpic = epicTasks.get(subtask.epicId); - associatedEpic.addSubtask(subtask); // Связываем подзадачу с эпиком - } - break; - default: - throw new IllegalArgumentException("Неизвестный тип задачи: " + parts[1]); - } - } - } catch (IOException e) { - throw new ManagerSaveException("Ошибка при загрузке данных из файла: " + filePath, e); - } - } +public class FileBackedTaskManager extends InMemoryTaskManager { + private final File file; - public static FileBackedTaskManager loadFromFile(File file) { - FileBackedTaskManager manager = new FileBackedTaskManager(new HashMap<>(), new HashMap<>(), new HashMap<>(), file.getPath()); - manager.load(); - return manager; + public FileBackedTaskManager(HistoryManager historyManager, String path) { + super(historyManager); + this.file = new File(path); } - private void save() { - StringBuilder csvData = new StringBuilder(); - csvData.append("id,type,name,status,description,epic\n"); - - for (Task task : super.getAllTasks()) { - csvData.append(task.toString()).append("\n"); - } - - for (EpicTask epic : super.getAllEpicTasks()) { - csvData.append(epic.toString()).append("\n"); - } - - for (Subtask subtask : super.getAllSubTasks()) { - csvData.append(subtask.toString()).append("\n"); - } + @Override + public Task addTask(Task task) { + super.addTask(task); + save(); + return task; + } - try (FileWriter writer = new FileWriter(filePath)) { - writer.write(csvData.toString()); - } catch (IOException e) { - e.printStackTrace(); - } + @Override + public Subtask addSubtask(Subtask subtask) { + super.addSubtask(subtask); + save(); + return subtask; } @Override - public Task createTask(Task task) { - if (lastId == 0) { - lastId = 1; - } else { - lastId++; - } - Task createdTask = super.createTask(task); - createdTask.setId(lastId); + public EpicTask addEpic(EpicTask epic) { + super.addEpic(epic); save(); - return createdTask; + return epic; } @Override - public EpicTask createEpicTask(EpicTask epicTask) { - if (lastId == 0) { - lastId = 1; - } else { - lastId++; + public Task getTaskById(int id) { + Task foundTask = super.getTaskById(id); + if (foundTask != null) { + save(); } - EpicTask createdEpic = super.createEpicTask(epicTask); - createdEpic.setId(lastId); - save(); - return createdEpic; + return foundTask; } @Override - public Subtask createSubTask(Subtask subtask) { - if (lastId == 0) { - lastId = 1; - } else { - lastId++; + public Subtask getSubtaskById(int id) { + Subtask foundSubtask = super.getSubtaskById(id); + if (foundSubtask != null) { + save(); } - Subtask createdSubtask = super.createSubTask(subtask); - createdSubtask.setId(lastId); - save(); - return createdSubtask; + return foundSubtask; } @Override - public boolean removeTaskById(int id) { - boolean removed = super.removeTaskById(id); - if (removed) { + public EpicTask getEpicById(int id) { + EpicTask foundEpic = super.getEpicById(id); + if (foundEpic != null) { save(); } - return removed; + return foundEpic; } @Override - public void removeAllTasks() { - super.removeAllTasks(); - lastId = 0; + public void updateTask(Task task) { + super.updateTask(task); save(); } @Override - public void removeAllEpicTasks() { - super.removeAllEpicTasks(); - lastId = 0; + public void updateSubtask(Subtask subtask) { + super.updateSubtask(subtask); save(); } @Override - public void removeAllSubTasks() { - super.removeAllSubTasks(); - lastId = 0; + public void updateEpic(EpicTask epic) { + super.updateEpic(epic); save(); } @Override - public void updateTask(int id, int comm, String change) { - super.updateTask(id, comm, change); + public void deleteTaskById(int id) { + super.deleteTaskById(id); save(); } @Override - public Task getTaskById(int id) { - String taskData = getTaskByIdFromFile(id); - if (taskData.startsWith("Задача с ID")) { - System.out.println(taskData); - return null; - } - Task task = Task.fromString(taskData); - historyManager.add(task); - return task; + public void deleteSubtaskById(int id) { + super.deleteSubtaskById(id); + save(); } @Override - public EpicTask getEpicTaskById(int id) { - String epicData = getTaskByIdFromFile(id); - if (epicData.startsWith("Задача с ID")) { - System.out.println(epicData); - return null; + public void deleteEpicById(int id) { + super.deleteEpicById(id); + save(); + } + + public void save() { + try (Writer writer = new FileWriter(file)) { + writer.write("id,type,title,status,description,startTime,duration,epic\n"); // Заголовок для файла + HashMap allTasks = new HashMap<>(); + + HashMap tasks = super.getTasks(); + for (Integer id : tasks.keySet()) { + allTasks.put(id, tasks.get(id).toString()); + } + + HashMap epics = super.getEpics(); + for (Integer id : epics.keySet()) { + allTasks.put(id, epics.get(id).toString()); + } + + HashMap subtasks = super.getSubtasks(); + for (Integer id : subtasks.keySet()) { + allTasks.put(id, subtasks.get(id).toString()); + } + + for (String value : allTasks.values()) { + writer.write(String.format("%s\n", value)); // Запись задач в файл + } + + writer.write("history\n"); // Добавлено для обозначения начала истории + for (Task task : super.getHistory()) { + writer.write(task.getId() + ","); + } + writer.write("\n"); // Добавлен символ новой строки в конце истории + + } catch (IOException exception) { + throw new ManagerSaveException("Не удалось записать файл"); } - EpicTask epic = EpicTask.fromString(epicData); - historyManager.add(epic); - return epic; } - @Override - public Subtask getSubTaskById(int id) { - String subtaskData = getTaskByIdFromFile(id); - if (subtaskData.startsWith("Задача с ID")) { - System.out.println(subtaskData); - return null; + private static Task fromString(String content) { + String[] elements = content.split(","); + int id = Integer.parseInt(elements[0]); + Type type = Type.valueOf(elements[1]); + String title = elements[2]; + Status status = Status.valueOf(elements[3]); + String description = elements[4]; + + // Преобразуем строку в LocalDateTime + LocalDateTime startTime = LocalDateTime.parse(elements[5]); + // Преобразуем строку в Duration + Duration duration = Duration.ofMillis(Long.parseLong(elements[6])); + int epicId = (elements.length == 8) ? Integer.parseInt(elements[7]) : 0; + + switch (type) { + case TASK: + return new Task(title, description, id, duration, startTime); + case SUB: + return new Subtask(title, description, id, epicId, duration, startTime); + case EPIC: + return new EpicTask(title, description, id); // Учитываем, что EpicTask требует только заголовок, описание и id + default: + throw new IllegalArgumentException("Неизвестный тип: " + type); } - Subtask subtask = Subtask.fromString(subtaskData); - historyManager.add(subtask); - return subtask; } - public String getTaskByIdFromFile(int id) { - try { - List lines = Files.readAllLines(Path.of(filePath)); - for (String line : lines.subList(1, lines.size())) { - String[] parts = line.split(","); - int taskId = Integer.parseInt(parts[0]); - if (taskId == id) { - return line; - } + private static List historyFromString(String value) { + List tasksIds = new ArrayList<>(); + if (value != null && !value.isEmpty()) { + String[] idsString = value.split(","); + for (String idString : idsString) { + tasksIds.add(Integer.valueOf(idString)); } - } catch (IOException e) { - throw new ManagerSaveException("Ошибка при загрузке данных из файла: " + filePath, e); - } catch (NumberFormatException e) { - return "Ошибка формата ID задачи в строке: " + e.getMessage(); } - - return "Задача с ID " + id + " не найдена."; + return tasksIds; } - public String getTaskTypeById(int id) { - try { - List lines = Files.readAllLines(Path.of(filePath)); - for (String line : lines.subList(1, lines.size())) { - String[] parts = line.split(","); - int taskId = Integer.parseInt(parts[0]); - if (taskId == id) { - return parts[1]; // Предполагается, что тип задачи находится во втором элементе + public void loadFromFile() { + try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) { + String line; + while ((line = bufferedReader.readLine()) != null) { + if (line.isEmpty() || line.contains("id")) { + continue; // Пропускаем пустые строки и заголовок + } + + Task task = fromString(line); + if (task instanceof EpicTask) { + super.addEpic((EpicTask) task); + } else if (task instanceof Subtask) { + super.addSubtask((Subtask) task); + } else { + addTask(task); } } - } catch (IOException e) { - throw new ManagerSaveException("Ошибка при загрузке данных из файла: " + filePath, e); - } catch (NumberFormatException e) { - return "Ошибка формата ID задачи в строке: " + e.getMessage(); - } - return null; // Задача не найдена + // Чтение истории + String lineWithHistory = bufferedReader.readLine(); + if (lineWithHistory != null) { + for (int id : historyFromString(lineWithHistory)) { + if (super.getTasks().containsKey(id)) { + historyManager.add(super.getTaskById(id)); + } else if (super.getSubtasks().containsKey(id)) { + historyManager.add(super.getSubtaskById(id)); + } else if (super.getEpics().containsKey(id)) { + historyManager.add(super.getEpicById(id)); + } + } + } + } catch (IOException exception) { + throw new ManagerSaveException("Не удалось прочитать файл"); + } } -} \ No newline at end of file +} + diff --git a/src/tracker/HistoryManager.java b/src/tracker/HistoryManager.java index 266b655..8c722db 100644 --- a/src/tracker/HistoryManager.java +++ b/src/tracker/HistoryManager.java @@ -1,14 +1,12 @@ package tracker; -import java.util.ArrayList; +import java.util.List; public interface HistoryManager { - void add(Task task); + Task add(Task task); - ArrayList getHistory(); + List getHistory(); void remove(int id); - - void clear(); } \ No newline at end of file diff --git a/src/tracker/HttpTaskManager.java b/src/tracker/HttpTaskManager.java new file mode 100644 index 0000000..bece04f --- /dev/null +++ b/src/tracker/HttpTaskManager.java @@ -0,0 +1,140 @@ +package tracker; + +import com.google.gson.*; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +public class HttpTaskManager extends FileBackedTaskManager { + private final KVTaskClient taskClient; + private static final Gson gson = new Gson(); + + public HttpTaskManager(HistoryManager historyManager, String url, KVTaskClient taskClient) { + super(historyManager, url); + this.taskClient = taskClient; + } + + @Override + public void save() { + taskClient.put("task", gson.toJson(tasks.values())); + taskClient.put("subtask", gson.toJson(subtasks.values())); + taskClient.put("epic", gson.toJson(epics.values())); + taskClient.put("tasks", gson.toJson(getPrioritizedTasks())); + List historyIds = getHistory() + .stream() + .map(Task::getId) + .collect(Collectors.toList()); + taskClient.put("history", gson.toJson(historyIds)); + } + + public void loadFromServer() { + loadTasks("task"); + loadTasks("subtask"); + loadTasks("epic"); + loadHistory(); + } + + private void loadTasks(String key) { + JsonElement jsonElement = JsonParser.parseString(taskClient.load(key)); + JsonArray jsonTasksArray = jsonElement.getAsJsonArray(); + for (JsonElement element : jsonTasksArray) { + Task task; + EpicTask epic; + Subtask subtask; + switch (key) { + case "task": + task = gson.fromJson(element.getAsJsonObject(), Task.class); + if (task.getStartTime() == null) { + task.setStartTime(LocalDateTime.now()); + } + if (task.getDuration() == null) { + task.setDuration(Duration.ZERO); + } + tasks.put(task.getId(), task); + addTaskToPrioritizedList(task); + break; + + case "subtask": + subtask = gson.fromJson(element.getAsJsonObject(), Subtask.class); + if (subtask.getStartTime() == null) { + subtask.setStartTime(LocalDateTime.now()); + } + if (subtask.getDuration() == null) { + subtask.setDuration(Duration.ZERO); + } + subtasks.put(subtask.getId(), subtask); + addTaskToPrioritizedList(subtask); + break; + + case "epic": + epic = gson.fromJson(element.getAsJsonObject(), EpicTask.class); + if (epic.getStartTime() == null) { + epic.setStartTime(LocalDateTime.now()); + } + if (epic.getDuration() == null) { + epic.setDuration(Duration.ZERO); + } + epics.put(epic.getId(), epic); + addTaskToPrioritizedList(epic); + break; + + default: + System.out.println("Не удалось загрузить задачи"); + return; + } + } + } + + private void loadHistory() { + JsonElement jsonElement = JsonParser.parseString(taskClient.load("history")); + JsonArray jsonHistoryArray = jsonElement.getAsJsonArray(); + for (JsonElement element : jsonHistoryArray) { + int id = element.getAsInt(); + if (tasks.containsKey(id)) { + historyManager.add(tasks.get(id)); + } else if (epics.containsKey(id)) { + historyManager.add(epics.get(id)); + } else if (subtasks.containsKey(id)) { + historyManager.add(subtasks.get(id)); + } + } + } + + // Метод для получения всех задач + public List getAllTasks() { + return tasks.values().stream().collect(Collectors.toList()); + } + + // Метод для удаления задачи по идентификатору + public boolean removeTaskById(int id) { + if (tasks.containsKey(id)) { + tasks.remove(id); + return true; + } + return false; + } + + // Метод для удаления всех задач + public void removeAllTasks() { + tasks.clear(); + } + + // Метод для обновления описания задачи + public void updateTaskDescription(int id, String newDescription) { + Task task = tasks.get(id); + if (task != null) { + task.setDescription(newDescription); + } + } + + // Метод для обновления названия задачи + public void updateTaskName(int id, String newHeading) { + Task task = tasks.get(id); + if (task != null) { + task.setHeading(newHeading); + } + } +} + diff --git a/src/tracker/HttpTaskServer.java b/src/tracker/HttpTaskServer.java new file mode 100644 index 0000000..f78056f --- /dev/null +++ b/src/tracker/HttpTaskServer.java @@ -0,0 +1,266 @@ +package tracker; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.stream.Collectors; + +public class HttpTaskServer { + public static final int PORT = 8080; + private static final Gson gson = new Gson(); + private final HttpServer server; + + public HttpTaskServer(Manager manager) throws IOException { + server = HttpServer.create(new InetSocketAddress("localhost", PORT), 0); + server.createContext("/tasks", new Handler(manager)); + } + + public void start() { + System.out.println("Запуск сервера на порту " + PORT); + server.start(); + } + + public void stop() { + server.stop(1); + } + + private static class Handler implements HttpHandler { + private final Manager manager; + + public Handler(Manager manager) { + this.manager = manager; + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + String requestMethod = exchange.getRequestMethod(); + String url = exchange.getRequestURI().toString(); + String[] urlParts = url.split("/"); + + Endpoint endpoint = getEndpoint(requestMethod, url); + + switch (endpoint) { + case GET_TASKS: + handleGetTasks(exchange, urlParts[2]); + break; + case GET_PRIORITIZED: + handleGetPrioritized(exchange); + break; + case GET_HISTORY: + handleGetHistory(exchange); + break; + case GET_BY_ID: + handleGetById(exchange, urlParts); + break; + case DELETE_TASKS: + handleDeleteTasks(exchange, urlParts[2]); + break; + case DELETE_BY_ID: + handleDeleteById(exchange, urlParts); + break; + case POST_TASK: + handlePostTask(exchange); + break; + default: + writeResponse(exchange, "Некорректный запрос", 404); + } + } + + private Endpoint getEndpoint(String requestMethod, String url) { + String[] urlParts = url.split("/"); + if (requestMethod.equals("GET")) { + switch (url) { + case "/tasks/": + return Endpoint.GET_PRIORITIZED; + case "/tasks/history/": + return Endpoint.GET_HISTORY; + case "/tasks/task/": + case "/tasks/subtask/": + case "/tasks/epic/": + return Endpoint.GET_TASKS; + } + if (urlParts[urlParts.length - 1].startsWith("?id")) { + return Endpoint.GET_BY_ID; + } + } + if (requestMethod.equals("DELETE")) { + switch (url) { + case "/tasks/task": + case "/tasks/subtask": + case "/tasks/epic": + return Endpoint.DELETE_TASKS; + } + if (urlParts[urlParts.length - 1].startsWith("?id")) { + return Endpoint.DELETE_BY_ID; + } + } + if (requestMethod.equals("POST") && urlParts[1].equals("tasks") && urlParts.length == 3) { + return Endpoint.POST_TASK; + } + return Endpoint.UNKNOWN; + } + + private Optional getTaskId(String[] urlParts) { + try { + return Optional.of(Integer.parseInt(urlParts[urlParts.length - 1].split("=")[1])); + } catch (NumberFormatException exception) { + return Optional.empty(); + } + } + + private void handleGetTasks(HttpExchange exchange, String type) throws IOException { + switch (type) { + case "task": + writeResponse(exchange, gson.toJson(manager.getTasks()), 200); + return; + case "subtask": + writeResponse(exchange, gson.toJson(manager.getSubtasks()), 200); + return; + case "epic": + writeResponse(exchange, gson.toJson(manager.getEpics()), 200); + return; + } + writeResponse(exchange, "Некорректный запрос", 400); + } + + private void handleGetPrioritized(HttpExchange exchange) throws IOException { + Collection prioritized = manager.getPrioritizedTasks(); + if (prioritized.isEmpty()) { + writeResponse(exchange, "Список приоритетных задач пуст", 404); + return; + } + writeResponse(exchange, gson.toJson(prioritized), 200); + } + + private void handleGetById(HttpExchange exchange, String[] urlParts) throws IOException { + Optional optionalId = getTaskId(urlParts); + if (optionalId.isEmpty()) { + writeResponse(exchange, "Некорректный идентификатор задачи", 400); + return; + } + int id = optionalId.get(); + if (urlParts.length == 4 && urlParts[2].equals("task")) { + try { + writeResponse(exchange, gson.toJson(manager.getTaskById(id)), 200); + } catch (NoSuchElementException e) { + writeResponse(exchange, e.getMessage(), 404); + } + } else if (urlParts.length == 5 && urlParts[2].equals("subtask") && urlParts[3].equals("epic")) { + try { + writeResponse(exchange, gson.toJson(manager.getSubtasksOfEpic(id)), 200); + } catch (NoSuchElementException e) { + writeResponse(exchange, e.getMessage(), 404); + } + } else { + writeResponse(exchange, "Некорректный запрос", 400); + } + } + + private void handlePostTask(HttpExchange exchange) throws IOException { + try { + InputStream inputStream = exchange.getRequestBody(); + String body = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + Task task; + Subtask subtask; + EpicTask epic; + switch (exchange.getRequestURI().getPath()) { + case "/tasks/task/": + task = gson.fromJson(body, Task.class); + manager.addTask(task); + writeResponse(exchange, "Задача была создана", 201); + break; + case "/tasks/epic/": + epic = gson.fromJson(body, EpicTask.class); + manager.addEpic(epic); + writeResponse(exchange, "Эпическая задача была создана", 201); + break; + case "/tasks/subtask/": + subtask = gson.fromJson(body, Subtask.class); + manager.addSubtask(subtask); + writeResponse(exchange, "Подзадача была создана", 201); + break; + default: + writeResponse(exchange, "Некорректный запрос", 400); + break; + } + } catch (JsonSyntaxException e) { + writeResponse(exchange, "Некорректный JSON", 400); + } + } + + private void handleDeleteTasks(HttpExchange exchange, String type) throws IOException { + switch (type) { + case "task": + manager.deleteTasks(); + writeResponse(exchange, "Все задачи были удалены", 200); + return; + case "epic": + manager.deleteEpics(); + writeResponse(exchange, "Все эпические задачи были удалены", 200); + return; + case "subtask": + manager.deleteSubtasks(); + writeResponse(exchange, "Все подзадачи были удалены", 200); + return; + } + writeResponse(exchange, "Некорректный запрос", 400); + } + + private void handleDeleteById(HttpExchange exchange, String[] urlParts) throws IOException { + Optional optionalId = getTaskId(urlParts); + if (optionalId.isEmpty()) { + writeResponse(exchange, "Некорректный идентификатор задачи", 400); + return; + } + int id = optionalId.get(); + if (urlParts[2].equals("task")) { + try { + manager.deleteTaskById(id); + writeResponse(exchange, "Задача была удалена", 200); + } catch (NoSuchElementException e) { + writeResponse(exchange, e.getMessage(), 404); + } + } else { + writeResponse(exchange, "Некорректный запрос", 400); + } + } + + private void handleGetHistory(HttpExchange exchange) throws IOException { + Collection history = manager.getHistory(); + if (history.isEmpty()) { + writeResponse(exchange, "Список истории пуст", 404); + return; + } + List historyIds = history + .stream() + .map(Task::getId) + .collect(Collectors.toList()); + writeResponse(exchange, gson.toJson(historyIds), 200); + } + + private void writeResponse(HttpExchange exchange, String response, int code) throws IOException { + if (response.isBlank()) { + exchange.sendResponseHeaders(code, 0); + } else { + byte[] bytes = response.getBytes(StandardCharsets.UTF_8); + exchange.sendResponseHeaders(code, bytes.length); + try (OutputStream os = exchange.getResponseBody()) { + os.write(bytes); + } + } + exchange.close(); + } + } +} diff --git a/src/tracker/InMemoryHistoryManager.java b/src/tracker/InMemoryHistoryManager.java index 1e3fc4d..914cd17 100644 --- a/src/tracker/InMemoryHistoryManager.java +++ b/src/tracker/InMemoryHistoryManager.java @@ -1,94 +1,82 @@ package tracker; -import java.util.ArrayList; import java.util.HashMap; - +import java.util.LinkedList; +import java.util.List; +import java.util.Map; public class InMemoryHistoryManager implements HistoryManager { - private final HashMap tasksById; - private Node head; - private Node tail; + private final Map> receivedTasksMap; + private Node head; + private Node tail; public InMemoryHistoryManager() { - tasksById = new HashMap<>(); - head = null; - tail = null; + receivedTasksMap = new HashMap<>(); } @Override - public void add(Task task) { - if (tasksById.containsKey(task.getId())) { - remove(task.getId()); + public Task add(Task task) { + if (task != null) { + linkLast(task); } - - Node newNode = new Node(task); - linkLast(newNode); - tasksById.put(task.getId(), newNode); + return task; } + @Override public void remove(int id) { - if (tasksById.containsKey(id)) { - removeNode(tasksById.get(id)); - tasksById.remove(id); - } + removeNode(receivedTasksMap.get(id)); } - public void clear() { - tasksById.clear(); - head = null; - tail = null; + @Override + public List getHistory() { + return getTasks(); } - private void linkLast(Node node) { - if (head == null) { - head = node; - tail = node; - } else { - tail.next = node; - node.prev = tail; - tail = node; + private void linkLast(Task task) { + if (receivedTasksMap.containsKey(task.getId())) { + removeNode(receivedTasksMap.get(task.getId())); } - } - - private void removeNode(Node node) { - if (node == head && node == tail) { - head = null; - tail = null; - } else if (node == head) { - head = node.next; - if (head != null) { - head.prev = null; - } - } else if (node == tail) { - tail = node.prev; - if (tail != null) { - tail.next = null; - } + final Node oldTail = tail; + final Node newNode = new Node<>(task, tail, null); + tail = newNode; + receivedTasksMap.put(task.getId(), newNode); + if (oldTail == null) { + head = newNode; } else { - node.prev.next = node.next; - node.next.prev = node.prev; + oldTail.setNext(newNode); } } - public ArrayList getHistory() { - ArrayList history = new ArrayList<>(); - Node current = head; - while (current != null) { - history.add(current.task); - current = current.next; + private List getTasks() { + List tasks = new LinkedList<>(); + Node currentNode = head; + while (currentNode != null) { + tasks.add(currentNode.getData()); + currentNode = currentNode.getNext(); } - return history; + return tasks; } - private static class Node { - Task task; - Node prev; - Node next; + private void removeNode(Node node) { + if (node != null) { + final Node next = node.getNext(); + final Node previous = node.getPrevious(); + node.setData(null); - public Node(Task task) { - this.task = task; - this.prev = null; - this.next = null; + if (head == node && tail == node) { + head = null; + tail = null; + } else if (head == node && tail != node) { + head = next; + head.setPrevious(null); + } else if (head != node && tail == node) { + tail = previous; + tail.setNext(null); + } else { + previous.setNext(next); + next.setPrevious(previous); + } } } + } diff --git a/src/tracker/InMemoryTaskManager.java b/src/tracker/InMemoryTaskManager.java index afeebcf..c0235ce 100644 --- a/src/tracker/InMemoryTaskManager.java +++ b/src/tracker/InMemoryTaskManager.java @@ -1,321 +1,357 @@ package tracker; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.*; -import java.util.stream.Collectors; - -public class InMemoryTaskManager implements TaskManager { - protected final HashMap tasks; - protected final HashMap epicTasks; - protected final HashMap> subTasks; - protected final Map taskIndexMap = new HashMap<>(); - HistoryManager historyManager = Managers.getDefaultHistory(); - - int id = 0; - String type = ""; - - public InMemoryTaskManager(HashMap tasks, HashMap epicTasks, HashMap> subTasks) { - this.tasks = tasks; - this.epicTasks = epicTasks; - this.subTasks = subTasks; + +public class InMemoryTaskManager implements Manager { + protected int id; + protected HashMap tasks = new HashMap<>(); + protected HashMap subtasks = new HashMap<>(); + protected HashMap epics = new HashMap<>(); + protected HistoryManager historyManager; + private final Comparator comparator = Comparator.comparing(Task::getStartTime); + private final Set prioritizedTasks = new TreeSet<>(comparator); + + public InMemoryTaskManager() { + id = 0; + historyManager = Managers.getDefaultHistory(); } - @Override - public List getAllTasks() { - return new ArrayList<>(tasks.values()); + public InMemoryTaskManager(HistoryManager historyManager) { + this.historyManager = historyManager; } - @Override - public ArrayList getAllEpicTasks() { - return new ArrayList<>(epicTasks.values()); + private int idIncrease() { + return ++id; } @Override - public List getAllSubTasks() { - return subTasks.values().stream() - .flatMap(Collection::stream) - .collect(Collectors.toList()); + public Task addTask(Task task) { + if (task != null && !tasks.containsKey(task.getId())) { + if (task.getStartTime() == null || task.getDuration() == null) { + throw new IllegalArgumentException("Время начала задачи и продолжительность не могут быть null"); + } + int newId = task.getId(); + if (newId == 0) { + newId = idIncrease(); + task.setId(newId); + } + tasks.put(newId, task); + addTaskToPrioritizedList(task); + } else { + return null; + } + return task; } + @Override + public Task getTaskById(int id) { + Task task = tasks.get(id); + if (task != null && tasks.containsKey(id)) { + historyManager.add(task); + } else { + return null; + } + return task; + } @Override - public void removeAllTasks() { + public void deleteTasks() { tasks.clear(); - taskIndexMap.clear(); - historyManager.clear(); + prioritizedTasks.clear(); } @Override - public void removeAllEpicTasks() { - HashSet epicIds = new HashSet<>(epicTasks.keySet()); - - for (Integer epicId : epicIds) { - subTasks.remove(epicId); + public HashMap getTasks() { + if (tasks.size() != 0) { + return tasks; + } else { + return new HashMap<>(); } - - epicTasks.clear(); } @Override - public void removeAllSubTasks() { - subTasks.clear(); - - for (EpicTask epic : epicTasks.values()) { - if (epic.getSubtasks().isEmpty()) { - epic.setStatus(Status.NEW); - } + public void updateTask(Task task) { + if (task != null && tasks.containsKey(task.getId())) { + tasks.put(task.getId(), task); + addTaskToPrioritizedList(task); } } @Override - public Task getTaskById(int id) { - historyManager.add(tasks.get(id)); - return tasks.get(id); + public void deleteTaskById(int id) { + if (tasks.containsKey(id)) { + tasks.remove(id); + historyManager.remove(id); + prioritizedTasks.removeIf(task -> task.getId() == id); + } } @Override - public EpicTask getEpicTaskById(int id) { - historyManager.add(epicTasks.get(id)); - return epicTasks.get(id); + public EpicTask addEpic(EpicTask epic) { + if (epic != null && !epics.containsKey(epic.getId())) { + int newId = epic.getId(); + if (newId == 0) { + newId = idIncrease(); + epic.setId(newId); + } + epics.put(newId, epic); + } else { + return null; + } + return epic; } @Override - public Subtask getSubTaskById(int id) { - return subTasks.values().stream() - .flatMap(List::stream) - .filter(subtask -> subtask.getId() == id) - .peek(historyManager::add) - .findFirst() - .orElse(null); + public EpicTask getEpicById(int id) { + EpicTask epic = epics.get(id); + if (epic != null && epics.containsKey(id)) { + historyManager.add(epic); + } else { + return null; + } + return epic; } + @Override + public void deleteEpics() { + epics.clear(); + subtasks.clear(); + } - public int getTaskIndex(String heading, String description, String type) { - String taskKey = heading + " " + description + " " + type; - if (taskIndexMap.containsKey(taskKey)) { - return taskIndexMap.get(taskKey); + @Override + public HashMap getEpics() { + if (epics.size() != 0) { + return epics; } else { - return -1; + return new HashMap<>(); } } @Override - public Task createTask(Task task) { - boolean isOverlapping = tasks.values().stream() - .filter(existingTask -> existingTask.getStartTime() != null) - .anyMatch(existingTask -> task.isOverlapping(existingTask)); - - if (isOverlapping) { - throw new IllegalArgumentException("Задача пересекается с существующей задачей."); + public void updateEpic(EpicTask epic) { + if (epic != null && epics.containsKey(epic.getId())) { + epics.put(epic.getId(), epic); + statusUpdate(epic); + updateEpicTime(epic); } - - type = "task"; - task.setId(++id); - tasks.put(id, task); - taskIndexMap.put(task.heading + " " + task.description + " " + type, id); - return task; } - @Override - public EpicTask createEpicTask(EpicTask epicTask) { - boolean isOverlapping = epicTasks.values().stream() - .filter(existingEpic -> existingEpic.getStartTime() != null) - .anyMatch(existingEpic -> epicTask.isOverlapping(existingEpic)); - - if (isOverlapping) { - throw new IllegalArgumentException("Эпическая задача пересекается с существующей эпической задачей."); + public void deleteEpicById(int id) { + if (epics.containsKey(id)) { + EpicTask epic = epics.get(id); + for (Integer subtaskId : epic.getSubtasksIds()) { + historyManager.remove(id); + subtasks.remove(subtaskId); + prioritizedTasks.removeIf(task -> Objects.equals(task.getId(), subtaskId)); + } + epics.remove(id); + historyManager.remove(epic.getId()); } - - type = "epic task"; - epicTask.setId(++id); - epicTasks.put(id, epicTask); - taskIndexMap.put(epicTask.heading + " " + epicTask.description + " " + type, id); - return epicTask; } - @Override - public Subtask createSubTask(Subtask subtask) { - int epicId = subtask.epicId; - - if (!epicTasks.containsKey(epicId)) { + public Subtask addSubtask(Subtask subtask) { + if (subtask != null && !subtasks.containsKey(subtask.getId())) { + int newId = subtask.getId(); + if (newId == 0) { + newId = idIncrease(); + subtask.setId(newId); + } + EpicTask epic = epics.get(subtask.epicId); + if (epic != null) { + addTaskToPrioritizedList(subtask); + subtasks.put(newId, subtask); + epic.setSubtasksIds(newId); + statusUpdate(epic); + updateEpicTime(epic); + } else { + throw new IllegalArgumentException("Эпическая задача с id " + subtask.epicId + " не существует."); + } + } else { return null; } + return subtask; + } - if (!subTasks.containsKey(epicId)) { - subTasks.put(epicId, new ArrayList<>()); + @Override + public Subtask getSubtaskById(int id) { + Subtask subtask = subtasks.get(id); + if (subtask != null && subtasks.containsKey(id)) { + historyManager.add(subtask); + } else { + return null; } + return subtask; + } - boolean isOverlapping = subTasks.get(epicId).stream() - .filter(existingSubtask -> existingSubtask.getStartTime() != null) - .anyMatch(existingSubtask -> subtask.isOverlapping(existingSubtask)); - - if (isOverlapping) { - throw new IllegalArgumentException("Подзадача пересекается с существующей подзадачей."); + @Override + public void deleteSubtasks() { + for (EpicTask epic : epics.values()) { + for (Integer subtaskId : epic.getSubtasksIds()) { + subtasks.remove(subtaskId); + historyManager.remove(subtaskId); + Subtask subtask = subtasks.get(subtaskId); + prioritizedTasks.remove(subtask); + } + epic.getSubtasksIds().clear(); } + } - type = "subtask"; - subtask.setId(++id); - subTasks.get(epicId).add(subtask); - epicTasks.get(epicId).addSubtask(subtask); - taskIndexMap.put(subtask.heading + " " + subtask.description + " " + type, id); - return subtask; + @Override + public HashMap getSubtasks() { + if (subtasks.size() != 0) { + return subtasks; + } else { + return new HashMap<>(); + } } + @Override + public void updateSubtask(Subtask subtask) { + if (subtask != null && subtasks.containsKey(subtask.getId())) { + EpicTask epic = getEpicById(subtask.getId()); + subtasks.put(subtask.getId(), subtask); + statusUpdate(epic); + addTaskToPrioritizedList(subtask); + updateEpicTime(epic); + } + } @Override - public void updateTask(int id, int comm, String change) { - if (tasks.containsKey(id)) { - if (comm == 1) { - tasks.get(id).setHeading(change); - } else if (comm == 2) { - tasks.get(id).setDescription(change); - } - } else if (epicTasks.containsKey(id)) { - if (comm == 1) { - epicTasks.get(id).setHeading(change); - } else if (comm == 2) { - epicTasks.get(id).setDescription(change); - } + public void deleteSubtaskById(int id) { + if (subtasks.containsKey(id)) { + Subtask subtask = subtasks.remove(id); + EpicTask epic = epics.get(subtask.epicId); + subtasks.remove(id); + epic.getSubtasksIds().remove(id); + historyManager.remove(id); + statusUpdate(epic); + updateEpicTime(epic); + prioritizedTasks.remove(subtask); } } - public List getSubtasks(int id) { - return epicTasks.containsKey(id) ? - epicTasks.get(id).getSubtasks() : - Collections.emptyList(); + @Override + public List getHistory() { + return historyManager.getHistory(); } + @Override + public List getPrioritizedTasks() { + return new ArrayList<>(prioritizedTasks); + } @Override - public boolean removeTaskById(int id) { - if (tasks.containsKey(id)) { - String taskKey = tasks.get(id).heading + " " + tasks.get(id).description; - taskIndexMap.remove(taskKey); - tasks.remove(id); - historyManager.remove(id); - return true; - } else if (epicTasks.containsKey(id)) { - String taskKey = epicTasks.get(id).heading + " " + epicTasks.get(id).description; - taskIndexMap.remove(taskKey); - epicTasks.remove(id); - if (!subTasks.isEmpty() && subTasks.containsKey(id)) { - for (Subtask subtask : subTasks.get(id)) { - historyManager.remove(subtask.getId()); - } - } - subTasks.remove(id); - historyManager.remove(id); - return true; - } else if (!subTasks.isEmpty()) { - for (List subtasks : subTasks.values()) { - for (Subtask subtask : subtasks) { - if (subtask.getId() == id) { - subtasks.remove(subtask); - historyManager.remove(id); - return true; - } - } + public List getSubtasksOfEpic(int id) { + if (epics.containsKey(id)) { + EpicTask epic = epics.get(id); + List newSubtasks = new ArrayList<>(); + for (int i = 0; i < epic.getSubtasksIds().size(); i++) { + newSubtasks.add(subtasks.get(epic.getSubtasksIds().get(i))); } + return newSubtasks; + } else { + return new ArrayList<>(); } - return false; } - public Status checkStatus(int id, int status) { - if (tasks.containsKey(id)) { - tasks.get(id).setStatus(status == 1 ? Status.IN_PROGRESS : Status.DONE); - return tasks.get(id).status; + private void statusUpdate(EpicTask epic) { + boolean isNew = true; + boolean isDone = true; + + if (epic.getSubtasksIds().size() == 0) { + epic.setStatus(Status.NEW); + return; } - if (epicTasks.containsKey(id)) { - EpicTask epicTask = epicTasks.get(id); - if (epicTask.getSubtasks().isEmpty()) { - epicTask.setStatus(Status.NEW); - return epicTask.status; + for (Integer epicSubtask : epic.getSubtasksIds()) { + Status status = subtasks.get(epicSubtask).getStatus(); + if (status != Status.NEW) { + isNew = false; } - - boolean flag = false; - int newCount = 0; - int doneCount = 0; - for (Subtask subtask : epicTask.getSubtasks()) { - if (subtask.status == Status.IN_PROGRESS) { - flag = true; - break; - } else if (subtask.status == Status.NEW) { - newCount++; - } else if (subtask.status == Status.DONE) { - doneCount++; - } + if (status != Status.DONE) { + isDone = false; } + } - if (flag) { - epicTask.setStatus(Status.IN_PROGRESS); - } else if (newCount == epicTask.getSubtasks().size()) { - epicTask.setStatus(Status.NEW); - } else if (doneCount == epicTask.getSubtasks().size()) { - epicTask.setStatus(Status.DONE); - } else { - epicTask.setStatus(Status.IN_PROGRESS); - } - return epicTask.status; + if (isNew) { + epic.setStatus(Status.NEW); + } else if (isDone) { + epic.setStatus(Status.DONE); + } else { + epic.setStatus(Status.IN_PROGRESS); } + } - for (List subtaskList : subTasks.values()) { - for (Subtask subtask : subtaskList) { - if (subtask.getId() == id) { - subtask.setStatus(status == 1 ? Status.IN_PROGRESS : Status.DONE); - return subtask.status; - } - } + private void updateEpicTime(EpicTask epic) { + List subtasks = getSubtasksOfEpic(epic.getId()); + + if (subtasks.isEmpty()) { + // Если подзадач нет, устанавливаем время начала и окончания в null + epic.setStartTime(null); + epic.setDuration(Duration.ZERO); + return; } - return null; - } + LocalDateTime startTime = subtasks.get(0).getStartTime(); + LocalDateTime endTime = subtasks.get(0).getEndTime(); - public boolean checkTaskId(int id) { - if (tasks.containsKey(id)) { - return true; + for (Subtask subtask : subtasks) { + if (subtask.getStartTime().isBefore(startTime)) { + startTime = subtask.getStartTime(); + } + if (subtask.getEndTime().isAfter(endTime)) { + endTime = subtask.getEndTime(); + } } - return false; + + epic.setStartTime(startTime); + + // Вычисляем продолжительность + long durationMillis = Duration.between(startTime, endTime).toMillis(); + epic.setDuration(Duration.ofMillis(durationMillis)); } - public boolean checkEpicTaskId(int id) { - if (epicTasks.containsKey(id)) { - return true; + public void addTaskToPrioritizedList(Task task) { + if (task.getStartTime() == null) { + throw new IllegalArgumentException("Время начала задачи не может быть null"); + } + boolean isValidated = validation(task); + if (!isValidated) { + prioritizedTasks.add(task); + } else { + throw new TaskConflictException("Существует проблема, вызванная временем схожих задач"); } - return false; } - @Override - public ArrayList getHistory() { - return historyManager.getHistory(); - } + private boolean validation(Task task) { + if (task.getStartTime() == null || task.getDuration() == null) { + return false; // Нельзя валидировать задачу без времени начала или продолжительности + } - public TreeSet getPrioritizedTasks() { - TreeSet prioritizedTasks = new TreeSet<>(Comparator - .comparing(Task::getStartTime, Comparator.nullsLast(Comparator.naturalOrder())) - .thenComparing(Task::getId)); + boolean isOverlapping = false; + Instant startOfTask = task.getStartTime().atZone(ZoneId.systemDefault()).toInstant(); + Instant endOfTask = startOfTask.plus(task.getDuration()); - for (Task task : tasks.values()) { - if (task.getStartTime() != null) { - prioritizedTasks.add(task); + for (Task taskValue : prioritizedTasks) { + if (taskValue.getStartTime() == null || taskValue.getDuration() == null) { + continue; // Пропускаем задачи без времени начала или продолжительности } - } - for (EpicTask epic : epicTasks.values()) { - if (epic.getStartTime() != null) { - prioritizedTasks.add(epic); - - for (Subtask subtask : epic.getSubtasks()) { - if (subtask.getStartTime() != null) { - prioritizedTasks.add(subtask); - } else { - System.out.println("Подзадача с ID " + subtask.getId() + " имеет null startTime и не будет добавлена."); - } - } - } - } + Instant startTime = taskValue.getStartTime().atZone(ZoneId.systemDefault()).toInstant(); + Instant endTime = startTime.plus(taskValue.getDuration()); - return prioritizedTasks; + boolean isCovering = startTime.isBefore(startOfTask) && endTime.isAfter(endOfTask); + boolean isOverlappingByEnd = startTime.isBefore(startOfTask) && endTime.isAfter(startOfTask); + boolean isOverlappingByStart = startTime.isBefore(endOfTask) && endTime.isAfter(endOfTask); + boolean isWithin = startTime.isAfter(startOfTask) && endTime.isBefore(endOfTask); + isOverlapping = isCovering || isOverlappingByEnd || isOverlappingByStart || isWithin; + } + return isOverlapping; } } \ No newline at end of file diff --git a/src/tracker/KVServer.java b/src/tracker/KVServer.java new file mode 100644 index 0000000..090e544 --- /dev/null +++ b/src/tracker/KVServer.java @@ -0,0 +1,135 @@ +package tracker; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpServer; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.HashMap; +import java.util.Map; + +import static java.nio.charset.StandardCharsets.UTF_8; + +public class KVServer { + public static final int PORT = 8078; + private final String apiToken; + private final HttpServer server; + private final Map data = new HashMap<>(); + + public KVServer() throws IOException { + apiToken = newApiToken(); + server = HttpServer.create(new InetSocketAddress("localhost", PORT), 0); + server.createContext("/register", this::register); + server.createContext("/save", this::save); + server.createContext("/load", this::load); + } + + private void load(HttpExchange httpExchange) throws IOException { + try { + System.out.println("\n/load"); + if (!hasAuth(httpExchange)) { + System.out.println("Запрос без авторизации, параметр API_TOKEN необходим в запросе с значением API-ключа"); + httpExchange.sendResponseHeaders(403, 0); + return; + } + if ("GET".equals(httpExchange.getRequestMethod())) { + String key = httpExchange.getRequestURI().getPath().substring("/load/".length()); + if (key.isEmpty()) { + System.out.println("Ключ пуст, невозможно получить значение. Ключ должен быть указан: /load/{key}"); + httpExchange.sendResponseHeaders(400, 0); + return; + } + if (data.get(key) == null) { + System.out.println("Неотслеживаемое значение для " + key); + httpExchange.sendResponseHeaders(404, 0); + return; + } + sendText(httpExchange, data.get(key)); + httpExchange.sendResponseHeaders(200, 0); + } else { + System.out.println("/load ожидает GET-запрос, но получил: " + httpExchange.getRequestMethod()); + httpExchange.sendResponseHeaders(405, 0); + } + } finally { + httpExchange.close(); + } + } + + private void save(HttpExchange httpExchange) throws IOException { + try { + System.out.println("\n/save"); + if (!hasAuth(httpExchange)) { + System.out.println("Запрос без авторизации, параметр API_TOKEN необходим в запросе с значением API-ключа"); + httpExchange.sendResponseHeaders(403, 0); + return; + } + if ("POST".equals(httpExchange.getRequestMethod())) { + String key = httpExchange.getRequestURI().getPath().substring("/save/".length()); + if (key.isEmpty()) { + System.out.println("Ключ пуст, невозможно получить значение. Ключ должен быть указан: /save/{key}"); + httpExchange.sendResponseHeaders(400, 0); + return; + } + String value = readText(httpExchange); + if (value.isEmpty()) { + System.out.println("Значение пусто, невозможно сохранить. Значение должно быть указано в теле запроса"); + httpExchange.sendResponseHeaders(400, 0); + return; + } + data.put(key, value); + System.out.println("Значение для ключа " + key + " было успешно обновлено"); + httpExchange.sendResponseHeaders(200, 0); + } else { + System.out.println("/save ожидает POST-запрос, но получил: " + httpExchange.getRequestMethod()); + httpExchange.sendResponseHeaders(405, 0); + } + } finally { + httpExchange.close(); + } + } + + private void register(HttpExchange httpExchange) throws IOException { + try { + System.out.println("\n/register"); + if ("GET".equals(httpExchange.getRequestMethod())) { + sendText(httpExchange, apiToken); + } else { + System.out.println("/register ожидает GET-запрос, но получил " + httpExchange.getRequestMethod()); + httpExchange.sendResponseHeaders(405, 0); + } + } finally { + httpExchange.close(); + } + } + + public void start() { + System.out.println("Запуск сервера на порту " + PORT); + System.out.println("Ссылка для браузера http://localhost:" + PORT + "/"); + System.out.println("API_TOKEN: " + apiToken); + server.start(); + } + + public void stop() { + server.stop(1); + } + + private String newApiToken() { + return "" + System.currentTimeMillis(); + } + + private boolean hasAuth(HttpExchange httpExchange) { + String rawQuery = httpExchange.getRequestURI().getRawQuery(); + return rawQuery != null && (rawQuery.contains("API_TOKEN=" + apiToken) || rawQuery.contains("API_TOKEN=DEBUG")); + } + + private String readText(HttpExchange httpExchange) throws IOException { + return new String(httpExchange.getRequestBody().readAllBytes(), UTF_8); + } + + private void sendText(HttpExchange httpExchange, String text) throws IOException { + byte[] resp = text.getBytes(UTF_8); + httpExchange.getResponseHeaders().add("Content-Type", "application/json"); + httpExchange.sendResponseHeaders(200, resp.length); + httpExchange.getResponseBody().write(resp); + } +} diff --git a/src/tracker/KVTaskClient.java b/src/tracker/KVTaskClient.java new file mode 100644 index 0000000..88a9fa1 --- /dev/null +++ b/src/tracker/KVTaskClient.java @@ -0,0 +1,70 @@ +package tracker; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +public class KVTaskClient { + private final String serverUrl; + private final String apiToken; + private HttpResponse response; + + public KVTaskClient(String serverUrl) { + this.serverUrl = serverUrl; + URI url = URI.create(serverUrl + "/register"); + HttpRequest request = HttpRequest.newBuilder() + .GET() + .uri(url) + .header("Accept", "application/json") + .build(); + HttpClient client = HttpClient.newHttpClient(); + try { + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + } catch (IOException | InterruptedException e) { + System.out.println("Произошла проблема\n" + + "Проверьте адрес и попробуйте снова"); + } + apiToken = response.body(); + } + + public void put(String key, String requestBody) { + URI uri = URI.create(serverUrl + "/save/" + key + "?API_TOKEN=" + apiToken); + HttpRequest request = HttpRequest.newBuilder() + .POST(HttpRequest.BodyPublishers.ofString(requestBody)) + .uri(uri) + .header("Accept", "application/json") + .build(); + HttpClient client = HttpClient.newHttpClient(); + try { + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() != 200) { + System.out.println("Что-то пошло не так. Код статуса: " + response.statusCode()); + } + } catch (IOException | InterruptedException e) { + System.out.println("Произошла проблема\n" + + "Проверьте адрес и попробуйте снова"); + } + } + + public String load(String key) { + URI uri = URI.create(serverUrl + "/load/" + key + "?API_TOKEN=" + apiToken); + HttpRequest request = HttpRequest.newBuilder() + .GET() + .uri(uri) + .header("Accept", "application/json") + .build(); + HttpClient client = HttpClient.newHttpClient(); + try { + response = client.send(request, HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() != 200) { + return "Что-то пошло не так. Код статуса: " + response.statusCode(); + } + return response.body(); + } catch (IOException | InterruptedException e) { + return "Произошла проблема\n" + + "Проверьте адрес и попробуйте снова"; + } + } +} diff --git a/src/tracker/Manager.java b/src/tracker/Manager.java new file mode 100644 index 0000000..d7364fc --- /dev/null +++ b/src/tracker/Manager.java @@ -0,0 +1,49 @@ +package tracker; + +import java.util.HashMap; +import java.util.List; + +public interface Manager { + + Task addTask(Task task); + + Task getTaskById(int id); + + void deleteTasks(); + + HashMap getTasks(); + + void updateTask(Task task); + + void deleteTaskById(int id); + + EpicTask addEpic(EpicTask epic); + + EpicTask getEpicById(int id); + + void deleteEpics(); + + HashMap getEpics(); + + void updateEpic(EpicTask epic); + + void deleteEpicById(int id); + + Subtask addSubtask(Subtask subtask); + + Subtask getSubtaskById(int id); + + void deleteSubtasks(); + + HashMap getSubtasks(); + + void updateSubtask(Subtask subtask); + + void deleteSubtaskById(int id); + + List getHistory(); + + List getPrioritizedTasks(); + + List getSubtasksOfEpic(int id); +} diff --git a/src/tracker/ManagerSaveException.java b/src/tracker/ManagerSaveException.java index 57eb017..ea8a76d 100644 --- a/src/tracker/ManagerSaveException.java +++ b/src/tracker/ManagerSaveException.java @@ -1,7 +1,8 @@ package tracker; public class ManagerSaveException extends RuntimeException { - public ManagerSaveException(String message, Throwable cause) { - super(message, cause); + public ManagerSaveException(final String message) { + super(message); } + } diff --git a/src/tracker/Managers.java b/src/tracker/Managers.java index 5b724cf..2a6e477 100644 --- a/src/tracker/Managers.java +++ b/src/tracker/Managers.java @@ -1,23 +1,17 @@ package tracker; -import java.util.HashMap; - public class Managers { - private static TaskManager taskManager; - private static InMemoryHistoryManager historyManager; + public static Manager getDefault() { + return new InMemoryTaskManager(getDefaultHistory()); + } - public static TaskManager getDefault() { - if (taskManager == null) { - taskManager = new InMemoryTaskManager(new HashMap<>(), new HashMap<>(), new HashMap<>()); - } - return taskManager; + public static HistoryManager getDefaultHistory() { + return new InMemoryHistoryManager(); } - public static InMemoryHistoryManager getDefaultHistory() { - if (historyManager == null) { - historyManager = new InMemoryHistoryManager(); - } - return historyManager; + public static Manager getDefault(String url) { + return new HttpTaskManager(getDefaultHistory(), url, new KVTaskClient(url)); } + } diff --git a/src/tracker/Node.java b/src/tracker/Node.java new file mode 100644 index 0000000..e128eaf --- /dev/null +++ b/src/tracker/Node.java @@ -0,0 +1,37 @@ +package tracker; + +public class Node { + private T data; + private Node previous; + private Node next; + + public Node(T data, Node previous, Node next) { + this.previous = previous; + this.data = data; + this.next = next; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + public Node getPrevious() { + return previous; + } + + public void setPrevious(Node previous) { + this.previous = previous; + } + + public Node getNext() { + return next; + } + + public void setNext(Node next) { + this.next = next; + } +} diff --git a/src/tracker/Status.java b/src/tracker/Status.java index 7990605..42598fa 100644 --- a/src/tracker/Status.java +++ b/src/tracker/Status.java @@ -2,4 +2,4 @@ public enum Status { NEW, IN_PROGRESS, DONE -} \ No newline at end of file +} diff --git a/src/tracker/Subtask.java b/src/tracker/Subtask.java index 651a7cb..6ee34e5 100644 --- a/src/tracker/Subtask.java +++ b/src/tracker/Subtask.java @@ -2,7 +2,6 @@ import java.time.Duration; import java.time.LocalDateTime; -import java.util.HashMap; public class Subtask extends Task { int epicId; @@ -12,8 +11,8 @@ public Subtask(String heading, String description, int id, int epicId, Duration this.epicId = epicId; } - public EpicTask getEpicTask(HashMap epicTaskHashMap) { - return epicTaskHashMap.get(epicId); + public int getEpicID() { + return epicId; } @Override diff --git a/src/tracker/Task.java b/src/tracker/Task.java index cfffd28..fdc51e4 100644 --- a/src/tracker/Task.java +++ b/src/tracker/Task.java @@ -11,7 +11,6 @@ public class Task { protected Duration duration; // Продолжительность задачи protected LocalDateTime startTime; // Дата начала задачи - // Конструктор с параметрами public Task(String heading, String description, int id, Duration duration, LocalDateTime startTime) { this.heading = heading; this.description = description; @@ -21,7 +20,6 @@ public Task(String heading, String description, int id, Duration duration, Local this.startTime = startTime; } - // Геттеры и сеттеры public Duration getDuration() { return duration; } @@ -119,4 +117,4 @@ public boolean isOverlapping(Task other) { return this.startTime.isBefore(otherEndTime) && thisEndTime.isAfter(other.startTime); } -} \ No newline at end of file +} diff --git a/src/tracker/TaskConflictException.java b/src/tracker/TaskConflictException.java new file mode 100644 index 0000000..9d7c121 --- /dev/null +++ b/src/tracker/TaskConflictException.java @@ -0,0 +1,7 @@ +package tracker; + +public class TaskConflictException extends RuntimeException { + public TaskConflictException(final String message) { + super(message); + } +} diff --git a/src/tracker/TaskManager.java b/src/tracker/TaskManager.java deleted file mode 100644 index a559bbd..0000000 --- a/src/tracker/TaskManager.java +++ /dev/null @@ -1,36 +0,0 @@ -package tracker; - -import java.util.ArrayList; -import java.util.List; - -public interface TaskManager { - List getAllTasks(); - - ArrayList getAllEpicTasks(); - - List getAllSubTasks(); - - void removeAllTasks(); - - void removeAllEpicTasks(); - - void removeAllSubTasks(); - - Task getTaskById(int id); - - EpicTask getEpicTaskById(int id); - - Subtask getSubTaskById(int id); - - Task createTask(Task task); - - EpicTask createEpicTask(EpicTask epicTask); - - Subtask createSubTask(Subtask subtask); - - void updateTask(int id, int comm, String change); - - boolean removeTaskById(int id); - - ArrayList getHistory(); -} \ No newline at end of file diff --git a/src/tracker/Type.java b/src/tracker/Type.java index 1a73cd2..ead1267 100644 --- a/src/tracker/Type.java +++ b/src/tracker/Type.java @@ -2,4 +2,4 @@ public enum Type { TASK, EPIC, SUB -} \ No newline at end of file +} diff --git a/test/test/EpicTaskTest.java b/test/test/EpicTaskTest.java deleted file mode 100644 index 6e87787..0000000 --- a/test/test/EpicTaskTest.java +++ /dev/null @@ -1,103 +0,0 @@ -package test; - -import org.junit.jupiter.api.Test; -import tracker.*; - -import java.time.Duration; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.HashMap; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static tracker.Status.*; - -class EpicTaskTest { - String epicHeading = "first epic"; - String epicDescription = "first description"; - - String subHeading = "first subtask"; - String subDescription = "first subtask description"; - - HashMap tasks = new HashMap<>(); - HashMap epicTasks = new HashMap<>(); - HashMap> subTasks = new HashMap<>(); - - InMemoryTaskManager manager = new InMemoryTaskManager(tasks, epicTasks, subTasks); - - @Test - public void getSubtasksTaskShouldReturnListOfSubtasks() { - EpicTask epicTask = new EpicTask(epicHeading, epicDescription, 0); - manager.createEpicTask(epicTask); - - int subtaskId = manager.getTaskIndex(subHeading, subDescription, "subtask"); - Subtask subtask = new Subtask(subHeading, subDescription, subtaskId, epicTask.getId(), Duration.ofMinutes(30), LocalDateTime.now()); - manager.createSubTask(subtask); - - ArrayList expectedSubtasks = new ArrayList<>(); - expectedSubtasks.add(subtask); - - assertEquals(expectedSubtasks, manager.getSubtasks(epicTask.getId())); - } - - @Test - public void getStatusShouldReturnEpicStatusAllNew() { - EpicTask epic = new EpicTask("Epic Task", "Epic Description", 1); - manager.createEpicTask(epic); - Subtask subtask1 = new Subtask("Subtask 1", "Description", 2, epic.getId(), Duration.ofMinutes(30), LocalDateTime.now()); - Subtask subtask2 = new Subtask("Subtask 2", "Description", 3, epic.getId(), Duration.ofMinutes(45), LocalDateTime.now().plusDays(1)); - manager.createSubTask(subtask1); - manager.createSubTask(subtask2); - - assertEquals(NEW, epic.getStatus()); - } - - @Test - public void checkStatusShouldReturnEpicStatusAllDone() { - EpicTask epic = new EpicTask("Epic Task", "Epic Description", 1); - manager.createEpicTask(epic); - - Subtask subtask1 = new Subtask("Subtask 1", "Description", 2, epic.getId(), Duration.ofMinutes(30), LocalDateTime.now()); - Subtask subtask2 = new Subtask("Subtask 2", "Description", 3, epic.getId(), Duration.ofMinutes(45), LocalDateTime.now().plusDays(1)); - - manager.createSubTask(subtask1); - manager.createSubTask(subtask2); - - subtask1.setStatus(Status.DONE); - subtask2.setStatus(Status.DONE); - - manager.checkStatus(epic.getId(), 1); - - assertEquals(Status.DONE, epic.getStatus(), "Статус эпической задачи должен быть DONE."); - } - - - @Test - public void checkStatusShouldReturnEpicStatusMixed() { - EpicTask epic = new EpicTask("Epic Task", "Epic Description", 1); - manager.createEpicTask(epic); - Subtask subtask1 = new Subtask("Subtask 1", "Description", 2, epic.getId(), Duration.ofMinutes(30), LocalDateTime.now()); - Subtask subtask2 = new Subtask("Subtask 2", "Description", 3, epic.getId(), Duration.ofMinutes(45), LocalDateTime.now().plusDays(1)); - subtask1.setStatus(DONE); - subtask2.setStatus(NEW); - manager.createSubTask(subtask1); - manager.createSubTask(subtask2); - - manager.checkStatus(epic.getId(), 1); - - assertEquals(IN_PROGRESS, epic.getStatus()); - } - - @Test - public void checkStatusShouldReturnEpicStatusInProgress() { - EpicTask epic = new EpicTask("Epic Task", "Epic Description", 1); - manager.createEpicTask(epic); - Subtask subtask1 = new Subtask("Subtask 1", "Description", 2, epic.getId(), - Duration.ofMinutes(30), LocalDateTime.now()); - subtask1.setStatus(IN_PROGRESS); - manager.createSubTask(subtask1); - - manager.checkStatus(epic.getId(), 1); - - assertEquals(IN_PROGRESS, epic.getStatus()); - } -} \ No newline at end of file diff --git a/test/test/InMemoryHistoryManagerTest.java b/test/test/InMemoryHistoryManagerTest.java deleted file mode 100644 index 9810f2e..0000000 --- a/test/test/InMemoryHistoryManagerTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package test; - -import static org.junit.jupiter.api.Assertions.*; - -import org.junit.jupiter.api.Test; -import tracker.*; - -import java.time.Duration; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.HashMap; - -class InMemoryHistoryManagerTest { - InMemoryHistoryManager historyManager = Managers.getDefaultHistory(); - HashMap tasks = new HashMap<>(); - HashMap epicTasks = new HashMap<>(); - HashMap> subTasks = new HashMap<>(); - InMemoryTaskManager manager = new InMemoryTaskManager(tasks, epicTasks, subTasks); - - - @Test - void historyShouldContainOnlyLastAddedTask() { - String heading1 = "task1"; - String description1 = "task1 description"; - Task task1 = new Task(heading1, description1, 1, Duration.ofMinutes(30), LocalDateTime.now()); - historyManager.add(task1); - - String heading2 = "task2"; - String description2 = "task description2"; - Task task2 = new Task(heading2, description2, 2, Duration.ofMinutes(45), LocalDateTime.now().plusHours(1)); - historyManager.add(task2); - - String heading3 = "task3"; - String description3 = "task description3"; - Task task3 = new Task(heading3, description3, 3, Duration.ofMinutes(60), LocalDateTime.now().plusHours(2)); - historyManager.add(task3); - - final ArrayList history = historyManager.getHistory(); - assertNotNull(history, "История не пустая."); - assertEquals(3, history.size(), "История содержит три задачи."); - assertEquals(task3, history.get(2), "Последняя задача в истории"); - assertEquals(task2, history.get(1), "Вторая задача в истории"); - assertEquals(task1, history.get(0), "Первая задача в истории"); - - manager.removeTaskById(1); - assertEquals(3, history.size(), "История содержит информацию об удаленной задаче"); - } - - @Test - public void testRemoveFromHistory() { - Task task1 = new Task("Task 1", "Description", 1, Duration.ofMinutes(30), LocalDateTime.now()); - Task task2 = new Task("Task 2", "Description", 2, Duration.ofMinutes(45), LocalDateTime.now().plusDays(1)); - historyManager.add(task1); - historyManager.add(task2); - - historyManager.remove(task1.getId()); - - assertEquals(1, historyManager.getHistory().size(), "История должна содержать одну задачу"); - assertEquals(task2, historyManager.getHistory().get(0), "Осталась неверная задача в истории"); - } -} \ No newline at end of file diff --git a/test/test/InMemoryTaskManagerTest.java b/test/test/InMemoryTaskManagerTest.java deleted file mode 100644 index 5900b87..0000000 --- a/test/test/InMemoryTaskManagerTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package test; - -import org.junit.jupiter.api.BeforeEach; -import tracker.*; - -import java.util.ArrayList; -import java.util.HashMap; - -class InMemoryTaskManagerTest extends TaskManagerTest { - private HashMap tasks; - private HashMap epicTasks; - private HashMap> subTasks; - - @Override - protected InMemoryTaskManager createManager() { - return new InMemoryTaskManager(tasks, epicTasks, subTasks); - } - - @BeforeEach - public void setUp() { - tasks = new HashMap<>(); - epicTasks = new HashMap<>(); - subTasks = new HashMap<>(); - super.setUp(); - } -} diff --git a/test/test/ManagersTest.java b/test/test/ManagersTest.java deleted file mode 100644 index 8effed1..0000000 --- a/test/test/ManagersTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package test; - -import org.junit.jupiter.api.Test; -import tracker.InMemoryHistoryManager; -import tracker.Managers; -import tracker.TaskManager; - -import static org.junit.jupiter.api.Assertions.*; - -public class ManagersTest { - - @Test - public void getDefaultHistoryShouldReturnInitializedInstance() { - InMemoryHistoryManager history1 = Managers.getDefaultHistory(); - InMemoryHistoryManager history2 = Managers.getDefaultHistory(); - - assertNotNull(history1, "Первый экземпляр истории не должен быть null."); - assertNotNull(history2, "Второй экземпляр истории не должен быть null."); - assertEquals(history1, history2, "Оба экземпляра истории должны быть равны."); - } - - @Test - public void getDefaultShouldReturnInitializedInstance() { - TaskManager default1 = Managers.getDefault(); - TaskManager default2 = Managers.getDefault(); - - assertNotNull(default1, "Первый экземпляр TaskManager не должен быть null."); - assertNotNull(default2, "Второй экземпляр TaskManager не должен быть null."); - assertEquals(default1, default2, "Оба экземпляра TaskManager должны быть равны."); - } -} \ No newline at end of file diff --git a/test/test/SubtaskTest.java b/test/test/SubtaskTest.java deleted file mode 100644 index 4ceec38..0000000 --- a/test/test/SubtaskTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package test; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import tracker.EpicTask; -import tracker.InMemoryTaskManager; -import tracker.Subtask; -import tracker.Task; - -import java.time.Duration; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.HashMap; - -class SubtaskTest { - String epicHeading = "second epic"; - String epicDescription = "second description"; - - String subHeading_ = "third subtask"; - String subDescription_ = "third subtask description"; - - HashMap tasks = new HashMap<>(); - HashMap epicTasks = new HashMap<>(); - HashMap> subTasks = new HashMap<>(); - InMemoryTaskManager manager = new InMemoryTaskManager(tasks, epicTasks, subTasks); - - @Test - public void getEpicTaskShouldReturnEpicAssociatedWithSubtask() { - int epicId = manager.getTaskIndex(epicHeading, epicDescription, "epic task"); - EpicTask epic = new EpicTask(epicHeading, epicDescription, epicId); - epicTasks.put(epic.getId(), epic); - - String subHeading = "second subtask"; - String subDescription = "second subtask description"; - int subtaskId = manager.getTaskIndex(subHeading, subDescription, "subtask"); - Subtask subtask = new Subtask(subHeading, subDescription, subtaskId, epic.getId(), Duration.ofMinutes(30), LocalDateTime.now()); - - ArrayList subtaskList = new ArrayList<>(); - subtaskList.add(subtask); - subTasks.put(epic.getId(), subtaskList); - - Assertions.assertEquals(epic, subtask.getEpicTask(epicTasks), "Метод должен вернуть связанный эпик для сабтаска."); - } - - @Test - public void getEpicTaskShouldReturnNullIfEpicIsNotInTheMap() { - int epicId = manager.getTaskIndex(epicHeading, epicDescription, "epic task"); - EpicTask epic = new EpicTask(epicHeading, epicDescription, epicId); - epicTasks.put(epic.getId(), epic); - - int subtaskId = manager.getTaskIndex(subHeading_, subDescription_, "subtask"); - Subtask subtaskSecond = new Subtask(subHeading_, subDescription_, subtaskId, 78, Duration.ofMinutes(30), LocalDateTime.now()); - - Assertions.assertNull(subtaskSecond.getEpicTask(epicTasks), "Метод должен вернуть null, если эпик не найден."); - } -} \ No newline at end of file diff --git a/test/test/TaskManagerTest.java b/test/test/TaskManagerTest.java deleted file mode 100644 index 1a7536d..0000000 --- a/test/test/TaskManagerTest.java +++ /dev/null @@ -1,169 +0,0 @@ -package test; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import tracker.*; - -import java.time.Duration; -import java.time.LocalDateTime; - -import static org.junit.jupiter.api.Assertions.*; - -abstract class TaskManagerTest { - protected T manager; - - @BeforeEach - public void setUp() { - manager = createManager(); - } - - protected abstract T createManager(); - - @Test - public void getAllTasksShouldReturnAllTasks() { - Task task1 = new Task("Task 1", "Description 1", 1, Duration.ofMinutes(30), LocalDateTime.now()); - Task task2 = new Task("Task 2", "Description 2", 2, Duration.ofMinutes(45), LocalDateTime.now().plusDays(1)); - manager.createTask(task1); - manager.createTask(task2); - - assertEquals(2, manager.getAllTasks().size(), "Должно быть 2 задачи."); - } - - @Test - public void getAllEpicTasksShouldReturnAllEpicTasks() { - EpicTask epicTask1 = new EpicTask("Epic Task 1", "Description 1", 1); - EpicTask epicTask2 = new EpicTask("Epic Task 2", "Description 2", 2); - manager.createEpicTask(epicTask1); - manager.createEpicTask(epicTask2); - - assertEquals(2, manager.getAllEpicTasks().size(), "Должно быть 2 эпические задачи."); - } - - @Test - public void getAllSubTasksShouldReturnAllSubTasks() { - EpicTask epicTask = new EpicTask("Epic Task", "Description", 1); - manager.createEpicTask(epicTask); - Subtask subtask1 = new Subtask("Subtask 1", "Description", 2, epicTask.getId(), Duration.ofMinutes(30), LocalDateTime.now()); - Subtask subtask2 = new Subtask("Subtask 2", "Description", 3, epicTask.getId(), Duration.ofMinutes(45), LocalDateTime.now().plusHours(1)); - manager.createSubTask(subtask1); - manager.createSubTask(subtask2); - - assertEquals(2, manager.getAllSubTasks().size(), "Должно быть 2 подзадачи."); - } - - @Test - public void removeAllTasksShouldClearAllTasks() { - Task task = new Task("Task", "Description", 1, Duration.ofMinutes(30), LocalDateTime.now()); - manager.createTask(task); - manager.removeAllTasks(); - - assertEquals(0, manager.getAllTasks().size(), "Количество задач должно быть 0 после удаления."); - } - - @Test - public void removeAllEpicTasksShouldClearAllEpicTasks() { - EpicTask epicTask = new EpicTask("Epic Task", "Description", 1); - manager.createEpicTask(epicTask); - manager.removeAllEpicTasks(); - - assertEquals(0, manager.getAllEpicTasks().size(), "Количество эпических задач должно быть 0 после удаления."); - } - - @Test - public void removeAllSubTasksShouldClearAllSubTasks() { - EpicTask epicTask = new EpicTask("Epic Task", "Description", 1); - manager.createEpicTask(epicTask); - Subtask subtask = new Subtask("Subtask", "Description", 2, epicTask.getId(), Duration.ofMinutes(30), LocalDateTime.now()); - manager.createSubTask(subtask); - manager.removeAllSubTasks(); - - assertEquals(0, manager.getAllSubTasks().size(), "Количество подзадач должно быть 0 после удаления."); - } - - @Test - public void getTaskByIdShouldReturnCorrectTask() { - Task task = new Task("Task", "Description", 1, Duration.ofMinutes(30), LocalDateTime.now()); - manager.createTask(task); - Task retrievedTask = manager.getTaskById(task.getId()); - - assertEquals(task, retrievedTask, "Должен вернуть правильную задачу по ID."); - } - - @Test - public void getEpicTaskByIdShouldReturnCorrectEpicTask() { - EpicTask epicTask = new EpicTask("Epic Task", "Description", 1); - manager.createEpicTask(epicTask); - EpicTask retrievedEpicTask = manager.getEpicTaskById(epicTask.getId()); - - assertEquals(epicTask, retrievedEpicTask, "Должен вернуть правильную эпическую задачу по ID."); - } - - @Test - public void getSubTaskByIdShouldReturnCorrectSubtask() { - EpicTask epicTask = new EpicTask("Epic Task", "Description", 1); - manager.createEpicTask(epicTask); - Subtask subtask = new Subtask("Subtask", "Description", 2, epicTask.getId(), Duration.ofMinutes(30), LocalDateTime.now()); - manager.createSubTask(subtask); - Subtask retrievedSubtask = manager.getSubTaskById(subtask.getId()); - - assertEquals(subtask, retrievedSubtask, "Должен вернуть правильную подзадачу по ID."); - } - - @Test - public void createTaskShouldAddTask() { - Task task = new Task("Task", "Description", 1, Duration.ofMinutes(30), LocalDateTime.now()); - manager.createTask(task); - - assertEquals(1, manager.getAllTasks().size(), "Количество задач должно быть 1 после добавления."); - } - - @Test - public void createEpicTaskShouldAddEpicTask() { - EpicTask epicTask = new EpicTask("Epic Task", "Description", 1); - manager.createEpicTask(epicTask); - - assertEquals(1, manager.getAllEpicTasks().size(), "Количество эпических задач должно быть 1 после добавления."); - } - - @Test - public void createSubTaskShouldAddSubtask() { - EpicTask epicTask = new EpicTask("Epic Task", "Description", 1); - manager.createEpicTask(epicTask); - Subtask subtask = new Subtask("Subtask", "Description", 2, epicTask.getId(), Duration.ofMinutes(30), LocalDateTime.now()); - manager.createSubTask(subtask); - - assertEquals(1, manager.getAllSubTasks().size(), "Количество подзадач должно быть 1 после добавления."); - } - - @Test - public void updateTaskShouldChangeTaskDetails() { - Task task = new Task("Task", "Description", 1, Duration.ofMinutes(30), LocalDateTime.now()); - manager.createTask(task); - manager.updateTask(task.getId(), 1, "Updated Task"); - - assertEquals("Updated Task", manager.getTaskById(task.getId()).getHeading(), "Заголовок задачи должен быть обновлен."); - } - - @Test - public void removeSubTaskByIdShouldRemoveSubtask() { - EpicTask epicTask = new EpicTask("Epic Task", "Description", 1); - manager.createEpicTask(epicTask); - Subtask subtask = new Subtask("Subtask", "Description", 2, epicTask.getId(), Duration.ofMinutes(30), LocalDateTime.now()); - manager.createSubTask(subtask); - manager.removeTaskById(subtask.getId()); - - assertNull(manager.getSubTaskById(subtask.getId()), "Подзадача должна быть удалена."); - } - - @Test - public void getHistoryShouldReturnTaskHistory() { - Task task1 = new Task("Task 1", "Description 1", 1, Duration.ofMinutes(30), LocalDateTime.now()); - Task task2 = new Task("Task 2", "Description 2", 2, Duration.ofMinutes(45), LocalDateTime.now().plusDays(1)); - manager.createTask(task1); - manager.createTask(task2); - manager.getTaskById(task1.getId()); - manager.getTaskById(task2.getId()); - - assertEquals(2, manager.getHistory().size(), "История должна содержать 2 задачи."); - } -} \ No newline at end of file