From 0087d5b467ef8505f9ccfaa8849c8304f3520ee6 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 4 Dec 2024 18:15:30 +0300 Subject: [PATCH 01/16] commit 7 --- Test/manager/InMemoryHistoryManagerTest.java | 128 +++++++++++++++---- src/manager/HistoryManager.java | 1 + src/manager/InMemoryHistoryManager.java | 116 ++++++++++++++++- src/manager/InMemoryTaskManager.java | 33 ++--- src/model/Task.java | 27 ++-- 5 files changed, 242 insertions(+), 63 deletions(-) diff --git a/Test/manager/InMemoryHistoryManagerTest.java b/Test/manager/InMemoryHistoryManagerTest.java index 6dfb7f4..96c8e36 100644 --- a/Test/manager/InMemoryHistoryManagerTest.java +++ b/Test/manager/InMemoryHistoryManagerTest.java @@ -7,7 +7,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; - import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -23,8 +22,8 @@ public void beforeEach() { @Test public void getHistoryShouldReturnListOf10Tasks() { - for (int i = 0; i < 20; i++) { - taskManager.addTask(new Task("Some name", "Some description")); + for (int i = 0; i < 10; i++) { + taskManager.addTask(new Task("Some name " + i, "Some description " + i)); } List tasks = taskManager.getTasks(); @@ -41,30 +40,19 @@ public void getHistoryShouldReturnOldTaskAfterUpdate() { Task washFloor = new Task("Помыть полы", "С новым средством"); taskManager.addTask(washFloor); taskManager.getTaskByID(washFloor.getId()); - taskManager.updateTask(new Task(washFloor.getId(), "Не забыть помыть полы", - "Можно и без средства", Status.IN_PROGRESS)); + + // Update the task + Task updatedTask = new Task(washFloor.getId(), "Не забыть помыть полы", + "Можно и без средства", Status.IN_PROGRESS); + taskManager.updateTask(updatedTask); + List tasks = taskManager.getHistory(); - Task oldTask = tasks.getFirst(); + Task oldTask = tasks.get(tasks.size() - 1); // Get the last accessed task 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() { @@ -73,14 +61,98 @@ public void getHistoryShouldReturnOldSubtaskAfterUpdate() { Subtask flatRenovationSubtask3 = new Subtask("Заказать книжный шкаф", "Из темного дерева", flatRenovation.getId()); taskManager.addSubtask(flatRenovationSubtask3); + + // Access the subtask to record it in history taskManager.getSubtaskByID(flatRenovationSubtask3.getId()); - taskManager.updateSubtask(new Subtask(flatRenovationSubtask3.getId(), "Новое имя", - "новое описание", Status.IN_PROGRESS, flatRenovation.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(); - Subtask oldSubtask = (Subtask) subtasks.getFirst(); - assertEquals(flatRenovationSubtask3.getName(), oldSubtask.getName(), - "В истории не сохранилась старая версия эпика"); - assertEquals(flatRenovationSubtask3.getDescription(), oldSubtask.getDescription(), - "В истории не сохранилась старая версия эпика"); + System.out.println("History contents:"); + for (Task task : subtasks) { + System.out.println(task.getId() + ": " + task.getName() + " (" + task.getClass().getSimpleName() + ")"); + } + + // Check the last accessed task + 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/src/manager/HistoryManager.java b/src/manager/HistoryManager.java index b2bcde7..354efe4 100644 --- a/src/manager/HistoryManager.java +++ b/src/manager/HistoryManager.java @@ -6,5 +6,6 @@ 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..f674966 100644 --- a/src/manager/InMemoryHistoryManager.java +++ b/src/manager/InMemoryHistoryManager.java @@ -1,23 +1,125 @@ package manager; + + import model.Task; 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 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(); + } +} + +class Node { + private Task task; + private Node prev; + private Node next; + + public Node getNext() { + return next; + } + + public Node getPrev() { + return prev; + } + + public Task getTask() { + return task; + } + + public void setNext(Node next) { + this.next = next; + } + + public void setPrev(Node prev) { + this.prev = prev; + } + + public void setTask(Task task) { + this.task = task; } } \ 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/model/Task.java b/src/model/Task.java index e70661f..debf3f6 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -8,6 +8,7 @@ public class Task { private int id; private Status status; + // Constructor with parameters 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; } + // Constructor with parameters (default status NEW) public Task(String name, String description) { this.name = name; this.description = description; this.status = Status.NEW; } + // Constructor with parameters (default status NEW) public Task(int id, String name, String description) { this(id, name, description, Status.NEW); } + // Copy constructor + public Task(Task task) { + this.id = task.id; // Copy id + this.name = task.name; // Copy name + this.description = task.description; // Copy description + this.status = task.status; // Copy status + } + + // Getters and setters public String getName() { return name; } @@ -62,30 +74,21 @@ public boolean equals(Object object) { if (this == object) return true; if (object == null || getClass() != object.getClass()) return false; Task task = (Task) object; - return id == task.id; + return id == task.id; // Compare by id for equality } @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); // Hash based on id only for uniqueness } @Override public String toString() { - return "model.Task{" + + return "Task{" + "name='" + name + '\'' + ", description='" + description + '\'' + ", id=" + id + ", status=" + status + '}'; } - } \ No newline at end of file From 25f1cef9d2a184ba312f4c54bad8d82d7816dc8a Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 4 Dec 2024 18:29:04 +0300 Subject: [PATCH 02/16] commit 8 --- Test/manager/InMemoryHistoryManagerTest.java | 8 +++---- src/model/Task.java | 22 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Test/manager/InMemoryHistoryManagerTest.java b/Test/manager/InMemoryHistoryManagerTest.java index 96c8e36..f9611ec 100644 --- a/Test/manager/InMemoryHistoryManagerTest.java +++ b/Test/manager/InMemoryHistoryManagerTest.java @@ -41,13 +41,13 @@ public void getHistoryShouldReturnOldTaskAfterUpdate() { taskManager.addTask(washFloor); taskManager.getTaskByID(washFloor.getId()); - // Update the task + Task updatedTask = new Task(washFloor.getId(), "Не забыть помыть полы", "Можно и без средства", Status.IN_PROGRESS); taskManager.updateTask(updatedTask); List tasks = taskManager.getHistory(); - Task oldTask = tasks.get(tasks.size() - 1); // Get the last accessed task + Task oldTask = tasks.get(tasks.size() - 1); assertEquals(washFloor.getName(), oldTask.getName(), "В истории не сохранилась старая версия задачи"); assertEquals(washFloor.getDescription(), oldTask.getDescription(), "В истории не сохранилась старая версия задачи"); @@ -62,7 +62,7 @@ public void getHistoryShouldReturnOldSubtaskAfterUpdate() { flatRenovation.getId()); taskManager.addSubtask(flatRenovationSubtask3); - // Access the subtask to record it in history + taskManager.getSubtaskByID(flatRenovationSubtask3.getId()); // Update the subtask @@ -77,7 +77,7 @@ public void getHistoryShouldReturnOldSubtaskAfterUpdate() { System.out.println(task.getId() + ": " + task.getName() + " (" + task.getClass().getSimpleName() + ")"); } - // Check the last accessed task + Task lastAccessedTask = subtasks.get(subtasks.size() - 1); if (lastAccessedTask instanceof Subtask) { Subtask oldSubtask = (Subtask) lastAccessedTask; diff --git a/src/model/Task.java b/src/model/Task.java index debf3f6..9c2ed8a 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -8,7 +8,7 @@ public class Task { private int id; private Status status; - // Constructor with parameters + public Task(int id, String name, String description, Status status) { this.id = id; this.name = name; @@ -16,27 +16,27 @@ public Task(int id, String name, String description, Status status) { this.status = status; } - // Constructor with parameters (default status NEW) + public Task(String name, String description) { this.name = name; this.description = description; this.status = Status.NEW; } - // Constructor with parameters (default status NEW) + public Task(int id, String name, String description) { this(id, name, description, Status.NEW); } - // Copy constructor + public Task(Task task) { - this.id = task.id; // Copy id - this.name = task.name; // Copy name - this.description = task.description; // Copy description - this.status = task.status; // Copy status + this.id = task.id; + this.name = task.name; + this.description = task.description; + this.status = task.status; } - // Getters and setters + public String getName() { return name; } @@ -74,12 +74,12 @@ public boolean equals(Object object) { if (this == object) return true; if (object == null || getClass() != object.getClass()) return false; Task task = (Task) object; - return id == task.id; // Compare by id for equality + return id == task.id; } @Override public int hashCode() { - return Objects.hash(id); // Hash based on id only for uniqueness + return Objects.hash(id); } @Override From a983b45fe03371209f3488ef2498b90b87af512b Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 4 Dec 2024 18:36:51 +0300 Subject: [PATCH 03/16] commit 9 --- src/manager/TaskManager.java | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) 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(); + } From 10a757ecaedfa00667a7112d8e296ff727694821 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 4 Dec 2024 18:38:07 +0300 Subject: [PATCH 04/16] commit 10 --- src/manager/HistoryManager.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/manager/HistoryManager.java b/src/manager/HistoryManager.java index 354efe4..d06a752 100644 --- a/src/manager/HistoryManager.java +++ b/src/manager/HistoryManager.java @@ -5,7 +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 From 9b3d3d1b242c2f45726fe9feb852dba238360ae8 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 4 Dec 2024 18:42:13 +0300 Subject: [PATCH 05/16] commit 11 --- src/manager/InMemoryHistoryManager.java | 29 ------------------------- 1 file changed, 29 deletions(-) diff --git a/src/manager/InMemoryHistoryManager.java b/src/manager/InMemoryHistoryManager.java index f674966..8565d6d 100644 --- a/src/manager/InMemoryHistoryManager.java +++ b/src/manager/InMemoryHistoryManager.java @@ -94,32 +94,3 @@ public List getHistory() { } } -class Node { - private Task task; - private Node prev; - private Node next; - - public Node getNext() { - return next; - } - - public Node getPrev() { - return prev; - } - - public Task getTask() { - return task; - } - - public void setNext(Node next) { - this.next = next; - } - - public void setPrev(Node prev) { - this.prev = prev; - } - - public void setTask(Task task) { - this.task = task; - } -} \ No newline at end of file From 2c3695b813cfd70831071180c0c1ca33d85114d1 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 4 Dec 2024 18:45:24 +0300 Subject: [PATCH 06/16] commit 12 --- src/model/Subtask.java | 1 + 1 file changed, 1 insertion(+) 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; From c08dbf8eda9738673eb54016c5c4087fdf890ef7 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 4 Dec 2024 18:48:54 +0300 Subject: [PATCH 07/16] commit 13 --- src/manager/InMemoryHistoryManager.java | 33 +++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/manager/InMemoryHistoryManager.java b/src/manager/InMemoryHistoryManager.java index 8565d6d..e42534d 100644 --- a/src/manager/InMemoryHistoryManager.java +++ b/src/manager/InMemoryHistoryManager.java @@ -1,7 +1,5 @@ package manager; - - import model.Task; import java.util.*; @@ -12,6 +10,36 @@ private static class CustomLinkedList { 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); @@ -94,3 +122,4 @@ public List getHistory() { } } + From 73316fd3b12e291e73d29a1794f1780e9e4bfeda Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 4 Dec 2024 19:03:46 +0300 Subject: [PATCH 08/16] commit 14 --- {Test => test}/manager/InMemoryHistoryManagerTest.java | 0 {Test => test}/manager/InMemoryTaskManagerTest.java | 0 {Test => test}/manager/ManagersTest.java | 0 {Test => test}/model/EpicTest.java | 0 {Test => test}/model/SubtaskTest.java | 0 {Test => test}/model/TaskTest.java | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename {Test => test}/manager/InMemoryHistoryManagerTest.java (100%) rename {Test => test}/manager/InMemoryTaskManagerTest.java (100%) rename {Test => test}/manager/ManagersTest.java (100%) rename {Test => test}/model/EpicTest.java (100%) rename {Test => test}/model/SubtaskTest.java (100%) rename {Test => test}/model/TaskTest.java (100%) diff --git a/Test/manager/InMemoryHistoryManagerTest.java b/test/manager/InMemoryHistoryManagerTest.java similarity index 100% rename from Test/manager/InMemoryHistoryManagerTest.java rename to test/manager/InMemoryHistoryManagerTest.java 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 From b781730907fae80bf6205b0fbda16955f19a17e3 Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 26 Jan 2025 18:42:10 +0300 Subject: [PATCH 09/16] commit 15 --- java-kanban.iml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 @@ - + From 46194f82b0f20aa7fd19c12cb0fd68352491fe4f Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 26 Jan 2025 18:51:37 +0300 Subject: [PATCH 10/16] Add saving tasks to a file --- src/manager/InMemoryTaskManager.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index 5dc2047..27623f5 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -38,8 +38,11 @@ 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); @@ -49,7 +52,7 @@ public Subtask addSubtask(Subtask subtask) { public Task updateTask(Task updatedTask) { Task existingTask = getTaskByID(updatedTask.getId()); if (existingTask != null) { - historyManager.add(new Task(existingTask)); // Добавляем старую версию в историю + historyManager.add(new Task(existingTask)); tasks.put(updatedTask.getId(), updatedTask); } return existingTask; @@ -61,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()) { @@ -70,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; } From f0747a14b0daf0e9bdcbad06df16a16a855c9c40 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 28 Jan 2025 09:55:29 +0300 Subject: [PATCH 11/16] Add saving tasks to a file --- module-info.java | 0 src/TaskType/TaskType.java | 7 ++ src/manager/FileBackedTaskManager.java | 109 +++++++++++++++++++ src/manager/ManagerSaveException.java | 7 ++ src/manager/Node.java | 34 ++++++ test/manager/FileBackedTasksManagerTest.java | 52 +++++++++ 6 files changed, 209 insertions(+) create mode 100644 module-info.java create mode 100644 src/TaskType/TaskType.java create mode 100644 src/manager/FileBackedTaskManager.java create mode 100644 src/manager/ManagerSaveException.java create mode 100644 src/manager/Node.java create mode 100644 test/manager/FileBackedTasksManagerTest.java diff --git a/module-info.java b/module-info.java new file mode 100644 index 0000000..e69de29 diff --git a/src/TaskType/TaskType.java b/src/TaskType/TaskType.java new file mode 100644 index 0000000..779cbfb --- /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/src/manager/FileBackedTaskManager.java b/src/manager/FileBackedTaskManager.java new file mode 100644 index 0000000..fa82c08 --- /dev/null +++ b/src/manager/FileBackedTaskManager.java @@ -0,0 +1,109 @@ +package manager; + +import model.Epic; +import model.Status; +import model.Subtask; +import model.Task; + +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; + } + + + 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) { + if (task instanceof Subtask) { + return String.format("%d,SUBTASK,%s,%s,%s,%d", + task.getId(), task.getName(), task.getStatus(), task.getDescription(), ((Subtask) task).getEpicID()); + } else if (task instanceof Epic) { + return String.format("%d,EPIC,%s,%s,%s,", + task.getId(), task.getName(), task.getStatus(), task.getDescription()); + } else { + 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]; + if (type.equals("SUBTASK")) { + int epicID = Integer.parseInt(parts[5]); + return new Subtask(id, name, description, status, epicID); + } else if (type.equals("EPIC")) { + return new Epic(id, name, description); + } else { + return new Task(id, name, description, status); + } + } +} \ No newline at end of file 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/test/manager/FileBackedTasksManagerTest.java b/test/manager/FileBackedTasksManagerTest.java new file mode 100644 index 0000000..3c6a7f0 --- /dev/null +++ b/test/manager/FileBackedTasksManagerTest.java @@ -0,0 +1,52 @@ +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()); + } + } From a3c8ae82612269829b756e6b47ef4905cd7622b1 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 28 Jan 2025 09:57:29 +0300 Subject: [PATCH 12/16] Add saving tasks to a file --- src/{TaskType => tasktype}/TaskType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/{TaskType => tasktype}/TaskType.java (76%) diff --git a/src/TaskType/TaskType.java b/src/tasktype/TaskType.java similarity index 76% rename from src/TaskType/TaskType.java rename to src/tasktype/TaskType.java index 779cbfb..1405e80 100644 --- a/src/TaskType/TaskType.java +++ b/src/tasktype/TaskType.java @@ -1,4 +1,4 @@ -package TaskType; +package tasktype; public enum TaskType { TASK, From d5603a6fbedc152472ca00fe222e20cb530ea92a Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 29 Jan 2025 19:46:56 +0300 Subject: [PATCH 13/16] Error correction --- src/manager/FileBackedTaskManager.java | 79 ++++++++++++++++++++------ src/model/Epic.java | 7 +++ src/model/Subtask.java | 6 ++ src/model/Task.java | 6 +- 4 files changed, 81 insertions(+), 17 deletions(-) diff --git a/src/manager/FileBackedTaskManager.java b/src/manager/FileBackedTaskManager.java index fa82c08..8f88c20 100644 --- a/src/manager/FileBackedTaskManager.java +++ b/src/manager/FileBackedTaskManager.java @@ -4,6 +4,7 @@ import model.Status; import model.Subtask; import model.Task; +import tasktype.TaskType; import java.io.File; import java.io.IOException; @@ -38,6 +39,44 @@ public Subtask addSubtask(Subtask 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(); + } public void save() { @@ -57,16 +96,19 @@ public void save() { } } + private String toString(Task task) { - if (task instanceof Subtask) { - return String.format("%d,SUBTASK,%s,%s,%s,%d", - task.getId(), task.getName(), task.getStatus(), task.getDescription(), ((Subtask) task).getEpicID()); - } else if (task instanceof Epic) { - return String.format("%d,EPIC,%s,%s,%s,", - task.getId(), task.getName(), task.getStatus(), task.getDescription()); - } else { - return String.format("%d,TASK,%s,%s,%s,", - task.getId(), task.getName(), task.getStatus(), task.getDescription()); + 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()); } } @@ -90,6 +132,7 @@ public static FileBackedTaskManager loadFromFile(File file) { return manager; } + // In src/manager/FileBackedTaskManager.java private static Task fromString(String value) { String[] parts = value.split(","); int id = Integer.parseInt(parts[0]); @@ -97,13 +140,17 @@ private static Task fromString(String value) { String name = parts[2]; Status status = Status.valueOf(parts[3]); String description = parts[4]; - if (type.equals("SUBTASK")) { - int epicID = Integer.parseInt(parts[5]); - return new Subtask(id, name, description, status, epicID); - } else if (type.equals("EPIC")) { - return new Epic(id, name, description); - } else { - return new Task(id, name, description, status); + + 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/model/Epic.java b/src/model/Epic.java index 3817186..85e5287 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; @@ -54,4 +56,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 ad37d23..8baefa5 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; @@ -35,4 +37,8 @@ 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 9c2ed8a..12d8f79 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 { @@ -15,7 +17,9 @@ public Task(int id, String name, String description, Status status) { this.description = description; this.status = status; } - + public TaskType getType() { + return TaskType.TASK; + } public Task(String name, String description) { this.name = name; From f9a838437ccc708fcc919183ada287dfd805b68c Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 29 Jan 2025 19:49:29 +0300 Subject: [PATCH 14/16] Error correction --- src/manager/FileBackedTaskManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/manager/FileBackedTaskManager.java b/src/manager/FileBackedTaskManager.java index 8f88c20..be0037b 100644 --- a/src/manager/FileBackedTaskManager.java +++ b/src/manager/FileBackedTaskManager.java @@ -39,6 +39,7 @@ public Subtask addSubtask(Subtask subtask) { save(); return addedSubtask; } + @Override public Task updateTask(Task updatedTask) { Task existingTask = super.updateTask(updatedTask); @@ -132,7 +133,6 @@ public static FileBackedTaskManager loadFromFile(File file) { return manager; } - // In src/manager/FileBackedTaskManager.java private static Task fromString(String value) { String[] parts = value.split(","); int id = Integer.parseInt(parts[0]); From 4a37c98a91983eb8d2f9be7d951a5b66a00cd3eb Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 29 Jan 2025 19:52:33 +0300 Subject: [PATCH 15/16] Error correction --- src/model/Epic.java | 1 - src/model/Subtask.java | 1 + src/model/Task.java | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/model/Epic.java b/src/model/Epic.java index 85e5287..9e9b66e 100644 --- a/src/model/Epic.java +++ b/src/model/Epic.java @@ -10,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) { diff --git a/src/model/Subtask.java b/src/model/Subtask.java index 8baefa5..6c2feca 100644 --- a/src/model/Subtask.java +++ b/src/model/Subtask.java @@ -37,6 +37,7 @@ public boolean equals(Object o) { Subtask subtask = (Subtask) o; return epicID == subtask.epicID; } + @Override public TaskType getType() { return TaskType.SUBTASK; diff --git a/src/model/Task.java b/src/model/Task.java index 12d8f79..844cbe0 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -17,6 +17,7 @@ public Task(int id, String name, String description, Status status) { this.description = description; this.status = status; } + public TaskType getType() { return TaskType.TASK; } From 2e78efba9cd9cbeaa0d3816045dbda9b19819c0a Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 31 Jan 2025 13:41:21 +0300 Subject: [PATCH 16/16] implemented methods with conservation --- src/manager/FileBackedTaskManager.java | 18 +++++++++++++++++- test/manager/FileBackedTasksManagerTest.java | 14 ++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/manager/FileBackedTaskManager.java b/src/manager/FileBackedTaskManager.java index be0037b..8fa5959 100644 --- a/src/manager/FileBackedTaskManager.java +++ b/src/manager/FileBackedTaskManager.java @@ -79,6 +79,23 @@ public void deleteSubtaskByID(int 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)) { @@ -97,7 +114,6 @@ public void save() { } } - private String toString(Task task) { switch (task.getType()) { case SUBTASK: diff --git a/test/manager/FileBackedTasksManagerTest.java b/test/manager/FileBackedTasksManagerTest.java index 3c6a7f0..92aef08 100644 --- a/test/manager/FileBackedTasksManagerTest.java +++ b/test/manager/FileBackedTasksManagerTest.java @@ -49,4 +49,18 @@ public void saveAndLoadMultipleTasks() throws IOException { 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(), "Задача не была удалена из файла."); } +}