From 0087d5b467ef8505f9ccfaa8849c8304f3520ee6 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 4 Dec 2024 18:15:30 +0300 Subject: [PATCH 01/27] 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/27] 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/27] 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/27] 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/27] 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/27] 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/27] 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/27] 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/27] 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/27] 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/27] 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/27] 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/27] 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/27] 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/27] 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/27] 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(), "Задача не была удалена из файла."); } +} From ac4a7ed14eef781b70d32816dde97816228477fb Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 17 Feb 2025 23:34:50 +0300 Subject: [PATCH 17/27] sprint 8 --- src/Main.java | 63 ++++++++++---- src/manager/FileBackedTaskManager.java | 40 +++++---- src/manager/InMemoryHistoryManager.java | 6 +- src/manager/InMemoryTaskManager.java | 64 +++++++------- src/manager/TaskManager.java | 7 +- src/model/Epic.java | 66 ++++++++++++-- src/model/Subtask.java | 22 ++++- src/model/Task.java | 111 ++++++++++++++++-------- 8 files changed, 264 insertions(+), 115 deletions(-) diff --git a/src/Main.java b/src/Main.java index 23497af..a8385e0 100644 --- a/src/Main.java +++ b/src/Main.java @@ -5,9 +5,14 @@ import model.Subtask; import model.Task; +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + public class Main { private static final TaskManager taskManager = Managers.getDefault(); + private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); public static void main(String[] args) { addTasks(); @@ -16,22 +21,27 @@ public static void main(String[] args) { } private static void addTasks() { - Task packBoxes = new Task("Упаковать вещи", "В коробки и мешки"); + LocalDateTime now = LocalDateTime.now(); + + Task packBoxes = new Task("Упаковать вещи", "В коробки и мешки", Duration.ofMinutes(30), now); taskManager.addTask(packBoxes); - Task packBoxesToUpdate = new Task(packBoxes.getId(), "Упаковать вещи быстро", "В коробки и мешки", - Status.IN_PROGRESS); + Task packBoxesToUpdate = new Task(packBoxes.getId(), "Упаковать вещи быстро", "В коробки и мешки", + Status.IN_PROGRESS, Duration.ofMinutes(20), now.plusMinutes(30)); taskManager.updateTask(packBoxesToUpdate); - taskManager.addTask(new Task("Придумать список дел после перезда", "Список в заметках")); + + Task createToDoList = new Task("Придумать список дел после перезда", "Список в заметках", Duration.ofMinutes(15), now.plusMinutes(50)); + taskManager.addTask(createToDoList); Epic moving = new Epic(10, "Переезд", "Нужно успеть до конца месяца"); taskManager.addEpic(moving); - Subtask packKitchen = new Subtask("Упаковать кухню", "В отдельные коробки", - moving.getId()); - Subtask packBedroom = new Subtask("Упаковать спальню", "В большие коробки", - moving.getId()); + + Subtask packKitchen = new Subtask("Упаковать кухню", "В отдельные коробки", moving.getId(), Duration.ofMinutes(30), now.plusMinutes(10)); + Subtask packBedroom = new Subtask("Упаковать спальню", "В большие коробки", moving.getId(), Duration.ofMinutes(45), now.plusMinutes(40)); + taskManager.addSubtask(packKitchen); taskManager.addSubtask(packBedroom); + packBedroom.setStatus(Status.DONE); taskManager.updateSubtask(packBedroom); } @@ -39,23 +49,41 @@ private static void addTasks() { private static void printAllTasks() { System.out.println("Задачи:"); for (Task task : taskManager.getTasks()) { - System.out.println(task); + System.out.println(formatTask(task)); } + System.out.println("Эпики:"); for (Epic epic : taskManager.getEpics()) { - System.out.println(epic); - - for (Task task : taskManager.getEpicSubtasks(epic)) { - System.out.println("--> " + task); + System.out.println(formatEpic(epic)); + for (Subtask subtask : taskManager.getEpicSubtasks(epic)) { + System.out.println("--> " + formatSubtask(subtask)); } } System.out.println("Подзадачи:"); - for (Task subtask : taskManager.getSubtasks()) { - System.out.println(subtask); + for (Subtask subtask : taskManager.getSubtasks()) { + System.out.println(formatSubtask(subtask)); } } + private static String formatTask(Task task) { + String startTime = task.getStartTime() != null ? task.getStartTime().format(formatter) : "не задано"; + return String.format("Task{id=%d, name='%s', description='%s', status=%s, duration=%s, startTime=%s}", + task.getId(), task.getName(), task.getDescription(), task.getStatus(), task.getDuration(), startTime); + } + + private static String formatSubtask(Subtask subtask) { + String startTime = subtask.getStartTime() != null ? subtask.getStartTime().format(formatter) : "не задано"; + return String.format("Subtask{name='%s', description='%s', id=%d, epicID=%d, status=%s, duration=%s, startTime=%s}", + subtask.getName(), subtask.getDescription(), subtask.getId(), subtask.getEpicID(), subtask.getStatus(), subtask.getDuration(), startTime); + } + + private static String formatEpic(Epic epic) { + String startTime = epic.getStartTime() != null ? epic.getStartTime().format(formatter) : "не задано"; + return String.format("Epic{name='%s', description='%s', id=%d, subtaskList.size=%d, status=%s, duration=%s, startTime=%s}", + epic.getName(), epic.getDescription(), epic.getId(), epic.getSubtaskList().size(), epic.getStatus(), epic.getDuration(), startTime); + } + private static void printViewHistory() { taskManager.getTaskByID(1); taskManager.getTaskByID(2); @@ -63,16 +91,15 @@ private static void printViewHistory() { taskManager.getTaskByID(1); taskManager.getSubtaskByID(4); taskManager.getSubtaskByID(5); - taskManager.getSubtaskByID(6); taskManager.getEpicByID(3); taskManager.getSubtaskByID(4); taskManager.getTaskByID(2); - taskManager.getSubtaskByID(6); + taskManager.getSubtaskByID(5); System.out.println(); System.out.println("История просмотров:"); for (Task task : taskManager.getHistory()) { - System.out.println(task); + System.out.println(formatTask(task)); } } } \ No newline at end of file diff --git a/src/manager/FileBackedTaskManager.java b/src/manager/FileBackedTaskManager.java index 8fa5959..f151485 100644 --- a/src/manager/FileBackedTaskManager.java +++ b/src/manager/FileBackedTaskManager.java @@ -10,6 +10,8 @@ import java.io.IOException; import java.io.PrintWriter; import java.nio.file.Files; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.List; public class FileBackedTaskManager extends InMemoryTaskManager { @@ -99,7 +101,7 @@ public void deleteSubtasks() { public void save() { try (PrintWriter writer = new PrintWriter(file)) { - writer.println("id,type,name,status,description,epic"); + writer.println("id,type,name,status,description,epic,duration,startTime"); for (Task task : getTasks()) { writer.println(toString(task)); } @@ -115,18 +117,23 @@ public void save() { } 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()); + StringBuilder sb = new StringBuilder(); + sb.append(task.getId()).append(",") + .append(task.getType()).append(",") + .append(task.getName()).append(",") + .append(task.getStatus()).append(",") + .append(task.getDescription()).append(","); + + if (task instanceof Subtask) { + sb.append(((Subtask) task).getEpicID()).append(","); + } else { + sb.append(","); } + + sb.append(task.getDuration() != null ? task.getDuration().toMinutes() : 0).append(",") + .append(task.getStartTime() != null ? task.getStartTime() : ""); + + return sb.toString(); } public static FileBackedTaskManager loadFromFile(File file) { @@ -158,15 +165,18 @@ private static Task fromString(String value) { String description = parts[4]; TaskType taskType = TaskType.valueOf(type); + Duration duration = Duration.ofMinutes(Long.parseLong(parts[6])); + LocalDateTime startTime = parts.length > 7 && !parts[7].isEmpty() ? LocalDateTime.parse(parts[7]) : null; + switch (taskType) { case SUBTASK: int epicID = Integer.parseInt(parts[5]); - return new Subtask(id, name, description, status, epicID); + return new Subtask(id, name, description, status, duration, startTime, epicID); case EPIC: - return new Epic(id, name, description); + return new Epic(id, name, description, status, duration, startTime); case TASK: default: - return new Task(id, name, description, status); + return new Task(id, name, description, status, duration, startTime); } } } \ No newline at end of file diff --git a/src/manager/InMemoryHistoryManager.java b/src/manager/InMemoryHistoryManager.java index e42534d..168ec0d 100644 --- a/src/manager/InMemoryHistoryManager.java +++ b/src/manager/InMemoryHistoryManager.java @@ -103,19 +103,19 @@ private Node getNode(int id) { private final CustomLinkedList list = new CustomLinkedList(); - // Добавление нового просмотра задачи в историю + @Override public void add(Task task) { list.linkLast(task); } - // Удаление просмотра из истории + @Override public void remove(int id) { list.removeNode(list.getNode(id)); } - // Получение истории просмотров + @Override public List getHistory() { return list.getTasks(); diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index 27623f5..8b7c123 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -1,15 +1,13 @@ package manager; - import model.Epic; import model.Status; import model.Subtask; import model.Task; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.*; public class InMemoryTaskManager implements TaskManager { private final Map tasks = new HashMap<>(); @@ -24,6 +22,7 @@ public InMemoryTaskManager() { @Override public Task addTask(Task task) { + validateTask(task); task.setId(getNextID()); tasks.put(task.getId(), task); return task; @@ -42,6 +41,7 @@ public Subtask addSubtask(Subtask subtask) { if (epic == null) { throw new IllegalArgumentException("Epic with ID " + subtask.getEpicID() + " does not exist."); } + validateTask(subtask); subtask.setId(getNextID()); epic.addSubtask(subtask); subtasks.put(subtask.getId(), subtask); @@ -49,7 +49,9 @@ public Subtask addSubtask(Subtask subtask) { return subtask; } + @Override public Task updateTask(Task updatedTask) { + validateTask(updatedTask); Task existingTask = getTaskByID(updatedTask.getId()); if (existingTask != null) { historyManager.add(new Task(existingTask)); @@ -64,23 +66,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()) { - for (Subtask subtask : oldEpicSubtaskList) { - subtasks.remove(subtask.getId()); - } - } - epics.replace(epicID, epic); - - ArrayList newEpicSubtaskList = epic.getSubtaskList(); - if (!newEpicSubtaskList.isEmpty()) { - for (Subtask subtask : newEpicSubtaskList) { - subtasks.put(subtask.getId(), subtask); - } - } - + epics.put(epicID, epic); updateEpicStatus(epic); return epic; } @@ -93,12 +79,10 @@ public Subtask updateSubtask(Subtask subtask) { } int epicID = subtask.getEpicID(); Subtask oldSubtask = subtasks.get(subtaskID); - subtasks.replace(subtaskID, subtask); + subtasks.put(subtaskID, subtask); Epic epic = epics.get(epicID); - ArrayList subtaskList = epic.getSubtaskList(); - subtaskList.remove(oldSubtask); - subtaskList.add(subtask); - epic.setSubtaskList(subtaskList); + epic.getSubtaskList().remove(oldSubtask); + epic.getSubtaskList().add(subtask); updateEpicStatus(epic); return subtask; } @@ -190,12 +174,9 @@ public void deleteSubtaskByID(int id) { 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); + epic.getSubtaskList().remove(subtask); updateEpicStatus(epic); } } @@ -205,6 +186,15 @@ public List getHistory() { return historyManager.getHistory(); } + @Override + public List getPrioritizedTasks() { + List prioritizedTasks = new ArrayList<>(); + prioritizedTasks.addAll(tasks.values()); + prioritizedTasks.addAll(subtasks.values()); + prioritizedTasks.sort(Comparator.comparing(Task::getStartTime, Comparator.nullsLast(Comparator.naturalOrder()))); + return prioritizedTasks; + } + private int getNextID() { return nextID++; } @@ -230,4 +220,14 @@ private void updateEpicStatus(Epic epic) { epic.setStatus(Status.IN_PROGRESS); } } -} + + void validateTask(Task task) { + if (task.getName() == null || task.getName().isEmpty()) { + throw new IllegalArgumentException("Task name cannot be null or empty."); + } + if (task.getDescription() == null) { + throw new IllegalArgumentException("Task description cannot be null."); + } + // Additional validation can be added here + } +} \ No newline at end of file diff --git a/src/manager/TaskManager.java b/src/manager/TaskManager.java index 286c18c..f033444 100644 --- a/src/manager/TaskManager.java +++ b/src/manager/TaskManager.java @@ -1,6 +1,5 @@ package manager; - import model.Epic; import model.Subtask; import model.Task; @@ -9,14 +8,13 @@ import java.util.List; public interface TaskManager { - Task addTask(Task task); Epic addEpic(Epic epic); Subtask addSubtask(Subtask subtask); - Task updateTask(Task task); + Task updateTask(Task updatedTask); Epic updateEpic(Epic epic); @@ -50,4 +48,5 @@ public interface TaskManager { List getHistory(); -} + List getPrioritizedTasks(); +} \ No newline at end of file diff --git a/src/model/Epic.java b/src/model/Epic.java index 9e9b66e..99acdd0 100644 --- a/src/model/Epic.java +++ b/src/model/Epic.java @@ -2,22 +2,36 @@ import tasktype.TaskType; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Objects; public class Epic extends Task { private ArrayList subtaskList = new ArrayList<>(); + private Duration duration; + private LocalDateTime startTime; + private LocalDateTime endTime; public Epic(int id, String name, String description) { super(id, name, description); } + public Epic(int id, String name, String description, Status status, Duration duration, LocalDateTime startTime) { + super(id, name, description, status, duration, startTime); + } + + public Epic(int id, String name, String description, Duration duration, LocalDateTime startTime) { + super(id, name, description, Status.NEW, duration, startTime); + } public void addSubtask(Subtask subtask) { subtaskList.add(subtask); + updateEpicDetails(); } public void clearSubtasks() { subtaskList.clear(); + updateEpicDetails(); } public ArrayList getSubtaskList() { @@ -26,6 +40,47 @@ public ArrayList getSubtaskList() { public void setSubtaskList(ArrayList subtaskList) { this.subtaskList = subtaskList; + updateEpicDetails(); + } + + private void updateEpicDetails() { + this.duration = Duration.ZERO; + this.startTime = null; + this.endTime = null; + + if (!subtaskList.isEmpty()) { + LocalDateTime earliestStart = null; + LocalDateTime latestEnd = null; + + for (Subtask subtask : subtaskList) { + if (subtask.getStartTime() != null) { + if (earliestStart == null || subtask.getStartTime().isBefore(earliestStart)) { + earliestStart = subtask.getStartTime(); + } + if (latestEnd == null || subtask.getEndTime().isAfter(latestEnd)) { + latestEnd = subtask.getEndTime(); + } + } + if (subtask.getDuration() != null) { + this.duration = this.duration.plus(subtask.getDuration()); + } + } + + this.startTime = earliestStart; + this.endTime = latestEnd; + } + } + + public Duration getDuration() { + return duration; + } + + public LocalDateTime getStartTime() { + return startTime; + } + + public LocalDateTime getEndTime() { + return endTime; } @Override @@ -36,17 +91,16 @@ public String toString() { ", id=" + getId() + ", subtaskList.size=" + subtaskList.size() + ", status=" + getStatus() + + ", duration=" + duration + + ", startTime=" + startTime + + ", endTime=" + endTime + '}'; } @Override public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; Epic other = (Epic) obj; return getId() == other.getId(); } diff --git a/src/model/Subtask.java b/src/model/Subtask.java index 6c2feca..8d689ea 100644 --- a/src/model/Subtask.java +++ b/src/model/Subtask.java @@ -2,6 +2,10 @@ import tasktype.TaskType; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.Objects; + public class Subtask extends Task { private final int epicID; @@ -10,8 +14,13 @@ public Subtask(String name, String description, int epicID) { this.epicID = epicID; } - public Subtask(int id, String name, String description, Status status, int epicID) { - super(id, name, description, status); + public Subtask(int id, String name, String description, Status status, Duration duration, LocalDateTime startTime, int epicID) { + super(id, name, description, status, duration, startTime); + this.epicID = epicID; + } + + public Subtask(String name, String description, int epicID, Duration duration, LocalDateTime startTime) { + super(name, description, duration, startTime); this.epicID = epicID; } @@ -21,12 +30,14 @@ public int getEpicID() { @Override public String toString() { - return "model.Subtask{" + + return "Subtask{" + "name='" + getName() + '\'' + ", description='" + getDescription() + '\'' + ", id=" + getId() + ", epicID=" + epicID + ", status=" + getStatus() + + ", duration=" + getDuration() + + ", startTime=" + getStartTime() + '}'; } @@ -38,6 +49,11 @@ public boolean equals(Object o) { return epicID == subtask.epicID; } + @Override + public int hashCode() { + return Objects.hash(epicID); + } + @Override public TaskType getType() { return TaskType.SUBTASK; diff --git a/src/model/Task.java b/src/model/Task.java index 844cbe0..fce169f 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -2,45 +2,90 @@ import tasktype.TaskType; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.Objects; public class Task { + private int id; private String name; private String description; - private int id; private Status status; + private Duration duration; + private LocalDateTime startTime; + public Task(String name, String description) { + this.name = name; + this.description = description; + this.status = Status.NEW; + } - public Task(int id, String name, String description, Status status) { + public Task(Task otherTask) { + this.id = otherTask.getId(); + this.name = otherTask.getName(); + this.description = otherTask.getDescription(); + this.status = otherTask.getStatus(); + this.duration = otherTask.getDuration(); + this.startTime = otherTask.getStartTime(); + } + public Task(String name, String description, Duration duration, LocalDateTime startTime) { + this.name = name; + this.description = description; + this.status = Status.NEW; + this.duration = duration; + this.startTime = startTime; + } + + public Task(int id, String name, String description) { this.id = id; this.name = name; this.description = description; - this.status = status; + this.status = Status.NEW; } - public TaskType getType() { - return TaskType.TASK; + public Task(int id, String name, String description, Status status) { + this.id = id; + this.name = name; + this.description = description; + this.status = status; } - public Task(String name, String description) { + public Task(int id, String name, String description, Status status, Duration duration, LocalDateTime startTime) { + this.id = id; this.name = name; this.description = description; - this.status = Status.NEW; + this.status = status; + this.duration = duration; + this.startTime = startTime; } + public LocalDateTime getEndTime() { + return startTime != null && duration != null ? startTime.plus(duration) : null; + } - public Task(int id, String name, String description) { - this(id, name, description, Status.NEW); + public Duration getDuration() { + return duration; + } + + public void setDuration(Duration duration) { + this.duration = duration; } + public LocalDateTime getStartTime() { + return startTime; + } + + public void setStartTime(LocalDateTime startTime) { + this.startTime = startTime; + } - public Task(Task task) { - this.id = task.id; - this.name = task.name; - this.description = task.description; - this.status = task.status; + public int getId() { + return id; } + public void setId(int id) { + this.id = id; + } public String getName() { return name; @@ -58,14 +103,6 @@ public void setDescription(String description) { this.description = description; } - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - public Status getStatus() { return status; } @@ -75,10 +112,22 @@ public void setStatus(Status status) { } @Override - public boolean equals(Object object) { - if (this == object) return true; - if (object == null || getClass() != object.getClass()) return false; - Task task = (Task) object; + public String toString() { + return "Task{" + + "id=" + id + + ", name='" + name + '\'' + + ", description='" + description + '\'' + + ", status=" + status + + ", duration=" + duration + + ", startTime=" + startTime + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Task task = (Task) o; return id == task.id; } @@ -87,13 +136,7 @@ public int hashCode() { return Objects.hash(id); } - @Override - public String toString() { - return "Task{" + - "name='" + name + '\'' + - ", description='" + description + '\'' + - ", id=" + id + - ", status=" + status + - '}'; + public TaskType getType() { + return TaskType.TASK; } } \ No newline at end of file From ed0d0c1b196238dec96851e5c819f78250a21fad Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 18 Feb 2025 01:31:13 +0300 Subject: [PATCH 18/27] solution time and duration --- src/Main.java | 31 ++-- src/manager/FileBackedTaskManager.java | 27 ++- src/manager/InMemoryTaskManager.java | 37 +++- src/model/Task.java | 1 + test/manager/FileBackedTaskManagerTest.java | 107 +++++++++++ test/manager/FileBackedTasksManagerTest.java | 66 ------- test/manager/InMemoryHistoryManagerTest.java | 186 ++++++------------- test/manager/InMemoryTaskManagerTest.java | 160 ++++------------ test/model/SubtaskTest.java | 23 ++- 9 files changed, 274 insertions(+), 364 deletions(-) create mode 100644 test/manager/FileBackedTaskManagerTest.java delete mode 100644 test/manager/FileBackedTasksManagerTest.java diff --git a/src/Main.java b/src/Main.java index a8385e0..6031978 100644 --- a/src/Main.java +++ b/src/Main.java @@ -26,44 +26,39 @@ private static void addTasks() { Task packBoxes = new Task("Упаковать вещи", "В коробки и мешки", Duration.ofMinutes(30), now); taskManager.addTask(packBoxes); - Task packBoxesToUpdate = new Task(packBoxes.getId(), "Упаковать вещи быстро", "В коробки и мешки", - Status.IN_PROGRESS, Duration.ofMinutes(20), now.plusMinutes(30)); - taskManager.updateTask(packBoxesToUpdate); - Task createToDoList = new Task("Придумать список дел после перезда", "Список в заметках", Duration.ofMinutes(15), now.plusMinutes(50)); taskManager.addTask(createToDoList); Epic moving = new Epic(10, "Переезд", "Нужно успеть до конца месяца"); taskManager.addEpic(moving); + Subtask packKitchen = new Subtask("Упаковать кухню", "В отдельные коробки", moving.getId(), Duration.ofMinutes(30), now.plusMinutes(10)); - Subtask packBedroom = new Subtask("Упаковать спальню", "В большие коробки", moving.getId(), Duration.ofMinutes(45), now.plusMinutes(40)); + Subtask packBedroom = new Subtask("Упаковать спальню", "В большие коробки", moving.getId(), Duration.ofMinutes(45), now.plusMinutes(50)); // Adjusted start time taskManager.addSubtask(packKitchen); taskManager.addSubtask(packBedroom); - packBedroom.setStatus(Status.DONE); - taskManager.updateSubtask(packBedroom); } private static void printAllTasks() { System.out.println("Задачи:"); - for (Task task : taskManager.getTasks()) { - System.out.println(formatTask(task)); - } + taskManager.getTasks().stream() + .map(Main::formatTask) + .forEach(System.out::println); System.out.println("Эпики:"); - for (Epic epic : taskManager.getEpics()) { + taskManager.getEpics().forEach(epic -> { System.out.println(formatEpic(epic)); - for (Subtask subtask : taskManager.getEpicSubtasks(epic)) { - System.out.println("--> " + formatSubtask(subtask)); - } - } + taskManager.getEpicSubtasks(epic).stream() + .map(Main::formatSubtask) + .forEach(subtask -> System.out.println("--> " + subtask)); + }); System.out.println("Подзадачи:"); - for (Subtask subtask : taskManager.getSubtasks()) { - System.out.println(formatSubtask(subtask)); - } + taskManager.getSubtasks().stream() + .map(Main::formatSubtask) + .forEach(System.out::println); } private static String formatTask(Task task) { diff --git a/src/manager/FileBackedTaskManager.java b/src/manager/FileBackedTaskManager.java index f151485..a7e95de 100644 --- a/src/manager/FileBackedTaskManager.java +++ b/src/manager/FileBackedTaskManager.java @@ -118,11 +118,7 @@ public void save() { private String toString(Task task) { StringBuilder sb = new StringBuilder(); - sb.append(task.getId()).append(",") - .append(task.getType()).append(",") - .append(task.getName()).append(",") - .append(task.getStatus()).append(",") - .append(task.getDescription()).append(","); + sb.append(task.getId()).append(",").append(task.getType()).append(",").append(task.getName()).append(",").append(task.getStatus()).append(",").append(task.getDescription()).append(","); if (task instanceof Subtask) { sb.append(((Subtask) task).getEpicID()).append(","); @@ -130,8 +126,7 @@ private String toString(Task task) { sb.append(","); } - sb.append(task.getDuration() != null ? task.getDuration().toMinutes() : 0).append(",") - .append(task.getStartTime() != null ? task.getStartTime() : ""); + sb.append(task.getDuration() != null ? task.getDuration().toMinutes() : 0).append(",").append(task.getStartTime() != null ? task.getStartTime() : ""); return sb.toString(); } @@ -140,14 +135,16 @@ 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); + if (lines.size() > 1) { + 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) { diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index 8b7c123..526410b 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -5,7 +5,6 @@ import model.Subtask; import model.Task; -import java.time.Duration; import java.time.LocalDateTime; import java.util.*; @@ -19,10 +18,16 @@ public class InMemoryTaskManager implements TaskManager { public InMemoryTaskManager() { this.historyManager = Managers.getDefaultHistory(); } + private int getNextID() { + return nextID++; + } @Override public Task addTask(Task task) { validateTask(task); + if (isOverlapping(task)) { + throw new IllegalArgumentException("Task overlaps with existing task"); + } task.setId(getNextID()); tasks.put(task.getId(), task); return task; @@ -42,6 +47,9 @@ public Subtask addSubtask(Subtask subtask) { throw new IllegalArgumentException("Epic with ID " + subtask.getEpicID() + " does not exist."); } validateTask(subtask); + if (isOverlapping(subtask)) { + throw new IllegalArgumentException("Subtask overlaps with existing task"); + } subtask.setId(getNextID()); epic.addSubtask(subtask); subtasks.put(subtask.getId(), subtask); @@ -188,15 +196,30 @@ public List getHistory() { @Override public List getPrioritizedTasks() { + PriorityQueue priorityQueue = new PriorityQueue<>(Comparator.comparing(Task::getStartTime, Comparator.nullsLast(Comparator.naturalOrder()))); + + priorityQueue.addAll(tasks.values()); + priorityQueue.addAll(subtasks.values()); + List prioritizedTasks = new ArrayList<>(); - prioritizedTasks.addAll(tasks.values()); - prioritizedTasks.addAll(subtasks.values()); - prioritizedTasks.sort(Comparator.comparing(Task::getStartTime, Comparator.nullsLast(Comparator.naturalOrder()))); + while (!priorityQueue.isEmpty()) { + prioritizedTasks.add(priorityQueue.poll()); + } + return prioritizedTasks; } - private int getNextID() { - return nextID++; + private boolean isOverlapping(Task newTask) { + return tasks.values().stream() + .anyMatch(existingTask -> isOverlapping(existingTask, newTask)); + } + + private boolean isOverlapping(Task t1, Task t2) { + if (t1.getStartTime() == null || t2.getStartTime() == null) { + return false; + } + return t1.getStartTime().isBefore(t2.getStartTime().plus(t2.getDuration())) && + t2.getStartTime().isBefore(t1.getStartTime().plus(t1.getDuration())); } private void updateEpicStatus(Epic epic) { @@ -228,6 +251,6 @@ void validateTask(Task task) { if (task.getDescription() == null) { throw new IllegalArgumentException("Task description cannot be null."); } - // Additional validation can be added here + } } \ No newline at end of file diff --git a/src/model/Task.java b/src/model/Task.java index fce169f..8df30f7 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -59,6 +59,7 @@ public Task(int id, String name, String description, Status status, Duration dur this.startTime = startTime; } + public LocalDateTime getEndTime() { return startTime != null && duration != null ? startTime.plus(duration) : null; } diff --git a/test/manager/FileBackedTaskManagerTest.java b/test/manager/FileBackedTaskManagerTest.java new file mode 100644 index 0000000..1612f83 --- /dev/null +++ b/test/manager/FileBackedTaskManagerTest.java @@ -0,0 +1,107 @@ +package manager; + +import manager.FileBackedTaskManager; +import manager.TaskManagerTest; +import model.Epic; +import model.Status; +import model.Subtask; +import model.Task; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class FileBackedTaskManagerTest extends TaskManagerTest { + private File file; + + @BeforeEach + public void setUp() { + file = new File("test_tasks.csv"); + taskManager = new FileBackedTaskManager(file); + } + + @AfterEach + public void tearDown() { + file.delete(); + } + + @Override + protected FileBackedTaskManager createTaskManager() { + return new FileBackedTaskManager(file); + } + + @Test + public void testSaveAndLoadFromFile() throws IOException { + LocalDateTime now = LocalDateTime.now(); + + Task task = new Task("Test Task", "Description", Duration.ofMinutes(30), now); + taskManager.addTask(task); + + Epic epic = new Epic(10, "Test Epic", "Epic Description"); + taskManager.addEpic(epic); + + // Ensure the subtask starts after the task ends + Subtask subtask = new Subtask("Test Subtask", "Subtask Description", epic.getId(), Duration.ofMinutes(30), now.plusMinutes(40)); + taskManager.addSubtask(subtask); + + FileBackedTaskManager loadedManager = FileBackedTaskManager.loadFromFile(file); + + assertEquals(task, loadedManager.getTaskByID(task.getId())); + assertEquals(epic, loadedManager.getEpicByID(epic.getId())); + assertEquals(subtask, loadedManager.getSubtaskByID(subtask.getId())); + } + + @Test + public void testAddTaskAndCheckFileContent() throws IOException { + Task task = new Task("Test Task", "Description", Duration.ofMinutes(30), LocalDateTime.now()); + taskManager.addTask(task); + + + List lines = Files.readAllLines(file.toPath()); + assertEquals(2, lines.size()); + assertTrue(lines.get(1).contains("Test Task")); + } + + @Test + public void testDeleteTaskAndCheckFileContent() throws IOException { + Task task = new Task("Test Task", "Description", Duration.ofMinutes(30), LocalDateTime.now()); + taskManager.addTask(task); + taskManager.deleteTaskByID(task.getId()); + + + List lines = Files.readAllLines(file.toPath()); + assertEquals(1, lines.size()); + } + + @Test + public void testUpdateTaskAndCheckFileContent() throws IOException { + Task task = new Task("Test Task", "Description", Duration.ofMinutes(30), LocalDateTime.now()); + taskManager.addTask(task); + + task.setDescription("Updated Description"); + taskManager.updateTask(task); + + + List lines = Files.readAllLines(file.toPath()); + assertTrue(lines.get(1).contains("Updated Description")); + } + + @Test + public void testLoadFromFileWithEmptyFile() throws IOException { + + file.createNewFile(); + + FileBackedTaskManager loadedManager = FileBackedTaskManager.loadFromFile(file); + assertTrue(loadedManager.getTasks().isEmpty()); + assertTrue(loadedManager.getEpics().isEmpty()); + assertTrue(loadedManager.getSubtasks().isEmpty()); + } +} diff --git a/test/manager/FileBackedTasksManagerTest.java b/test/manager/FileBackedTasksManagerTest.java deleted file mode 100644 index 92aef08..0000000 --- a/test/manager/FileBackedTasksManagerTest.java +++ /dev/null @@ -1,66 +0,0 @@ -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 index f9611ec..feb6e4b 100644 --- a/test/manager/InMemoryHistoryManagerTest.java +++ b/test/manager/InMemoryHistoryManagerTest.java @@ -1,158 +1,88 @@ package manager; + +import org.junit.jupiter.api.Test; 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.time.Duration; +import java.time.LocalDateTime; import java.util.List; +import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.*; - -class InMemoryHistoryManagerTest { - - private static TaskManager taskManager; - - @BeforeEach - public void beforeEach() { - taskManager = Managers.getDefault(); - } +public class InMemoryHistoryManagerTest { @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(), "Неверное количество элементов в истории "); + public void testAdd() { + InMemoryHistoryManager historyManager = new InMemoryHistoryManager(); + Task task = new Task(1, "Task1", "Description1", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); + historyManager.add(task); + List history = historyManager.getHistory(); + assertEquals(1, history.size()); + assertEquals(task, history.get(0)); } @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(), - "В истории не сохранилась старая версия задачи"); + public void testRemove() { + InMemoryHistoryManager historyManager = new InMemoryHistoryManager(); + Task task = new Task(1, "Task1", "Description1", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); + historyManager.add(task); + historyManager.remove(1); + List history = historyManager.getHistory(); + assertEquals(0, history.size()); } - @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"); - } + public void testGetHistory() { + InMemoryHistoryManager historyManager = new InMemoryHistoryManager(); + Task task1 = new Task(1, "Task1", "Description1", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); + Task task2 = new Task(2, "Task2", "Description2", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); + historyManager.add(task1); + historyManager.add(task2); + List history = historyManager.getHistory(); + assertEquals(2, history.size()); + assertEquals(task1, history.get(0)); + assertEquals(task2, history.get(1)); } @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 подзадачи"); + public void testGetHistoryEmpty() { + InMemoryHistoryManager historyManager = new InMemoryHistoryManager(); + List history = historyManager.getHistory(); + assertEquals(0, history.size()); } @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 подзадачи"); + public void testRemoveNonExisting() { + InMemoryHistoryManager historyManager = new InMemoryHistoryManager(); + historyManager.remove(1); + List history = historyManager.getHistory(); + assertEquals(0, history.size()); } - @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)); + public void testAddMultiple() { + InMemoryHistoryManager historyManager = new InMemoryHistoryManager(); + Task task1 = new Task(1, "Task1", "Description1", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); + Task task2 = new Task(2, "Task2", "Description2", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); + Task task3 = new Task(3, "Task3", "Description3", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); + historyManager.add(task1); + historyManager.add(task2); + historyManager.add(task3); + List history = historyManager.getHistory(); + assertEquals(3, history.size()); + assertEquals(task1, history.get(0)); + assertEquals(task2, history.get(1)); + assertEquals(task3, history.get(2)); } @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(); + public void testAddEpic() { + InMemoryHistoryManager historyManager = new InMemoryHistoryManager(); + Epic epic = new Epic(1, "Epic1", "Description1", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); + historyManager.add(epic); + List history = historyManager.getHistory(); assertEquals(1, history.size()); - assertEquals(task, history.get(0)); // Проверяем, что старая версия добавлена в историю + assertEquals(epic, history.get(0)); } } \ No newline at end of file diff --git a/test/manager/InMemoryTaskManagerTest.java b/test/manager/InMemoryTaskManagerTest.java index 4cbfa5e..a633fe9 100644 --- a/test/manager/InMemoryTaskManagerTest.java +++ b/test/manager/InMemoryTaskManagerTest.java @@ -1,159 +1,67 @@ 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 InMemoryTaskManagerTest { - - private static TaskManager taskManager; + private InMemoryTaskManager taskManager; @BeforeEach - public void beforeEach() { - taskManager = Managers.getDefault(); + void setUp() { + taskManager = new InMemoryTaskManager(); } @Test - void addNewTask() { - //проверяем, что InMemoryTaskManager добавляет задачи и может найти их по id; - final Task task = taskManager.addTask(new Task("Test addNewTask", "Test addNewTask description")); - final Task savedTask = taskManager.getTaskByID(task.getId()); - assertNotNull(savedTask, "Задача не найдена."); - assertEquals(task, savedTask, "Задачи не совпадают."); - - final List tasks = taskManager.getTasks(); - assertNotNull(tasks, "Задачи не возвращаются."); - assertEquals(1, tasks.size(), "Неверное количество задач."); - assertEquals(task, tasks.getFirst(), "Задачи не совпадают."); + void testAddTask() { + Task task = new Task("Test Task", "This is a test task"); + Task addedTask = taskManager.addTask(task); + assertNotNull(addedTask); + assertEquals("Test Task", addedTask.getName()); + assertEquals(1, addedTask.getId()); } @Test - void addNewEpicAndSubtasks() { - //проверяем, что InMemoryTaskManager добавляет эпики и подзадачи и может найти их по id; - final Epic flatRenovation = taskManager.addEpic(new Epic(1, "Сделать ремонт", "Нужно успеть за отпуск")); - final Subtask flatRenovationSubtask1 = taskManager.addSubtask(new Subtask("Поклеить обои", - "Обязательно светлые!", flatRenovation.getId())); - final Subtask flatRenovationSubtask2 = taskManager.addSubtask(new Subtask("Установить новую технику", - "Старую продать на Авито", flatRenovation.getId())); - final Subtask flatRenovationSubtask3 = taskManager.addSubtask(new Subtask("Заказать книжный шкаф", "Из темного дерева", - flatRenovation.getId())); - final Epic savedEpic = taskManager.getEpicByID(flatRenovation.getId()); - final Subtask savedSubtask1 = taskManager.getSubtaskByID(flatRenovationSubtask1.getId()); - final Subtask savedSubtask2 = taskManager.getSubtaskByID(flatRenovationSubtask2.getId()); - final Subtask savedSubtask3 = taskManager.getSubtaskByID(flatRenovationSubtask3.getId()); - assertNotNull(savedEpic, "Эпик не найден."); - assertNotNull(savedSubtask2, "Подзадача не найдена."); - assertEquals(flatRenovation, savedEpic, "Эпики не совпадают."); - assertEquals(flatRenovationSubtask1, savedSubtask1, "Подзадачи не совпадают."); - assertEquals(flatRenovationSubtask3, savedSubtask3, "Подзадачи не совпадают."); - - final List epics = taskManager.getEpics(); - assertNotNull(epics, "Эпики не возвращаются."); - assertEquals(1, epics.size(), "Неверное количество эпиков."); - assertEquals(flatRenovation, epics.getFirst(), "Эпики не совпадают."); - - final List subtasks = taskManager.getSubtasks(); - assertNotNull(subtasks, "Подзадачи не возвращаются."); - assertEquals(3, subtasks.size(), "Неверное количество подзадач."); - assertEquals(savedSubtask1, subtasks.getFirst(), "Подзадачи не совпадают."); + void testUpdateTask() { + Task task = new Task("Test Task", "This is a test task"); + taskManager.addTask(task); + task.setName("Updated Task"); + Task updatedTask = taskManager.updateTask(task); + assertNotNull(updatedTask); + assertEquals("Updated Task", updatedTask.getName()); } @Test - public void updateTaskShouldReturnTaskWithTheSameId() { - final Task expected = new Task("имя", "описание"); - taskManager.addTask(expected); - final Task updatedTask = new Task(expected.getId(), "новое имя", "новое описание", Status.DONE); - final Task actual = taskManager.updateTask(updatedTask); - assertEquals(expected, actual, "Вернулась задачи с другим id"); + void testGetTaskByID() { + Task task = new Task("Test Task", "This is a test task"); + taskManager.addTask(task); + Task retrievedTask = taskManager.getTaskByID(task.getId()); + assertNotNull(retrievedTask); + assertEquals(task.getId(), retrievedTask.getId()); } - @Test - public void updateSubtaskShouldReturnSubtaskWithTheSameId() { - final Epic epic = new Epic(1, "Сделать ремонт", "Нужно успеть за отпуск"); - taskManager.addEpic(epic); - final Subtask expected = new Subtask("имя", "описание", epic.getId()); - taskManager.addSubtask(expected); - final Subtask updatedSubtask = new Subtask(expected.getId(), "новое имя", "новое описание", - Status.DONE, epic.getId()); - final Subtask actual = taskManager.updateSubtask(updatedSubtask); - assertEquals(expected, actual, "Вернулась подзадача с другим id"); + void testDeleteTaskByID() { + Task task = new Task("Test Task", "This is a test task"); + taskManager.addTask(task); + taskManager.deleteTaskByID(task.getId()); + assertNull(taskManager.getTaskByID(task.getId())); } @Test - public void deleteTasksShouldReturnEmptyList() { - taskManager.addTask(new Task("Купить книги", "Список в заметках")); - taskManager.addTask(new Task("Помыть полы", "С новым средством")); + void testDeleteTasks() { + Task task1 = new Task("Task 1", "Description 1"); + Task task2 = new Task("Task 2", "Description 2"); + taskManager.addTask(task1); + taskManager.addTask(task2); taskManager.deleteTasks(); - List tasks = taskManager.getTasks(); - assertTrue(tasks.isEmpty(), "После удаления задач список должен быть пуст."); - } - - @Test - public void deleteEpicsShouldReturnEmptyList() { - taskManager.addEpic(new Epic(1, "Сделать ремонт", "Нужно успеть за отпуск")); - taskManager.deleteEpics(); - List epics = taskManager.getEpics(); - assertTrue(epics.isEmpty(), "После удаления эпиков список должен быть пуст."); - } - - @Test - public void deleteSubtasksShouldReturnEmptyList() { - Epic flatRenovation = new Epic(1, "Сделать ремонт", "Нужно успеть за отпуск"); - taskManager.addEpic(flatRenovation); - taskManager.addSubtask(new Subtask("Поклеить обои", "Обязательно светлые!", - flatRenovation.getId())); - taskManager.addSubtask(new Subtask("Установить новую технику", "Старую продать на Авито", - flatRenovation.getId())); - taskManager.addSubtask(new Subtask("Заказать книжный шкаф", "Из темного дерева", - flatRenovation.getId())); - - taskManager.deleteSubtasks(); - List subtasks = taskManager.getSubtasks(); - assertTrue(subtasks.isEmpty(), "После удаления подзадач список должен быть пуст."); + assertTrue(taskManager.getTasks().isEmpty()); } - @Test - public void tasksWithEqualIdShouldBeEqual() { - Task task1 = new Task(10, "Забрать заказ", "На Ozon", Status.NEW); - Task task2 = new Task(10, "Забрать заказ", "На Wildberries", Status.DONE); - assertEquals(task1, task2, "Ошибка! Экземпляры класса Task должны быть равны друг другу, если равен их id;"); - } - - @Test - public void EpicsWithEqualIdShouldBeEqual() { - Epic epic1 = new Epic(10, "Сделать ремонт", "Уложиться в 2 миллиона"); - Epic epic2 = new Epic(10, "Подготовиться к собеседованию", "1 июля в 11:00"); - assertEquals(epic1, epic2, - "Ошибка! Наследники класса Task должны быть равны друг другу, если равен их id;"); - } - - @Test - public void SubtasksWithEqualEpicIDShouldBeEqual() { - Subtask subtask1 = new Subtask(10, "Забрать заказ", "На Ozon", Status.NEW, 5); - Subtask subtask2 = new Subtask(10, "Забрать заказ", "На Wildberries", Status.DONE, 5); - assertEquals(subtask1, subtask2, "Ошибка! Наследники класса Task должны быть равны друг другу, если равен их epicID;"); - } - - - @Test - void TaskCreatedAndTaskAddedShouldHaveSameVariables() { - Task expected = new Task(1, "Помыть полы", "С новым средством", Status.DONE); - taskManager.addTask(expected); - List list = taskManager.getTasks(); - Task actual = list.getFirst(); - assertEquals(expected.getId(), actual.getId()); - assertEquals(expected.getName(), actual.getName()); - assertEquals(expected.getDescription(), actual.getDescription()); - assertEquals(expected.getStatus(), actual.getStatus()); - } } \ No newline at end of file diff --git a/test/model/SubtaskTest.java b/test/model/SubtaskTest.java index 626c7c1..3a0fb96 100644 --- a/test/model/SubtaskTest.java +++ b/test/model/SubtaskTest.java @@ -8,9 +8,24 @@ class SubtaskTest { @Test - public void SubtasksWithEqualEpicIDShouldBeEqual() { - Subtask subtask1 = new Subtask(10, "Забрать заказ", "На Ozon", Status.NEW, 5); - Subtask subtask2 = new Subtask(10, "Забрать заказ", "На Wildberries", Status.DONE, 5); - assertEquals(subtask1, subtask2, "Ошибка! Наследники класса Task должны быть равны друг другу, если равен их epicID;"); + void testEquals() { + Subtask subtask1 = new Subtask("Test Subtask", "This is a test subtask", 1); + Subtask subtask2 = new Subtask("Another Subtask", "This is another test subtask", 1); + Subtask subtask3 = new Subtask("Different Subtask", "This is a different test subtask", 2); + + assertEquals(subtask1, subtask2); + assertNotEquals(subtask1, subtask3); } + + @Test + void testHashCode() { + Subtask subtask1 = new Subtask("Test Subtask", "This is a test subtask", 1); + Subtask subtask2 = new Subtask("Another Subtask", "This is another test subtask", 1); + Subtask subtask3 = new Subtask("Different Subtask", "This is a different test subtask", 2); + + assertEquals(subtask1.hashCode(), subtask2.hashCode()); + assertNotEquals(subtask1.hashCode(), subtask3.hashCode()); + } + + } \ No newline at end of file From e0dd1d9b95951ac2981eb3f85374f7b4f5e8089a Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 18 Feb 2025 01:33:17 +0300 Subject: [PATCH 19/27] solution time and duration --- src/manager/InMemoryTaskManager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index 526410b..9fb50c5 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -5,7 +5,6 @@ import model.Subtask; import model.Task; -import java.time.LocalDateTime; import java.util.*; public class InMemoryTaskManager implements TaskManager { From f27b4812a4c06d8d2b4c6137633fa7db8d2e524f Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 18 Feb 2025 11:37:19 +0300 Subject: [PATCH 20/27] solution time and duration --- src/Main.java | 13 ++-- src/manager/FileBackedTaskManager.java | 1 + src/manager/InMemoryTaskManager.java | 74 +++++++++++++----- src/model/Task.java | 1 - test/manager/FileBackedTaskManagerTest.java | 11 +-- test/manager/InMemoryHistoryManagerTest.java | 79 +++++++++++--------- 6 files changed, 107 insertions(+), 72 deletions(-) diff --git a/src/Main.java b/src/Main.java index 6031978..8cd7ec9 100644 --- a/src/Main.java +++ b/src/Main.java @@ -30,15 +30,14 @@ private static void addTasks() { taskManager.addTask(createToDoList); Epic moving = new Epic(10, "Переезд", "Нужно успеть до конца месяца"); - taskManager.addEpic(moving); + taskManager.addEpic(moving); // Epic with ID 10 added - - Subtask packKitchen = new Subtask("Упаковать кухню", "В отдельные коробки", moving.getId(), Duration.ofMinutes(30), now.plusMinutes(10)); - Subtask packBedroom = new Subtask("Упаковать спальню", "В большие коробки", moving.getId(), Duration.ofMinutes(45), now.plusMinutes(50)); // Adjusted start time + // Adjust start times for subtasks to avoid overlaps. Make sure they don't overlap with main tasks either + Subtask packKitchen = new Subtask("Упаковать кухню", "В отдельные коробки", moving.getId(), Duration.ofMinutes(30), now.plusMinutes(65)); + Subtask packBedroom = new Subtask("Упаковать спальню", "В большие коробки", moving.getId(), Duration.ofMinutes(30), now.plusMinutes(95)); taskManager.addSubtask(packKitchen); taskManager.addSubtask(packBedroom); - } private static void printAllTasks() { @@ -82,11 +81,11 @@ private static String formatEpic(Epic epic) { private static void printViewHistory() { taskManager.getTaskByID(1); taskManager.getTaskByID(2); - taskManager.getEpicByID(3); + taskManager.getEpicByID(10); // Changed to 10, based on the epic creation above. taskManager.getTaskByID(1); taskManager.getSubtaskByID(4); taskManager.getSubtaskByID(5); - taskManager.getEpicByID(3); + taskManager.getEpicByID(10); // Changed to 10 taskManager.getSubtaskByID(4); taskManager.getTaskByID(2); taskManager.getSubtaskByID(5); diff --git a/src/manager/FileBackedTaskManager.java b/src/manager/FileBackedTaskManager.java index a7e95de..8f1f27f 100644 --- a/src/manager/FileBackedTaskManager.java +++ b/src/manager/FileBackedTaskManager.java @@ -1,6 +1,7 @@ package manager; import model.Epic; + import model.Status; import model.Subtask; import model.Task; diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index 9fb50c5..b7863af 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -5,6 +5,7 @@ import model.Subtask; import model.Task; +import java.time.ZoneOffset; import java.util.*; public class InMemoryTaskManager implements TaskManager { @@ -17,6 +18,7 @@ public class InMemoryTaskManager implements TaskManager { public InMemoryTaskManager() { this.historyManager = Managers.getDefaultHistory(); } + private int getNextID() { return nextID++; } @@ -46,10 +48,13 @@ public Subtask addSubtask(Subtask subtask) { throw new IllegalArgumentException("Epic with ID " + subtask.getEpicID() + " does not exist."); } validateTask(subtask); - if (isOverlapping(subtask)) { - throw new IllegalArgumentException("Subtask overlaps with existing task"); - } + subtask.setId(getNextID()); + + while (isOverlapping(subtask)) { + subtask.setStartTime(subtask.getStartTime().plusMinutes(10)); + } + epic.addSubtask(subtask); subtasks.put(subtask.getId(), subtask); updateEpicStatus(epic); @@ -61,7 +66,11 @@ public Task updateTask(Task updatedTask) { validateTask(updatedTask); Task existingTask = getTaskByID(updatedTask.getId()); if (existingTask != null) { - historyManager.add(new Task(existingTask)); + tasks.remove(existingTask.getId()); + if (isOverlapping(updatedTask)) { + tasks.put(existingTask.getId(), existingTask); + throw new IllegalArgumentException("Task overlaps with existing task"); + } tasks.put(updatedTask.getId(), updatedTask); } return existingTask; @@ -85,11 +94,20 @@ public Subtask updateSubtask(Subtask subtask) { return null; } int epicID = subtask.getEpicID(); - Subtask oldSubtask = subtasks.get(subtaskID); - subtasks.put(subtaskID, subtask); Epic epic = epics.get(epicID); + Subtask oldSubtask = subtasks.get(subtaskID); + epic.getSubtaskList().remove(oldSubtask); - epic.getSubtaskList().add(subtask); + subtasks.remove(subtaskID); + + if (isOverlapping(subtask)) { + epic.getSubtaskList().add(oldSubtask); + subtasks.put(subtaskID, oldSubtask); + throw new IllegalArgumentException("Subtask overlaps with existing task"); + } + + subtasks.put(subtaskID, subtask); + epic.addSubtask(subtask); updateEpicStatus(epic); return subtask; } @@ -168,11 +186,15 @@ public void deleteTaskByID(int id) { @Override public void deleteEpicByID(int id) { - ArrayList epicSubtasks = epics.get(id).getSubtaskList(); - epics.remove(id); - for (Subtask subtask : epicSubtasks) { - subtasks.remove(subtask.getId()); + Epic epic = epics.get(id); + if (epic != null) { + ArrayList epicSubtasks = epic.getSubtaskList(); + epics.remove(id); + for (Subtask subtask : epicSubtasks) { + subtasks.remove(subtask.getId()); + } } + } @Override @@ -183,8 +205,10 @@ public void deleteSubtaskByID(int id) { subtasks.remove(id); historyManager.remove(id); Epic epic = epics.get(epicID); - epic.getSubtaskList().remove(subtask); - updateEpicStatus(epic); + if (epic != null) { + epic.getSubtaskList().remove(subtask); + updateEpicStatus(epic); + } } } @@ -209,16 +233,29 @@ public List getPrioritizedTasks() { } private boolean isOverlapping(Task newTask) { - return tasks.values().stream() - .anyMatch(existingTask -> isOverlapping(existingTask, newTask)); + for (Task existingTask : tasks.values()) { + if (existingTask.getId() != newTask.getId() && isOverlapping(existingTask, newTask)) { + return true; + } + } + for (Subtask existingSubtask : subtasks.values()) { + if (existingSubtask.getId() != newTask.getId() && isOverlapping(existingSubtask, newTask)) { + return true; + } + } + return false; } private boolean isOverlapping(Task t1, Task t2) { if (t1.getStartTime() == null || t2.getStartTime() == null) { return false; } - return t1.getStartTime().isBefore(t2.getStartTime().plus(t2.getDuration())) && - t2.getStartTime().isBefore(t1.getStartTime().plus(t1.getDuration())); + long t1StartEpoch = t1.getStartTime().toEpochSecond(ZoneOffset.UTC); + long t1EndEpoch = t1StartEpoch + t1.getDuration().getSeconds(); + long t2StartEpoch = t2.getStartTime().toEpochSecond(ZoneOffset.UTC); + long t2EndEpoch = t2StartEpoch + t2.getDuration().getSeconds(); + + return t1StartEpoch < t2EndEpoch && t2StartEpoch < t1EndEpoch; } private void updateEpicStatus(Epic epic) { @@ -234,7 +271,7 @@ private void updateEpicStatus(Epic epic) { allIsInNewCount++; } } - if (allIsDoneCount == list.size()) { + if (list.isEmpty() || allIsDoneCount == list.size()) { epic.setStatus(Status.DONE); } else if (allIsInNewCount == list.size()) { epic.setStatus(Status.NEW); @@ -250,6 +287,5 @@ void validateTask(Task task) { if (task.getDescription() == null) { throw new IllegalArgumentException("Task description cannot be null."); } - } } \ No newline at end of file diff --git a/src/model/Task.java b/src/model/Task.java index 8df30f7..fce169f 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -59,7 +59,6 @@ public Task(int id, String name, String description, Status status, Duration dur this.startTime = startTime; } - public LocalDateTime getEndTime() { return startTime != null && duration != null ? startTime.plus(duration) : null; } diff --git a/test/manager/FileBackedTaskManagerTest.java b/test/manager/FileBackedTaskManagerTest.java index 1612f83..dca39a8 100644 --- a/test/manager/FileBackedTaskManagerTest.java +++ b/test/manager/FileBackedTaskManagerTest.java @@ -1,9 +1,6 @@ package manager; -import manager.FileBackedTaskManager; -import manager.TaskManagerTest; import model.Epic; -import model.Status; import model.Subtask; import model.Task; import org.junit.jupiter.api.AfterEach; @@ -48,7 +45,6 @@ public void testSaveAndLoadFromFile() throws IOException { Epic epic = new Epic(10, "Test Epic", "Epic Description"); taskManager.addEpic(epic); - // Ensure the subtask starts after the task ends Subtask subtask = new Subtask("Test Subtask", "Subtask Description", epic.getId(), Duration.ofMinutes(30), now.plusMinutes(40)); taskManager.addSubtask(subtask); @@ -64,7 +60,6 @@ public void testAddTaskAndCheckFileContent() throws IOException { Task task = new Task("Test Task", "Description", Duration.ofMinutes(30), LocalDateTime.now()); taskManager.addTask(task); - List lines = Files.readAllLines(file.toPath()); assertEquals(2, lines.size()); assertTrue(lines.get(1).contains("Test Task")); @@ -76,20 +71,20 @@ public void testDeleteTaskAndCheckFileContent() throws IOException { taskManager.addTask(task); taskManager.deleteTaskByID(task.getId()); - List lines = Files.readAllLines(file.toPath()); assertEquals(1, lines.size()); } @Test public void testUpdateTaskAndCheckFileContent() throws IOException { - Task task = new Task("Test Task", "Description", Duration.ofMinutes(30), LocalDateTime.now()); + LocalDateTime now = LocalDateTime.now(); + + Task task = new Task("Test Task", "Description", Duration.ofMinutes(30), now); taskManager.addTask(task); task.setDescription("Updated Description"); taskManager.updateTask(task); - List lines = Files.readAllLines(file.toPath()); assertTrue(lines.get(1).contains("Updated Description")); } diff --git a/test/manager/InMemoryHistoryManagerTest.java b/test/manager/InMemoryHistoryManagerTest.java index feb6e4b..20056d2 100644 --- a/test/manager/InMemoryHistoryManagerTest.java +++ b/test/manager/InMemoryHistoryManagerTest.java @@ -1,88 +1,93 @@ package manager; - -import org.junit.jupiter.api.Test; import model.Epic; import model.Status; import model.Task; +import org.junit.jupiter.api.Test; + import java.time.Duration; import java.time.LocalDateTime; import java.util.List; + import static org.junit.jupiter.api.Assertions.assertEquals; public class InMemoryHistoryManagerTest { @Test - public void testAdd() { + public void testEmptyHistory() { InMemoryHistoryManager historyManager = new InMemoryHistoryManager(); - Task task = new Task(1, "Task1", "Description1", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); - historyManager.add(task); List history = historyManager.getHistory(); - assertEquals(1, history.size()); - assertEquals(task, history.get(0)); + assertEquals(0, history.size(), "History should be empty initially."); } @Test - public void testRemove() { + public void testDuplicateTask() { InMemoryHistoryManager historyManager = new InMemoryHistoryManager(); Task task = new Task(1, "Task1", "Description1", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); + + + historyManager.add(task); historyManager.add(task); - historyManager.remove(1); List history = historyManager.getHistory(); - assertEquals(0, history.size()); + + assertEquals(1, history.size(), "History should contain only one instance of the task."); + assertEquals(task, history.get(0), "The task in history should be the same as the added task."); } @Test - public void testGetHistory() { + public void testRemoveFromBeginning() { InMemoryHistoryManager historyManager = new InMemoryHistoryManager(); Task task1 = new Task(1, "Task1", "Description1", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); Task task2 = new Task(2, "Task2", "Description2", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); + Task task3 = new Task(3, "Task3", "Description3", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); + historyManager.add(task1); historyManager.add(task2); - List history = historyManager.getHistory(); - assertEquals(2, history.size()); - assertEquals(task1, history.get(0)); - assertEquals(task2, history.get(1)); - } - - @Test - public void testGetHistoryEmpty() { - InMemoryHistoryManager historyManager = new InMemoryHistoryManager(); - List history = historyManager.getHistory(); - assertEquals(0, history.size()); - } + historyManager.add(task3); - @Test - public void testRemoveNonExisting() { - InMemoryHistoryManager historyManager = new InMemoryHistoryManager(); historyManager.remove(1); List history = historyManager.getHistory(); - assertEquals(0, history.size()); + + assertEquals(2, history.size(), "History should contain two tasks after removing the first one."); + assertEquals(task2, history.get(0), "The first task in history should now be Task2."); + assertEquals(task3, history.get(1), "The second task in history should still be Task3."); } @Test - public void testAddMultiple() { + public void testRemoveFromMiddle() { InMemoryHistoryManager historyManager = new InMemoryHistoryManager(); Task task1 = new Task(1, "Task1", "Description1", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); Task task2 = new Task(2, "Task2", "Description2", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); Task task3 = new Task(3, "Task3", "Description3", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); + historyManager.add(task1); historyManager.add(task2); historyManager.add(task3); + + historyManager.remove(2); List history = historyManager.getHistory(); - assertEquals(3, history.size()); - assertEquals(task1, history.get(0)); - assertEquals(task2, history.get(1)); - assertEquals(task3, history.get(2)); + + assertEquals(2, history.size(), "History should contain two tasks after removing the second one."); + assertEquals(task1, history.get(0), "The first task in history should still be Task1."); + assertEquals(task3, history.get(1), "The second task in history should now be Task3."); } @Test - public void testAddEpic() { + public void testRemoveFromEnd() { InMemoryHistoryManager historyManager = new InMemoryHistoryManager(); - Epic epic = new Epic(1, "Epic1", "Description1", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); - historyManager.add(epic); + Task task1 = new Task(1, "Task1", "Description1", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); + Task task2 = new Task(2, "Task2", "Description2", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); + Task task3 = new Task(3, "Task3", "Description3", Status.NEW, Duration.ofMinutes(30), LocalDateTime.now()); + + historyManager.add(task1); + historyManager.add(task2); + historyManager.add(task3); + + historyManager.remove(3); List history = historyManager.getHistory(); - assertEquals(1, history.size()); - assertEquals(epic, history.get(0)); + + assertEquals(2, history.size(), "History should contain two tasks after removing the last one."); + assertEquals(task1, history.get(0), "The first task in history should still be Task1."); + assertEquals(task2, history.get(1), "The second task in history should now be Task2."); } } \ No newline at end of file From 11ee9311ecc3b83e0926907f2e0532a1b5af9e34 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 18 Feb 2025 11:39:22 +0300 Subject: [PATCH 21/27] solution time and duration --- src/Main.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Main.java b/src/Main.java index 8cd7ec9..4a1dd43 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,7 +1,6 @@ import manager.Managers; import manager.TaskManager; import model.Epic; -import model.Status; import model.Subtask; import model.Task; @@ -30,9 +29,8 @@ private static void addTasks() { taskManager.addTask(createToDoList); Epic moving = new Epic(10, "Переезд", "Нужно успеть до конца месяца"); - taskManager.addEpic(moving); // Epic with ID 10 added + taskManager.addEpic(moving); - // Adjust start times for subtasks to avoid overlaps. Make sure they don't overlap with main tasks either Subtask packKitchen = new Subtask("Упаковать кухню", "В отдельные коробки", moving.getId(), Duration.ofMinutes(30), now.plusMinutes(65)); Subtask packBedroom = new Subtask("Упаковать спальню", "В большие коробки", moving.getId(), Duration.ofMinutes(30), now.plusMinutes(95)); @@ -81,11 +79,11 @@ private static String formatEpic(Epic epic) { private static void printViewHistory() { taskManager.getTaskByID(1); taskManager.getTaskByID(2); - taskManager.getEpicByID(10); // Changed to 10, based on the epic creation above. + taskManager.getEpicByID(10); taskManager.getTaskByID(1); taskManager.getSubtaskByID(4); taskManager.getSubtaskByID(5); - taskManager.getEpicByID(10); // Changed to 10 + taskManager.getEpicByID(10); taskManager.getSubtaskByID(4); taskManager.getTaskByID(2); taskManager.getSubtaskByID(5); From 09608fba0383ec587433c4c85a6c275e9d569f81 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 18 Feb 2025 11:41:01 +0300 Subject: [PATCH 22/27] solution time and duration --- src/model/Task.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/model/Task.java b/src/model/Task.java index fce169f..3d78a8e 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -28,6 +28,7 @@ public Task(Task otherTask) { this.duration = otherTask.getDuration(); this.startTime = otherTask.getStartTime(); } + public Task(String name, String description, Duration duration, LocalDateTime startTime) { this.name = name; this.description = description; From 512c446019236906d4fff28ae06af799bac70e3d Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 18 Feb 2025 11:42:34 +0300 Subject: [PATCH 23/27] solution time and duration --- src/model/Epic.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/model/Epic.java b/src/model/Epic.java index 99acdd0..f904a60 100644 --- a/src/model/Epic.java +++ b/src/model/Epic.java @@ -16,6 +16,7 @@ public class Epic extends Task { public Epic(int id, String name, String description) { super(id, name, description); } + public Epic(int id, String name, String description, Status status, Duration duration, LocalDateTime startTime) { super(id, name, description, status, duration, startTime); } From d042219130fc40ebb5cd0833d6fdf91be81558b8 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 18 Feb 2025 11:50:12 +0300 Subject: [PATCH 24/27] solution time and duration --- test/manager/FileBackedTaskManagerTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/manager/FileBackedTaskManagerTest.java b/test/manager/FileBackedTaskManagerTest.java index dca39a8..1923bc7 100644 --- a/test/manager/FileBackedTaskManagerTest.java +++ b/test/manager/FileBackedTaskManagerTest.java @@ -27,7 +27,9 @@ public void setUp() { @AfterEach public void tearDown() { - file.delete(); + if (file.exists()) { + file.delete(); + } } @Override @@ -91,7 +93,6 @@ public void testUpdateTaskAndCheckFileContent() throws IOException { @Test public void testLoadFromFileWithEmptyFile() throws IOException { - file.createNewFile(); FileBackedTaskManager loadedManager = FileBackedTaskManager.loadFromFile(file); @@ -99,4 +100,4 @@ public void testLoadFromFileWithEmptyFile() throws IOException { assertTrue(loadedManager.getEpics().isEmpty()); assertTrue(loadedManager.getSubtasks().isEmpty()); } -} +} \ No newline at end of file From fd5507e19a672ae4f09972767ecc92feb8060716 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 18 Feb 2025 11:50:25 +0300 Subject: [PATCH 25/27] solution time and duration --- test/manager/TaskManagerTest.java | 138 ++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 test/manager/TaskManagerTest.java diff --git a/test/manager/TaskManagerTest.java b/test/manager/TaskManagerTest.java new file mode 100644 index 0000000..9f2b477 --- /dev/null +++ b/test/manager/TaskManagerTest.java @@ -0,0 +1,138 @@ +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.time.Duration; +import java.time.LocalDateTime; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public abstract class TaskManagerTest { + protected T taskManager; + + @BeforeEach + public void setUp() { + taskManager = createTaskManager(); + } + + protected abstract T createTaskManager(); + + @Test + public void testAddTask() { + Task task = new Task("Test Task", "Description", Duration.ofMinutes(30), LocalDateTime.now()); + taskManager.addTask(task); + assertEquals(task, taskManager.getTaskByID(task.getId())); + } + + @Test + public void testAddEpic() { + Epic epic = new Epic(10, "Test Epic", "Epic Description"); + taskManager.addEpic(epic); + assertEquals(epic, taskManager.getEpicByID(epic.getId())); + } + + @Test + public void testAddSubtask() { + Epic epic = new Epic(10, "Test Epic", "Epic Description"); + taskManager.addEpic(epic); + Subtask subtask = new Subtask("Test Subtask", "Subtask Description", epic.getId(), Duration.ofMinutes(30), LocalDateTime.now()); + taskManager.addSubtask(subtask); + assertEquals(subtask, taskManager.getSubtaskByID(subtask.getId())); + } + + @Test + public void testEpicStatusCalculation() { + Epic epic = new Epic(10, "Test Epic", "Epic Description"); + taskManager.addEpic(epic); + Subtask subtask1 = new Subtask("Subtask 1", "Description", epic.getId(), Duration.ofMinutes(30), LocalDateTime.now()); + Subtask subtask2 = new Subtask("Subtask 2", "Description", epic.getId(), Duration.ofMinutes(30), LocalDateTime.now()); + taskManager.addSubtask(subtask1); + taskManager.addSubtask(subtask2); + + assertEquals(Status.NEW, epic.getStatus()); + + subtask1.setStatus(Status.DONE); + taskManager.updateSubtask(subtask1); + + assertEquals(Status.IN_PROGRESS, epic.getStatus()); + + subtask2.setStatus(Status.DONE); + taskManager.updateSubtask(subtask2); + + assertEquals(Status.DONE, epic.getStatus()); + } + + @Test + public void testGetPrioritizedTasks() { + LocalDateTime now = LocalDateTime.now(); + + Task task1 = new Task("Task 1", "Description 1", Duration.ofMinutes(30), now.plusMinutes(10)); + Task task2 = new Task("Task 2", "Description 2", Duration.ofMinutes(30), now.plusMinutes(50)); + Task task3 = new Task("Task 3", "Description 3", Duration.ofMinutes(30), now.plusMinutes(90)); + + taskManager.addTask(task1); + taskManager.addTask(task2); + taskManager.addTask(task3); + + List prioritizedTasks = taskManager.getPrioritizedTasks(); + + assertEquals(3, prioritizedTasks.size()); + assertEquals(task1, prioritizedTasks.get(0)); + assertEquals(task2, prioritizedTasks.get(1)); + assertEquals(task3, prioritizedTasks.get(2)); + } + + @Test + public void testDeleteTaskByID() { + Task task = new Task("Test Task", "Description", Duration.ofMinutes(30), LocalDateTime.now()); + taskManager.addTask(task); + taskManager.deleteTaskByID(task.getId()); + assertNull(taskManager.getTaskByID(task.getId())); + } + + @Test + public void testDeleteEpicWithSubtasks() { + Epic epic = new Epic(10, "Test Epic", "Epic Description"); + taskManager.addEpic(epic); + Subtask subtask = new Subtask("Test Subtask", "Subtask Description", epic.getId(), Duration.ofMinutes(30), LocalDateTime.now()); + taskManager.addSubtask(subtask); + taskManager.deleteEpicByID(epic.getId()); + assertNull(taskManager.getEpicByID(epic.getId())); + assertNull(taskManager.getSubtaskByID(subtask.getId())); + } + + @Test + public void testUpdateTask() { + Task task = new Task("Test Task", "Description", Duration.ofMinutes(30), LocalDateTime.now()); + taskManager.addTask(task); + task.setDescription("Updated Description"); + taskManager.updateTask(task); + assertEquals("Updated Description", taskManager.getTaskByID(task.getId()).getDescription()); + } + + @Test + public void testUpdateEpic() { + Epic epic = new Epic(10, "Test Epic", "Epic Description"); + taskManager.addEpic(epic); + epic.setDescription("Updated Epic Description"); + taskManager.updateEpic(epic); + assertEquals("Updated Epic Description", taskManager.getEpicByID(epic.getId()).getDescription()); + } + + @Test + public void testUpdateSubtask() { + Epic epic = new Epic(10, "Test Epic", "Epic Description"); + taskManager.addEpic(epic); + Subtask subtask = new Subtask("Test Subtask", "Subtask Description", epic.getId(), Duration.ofMinutes(30), LocalDateTime.now()); + taskManager.addSubtask(subtask); + subtask.setDescription("Updated Subtask Description"); + taskManager.updateSubtask(subtask); + assertEquals("Updated Subtask Description", taskManager.getSubtaskByID(subtask.getId()).getDescription()); + } +} \ No newline at end of file From f0fffdc2425cf245d3dcc17621966c6f1045bb70 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 18 Feb 2025 17:44:36 +0300 Subject: [PATCH 26/27] correcting errors and reducing the difficulty of getting to O(n) --- .../ManagerSaveException.java | 2 +- src/manager/FileBackedTaskManager.java | 1 + src/manager/InMemoryTaskManager.java | 32 +++++++++++-------- src/model/Epic.java | 21 ++---------- src/model/Task.java | 12 +++---- 5 files changed, 30 insertions(+), 38 deletions(-) rename src/{manager => exceptions}/ManagerSaveException.java (89%) diff --git a/src/manager/ManagerSaveException.java b/src/exceptions/ManagerSaveException.java similarity index 89% rename from src/manager/ManagerSaveException.java rename to src/exceptions/ManagerSaveException.java index cc94837..e43db7e 100644 --- a/src/manager/ManagerSaveException.java +++ b/src/exceptions/ManagerSaveException.java @@ -1,4 +1,4 @@ -package manager; +package exceptions; public class ManagerSaveException extends RuntimeException { public ManagerSaveException(String message, Throwable cause) { diff --git a/src/manager/FileBackedTaskManager.java b/src/manager/FileBackedTaskManager.java index 8f1f27f..ccb3301 100644 --- a/src/manager/FileBackedTaskManager.java +++ b/src/manager/FileBackedTaskManager.java @@ -1,5 +1,6 @@ package manager; +import exceptions.ManagerSaveException; import model.Epic; import model.Status; diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index b7863af..2cf9ef0 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -13,6 +13,7 @@ public class InMemoryTaskManager implements TaskManager { private final Map epics = new HashMap<>(); private final Map subtasks = new HashMap<>(); private final HistoryManager historyManager; + private final Set prioritizedTasks = new TreeSet<>(Comparator.comparing(Task::getStartTime, Comparator.nullsLast(Comparator.naturalOrder()))); private int nextID = 1; public InMemoryTaskManager() { @@ -31,6 +32,7 @@ public Task addTask(Task task) { } task.setId(getNextID()); tasks.put(task.getId(), task); + prioritizedTasks.add(task); return task; } @@ -57,6 +59,7 @@ public Subtask addSubtask(Subtask subtask) { epic.addSubtask(subtask); subtasks.put(subtask.getId(), subtask); + prioritizedTasks.add(subtask); updateEpicStatus(epic); return subtask; } @@ -67,11 +70,14 @@ public Task updateTask(Task updatedTask) { Task existingTask = getTaskByID(updatedTask.getId()); if (existingTask != null) { tasks.remove(existingTask.getId()); + prioritizedTasks.remove(existingTask); if (isOverlapping(updatedTask)) { tasks.put(existingTask.getId(), existingTask); + prioritizedTasks.add(existingTask); throw new IllegalArgumentException("Task overlaps with existing task"); } tasks.put(updatedTask.getId(), updatedTask); + prioritizedTasks.add(updatedTask); } return existingTask; } @@ -99,14 +105,17 @@ public Subtask updateSubtask(Subtask subtask) { epic.getSubtaskList().remove(oldSubtask); subtasks.remove(subtaskID); + prioritizedTasks.remove(oldSubtask); if (isOverlapping(subtask)) { epic.getSubtaskList().add(oldSubtask); subtasks.put(subtaskID, oldSubtask); + prioritizedTasks.add(oldSubtask); throw new IllegalArgumentException("Subtask overlaps with existing task"); } subtasks.put(subtaskID, subtask); + prioritizedTasks.add(subtask); epic.addSubtask(subtask); updateEpicStatus(epic); return subtask; @@ -162,17 +171,20 @@ public ArrayList getEpicSubtasks(Epic epic) { @Override public void deleteTasks() { tasks.clear(); + prioritizedTasks.clear(); } @Override public void deleteEpics() { epics.clear(); subtasks.clear(); + prioritizedTasks.clear(); } @Override public void deleteSubtasks() { subtasks.clear(); + prioritizedTasks.clear(); for (Epic epic : epics.values()) { epic.clearSubtasks(); epic.setStatus(Status.NEW); @@ -181,7 +193,10 @@ public void deleteSubtasks() { @Override public void deleteTaskByID(int id) { - tasks.remove(id); + Task task = tasks.remove(id); + if (task != null) { + prioritizedTasks.remove(task); + } } @Override @@ -192,9 +207,9 @@ public void deleteEpicByID(int id) { epics.remove(id); for (Subtask subtask : epicSubtasks) { subtasks.remove(subtask.getId()); + prioritizedTasks.remove(subtask); } } - } @Override @@ -203,6 +218,7 @@ public void deleteSubtaskByID(int id) { if (subtask != null) { int epicID = subtask.getEpicID(); subtasks.remove(id); + prioritizedTasks.remove(subtask); historyManager.remove(id); Epic epic = epics.get(epicID); if (epic != null) { @@ -219,17 +235,7 @@ public List getHistory() { @Override public List getPrioritizedTasks() { - PriorityQueue priorityQueue = new PriorityQueue<>(Comparator.comparing(Task::getStartTime, Comparator.nullsLast(Comparator.naturalOrder()))); - - priorityQueue.addAll(tasks.values()); - priorityQueue.addAll(subtasks.values()); - - List prioritizedTasks = new ArrayList<>(); - while (!priorityQueue.isEmpty()) { - prioritizedTasks.add(priorityQueue.poll()); - } - - return prioritizedTasks; + return new ArrayList<>(prioritizedTasks); } private boolean isOverlapping(Task newTask) { diff --git a/src/model/Epic.java b/src/model/Epic.java index f904a60..b69b861 100644 --- a/src/model/Epic.java +++ b/src/model/Epic.java @@ -9,9 +9,6 @@ public class Epic extends Task { private ArrayList subtaskList = new ArrayList<>(); - private Duration duration; - private LocalDateTime startTime; - private LocalDateTime endTime; public Epic(int id, String name, String description) { super(id, name, description); @@ -47,7 +44,6 @@ public void setSubtaskList(ArrayList subtaskList) { private void updateEpicDetails() { this.duration = Duration.ZERO; this.startTime = null; - this.endTime = null; if (!subtaskList.isEmpty()) { LocalDateTime earliestStart = null; @@ -68,20 +64,8 @@ private void updateEpicDetails() { } this.startTime = earliestStart; - this.endTime = latestEnd; - } - } - - public Duration getDuration() { - return duration; - } - public LocalDateTime getStartTime() { - return startTime; - } - - public LocalDateTime getEndTime() { - return endTime; + } } @Override @@ -94,10 +78,11 @@ public String toString() { ", status=" + getStatus() + ", duration=" + duration + ", startTime=" + startTime + - ", endTime=" + endTime + + ", endTime=" + getEndTime() + '}'; } + @Override public boolean equals(Object obj) { if (this == obj) return true; diff --git a/src/model/Task.java b/src/model/Task.java index 3d78a8e..bb4332a 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -7,12 +7,12 @@ import java.util.Objects; public class Task { - private int id; - private String name; - private String description; - private Status status; - private Duration duration; - private LocalDateTime startTime; + protected int id; + protected String name; + protected String description; + protected Status status; + protected Duration duration; + protected LocalDateTime startTime; public Task(String name, String description) { this.name = name; From 918d520ccc30e4d5d1e6f3a11ff55808fdd90dbe Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 19 Feb 2025 14:31:19 +0300 Subject: [PATCH 27/27] correcting errors --- src/manager/InMemoryTaskManager.java | 36 +++++++++++++++++++--------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index 2cf9ef0..665bad6 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -170,24 +170,37 @@ public ArrayList getEpicSubtasks(Epic epic) { @Override public void deleteTasks() { + for (Task task : tasks.values()) { + historyManager.remove(task.getId()); + prioritizedTasks.remove(task); + } tasks.clear(); - prioritizedTasks.clear(); } @Override public void deleteEpics() { + for (Epic epic : epics.values()) { + for (Subtask subtask : epic.getSubtaskList()) { + subtasks.remove(subtask.getId()); + prioritizedTasks.remove(subtask); + historyManager.remove(subtask.getId()); + } + } epics.clear(); - subtasks.clear(); - prioritizedTasks.clear(); } @Override public void deleteSubtasks() { - subtasks.clear(); - prioritizedTasks.clear(); - for (Epic epic : epics.values()) { - epic.clearSubtasks(); - epic.setStatus(Status.NEW); + for (Subtask subtask : new ArrayList<>(subtasks.values())) { + int epicID = subtask.getEpicID(); + subtasks.remove(subtask.getId()); + prioritizedTasks.remove(subtask); + historyManager.remove(subtask.getId()); + Epic epic = epics.get(epicID); + if (epic != null) { + epic.getSubtaskList().remove(subtask); + updateEpicStatus(epic); + } } } @@ -196,6 +209,7 @@ public void deleteTaskByID(int id) { Task task = tasks.remove(id); if (task != null) { prioritizedTasks.remove(task); + historyManager.remove(id); } } @@ -203,12 +217,12 @@ public void deleteTaskByID(int id) { public void deleteEpicByID(int id) { Epic epic = epics.get(id); if (epic != null) { - ArrayList epicSubtasks = epic.getSubtaskList(); - epics.remove(id); - for (Subtask subtask : epicSubtasks) { + for (Subtask subtask : epic.getSubtaskList()) { subtasks.remove(subtask.getId()); prioritizedTasks.remove(subtask); + historyManager.remove(subtask.getId()); } + epics.remove(id); } }