diff --git a/.idea/checkstyle-idea.xml b/.idea/checkstyle-idea.xml new file mode 100644 index 0000000..94f04f1 --- /dev/null +++ b/.idea/checkstyle-idea.xml @@ -0,0 +1,19 @@ + + + + 10.25.0 + Everything + true + + + + \ No newline at end of file diff --git a/.idea/checkstyleidea-libs/readme.txt b/.idea/checkstyleidea-libs/readme.txt new file mode 100644 index 0000000..d011e75 --- /dev/null +++ b/.idea/checkstyleidea-libs/readme.txt @@ -0,0 +1,6 @@ +This folder contains libraries copied from the "java-kanban" project. +It is managed by the CheckStyle-IDEA IDE plugin. +Do not modify this folder while the IDE is running. +When the IDE is stopped, you may delete this folder at any time. It will be recreated as needed. +In order to prevent the CheckStyle-IDEA IDE plugin from creating this folder, +uncheck the "Copy libraries from project directory" option in the CheckStyle-IDEA settings dialog. diff --git a/checkstyle.xml b/checkstyle.xml new file mode 100644 index 0000000..87bb112 --- /dev/null +++ b/checkstyle.xml @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java-kanban.iml b/java-kanban.iml index 5dfd50f..265bb5c 100644 --- a/java-kanban.iml +++ b/java-kanban.iml @@ -1,5 +1,8 @@ + + diff --git a/src/Main.java b/src/Main.java index 039c654..784c22a 100644 --- a/src/Main.java +++ b/src/Main.java @@ -8,86 +8,72 @@ public class Main { public static void main(String[] args) { - TaskManager taskManager = Managers.getDefault(); - - // 1.Создать таску + // 1. Создать таску System.out.println("Создать таску"); - Task taskForCreate = new Task("Name", "Desc", TaskStatus.NEW); - taskManager.createTask(taskForCreate); + Task task = new Task("Name", "Desc", TaskStatus.NEW); + taskManager.createTask(task); System.out.println(taskManager.getTasks()); + System.out.println("История после создания задачи (должна быть пустая): " + taskManager.getHistory()); System.out.println(); - // 2.Получить таску + // 2. Получить таску (добавится в историю) System.out.println("Получить таску"); - System.out.println(taskManager.getTask(taskForCreate.getId())); + System.out.println(taskManager.getTask(task.getId())); + System.out.println("История после первого просмотра (1 задача): " + taskManager.getHistory()); System.out.println(); - // 3. Проверим обновление - System.out.println("Проверим обновление"); - Task taskForUpdate = new Task(taskForCreate.getId(), "New name", - taskForCreate.getDescription(), TaskStatus.IN_PROGRESS); - taskForUpdate = taskManager.updateTask(taskForUpdate); - System.out.println(taskManager.getTasks()); - System.out.println(); - - //4. Удаляем таску - System.out.println("Удаляем таску"); - taskManager.deleteTask(taskForUpdate.getId()); - System.out.println(taskManager.getTasks()); + // 3. Получить таску еще раз (должна остаться одна запись) + System.out.println("Получить таску повторно"); + System.out.println(taskManager.getTask(task.getId())); + System.out.println("История после повторного просмотра (все равно 1 задача): " + taskManager.getHistory()); System.out.println(); - //5. Создаём Эпик + // 4. Создаём Эпик System.out.println("Создаём Эпик"); Epic epic = new Epic("Отпуск", "Организовать отпуск"); taskManager.createEpic(epic); + System.out.println("История после создания эпика (не должна измениться): " + taskManager.getHistory()); + System.out.println(); + + // 5. Просматриваем эпик (добавится в историю) + System.out.println("Просматриваем эпик"); System.out.println(taskManager.getEpic(epic.getId())); + System.out.println("История после просмотра эпика (2 задачи): " + taskManager.getHistory()); System.out.println(); - //5. Создаём Сабтаски + // 6. Создаём Сабтаски System.out.println("Создаём Сабтаски"); Subtask subtask1 = new Subtask("Путёвка", "Выбрать путёвку", TaskStatus.NEW, epic.getId()); Subtask subtask2 = new Subtask("Билеты", "Купить билеты", TaskStatus.NEW, epic.getId()); taskManager.createSubtask(subtask1); taskManager.createSubtask(subtask2); - taskManager.getEpicSubtasks(epic.getId()); - System.out.println(taskManager.getEpicSubtasks(epic.getId())); - System.out.println(); - - //6. Проверяем статус Эпика (NEW) - System.out.println("Проверяем статус Эпика " + taskManager.getEpic(epic.getId()).getTaskStatus()); + System.out.println("История после создания подзадач (не должна измениться): " + taskManager.getHistory()); System.out.println(); - //7. Меняем статус первого Сабтаска. - Subtask updatedSubtask = new Subtask(subtask1.getId(), subtask1.getName(), subtask1.getDescription(), - TaskStatus.DONE, subtask1.getEpicId()); - taskManager.updateSubtask(updatedSubtask); - System.out.println("Статус Эпика после изменения одной Сабтаски " + taskManager.getEpic(epic.getId()).getTaskStatus()); + // 7. Просматриваем подзадачи (добавляются в историю) + System.out.println("Просматриваем подзадачи"); + System.out.println("Подзадача 1: " + taskManager.getSubtasks(subtask1.getId())); + System.out.println("Текущая история (3 задачи - задача, эпик, подзадача1): " + taskManager.getHistory()); + System.out.println("Подзадача 2: " + taskManager.getSubtasks(subtask2.getId())); + System.out.println("История после просмотра второй подзадачи (4 задачи): " + taskManager.getHistory()); System.out.println(); - //8. Меняем статус второго Сабтаска. - Subtask updatedSubtask2 = new Subtask(subtask2.getId(), subtask2.getName(), subtask2.getDescription(), - TaskStatus.DONE, subtask2.getEpicId()); - taskManager.updateSubtask(updatedSubtask2); - System.out.println("Статус Эпика после изменения одной Сабтаски " + taskManager.getEpic(epic.getId()).getTaskStatus()); + // 8. Удаляем таску (должна удалиться из истории) + System.out.println("Удаляем таску"); + taskManager.deleteTask(task.getId()); + System.out.println("История после удаления задачи (3 задачи): " + taskManager.getHistory()); System.out.println(); - //9. Удаляем Эпик. + // 9. Удаляем Эпик (должны удалиться эпик и его подзадачи из истории) + System.out.println("Удаляем Эпик"); taskManager.deleteEpic(epic.getId()); - System.out.println("Эпики после удаления: " + taskManager.getEpics()); - System.out.println("Сабтаски после удаления Эпика: " + taskManager.getSubtasks()); + System.out.println("История после удаления эпика (должна быть пустая): " + taskManager.getHistory()); System.out.println(); - //10. Проверяем удаление всех задач. - taskManager.deleteAllTasks(); - System.out.println("Все Таски после очистки: " + taskManager.getTasks()); - System.out.println("Все Сабтаски после очистки: " + taskManager.getSubtasks()); - System.out.println("Все Эпики после очистки: " + taskManager.getEpics()); - - //11.Проверяем историю. - System.out.println("Проверяем историю."); - System.out.println(taskManager.getHistory()); - System.out.println(); + // 10. Проверяем историю после всех операций + System.out.println("Финальная проверка истории"); + System.out.println("История: " + taskManager.getHistory()); } } diff --git a/src/manager/HistoryManager.java b/src/manager/HistoryManager.java index 3307c60..be0776e 100644 --- a/src/manager/HistoryManager.java +++ b/src/manager/HistoryManager.java @@ -8,4 +8,7 @@ public interface HistoryManager { List getHistory(); void add(Task task); + + void remove(int id); + } diff --git a/src/manager/InMemoryHistoryManager.java b/src/manager/InMemoryHistoryManager.java index e47e982..3ec8caa 100644 --- a/src/manager/InMemoryHistoryManager.java +++ b/src/manager/InMemoryHistoryManager.java @@ -1,31 +1,86 @@ package manager; import tasks.Task; -import java.util.LinkedList; -import java.util.List; +import java.util.*; public class InMemoryHistoryManager implements HistoryManager { - private static final int MAX_HISTORY_SIZE = 10; - private final LinkedList history = new LinkedList<>(); - @Override - public List getHistory() { - //Получить список историй. - return new LinkedList<>(history); - } + private final Map nodeMap = 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 node = new Node(task); + linkLast(node); + nodeMap.put(task.getId(), node); + } + + // Удаление задачи из истории по ID. + @Override + public void remove(int id) { + Node node = nodeMap.remove(id); + + if (node != null) { + removeNode(node); + } + } + + // Получение списка задач из истории просмотров. + @Override + public List getHistory() { + List history = new ArrayList<>(); + + Node current = head; + while (current != null) { + history.add(current.item); + current = current.next; + } + return history; + } + + // Добавление узла в конец двусвязного списка. + private void linkLast(Node node) { + if (tail == null) { + head = tail = node; + } else { + tail.next = node; + node.prev = tail; + tail = node; + } + } + + // Удаление узла из двусвязного списка + private void removeNode(Node node) { + if (node.prev != null) { + node.prev.next = node.next; + } else { + head = node.next; } - history.remove(task); - history.addLast(task); + if (node.next != null) { + node.next.prev = node.prev; + } else { + tail = node.prev; + } + } + + // Внутренний класс для узла двусвязного списка. + private static class Node { + T item; + Node prev; + Node next; + + Node(T item) { + this.item = item; + } } } + diff --git a/src/manager/InMemoryTaskManager.java b/src/manager/InMemoryTaskManager.java index e755b7d..2c7dae9 100644 --- a/src/manager/InMemoryTaskManager.java +++ b/src/manager/InMemoryTaskManager.java @@ -23,6 +23,7 @@ public class InMemoryTaskManager implements TaskManager { // Методы для Task @Override public List getTasks() { + return new ArrayList<>(tasks.values()); } @@ -54,7 +55,11 @@ public Task updateTask(Task task) { @Override public Task deleteTask(int id) { - return tasks.remove(id); + Task task = tasks.remove(id); + if (task != null) { + historyManager.remove(id); + } + return task; } // Методы для Subtask @@ -119,6 +124,7 @@ public Subtask deleteSubtask(int id) { epic.removeSubtaskId(id); updateEpicStatus(epic); } + historyManager.remove(id); } return subtask; } @@ -162,8 +168,9 @@ public Epic deleteEpic(int id) { if (epic != null) { for (Integer subtaskId : epic.getSubtasksId()) { subtasks.remove(subtaskId); + historyManager.remove(subtaskId); } - + historyManager.remove(id); } return epic; } @@ -186,9 +193,38 @@ public List getEpicSubtasks(int epicId) { @Override public void deleteAllTasks() { + for (Integer taskId : tasks.keySet()) { + historyManager.remove(taskId); + } tasks.clear(); + } + + @Override + public void deleteAllSubtasks() { + for (Integer subtaskId : subtasks.keySet()) { + historyManager.remove(subtaskId); + } subtasks.clear(); + for (Epic epic : epics.values()) { + epic.getSubtasksId().clear(); + updateEpicStatus(epic); + } + } + + @Override + public void deleteAllEpics() { + deleteAllSubtasks(); + for (Integer epicId : epics.keySet()) { + historyManager.remove(epicId); + } epics.clear(); + } + + @Override + public void deleteAll() { + deleteAllTasks(); + deleteAllSubtasks(); + deleteAllEpics(); generatorId = 1; } diff --git a/src/manager/TaskManager.java b/src/manager/TaskManager.java index e714b04..81e0619 100644 --- a/src/manager/TaskManager.java +++ b/src/manager/TaskManager.java @@ -41,7 +41,15 @@ public interface TaskManager { List getEpicSubtasks(int epicId); + // Метод для получения истории + List getHistory(); + + // Методы для удаления void deleteAllTasks(); - List getHistory(); + void deleteAllSubtasks(); + + void deleteAllEpics(); + + void deleteAll(); } diff --git a/test/manager/InMemoryHistoryManagerTest.java b/test/manager/InMemoryHistoryManagerTest.java index a08e241..d5e7059 100644 --- a/test/manager/InMemoryHistoryManagerTest.java +++ b/test/manager/InMemoryHistoryManagerTest.java @@ -6,8 +6,7 @@ import tasks.TaskStatus; import java.util.List; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.*; public class InMemoryHistoryManagerTest { @@ -46,5 +45,39 @@ void addToHistory() { assertEquals(1, history.size(), "История должна содержать 1 задачу"); assertEquals(task, history.get(0), "Задача в истории должна соответствовать добавленной"); } + + // Повторное добавление задачи заменяет предыдущую запись. + @Test + void duplicateTaskInHistory() { + Task task = taskManager.createTask(new Task("Task", "Desc", TaskStatus.NEW)); + historyManager.add(task); + Task updatedTask = new Task(task.getId(), "Task", "Updated Desc", TaskStatus.IN_PROGRESS); + historyManager.add(updatedTask); + + List history = historyManager.getHistory(); + assertEquals(1, history.size(), "История должна содержать только одну задачу"); + assertEquals(TaskStatus.IN_PROGRESS, history.get(0).getTaskStatus(), "Задача должна быть обновлена"); + } + + // Удаление задачи из истории. + @Test + void removeTaskFromHistory() { + Task task1 = taskManager.createTask(new Task("Task1", "Desc", TaskStatus.NEW)); + Task task2 = taskManager.createTask(new Task("Task2", "Desc", TaskStatus.IN_PROGRESS)); + historyManager.add(task1); + historyManager.add(task2); + historyManager.remove(task1.getId()); + + List history = historyManager.getHistory(); + assertEquals(1, history.size(), "История должна содержать 1 задачу после удаления"); + assertEquals(task2, history.get(0), "Оставшаяся задача должна быть task2"); + } + + // Пустая история. + @Test + void emptyHistory() { + List history = historyManager.getHistory(); + assertTrue(history.isEmpty(), "История должна быть пустой"); + } } diff --git a/test/manager/InMemoryTaskManagerTest.java b/test/manager/InMemoryTaskManagerTest.java index e9359fe..1af39da 100644 --- a/test/manager/InMemoryTaskManagerTest.java +++ b/test/manager/InMemoryTaskManagerTest.java @@ -126,4 +126,87 @@ void taskRemainsUnchanged() { assertEquals(original.getTaskStatus(), added.getTaskStatus(), "Статус не должен изменяться"); } + // Удаление задачи удаляет её из истории. + @Test + void deleteTaskRemovesFromHistory() { + Task task = taskManager.createTask(new Task("Task", "Desc", TaskStatus.NEW)); + taskManager.getTask(task.getId()); + taskManager.deleteTask(task.getId()); + + List history = taskManager.getHistory(); + assertTrue(history.isEmpty(), "История должна быть пустой после удаления задачи"); + } + + // Удаление эпика удаляет его подзадачи из истории. + @Test + void deleteEpicRemovesSubtasksFromHistory() { + Epic epic = taskManager.createEpic(new Epic("Epic", "Desc")); + Subtask subtask = taskManager.createSubtask( + new Subtask("Subtask", "Desc", TaskStatus.NEW, epic.getId())); + taskManager.getSubtasks(subtask.getId()); + taskManager.getEpic(epic.getId()); + taskManager.deleteEpic(epic.getId()); + + List history = taskManager.getHistory(); + assertTrue(history.isEmpty(), "История должна быть пустой после удаления эпика"); + } + + // Удаляем только таски. + @Test + void deleteAllTasksRemovesOnlyTasks() { + Task task = taskManager.createTask(new Task("Task", "Desc", TaskStatus.NEW)); + Epic epic = taskManager.createEpic(new Epic("Epic", "Desc")); + Subtask subtask = taskManager.createSubtask(new Subtask("Sub", "Desc", TaskStatus.NEW, epic.getId())); + + taskManager.deleteAllTasks(); + + assertTrue(taskManager.getTasks().isEmpty(), "Все задачи должны быть удалены"); + assertFalse(taskManager.getEpics().isEmpty(), "Эпики должны остаться"); + assertFalse(taskManager.getSubtasks().isEmpty(), "Подзадачи должны остаться"); + } + + // Удаляем только сабтаски. + @Test + void deleteAllSubtasksRemovesOnlySubtasks() { + Task task = taskManager.createTask(new Task("Task", "Desc", TaskStatus.NEW)); + Epic epic = taskManager.createEpic(new Epic("Epic", "Desc")); + Subtask subtask = taskManager.createSubtask(new Subtask("Sub", "Desc", TaskStatus.NEW, epic.getId())); + + taskManager.deleteAllSubtasks(); + + assertFalse(taskManager.getTasks().isEmpty(), "Задачи должны остаться"); + assertFalse(taskManager.getEpics().isEmpty(), "Эпики должны остаться"); + assertTrue(taskManager.getSubtasks().isEmpty(), "Все подзадачи должны быть удалены"); + } + + // Удаляем эпики и их сабтаски. + @Test + void deleteAllEpicsRemovesEpicsAndSubtasks() { + Task task = taskManager.createTask(new Task("Task", "Desc", TaskStatus.NEW)); + Epic epic = taskManager.createEpic(new Epic("Epic", "Desc")); + Subtask subtask = taskManager.createSubtask(new Subtask("Sub", "Desc", TaskStatus.NEW, epic.getId())); + + taskManager.deleteAllEpics(); + + assertFalse(taskManager.getTasks().isEmpty(), "Задачи должны остаться"); + assertTrue(taskManager.getEpics().isEmpty(), "Все эпики должны быть удалены"); + assertTrue(taskManager.getSubtasks().isEmpty(), "Все подзадачи должны быть удалены"); + } + + // Удаляем всё. + @Test + void deleteAllRemovesEverything() { + Task task = taskManager.createTask(new Task("Task", "Desc", TaskStatus.NEW)); + Epic epic = taskManager.createEpic(new Epic("Epic", "Desc")); + Subtask subtask = taskManager.createSubtask(new Subtask("Sub", "Desc", TaskStatus.NEW, epic.getId())); + + taskManager.deleteAll(); + + assertTrue(taskManager.getTasks().isEmpty(), "Все задачи должны быть удалены"); + assertTrue(taskManager.getEpics().isEmpty(), "Все эпики должны быть удалены"); + assertTrue(taskManager.getSubtasks().isEmpty(), "Все подзадачи должны быть удалены"); + } } + + +