From 5d289f52af8cabdcc5fed90afc3f24425c51d0e9 Mon Sep 17 00:00:00 2001 From: n20va Date: Wed, 2 Jul 2025 19:07:38 +0300 Subject: [PATCH 1/7] =?UTF-8?q?=D1=83=D0=B1=D1=80=D0=B0=D0=BD=20=D0=BA?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=BE=D0=BC=D0=BD=D1=8B=D0=B9=20=D1=81=D0=B2?= =?UTF-8?q?=D1=8F=D0=B7=D0=BD=D1=8B=D0=B9=20=D1=81=D0=BF=D0=B8=D1=81=D0=BE?= =?UTF-8?q?=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- {src/tests => test}/manager/InMemoryHistoryManagerTest.java | 2 +- {src/tests => test}/manager/InMemoryTaskManagerTest.java | 2 +- {src/tests => test}/model/EpicTest.java | 2 +- {src/tests => test}/model/SubtaskTest.java | 2 +- {src/tests => test}/model/TaskTest.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) rename {src/tests => test}/manager/InMemoryHistoryManagerTest.java (98%) rename {src/tests => test}/manager/InMemoryTaskManagerTest.java (99%) rename {src/tests => test}/model/EpicTest.java (98%) rename {src/tests => test}/model/SubtaskTest.java (96%) rename {src/tests => test}/model/TaskTest.java (99%) diff --git a/src/tests/manager/InMemoryHistoryManagerTest.java b/test/manager/InMemoryHistoryManagerTest.java similarity index 98% rename from src/tests/manager/InMemoryHistoryManagerTest.java rename to test/manager/InMemoryHistoryManagerTest.java index 9eb7be6..c02bfbc 100644 --- a/src/tests/manager/InMemoryHistoryManagerTest.java +++ b/test/manager/InMemoryHistoryManagerTest.java @@ -1,4 +1,4 @@ -package tests.manager; +package test.manager; import manager.HistoryManager; import manager.InMemoryHistoryManager; diff --git a/src/tests/manager/InMemoryTaskManagerTest.java b/test/manager/InMemoryTaskManagerTest.java similarity index 99% rename from src/tests/manager/InMemoryTaskManagerTest.java rename to test/manager/InMemoryTaskManagerTest.java index 7792d5d..30d615c 100644 --- a/src/tests/manager/InMemoryTaskManagerTest.java +++ b/test/manager/InMemoryTaskManagerTest.java @@ -1,4 +1,4 @@ -package tests.manager; +package test.manager; import manager.InMemoryTaskManager; import model.Epic; diff --git a/src/tests/model/EpicTest.java b/test/model/EpicTest.java similarity index 98% rename from src/tests/model/EpicTest.java rename to test/model/EpicTest.java index 9f24042..074072d 100644 --- a/src/tests/model/EpicTest.java +++ b/test/model/EpicTest.java @@ -1,4 +1,4 @@ -package tests.model; +package test.model; import model.Epic; import model.Status; diff --git a/src/tests/model/SubtaskTest.java b/test/model/SubtaskTest.java similarity index 96% rename from src/tests/model/SubtaskTest.java rename to test/model/SubtaskTest.java index 68fc489..5131012 100644 --- a/src/tests/model/SubtaskTest.java +++ b/test/model/SubtaskTest.java @@ -1,4 +1,4 @@ -package tests.model; +package test.model; import model.Status; import model.Subtask; diff --git a/src/tests/model/TaskTest.java b/test/model/TaskTest.java similarity index 99% rename from src/tests/model/TaskTest.java rename to test/model/TaskTest.java index 1d39ff2..d37f182 100644 --- a/src/tests/model/TaskTest.java +++ b/test/model/TaskTest.java @@ -1,4 +1,4 @@ -package tests.model; +package test.model; import model.Status; import model.Task; From 57cb47f66aaaa1c2b935cbf0d4ddf23c00b5e29e Mon Sep 17 00:00:00 2001 From: n20va Date: Wed, 2 Jul 2025 19:15:36 +0300 Subject: [PATCH 2/7] =?UTF-8?q?=D1=83=D0=B1=D1=80=D0=B0=D0=BD=20=D0=BA?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=BE=D0=BC=D0=BD=D1=8B=D0=B9=20=D1=81=D0=B2?= =?UTF-8?q?=D1=8F=D0=B7=D0=BD=D1=8B=D0=B9=20=D1=81=D0=BF=D0=B8=D1=81=D0=BE?= =?UTF-8?q?=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Main.java | 91 +++++++------------- src/manager/HistoryManager.java | 4 + src/manager/InMemoryHistoryManager.java | 66 ++++++++++++-- src/manager/InMemoryTaskManager.java | 19 +++- src/manager/TaskManager.java | 12 +++ src/model/Epic.java | 27 +++--- src/model/Task.java | 68 ++++++++++----- test/manager/InMemoryHistoryManagerTest.java | 27 +++--- test/model/SubtaskTest.java | 19 ---- 9 files changed, 197 insertions(+), 136 deletions(-) delete mode 100644 test/model/SubtaskTest.java diff --git a/src/Main.java b/src/Main.java index c4fd905..402476a 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,4 +1,3 @@ -import manager.InMemoryTaskManager; import manager.Managers; import manager.TaskManager; import model.Epic; @@ -10,76 +9,44 @@ public class Main { public static void main(String[] args) { - TaskManager taskManager = Managers.getDefault(); - - // Создаем задачи - Task task1 = new Task("Покупки", "Купить продукты", Status.NEW); - Task task2 = new Task("Тренировка", "Сходить в зал", Status.IN_PROGRESS); - taskManager.addTask(task1); - taskManager.addTask(task2); - - // Создаем эпик с подзадачами - Epic epic1 = new Epic("Проект", "Разработка нового функционала"); - taskManager.addEpic(epic1); - - Subtask subtask1 = new Subtask("Разработка интерфейса", "Создать макет UI", Status.NEW, epic1.getId()); - Subtask subtask2 = new Subtask("Тестирование", "Проверить функционал", Status.DONE, epic1.getId()); - taskManager.addSubtask(subtask1); - taskManager.addSubtask(subtask2); - - // Просматриваем задачи для наполнения истории - System.out.println("\n=== Просмотр задач ==="); - taskManager.getTaskById(task1.getId()); - taskManager.getEpicById(epic1.getId()); - taskManager.getSubtaskById(subtask1.getId()); - taskManager.getSubtaskById(subtask2.getId()); - taskManager.getTaskById(task2.getId()); - - // Выводим все задачи и историю - printAllTasks(taskManager); - - // Создаем больше задач для демонстрации ограничения истории - System.out.println("\n=== Создаем дополнительные задачи ==="); - for (int i = 3; i <= 12; i++) { - Task task = new Task("Задача " + i, "Описание " + i, Status.NEW); - taskManager.addTask(task); - taskManager.getTaskById(task.getId()); // Просматриваем задачу - } + TaskManager manager = Managers.getDefault(); + Task task1 = new Task("Task1", "Desc", Status.NEW); + Task task2 = new Task("Task2", "Desc", Status.NEW); + manager.addTask(task1); + manager.addTask(task2); + + Epic epic1 = new Epic("Epic1", "Desc"); + Epic epic2 = new Epic("Epic2", "Desc"); + manager.addEpic(epic1); + manager.addEpic(epic2); + + Subtask subtask1 = new Subtask("Sub1", "Desc", Status.NEW, epic1.getId()); + Subtask subtask2 = new Subtask("Sub2", "Desc", Status.NEW, epic1.getId()); + manager.addSubtask(subtask1); + manager.addSubtask(subtask2); + + manager.getTaskById(task1.getId()); + manager.getEpicById(epic1.getId()); + manager.getTaskById(task1.getId()); + manager.getSubtaskById(subtask1.getId()); + printHistory(manager); - // Выводим историю после превышения лимита (10 элементов) - System.out.println("\n=== История после 12 просмотров ==="); - printHistory(taskManager); - } + manager.removeTaskById(task1.getId()); + printHistory(manager); - private static void printAllTasks(TaskManager manager) { - System.out.println("\n=== Все задачи ==="); - System.out.println("Задачи:"); - for (Task task : manager.getAllTasks()) { - System.out.println(task); - } - System.out.println("\nЭпики:"); - for (Epic epic : manager.getAllEpics()) { - System.out.println(epic); - for (Task subtask : manager.getSubtasksOfEpic(epic.getId())) { - System.out.println("--> " + subtask); - } - } - System.out.println("\nПодзадачи:"); - for (Task subtask : manager.getAllSubtasks()) { - System.out.println(subtask); - } - System.out.println("\nИстория просмотров:"); + manager.removeEpicById(epic1.getId()); printHistory(manager); } private static void printHistory(TaskManager manager) { List history = manager.getHistory(); if (history.isEmpty()) { - System.out.println("История пуста"); + System.out.println("History is empty"); } else { - System.out.println("Последние " + history.size() + " просмотренных задач:"); - for (Task task : history) { - System.out.println(" - " + task.getTitle() + " (ID: " + task.getId() + ")"); + System.out.println("\nView history (" + history.size() + " items):"); + for (int i = 0; i < history.size(); i++) { + Task task = history.get(i); + System.out.println((i + 1) + ". " + task.getTitle() + " [ID:" + task.getId() + "]"); } } } diff --git a/src/manager/HistoryManager.java b/src/manager/HistoryManager.java index 6070997..bfe6cfc 100644 --- a/src/manager/HistoryManager.java +++ b/src/manager/HistoryManager.java @@ -4,6 +4,10 @@ import java.util.List; public interface HistoryManager { + void add(Task task); + + void remove(int id); + List getHistory(); } \ No newline at end of file diff --git a/src/manager/InMemoryHistoryManager.java b/src/manager/InMemoryHistoryManager.java index 4d91302..3dd9200 100644 --- a/src/manager/InMemoryHistoryManager.java +++ b/src/manager/InMemoryHistoryManager.java @@ -1,25 +1,75 @@ package manager; import model.Task; -import java.util.ArrayList; -import java.util.List; +import java.util.*; + public class InMemoryHistoryManager implements HistoryManager { - private static final int MAX_HISTORY_SIZE = 10; - private final List history = new ArrayList<>(); + + protected 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; + int id = task.getId(); + remove(id); // Удаляем предыдущий просмотр + linkLast(task); + } - history.add(task); - if (history.size() > MAX_HISTORY_SIZE) { - history.remove(0); + @Override + public void remove(int id) { + Node node = historyMap.remove(id); + if (node != null) { + removeNode(node); } } @Override public List getHistory() { - return new ArrayList<>(history); + List tasks = new ArrayList<>(); + Node current = head; + while (current != null) { + tasks.add(current.task); + current = current.next; + } + return tasks; + } + + private void linkLast(Task task) { + Node node = new Node(task); + if (tail == null) { + head = node; + } else { + tail.next = node; + node.prev = tail; + } + tail = node; + historyMap.put(task.getId(), node); + } + + private void removeNode(Node node) { + 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; + } } } \ No newline at end of file diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index 05b4454..34c5bc2 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -99,7 +99,6 @@ public void updateEpic(Epic epic) { oldEpic.setDescription(epic.getDescription()); } - @Override public void updateSubtask(Subtask subtask) { int id = subtask.getId(); @@ -119,10 +118,10 @@ public void updateSubtask(Subtask subtask) { } } - @Override public void removeTaskById(int id) { tasks.remove(id); + historyManager.remove(id); } @Override @@ -131,7 +130,9 @@ public void removeEpicById(int id) { if (epic != null) { for (int subId : epic.getSubtaskIds()) { subtasks.remove(subId); + historyManager.remove(subId); } + historyManager.remove(id); } } @@ -144,22 +145,35 @@ public void removeSubtaskById(int id) { epic.removeSubtask(id); updateEpicStatus(epic.getId()); } + historyManager.remove(id); } } @Override public void clearTasks() { + for (int id : tasks.keySet()) { + historyManager.remove(id); + } tasks.clear(); } @Override public void clearEpics() { + for (int epicId : epics.keySet()) { + historyManager.remove(epicId); + } + for (int subtaskId : subtasks.keySet()) { + historyManager.remove(subtaskId); + } epics.clear(); subtasks.clear(); } @Override public void clearSubtasks() { + for (int subtaskId : subtasks.keySet()) { + historyManager.remove(subtaskId); + } subtasks.clear(); for (Epic epic : epics.values()) { epic.getSubtaskIds().clear(); @@ -182,7 +196,6 @@ public List getSubtasksOfEpic(int epicId) { return result; } - @Override public List getHistory() { return historyManager.getHistory(); diff --git a/src/manager/TaskManager.java b/src/manager/TaskManager.java index 9a4c891..3ef3ae1 100644 --- a/src/manager/TaskManager.java +++ b/src/manager/TaskManager.java @@ -9,27 +9,39 @@ public interface TaskManager { void addTask(Task task); + void addEpic(Epic epic); + void addSubtask(Subtask subtask); List getAllTasks(); + List getAllEpics(); + List getAllSubtasks(); Task getTaskById(int id); + Epic getEpicById(int id); + Subtask getSubtaskById(int id); void updateTask(Task task); + void updateEpic(Epic epic); + void updateSubtask(Subtask subtask); void removeTaskById(int id); + void removeEpicById(int id); + void removeSubtaskById(int id); void clearTasks(); + void clearEpics(); + void clearSubtasks(); List getSubtasksOfEpic(int epicId); diff --git a/src/model/Epic.java b/src/model/Epic.java index bdbde3d..3bf9376 100644 --- a/src/model/Epic.java +++ b/src/model/Epic.java @@ -25,9 +25,15 @@ public void removeSubtask(int subtaskId) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Epic)) return false; - if (!super.equals(o)) return false; + if (this == o) { + return true; + } + if (!(o instanceof Epic)) { + return false; + } + if (!super.equals(o)) { + return false; + } Epic epic = (Epic) o; return Objects.equals(subtaskIds, epic.subtaskIds); } @@ -36,14 +42,15 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(super.hashCode(), subtaskIds); } + @Override public String toString() { - return "Epic{" + - "id=" + getId() + - ", title='" + getTitle() + '\'' + - ", description='" + getDescription() + '\'' + - ", status=" + getStatus() + - ", subtaskIds=" + subtaskIds + - '}'; + return "Epic{" + + "id=" + getId() + + ", title='" + getTitle() + '\'' + + ", description='" + getDescription() + '\'' + + ", status=" + getStatus() + + ", subtaskIds=" + subtaskIds + + '}'; } } \ No newline at end of file diff --git a/src/model/Task.java b/src/model/Task.java index 79a3730..2bc080b 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -1,6 +1,5 @@ package model; - import java.util.Objects; public class Task { @@ -15,24 +14,51 @@ public Task(String title, String description, Status status) { this.status = status; } - public int getId() { return id; } - public void setId(int id) { this.id = id; } - public String getTitle() { return title; } - public void setTitle(String title) { this.title = title; } - public String getDescription() { return description; } - public void setDescription(String description) { this.description = description; } - public Status getStatus() { return status; } - public void setStatus(Status status) { this.status = status; } + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } @Override public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Task)) return false; + if (this == o) { + return true; + } + if (!(o instanceof Task)) { + return false; + } Task task = (Task) o; - return id == task.id && - Objects.equals(title, task.title) && - Objects.equals(description, task.description) && - status == task.status; + return id == task.id + && Objects.equals(title, task.title) + && Objects.equals(description, task.description) + && status == task.status; } @Override @@ -42,11 +68,11 @@ public int hashCode() { @Override public String toString() { - return "Task{" + - "id=" + id + - ", title='" + title + '\'' + - ", description='" + description + '\'' + - ", status=" + status + - '}'; + return "Task{" + + "id=" + id + + ", title='" + title + '\'' + + ", description='" + description + '\'' + + ", status=" + status + + '}'; } } \ No newline at end of file diff --git a/test/manager/InMemoryHistoryManagerTest.java b/test/manager/InMemoryHistoryManagerTest.java index c02bfbc..7f4ff98 100644 --- a/test/manager/InMemoryHistoryManagerTest.java +++ b/test/manager/InMemoryHistoryManagerTest.java @@ -36,7 +36,7 @@ void addAndGetHistory() { } @Test - void addSameTaskTwice() { + void shouldRemoveDuplicates() { Task task = new Task("Task", "Desc", Status.NEW); task.setId(1); @@ -44,22 +44,23 @@ void addSameTaskTwice() { historyManager.add(task); List history = historyManager.getHistory(); - assertEquals(2, history.size()); - assertEquals(task, history.get(0)); - assertEquals(task, history.get(1)); + assertEquals(1, history.size()); } @Test - void historyLimit() { - for (int i = 1; i <= 15; i++) { - Task task = new Task("Task" + i, "Desc", Status.NEW); - task.setId(i); - historyManager.add(task); - } + void shouldRemoveNodeFromMiddle() { + Task task1 = new Task("Task1", "Desc", Status.NEW); + Task task2 = new Task("Task2", "Desc", Status.NEW); + Task task3 = new Task("Task3", "Desc", Status.NEW); + task1.setId(1); task2.setId(2); task3.setId(3); + + historyManager.add(task1); + historyManager.add(task2); + historyManager.add(task3); + historyManager.add(task2); // Дубликат List history = historyManager.getHistory(); - assertEquals(10, history.size()); - assertEquals(6, history.get(0).getId()); - assertEquals(15, history.get(9).getId()); + assertEquals(3, history.size()); + assertEquals(List.of(task1, task3, task2), history); } } \ No newline at end of file diff --git a/test/model/SubtaskTest.java b/test/model/SubtaskTest.java deleted file mode 100644 index 5131012..0000000 --- a/test/model/SubtaskTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package test.model; - -import model.Status; -import model.Subtask; -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - -public class SubtaskTest { - - @Test - public void testSubtaskCreation() { - Subtask subtask = new Subtask("Test", "Description", Status.NEW, 1); - assertEquals("Test", subtask.getTitle()); - assertEquals("Description", subtask.getDescription()); - assertEquals(Status.NEW, subtask.getStatus()); - assertEquals(1, subtask.getEpicId()); - } - -} \ No newline at end of file From 35395476c16902469ed94055d9912d0d2dad0e1d Mon Sep 17 00:00:00 2001 From: n20va Date: Wed, 2 Jul 2025 19:47:24 +0300 Subject: [PATCH 3/7] =?UTF-8?q?=D1=83=D0=B1=D1=80=D0=B0=D0=BD=20=D0=BA?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=BE=D0=BC=D0=BD=D1=8B=D0=B9=20=D1=81=D0=B2?= =?UTF-8?q?=D1=8F=D0=B7=D0=BD=D1=8B=D0=B9=20=D1=81=D0=BF=D0=B8=D1=81=D0=BE?= =?UTF-8?q?=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Main.java | 60 ++++++---- src/manager/FileBackedTaskManager.java | 155 +++++++++++++++++++++++++ src/manager/ManagerSaveException.java | 12 ++ src/manager/Managers.java | 6 + src/model/Epic.java | 11 +- src/model/Subtask.java | 8 +- src/model/Task.java | 7 +- 7 files changed, 212 insertions(+), 47 deletions(-) create mode 100644 src/manager/FileBackedTaskManager.java create mode 100644 src/manager/ManagerSaveException.java diff --git a/src/Main.java b/src/Main.java index 402476a..d532d87 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,53 +1,63 @@ -import manager.Managers; +import manager.FileBackedTaskManager; import manager.TaskManager; import model.Epic; import model.Status; import model.Subtask; import model.Task; +import java.io.File; import java.util.List; public class Main { public static void main(String[] args) { - TaskManager manager = Managers.getDefault(); - Task task1 = new Task("Task1", "Desc", Status.NEW); - Task task2 = new Task("Task2", "Desc", Status.NEW); + File file = new File("tasks.csv"); + TaskManager manager = new FileBackedTaskManager(file); + + Task task1 = new Task("Планирование отпуска", "Выбрать направление и даты", Status.NEW); + Task task2 = new Task("Закупка продуктов", "Купить продукты на неделю", Status.IN_PROGRESS); manager.addTask(task1); manager.addTask(task2); - Epic epic1 = new Epic("Epic1", "Desc"); - Epic epic2 = new Epic("Epic2", "Desc"); + Epic epic1 = new Epic("Организация мероприятия", "Подготовка к корпоративу"); manager.addEpic(epic1); - manager.addEpic(epic2); - Subtask subtask1 = new Subtask("Sub1", "Desc", Status.NEW, epic1.getId()); - Subtask subtask2 = new Subtask("Sub2", "Desc", Status.NEW, epic1.getId()); + Subtask subtask1 = new Subtask("Бронирование зала", "Выбрать и забронировать помещение", Status.NEW, epic1.getId()); + Subtask subtask2 = new Subtask("Закупка еды", "Заказать еду и напитки", Status.NEW, epic1.getId()); manager.addSubtask(subtask1); manager.addSubtask(subtask2); + // Просмотры для теста истории manager.getTaskById(task1.getId()); manager.getEpicById(epic1.getId()); - manager.getTaskById(task1.getId()); manager.getSubtaskById(subtask1.getId()); - printHistory(manager); - manager.removeTaskById(task1.getId()); - printHistory(manager); + printAll(manager); - manager.removeEpicById(epic1.getId()); - printHistory(manager); + // Восстановление менеджера из файла + System.out.println("\nВосстановление менеджера из файла:"); + TaskManager restoredManager = FileBackedTaskManager.loadFromFile(file); + printAll(restoredManager); } - private static void printHistory(TaskManager manager) { - List history = manager.getHistory(); - if (history.isEmpty()) { - System.out.println("History is empty"); - } else { - System.out.println("\nView history (" + history.size() + " items):"); - for (int i = 0; i < history.size(); i++) { - Task task = history.get(i); - System.out.println((i + 1) + ". " + task.getTitle() + " [ID:" + task.getId() + "]"); - } + private static void printAll(TaskManager manager) { + System.out.println("\n=== Задачи ==="); + for (Task task : manager.getAllTasks()) { + System.out.println(task); + } + + System.out.println("\n=== Эпики ==="); + for (Epic epic : manager.getAllEpics()) { + System.out.println(epic); + } + + System.out.println("\n=== Подзадачи ==="); + for (Subtask subtask : manager.getAllSubtasks()) { + System.out.println(subtask); + } + + System.out.println("\n=== История просмотров ==="); + for (Task task : manager.getHistory()) { + System.out.println(task); } } } \ No newline at end of file diff --git a/src/manager/FileBackedTaskManager.java b/src/manager/FileBackedTaskManager.java new file mode 100644 index 0000000..a155d5f --- /dev/null +++ b/src/manager/FileBackedTaskManager.java @@ -0,0 +1,155 @@ +package manager; + +import model.*; +import java.io.*; +import java.nio.file.Files; +import java.util.*; + +public class FileBackedTaskManager extends InMemoryTaskManager { + + private final File file; + + public FileBackedTaskManager(File file) { + this.file = file; + } + + private void save() { + try (Writer writer = new FileWriter(file)) { + writer.write("id,type,name,status,description,epic\n"); + + for (Task task : getAllTasks()) { + writer.write(toString(task) + "\n"); + } + for (Epic epic : getAllEpics()) { + writer.write(toString(epic) + "\n"); + } + for (Subtask subtask : getAllSubtasks()) { + writer.write(toString(subtask) + "\n"); + } + + } catch (IOException e) { + throw new ManagerSaveException("Ошибка при сохранении данных в файл.", e); + } + } + + @Override + public void addTask(Task task) { + super.addTask(task); + save(); + } + + @Override + public void updateTask(Task task) { + super.updateTask(task); + save(); + } + + @Override + public void removeTaskById(int id) { + super.removeTaskById(id); + save(); + } + + @Override + public void addEpic(Epic epic) { + super.addEpic(epic); + save(); + } + + @Override + public void updateEpic(Epic epic) { + super.updateEpic(epic); + save(); + } + + @Override + public void removeEpicById(int id) { + super.removeEpicById(id); + save(); + } + + @Override + public void addSubtask(Subtask subtask) { + super.addSubtask(subtask); + save(); + } + + @Override + public void updateSubtask(Subtask subtask) { + super.updateSubtask(subtask); + save(); + } + + @Override + public void removeSubtaskById(int id) { + super.removeSubtaskById(id); + save(); + } + + private String toString(Task task) { + StringBuilder sb = new StringBuilder(); + sb.append(task.getId()).append(",") + .append(task instanceof Epic ? "EPIC" : task instanceof Subtask ? "SUBTASK" : "TASK").append(",") + .append(task.getTitle()).append(",") + .append(task.getStatus()).append(",") + .append(task.getDescription()); + + if (task instanceof Subtask) { + sb.append(",").append(((Subtask) task).getEpicId()); + } else { + sb.append(","); + } + return sb.toString(); + } + + private Task fromString(String line) { + String[] parts = line.split(","); + int id = Integer.parseInt(parts[0]); + String type = parts[1]; + String title = parts[2]; + Status status = Status.valueOf(parts[3]); + String description = parts[4]; + + switch (type) { + case "TASK": + Task task = new Task(title, description, status); + task.setId(id); + return task; + case "EPIC": + Epic epic = new Epic(title, description); + epic.setId(id); + return epic; + case "SUBTASK": + int epicId = Integer.parseInt(parts[5]); + Subtask subtask = new Subtask(title, 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 { + List lines = Files.readAllLines(file.toPath()); + for (int i = 1; i < lines.size(); i++) { // пропускаем заголовок + Task task = manager.fromString(lines.get(i)); + 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); + } + if (task.getId() >= manager.nextId) { + manager.nextId = task.getId() + 1; + } + } + } catch (IOException e) { + throw new ManagerSaveException("Ошибка при загрузке данных из файла.", e); + } + + return manager; + } +} \ No newline at end of file diff --git a/src/manager/ManagerSaveException.java b/src/manager/ManagerSaveException.java new file mode 100644 index 0000000..ae28077 --- /dev/null +++ b/src/manager/ManagerSaveException.java @@ -0,0 +1,12 @@ +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..71ee949 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 TaskManager getFileBackedTaskManager(File file) { + return new FileBackedTaskManager(file); + } } \ No newline at end of file diff --git a/src/model/Epic.java b/src/model/Epic.java index 3bf9376..2358141 100644 --- a/src/model/Epic.java +++ b/src/model/Epic.java @@ -43,14 +43,7 @@ public int hashCode() { return Objects.hash(super.hashCode(), subtaskIds); } - @Override - public String toString() { - return "Epic{" - + "id=" + getId() - + ", title='" + getTitle() + '\'' - + ", description='" + getDescription() + '\'' - + ", status=" + getStatus() - + ", subtaskIds=" + subtaskIds - + '}'; + public String toCsvString() { + return String.format("%d,EPIC,%s,%s,%s,", getId(), getTitle(), getStatus(), getDescription()); } } \ No newline at end of file diff --git a/src/model/Subtask.java b/src/model/Subtask.java index 0b4eef5..cd3ddd5 100644 --- a/src/model/Subtask.java +++ b/src/model/Subtask.java @@ -14,12 +14,6 @@ public int getEpicId() { @Override public String toString() { - return "Subtask{" + - "id=" + getId() + - ", title='" + getTitle() + '\'' + - ", description='" + getDescription() + '\'' + - ", status=" + getStatus() + - ", epicId=" + epicId + - '}'; + return String.format("%d,SUBTASK,%s,%s,%s,%d", getId(), getTitle(), getStatus(), getDescription(), getEpicId()); } } \ No newline at end of file diff --git a/src/model/Task.java b/src/model/Task.java index 2bc080b..1605ac6 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -68,11 +68,6 @@ public int hashCode() { @Override public String toString() { - return "Task{" - + "id=" + id - + ", title='" + title + '\'' - + ", description='" + description + '\'' - + ", status=" + status - + '}'; + return String.format("%d,TASK,%s,%s,%s,", id, title, status, description); } } \ No newline at end of file From bdf7154012b39a806663ff52f1fa667ba45de0bb Mon Sep 17 00:00:00 2001 From: n20va <99407852+n20va@users.noreply.github.com> Date: Wed, 2 Jul 2025 19:50:35 +0300 Subject: [PATCH 4/7] Update Main.java --- src/Main.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Main.java b/src/Main.java index d532d87..a794992 100644 --- a/src/Main.java +++ b/src/Main.java @@ -26,14 +26,11 @@ public static void main(String[] args) { manager.addSubtask(subtask1); manager.addSubtask(subtask2); - // Просмотры для теста истории manager.getTaskById(task1.getId()); manager.getEpicById(epic1.getId()); manager.getSubtaskById(subtask1.getId()); printAll(manager); - - // Восстановление менеджера из файла System.out.println("\nВосстановление менеджера из файла:"); TaskManager restoredManager = FileBackedTaskManager.loadFromFile(file); printAll(restoredManager); @@ -60,4 +57,4 @@ private static void printAll(TaskManager manager) { System.out.println(task); } } -} \ No newline at end of file +} From c135bdf6295d6bb235edb7cff7006ba8adbd97a0 Mon Sep 17 00:00:00 2001 From: n20va <99407852+n20va@users.noreply.github.com> Date: Wed, 2 Jul 2025 20:02:17 +0300 Subject: [PATCH 5/7] Update Main.java --- src/Main.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Main.java b/src/Main.java index b637793..a8b357c 100644 --- a/src/Main.java +++ b/src/Main.java @@ -6,7 +6,6 @@ import model.Task; import java.io.File; -import java.util.List; public class Main { public static void main(String[] args) { From 9813abc34c5526c2ff442a4554466355a58b2154 Mon Sep 17 00:00:00 2001 From: n20va <99407852+n20va@users.noreply.github.com> Date: Wed, 2 Jul 2025 21:59:18 +0300 Subject: [PATCH 6/7] Update FileBackedTaskManager.java --- src/manager/FileBackedTaskManager.java | 28 +++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/manager/FileBackedTaskManager.java b/src/manager/FileBackedTaskManager.java index a155d5f..46fc2ca 100644 --- a/src/manager/FileBackedTaskManager.java +++ b/src/manager/FileBackedTaskManager.java @@ -50,6 +50,12 @@ public void removeTaskById(int id) { save(); } + @Override + public void clearTasks() { + super.clearTasks(); + save(); + } + @Override public void addEpic(Epic epic) { super.addEpic(epic); @@ -68,6 +74,12 @@ public void removeEpicById(int id) { save(); } + @Override + public void clearEpics() { + super.clearEpics(); + save(); + } + @Override public void addSubtask(Subtask subtask) { super.addSubtask(subtask); @@ -86,6 +98,12 @@ public void removeSubtaskById(int id) { save(); } + @Override + public void clearSubtasks() { + super.clearSubtasks(); + save(); + } + private String toString(Task task) { StringBuilder sb = new StringBuilder(); sb.append(task.getId()).append(",") @@ -118,6 +136,7 @@ private Task fromString(String line) { case "EPIC": Epic epic = new Epic(title, description); epic.setId(id); + epic.setStatus(Status.NEW); return epic; case "SUBTASK": int epicId = Integer.parseInt(parts[5]); @@ -131,6 +150,7 @@ private Task fromString(String line) { public static FileBackedTaskManager loadFromFile(File file) { FileBackedTaskManager manager = new FileBackedTaskManager(file); + try { List lines = Files.readAllLines(file.toPath()); for (int i = 1; i < lines.size(); i++) { // пропускаем заголовок @@ -146,10 +166,16 @@ public static FileBackedTaskManager loadFromFile(File file) { manager.nextId = task.getId() + 1; } } + for (Subtask subtask : manager.subtasks.values()) { + Epic epic = manager.epics.get(subtask.getEpicId()); + if (epic != null) { + epic.addSubtask(subtask); + } + } } catch (IOException e) { throw new ManagerSaveException("Ошибка при загрузке данных из файла.", e); } return manager; } -} \ No newline at end of file +} From 0d1354f625431b6aae72b2865141b63735b4b47b Mon Sep 17 00:00:00 2001 From: n20va <99407852+n20va@users.noreply.github.com> Date: Thu, 3 Jul 2025 22:34:08 +0300 Subject: [PATCH 7/7] Update FileBackedTaskManager.java --- src/manager/FileBackedTaskManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/manager/FileBackedTaskManager.java b/src/manager/FileBackedTaskManager.java index 46fc2ca..040f931 100644 --- a/src/manager/FileBackedTaskManager.java +++ b/src/manager/FileBackedTaskManager.java @@ -136,7 +136,7 @@ private Task fromString(String line) { case "EPIC": Epic epic = new Epic(title, description); epic.setId(id); - epic.setStatus(Status.NEW); + epic.setStatus(status); return epic; case "SUBTASK": int epicId = Integer.parseInt(parts[5]);