diff --git a/src/Main.java b/src/Main.java index 0c765af..1ef8157 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,4 +1,3 @@ - public class Main { public static void main(String[] args) { diff --git a/src/managers/InMemoryHistoryManager.java b/src/managers/InMemoryHistoryManager.java deleted file mode 100644 index 0439dcf..0000000 --- a/src/managers/InMemoryHistoryManager.java +++ /dev/null @@ -1,26 +0,0 @@ -package managers; - -import model.Task; - -import java.util.LinkedList; -import java.util.List; - -public class InMemoryHistoryManager implements HistoryManager { - - private final LinkedList history = new LinkedList<>(); - private final int MAX_HISTORY_CAPACITY = 10; - - @Override - public void addTask(Task task) { - - if (history.size() == MAX_HISTORY_CAPACITY) { - history.removeFirst(); - } - history.add(task); - } - - @Override - public List getHistory() { - return new LinkedList<>(history); - } -} diff --git a/src/managers/InMemoryTaskManager.java b/src/managers/InMemoryTaskManager.java index 8e9b5d3..0c8396a 100644 --- a/src/managers/InMemoryTaskManager.java +++ b/src/managers/InMemoryTaskManager.java @@ -1,5 +1,6 @@ package managers; +import managers.history.HistoryManager; import model.Epic; import model.Status; import model.SubTask; @@ -150,11 +151,13 @@ public void deleteTask(int id) { if (!tasks.containsKey(id)) { return; } + historyManager.remove(id); // удаляем из истории tasks.remove(id); } @Override public void clearTasks() { + clearHistoryTasks(); tasks.clear(); } @@ -163,18 +166,24 @@ public void deleteEpic(int id) { if (!epics.containsKey(id)) { return; } - Epic epic = epics.get(id); for (Integer subtaskId : epic.getSubtaskIds()) { // удаляем из основной таблицы подзадач каждую подзадачу эпика subtasks.remove(subtaskId); + historyManager.remove(subtaskId); // удаляем из истории } + + historyManager.remove(id); // удаляем из истории epics.remove(id); + } @Override public void clearEpics() { + clearHistoryEpics(); epics.clear(); + + clearHistorySubTasks(); subtasks.clear(); } @@ -190,17 +199,37 @@ public void deleteSubTask(int id) { epic.deleteSubTask(id); updateEpicStatus(epic); + historyManager.remove(id); // удаляем из истории subtasks.remove(id); } @Override public void clearSubTasks() { + clearHistorySubTasks(); subtasks.clear(); for (Epic epic : epics.values()) { epic.clearSubtasks(); // статус эпика обновляется внутри метода } } + private void clearHistoryTasks() { + for (Integer id : tasks.keySet()) { + historyManager.remove(id); + } + } + + private void clearHistoryEpics() { + for (Integer id : epics.keySet()) { + historyManager.remove(id); + } + } + + private void clearHistorySubTasks() { + for (Integer id : subtasks.keySet()) { + historyManager.remove(id); + } + } + @Override public List getHistory() { return historyManager.getHistory(); diff --git a/src/managers/Managers.java b/src/managers/Managers.java index 99b8662..24c98dc 100644 --- a/src/managers/Managers.java +++ b/src/managers/Managers.java @@ -1,5 +1,8 @@ package managers; +import managers.history.HistoryManager; +import managers.history.InMemoryHistoryManager; + public class Managers { public static TaskManager getDefault() { diff --git a/src/managers/HistoryManager.java b/src/managers/history/HistoryManager.java similarity index 73% rename from src/managers/HistoryManager.java rename to src/managers/history/HistoryManager.java index 167b664..dacd43a 100644 --- a/src/managers/HistoryManager.java +++ b/src/managers/history/HistoryManager.java @@ -1,4 +1,4 @@ -package managers; +package managers.history; import model.Task; @@ -8,6 +8,8 @@ public interface HistoryManager { void addTask(Task task); + void remove(int id); + List getHistory(); } diff --git a/src/managers/history/InMemoryHistoryManager.java b/src/managers/history/InMemoryHistoryManager.java new file mode 100644 index 0000000..6f8d3bb --- /dev/null +++ b/src/managers/history/InMemoryHistoryManager.java @@ -0,0 +1,88 @@ +package managers.history; + +import model.Task; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class InMemoryHistoryManager implements HistoryManager { + private Node head; + private Node tail; + + private final HashMap history = new HashMap<>(); + + @Override + public void addTask(Task task) { + if (task == null) { + return; + } + int id = task.getTaskId(); + remove(id); + history.put(id, linkLast(task)); + } + + + @Override + public void remove(int id) { + Node node = history.remove(id); + if (node == null) { + return; + } + removeNode(node); + } + + @Override + public List getHistory() { + return getTasks(); + } + + private Node linkLast(Task task) { + Node newNode = new Node(tail, task, null); + + if (tail == null) { + // инициализируем голову, теперь она будет хранить всю последовательность + head = newNode; + } else { + // добавляем новый узел к текущему хвосту + tail.setNext(newNode); + } + tail = newNode; // переопределяем хвост + + return newNode; + } + + private void removeNode(Node node) { + Node next = node.getNext(); + Node prev = node.getPrev(); + + if (prev == null) { + // переопределяем голову на второй элемент последовательности + head = next; + } else { + // привязываем предыдущий узел к последующему (минуя текущий) + prev.setNext(next); + } + + if (next == null) { + // переопределяем хвост на предпоследний элемент последовательности + tail = prev; + } else { + // привязываем к последующему узлу предыдущий (минуя текущий) + next.setPrev(prev); + } + + } + + private List getTasks() { + List tasks = new ArrayList<>(); + Node current = head; // копия головы, чтобы избежать потери + + // проходим через всю последовательность и добавляем задачу в список + while (current != null) { + tasks.add(current.getTask()); + current = current.getNext(); + } + return tasks; + } +} diff --git a/src/managers/history/Node.java b/src/managers/history/Node.java new file mode 100644 index 0000000..8485aa5 --- /dev/null +++ b/src/managers/history/Node.java @@ -0,0 +1,44 @@ +package managers.history; + +import model.Task; + +public class Node { + + private final Task task; + private Node prev; + private Node next; + + public Node(Node prev, Task task, Node next) { + this.task = task; + this.prev = prev; + this.next = next; + } + + public Task getTask() { + return task; + } + + public Node getPrev() { + return prev; + } + + public void setPrev(Node prev) { + this.prev = prev; + } + + public Node getNext() { + return next; + } + + public void setNext(Node next) { + this.next = next; + } + + @Override + public String toString() { + return String.format("task=%s, next=%s", + this.task, + this.next); + } + +} diff --git a/src/model/Task.java b/src/model/Task.java index e86312c..f1ba32b 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -27,7 +27,7 @@ public String getTitle() { return title; } - public void setTitle(String title){ + public void setTitle(String title) { this.title = title; } @@ -35,9 +35,10 @@ public String getDescription() { return description; } - public void setDescription(String description){ + public void setDescription(String description) { this.description = description; } + public Status getStatus() { return status; } diff --git a/test/managers/InMemoryHistoryManagerTest.java b/test/managers/InMemoryHistoryManagerTest.java index 255d947..540ae7e 100644 --- a/test/managers/InMemoryHistoryManagerTest.java +++ b/test/managers/InMemoryHistoryManagerTest.java @@ -1,17 +1,17 @@ package managers; +import managers.history.HistoryManager; 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.assertTrue; -import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.*; -class InMemoryHistoryManagerTest { +public class InMemoryHistoryManagerTest { - private final HistoryManager manager = Managers.getDefaultHistory(); + private final HistoryManager historyManager = Managers.getDefaultHistory(); @Test public void shouldAddAnyTask() { @@ -23,28 +23,116 @@ public void shouldAddAnyTask() { SubTask subtask = new SubTask("subtask", "test", Status.NEW, 2); subtask.setTaskId(3); - manager.addTask(task); - manager.addTask(epic); - manager.addTask(subtask); + historyManager.addTask(task); + historyManager.addTask(epic); + historyManager.addTask(subtask); - assertTrue(manager.getHistory().contains(task)); - assertTrue(manager.getHistory().contains(epic)); - assertTrue(manager.getHistory().contains(subtask)); + assertTrue(historyManager.getHistory().contains(task)); + assertTrue(historyManager.getHistory().contains(epic)); + assertTrue(historyManager.getHistory().contains(subtask)); } @Test - public void shouldDeleteFirstAndAddLastWhenMaxLimit() { - for (int i = 0; i < 10; i++) { - manager.addTask(new Task(i+"", i+"", Status.NEW)); + public void shouldBeUniqueInHistoryWhenWasAddedAgain() { + for (int i = 1; i <= 3; i++) { + Task task = new Task(i + "", "test", Status.NEW); + task.setTaskId(i); + historyManager.addTask(task); } - Task first = manager.getHistory().getFirst(); + int id = 2; + Task task = new Task(id + "", "again", Status.NEW); + task.setTaskId(id); + historyManager.addTask(task); - Task last = new Task(11+"", 11+"", Status.NEW); - manager.addTask(last); + int expected = 1; + int actual = 0; + for (Task t : historyManager.getHistory()) { + if (t.getTaskId() == id) { + actual++; + } + } + assertEquals(expected, actual); + } + + @Test + public void shouldBeLastInHistoryWhenWasAddedAgain() { + for (int i = 1; i <= 3; i++) { + Task task = new Task(i + "", "test", Status.NEW); + task.setTaskId(i); + historyManager.addTask(task); + } + + Task task = new Task(1 + "", "again", Status.NEW); + task.setTaskId(1); + historyManager.addTask(task); + + assertEquals(historyManager.getHistory().getLast(), task); + } + + @Test + public void shouldNotContainWhenDeletedFromTaskManager() { + TaskManager taskManager = Managers.getDefault(); + Task task = new Task("title", "demo", Status.NEW); + taskManager.addTask(task); + taskManager.getTask(1); + + taskManager.deleteTask(1); + + assertFalse(taskManager.getHistory().contains(task)); + + } + + @Test + public void shouldBeEmptyWhenTasksClearedFromTaskManager() { + TaskManager taskManager = Managers.getDefault(); + for (int i = 1; i <= 10; i++) { + taskManager.addTask(new Task("title", "demo", Status.NEW)); + taskManager.getTask(i); + } + taskManager.clearTasks(); + assertTrue(taskManager.getHistory().isEmpty()); + } - assertFalse(manager.getHistory().contains(first)); - assertTrue(manager.getHistory().contains(last)); + @Test + public void shouldBeEmptyWhenEpicsClearedFromTaskManager() { + TaskManager taskManager = Managers.getDefault(); + for (int i = 1; i <= 10; i++) { + taskManager.addEpic(new Epic("title", "demo", Status.NEW)); + taskManager.getEpic(i); + } + taskManager.clearEpics(); + assertTrue(taskManager.getHistory().isEmpty()); + } + + @Test + public void shouldBeEmptyWhenSubtasksClearedFromTaskManager() { + TaskManager taskManager = Managers.getDefault(); + taskManager.addEpic(new Epic("epic", "demo", Status.NEW)); + + for (int i = 2; i <= 10; i++) { + taskManager.addSubTask(new SubTask("title", "demo", Status.NEW, 1)); + taskManager.getSubTask(i); + } + taskManager.clearSubTasks(); + assertTrue(taskManager.getHistory().isEmpty()); } + + @Test + public void shouldBeEmptyWhenEpicsClearedFromTaskManagerAndHistoryContainsSubtasks() { + TaskManager taskManager = Managers.getDefault(); + for (int i = 1; i <= 10; i++) { + taskManager.addEpic(new Epic("title", "demo", Status.NEW)); + } + for (int i = 11; i <= 20; i++) { + taskManager.addSubTask(new SubTask("title", "demo", Status.NEW, i - 10)); + taskManager.getSubTask(i); + } + + taskManager.clearEpics(); + assertTrue(taskManager.getHistory().isEmpty()); + } + + } \ No newline at end of file diff --git a/test/managers/InMemoryTaskManagerTest.java b/test/managers/InMemoryTaskManagerTest.java index aac9b63..dded598 100644 --- a/test/managers/InMemoryTaskManagerTest.java +++ b/test/managers/InMemoryTaskManagerTest.java @@ -6,7 +6,7 @@ import static org.junit.jupiter.api.Assertions.*; -class InMemoryTaskManagerTest { +public class InMemoryTaskManagerTest { private final TaskManager manager = Managers.getDefault(); private Task task; @@ -122,7 +122,7 @@ public void shouldContainSubtaskIdInEpic() { @Test public void subTasksSizeInEpicShouldBeEqualWithSize() { - // проверяем, что количетсво сабтасков в эпике равно добавленным сабтаскам + // проверяем, что количество сабтасков в эпике равно добавленным сабтаскам assertEquals(2, manager.getSubTasksFromEpic(epicId).size()); assertEquals(2, manager.getEpic(epicId).getSubtaskIds().size()); } diff --git a/test/managers/ManagersTest.java b/test/managers/ManagersTest.java index b3fdd56..9020b6e 100644 --- a/test/managers/ManagersTest.java +++ b/test/managers/ManagersTest.java @@ -4,15 +4,15 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; -class ManagersTest { +public class ManagersTest { @Test - public void shouldBeNotNullWhenDefault(){ + public void shouldBeNotNullWhenDefault() { assertNotNull(Managers.getDefault()); } @Test - public void shouldBeNotNullWhenHistoryDefault(){ + public void shouldBeNotNullWhenHistoryDefault() { assertNotNull(Managers.getDefaultHistory()); } } \ No newline at end of file diff --git a/test/model/EpicTest.java b/test/model/EpicTest.java index 1c09cdf..5e365f2 100644 --- a/test/model/EpicTest.java +++ b/test/model/EpicTest.java @@ -3,10 +3,10 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -class EpicTest { +public class EpicTest { @Test - void shouldBeEqualWhenIdEqual() { + public void shouldBeEqualWhenIdEqual() { Epic epic1 = new Epic("test1", "test1", Status.NEW); Epic epic2 = new Epic("test2", "test2", Status.NEW); diff --git a/test/model/SubTaskTest.java b/test/model/SubTaskTest.java index 70c39e5..f032c10 100644 --- a/test/model/SubTaskTest.java +++ b/test/model/SubTaskTest.java @@ -3,12 +3,12 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -class SubTaskTest { +public class SubTaskTest { @Test - void shouldBeEqualWhenIdEqual() { - SubTask subtask1 = new SubTask("test1", "test1", Status.NEW,2); - SubTask subTask2 = new SubTask("test2", "test2", Status.NEW,2); + public void shouldBeEqualWhenIdEqual() { + SubTask subtask1 = new SubTask("test1", "test1", Status.NEW, 2); + SubTask subTask2 = new SubTask("test2", "test2", Status.NEW, 2); subtask1.setTaskId(1); // устанавливаем одинаковые id subTask2.setTaskId(1); diff --git a/test/model/TaskTest.java b/test/model/TaskTest.java index d4da1d7..0051c12 100644 --- a/test/model/TaskTest.java +++ b/test/model/TaskTest.java @@ -3,10 +3,10 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -class TaskTest { +public class TaskTest { @Test - void shouldBeEqualWhenIdEqual() { + public void shouldBeEqualWhenIdEqual() { Task task1 = new Task("test1", "test1", Status.NEW); Task task2 = new Task("test2", "test2", Status.NEW);