Skip to content
60 changes: 24 additions & 36 deletions src/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
public class Main {

// Метод для разделительной строки
private static void printDelimiter(){
private static void printDelimiter() {
System.out.println();
System.out.println("-".repeat(30));
}
Expand All @@ -24,22 +24,21 @@ public static void main(String[] args) {
manager.createTask(task1);
manager.createTask(task2);

// Создание Эпика с двумя Подзадачами
Epic epic1 = new Epic("Эпик 1", "Эпик с 2 подзадачами");
// Создание Эпика с тремя подзадачами
Epic epic1 = new Epic("Эпик 1", "Эпик с 3 подзадачами");
manager.createEpic(epic1);

Subtask subtask1 = new Subtask("Подзадача 1", "Подзадача Эпика 1", Status.NEW, epic1.getId());
Subtask subtask2 = new Subtask("Подзадача 2", "Подзадача Эпика 1", Status.NEW, epic1.getId());
Subtask subtask3 = new Subtask("Подзадача 3", "Подзадача Эпика 1", Status.NEW, epic1.getId());
manager.createSubtask(subtask1);
manager.createSubtask(subtask2);
manager.createSubtask(subtask3);

// Создание Эпика с одной подзадачей
Epic epic2 = new Epic("Эпик 2", "Эпик с 1 подзадачей");
// Создание Эпика без подзадач
Epic epic2 = new Epic("Эпик 2", "Эпик без подзадач");
manager.createEpic(epic2);

Subtask subtask3 = new Subtask("Подзадача 1", "Подзадача Эпика 2", Status.NEW, epic2.getId());
manager.createSubtask(subtask3);

// Печать начального состояния списков Эпиков, Задач и Подзадач
System.out.println("Задачи: " + manager.getTasks());
System.out.println();
Expand All @@ -50,15 +49,6 @@ public static void main(String[] args) {
// Разделительная строка
printDelimiter();

// Изменение статуса Задачи 2
task2.setStatus(Status.IN_PROGRESS);
manager.updateTask(task2);
System.out.println("Задача 2: в процессе");
System.out.println("Статус задачи 2: " + manager.getTask(task2.getId()).getStatus());

// Разделительная строка
printDelimiter();

// Изменение статуса Подзадач в Эпике 1
subtask1.setStatus(Status.DONE);
subtask2.setStatus(Status.IN_PROGRESS);
Expand Down Expand Up @@ -88,39 +78,37 @@ public static void main(String[] args) {
// Разделительная строка
printDelimiter();

// Заполнение истории просмотра
System.out.println("Запрашиваем задачи, чтобы заполнить историю.");

// много запросов, чтобы превысить лимит 10
// Запрашивание задачи несколько раз в разном порядке
System.out.println("Запрашиваем задачи в разном порядке.");
manager.getTask(task1.getId());
manager.getTask(task2.getId());
manager.getEpic(epic1.getId());
manager.getSubtask(subtask1.getId());
manager.getTask(task2.getId());
manager.getSubtask(subtask2.getId());
manager.getEpic(epic2.getId());
manager.getSubtask(subtask3.getId());

// Повторные запросы (дубли)
manager.getTask(task1.getId());
manager.getEpic(epic1.getId());
// Повторные запросы = проверке, что дублей нет
manager.getTask(task1.getId()); // если task1 уже был = перемещение в конец
manager.getSubtask(subtask1.getId()); // если subtask1 уже был = перемещение в конец

// Еще запросы, чтобы вытеснить старые и проверить, выполняется ли лимит в 10 задач
manager.getTask(task2.getId());
manager.getSubtask(subtask1.getId());

// Проверка истории
System.out.println("Проверка истории (10 элементов):");
System.out.println("История (без повторов):");
printAllTasks(manager);

// Разделительная строка
printDelimiter();

// Удаление задачи и эпика
System.out.println("Удаляем задачу 1 и эпик 1");
// Удаление задачи из истории
System.out.println("Удаляем задачу 1");
manager.deleteTask(task1.getId());
manager.deleteEpic(epic1.getId());
System.out.println("История после удаления задачи 1:");
printAllTasks(manager);

System.out.println("Состояние после удаления:");
printDelimiter();

// Удаление эпика с тремя подзадачами
System.out.println("Удаляем эпик 1 (с тремя подзадачами)");
manager.deleteEpic(epic1.getId());
System.out.println("История после удаления эпика 1 и его подзадач:");
printAllTasks(manager);
}

Expand Down
2 changes: 1 addition & 1 deletion src/model/Epic.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public Epic(String name, String description) {
}

public ArrayList<Integer> getSubtaskIds() {
return new ArrayList<>(subtaskIds);;
return new ArrayList<>(subtaskIds);
}

public void setSubtaskIds(ArrayList<Integer> subtaskIds) {
Expand Down
4 changes: 3 additions & 1 deletion src/service/HistoryManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

public interface HistoryManager {
void add(Task task);


void remove(int id);

List<Task> getHistory();
}
112 changes: 104 additions & 8 deletions src/service/InMemoryHistoryManager.java
Original file line number Diff line number Diff line change
@@ -1,29 +1,125 @@
package service;

import model.Epic;
import model.Subtask;
import model.Task;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class InMemoryHistoryManager implements HistoryManager {
private static final int HISTORY_LIMIT = 10;

// Список для хранения истории просмотров задач
private final List<Task> history = new ArrayList<>();
// Голова и хвост двусвязного списка
private Node head;
private Node tail;

// В HashMap ключ = id задачи, значение = узел в списке
private final HashMap<Integer, Node> historyMap = new HashMap<>();

// Создание снимка задачи, чтобы история не зависела от внешних изменений
private Task makeSnapshot(Task task) {
if (task instanceof Subtask) {
Subtask original = (Subtask) task;
Subtask copy = new Subtask(
original.getName(),
original.getDescription(),
original.getStatus(),
original.getEpicId()
);
copy.setId(original.getId());
return copy;
} else if (task instanceof Epic) {
Epic original = (Epic) task;
Epic copy = new Epic(original.getName(), original.getDescription());
copy.setId(original.getId());
copy.setStatus(original.getStatus());
copy.setSubtaskIds(original.getSubtaskIds());
return copy;
} else {
Task copy = new Task(task.getName(), task.getDescription(), task.getStatus());
copy.setId(task.getId());
return copy;
}
}

// Добавление задачи в конец двусвязного списка
private void linkLast(Task task) {
Node newNode = new Node(makeSnapshot(task));
if (tail == null) {
// Если список пустой, то полностью новый узел - и голова, и хвост
head = newNode;
} else {
// Иначе подвешивание к хвосту
tail.setNext(newNode);
newNode.setPrev(tail);
}
tail = newNode;

// Сохранение узла в индексе
historyMap.put(task.getId(), newNode);
}

// Удаление конкретного узла из списка
private void removeNode(Node node) {
if (node == null) return;

Node prevNode = node.getPrev();
Node nextNode = node.getNext();

if (prevNode != null) {
prevNode.setNext(nextNode); // левый сосед смотрит на правого
} else {
head = nextNode; // удаление головы и новая голова - это следующий
}

if (nextNode != null) {
nextNode.setPrev(prevNode); // правый сосед теперь смотрит на левого
} else {
tail = prevNode; // удаление хвоста и новый хвост - это предыдущий
}

// Обнуление ссылок удалённого узла (помощь Garbage Collector)
node.setPrev(null);
node.setNext(null);
}

// Сбор задач всех из двусвязного списка в ArrayList
private List<Task> getTasks() {
List<Task> result = new ArrayList<>();
Node current = head;
while (current != null) {
result.add(current.getTask());
current = current.getNext();
}
return result;
}

// Добавление в историю
@Override
public void add(Task task) {
history.add(task);
// Ограничение в 10 элементов
if (history.size() > HISTORY_LIMIT) {
history.remove(0);
if (task == null) return;

// Если задача уже в истории = удаление старого просмотра
Node existingNode = historyMap.remove(task.getId());
if (existingNode != null) {
removeNode(existingNode);
}

// Добавление копии в конец списка
linkLast(task);
}

// Удаление задачи из истории по id
@Override
public void remove(int id) {
Node node = historyMap.remove(id);
removeNode(node);
}

// Возвращение списка истории
@Override
public List<Task> getHistory() {
return new ArrayList<>(history);
return getTasks();
}
}
Loading
Loading