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/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..5dc2047 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -46,14 +46,13 @@ public Subtask addSubtask(Subtask subtask) { 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 @@ -92,7 +91,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 +184,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/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/Subtask.java b/src/model/Subtask.java index 38410af..ad37d23 100644 --- a/src/model/Subtask.java +++ b/src/model/Subtask.java @@ -27,6 +27,7 @@ public String toString() { ", status=" + getStatus() + '}'; } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/model/Task.java b/src/model/Task.java index e70661f..9c2ed8a 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -8,6 +8,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 +16,27 @@ public Task(int id, String name, String description, Status status) { this.status = status; } + 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 +79,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/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