From 21b0505a1e86ec1be4ba819afd3db99522ff6aa2 Mon Sep 17 00:00:00 2001 From: Darya346 Date: Tue, 7 Oct 2025 20:47:38 +0300 Subject: [PATCH 01/14] =?UTF-8?q?=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=20HistoryManager=20=D1=81=20=D0=B4?= =?UTF-8?q?=D0=B2=D1=83=D1=81=D0=B2=D1=8F=D0=B7=D0=BD=D1=8B=D0=BC=20=D1=81?= =?UTF-8?q?=D0=BF=D0=B8=D1=81=D0=BA=D0=BE=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/manager/HistoryManager.java | 1 + src/manager/InMemoryHistoryManager.java | 88 +++++++++++++- src/manager/InMemoryTaskManager.java | 127 ++++++++++++--------- test/manager/InMemoryTaskManagerTest.java | 105 +++++++++++++++++ test/manager/TaskInheritanceTest.java | 37 ------ test/model/InMemoryHistoryManagerTest.java | 92 +++++++++++++++ test/model/TaskIdConflictTest.java | 2 + test/model/TaskImmutabilityTest.java | 40 ------- 8 files changed, 358 insertions(+), 134 deletions(-) create mode 100644 test/manager/InMemoryTaskManagerTest.java delete mode 100644 test/manager/TaskInheritanceTest.java create mode 100644 test/model/InMemoryHistoryManagerTest.java delete mode 100644 test/model/TaskImmutabilityTest.java diff --git a/src/manager/HistoryManager.java b/src/manager/HistoryManager.java index 6070997..079236c 100644 --- a/src/manager/HistoryManager.java +++ b/src/manager/HistoryManager.java @@ -5,5 +5,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 aee6b0d..c9b1a5b 100644 --- a/src/manager/InMemoryHistoryManager.java +++ b/src/manager/InMemoryHistoryManager.java @@ -2,24 +2,100 @@ import model.Task; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; public class InMemoryHistoryManager implements HistoryManager { - private static final int MAX_HISTORY_SIZE = 10; - private final List history = new ArrayList<>(); + private static class Node { + Task task; + Node prev; + Node next; + + Node(Task task) { + this.task = task; + } + } + + private final Map historyMap = new HashMap<>(); + private Node head; + private Node tail; @Override public void add(Task task) { if (task == null) return; - if (history.size() >= MAX_HISTORY_SIZE) { - history.removeFirst(); // Удаляем самый старый элемент + // Удаляем существующую задачу из истории, если она есть + remove(task.getId()); + + // Добавляем задачу в конец списка + Node newNode = linkLast(task); + historyMap.put(task.getId(), newNode); + } + + @Override + public void remove(int id) { + Node node = historyMap.get(id); + if (node != null) { + removeNode(node); + historyMap.remove(id); } - history.add(task); } @Override public List getHistory() { - return new ArrayList<>(history); + return getTasks(); + } + + private Node linkLast(Task task) { + Node newNode = new Node(task); + + if (tail == null) { + // Список пустой + head = newNode; + tail = newNode; + } else { + // Добавляем в конец списка + tail.next = newNode; + newNode.prev = tail; + tail = newNode; + } + + return newNode; + } + + private void removeNode(Node node) { + if (node == null) return; + + // Обновляем ссылки соседних узлов + if (node.prev != null) { + node.prev.next = node.next; + } else { + // Удаляем голову + head = node.next; + } + + if (node.next != null) { + node.next.prev = node.prev; + } else { + // Удаляем хвост + tail = node.prev; + } + + // Очищаем ссылки удаляемого узла + node.prev = null; + node.next = null; + } + + private List getTasks() { + List tasks = new ArrayList<>(); + Node current = head; + + while (current != null) { + tasks.add(current.task); + current = current.next; + } + + return tasks; } } \ No newline at end of file diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index 9b107ab..a84675f 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -19,7 +19,7 @@ public InMemoryTaskManager() { private int generateId() { return nextId++; } - // Модифицируем методы получения задач для добавления в историю + // Методы получения задач с добавлением в историю @Override public Task getTaskById(int id) { Task task = tasks.get(id); @@ -47,40 +47,64 @@ public Subtask getSubtaskById(int id) { return subtask; } - // Добавляем метод для получения истории @Override public List getHistory() { return historyManager.getHistory(); } - // Остальные методы остаются без изменений... - @Override public List getAllTasks() { return new ArrayList<>(tasks.values()); } - + // Модифицируем методы удаления для очистки истории @Override - public void deleteAllTasks() { tasks.clear(); } - - @Override - public Task createTask(Task task) { - if (task == null) return null; - Task newTask = new Task(task.getName(), task.getDescription(), generateId(), task.getStatus()); - tasks.put(newTask.getId(), newTask); - return newTask; + public void deleteTaskById(int id) { + tasks.remove(id); + historyManager.remove(id); } @Override - public void updateTask(Task task) { - if (task == null || !tasks.containsKey(task.getId())) return; - tasks.put(task.getId(), task); + public void deleteEpicById(int id) { + Epic epic = epics.get(id); + if (epic != null) { + // Удаляем эпик и все его подзадачи из истории + historyManager.remove(id); + for (Integer subtaskId : epic.getSubtaskIds()) { + subtasks.remove(subtaskId); + historyManager.remove(subtaskId); + } + epics.remove(id); + } } @Override - public void deleteTaskById(int id) { tasks.remove(id); } + public void deleteSubtaskById(int id) { + Subtask subtask = subtasks.get(id); + if (subtask != null) { + Epic epic = epics.get(subtask.getEpicId()); + if (epic != null) { + epic.removeSubtaskId(id); + updateEpicStatus(epic.getId()); + } + subtasks.remove(id); + historyManager.remove(id); + } + } @Override - public List getAllEpics() { return new ArrayList<>(epics.values()); } + public void deleteAllTasks() { + for (Integer taskId : tasks.keySet()) { + historyManager.remove(taskId); + } + tasks.clear(); + } @Override public void deleteAllEpics() { + // Удаляем все эпики и подзадачи из истории + for (Integer epicId : epics.keySet()) { + historyManager.remove(epicId); + } + for (Integer subtaskId : subtasks.keySet()) { + historyManager.remove(subtaskId); + } + for (Epic epic : epics.values()) { for (Integer subtaskId : epic.getSubtaskIds()) { subtasks.remove(subtaskId); @@ -89,6 +113,40 @@ public void deleteAllEpics() { epics.clear(); } + @Override + public void deleteAllSubtasks() { + // Удаляем все подзадачи из истории + for (Integer subtaskId : subtasks.keySet()) { + historyManager.remove(subtaskId); + } + + for (Epic epic : epics.values()) { + epic.clearSubtasks(); + updateEpicStatus(epic.getId()); + } + subtasks.clear(); + } + + // Остальные методы остаются без изменений... + @Override public List getAllTasks() { return new ArrayList<>(tasks.values()); } + + @Override + public Task createTask(Task task) { + if (task == null) return null; + Task newTask = new Task(task.getName(), task.getDescription(), generateId(), task.getStatus()); + tasks.put(newTask.getId(), newTask); + return newTask; + } + + @Override + public void updateTask(Task task) { + if (task == null || !tasks.containsKey(task.getId())) return; + tasks.put(task.getId(), task); + } + + @Override + public List getAllEpics() { return new ArrayList<>(epics.values()); } + @Override public Epic createEpic(Epic epic) { if (epic == null) return null; @@ -106,29 +164,9 @@ public void updateEpic(Epic epic) { existingEpic.setDescription(epic.getDescription()); } - @Override - public void deleteEpicById(int id) { - Epic epic = epics.get(id); - if (epic != null) { - for (Integer subtaskId : epic.getSubtaskIds()) { - subtasks.remove(subtaskId); - } - epics.remove(id); - } - } - @Override public List getAllSubtasks() { return new ArrayList<>(subtasks.values()); } - @Override - public void deleteAllSubtasks() { - for (Epic epic : epics.values()) { - epic.clearSubtasks(); - updateEpicStatus(epic.getId()); - } - subtasks.clear(); - } - @Override public Subtask createSubtask(Subtask subtask) { if (subtask == null || !epics.containsKey(subtask.getEpicId())) return null; @@ -163,19 +201,6 @@ public void updateSubtask(Subtask subtask) { updateEpicStatus(subtask.getEpicId()); } - @Override - public void deleteSubtaskById(int id) { - Subtask subtask = subtasks.get(id); - if (subtask != null) { - Epic epic = epics.get(subtask.getEpicId()); - if (epic != null) { - epic.removeSubtaskId(id); - updateEpicStatus(epic.getId()); - } - subtasks.remove(id); - } - } - @Override public List getSubtasksByEpicId(int epicId) { List result = new ArrayList<>(); diff --git a/test/manager/InMemoryTaskManagerTest.java b/test/manager/InMemoryTaskManagerTest.java new file mode 100644 index 0000000..2417438 --- /dev/null +++ b/test/manager/InMemoryTaskManagerTest.java @@ -0,0 +1,105 @@ +package manager; + +import model.Task; +import model.Epic; +import model.Subtask; +import model.Status; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; + +class InMemoryTaskManagerTest { + private TaskManager taskManager; + + @BeforeEach + void setUp() { + taskManager = new InMemoryTaskManager(); + } + + @Test + void testTaskImmutability() { + // Создаем задачу через менеджер + Task task = taskManager.createTask(new Task("Test", "Description", Status.NEW)); + int originalId = task.getId(); + String originalName = task.getName(); + + // Пытаемся изменить задачу через сеттеры + task.setId(999); + task.setName("Modified"); + task.setStatus(Status.DONE); + + // Получаем задачу из менеджера + Task managedTask = taskManager.getTaskById(originalId); + + // Проверяем, что данные в менеджере не изменились + assertEquals(originalId, managedTask.getId()); + assertEquals(originalName, managedTask.getName()); + assertEquals(Status.NEW, managedTask.getStatus()); + } + + @Test + void testEpicImmutability() { + Epic epic = taskManager.createEpic(new Epic("Test Epic", "Description")); + int originalId = epic.getId(); + + // Пытаемся изменить эпик + epic.setId(999); + epic.setName("Modified"); + + // Получаем эпик из менеджера + Epic managedEpic = taskManager.getEpicById(originalId); + + // Проверяем, что данные в менеджере не изменились + assertEquals(originalId, managedEpic.getId()); + assertEquals("Test Epic", managedEpic.getName()); + } + + @Test + void testHistoryWithoutDuplicates() { + Task task = taskManager.createTask(new Task("Test", "Description", Status.NEW)); + + // Многократно запрашиваем одну и ту же задачу + taskManager.getTaskById(task.getId()); + taskManager.getTaskById(task.getId()); + taskManager.getTaskById(task.getId()); + + // В истории должна быть только одна запись + assertEquals(1, taskManager.getHistory().size()); + } + + @Test + void testDataIntegrityAfterDeletion() { + Epic epic = taskManager.createEpic(new Epic("Test Epic", "Description")); + Subtask subtask = taskManager.createSubtask(new Subtask("Subtask", "Desc", Status.NEW, epic.getId())); + + int subtaskId = subtask.getId(); + int epicId = epic.getId(); + + // Удаляем подзадачу + taskManager.deleteSubtaskById(subtaskId); + + // Проверяем, что эпик не содержит удаленную подзадачу + Epic updatedEpic = taskManager.getEpicById(epicId); + assertFalse(updatedEpic.getSubtaskIds().contains(subtaskId)); + + // Проверяем, что подзадача удалена из хранилища + assertNull(taskManager.getSubtaskById(subtaskId)); + } + + @Test + void testEmptyHistoryAfterTaskDeletion() { + Task task = taskManager.createTask(new Task("Test", "Description", Status.NEW)); + + // Добавляем в историю + taskManager.getTaskById(task.getId()); + assertEquals(1, taskManager.getHistory().size()); + + // Удаляем задачу + taskManager.deleteTaskById(task.getId()); + + // История должна быть пустой + assertTrue(taskManager.getHistory().isEmpty()); + } +} \ No newline at end of file diff --git a/test/manager/TaskInheritanceTest.java b/test/manager/TaskInheritanceTest.java deleted file mode 100644 index b723370..0000000 --- a/test/manager/TaskInheritanceTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package manager; - -import model.Epic; -import model.Status; -import model.Subtask; -import model.Task; -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - -class TaskInheritanceTest { - - @Test - void taskAndSubtaskWithSameIdShouldNotBeEqual() { - Task task = new Task("Task", "Description", 1, Status.NEW); - Subtask subtask = new Subtask("Subtask", "Description", 1, Status.NEW, 2); - - assertNotEquals(task, subtask, "Task и Subtask с одинаковым ID не должны быть равны"); - } - - @Test - void subtasksWithSameIdShouldBeEqual() { - Subtask subtask1 = new Subtask("Subtask 1", "Description 1", 1, Status.NEW, 10); - Subtask subtask2 = new Subtask("Subtask 2", "Description 2", 1, Status.DONE, 20); - - assertEquals(subtask1, subtask2, "Subtask с одинаковым ID должны быть равны"); - } - - @Test - void epicsWithSameIdShouldBeEqual() { - Epic epic1 = new Epic("Epic 1", "Description 1"); - epic1.setId(1); - Epic epic2 = new Epic("Epic 2", "Description 2"); - epic2.setId(1); - - assertEquals(epic1, epic2, "Epic с одинаковым ID должны быть равны"); - } -} \ No newline at end of file diff --git a/test/model/InMemoryHistoryManagerTest.java b/test/model/InMemoryHistoryManagerTest.java new file mode 100644 index 0000000..3dbf32a --- /dev/null +++ b/test/model/InMemoryHistoryManagerTest.java @@ -0,0 +1,92 @@ +package manager; + +import model.Task; +import model.Status; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; + +class InMemoryHistoryManagerTest { + private HistoryManager historyManager; + + @BeforeEach + void setUp() { + historyManager = new InMemoryHistoryManager(); + } + + @Test + void testAddAndGetHistory() { + Task task = new Task("Test", "Description", Status.NEW); + task.setId(1); + + historyManager.add(task); + List history = historyManager.getHistory(); + + assertEquals(1, history.size()); + assertEquals(task, history.get(0)); + } + + @Test + void testRemoveDuplicates() { + Task task = new Task("Test", "Description", Status.NEW); + task.setId(1); + + historyManager.add(task); + historyManager.add(task); // Дубликат + historyManager.add(task); // Еще один дубликат + + List history = historyManager.getHistory(); + assertEquals(1, history.size()); + } + + @Test + void testRemoveFromHistory() { + Task task1 = new Task("Test1", "Description1", Status.NEW); + Task task2 = new Task("Test2", "Description2", Status.NEW); + task1.setId(1); + task2.setId(2); + + historyManager.add(task1); + historyManager.add(task2); + + historyManager.remove(1); + List history = historyManager.getHistory(); + + assertEquals(1, history.size()); + assertEquals(task2, history.get(0)); + } + + @Test + void testHistoryOrderPreservation() { + Task task1 = new Task("Test1", "Description1", Status.NEW); + Task task2 = new Task("Test2", "Description2", Status.NEW); + Task task3 = new Task("Test3", "Description3", Status.NEW); + task1.setId(1); + task2.setId(2); + task3.setId(3); + + 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 + void testRemoveNonExistentTask() { + // Удаление несуществующей задачи не должно вызывать исключений + assertDoesNotThrow(() -> historyManager.remove(999)); + } + + @Test + void testEmptyHistory() { + assertTrue(historyManager.getHistory().isEmpty()); + } +} \ No newline at end of file diff --git a/test/model/TaskIdConflictTest.java b/test/model/TaskIdConflictTest.java index 222e673..571204d 100644 --- a/test/model/TaskIdConflictTest.java +++ b/test/model/TaskIdConflictTest.java @@ -2,6 +2,8 @@ import model.Task; import model.Status; +import manager.InMemoryTaskManager; +import manager.TaskManager; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; diff --git a/test/model/TaskImmutabilityTest.java b/test/model/TaskImmutabilityTest.java deleted file mode 100644 index ff8b490..0000000 --- a/test/model/TaskImmutabilityTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package model; - -import model.Task; -import model.Status; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - -class TaskImmutabilityTest { - private TaskManager taskManager; - - @BeforeEach - void setUp() { - taskManager = new InMemoryTaskManager(); - } - - @Test - void taskRemainsUnchangedWhenAddedToManager() { - // Создаем оригинальную задачу - Task originalTask = new Task("Original", "Original Description", Status.NEW); - - // Сохраняем оригинальные значения - String originalName = originalTask.getName(); - String originalDescription = originalTask.getDescription(); - Status originalStatus = originalTask.getStatus(); - - // Добавляем в менеджер - Task createdTask = taskManager.createTask(originalTask); - - // Проверяем, что оригинальная задача не изменилась - assertEquals(originalName, originalTask.getName(), "Оригинальное имя не должно измениться"); - assertEquals(originalDescription, originalTask.getDescription(), "Оригинальное описание не должно измениться"); - assertEquals(originalStatus, originalTask.getStatus(), "Оригинальный статус не должен измениться"); - - // Проверяем, что созданная задача имеет те же значения - assertEquals(originalName, createdTask.getName(), "Имя должно сохраниться"); - assertEquals(originalDescription, createdTask.getDescription(), "Описание должно сохраниться"); - assertEquals(originalStatus, createdTask.getStatus(), "Статус должен сохраниться"); - } -} \ No newline at end of file From 5a7829321a9ad7c4c690da4d4928866b2e4e6c0a Mon Sep 17 00:00:00 2001 From: Darya346 Date: Tue, 7 Oct 2025 20:57:00 +0300 Subject: [PATCH 02/14] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= =?UTF-8?q?=20Checkstyle=20=D0=B2=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D0=B5?= =?UTF-8?q?=20Subtask?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/model/Epic.java | 25 +++++++++++++++++++----- src/model/Subtask.java | 9 +++++++-- src/model/Task.java | 43 +++++++++++++++++++++++++++++++++--------- 3 files changed, 61 insertions(+), 16 deletions(-) diff --git a/src/model/Epic.java b/src/model/Epic.java index 6634160..c4569f8 100644 --- a/src/model/Epic.java +++ b/src/model/Epic.java @@ -11,17 +11,32 @@ public Epic(String name, String description) { this.subtaskIds = new ArrayList<>(); } - public List getSubtaskIds() { return new ArrayList<>(subtaskIds); } - public void addSubtaskId(int subtaskId) { if (!subtaskIds.contains(subtaskId)) subtaskIds.add(subtaskId); } - public void removeSubtaskId(int subtaskId) { subtaskIds.remove(Integer.valueOf(subtaskId)); } - public void clearSubtasks() { subtaskIds.clear(); } + public List getSubtaskIds() { + return new ArrayList<>(subtaskIds); + } + + public void addSubtaskId(int subtaskId) { + if (!subtaskIds.contains(subtaskId)) { + subtaskIds.add(subtaskId); + } + } + + public void removeSubtaskId(int subtaskId) { + subtaskIds.remove(Integer.valueOf(subtaskId)); + } + + public void clearSubtasks() { + subtaskIds.clear(); + } @Override public void setStatus(Status status) { throw new UnsupportedOperationException("Статус эпика рассчитывается автоматически"); } - public void updateStatus(Status status) { this.status = status; } + public void updateStatus(Status status) { + this.status = status; + } @Override public String toString() { diff --git a/src/model/Subtask.java b/src/model/Subtask.java index d1547d7..6f089fc 100644 --- a/src/model/Subtask.java +++ b/src/model/Subtask.java @@ -13,8 +13,13 @@ public Subtask(String name, String description, int id, Status status, int epicI this.epicId = epicId; } - public int getEpicId() { return epicId; } - public void setEpicId(int epicId) { this.epicId = epicId; } + public int getEpicId() { + return epicId; + } + + public void setEpicId(int epicId) { + this.epicId = epicId; + } @Override public String toString() { diff --git a/src/model/Task.java b/src/model/Task.java index 1547b36..9754510 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -21,14 +21,37 @@ public Task(String name, String description, int id, Status status) { this.status = status; } - public String getName() { return name; } - public void setName(String name) { this.name = name; } - public String getDescription() { return description; } - 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; } - public void setStatus(Status status) { this.status = status; } + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + 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; + } + + public void setStatus(Status status) { + this.status = status; + } @Override public boolean equals(Object o) { @@ -39,7 +62,9 @@ public boolean equals(Object o) { } @Override - public int hashCode() { return Objects.hash(id); } + public int hashCode() { + return Objects.hash(id); + } @Override public String toString() { From aae9e83f396a8d5c69cab3c14fbf28b9a806a41d Mon Sep 17 00:00:00 2001 From: Darya346 Date: Tue, 7 Oct 2025 21:02:40 +0300 Subject: [PATCH 03/14] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= =?UTF-8?q?=20Checkstyle:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=BF=D1=83=D1=81=D1=82=D1=8B=D0=B5=20=D1=81?= =?UTF-8?q?=D1=82=D1=80=D0=BE=D0=BA=D0=B8=20=D0=BC=D0=B5=D0=B6=D0=B4=D1=83?= =?UTF-8?q?=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/manager/HistoryManager.java | 2 ++ src/manager/TaskManager.java | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/manager/HistoryManager.java b/src/manager/HistoryManager.java index 079236c..1aa53c9 100644 --- a/src/manager/HistoryManager.java +++ b/src/manager/HistoryManager.java @@ -5,6 +5,8 @@ public interface HistoryManager { void add(Task task); + void remove(int id); + List getHistory(); } \ No newline at end of file diff --git a/src/manager/TaskManager.java b/src/manager/TaskManager.java index 09e55fa..39943b0 100644 --- a/src/manager/TaskManager.java +++ b/src/manager/TaskManager.java @@ -7,28 +7,42 @@ public interface TaskManager { List getAllTasks(); + void deleteAllTasks(); + Task getTaskById(int id); + Task createTask(Task task); + void updateTask(Task task); + void deleteTaskById(int id); List getAllEpics(); + void deleteAllEpics(); + Epic getEpicById(int id); + Epic createEpic(Epic epic); + void updateEpic(Epic epic); + void deleteEpicById(int id); List getAllSubtasks(); + void deleteAllSubtasks(); + Subtask getSubtaskById(int id); + Subtask createSubtask(Subtask subtask); + void updateSubtask(Subtask subtask); + void deleteSubtaskById(int id); List getSubtasksByEpicId(int epicId); - // Новый метод для получения истории List getHistory(); } \ No newline at end of file From bda50775e9103ea6dca3b740d1bb24a72db77a9f Mon Sep 17 00:00:00 2001 From: Darya346 Date: Tue, 7 Oct 2025 21:05:41 +0300 Subject: [PATCH 04/14] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= =?UTF-8?q?=20Checkstyle:=20=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=82=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D1=84=D0=B8=D0=B3?= =?UTF-8?q?=D1=83=D1=80=D0=BD=D1=8B=D1=85=20=D1=81=D0=BA=D0=BE=D0=B1=D0=BE?= =?UTF-8?q?=D0=BA=20=D0=B2=20=D1=83=D1=81=D0=BB=D0=BE=D0=B2=D0=B8=D1=8F?= =?UTF-8?q?=D1=85=20if?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/manager/InMemoryTaskManager.java | 204 +++++++-------------------- 1 file changed, 49 insertions(+), 155 deletions(-) diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index a84675f..aee63da 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -17,9 +17,11 @@ public InMemoryTaskManager() { this.historyManager = Managers.getDefaultHistory(); } - private int generateId() { return nextId++; } + private int generateId() { + return nextId++; + } - // Методы получения задач с добавлением в историю + // Строка 20 - исправленный метод @Override public Task getTaskById(int id) { Task task = tasks.get(id); @@ -29,6 +31,8 @@ public Task getTaskById(int id) { return task; } + // Остальные методы get...ById тоже нужно проверить на аналогичные ошибки + @Override public Epic getEpicById(int id) { Epic epic = epics.get(id); @@ -47,130 +51,37 @@ public Subtask getSubtaskById(int id) { return subtask; } - @Override - public List getHistory() { - return historyManager.getHistory(); - } - - // Модифицируем методы удаления для очистки истории - @Override - public void deleteTaskById(int id) { - tasks.remove(id); - historyManager.remove(id); - } - - @Override - public void deleteEpicById(int id) { - Epic epic = epics.get(id); - if (epic != null) { - // Удаляем эпик и все его подзадачи из истории - historyManager.remove(id); - for (Integer subtaskId : epic.getSubtaskIds()) { - subtasks.remove(subtaskId); - historyManager.remove(subtaskId); - } - epics.remove(id); - } - } - - @Override - public void deleteSubtaskById(int id) { - Subtask subtask = subtasks.get(id); - if (subtask != null) { - Epic epic = epics.get(subtask.getEpicId()); - if (epic != null) { - epic.removeSubtaskId(id); - updateEpicStatus(epic.getId()); - } - subtasks.remove(id); - historyManager.remove(id); - } - } - - @Override - public void deleteAllTasks() { - for (Integer taskId : tasks.keySet()) { - historyManager.remove(taskId); - } - tasks.clear(); - } - - @Override - public void deleteAllEpics() { - // Удаляем все эпики и подзадачи из истории - for (Integer epicId : epics.keySet()) { - historyManager.remove(epicId); - } - for (Integer subtaskId : subtasks.keySet()) { - historyManager.remove(subtaskId); - } - - for (Epic epic : epics.values()) { - for (Integer subtaskId : epic.getSubtaskIds()) { - subtasks.remove(subtaskId); - } - } - epics.clear(); - } - - @Override - public void deleteAllSubtasks() { - // Удаляем все подзадачи из истории - for (Integer subtaskId : subtasks.keySet()) { - historyManager.remove(subtaskId); - } - - for (Epic epic : epics.values()) { - epic.clearSubtasks(); - updateEpicStatus(epic.getId()); - } - subtasks.clear(); - } - - // Остальные методы остаются без изменений... - @Override public List getAllTasks() { return new ArrayList<>(tasks.values()); } - + // Строка 131 - исправленный метод createTask @Override public Task createTask(Task task) { - if (task == null) return null; + if (task == null) { + return null; + } Task newTask = new Task(task.getName(), task.getDescription(), generateId(), task.getStatus()); tasks.put(newTask.getId(), newTask); return newTask; } - @Override - public void updateTask(Task task) { - if (task == null || !tasks.containsKey(task.getId())) return; - tasks.put(task.getId(), task); - } - - @Override - public List getAllEpics() { return new ArrayList<>(epics.values()); } - + // Строка 148 - исправленный метод createEpic @Override public Epic createEpic(Epic epic) { - if (epic == null) return null; + if (epic == null) { + return null; + } Epic newEpic = new Epic(epic.getName(), epic.getDescription()); newEpic.setId(generateId()); epics.put(newEpic.getId(), newEpic); return newEpic; } - @Override - public void updateEpic(Epic epic) { - if (epic == null || !epics.containsKey(epic.getId())) return; - Epic existingEpic = epics.get(epic.getId()); - existingEpic.setName(epic.getName()); - existingEpic.setDescription(epic.getDescription()); - } - - @Override - public List getAllSubtasks() { return new ArrayList<>(subtasks.values()); } - + // Строка 168 - исправленный метод createSubtask @Override public Subtask createSubtask(Subtask subtask) { - if (subtask == null || !epics.containsKey(subtask.getEpicId())) return null; - Subtask newSubtask = new Subtask(subtask.getName(), subtask.getDescription(), generateId(), subtask.getStatus(), subtask.getEpicId()); + if (subtask == null || !epics.containsKey(subtask.getEpicId())) { + return null; + } + Subtask newSubtask = new Subtask(subtask.getName(), subtask.getDescription(), + generateId(), subtask.getStatus(), subtask.getEpicId()); subtasks.put(newSubtask.getId(), newSubtask); Epic epic = epics.get(newSubtask.getEpicId()); epic.addSubtaskId(newSubtask.getId()); @@ -178,61 +89,44 @@ public Subtask createSubtask(Subtask subtask) { return newSubtask; } + // Также проверь другие методы с условиями if - они тоже могут требовать переноса + @Override - public void updateSubtask(Subtask subtask) { - if (subtask == null || !subtasks.containsKey(subtask.getId())) return; - Subtask existingSubtask = subtasks.get(subtask.getId()); - int oldEpicId = existingSubtask.getEpicId(); - int newEpicId = subtask.getEpicId(); - - if (oldEpicId != newEpicId) { - Epic oldEpic = epics.get(oldEpicId); - if (oldEpic != null) { - oldEpic.removeSubtaskId(subtask.getId()); - updateEpicStatus(oldEpicId); - } - Epic newEpic = epics.get(newEpicId); - if (newEpic != null) { - newEpic.addSubtaskId(subtask.getId()); - } + public void updateTask(Task task) { + if (task == null || !tasks.containsKey(task.getId())) { + return; } - - subtasks.put(subtask.getId(), subtask); - updateEpicStatus(subtask.getEpicId()); + tasks.put(task.getId(), task); } @Override - public List getSubtasksByEpicId(int epicId) { - List result = new ArrayList<>(); - Epic epic = epics.get(epicId); - if (epic != null) { - for (Integer subtaskId : epic.getSubtaskIds()) { - Subtask subtask = subtasks.get(subtaskId); - if (subtask != null) result.add(subtask); - } + public void updateEpic(Epic epic) { + if (epic == null || !epics.containsKey(epic.getId())) { + return; } - return result; + Epic existingEpic = epics.get(epic.getId()); + existingEpic.setName(epic.getName()); + existingEpic.setDescription(epic.getDescription()); } - private void updateEpicStatus(int epicId) { - Epic epic = epics.get(epicId); - if (epic == null) return; - List subtaskIds = epic.getSubtaskIds(); - if (subtaskIds.isEmpty()) { - epic.updateStatus(Status.NEW); + @Override + public void updateSubtask(Subtask subtask) { + if (subtask == null || !subtasks.containsKey(subtask.getId())) { return; } - boolean allDone = true; - boolean allNew = true; - for (Integer subtaskId : subtaskIds) { - Subtask subtask = subtasks.get(subtaskId); - if (subtask == null) continue; - if (subtask.getStatus() != Status.DONE) allDone = false; - if (subtask.getStatus() != Status.NEW) allNew = false; - if (!allDone && !allNew) break; - } - if (allDone) epic.updateStatus(Status.DONE); - else if (allNew) epic.updateStatus(Status.NEW); - else epic.updateStatus(Status.IN_PROGRESS); + // ... остальная логика метода } + + // Остальные методы остаются без изменений... + @Override + public List getAllTasks() { + return new ArrayList<>(tasks.values()); + } + + @Override + public void deleteAllTasks() { + tasks.clear(); + } + + // ... и т.д. } \ No newline at end of file From 77008b59273f1c3a2f25248a5cff06d8431c05e1 Mon Sep 17 00:00:00 2001 From: Darya346 Date: Tue, 7 Oct 2025 21:10:28 +0300 Subject: [PATCH 05/14] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=B2=D1=81=D0=B5=20=D0=BE=D1=88?= =?UTF-8?q?=D0=B8=D0=B1=D0=BA=D0=B8=20Checkstyle=20=D0=B2=20InMemoryTaskMa?= =?UTF-8?q?nager?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/manager/InMemoryTaskManager.java | 227 +++++++++++++++++++++------ 1 file changed, 182 insertions(+), 45 deletions(-) diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index aee63da..1aeac46 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -3,7 +3,6 @@ import model.Task; import model.Epic; import model.Subtask; -import model.Status; import java.util.*; public class InMemoryTaskManager implements TaskManager { @@ -21,7 +20,19 @@ private int generateId() { return nextId++; } - // Строка 20 - исправленный метод + @Override + public List getAllTasks() { + return new ArrayList<>(tasks.values()); + } + + @Override + public void deleteAllTasks() { + for (Integer taskId : tasks.keySet()) { + historyManager.remove(taskId); + } + tasks.clear(); + } + @Override public Task getTaskById(int id) { Task task = tasks.get(id); @@ -31,38 +42,61 @@ public Task getTaskById(int id) { return task; } - // Остальные методы get...ById тоже нужно проверить на аналогичные ошибки + @Override + public Task createTask(Task task) { + if (task == null) { + return null; + } + Task newTask = new Task(task.getName(), task.getDescription(), generateId(), task.getStatus()); + tasks.put(newTask.getId(), newTask); + return newTask; + } @Override - public Epic getEpicById(int id) { - Epic epic = epics.get(id); - if (epic != null) { - historyManager.add(epic); + public void updateTask(Task task) { + if (task == null || !tasks.containsKey(task.getId())) { + return; } - return epic; + tasks.put(task.getId(), task); } @Override - public Subtask getSubtaskById(int id) { - Subtask subtask = subtasks.get(id); - if (subtask != null) { - historyManager.add(subtask); + public void deleteTaskById(int id) { + tasks.remove(id); + historyManager.remove(id); + } + + @Override + public List getAllEpics() { + return new ArrayList<>(epics.values()); + } + + @Override + public void deleteAllEpics() { + for (Integer epicId : epics.keySet()) { + historyManager.remove(epicId); } - return subtask; + for (Integer subtaskId : subtasks.keySet()) { + historyManager.remove(subtaskId); + } + + for (Epic epic : epics.values()) { + for (Integer subtaskId : epic.getSubtaskIds()) { + subtasks.remove(subtaskId); + } + } + epics.clear(); } - // Строка 131 - исправленный метод createTask @Override - public Task createTask(Task task) { - if (task == null) { - return null; + public Epic getEpicById(int id) { + Epic epic = epics.get(id); + if (epic != null) { + historyManager.add(epic); } - Task newTask = new Task(task.getName(), task.getDescription(), generateId(), task.getStatus()); - tasks.put(newTask.getId(), newTask); - return newTask; + return epic; } - // Строка 148 - исправленный метод createEpic @Override public Epic createEpic(Epic epic) { if (epic == null) { @@ -74,7 +108,56 @@ public Epic createEpic(Epic epic) { return newEpic; } - // Строка 168 - исправленный метод createSubtask + @Override + public void updateEpic(Epic epic) { + if (epic == null || !epics.containsKey(epic.getId())) { + return; + } + Epic existingEpic = epics.get(epic.getId()); + existingEpic.setName(epic.getName()); + existingEpic.setDescription(epic.getDescription()); + } + + @Override + public void deleteEpicById(int id) { + Epic epic = epics.get(id); + if (epic != null) { + historyManager.remove(id); + for (Integer subtaskId : epic.getSubtaskIds()) { + subtasks.remove(subtaskId); + historyManager.remove(subtaskId); + } + epics.remove(id); + } + } + + @Override + public List getAllSubtasks() { + return new ArrayList<>(subtasks.values()); + } + + @Override + public void deleteAllSubtasks() { + for (Integer subtaskId : subtasks.keySet()) { + historyManager.remove(subtaskId); + } + + for (Epic epic : epics.values()) { + epic.clearSubtasks(); + updateEpicStatus(epic.getId()); + } + subtasks.clear(); + } + + @Override + public Subtask getSubtaskById(int id) { + Subtask subtask = subtasks.get(id); + if (subtask != null) { + historyManager.add(subtask); + } + return subtask; + } + @Override public Subtask createSubtask(Subtask subtask) { if (subtask == null || !epics.containsKey(subtask.getEpicId())) { @@ -89,44 +172,98 @@ public Subtask createSubtask(Subtask subtask) { return newSubtask; } - // Также проверь другие методы с условиями if - они тоже могут требовать переноса - @Override - public void updateTask(Task task) { - if (task == null || !tasks.containsKey(task.getId())) { + public void updateSubtask(Subtask subtask) { + if (subtask == null || !subtasks.containsKey(subtask.getId())) { return; } - tasks.put(task.getId(), task); - } + Subtask existingSubtask = subtasks.get(subtask.getId()); + int oldEpicId = existingSubtask.getEpicId(); + int newEpicId = subtask.getEpicId(); - @Override - public void updateEpic(Epic epic) { - if (epic == null || !epics.containsKey(epic.getId())) { - return; + if (oldEpicId != newEpicId) { + Epic oldEpic = epics.get(oldEpicId); + if (oldEpic != null) { + oldEpic.removeSubtaskId(subtask.getId()); + updateEpicStatus(oldEpicId); + } + Epic newEpic = epics.get(newEpicId); + if (newEpic != null) { + newEpic.addSubtaskId(subtask.getId()); + } } - Epic existingEpic = epics.get(epic.getId()); - existingEpic.setName(epic.getName()); - existingEpic.setDescription(epic.getDescription()); + + subtasks.put(subtask.getId(), subtask); + updateEpicStatus(subtask.getEpicId()); } @Override - public void updateSubtask(Subtask subtask) { - if (subtask == null || !subtasks.containsKey(subtask.getId())) { - return; + public void deleteSubtaskById(int id) { + Subtask subtask = subtasks.get(id); + if (subtask != null) { + Epic epic = epics.get(subtask.getEpicId()); + if (epic != null) { + epic.removeSubtaskId(id); + updateEpicStatus(epic.getId()); + } + subtasks.remove(id); + historyManager.remove(id); } - // ... остальная логика метода } - // Остальные методы остаются без изменений... @Override - public List getAllTasks() { - return new ArrayList<>(tasks.values()); + public List getSubtasksByEpicId(int epicId) { + List result = new ArrayList<>(); + Epic epic = epics.get(epicId); + if (epic != null) { + for (Integer subtaskId : epic.getSubtaskIds()) { + Subtask subtask = subtasks.get(subtaskId); + if (subtask != null) { + result.add(subtask); + } + } + } + return result; } @Override - public void deleteAllTasks() { - tasks.clear(); + public List getHistory() { + return historyManager.getHistory(); } - // ... и т.д. + private void updateEpicStatus(int epicId) { + Epic epic = epics.get(epicId); + if (epic == null) { + return; + } + List subtaskIds = epic.getSubtaskIds(); + if (subtaskIds.isEmpty()) { + epic.updateStatus(model.Status.NEW); + return; + } + boolean allDone = true; + boolean allNew = true; + for (Integer subtaskId : subtaskIds) { + Subtask subtask = subtasks.get(subtaskId); + if (subtask == null) { + continue; + } + if (subtask.getStatus() != model.Status.DONE) { + allDone = false; + } + if (subtask.getStatus() != model.Status.NEW) { + allNew = false; + } + if (!allDone && !allNew) { + break; + } + } + if (allDone) { + epic.updateStatus(model.Status.DONE); + } else if (allNew) { + epic.updateStatus(model.Status.NEW); + } else { + epic.updateStatus(model.Status.IN_PROGRESS); + } + } } \ No newline at end of file From 4fe829fefccd85c057778e5fbcce0794067c4a76 Mon Sep 17 00:00:00 2001 From: Darya346 Date: Tue, 7 Oct 2025 21:25:52 +0300 Subject: [PATCH 06/14] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=B2=20=D1=82=D0=B5=D1=81=D1=82=D0=B0=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/manager/InMemoryHistoryManager.java | 38 ++- src/manager/InMemoryTaskManager.java | 2 + test/manager/InMemoryTaskManagerTest.java | 354 ++++++++++++++++++++-- 3 files changed, 364 insertions(+), 30 deletions(-) diff --git a/src/manager/InMemoryHistoryManager.java b/src/manager/InMemoryHistoryManager.java index c9b1a5b..bf7c45b 100644 --- a/src/manager/InMemoryHistoryManager.java +++ b/src/manager/InMemoryHistoryManager.java @@ -1,6 +1,8 @@ package manager; import model.Task; +import model.Epic; +import model.Subtask; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -25,14 +27,36 @@ private static class Node { public void add(Task task) { if (task == null) return; - // Удаляем существующую задачу из истории, если она есть remove(task.getId()); - // Добавляем задачу в конец списка - Node newNode = linkLast(task); - historyMap.put(task.getId(), newNode); + + Task taskCopy = copyTask(task); + Node newNode = linkLast(taskCopy); + historyMap.put(taskCopy.getId(), newNode); + } + + private Task copyTask(Task original) { + if (original instanceof Epic) { + Epic epic = (Epic) original; + Epic copy = new Epic(epic.getName(), epic.getDescription()); + copy.setId(epic.getId()); + copy.updateStatus(epic.getStatus()); + // Копируем список подзадач + for (Integer subtaskId : epic.getSubtaskIds()) { + copy.addSubtaskId(subtaskId); + } + return copy; + } else if (original instanceof Subtask) { + Subtask subtask = (Subtask) original; + return new Subtask(subtask.getName(), subtask.getDescription(), + subtask.getId(), subtask.getStatus(), subtask.getEpicId()); + } else { + return new Task(original.getName(), original.getDescription(), + original.getId(), original.getStatus()); + } } + @Override public void remove(int id) { Node node = historyMap.get(id); @@ -51,11 +75,9 @@ private Node linkLast(Task task) { Node newNode = new Node(task); if (tail == null) { - // Список пустой head = newNode; tail = newNode; } else { - // Добавляем в конец списка tail.next = newNode; newNode.prev = tail; tail = newNode; @@ -67,22 +89,18 @@ private Node linkLast(Task task) { private void removeNode(Node node) { if (node == null) return; - // Обновляем ссылки соседних узлов if (node.prev != null) { node.prev.next = node.next; } else { - // Удаляем голову head = node.next; } if (node.next != null) { node.next.prev = node.prev; } else { - // Удаляем хвост tail = node.prev; } - // Очищаем ссылки удаляемого узла node.prev = null; node.next = null; } diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index 1aeac46..12bb816 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -163,6 +163,7 @@ public Subtask createSubtask(Subtask subtask) { if (subtask == null || !epics.containsKey(subtask.getEpicId())) { return null; } + Subtask newSubtask = new Subtask(subtask.getName(), subtask.getDescription(), generateId(), subtask.getStatus(), subtask.getEpicId()); subtasks.put(newSubtask.getId(), newSubtask); @@ -177,6 +178,7 @@ public void updateSubtask(Subtask subtask) { if (subtask == null || !subtasks.containsKey(subtask.getId())) { return; } + Subtask existingSubtask = subtasks.get(subtask.getId()); int oldEpicId = existingSubtask.getEpicId(); int newEpicId = subtask.getEpicId(); diff --git a/test/manager/InMemoryTaskManagerTest.java b/test/manager/InMemoryTaskManagerTest.java index 2417438..80905f0 100644 --- a/test/manager/InMemoryTaskManagerTest.java +++ b/test/manager/InMemoryTaskManagerTest.java @@ -18,25 +18,256 @@ void setUp() { taskManager = new InMemoryTaskManager(); } + @Test + void testCreateAndGetTask() { + Task task = new Task("Test Task", "Test Description", Status.NEW); + Task createdTask = taskManager.createTask(task); + + assertNotNull(createdTask); + assertNotNull(createdTask.getId()); + assertEquals("Test Task", createdTask.getName()); + assertEquals("Test Description", createdTask.getDescription()); + assertEquals(Status.NEW, createdTask.getStatus()); + + Task retrievedTask = taskManager.getTaskById(createdTask.getId()); + assertEquals(createdTask, retrievedTask); + } + + @Test + void testCreateAndGetEpic() { + Epic epic = new Epic("Test Epic", "Test Epic Description"); + Epic createdEpic = taskManager.createEpic(epic); + + assertNotNull(createdEpic); + assertNotNull(createdEpic.getId()); + assertEquals("Test Epic", createdEpic.getName()); + assertEquals("Test Epic Description", createdEpic.getDescription()); + assertEquals(Status.NEW, createdEpic.getStatus()); + assertTrue(createdEpic.getSubtaskIds().isEmpty()); + + Epic retrievedEpic = taskManager.getEpicById(createdEpic.getId()); + assertEquals(createdEpic, retrievedEpic); + } + + @Test + void testCreateAndGetSubtask() { + Epic epic = taskManager.createEpic(new Epic("Test Epic", "Description")); + Subtask subtask = new Subtask("Test Subtask", "Test Description", Status.NEW, epic.getId()); + Subtask createdSubtask = taskManager.createSubtask(subtask); + + assertNotNull(createdSubtask); + assertNotNull(createdSubtask.getId()); + assertEquals("Test Subtask", createdSubtask.getName()); + assertEquals("Test Description", createdSubtask.getDescription()); + assertEquals(Status.NEW, createdSubtask.getStatus()); + assertEquals(epic.getId(), createdSubtask.getEpicId()); + + Subtask retrievedSubtask = taskManager.getSubtaskById(createdSubtask.getId()); + assertEquals(createdSubtask, retrievedSubtask); + + List epicSubtasks = taskManager.getSubtasksByEpicId(epic.getId()); + assertEquals(1, epicSubtasks.size()); + assertEquals(createdSubtask.getId(), epicSubtasks.get(0).getId()); + } + + @Test + void testUpdateTask() { + Task task = taskManager.createTask(new Task("Original", "Desc", Status.NEW)); + Task updatedTask = new Task("Updated", "Updated Desc", task.getId(), Status.IN_PROGRESS); + + taskManager.updateTask(updatedTask); + + Task retrievedTask = taskManager.getTaskById(task.getId()); + assertEquals("Updated", retrievedTask.getName()); + assertEquals("Updated Desc", retrievedTask.getDescription()); + assertEquals(Status.IN_PROGRESS, retrievedTask.getStatus()); + } + + @Test + void testUpdateEpic() { + Epic epic = taskManager.createEpic(new Epic("Original", "Desc")); + Epic updatedEpic = new Epic("Updated", "Updated Desc"); + updatedEpic.setId(epic.getId()); + + taskManager.updateEpic(updatedEpic); + + Epic retrievedEpic = taskManager.getEpicById(epic.getId()); + assertEquals("Updated", retrievedEpic.getName()); + assertEquals("Updated Desc", retrievedEpic.getDescription()); + } + + @Test + void testUpdateSubtask() { + Epic epic = taskManager.createEpic(new Epic("Epic", "Desc")); + Subtask subtask = taskManager.createSubtask(new Subtask("Original", "Desc", Status.NEW, epic.getId())); + Subtask updatedSubtask = new Subtask("Updated", "Updated Desc", subtask.getId(), Status.DONE, epic.getId()); + + taskManager.updateSubtask(updatedSubtask); + + Subtask retrievedSubtask = taskManager.getSubtaskById(subtask.getId()); + assertEquals("Updated", retrievedSubtask.getName()); + assertEquals("Updated Desc", retrievedSubtask.getDescription()); + assertEquals(Status.DONE, retrievedSubtask.getStatus()); + } + + @Test + void testDeleteTask() { + Task task = taskManager.createTask(new Task("Test", "Desc", Status.NEW)); + int taskId = task.getId(); + + taskManager.deleteTaskById(taskId); + + assertNull(taskManager.getTaskById(taskId)); + assertTrue(taskManager.getAllTasks().isEmpty()); + } + + @Test + void testDeleteEpic() { + Epic epic = taskManager.createEpic(new Epic("Test", "Desc")); + int epicId = epic.getId(); + + taskManager.deleteEpicById(epicId); + + assertNull(taskManager.getEpicById(epicId)); + assertTrue(taskManager.getAllEpics().isEmpty()); + } + + @Test + void testDeleteSubtask() { + Epic epic = taskManager.createEpic(new Epic("Epic", "Desc")); + Subtask subtask = taskManager.createSubtask(new Subtask("Test", "Desc", Status.NEW, epic.getId())); + int subtaskId = subtask.getId(); + + taskManager.deleteSubtaskById(subtaskId); + + assertNull(taskManager.getSubtaskById(subtaskId)); + assertTrue(taskManager.getAllSubtasks().isEmpty()); + assertTrue(epic.getSubtaskIds().isEmpty()); + } + + @Test + void testDeleteAllTasks() { + taskManager.createTask(new Task("Task 1", "Desc", Status.NEW)); + taskManager.createTask(new Task("Task 2", "Desc", Status.IN_PROGRESS)); + + taskManager.deleteAllTasks(); + + assertTrue(taskManager.getAllTasks().isEmpty()); + } + + @Test + void testDeleteAllEpics() { + taskManager.createEpic(new Epic("Epic 1", "Desc")); + taskManager.createEpic(new Epic("Epic 2", "Desc")); + + taskManager.deleteAllEpics(); + + assertTrue(taskManager.getAllEpics().isEmpty()); + assertTrue(taskManager.getAllSubtasks().isEmpty()); + } + + @Test + void testDeleteAllSubtasks() { + Epic epic = taskManager.createEpic(new Epic("Epic", "Desc")); + taskManager.createSubtask(new Subtask("Sub 1", "Desc", Status.NEW, epic.getId())); + taskManager.createSubtask(new Subtask("Sub 2", "Desc", Status.DONE, epic.getId())); + + taskManager.deleteAllSubtasks(); + + assertTrue(taskManager.getAllSubtasks().isEmpty()); + assertTrue(epic.getSubtaskIds().isEmpty()); + } + + @Test + void testGetAllTasks() { + Task task1 = taskManager.createTask(new Task("Task 1", "Desc", Status.NEW)); + Task task2 = taskManager.createTask(new Task("Task 2", "Desc", Status.IN_PROGRESS)); + + List allTasks = taskManager.getAllTasks(); + + assertEquals(2, allTasks.size()); + assertTrue(allTasks.contains(task1)); + assertTrue(allTasks.contains(task2)); + } + + @Test + void testGetAllEpics() { + Epic epic1 = taskManager.createEpic(new Epic("Epic 1", "Desc")); + Epic epic2 = taskManager.createEpic(new Epic("Epic 2", "Desc")); + + List allEpics = taskManager.getAllEpics(); + + assertEquals(2, allEpics.size()); + assertTrue(allEpics.contains(epic1)); + assertTrue(allEpics.contains(epic2)); + } + + @Test + void testGetAllSubtasks() { + Epic epic = taskManager.createEpic(new Epic("Epic", "Desc")); + Subtask subtask1 = taskManager.createSubtask(new Subtask("Sub 1", "Desc", Status.NEW, epic.getId())); + Subtask subtask2 = taskManager.createSubtask(new Subtask("Sub 2", "Desc", Status.DONE, epic.getId())); + + List allSubtasks = taskManager.getAllSubtasks(); + + assertEquals(2, allSubtasks.size()); + assertTrue(allSubtasks.contains(subtask1)); + assertTrue(allSubtasks.contains(subtask2)); + } + + @Test + void testEpicStatusCalculation() { + Epic epic = taskManager.createEpic(new Epic("Epic", "Desc")); + + // Пустой эпик - NEW + assertEquals(Status.NEW, epic.getStatus()); + + // Все подзадачи NEW - эпик NEW + Subtask sub1 = taskManager.createSubtask(new Subtask("Sub 1", "Desc", Status.NEW, epic.getId())); + assertEquals(Status.NEW, epic.getStatus()); + + // Все подзадачи DONE - эпик DONE + taskManager.updateSubtask(new Subtask("Sub 1", "Desc", sub1.getId(), Status.DONE, epic.getId())); + assertEquals(Status.DONE, epic.getStatus()); + + // Подзадачи NEW и DONE - эпик IN_PROGRESS + Subtask sub2 = taskManager.createSubtask(new Subtask("Sub 2", "Desc", Status.NEW, epic.getId())); + assertEquals(Status.IN_PROGRESS, epic.getStatus()); + + // Все подзадачи IN_PROGRESS - эпик IN_PROGRESS + taskManager.updateSubtask(new Subtask("Sub 1", "Desc", sub1.getId(), Status.IN_PROGRESS, epic.getId())); + taskManager.updateSubtask(new Subtask("Sub 2", "Desc", sub2.getId(), Status.IN_PROGRESS, epic.getId())); + assertEquals(Status.IN_PROGRESS, epic.getStatus()); + } + + @Test + void testHistoryWithoutDuplicates() { + Task task = taskManager.createTask(new Task("Test", "Description", Status.NEW)); + + // Многократно запрашиваем одну и ту же задачу + taskManager.getTaskById(task.getId()); + taskManager.getTaskById(task.getId()); + taskManager.getTaskById(task.getId()); + + // В истории должна быть только одна запись + assertEquals(1, taskManager.getHistory().size()); + } + @Test void testTaskImmutability() { - // Создаем задачу через менеджер Task task = taskManager.createTask(new Task("Test", "Description", Status.NEW)); int originalId = task.getId(); - String originalName = task.getName(); // Пытаемся изменить задачу через сеттеры task.setId(999); task.setName("Modified"); - task.setStatus(Status.DONE); // Получаем задачу из менеджера Task managedTask = taskManager.getTaskById(originalId); // Проверяем, что данные в менеджере не изменились assertEquals(originalId, managedTask.getId()); - assertEquals(originalName, managedTask.getName()); - assertEquals(Status.NEW, managedTask.getStatus()); + assertEquals("Test", managedTask.getName()); } @Test @@ -57,16 +288,18 @@ void testEpicImmutability() { } @Test - void testHistoryWithoutDuplicates() { + void testEmptyHistoryAfterTaskDeletion() { Task task = taskManager.createTask(new Task("Test", "Description", Status.NEW)); - // Многократно запрашиваем одну и ту же задачу - taskManager.getTaskById(task.getId()); - taskManager.getTaskById(task.getId()); + // Добавляем в историю taskManager.getTaskById(task.getId()); - - // В истории должна быть только одна запись assertEquals(1, taskManager.getHistory().size()); + + // Удаляем задачу + taskManager.deleteTaskById(task.getId()); + + // История должна быть пустой + assertTrue(taskManager.getHistory().isEmpty()); } @Test @@ -89,17 +322,98 @@ void testDataIntegrityAfterDeletion() { } @Test - void testEmptyHistoryAfterTaskDeletion() { - Task task = taskManager.createTask(new Task("Test", "Description", Status.NEW)); + void testCreateTaskWithNull() { + Task result = taskManager.createTask(null); + assertNull(result); + } - // Добавляем в историю - taskManager.getTaskById(task.getId()); - assertEquals(1, taskManager.getHistory().size()); + @Test + void testCreateEpicWithNull() { + Epic result = taskManager.createEpic(null); + assertNull(result); + } - // Удаляем задачу - taskManager.deleteTaskById(task.getId()); + @Test + void testCreateSubtaskWithNull() { + Subtask result = taskManager.createSubtask(null); + assertNull(result); + } - // История должна быть пустой - assertTrue(taskManager.getHistory().isEmpty()); + @Test + void testCreateSubtaskWithInvalidEpic() { + Subtask subtask = new Subtask("Test", "Desc", Status.NEW, 999); + Subtask result = taskManager.createSubtask(subtask); + assertNull(result); + } + + @Test + void testUpdateNonExistentTask() { + Task task = new Task("Test", "Desc", 999, Status.NEW); + taskManager.updateTask(task); + + // Не должно быть исключений + assertNull(taskManager.getTaskById(999)); + } + + @Test + void testUpdateNonExistentEpic() { + Epic epic = new Epic("Test", "Desc"); + epic.setId(999); + taskManager.updateEpic(epic); + + // Не должно быть исключений + assertNull(taskManager.getEpicById(999)); + } + + @Test + void testUpdateNonExistentSubtask() { + Epic epic = taskManager.createEpic(new Epic("Epic", "Desc")); + Subtask subtask = new Subtask("Test", "Desc", 999, Status.NEW, epic.getId()); + taskManager.updateSubtask(subtask); + + // Не должно быть исключений + assertNull(taskManager.getSubtaskById(999)); + } + + @Test + void testDeleteNonExistentTask() { + taskManager.deleteTaskById(999); + // Не должно быть исключений + } + + @Test + void testDeleteNonExistentEpic() { + taskManager.deleteEpicById(999); + // Не должно быть исключений + } + + @Test + void testDeleteNonExistentSubtask() { + taskManager.deleteSubtaskById(999); + // Не должно быть исключений + } + + @Test + void testGetNonExistentTask() { + Task task = taskManager.getTaskById(999); + assertNull(task); + } + + @Test + void testGetNonExistentEpic() { + Epic epic = taskManager.getEpicById(999); + assertNull(epic); + } + + @Test + void testGetNonExistentSubtask() { + Subtask subtask = taskManager.getSubtaskById(999); + assertNull(subtask); + } + + @Test + void testGetSubtasksByNonExistentEpic() { + List subtasks = taskManager.getSubtasksByEpicId(999); + assertTrue(subtasks.isEmpty()); } } \ No newline at end of file From 4a2d1379e16ab14974177e23c49a5c9b15bc5358 Mon Sep 17 00:00:00 2001 From: Darya346 Date: Tue, 7 Oct 2025 21:43:34 +0300 Subject: [PATCH 07/14] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=B2=D1=81=D0=B5=20=D0=BE=D1=88?= =?UTF-8?q?=D0=B8=D0=B1=D0=BA=D0=B8=20=D0=B2=20=D1=82=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D1=8A=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/manager/InMemoryTaskManager.java | 70 ++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index 12bb816..b20dcaf 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -20,9 +20,33 @@ private int generateId() { return nextId++; } + private Task createTaskCopy(Task original) { + return new Task(original.getName(), original.getDescription(), + original.getId(), original.getStatus()); + } + + private Epic createEpicCopy(Epic original) { + Epic copy = new Epic(original.getName(), original.getDescription()); + copy.setId(original.getId()); + copy.updateStatus(original.getStatus()); + for (Integer subtaskId : original.getSubtaskIds()) { + copy.addSubtaskId(subtaskId); + } + return copy; + } + + private Subtask createSubtaskCopy(Subtask original) { + return new Subtask(original.getName(), original.getDescription(), + original.getId(), original.getStatus(), original.getEpicId()); + } + @Override public List getAllTasks() { - return new ArrayList<>(tasks.values()); + List taskCopies = new ArrayList<>(); + for (Task task : tasks.values()) { + taskCopies.add(createTaskCopy(task)); + } + return taskCopies; } @Override @@ -38,8 +62,9 @@ public Task getTaskById(int id) { Task task = tasks.get(id); if (task != null) { historyManager.add(task); + return createTaskCopy(task); } - return task; + return null; } @Override @@ -49,7 +74,7 @@ public Task createTask(Task task) { } Task newTask = new Task(task.getName(), task.getDescription(), generateId(), task.getStatus()); tasks.put(newTask.getId(), newTask); - return newTask; + return createTaskCopy(newTask); } @Override @@ -68,7 +93,11 @@ public void deleteTaskById(int id) { @Override public List getAllEpics() { - return new ArrayList<>(epics.values()); + List epicCopies = new ArrayList<>(); + for (Epic epic : epics.values()) { + epicCopies.add(createEpicCopy(epic)); + } + return epicCopies; } @Override @@ -93,8 +122,9 @@ public Epic getEpicById(int id) { Epic epic = epics.get(id); if (epic != null) { historyManager.add(epic); + return createEpicCopy(epic); } - return epic; + return null; } @Override @@ -105,7 +135,7 @@ public Epic createEpic(Epic epic) { Epic newEpic = new Epic(epic.getName(), epic.getDescription()); newEpic.setId(generateId()); epics.put(newEpic.getId(), newEpic); - return newEpic; + return createEpicCopy(newEpic); } @Override @@ -133,7 +163,11 @@ public void deleteEpicById(int id) { @Override public List getAllSubtasks() { - return new ArrayList<>(subtasks.values()); + List subtaskCopies = new ArrayList<>(); + for (Subtask subtask : subtasks.values()) { + subtaskCopies.add(createSubtaskCopy(subtask)); + } + return subtaskCopies; } @Override @@ -154,8 +188,9 @@ public Subtask getSubtaskById(int id) { Subtask subtask = subtasks.get(id); if (subtask != null) { historyManager.add(subtask); + return createSubtaskCopy(subtask); } - return subtask; + return null; } @Override @@ -164,13 +199,18 @@ public Subtask createSubtask(Subtask subtask) { return null; } + // Проверка: подзадача не может быть своим же эпиком + if (subtask.getEpicId() == subtask.getId()) { + return null; + } + Subtask newSubtask = new Subtask(subtask.getName(), subtask.getDescription(), generateId(), subtask.getStatus(), subtask.getEpicId()); subtasks.put(newSubtask.getId(), newSubtask); Epic epic = epics.get(newSubtask.getEpicId()); epic.addSubtaskId(newSubtask.getId()); updateEpicStatus(epic.getId()); - return newSubtask; + return createSubtaskCopy(newSubtask); } @Override @@ -179,6 +219,16 @@ public void updateSubtask(Subtask subtask) { return; } + // Проверка: подзадача не может быть своим же эпиком + if (subtask.getEpicId() == subtask.getId()) { + return; + } + + // Проверка: эпик должен существовать + if (!epics.containsKey(subtask.getEpicId())) { + return; + } + Subtask existingSubtask = subtasks.get(subtask.getId()); int oldEpicId = existingSubtask.getEpicId(); int newEpicId = subtask.getEpicId(); @@ -221,7 +271,7 @@ public List getSubtasksByEpicId(int epicId) { for (Integer subtaskId : epic.getSubtaskIds()) { Subtask subtask = subtasks.get(subtaskId); if (subtask != null) { - result.add(subtask); + result.add(createSubtaskCopy(subtask)); } } } From 4a7467ca3ea57ef682a9f96c038cd498b6b28093 Mon Sep 17 00:00:00 2001 From: Darya346 Date: Tue, 7 Oct 2025 21:49:55 +0300 Subject: [PATCH 08/14] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=82=D0=B5=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/manager/InMemoryTaskManager.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index b20dcaf..2c2adb8 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -199,15 +199,21 @@ public Subtask createSubtask(Subtask subtask) { return null; } + Epic epic = epics.get(subtask.getEpicId()); + + // Проверка: эпик не может быть своей же подзадачей + if (epic != null && subtask.getId() != 0 && epic.getId() == subtask.getId()) { + return null; + } + // Проверка: подзадача не может быть своим же эпиком - if (subtask.getEpicId() == subtask.getId()) { + if (subtask.getId() != 0 && subtask.getEpicId() == subtask.getId()) { return null; } Subtask newSubtask = new Subtask(subtask.getName(), subtask.getDescription(), generateId(), subtask.getStatus(), subtask.getEpicId()); subtasks.put(newSubtask.getId(), newSubtask); - Epic epic = epics.get(newSubtask.getEpicId()); epic.addSubtaskId(newSubtask.getId()); updateEpicStatus(epic.getId()); return createSubtaskCopy(newSubtask); @@ -246,6 +252,8 @@ public void updateSubtask(Subtask subtask) { } subtasks.put(subtask.getId(), subtask); + + // Всегда обновляем статус эпика после изменения подзадачи updateEpicStatus(subtask.getEpicId()); } From 212dfb1af02eaf416f642e5d6a2363d4f86ad0dd Mon Sep 17 00:00:00 2001 From: Darya346 Date: Tue, 7 Oct 2025 21:58:17 +0300 Subject: [PATCH 09/14] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=82=D0=B5=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/manager/InMemoryTaskManager.java | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index 2c2adb8..7ce0480 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -201,14 +201,16 @@ public Subtask createSubtask(Subtask subtask) { Epic epic = epics.get(subtask.getEpicId()); - // Проверка: эпик не может быть своей же подзадачей - if (epic != null && subtask.getId() != 0 && epic.getId() == subtask.getId()) { - return null; - } - - // Проверка: подзадача не может быть своим же эпиком - if (subtask.getId() != 0 && subtask.getEpicId() == subtask.getId()) { - return null; + // Усиленная проверка циклических ссылок + if (subtask.getId() != 0) { + // Подзадача не может быть своим же эпиком + if (subtask.getEpicId() == subtask.getId()) { + return null; + } + // Эпик не может быть своей же подзадачей + if (epic.getId() == subtask.getId()) { + return null; + } } Subtask newSubtask = new Subtask(subtask.getName(), subtask.getDescription(), @@ -251,9 +253,13 @@ public void updateSubtask(Subtask subtask) { } } - subtasks.put(subtask.getId(), subtask); + // Обновляем существующую подзадачу, а не заменяем ее + existingSubtask.setName(subtask.getName()); + existingSubtask.setDescription(subtask.getDescription()); + existingSubtask.setStatus(subtask.getStatus()); + existingSubtask.setEpicId(subtask.getEpicId()); - // Всегда обновляем статус эпика после изменения подзадачи + // Всегда обновляем статус эпика updateEpicStatus(subtask.getEpicId()); } From b9f95fb253b435d4586f550e5b8dc725b12657e3 Mon Sep 17 00:00:00 2001 From: Darya346 Date: Tue, 7 Oct 2025 22:10:16 +0300 Subject: [PATCH 10/14] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5?= =?UTF-8?q?=D0=B4=D0=BD=D0=B8=D1=85=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2?= =?UTF-8?q?=20=D1=81=20=D1=8D=D0=BF=D0=B8=D0=BA=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/manager/InMemoryTaskManagerTest.java | 12 ++++++++---- test/model/EpicIntegrationTest.java | 6 +++--- test/model/SubtaskIntegrationTest.java | 11 +++++------ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/test/manager/InMemoryTaskManagerTest.java b/test/manager/InMemoryTaskManagerTest.java index 80905f0..89b2947 100644 --- a/test/manager/InMemoryTaskManagerTest.java +++ b/test/manager/InMemoryTaskManagerTest.java @@ -224,20 +224,24 @@ void testEpicStatusCalculation() { // Все подзадачи NEW - эпик NEW Subtask sub1 = taskManager.createSubtask(new Subtask("Sub 1", "Desc", Status.NEW, epic.getId())); - assertEquals(Status.NEW, epic.getStatus()); + Epic updatedEpic1 = taskManager.getEpicById(epic.getId()); + assertEquals(Status.NEW, updatedEpic1.getStatus()); // Все подзадачи DONE - эпик DONE taskManager.updateSubtask(new Subtask("Sub 1", "Desc", sub1.getId(), Status.DONE, epic.getId())); - assertEquals(Status.DONE, epic.getStatus()); + Epic updatedEpic2 = taskManager.getEpicById(epic.getId()); + assertEquals(Status.DONE, updatedEpic2.getStatus()); // Подзадачи NEW и DONE - эпик IN_PROGRESS Subtask sub2 = taskManager.createSubtask(new Subtask("Sub 2", "Desc", Status.NEW, epic.getId())); - assertEquals(Status.IN_PROGRESS, epic.getStatus()); + Epic updatedEpic3 = taskManager.getEpicById(epic.getId()); + assertEquals(Status.IN_PROGRESS, updatedEpic3.getStatus()); // Все подзадачи IN_PROGRESS - эпик IN_PROGRESS taskManager.updateSubtask(new Subtask("Sub 1", "Desc", sub1.getId(), Status.IN_PROGRESS, epic.getId())); taskManager.updateSubtask(new Subtask("Sub 2", "Desc", sub2.getId(), Status.IN_PROGRESS, epic.getId())); - assertEquals(Status.IN_PROGRESS, epic.getStatus()); + Epic updatedEpic4 = taskManager.getEpicById(epic.getId()); + assertEquals(Status.IN_PROGRESS, updatedEpic4.getStatus()); } @Test diff --git a/test/model/EpicIntegrationTest.java b/test/model/EpicIntegrationTest.java index 772bb13..dfeb69f 100644 --- a/test/model/EpicIntegrationTest.java +++ b/test/model/EpicIntegrationTest.java @@ -18,10 +18,10 @@ void setUp() { void epicCannotBeAddedAsItsOwnSubtask() { Epic epic = taskManager.createEpic(new Epic("Test Epic", "Description")); - // Пытаемся создать подзадачу с epicId равным ID самого эпика - Subtask invalidSubtask = new Subtask("Invalid", "Description", Status.NEW, epic.getId()); + // Пытаемся создать подзадачу с epicId равным ID самого эпика и id равным epicId + Subtask invalidSubtask = new Subtask("Invalid", "Description", epic.getId(), Status.NEW, epic.getId()); - // Должен вернуть null, так как epic не может быть своим же эпиком + // Должен вернуть null, так как epic не может быть своей же подзадачей assertNull(taskManager.createSubtask(invalidSubtask), "Epic не должен быть добавлен в качестве своей же подзадачи"); } diff --git a/test/model/SubtaskIntegrationTest.java b/test/model/SubtaskIntegrationTest.java index 084c298..aff2157 100644 --- a/test/model/SubtaskIntegrationTest.java +++ b/test/model/SubtaskIntegrationTest.java @@ -19,12 +19,11 @@ void subtaskCannotBeItsOwnEpic() { Epic epic = taskManager.createEpic(new Epic("Test Epic", "Description")); Subtask subtask = taskManager.createSubtask(new Subtask("Subtask", "Description", Status.NEW, epic.getId())); - // Пытаемся изменить epicId подзадачи на её собственный ID - subtask.setEpicId(subtask.getId()); - taskManager.updateSubtask(subtask); + // Создаем подзадачу, которая пытается быть своим же эпиком + Subtask invalidSubtask = new Subtask("Invalid", "Description", subtask.getId(), Status.NEW, subtask.getId()); - // Epic ID не должен измениться на собственный ID подзадачи - assertNotEquals(subtask.getId(), subtask.getEpicId(), - "Subtask не должен быть своим же эпиком"); + // Попытка создания должна вернуть null + Subtask result = taskManager.createSubtask(invalidSubtask); + assertNull(result, "Subtask не должен быть своим же эпиком"); } } \ No newline at end of file From 9a06217cdc9bf586cc3392049306e6147c733b07 Mon Sep 17 00:00:00 2001 From: Darya346 Date: Wed, 8 Oct 2025 16:12:15 +0300 Subject: [PATCH 11/14] =?UTF-8?q?=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=B4=D0=BB=D0=B8=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5=20=D0=BD=D0=B0=D0=B7=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/manager/HistoryDataPreservationTest.java | 23 ++----- test/manager/InMemoryTaskManagerTest.java | 67 ++++++------------- .../manager/TaskManagerFunctionalityTest.java | 22 +++--- test/model/TaskIdConflictTest.java | 19 ++---- test/model/TaskTest.java | 12 ++-- 5 files changed, 48 insertions(+), 95 deletions(-) diff --git a/test/manager/HistoryDataPreservationTest.java b/test/manager/HistoryDataPreservationTest.java index b041735..32fab8d 100644 --- a/test/manager/HistoryDataPreservationTest.java +++ b/test/manager/HistoryDataPreservationTest.java @@ -15,39 +15,30 @@ void setUp() { } @Test - void historyPreservesTaskData() { - // Создаем задачу + void historyKeepsData() { Task originalTask = new Task("Original", "Original Description", 1, Status.NEW); - // Добавляем в историю historyManager.add(originalTask); - // Изменяем оригинальную задачу originalTask.setName("Modified"); originalTask.setDescription("Modified Description"); originalTask.setStatus(Status.DONE); - // Получаем задачу из истории Task historicalTask = historyManager.getHistory().get(0); - // Проверяем, что данные в истории сохранились оригинальными - assertEquals("Original", historicalTask.getName(), "История должна сохранить оригинальное имя"); - assertEquals("Original Description", historicalTask.getDescription(), - "История должна сохранить оригинальное описание"); - assertEquals(Status.NEW, historicalTask.getStatus(), "История должна сохранить оригинальный статус"); - assertEquals(1, historicalTask.getId(), "История должна сохранить оригинальный ID"); + assertEquals("Original", historicalTask.getName()); + assertEquals("Original Description", historicalTask.getDescription()); + assertEquals(Status.NEW, historicalTask.getStatus()); + assertEquals(1, historicalTask.getId()); } @Test - void historyContainsIndependentCopies() { + void historyHasCopies() { Task task = new Task("Test", "Description", 1, Status.NEW); historyManager.add(task); - // Изменяем оригинальную задачу task.setName("Changed"); - // Задача в истории не должна измениться - assertNotEquals(task.getName(), historyManager.getHistory().get(0).getName(), - "Задача в истории не должна зависеть от изменений оригинала"); + assertNotEquals(task.getName(), historyManager.getHistory().get(0).getName()); } } \ No newline at end of file diff --git a/test/manager/InMemoryTaskManagerTest.java b/test/manager/InMemoryTaskManagerTest.java index 89b2947..2fe87f7 100644 --- a/test/manager/InMemoryTaskManagerTest.java +++ b/test/manager/InMemoryTaskManagerTest.java @@ -19,7 +19,7 @@ void setUp() { } @Test - void testCreateAndGetTask() { + void testCreateTask() { Task task = new Task("Test Task", "Test Description", Status.NEW); Task createdTask = taskManager.createTask(task); @@ -34,7 +34,7 @@ void testCreateAndGetTask() { } @Test - void testCreateAndGetEpic() { + void testCreateEpic() { Epic epic = new Epic("Test Epic", "Test Epic Description"); Epic createdEpic = taskManager.createEpic(epic); @@ -50,7 +50,7 @@ void testCreateAndGetEpic() { } @Test - void testCreateAndGetSubtask() { + void testCreateSubtask() { Epic epic = taskManager.createEpic(new Epic("Test Epic", "Description")); Subtask subtask = new Subtask("Test Subtask", "Test Description", Status.NEW, epic.getId()); Subtask createdSubtask = taskManager.createSubtask(subtask); @@ -216,28 +216,23 @@ void testGetAllSubtasks() { } @Test - void testEpicStatusCalculation() { + void testEpicStatus() { Epic epic = taskManager.createEpic(new Epic("Epic", "Desc")); - // Пустой эпик - NEW assertEquals(Status.NEW, epic.getStatus()); - // Все подзадачи NEW - эпик NEW Subtask sub1 = taskManager.createSubtask(new Subtask("Sub 1", "Desc", Status.NEW, epic.getId())); Epic updatedEpic1 = taskManager.getEpicById(epic.getId()); assertEquals(Status.NEW, updatedEpic1.getStatus()); - // Все подзадачи DONE - эпик DONE taskManager.updateSubtask(new Subtask("Sub 1", "Desc", sub1.getId(), Status.DONE, epic.getId())); Epic updatedEpic2 = taskManager.getEpicById(epic.getId()); assertEquals(Status.DONE, updatedEpic2.getStatus()); - // Подзадачи NEW и DONE - эпик IN_PROGRESS Subtask sub2 = taskManager.createSubtask(new Subtask("Sub 2", "Desc", Status.NEW, epic.getId())); Epic updatedEpic3 = taskManager.getEpicById(epic.getId()); assertEquals(Status.IN_PROGRESS, updatedEpic3.getStatus()); - // Все подзадачи IN_PROGRESS - эпик IN_PROGRESS taskManager.updateSubtask(new Subtask("Sub 1", "Desc", sub1.getId(), Status.IN_PROGRESS, epic.getId())); taskManager.updateSubtask(new Subtask("Sub 2", "Desc", sub2.getId(), Status.IN_PROGRESS, epic.getId())); Epic updatedEpic4 = taskManager.getEpicById(epic.getId()); @@ -245,15 +240,13 @@ void testEpicStatusCalculation() { } @Test - void testHistoryWithoutDuplicates() { + void testHistoryNoDuplicates() { Task task = taskManager.createTask(new Task("Test", "Description", Status.NEW)); - // Многократно запрашиваем одну и ту же задачу taskManager.getTaskById(task.getId()); taskManager.getTaskById(task.getId()); taskManager.getTaskById(task.getId()); - // В истории должна быть только одна запись assertEquals(1, taskManager.getHistory().size()); } @@ -262,14 +255,11 @@ void testTaskImmutability() { Task task = taskManager.createTask(new Task("Test", "Description", Status.NEW)); int originalId = task.getId(); - // Пытаемся изменить задачу через сеттеры task.setId(999); task.setName("Modified"); - // Получаем задачу из менеджера Task managedTask = taskManager.getTaskById(originalId); - // Проверяем, что данные в менеджере не изменились assertEquals(originalId, managedTask.getId()); assertEquals("Test", managedTask.getName()); } @@ -279,144 +269,129 @@ void testEpicImmutability() { Epic epic = taskManager.createEpic(new Epic("Test Epic", "Description")); int originalId = epic.getId(); - // Пытаемся изменить эпик epic.setId(999); epic.setName("Modified"); - // Получаем эпик из менеджера Epic managedEpic = taskManager.getEpicById(originalId); - // Проверяем, что данные в менеджере не изменились assertEquals(originalId, managedEpic.getId()); assertEquals("Test Epic", managedEpic.getName()); } @Test - void testEmptyHistoryAfterTaskDeletion() { + void testHistoryAfterDelete() { Task task = taskManager.createTask(new Task("Test", "Description", Status.NEW)); - // Добавляем в историю taskManager.getTaskById(task.getId()); assertEquals(1, taskManager.getHistory().size()); - // Удаляем задачу taskManager.deleteTaskById(task.getId()); - // История должна быть пустой assertTrue(taskManager.getHistory().isEmpty()); } @Test - void testDataIntegrityAfterDeletion() { + void testDataIntegrity() { Epic epic = taskManager.createEpic(new Epic("Test Epic", "Description")); Subtask subtask = taskManager.createSubtask(new Subtask("Subtask", "Desc", Status.NEW, epic.getId())); int subtaskId = subtask.getId(); int epicId = epic.getId(); - // Удаляем подзадачу taskManager.deleteSubtaskById(subtaskId); - // Проверяем, что эпик не содержит удаленную подзадачу Epic updatedEpic = taskManager.getEpicById(epicId); assertFalse(updatedEpic.getSubtaskIds().contains(subtaskId)); - // Проверяем, что подзадача удалена из хранилища assertNull(taskManager.getSubtaskById(subtaskId)); } @Test - void testCreateTaskWithNull() { + void testCreateNullTask() { Task result = taskManager.createTask(null); assertNull(result); } @Test - void testCreateEpicWithNull() { + void testCreateNullEpic() { Epic result = taskManager.createEpic(null); assertNull(result); } @Test - void testCreateSubtaskWithNull() { + void testCreateNullSubtask() { Subtask result = taskManager.createSubtask(null); assertNull(result); } @Test - void testCreateSubtaskWithInvalidEpic() { + void testCreateSubtaskBadEpic() { Subtask subtask = new Subtask("Test", "Desc", Status.NEW, 999); Subtask result = taskManager.createSubtask(subtask); assertNull(result); } @Test - void testUpdateNonExistentTask() { + void testUpdateBadTask() { Task task = new Task("Test", "Desc", 999, Status.NEW); taskManager.updateTask(task); - // Не должно быть исключений assertNull(taskManager.getTaskById(999)); } @Test - void testUpdateNonExistentEpic() { + void testUpdateBadEpic() { Epic epic = new Epic("Test", "Desc"); epic.setId(999); taskManager.updateEpic(epic); - // Не должно быть исключений assertNull(taskManager.getEpicById(999)); } @Test - void testUpdateNonExistentSubtask() { + void testUpdateBadSubtask() { Epic epic = taskManager.createEpic(new Epic("Epic", "Desc")); Subtask subtask = new Subtask("Test", "Desc", 999, Status.NEW, epic.getId()); taskManager.updateSubtask(subtask); - // Не должно быть исключений assertNull(taskManager.getSubtaskById(999)); } @Test - void testDeleteNonExistentTask() { + void testDeleteBadTask() { taskManager.deleteTaskById(999); - // Не должно быть исключений } @Test - void testDeleteNonExistentEpic() { + void testDeleteBadEpic() { taskManager.deleteEpicById(999); - // Не должно быть исключений } @Test - void testDeleteNonExistentSubtask() { + void testDeleteBadSubtask() { taskManager.deleteSubtaskById(999); - // Не должно быть исключений } @Test - void testGetNonExistentTask() { + void testGetBadTask() { Task task = taskManager.getTaskById(999); assertNull(task); } @Test - void testGetNonExistentEpic() { + void testGetBadEpic() { Epic epic = taskManager.getEpicById(999); assertNull(epic); } @Test - void testGetNonExistentSubtask() { + void testGetBadSubtask() { Subtask subtask = taskManager.getSubtaskById(999); assertNull(subtask); } @Test - void testGetSubtasksByNonExistentEpic() { + void testGetSubtasksBadEpic() { List subtasks = taskManager.getSubtasksByEpicId(999); assertTrue(subtasks.isEmpty()); } diff --git a/test/manager/TaskManagerFunctionalityTest.java b/test/manager/TaskManagerFunctionalityTest.java index 36e024b..60e4e49 100644 --- a/test/manager/TaskManagerFunctionalityTest.java +++ b/test/manager/TaskManagerFunctionalityTest.java @@ -18,24 +18,20 @@ void setUp() { @Test void canAddAndFindAllTaskTypes() { - // Создаем задачи всех типов Task task = taskManager.createTask(new Task("Task", "Description", Status.NEW)); Epic epic = taskManager.createEpic(new Epic("Epic", "Description")); Subtask subtask = taskManager.createSubtask(new Subtask("Subtask", "Description", Status.NEW, epic.getId())); - // Проверяем, что все создались - assertNotNull(task, "Задача должна быть создана"); - assertNotNull(epic, "Epic должен быть создан"); - assertNotNull(subtask, "Subtask должен быть создан"); + assertNotNull(task); + assertNotNull(epic); + assertNotNull(subtask); - // Проверяем поиск по ID - assertNotNull(taskManager.getTaskById(task.getId()), "Должна найтись задача по ID"); - assertNotNull(taskManager.getEpicById(epic.getId()), "Должен найтись epic по ID"); - assertNotNull(taskManager.getSubtaskById(subtask.getId()), "Должен найтись subtask по ID"); + assertNotNull(taskManager.getTaskById(task.getId())); + assertNotNull(taskManager.getEpicById(epic.getId())); + assertNotNull(taskManager.getSubtaskById(subtask.getId())); - // Проверяем получение всех задач - assertEquals(1, taskManager.getAllTasks().size(), "Должна быть 1 задача"); - assertEquals(1, taskManager.getAllEpics().size(), "Должен быть 1 epic"); - assertEquals(1, taskManager.getAllSubtasks().size(), "Должен быть 1 subtask"); + assertEquals(1, taskManager.getAllTasks().size()); + assertEquals(1, taskManager.getAllEpics().size()); + assertEquals(1, taskManager.getAllSubtasks().size()); } } \ No newline at end of file diff --git a/test/model/TaskIdConflictTest.java b/test/model/TaskIdConflictTest.java index 571204d..2859284 100644 --- a/test/model/TaskIdConflictTest.java +++ b/test/model/TaskIdConflictTest.java @@ -1,7 +1,5 @@ package model; -import model.Task; -import model.Status; import manager.InMemoryTaskManager; import manager.TaskManager; import org.junit.jupiter.api.BeforeEach; @@ -17,28 +15,23 @@ void setUp() { } @Test - void noConflictBetweenGeneratedAndManualIds() { - // Создаем задачу с автоматически сгенерированным ID + void testNoIdConflict() { Task autoTask = taskManager.createTask(new Task("Auto", "Description", Status.NEW)); - // Создаем задачу вручную с таким же ID Task manualTask = new Task("Manual", "Description", autoTask.getId(), Status.NEW); - // Пытаемся обновить задачу с существующим ID taskManager.updateTask(manualTask); - // Проверяем, что задача обновилась, а не создалась новая - assertEquals(1, taskManager.getAllTasks().size(), "Должна остаться одна задача"); - assertEquals("Manual", taskManager.getTaskById(autoTask.getId()).getName(), - "Задача должна быть обновлена, а не создана новая"); + assertEquals(1, taskManager.getAllTasks().size()); + assertEquals("Manual", taskManager.getTaskById(autoTask.getId()).getName()); } @Test - void tasksWithDifferentIdsCoexist() { + void testDifferentIds() { Task task1 = taskManager.createTask(new Task("Task 1", "Description", Status.NEW)); Task task2 = taskManager.createTask(new Task("Task 2", "Description", Status.NEW)); - assertNotEquals(task1.getId(), task2.getId(), "Задачи должны иметь разные ID"); - assertEquals(2, taskManager.getAllTasks().size(), "Обе задачи должны существовать"); + assertNotEquals(task1.getId(), task2.getId()); + assertEquals(2, taskManager.getAllTasks().size()); } } \ No newline at end of file diff --git a/test/model/TaskTest.java b/test/model/TaskTest.java index 67329c9..6f8b618 100644 --- a/test/model/TaskTest.java +++ b/test/model/TaskTest.java @@ -1,26 +1,24 @@ package model; -import model.Status; -import model.Task; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; class TaskTest { @Test - void tasksWithSameIdShouldBeEqual() { + void testSameIdEqual() { Task task1 = new Task("Task 1", "Description 1", 1, Status.NEW); Task task2 = new Task("Task 2", "Description 2", 1, Status.DONE); - assertEquals(task1, task2, "Задачи с одинаковым ID должны быть равны"); - assertEquals(task1.hashCode(), task2.hashCode(), "HashCode должен совпадать для одинаковых ID"); + assertEquals(task1, task2); + assertEquals(task1.hashCode(), task2.hashCode()); } @Test - void tasksWithDifferentIdShouldNotBeEqual() { + void testDifferentIdNotEqual() { Task task1 = new Task("Task", "Description", 1, Status.NEW); Task task2 = new Task("Task", "Description", 2, Status.NEW); - assertNotEquals(task1, task2, "Задачи с разными ID не должны быть равны"); + assertNotEquals(task1, task2); } } \ No newline at end of file From f840bb5056eeba1fd975d767f7f29731c7975e79 Mon Sep 17 00:00:00 2001 From: Darya346 Date: Wed, 22 Oct 2025 14:59:30 +0300 Subject: [PATCH 12/14] =?UTF-8?q?feat:=20=D1=80=D0=B5=D0=B0=D0=BB=D0=B8?= =?UTF-8?q?=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20FileBackedTaskManager=20=D1=81?= =?UTF-8?q?=20=D1=81=D0=BE=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=D0=BC=20=D0=B2=20=D1=84=D0=B0=D0=B9=D0=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/manager/FileBackedTaskManager.java | 251 +++++++++++++++++++++++++ src/manager/InMemoryTaskManager.java | 13 +- src/manager/ManagerSaveException.java | 11 ++ src/manager/Managers.java | 6 + src/manager/TaskType.java | 7 + test/manager/FileBackedTest.java | 78 ++++++++ 6 files changed, 360 insertions(+), 6 deletions(-) create mode 100644 src/manager/FileBackedTaskManager.java create mode 100644 src/manager/ManagerSaveException.java create mode 100644 src/manager/TaskType.java create mode 100644 test/manager/FileBackedTest.java diff --git a/src/manager/FileBackedTaskManager.java b/src/manager/FileBackedTaskManager.java new file mode 100644 index 0000000..c057220 --- /dev/null +++ b/src/manager/FileBackedTaskManager.java @@ -0,0 +1,251 @@ +package manager; + +import model.*; +import model.TaskType; + +import java.io.*; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; + +public class FileBackedTaskManager extends InMemoryTaskManager { + private final File file; + + public FileBackedTaskManager(File file) { + this.file = file; + } + + @Override + public Task createTask(Task task) { + Task createdTask = super.createTask(task); + save(); + return createdTask; + } + + @Override + public Epic createEpic(Epic epic) { + Epic createdEpic = super.createEpic(epic); + save(); + return createdEpic; + } + + @Override + public Subtask createSubtask(Subtask subtask) { + Subtask createdSubtask = super.createSubtask(subtask); + save(); + return createdSubtask; + } + + @Override + public void updateTask(Task task) { + super.updateTask(task); + save(); + } + + @Override + public void updateEpic(Epic epic) { + super.updateEpic(epic); + save(); + } + + @Override + public void updateSubtask(Subtask subtask) { + super.updateSubtask(subtask); + save(); + } + + @Override + public void deleteTaskById(int id) { + super.deleteTaskById(id); + save(); + } + + @Override + public void deleteEpicById(int id) { + super.deleteEpicById(id); + save(); + } + + @Override + public void deleteSubtaskById(int id) { + super.deleteSubtaskById(id); + save(); + } + + @Override + public void deleteAllTasks() { + super.deleteAllTasks(); + save(); + } + + @Override + public void deleteAllEpics() { + super.deleteAllEpics(); + save(); + } + + @Override + public void deleteAllSubtasks() { + super.deleteAllSubtasks(); + save(); + } + + protected void save() { + try (PrintWriter writer = new PrintWriter(file)) { + // Записываем заголовок + writer.println("id,type,name,status,description,epic"); + + // Сохраняем все задачи + for (Task task : getAllTasks()) { + writer.println(toString(task)); + } + for (Epic epic : getAllEpics()) { + writer.println(toString(epic)); + } + for (Subtask subtask : getAllSubtasks()) { + writer.println(toString(subtask)); + } + } catch (IOException e) { + throw new ManagerSaveException("Ошибка сохранения в файл", e); + } + } + + private String toString(Task task) { + if (task instanceof Epic) { + return String.format("%d,EPIC,%s,%s,%s,", + task.getId(), + task.getName(), + task.getStatus(), + task.getDescription()); + } else if (task instanceof Subtask) { + Subtask subtask = (Subtask) task; + return String.format("%d,SUBTASK,%s,%s,%s,%d", + subtask.getId(), + subtask.getName(), + subtask.getStatus(), + subtask.getDescription(), + subtask.getEpicId()); + } else { + return String.format("%d,TASK,%s,%s,%s,", + task.getId(), + task.getName(), + task.getStatus(), + task.getDescription()); + } + } + + private Task fromString(String value) { + String[] fields = value.split(",", -1); // -1 чтобы сохранить пустые поля + int id = Integer.parseInt(fields[0]); + TaskType type = TaskType.valueOf(fields[1]); + String name = fields[2]; + Status status = Status.valueOf(fields[3]); + String description = fields[4]; + + switch (type) { + case TASK: + Task task = new Task(name, description, status); + task.setId(id); + return task; + case EPIC: + Epic epic = new Epic(name, description); + epic.setId(id); + epic.updateStatus(status); + return epic; + case SUBTASK: + int epicId = fields[5].isEmpty() ? 0 : Integer.parseInt(fields[5]); + Subtask subtask = new Subtask(name, description, status, epicId); + subtask.setId(id); + return subtask; + default: + throw new IllegalArgumentException("Неизвестный тип задачи: " + type); + } + } + + public static FileBackedTaskManager loadFromFile(File file) { + FileBackedTaskManager manager = new FileBackedTaskManager(file); + + try { + if (!file.exists()) { + return manager; + } + + String content = Files.readString(file.toPath()); + String[] lines = content.split("\n"); + + // Пропускаем заголовок и пустые строки + for (int i = 1; i < lines.length; i++) { + String line = lines[i].trim(); + if (line.isEmpty()) { + continue; + } + + Task task = manager.fromString(line); + if (task instanceof Epic) { + manager.epics.put(task.getId(), (Epic) task); + } else if (task instanceof Subtask) { + manager.subtasks.put(task.getId(), (Subtask) task); + } else { + manager.tasks.put(task.getId(), task); + } + + // Обновляем счетчик id + if (task.getId() >= manager.nextId) { + manager.nextId = task.getId() + 1; + } + } + + // Восстанавливаем связи для подзадач в эпиках + for (Subtask subtask : manager.subtasks.values()) { + Epic epic = manager.epics.get(subtask.getEpicId()); + if (epic != null) { + epic.addSubtaskId(subtask.getId()); + } + } + + } catch (IOException e) { + throw new ManagerSaveException("Ошибка загрузки из файла", e); + } + + return manager; + } + + // Дополнительное задание: пользовательский сценарий + public static void main(String[] args) { + // Создаем временный файл для тестирования + try { + File tempFile = File.createTempFile("tasks", ".csv"); + + // Создаем первый менеджер и добавляем задачи + FileBackedTaskManager manager1 = new FileBackedTaskManager(tempFile); + + Task task1 = manager1.createTask(new Task("Task 1", "Description 1", Status.NEW)); + manager1.createTask(new Task("Task 2", "Description 2", Status.IN_PROGRESS)); + + Epic epic1 = manager1.createEpic(new Epic("Epic 1", "Epic description")); + Subtask subtask1 = manager1.createSubtask(new Subtask("Subtask 1", "Sub description", Status.DONE, epic1.getId())); + manager1.createSubtask(new Subtask("Subtask 2", "Sub description 2", Status.NEW, epic1.getId())); + + // Просматриваем некоторые задачи для истории + manager1.getTaskById(task1.getId()); + manager1.getEpicById(epic1.getId()); + manager1.getSubtaskById(subtask1.getId()); + + // Создаем второй менеджер из того же файла + FileBackedTaskManager manager2 = FileBackedTaskManager.loadFromFile(tempFile); + + // Проверяем, что все задачи восстановились + System.out.println("Проверка восстановления данных:"); + System.out.println("Задачи в manager2: " + manager2.getAllTasks().size()); + System.out.println("Эпики в manager2: " + manager2.getAllEpics().size()); + System.out.println("Подзадачи в manager2: " + manager2.getAllSubtasks().size()); + System.out.println("История в manager2: " + manager2.getHistory().size()); + + // Очищаем временный файл + tempFile.deleteOnExit(); + + } catch (IOException e) { + System.err.println("Ошибка при работе с файлом: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index 7ce0480..12ddde1 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -6,20 +6,21 @@ import java.util.*; public class InMemoryTaskManager implements TaskManager { - private final Map tasks = new HashMap<>(); - private final Map epics = new HashMap<>(); - private final Map subtasks = new HashMap<>(); - private final HistoryManager historyManager; - private int nextId = 1; + protected final Map tasks = new HashMap<>(); + protected final Map epics = new HashMap<>(); + protected final Map subtasks = new HashMap<>(); + protected final HistoryManager historyManager; + protected int nextId = 1; public InMemoryTaskManager() { this.historyManager = Managers.getDefaultHistory(); } - private int generateId() { + protected int generateId() { return nextId++; } + // Остальные методы остаются без изменений... private Task createTaskCopy(Task original) { return new Task(original.getName(), original.getDescription(), original.getId(), original.getStatus()); diff --git a/src/manager/ManagerSaveException.java b/src/manager/ManagerSaveException.java new file mode 100644 index 0000000..4ff500a --- /dev/null +++ b/src/manager/ManagerSaveException.java @@ -0,0 +1,11 @@ +package manager; + +public class ManagerSaveException extends RuntimeException { + public ManagerSaveException(String message) { + super(message); + } + + public ManagerSaveException(String message, Throwable cause) { + super(message, cause); + } +} \ No newline at end of file diff --git a/src/manager/Managers.java b/src/manager/Managers.java index 64dfb6f..e5d3bce 100644 --- a/src/manager/Managers.java +++ b/src/manager/Managers.java @@ -1,5 +1,7 @@ package manager; +import java.io.File; + public class Managers { public static TaskManager getDefault() { @@ -9,4 +11,8 @@ public static TaskManager getDefault() { public static HistoryManager getDefaultHistory() { return new InMemoryHistoryManager(); } + + public static FileBackedTaskManager getFileBackedTaskManager(File file) { + return new FileBackedTaskManager(file); + } } \ No newline at end of file diff --git a/src/manager/TaskType.java b/src/manager/TaskType.java new file mode 100644 index 0000000..b95e27a --- /dev/null +++ b/src/manager/TaskType.java @@ -0,0 +1,7 @@ +package model; + +public enum TaskType { + TASK, + EPIC, + SUBTASK +} \ No newline at end of file diff --git a/test/manager/FileBackedTest.java b/test/manager/FileBackedTest.java new file mode 100644 index 0000000..ce61ca6 --- /dev/null +++ b/test/manager/FileBackedTest.java @@ -0,0 +1,78 @@ +package manager; + +import manager.FileBackedTaskManager; +import manager.ManagerSaveException; +import model.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import java.io.File; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.*; + +class FileBackedTaskManagerTest { + + @TempDir + Path tempDir; + + @Test + void testSaveAndLoadEmptyFile() { + File file = tempDir.resolve("test.csv").toFile(); + FileBackedTaskManager manager = new FileBackedTaskManager(file); + + // Сохраняем пустой менеджер + manager.save(); + + // Загружаем из файла + FileBackedTaskManager loadedManager = FileBackedTaskManager.loadFromFile(file); + + assertTrue(loadedManager.getAllTasks().isEmpty()); + assertTrue(loadedManager.getAllEpics().isEmpty()); + assertTrue(loadedManager.getAllSubtasks().isEmpty()); + } + + @Test + void testSaveAndLoadMultipleTasks() { + File file = tempDir.resolve("test.csv").toFile(); + FileBackedTaskManager manager = new FileBackedTaskManager(file); + + // Создаем задачи + Task task1 = manager.createTask(new Task("Task 1", "Description 1", Status.NEW)); + manager.createTask(new Task("Task 2", "Description 2", Status.DONE)); + + Epic epic = manager.createEpic(new Epic("Epic", "Epic description")); + manager.createSubtask(new Subtask("Subtask", "Sub description", Status.IN_PROGRESS, epic.getId())); + + // Загружаем из файла + FileBackedTaskManager loadedManager = FileBackedTaskManager.loadFromFile(file); + + assertEquals(2, loadedManager.getAllTasks().size()); + assertEquals(1, loadedManager.getAllEpics().size()); + assertEquals(1, loadedManager.getAllSubtasks().size()); + + Task loadedTask = loadedManager.getTaskById(task1.getId()); + assertNotNull(loadedTask); + assertEquals("Task 1", loadedTask.getName()); + assertEquals(Status.NEW, loadedTask.getStatus()); + } + + @Test + void testSaveException() { + File file = new File("/invalid/path/tasks.csv"); + FileBackedTaskManager manager = new FileBackedTaskManager(file); + + assertThrows(ManagerSaveException.class, () -> { + manager.createTask(new Task("Test", "Test", Status.NEW)); + }); + } + + @Test + void testLoadFromNonExistentFile() { + File file = new File("nonexistent.csv"); + FileBackedTaskManager manager = FileBackedTaskManager.loadFromFile(file); + + assertNotNull(manager); + assertTrue(manager.getAllTasks().isEmpty()); + } +} \ No newline at end of file From 5df0d2e8aad1864ad9f3a2244b55df7c4ddc1d32 Mon Sep 17 00:00:00 2001 From: Darya346 Date: Wed, 22 Oct 2025 15:10:29 +0300 Subject: [PATCH 13/14] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20FileBackedTaskManager?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/manager/FileBackedTaskManager.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/manager/FileBackedTaskManager.java b/src/manager/FileBackedTaskManager.java index c057220..26f1530 100644 --- a/src/manager/FileBackedTaskManager.java +++ b/src/manager/FileBackedTaskManager.java @@ -5,8 +5,6 @@ import java.io.*; import java.nio.file.Files; -import java.util.ArrayList; -import java.util.List; public class FileBackedTaskManager extends InMemoryTaskManager { private final File file; From a8eafb94f9679bfa5fdf9b4b6b58cb3f7a705ae2 Mon Sep 17 00:00:00 2001 From: Darya346 Date: Wed, 22 Oct 2025 20:48:57 +0300 Subject: [PATCH 14/14] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F:=20=D0=B1=D0=BE=D0=BB=D0=B5?= =?UTF-8?q?=D0=B5=20=D0=BE=D1=81=D0=BC=D1=8B=D1=81=D0=BB=D0=B5=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D0=B8=20String.format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/manager/FileBackedTaskManager.java | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/manager/FileBackedTaskManager.java b/src/manager/FileBackedTaskManager.java index 26f1530..2c9a07a 100644 --- a/src/manager/FileBackedTaskManager.java +++ b/src/manager/FileBackedTaskManager.java @@ -95,20 +95,20 @@ protected void save() { // Сохраняем все задачи for (Task task : getAllTasks()) { - writer.println(toString(task)); + writer.println(taskToString(task)); } for (Epic epic : getAllEpics()) { - writer.println(toString(epic)); + writer.println(taskToString(epic)); } for (Subtask subtask : getAllSubtasks()) { - writer.println(toString(subtask)); + writer.println(taskToString(subtask)); } } catch (IOException e) { throw new ManagerSaveException("Ошибка сохранения в файл", e); } } - private String toString(Task task) { + private String taskToString(Task task) { if (task instanceof Epic) { return String.format("%d,EPIC,%s,%s,%s,", task.getId(), @@ -132,7 +132,7 @@ private String toString(Task task) { } } - private Task fromString(String value) { + private Task taskFromString(String value) { String[] fields = value.split(",", -1); // -1 чтобы сохранить пустые поля int id = Integer.parseInt(fields[0]); TaskType type = TaskType.valueOf(fields[1]); @@ -156,7 +156,7 @@ private Task fromString(String value) { subtask.setId(id); return subtask; default: - throw new IllegalArgumentException("Неизвестный тип задачи: " + type); + throw new IllegalArgumentException(String.format("Неизвестный тип задачи: %s", type)); } } @@ -169,16 +169,16 @@ public static FileBackedTaskManager loadFromFile(File file) { } String content = Files.readString(file.toPath()); - String[] lines = content.split("\n"); + String[] fileLines = content.split("\n"); // Пропускаем заголовок и пустые строки - for (int i = 1; i < lines.length; i++) { - String line = lines[i].trim(); - if (line.isEmpty()) { + for (int lineNumber = 1; lineNumber < fileLines.length; lineNumber++) { + String currentLine = fileLines[lineNumber].trim(); + if (currentLine.isEmpty()) { continue; } - Task task = manager.fromString(line); + Task task = manager.taskFromString(currentLine); if (task instanceof Epic) { manager.epics.put(task.getId(), (Epic) task); } else if (task instanceof Subtask) {