diff --git a/Test/manager/InMemoryHistoryManagerTest.java b/Test/manager/InMemoryHistoryManagerTest.java deleted file mode 100644 index 6dfb7f4..0000000 --- a/Test/manager/InMemoryHistoryManagerTest.java +++ /dev/null @@ -1,86 +0,0 @@ -package manager; - -import model.Epic; -import model.Status; -import model.Subtask; -import model.Task; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -class InMemoryHistoryManagerTest { - - private static TaskManager taskManager; - - @BeforeEach - public void beforeEach() { - taskManager = Managers.getDefault(); - } - - @Test - public void getHistoryShouldReturnListOf10Tasks() { - for (int i = 0; i < 20; i++) { - taskManager.addTask(new Task("Some name", "Some description")); - } - - List tasks = taskManager.getTasks(); - for (Task task : tasks) { - taskManager.getTaskByID(task.getId()); - } - - List list = taskManager.getHistory(); - assertEquals(10, list.size(), "Неверное количество элементов в истории "); - } - - @Test - public void getHistoryShouldReturnOldTaskAfterUpdate() { - Task washFloor = new Task("Помыть полы", "С новым средством"); - taskManager.addTask(washFloor); - taskManager.getTaskByID(washFloor.getId()); - taskManager.updateTask(new Task(washFloor.getId(), "Не забыть помыть полы", - "Можно и без средства", Status.IN_PROGRESS)); - List tasks = taskManager.getHistory(); - Task oldTask = tasks.getFirst(); - assertEquals(washFloor.getName(), oldTask.getName(), "В истории не сохранилась старая версия задачи"); - assertEquals(washFloor.getDescription(), oldTask.getDescription(), - "В истории не сохранилась старая версия задачи"); - - } - - @Test - public void getHistoryShouldReturnOldEpicAfterUpdate() { - Epic flatRenovation = new Epic(1, "Сделать ремонт", "Нужно успеть за отпуск"); - taskManager.addEpic(flatRenovation); - taskManager.getEpicByID(flatRenovation.getId()); - taskManager.updateEpic(new Epic(flatRenovation.getId(), "Новое имя", "новое описание" - )); - List epics = taskManager.getHistory(); - Epic oldEpic = (Epic) epics.getFirst(); - assertEquals(flatRenovation.getName(), oldEpic.getName(), - "В истории не сохранилась старая версия эпика"); - assertEquals(flatRenovation.getDescription(), oldEpic.getDescription(), - "В истории не сохранилась старая версия эпика"); - } - - @Test - public void getHistoryShouldReturnOldSubtaskAfterUpdate() { - Epic flatRenovation = new Epic(1, "Сделать ремонт", "Нужно успеть за отпуск"); - taskManager.addEpic(flatRenovation); - Subtask flatRenovationSubtask3 = new Subtask("Заказать книжный шкаф", "Из темного дерева", - flatRenovation.getId()); - taskManager.addSubtask(flatRenovationSubtask3); - taskManager.getSubtaskByID(flatRenovationSubtask3.getId()); - taskManager.updateSubtask(new Subtask(flatRenovationSubtask3.getId(), "Новое имя", - "новое описание", Status.IN_PROGRESS, flatRenovation.getId())); - List subtasks = taskManager.getHistory(); - Subtask oldSubtask = (Subtask) subtasks.getFirst(); - assertEquals(flatRenovationSubtask3.getName(), oldSubtask.getName(), - "В истории не сохранилась старая версия эпика"); - assertEquals(flatRenovationSubtask3.getDescription(), oldSubtask.getDescription(), - "В истории не сохранилась старая версия эпика"); - } -} \ No newline at end of file diff --git a/java-kanban.iml b/java-kanban.iml index 55a0bff..9d56d29 100644 --- a/java-kanban.iml +++ b/java-kanban.iml @@ -4,7 +4,7 @@ - + diff --git a/module-info.java b/module-info.java new file mode 100644 index 0000000..e69de29 diff --git a/src/manager/FileBackedTaskManager.java b/src/manager/FileBackedTaskManager.java new file mode 100644 index 0000000..8fa5959 --- /dev/null +++ b/src/manager/FileBackedTaskManager.java @@ -0,0 +1,172 @@ +package manager; + +import model.Epic; +import model.Status; +import model.Subtask; +import model.Task; +import tasktype.TaskType; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.util.List; + +public class FileBackedTaskManager extends InMemoryTaskManager { + private final File file; + + public FileBackedTaskManager(File file) { + this.file = file; + } + + @Override + public Task addTask(Task task) { + Task addedTask = super.addTask(task); + save(); + return addedTask; + } + + @Override + public Epic addEpic(Epic epic) { + Epic addedEpic = super.addEpic(epic); + save(); + return addedEpic; + } + + @Override + public Subtask addSubtask(Subtask subtask) { + Subtask addedSubtask = super.addSubtask(subtask); + save(); + return addedSubtask; + } + + @Override + public Task updateTask(Task updatedTask) { + Task existingTask = super.updateTask(updatedTask); + save(); + return existingTask; + } + + @Override + public Epic updateEpic(Epic updatedEpic) { + Epic existingEpic = super.updateEpic(updatedEpic); + save(); + return existingEpic; + } + + @Override + public Subtask updateSubtask(Subtask updatedSubtask) { + Subtask existingSubtask = super.updateSubtask(updatedSubtask); + save(); + return existingSubtask; + } + + @Override + public void deleteTaskByID(int id) { + super.deleteTaskByID(id); + save(); + } + + @Override + public void deleteEpicByID(int id) { + super.deleteEpicByID(id); + save(); + } + + @Override + public void deleteSubtaskByID(int id) { + super.deleteSubtaskByID(id); + save(); + } + + @Override + public void deleteTasks() { + super.deleteTasks(); + save(); + } + + @Override + public void deleteEpics() { + super.deleteEpics(); + save(); + } + + @Override + public void deleteSubtasks() { + super.deleteSubtasks(); + save(); + } + + public void save() { + try (PrintWriter writer = new PrintWriter(file)) { + writer.println("id,type,name,status,description,epic"); + for (Task task : getTasks()) { + writer.println(toString(task)); + } + for (Epic epic : getEpics()) { + writer.println(toString(epic)); + } + for (Subtask subtask : getSubtasks()) { + writer.println(toString(subtask)); + } + } catch (IOException e) { + throw new ManagerSaveException("Failed to save tasks to file", e); + } + } + + private String toString(Task task) { + switch (task.getType()) { + case SUBTASK: + return String.format("%d,SUBTASK,%s,%s,%s,%d", + task.getId(), task.getName(), task.getStatus(), task.getDescription(), ((Subtask) task).getEpicID()); + case EPIC: + return String.format("%d,EPIC,%s,%s,%s,", + task.getId(), task.getName(), task.getStatus(), task.getDescription()); + case TASK: + default: + return String.format("%d,TASK,%s,%s,%s,", + task.getId(), task.getName(), task.getStatus(), task.getDescription()); + } + } + + public static FileBackedTaskManager loadFromFile(File file) { + FileBackedTaskManager manager = new FileBackedTaskManager(file); + try { + List lines = Files.readAllLines(file.toPath()); + for (String line : lines.subList(1, lines.size())) { + Task task = fromString(line); + if (task instanceof Epic) { + manager.addEpic((Epic) task); + } else if (task instanceof Subtask) { + manager.addSubtask((Subtask) task); + } else { + manager.addTask(task); + } + } + } catch (IOException e) { + throw new ManagerSaveException("Failed to load tasks from file", e); + } + return manager; + } + + private static Task fromString(String value) { + String[] parts = value.split(","); + int id = Integer.parseInt(parts[0]); + String type = parts[1]; + String name = parts[2]; + Status status = Status.valueOf(parts[3]); + String description = parts[4]; + + TaskType taskType = TaskType.valueOf(type); + switch (taskType) { + case SUBTASK: + int epicID = Integer.parseInt(parts[5]); + return new Subtask(id, name, description, status, epicID); + case EPIC: + return new Epic(id, name, description); + case TASK: + default: + return new Task(id, name, description, status); + } + } +} \ No newline at end of file diff --git a/src/manager/HistoryManager.java b/src/manager/HistoryManager.java index b2bcde7..d06a752 100644 --- a/src/manager/HistoryManager.java +++ b/src/manager/HistoryManager.java @@ -5,6 +5,11 @@ import java.util.List; public interface HistoryManager { + void add(Task task); + + void remove(int id); + List getHistory(); + } \ No newline at end of file diff --git a/src/manager/InMemoryHistoryManager.java b/src/manager/InMemoryHistoryManager.java index b9908b3..e42534d 100644 --- a/src/manager/InMemoryHistoryManager.java +++ b/src/manager/InMemoryHistoryManager.java @@ -4,20 +4,122 @@ import java.util.*; - public class InMemoryHistoryManager implements HistoryManager { - private final List history = new ArrayList<>(); + private static class CustomLinkedList { + private final Map table = new HashMap<>(); + private Node head; + private Node tail; + + private static class Node { + private Task task; + private Node prev; + private Node next; + + public Task getTask() { + return task; + } + + public void setTask(Task task) { + this.task = task; + } + + public Node getPrev() { + return prev; + } + + public void setPrev(Node prev) { + this.prev = prev; + } + + public Node getNext() { + return next; + } + + public void setNext(Node next) { + this.next = next; + } + } + + private void linkLast(Task task) { + Node element = new Node(); + element.setTask(task); + + if (table.containsKey(task.getId())) { + removeNode(table.get(task.getId())); + } + + if (head == null) { + tail = element; + head = element; + element.setNext(null); + element.setPrev(null); + } else { + element.setPrev(tail); + element.setNext(null); + tail.setNext(element); + tail = element; + } + + table.put(task.getId(), element); + } + + private List getTasks() { + List result = new ArrayList<>(); + Node element = head; + while (element != null) { + result.add(element.getTask()); + element = element.getNext(); + } + return result; + } + private void removeNode(Node node) { + if (node != null) { + table.remove(node.getTask().getId()); + Node prev = node.getPrev(); + Node next = node.getNext(); + + if (head == node) { + head = node.getNext(); + } + if (tail == node) { + tail = node.getPrev(); + } + + if (prev != null) { + prev.setNext(next); + } + + if (next != null) { + next.setPrev(prev); + } + } + } + + private Node getNode(int id) { + return table.get(id); + } + } + + private final CustomLinkedList list = new CustomLinkedList(); + + // Добавление нового просмотра задачи в историю @Override public void add(Task task) { - if (history.size() >= 10) { - history.remove(0); - } - history.add(task); + list.linkLast(task); } + // Удаление просмотра из истории + @Override + public void remove(int id) { + list.removeNode(list.getNode(id)); + } + + // Получение истории просмотров @Override public List getHistory() { - return List.copyOf(history); + return list.getTasks(); } -} \ No newline at end of file +} + + diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index aa804bd..27623f5 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -38,22 +38,24 @@ public Epic addEpic(Epic epic) { @Override public Subtask addSubtask(Subtask subtask) { - subtask.setId(getNextID()); Epic epic = epics.get(subtask.getEpicID()); + if (epic == null) { + throw new IllegalArgumentException("Epic with ID " + subtask.getEpicID() + " does not exist."); + } + subtask.setId(getNextID()); epic.addSubtask(subtask); subtasks.put(subtask.getId(), subtask); updateEpicStatus(epic); return subtask; } - @Override - public Task updateTask(Task task) { - Integer taskID = task.getId(); - if (taskID == null || !tasks.containsKey(taskID)) { - return null; + public Task updateTask(Task updatedTask) { + Task existingTask = getTaskByID(updatedTask.getId()); + if (existingTask != null) { + historyManager.add(new Task(existingTask)); + tasks.put(updatedTask.getId(), updatedTask); } - tasks.replace(taskID, task); - return task; + return existingTask; } @Override @@ -62,7 +64,7 @@ public Epic updateEpic(Epic epic) { if (epicID == null || !epics.containsKey(epicID)) { return null; } - // если у эпика были подзадачи, удаляем их из мапы с подзадачами + Epic oldEpic = epics.get(epicID); ArrayList oldEpicSubtaskList = oldEpic.getSubtaskList(); if (!oldEpicSubtaskList.isEmpty()) { @@ -71,14 +73,14 @@ public Epic updateEpic(Epic epic) { } } epics.replace(epicID, epic); - // если у обновленного эпика есть подзадачи, добавляем их в мапу подзадач + ArrayList newEpicSubtaskList = epic.getSubtaskList(); if (!newEpicSubtaskList.isEmpty()) { for (Subtask subtask : newEpicSubtaskList) { subtasks.put(subtask.getId(), subtask); } } - // обновляем статус эпика + updateEpicStatus(epic); return epic; } @@ -92,7 +94,6 @@ public Subtask updateSubtask(Subtask subtask) { int epicID = subtask.getEpicID(); Subtask oldSubtask = subtasks.get(subtaskID); subtasks.replace(subtaskID, subtask); - // обновляем подзадачу в списке подзадач эпика и проверяем статус эпика Epic epic = epics.get(epicID); ArrayList subtaskList = epic.getSubtaskList(); subtaskList.remove(oldSubtask); @@ -186,14 +187,17 @@ public void deleteEpicByID(int id) { @Override public void deleteSubtaskByID(int id) { Subtask subtask = subtasks.get(id); - int epicID = subtask.getEpicID(); - subtasks.remove(id); - // обновляем список подзадач и статус эпика - Epic epic = epics.get(epicID); - ArrayList subtaskList = epic.getSubtaskList(); - subtaskList.remove(subtask); - epic.setSubtaskList(subtaskList); - updateEpicStatus(epic); + if (subtask != null) { + int epicID = subtask.getEpicID(); + subtasks.remove(id); + // Remove from history + historyManager.remove(id); + Epic epic = epics.get(epicID); + ArrayList subtaskList = epic.getSubtaskList(); + subtaskList.remove(subtask); + epic.setSubtaskList(subtaskList); + updateEpicStatus(epic); + } } @Override diff --git a/src/manager/ManagerSaveException.java b/src/manager/ManagerSaveException.java new file mode 100644 index 0000000..cc94837 --- /dev/null +++ b/src/manager/ManagerSaveException.java @@ -0,0 +1,7 @@ +package manager; + +public class ManagerSaveException extends RuntimeException { + public ManagerSaveException(String message, Throwable cause) { + super(message, cause); + } +} \ No newline at end of file diff --git a/src/manager/Node.java b/src/manager/Node.java new file mode 100644 index 0000000..4f9bb35 --- /dev/null +++ b/src/manager/Node.java @@ -0,0 +1,34 @@ +package manager; + +import model.Task; + +public class Node { + private Task task; + private manager.Node prev; + private manager.Node next; + + public manager.Node getNext() { + return next; + } + + public manager.Node getPrev() { + return prev; + } + + public Task getTask() { + return task; + } + + public void setNext(manager.Node next) { + this.next = next; + } + + public void setPrev(manager.Node prev) { + this.prev = prev; + } + + public void setTask(Task task) { + this.task = task; + } + } + diff --git a/src/manager/TaskManager.java b/src/manager/TaskManager.java index 917f3f8..286c18c 100644 --- a/src/manager/TaskManager.java +++ b/src/manager/TaskManager.java @@ -9,24 +9,45 @@ import java.util.List; public interface TaskManager { + Task addTask(Task task); + Epic addEpic(Epic epic); + Subtask addSubtask(Subtask subtask); + Task updateTask(Task task); + Epic updateEpic(Epic epic); + Subtask updateSubtask(Subtask subtask); + Task getTaskByID(int id); + Epic getEpicByID(int id); + Subtask getSubtaskByID(int id); + ArrayList getTasks(); + ArrayList getEpics(); + ArrayList getSubtasks(); + ArrayList getEpicSubtasks(Epic epic); + void deleteTasks(); + void deleteEpics(); + void deleteSubtasks(); + void deleteTaskByID(int id); + void deleteEpicByID(int id); + void deleteSubtaskByID(int id); + List getHistory(); + } diff --git a/src/model/Epic.java b/src/model/Epic.java index 3817186..9e9b66e 100644 --- a/src/model/Epic.java +++ b/src/model/Epic.java @@ -1,5 +1,7 @@ package model; +import tasktype.TaskType; + import java.util.ArrayList; import java.util.Objects; @@ -8,7 +10,6 @@ public class Epic extends Task { public Epic(int id, String name, String description) { super(id, name, description); - // Статус NEW устанавливается по умолчанию в конструкторе родительского класса Task } public void addSubtask(Subtask subtask) { @@ -54,4 +55,9 @@ public boolean equals(Object obj) { public int hashCode() { return Objects.hash(getId()); } + + @Override + public TaskType getType() { + return TaskType.EPIC; + } } \ No newline at end of file diff --git a/src/model/Subtask.java b/src/model/Subtask.java index 38410af..6c2feca 100644 --- a/src/model/Subtask.java +++ b/src/model/Subtask.java @@ -1,5 +1,7 @@ package model; +import tasktype.TaskType; + public class Subtask extends Task { private final int epicID; @@ -27,6 +29,7 @@ public String toString() { ", status=" + getStatus() + '}'; } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -34,4 +37,9 @@ public boolean equals(Object o) { Subtask subtask = (Subtask) o; return epicID == subtask.epicID; } + + @Override + public TaskType getType() { + return TaskType.SUBTASK; + } } \ No newline at end of file diff --git a/src/model/Task.java b/src/model/Task.java index e70661f..844cbe0 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -1,5 +1,7 @@ package model; +import tasktype.TaskType; + import java.util.Objects; public class Task { @@ -8,6 +10,7 @@ public class Task { private int id; private Status status; + public Task(int id, String name, String description, Status status) { this.id = id; this.name = name; @@ -15,16 +18,30 @@ public Task(int id, String name, String description, Status status) { this.status = status; } + public TaskType getType() { + return TaskType.TASK; + } + public Task(String name, String description) { this.name = name; this.description = description; this.status = Status.NEW; } + public Task(int id, String name, String description) { this(id, name, description, Status.NEW); } + + public Task(Task task) { + this.id = task.id; + this.name = task.name; + this.description = task.description; + this.status = task.status; + } + + public String getName() { return name; } @@ -67,25 +84,16 @@ public boolean equals(Object object) { @Override public int hashCode() { - int hash = 17; - if (name != null) { - hash = hash + name.hashCode(); - } - hash = hash * 31; - if (description != null) { - hash = hash + description.hashCode(); - } - return hash; + return Objects.hash(id); } @Override public String toString() { - return "model.Task{" + + return "Task{" + "name='" + name + '\'' + ", description='" + description + '\'' + ", id=" + id + ", status=" + status + '}'; } - } \ No newline at end of file diff --git a/src/tasktype/TaskType.java b/src/tasktype/TaskType.java new file mode 100644 index 0000000..1405e80 --- /dev/null +++ b/src/tasktype/TaskType.java @@ -0,0 +1,7 @@ +package tasktype; + +public enum TaskType { + TASK, + EPIC, + SUBTASK +} \ No newline at end of file diff --git a/test/manager/FileBackedTasksManagerTest.java b/test/manager/FileBackedTasksManagerTest.java new file mode 100644 index 0000000..92aef08 --- /dev/null +++ b/test/manager/FileBackedTasksManagerTest.java @@ -0,0 +1,66 @@ +package manager; + +import model.Epic; +import model.Subtask; +import model.Task; +import org.junit.jupiter.api.Test; + + +import java.io.File; +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + + +public class FileBackedTasksManagerTest { + @Test + public void saveAndLoadEmptyFile() throws IOException { + File tempFile = File.createTempFile("test", ".csv"); + tempFile.deleteOnExit(); + FileBackedTaskManager manager = new FileBackedTaskManager(tempFile); + manager.save(); + FileBackedTaskManager loadedManager = FileBackedTaskManager.loadFromFile(tempFile); + assertTrue(loadedManager.getTasks().isEmpty()); + assertTrue(loadedManager.getEpics().isEmpty()); + assertTrue(loadedManager.getSubtasks().isEmpty()); + } + + @Test + public void saveAndLoadMultipleTasks() throws IOException { + File tempFile = File.createTempFile("test", ".csv"); + tempFile.deleteOnExit(); + FileBackedTaskManager manager = new FileBackedTaskManager(tempFile); + + + manager.addTask(new Task("Task 1", "Description 1")); + Epic epic = new Epic(1, "Epic 1", "Description Epic 1"); + manager.addEpic(epic); + manager.addSubtask(new Subtask("Subtask 1", "Description Subtask 1", epic.getId())); + + + manager.save(); + + + FileBackedTaskManager loadedManager = FileBackedTaskManager.loadFromFile(tempFile); + + + assertEquals(1, loadedManager.getTasks().size()); + assertEquals(1, loadedManager.getEpics().size()); + assertEquals(1, loadedManager.getSubtasks().size()); + } + + @Test + public void deleteTaskShouldRemoveTaskFromFile() throws IOException { + File tempFile = File.createTempFile("test", ".csv"); + tempFile.deleteOnExit(); + FileBackedTaskManager manager = new FileBackedTaskManager(tempFile); + + Task task = new Task("Test Task", "Description"); + manager.addTask(task); + manager.deleteTaskByID(task.getId()); + + FileBackedTaskManager loadedManager = FileBackedTaskManager.loadFromFile(tempFile); + assertTrue(loadedManager.getTasks().isEmpty(), "Задача не была удалена из файла."); + } +} diff --git a/test/manager/InMemoryHistoryManagerTest.java b/test/manager/InMemoryHistoryManagerTest.java new file mode 100644 index 0000000..f9611ec --- /dev/null +++ b/test/manager/InMemoryHistoryManagerTest.java @@ -0,0 +1,158 @@ +package manager; + +import model.Epic; +import model.Status; +import model.Subtask; +import model.Task; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class InMemoryHistoryManagerTest { + + private static TaskManager taskManager; + + @BeforeEach + public void beforeEach() { + taskManager = Managers.getDefault(); + } + + @Test + public void getHistoryShouldReturnListOf10Tasks() { + for (int i = 0; i < 10; i++) { + taskManager.addTask(new Task("Some name " + i, "Some description " + i)); + } + + List tasks = taskManager.getTasks(); + for (Task task : tasks) { + taskManager.getTaskByID(task.getId()); + } + + List list = taskManager.getHistory(); + assertEquals(10, list.size(), "Неверное количество элементов в истории "); + } + + @Test + public void getHistoryShouldReturnOldTaskAfterUpdate() { + Task washFloor = new Task("Помыть полы", "С новым средством"); + taskManager.addTask(washFloor); + taskManager.getTaskByID(washFloor.getId()); + + + Task updatedTask = new Task(washFloor.getId(), "Не забыть помыть полы", + "Можно и без средства", Status.IN_PROGRESS); + taskManager.updateTask(updatedTask); + + List tasks = taskManager.getHistory(); + Task oldTask = tasks.get(tasks.size() - 1); + assertEquals(washFloor.getName(), oldTask.getName(), "В истории не сохранилась старая версия задачи"); + assertEquals(washFloor.getDescription(), oldTask.getDescription(), + "В истории не сохранилась старая версия задачи"); + } + + + @Test + public void getHistoryShouldReturnOldSubtaskAfterUpdate() { + Epic flatRenovation = new Epic(1, "Сделать ремонт", "Нужно успеть за отпуск"); + taskManager.addEpic(flatRenovation); + Subtask flatRenovationSubtask3 = new Subtask("Заказать книжный шкаф", "Из темного дерева", + flatRenovation.getId()); + taskManager.addSubtask(flatRenovationSubtask3); + + + taskManager.getSubtaskByID(flatRenovationSubtask3.getId()); + + // Update the subtask + Subtask updatedSubtask = new Subtask(flatRenovationSubtask3.getId(), "Новое имя", + "новое описание", Status.IN_PROGRESS, flatRenovation.getId()); + taskManager.updateSubtask(updatedSubtask); + + // Check the history + List subtasks = taskManager.getHistory(); + System.out.println("History contents:"); + for (Task task : subtasks) { + System.out.println(task.getId() + ": " + task.getName() + " (" + task.getClass().getSimpleName() + ")"); + } + + + Task lastAccessedTask = subtasks.get(subtasks.size() - 1); + if (lastAccessedTask instanceof Subtask) { + Subtask oldSubtask = (Subtask) lastAccessedTask; + assertEquals(flatRenovationSubtask3.getName(), oldSubtask.getName(), + "В истории не сохранилась старая версия подзадачи"); + assertEquals(flatRenovationSubtask3.getDescription(), oldSubtask.getDescription(), + "В истории не сохранилась старая версия подзадачи"); + } else { + fail("Last accessed task is not a Subtask"); + } + } + + @Test + public void shouldNotRetainOldIdInDeletedSubtask() { + Epic epic = new Epic(1, "Сделать ремонт", "Нужно успеть за отпуск"); + taskManager.addEpic(epic); + Subtask subtask = new Subtask("Заказать книжный шкаф", "Из темного дерева", epic.getId()); + taskManager.addSubtask(subtask); + + // Добавляем подзадачу в историю + taskManager.getSubtaskByID(subtask.getId()); + + // Удаляем подзадачу + taskManager.deleteSubtaskByID(subtask.getId()); + + // Проверяем, что подзадача не осталась в менеджере + assertNull(taskManager.getSubtaskByID(subtask.getId()), "Подзадача не была удалена"); + + // Проверяем, что в истории не осталось старого ID + List history = taskManager.getHistory(); + assertFalse(history.stream().anyMatch(task -> task.getId() == subtask.getId()), + "История содержит неактуальный ID подзадачи"); + } + + @Test + public void shouldNotHaveInvalidSubtaskIdsInEpic() { + Epic epic = new Epic(1, "Сделать ремонт", "Нужно успеть за отпуск"); + taskManager.addEpic(epic); + Subtask subtask = new Subtask("Заказать книжный шкаф", "Из темного дерева", epic.getId()); + taskManager.addSubtask(subtask); + + // Удаляем подзадачу + taskManager.deleteSubtaskByID(subtask.getId()); + + // Проверяем, что в эпике не осталось неактуальных ID подзадач + List subtasksInEpic = taskManager.getEpicSubtasks(epic); // Передаем объект epic + assertFalse(subtasksInEpic.stream().anyMatch(s -> s.getId() == subtask.getId()), + "Эпик содержит неактуальный ID подзадачи"); + } + + + @Test + public void testGetTaskByIDAddsToHistory() { + InMemoryTaskManager taskManager = new InMemoryTaskManager(); + Task task = new Task("Test Task", "Description"); + taskManager.addTask(task); + + taskManager.getTaskByID(task.getId()); + + List history = taskManager.getHistory(); + assertEquals(1, history.size()); + assertEquals(task, history.get(0)); + } + + @Test + public void testUpdateTaskUpdatesTaskAndAddsOldVersionToHistory() { + InMemoryTaskManager taskManager = new InMemoryTaskManager(); + Task task = new Task("Test Task", "Description"); + taskManager.addTask(task); + + Task updatedTask = new Task(task.getId(), "Updated Task", "Updated Description"); + taskManager.updateTask(updatedTask); + + List history = taskManager.getHistory(); + assertEquals(1, history.size()); + assertEquals(task, history.get(0)); // Проверяем, что старая версия добавлена в историю + } +} \ No newline at end of file diff --git a/Test/manager/InMemoryTaskManagerTest.java b/test/manager/InMemoryTaskManagerTest.java similarity index 100% rename from Test/manager/InMemoryTaskManagerTest.java rename to test/manager/InMemoryTaskManagerTest.java diff --git a/Test/manager/ManagersTest.java b/test/manager/ManagersTest.java similarity index 100% rename from Test/manager/ManagersTest.java rename to test/manager/ManagersTest.java diff --git a/Test/model/EpicTest.java b/test/model/EpicTest.java similarity index 100% rename from Test/model/EpicTest.java rename to test/model/EpicTest.java diff --git a/Test/model/SubtaskTest.java b/test/model/SubtaskTest.java similarity index 100% rename from Test/model/SubtaskTest.java rename to test/model/SubtaskTest.java diff --git a/Test/model/TaskTest.java b/test/model/TaskTest.java similarity index 100% rename from Test/model/TaskTest.java rename to test/model/TaskTest.java