Repository: zvv24/java-kanban
Pull request #6: Сделать финальное задачние 8
Author: login: zvv24
Created: 2025-05-03T14:23:55Z | Merged: 2025-05-19T10:25:38Z

Добрый день. сделал финальное задание №8


Diff:
diff --git a/.idea/misc.xml b/.idea/misc.xml
index fa5b436..5a454e3 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,5 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
+  <component name="EntryPointsManager">
+    <list size="1">
+      <item index="0" class="java.lang.String" itemvalue="org.junit.jupiter.api.Test" />
+    </list>
+  </component>
   <component name="ProjectRootManager" version="2" languageLevel="JDK_21" project-jdk-name="openjdk-21" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/out" />
   </component>
diff --git a/src/Main.java b/src/Main.java
index 46032af..48e77ef 100644
--- a/src/Main.java
+++ b/src/Main.java
@@ -1,3 +1,4 @@
+/*
 import managers.InMemoryTaskManager;
 import managers.TaskManager;
 import tasks.Epic;
@@ -55,4 +56,4 @@ public static void main(String[] args) {
         System.out.println(manager.getHistory());
         System.out.println("----------");
     }
-}
\ No newline at end of file
+}*/
\ No newline at end of file
diff --git a/src/managers/ConversionMethods.java b/src/managers/ConversionMethods.java
index 1eba907..8850ab9 100644
--- a/src/managers/ConversionMethods.java
+++ b/src/managers/ConversionMethods.java
@@ -2,50 +2,72 @@
 
 import tasks.*;
 
+import java.time.Duration;
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 
 public class ConversionMethods {
     public static String toString(Task task) {
         TaskType taskType = task.getType();
+        String startTime;
+        String duration;
+
+        if (task.getStartTime() != null) {
+            startTime = task.getStartTime().toString();
+        } else {
+            startTime = "null";
+        }
+
+        if (task.getDuration() != null) {
+            duration = String.valueOf(task.getDuration().toMinutes());
+        } else {
+            duration = "null";
+        }
         switch (taskType) {
             case SUBTASK -> {
-                return String.format("%d,%s,%s,%s,%s,%d",
+                return String.format("%d,%s,%s,%s,%s,%d,%s,%s",
                         task.getId(),
                         taskType,
                         task.getName(),
                         task.getStatus(),
                         task.getDescription(),
-                        ((Subtask) task).getEpic());
+                        ((Subtask) task).getEpic(),
+                        startTime,
+                        duration);
             }
             case EPIC, TASK -> {
-                return String.format("%d,%s,%s,%s,%s",
+                return String.format("%d,%s,%s,%s,%s,%s,%s",
                         task.getId(),
                         taskType,
                         task.getName(),
                         task.getStatus(),
-                        task.getDescription());
+                        task.getDescription(),
+                        startTime,
+                        duration);
             }
             default -> throw new IllegalArgumentException("Неверный тип задачи");
         }
     }
 
     public static Task fromString(String value) {
-        String[] buf = value.split(","); // id,type,name,status,description,epic
+        String[] buf = value.split(","); // id,type,name,status,description,epic,startTime,duration
         int id = Integer.parseInt(buf[0]);
         TaskType taskType = TaskType.valueOf(buf[1]);
         String name = buf[2];
         Status status = Status.valueOf(buf[3]);
         String description = buf[4];
+        LocalDateTime startTime = LocalDateTime.parse(buf[buf.length - 2]);
+        Duration duration = Duration.ofMinutes(Integer.parseInt(buf[buf.length - 1]));
 
         switch (taskType) {
             case SUBTASK -> {
-                return new Subtask(id, name, description, status, Integer.parseInt(buf[5]));
+                return new Subtask(id, name, description, status, Integer.parseInt(buf[5]), startTime, duration);
             }
             case EPIC -> {
                 return new Epic(id, name, description, status, new ArrayList<>());
             }
             case TASK -> {
-                return new Task(id, name, description, status);
+                return new Task(id, name, description, status, startTime, duration);
             }
             default -> throw new IllegalArgumentException("Неверный тип задачи");
         }
diff --git a/src/managers/FileBackedTaskManager.java b/src/managers/FileBackedTaskManager.java
index c5c2834..c0d39a1 100644
--- a/src/managers/FileBackedTaskManager.java
+++ b/src/managers/FileBackedTaskManager.java
@@ -103,7 +103,7 @@ public Subtask deleteSubtaskByID(int id) {
 
     public void save() {
         try (BufferedWriter writer = new BufferedWriter(new FileWriter(file, StandardCharsets.UTF_8))) {
-            writer.write("id,type,name,status,description,epic\n");
+            writer.write("id,type,name,status,description,epic,startTime,duration\n");
             for (Task task : getAllTasks()) {
                 writer.write(ConversionMethods.toString(task));
                 writer.newLine();
diff --git a/src/managers/InMemoryTaskManager.java b/src/managers/InMemoryTaskManager.java
index 22a0502..125ce00 100644
--- a/src/managers/InMemoryTaskManager.java
+++ b/src/managers/InMemoryTaskManager.java
@@ -5,9 +5,10 @@
 import tasks.Subtask;
 import tasks.Task;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
 
 public class InMemoryTaskManager implements TaskManager {
     private int id = 1;
@@ -23,6 +24,9 @@ private int newId() {
     //Создание нового объекта
     @Override
     public Task newTask(Task task) {
+        if (taskOverlap(task)) {
+            throw new IllegalArgumentException("Задачи пересекаются");
+        }
         return tasks.put(newId(), task);
     }
 
@@ -35,6 +39,9 @@ public Epic newEpic(Epic epic) {
 
     @Override
     public Subtask newSubtasks(Subtask subtask) {
+        if (taskOverlap(subtask)) {
+            throw new IllegalArgumentException("Задачи пересекаются");
+        }
         int idSubtask = subtask.getId();
         int idEpic = subtask.getEpic();
         epics.get(idEpic).setSubtask(idSubtask);
@@ -62,34 +69,32 @@ public List<Subtask> printAllSubtasks() {
     //удаление всех объектов
     @Override
     public void deleteAllTasks() {
-        for (Task task : printAllTasks()) {
-            historyManager.removeHistory(task.getId());
-        }
+        printAllTasks().stream()
+                .map(Task::getId)
+                .forEach(historyManager::removeHistory);
         tasks.clear();
     }
 
     @Override
     public void deleteAllEpics() {
-        for (Epic epic : printAllEpics()) {
-            for (int subtask : epic.getSubtask()) {
-                historyManager.removeHistory(subtask);
-            }
+        printAllEpics().forEach(epic -> {
+            epic.getSubtask().forEach(historyManager::removeHistory);
             historyManager.removeHistory(epic.getId());
-        }
+        });
         subtasks.clear();
         epics.clear();
     }
 
     @Override
     public void deleteAllSubtasks() {
-        for (Subtask subtask : printAllSubtasks()) {
-            historyManager.removeHistory(subtask.getId());
-        }
+        printAllSubtasks().stream()
+                .map(Subtask::getId)
+                .forEach(historyManager::removeHistory);
         subtasks.clear();
-        for (int idEpic : epics.keySet()) {
+        epics.keySet().forEach(idEpic -> {
             epics.get(idEpic).getSubtask().clear();
             checkStatus(idEpic);
-        }
+        });
     }
 
     //Поиск по ID.
@@ -117,6 +122,9 @@ public Subtask searchSubtaskByID(int id) {
     //Обновление.
     @Override
     public Task updateTask(Task task) {
+        if (taskOverlap(task)) {
+            throw new IllegalArgumentException("Задачи пересекаются");
+        }
         return tasks.replace(task.getId(), task);
     }
 
@@ -129,6 +137,9 @@ public Epic updateEpic(Epic epic) {
 
     @Override
     public Subtask updateSubtask(Subtask subtask) {
+        if (taskOverlap(subtask)) {
+            throw new IllegalArgumentException("Задачи пересекаются");
+        }
         subtasks.replace(subtask.getId(), subtask);
         checkStatus(subtask.getEpic());
         return subtask;
@@ -164,6 +175,7 @@ public Subtask deleteSubtaskByID(int id) {
     //Проверка статуса для эпиков
     private void checkStatus(int id) {
         Epic epic = epics.get(id);
+        calculateTimeEpic(epic);
         if (epic.getSubtask().isEmpty()) {
             epic.setStatus(Status.NEW);
         } else {
@@ -188,19 +200,65 @@ private void checkStatus(int id) {
         }
     }
 
+    private void calculateTimeEpic(Epic epic) {
+        if (epic.getSubtask().isEmpty()) {
+            epic.setStartTime(null);
+            epic.setDuration(null);
+            epic.setEndTime(null);
+            return;
+        }
+
+        LocalDateTime start = null;
+        LocalDateTime end = null;
+        Duration duration = Duration.ZERO;
+
+        for (int subtaskId : epic.getSubtask()) {
+            Subtask subtask = subtasks.get(subtaskId);
+            if (subtask == null || subtask.getStartTime() == null) continue;
+
+            LocalDateTime startSubtask = subtask.getStartTime();
+            LocalDateTime endSubtask = subtask.getEndTime();
+            Duration durationSubtask = subtask.getDuration();
+
+            if (start == null || startSubtask.isBefore(start)) {
+                start = startSubtask;
+            }
+            if (end == null || endSubtask.isAfter(end)) {
+                end = endSubtask;
+            }
+            duration = duration.plus(durationSubtask);
+        }
+
+        epic.setStartTime(start);
+        epic.setDuration(duration);
+        epic.setEndTime(end);
+    }
+
     //Получение списка всех подзадач определённого эпика.
     @Override
     public ArrayList<Subtask> printSubtasksСertainEpic(int id) {
-        ArrayList<Integer> listSubtaks = epics.get(id).getSubtask();
-        ArrayList<Subtask> subtasks1 = new ArrayList<>();
-        for (int idSubtask : listSubtaks) {
-            subtasks1.add(subtasks.get(idSubtask));
-        }
-        return subtasks1;
+        return epics.get(id).getSubtask().stream()
+                .map(subtasks::get)
+                .collect(Collectors.toCollection(ArrayList::new));
     }
 
     @Override
     public List<Task> getHistory() {
         return historyManager.getHistory();
     }
+
+    @Override
+    public TreeSet<Task> getPrioritizedTasks() {
+        TreeSet<Task> prioritizedTasks = new TreeSet<>(Comparator.comparing(Task::getStartTime,
+                Comparator.nullsLast(Comparator.naturalOrder())));
+        prioritizedTasks.addAll(tasks.values());
+        prioritizedTasks.addAll(subtasks.values());
+        return prioritizedTasks;
+    }
+
+    private boolean taskOverlap(Task task) {
+        return getPrioritizedTasks().stream()
+                .filter(t -> t.getStartTime() != null)
+                .anyMatch(t -> !t.equals(task) && t.isOverlap(task));
+    }
 }
\ No newline at end of file
diff --git a/src/managers/TaskManager.java b/src/managers/TaskManager.java
index c3dad74..b89f16d 100644
--- a/src/managers/TaskManager.java
+++ b/src/managers/TaskManager.java
@@ -6,6 +6,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.TreeSet;
 
 public interface TaskManager {
     //Создание нового объекта
@@ -54,4 +55,6 @@ public interface TaskManager {
     ArrayList<Subtask> printSubtasksСertainEpic(int id);
 
     List<Task> getHistory();
+
+    TreeSet<Task> getPrioritizedTasks();
 }
diff --git a/src/tasks/Epic.java b/src/tasks/Epic.java
index 9f18f5a..7f04f9e 100644
--- a/src/tasks/Epic.java
+++ b/src/tasks/Epic.java
@@ -1,29 +1,33 @@
 package tasks;
 
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Objects;
 
 public class Epic extends Task {
     private ArrayList<Integer> subtask = new ArrayList<>();
+    private LocalDateTime endTime;
 
     public Epic(int id, String name, String description, Status status, ArrayList<Integer> subtask) {
-        super(id, name, description, status);
+        super(id, name, description, status, null, null);
         this.subtask = subtask;
     }
 
+    public ArrayList<Integer> getSubtask() {
+        return subtask;
+    }
+
+    public void setSubtask(int subtask) {
+        this.subtask.add(subtask);
+    }
+
     @Override
-    public String toString() {
-        return "{" +
-                "id='" + getId() + '\'' +
-                ", name='" + getName() + '\'' +
-                ", description='" + getDescription() + '\'' +
-                ", status=" + getStatus() +
-                ", subTask=" + subtask +
-                '}';
+    public LocalDateTime getEndTime() {
+        return endTime;
     }
 
-    public ArrayList<Integer> getSubtask() {
-        return subtask;
+    public void setEndTime(LocalDateTime endTime) {
+        this.endTime = endTime;
     }
 
     @Override
@@ -31,8 +35,15 @@ public TaskType getType() {
         return TaskType.EPIC;
     }
 
-    public void setSubtask(int subtask) {
-        this.subtask.add(subtask);
+    @Override
+    public String toString() {
+        return "{" +
+                "id='" + getId() + '\'' +
+                ", name='" + getName() + '\'' +
+                ", description='" + getDescription() + '\'' +
+                ", status=" + getStatus() +
+                ", subTask=" + subtask +
+                '}';
     }
 
     @Override
diff --git a/src/tasks/Subtask.java b/src/tasks/Subtask.java
index ea73748..98e181b 100644
--- a/src/tasks/Subtask.java
+++ b/src/tasks/Subtask.java
@@ -1,37 +1,39 @@
 package tasks;
 
+import java.time.Duration;
+import java.time.LocalDateTime;
 import java.util.Objects;
 
 public class Subtask extends Task {
     private int epic;
 
-    public Subtask(int id, String name, String description, Status status, int epic) {
-        super(id, name, description, status);
+    public Subtask(int id, String name, String description, Status status, int epic, LocalDateTime startTime, Duration duration) {
+        super(id, name, description, status, startTime, duration);
         this.epic = epic;
     }
 
-    @Override
-    public String toString() {
-        return "{" +
-                "id='" + getId() + '\'' +
-                ", name='" + getName() + '\'' +
-                ", description='" + getDescription() + '\'' +
-                ", status=" + getStatus() +
-                ", epic=" + epic +
-                '}';
-    }
-
     public int getEpic() {
         return epic;
     }
 
+    public void setEpic(int epic) {
+        this.epic = epic;
+    }
+
     @Override
     public TaskType getType() {
         return TaskType.SUBTASK;
     }
 
-    public void setEpic(int epic) {
-        this.epic = epic;
+    @Override
+    public String toString() {
+        return "{" +
+                "id='" + getId() + '\'' +
+                ", name='" + getName() + '\'' +
+                ", description='" + getDescription() + '\'' +
+                ", status=" + getStatus() +
+                ", epic=" + epic +
+                '}';
     }
 
     @Override
diff --git a/src/tasks/Task.java b/src/tasks/Task.java
index 8950e33..4c0ebf4 100644
--- a/src/tasks/Task.java
+++ b/src/tasks/Task.java
@@ -1,5 +1,7 @@
 package tasks;
 
+import java.time.Duration;
+import java.time.LocalDateTime;
 import java.util.Objects;
 
 public class Task {
@@ -7,22 +9,16 @@ public class Task {
     private String name;
     private String description;
     private Status status;
+    private LocalDateTime startTime;
+    private Duration duration;
 
-    public Task(int id, String name, String description, Status status) {
+    public Task(int id, String name, String description, Status status, LocalDateTime startTime, Duration duration) {
         this.id = id;
         this.name = name;
         this.description = description;
         this.status = status;
-    }
-
-    @Override
-    public String toString() {
-        return "{" +
-                "id='" + id + '\'' +
-                ", name='" + name + '\'' +
-                ", description='" + description + '\'' +
-                ", status=" + status +
-                '}';
+        this.startTime = startTime;
+        this.duration = duration;
     }
 
     public int getId() {
@@ -45,6 +41,18 @@ public TaskType getType() {
         return TaskType.TASK;
     }
 
+    public Duration getDuration() {
+        return duration;
+    }
+
+    public LocalDateTime getStartTime() {
+        return startTime;
+    }
+
+    public LocalDateTime getEndTime() {
+        return startTime.plus(duration);
+    }
+
     public void setId(int id) {
         this.id = id;
     }
@@ -61,6 +69,32 @@ public void setName(String name) {
         this.name = name;
     }
 
+    public void setDuration(Duration duration) {
+        this.duration = duration;
+    }
+
+    public void setStartTime(LocalDateTime startTime) {
+        this.startTime = startTime;
+    }
+
+    public boolean isOverlap(Task task) {
+        if (this.startTime == null || task.startTime == null) {
+            return false;
+        }
+        return !(this.getEndTime().isBefore(task.startTime) ||
+                task.getEndTime().isBefore(this.startTime));
+    }
+
+    @Override
+    public String toString() {
+        return "{" +
+                "id='" + id + '\'' +
+                ", name='" + name + '\'' +
+                ", description='" + description + '\'' +
+                ", status=" + status +
+                '}';
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
diff --git a/test/managers/FileBackedTaskManagerTest.java b/test/managers/FileBackedTaskManagerTest.java
index a09cae2..2a1b9ba 100644
--- a/test/managers/FileBackedTaskManagerTest.java
+++ b/test/managers/FileBackedTaskManagerTest.java
@@ -2,48 +2,49 @@
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import tasks.Epic;
-import tasks.Status;
-import tasks.Subtask;
-import tasks.Task;
 
 import java.io.File;
 import java.io.IOException;
-import java.util.ArrayList;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-class FileBackedTaskManagerTest {
-    File file;
-    FileBackedTaskManager manager;
+class FileBackedTaskManagerTest extends TaskManagerTest<FileBackedTaskManager> {
+    private File file;
 
     @BeforeEach
-    public void beforeEach() throws IOException {
-        file = File.createTempFile("file", ".csv");
+    public void setUp() throws IOException {
+        file = File.createTempFile("tasks", ".csv");
         file.deleteOnExit();
-        manager = new FileBackedTaskManager(file);
+        super.setUp();
+    }
+
+    @Override
+    public FileBackedTaskManager createManager() {
+        return new FileBackedTaskManager(file);
     }
 
     @Test
-    public void savingAndUploadingEmptyFile() {
-        manager.save();
-        FileBackedTaskManager fileBackedTaskManager = FileBackedTaskManager.loadFromFile(file);
+    public void savingAndUploadingEmptyFile() throws IOException {
+        File emptyFile = File.createTempFile("empty", ".csv");
+        emptyFile.deleteOnExit();
+        FileBackedTaskManager emptyManager = new FileBackedTaskManager(emptyFile);
 
-        assertTrue(fileBackedTaskManager.printAllTasks().isEmpty());
-        assertTrue(fileBackedTaskManager.printAllEpics().isEmpty());
-        assertTrue(fileBackedTaskManager.printAllSubtasks().isEmpty());
+        emptyManager.deleteAllTasks();
+        emptyManager.deleteAllEpics();
+        emptyManager.deleteAllSubtasks();
+        emptyManager.save();
+
+        FileBackedTaskManager loadedManager = FileBackedTaskManager.loadFromFile(emptyFile);
+
+        assertTrue(loadedManager.printAllTasks().isEmpty(), "Список задач должен быть пустым");
+        assertTrue(loadedManager.printAllEpics().isEmpty(), "Список эпиков должен быть пустым");
+        assertTrue(loadedManager.printAllSubtasks().isEmpty(), "Список подзадач должен быть пустым");
     }
 
     @Test
-    public void savingAndUploadingSomeTasks() throws IOException {
-        Task task = new Task(1, "Задача 1", "Описание задачи 1", Status.NEW);
-        Epic epic = new Epic(2, "Эпик 1", "Описание эпика 1", Status.NEW, new ArrayList<>());
-        Subtask subtask = new Subtask(3, "Подзадача 1", "Описание подзадачи 1", Status.NEW, 2);
-
-        manager.newTask(task);
-        manager.newEpic(epic);
-        manager.newSubtasks(subtask);
+    public void savingAndUploadingSomeTasks() {
+        manager.save();
         FileBackedTaskManager fileBackedTaskManager = FileBackedTaskManager.loadFromFile(file);
 
         assertEquals(manager.printAllTasks(), fileBackedTaskManager.printAllTasks());
diff --git a/test/managers/InMemoryHistoryManagerTest.java b/test/managers/InMemoryHistoryManagerTest.java
index 3144ec8..c23364d 100644
--- a/test/managers/InMemoryHistoryManagerTest.java
+++ b/test/managers/InMemoryHistoryManagerTest.java
@@ -6,6 +6,8 @@
 import tasks.Subtask;
 import tasks.Task;
 
+import java.time.Duration;
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -16,11 +18,13 @@ class InMemoryHistoryManagerTest {
 
     @Test
     public void historyManagerAddDifferentTypesOfTasks() {
-        Task task1 = new Task(1, "Задача 1", "Описание задачи 1", Status.NEW);
+        Task task1 = new Task(1, "Задача 1", "Описание задачи 1", Status.NEW,
+                LocalDateTime.now(), Duration.ofMinutes(30));
         manager.addHistory(task1);
         Epic epic1 = new Epic(2, "Эпик 1", "Описание эпика 1", Status.NEW, new ArrayList<>());
         manager.addHistory(epic1);
-        Subtask subtask1 = new Subtask(3, "Подзадача 1", "Описание подзадачи 1", Status.NEW, 2);
+        Subtask subtask1 = new Subtask(3, "Подзадача 1", "Описание подзадачи 1", Status.NEW, 2,
+                LocalDateTime.now().plusHours(1), Duration.ofMinutes(15));
         manager.addHistory(subtask1);
 
 
@@ -30,20 +34,12 @@ public void historyManagerAddDifferentTypesOfTasks() {
         assertEquals(subtask1, history.get(2));
     }
 
-    @Test
-    public void historyManagerNotSaveRepeats() {
-        manager.addHistory(new Task(1, "Задача 1", "Описание задачи 1", Status.NEW));
-        manager.addHistory(new Task(1, "Задача 1", "Описание задачи 1", Status.NEW));
-        manager.addHistory(new Task(1, "Задача 1", "Описание задачи 1", Status.NEW));
-
-
-        assertEquals(1, manager.getHistory().size());
-    }
 
     @Test
     public void historyIsNotLimitedInSize() {
         for (int i = 1; i <= 15; i++) {
-            manager.addHistory(new Task(i, "name", "des", Status.NEW));
+            manager.addHistory(new Task(i, "name", "des", Status.NEW,
+                    LocalDateTime.now().plusHours(i), Duration.ofMinutes(i)));
         }
 
         assertEquals(15, manager.getHistory().size());
@@ -52,10 +48,12 @@ public void historyIsNotLimitedInSize() {
 
     @Test
     public void deletingTaskFromHeadHistory() {
-        manager.addHistory(new Task(1, "Задача 1", "Описание задачи 1", Status.NEW));
+        manager.addHistory(new Task(1, "Задача 1", "Описание задачи 1", Status.NEW,
+                LocalDateTime.now(), Duration.ofMinutes(30)));
         Epic epic1 = new Epic(2, "Эпик 1", "Описание эпика 1", Status.NEW, new ArrayList<>());
         manager.addHistory(epic1);
-        Subtask subtask1 = new Subtask(3, "Подзадача 1", "Описание подзадачи 1", Status.NEW, 2);
+        Subtask subtask1 = new Subtask(3, "Подзадача 1", "Описание подзадачи 1", Status.NEW, 2,
+                LocalDateTime.now().plusHours(1), Duration.ofMinutes(15));
         manager.addHistory(subtask1);
 
         manager.removeHistory(1);
@@ -65,11 +63,13 @@ public void deletingTaskFromHeadHistory() {
 
     @Test
     public void deletingTaskFromMiddleHistory() {
-        Task task1 = new Task(1, "Задача 1", "Описание задачи 1", Status.NEW);
+        Task task1 = new Task(1, "Задача 1", "Описание задачи 1", Status.NEW,
+                LocalDateTime.now(), Duration.ofMinutes(30));
         manager.addHistory(task1);
         Epic epic1 = new Epic(2, "Эпик 1", "Описание эпика 1", Status.NEW, new ArrayList<>());
         manager.addHistory(epic1);
-        Task task2 = new Task(3, "Задача 2", "Описание задачи 2", Status.NEW);
+        Task task2 = new Task(3, "Задача 2", "Описание задачи 2", Status.NEW,
+                LocalDateTime.now().plusHours(1), Duration.ofMinutes(15));
         manager.addHistory(task2);
 
         manager.removeHistory(2);
@@ -80,11 +80,13 @@ public void deletingTaskFromMiddleHistory() {
 
     @Test
     public void deletingTaskFromTailHistory() {
-        Task task1 = new Task(1, "Задача 1", "Описание задачи 1", Status.NEW);
+        Task task1 = new Task(1, "Задача 1", "Описание задачи 1", Status.NEW,
+                LocalDateTime.now(), Duration.ofMinutes(30));
         manager.addHistory(task1);
         Epic epic1 = new Epic(2, "Эпик 1", "Описание эпика 1", Status.NEW, new ArrayList<>());
         manager.addHistory(epic1);
-        Task task2 = new Task(3, "Задача 2", "Описание задачи 2", Status.NEW);
+        Task task2 = new Task(3, "Задача 2", "Описание задачи 2", Status.NEW,
+                LocalDateTime.now().plusHours(1), Duration.ofMinutes(15));
         manager.addHistory(task2);
 
         manager.removeHistory(3);
diff --git a/test/managers/InMemoryTaskManagerTest.java b/test/managers/InMemoryTaskManagerTest.java
index c44e160..5460d29 100644
--- a/test/managers/InMemoryTaskManagerTest.java
+++ b/test/managers/InMemoryTaskManagerTest.java
@@ -1,50 +1,20 @@
 package managers;
 
-import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import tasks.Epic;
 import tasks.Status;
 import tasks.Subtask;
-import tasks.Task;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.time.Duration;
+import java.time.LocalDateTime;
 
-import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-class InMemoryTaskManagerTest {
+class InMemoryTaskManagerTest extends managers.TaskManagerTest<InMemoryTaskManager> {
 
-    InMemoryTaskManager manager;
-    Task task = new Task(1, "Задача", "Описание задачи", Status.NEW);
-    Epic epic = new Epic(2, "Эпик", "Описание эпика", Status.DONE, new ArrayList<>());
-    Subtask subtask1 = new Subtask(3, "Подзадача", "Описание подзадачи", Status.NEW, 2);
-    Subtask subtask2 = (new Subtask(4, "Подзадача 2", "Подзадача эпика 1", Status.IN_PROGRESS, 2));
-
-
-    @BeforeEach
-    void beforeEach() {
-        manager = new InMemoryTaskManager();
-        manager.newTask(task);
-        manager.newEpic(epic);
-        manager.newSubtasks(subtask1);
-        manager.newSubtasks(subtask2);
-    }
-
-    @Test
-    public void inMemoryTaskManagerCanAddAndSearchForDifferentTasks() {
-        assertEquals(task, manager.searchTaskByID(1), "Задача не найдена");
-        assertEquals(epic, manager.searchEpicByID(2), "Эпик не найдена");
-        assertEquals(subtask1, manager.searchSubtaskByID(3), "Подзадача не найдена");
-    }
-
-    @Test
-    public void taskDoesNotChangeWhenAddedToManager() {
-        Task addedTask = manager.searchTaskByID(1);
-
-        assertEquals(task.getId(), addedTask.getId(), "id не должно изменяться при добавлении в менеджер");
-        assertEquals(task.getName(), addedTask.getName(), "имя не должно изменяться при добавлении в менеджер");
-        assertEquals(task.getDescription(), addedTask.getDescription(), "описание не должно изменяться при добавлении в менеджер");
-        assertEquals(task.getStatus(), addedTask.getStatus(), "статус не должен изменяться при добавлении в менеджер");
+    @Override
+    public InMemoryTaskManager createManager() {
+        return new InMemoryTaskManager();
     }
 
     @Test
@@ -60,73 +30,64 @@ public void deletingAllEpicsDeletedAllSubtasks() {
     }
 
     @Test
-    public void printSubtasksOfCertainEpic() {
-        ArrayList<Subtask> subtasks = manager.printSubtasksСertainEpic(2);
-        assertEquals(manager.printAllSubtasks(), subtasks);
-    }
+    public void deletesSubtaskFromHistoryManagerIfEpicIsDeleted() {
+        manager.searchTaskByID(1);
+        manager.searchEpicByID(2);
+        manager.searchSubtaskByID(3);
+        manager.searchSubtaskByID(4);
+
+        assertEquals(4, manager.getHistory().size());
 
-    @Test
-    public void inMemoryTaskManagerCanDeleteTasksById() {
-        manager.deleteTaskByID(1);
-        manager.deleteSubtaskByID(3);
         manager.deleteEpicByID(2);
 
-        assertNull(manager.searchTaskByID(1));
-        assertNull(manager.searchEpicByID(2));
-        assertNull(manager.searchSubtaskByID(3));
+        assertEquals(1, manager.getHistory().size());
     }
 
     @Test
-    public void inMemoryTaskManagerCanUpdateTasks() {
-        task.setName("1");
-        epic.setDescription("2");
-        subtask1.setStatus(Status.IN_PROGRESS);
-
-        manager.updateTask(task);
-        manager.updateEpic(epic);
+    void calculatingEpicStatusShenAllSubtasksNew() {
+        Subtask subtask1 = new Subtask(3, "Подзадача 1", "Описание подзадачи 1", Status.NEW, 2,
+                LocalDateTime.now().plusHours(3), Duration.ofMinutes(15));
+        Subtask subtask2 = new Subtask(4, "Подзадача 2", "Описание подзадачи 2", Status.NEW, 2,
+                LocalDateTime.now().plusHours(4), Duration.ofMinutes(20));
         manager.updateSubtask(subtask1);
+        manager.updateSubtask(subtask2);
 
-        assertEquals(task.getName(), manager.searchTaskByID(1).getName());
-        assertEquals(epic.getDescription(), manager.searchEpicByID(2).getDescription());
-        assertEquals(subtask1.getStatus(), manager.searchSubtaskByID(3).getStatus());
+        assertEquals(Status.NEW, epic.getStatus());
     }
 
     @Test
-    public void inMemoryTaskManagerCanPrintTasks() {
-        assertTrue(manager.printAllTasks().contains(task));
-        assertTrue(manager.printAllEpics().contains(epic));
-        assertTrue(manager.printAllSubtasks().contains(subtask1));
-        assertTrue(manager.printAllSubtasks().contains(subtask2));
-    }
+    void calculatingEpicStatusWhenAllSubtasksDone() {
+        Subtask subtask1 = new Subtask(3, "Подзадача 1", "Описание подзадачи 1", Status.DONE, 2,
+                LocalDateTime.now().plusHours(3), Duration.ofMinutes(15));
+        Subtask subtask2 = new Subtask(4, "Подзадача 2", "Описание подзадачи 2", Status.DONE, 2,
+                LocalDateTime.now().plusHours(4), Duration.ofMinutes(20));
+        manager.updateSubtask(subtask1);
+        manager.updateSubtask(subtask2);
 
-    @Test
-    public void searchMethodsAddedToHistory() {
-        List<Task> tasks = new ArrayList<>();
-        tasks.add(manager.searchSubtaskByID(3));
-        tasks.add(manager.searchTaskByID(1));
-        tasks.add(manager.searchEpicByID(2));
-        tasks.add(manager.searchSubtaskByID(4));
-
-        assertEquals(tasks, manager.getHistory());
-        assertEquals(epic, manager.getHistory().get(2));
+        assertEquals(Status.DONE, epic.getStatus());
     }
 
     @Test
-    public void deletesSubtaskFromHistoryManagerIfEpicIsDeleted() {
-        manager.newTask(new Task(1, "Задача 1", "Описание задачи 1", Status.NEW));
-        manager.newEpic(new Epic(2, "Эпик 1", "Описание эпика 1", Status.NEW, new ArrayList<>()));
-        manager.newSubtasks(new Subtask(3, "Подзадача 1", "Описание подзадачи 1", Status.NEW, 2));
-        manager.newSubtasks(new Subtask(4, "Подзадача 1", "Описание подзадачи 1", Status.NEW, 2));
-
-        manager.searchTaskByID(1);
-        manager.searchEpicByID(2);
-        manager.searchSubtaskByID(3);
-        manager.searchSubtaskByID(4);
+    void calculatingEpicStatusWhenSubtasksNewAndDone() {
+        Subtask subtask1 = new Subtask(3, "Подзадача 1", "Описание подзадачи 1", Status.NEW, 2,
+                LocalDateTime.now().plusHours(3), Duration.ofMinutes(15));
+        Subtask subtask2 = new Subtask(4, "Подзадача 2", "Описание подзадачи 2", Status.DONE, 2,
+                LocalDateTime.now().plusHours(4), Duration.ofMinutes(20));
+        manager.updateSubtask(subtask1);
+        manager.updateSubtask(subtask2);
 
-        assertEquals(4, manager.getHistory().size());
+        assertEquals(Status.IN_PROGRESS, epic.getStatus());
+    }
 
-        manager.deleteEpicByID(2);
+    @Test
+    void calculatingEpicStatusWhenAllSubtasksInProgress() {
+        Subtask subtask1 = new Subtask(3, "Подзадача 1", "Описание подзадачи 1", Status.IN_PROGRESS, 2,
+                LocalDateTime.now().plusHours(3), Duration.ofMinutes(15));
+        Subtask subtask2 = new Subtask(4, "Подзадача 2", "Описание подзадачи 2", Status.IN_PROGRESS, 2,
+                LocalDateTime.now().plusHours(4), Duration.ofMinutes(20));
+        manager.updateSubtask(subtask1);
+        manager.updateSubtask(subtask2);
 
-        assertEquals(1, manager.getHistory().size());
+        assertEquals(Status.IN_PROGRESS, epic.getStatus());
     }
 }
\ No newline at end of file
diff --git a/test/managers/TaskManagerTest.java b/test/managers/TaskManagerTest.java
new file mode 100644
index 0000000..e8a7460
--- /dev/null
+++ b/test/managers/TaskManagerTest.java
@@ -0,0 +1,148 @@
+package managers;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import tasks.Epic;
+import tasks.Status;
+import tasks.Subtask;
+import tasks.Task;
+
+import java.io.IOException;
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public abstract class TaskManagerTest<T extends TaskManager> {
+    public T manager;
+    public Task task;
+    public Epic epic;
+    public Subtask subtask1;
+    public Subtask subtask2;
+
+    public abstract T createManager();
+
+    @BeforeEach
+    public void setUp() throws IOException {
+        manager = createManager();
+        task = new Task(1, "Задача 1", "Описание задачи 1", Status.NEW,
+                LocalDateTime.now(), Duration.ofMinutes(30));
+        epic = new Epic(2, "Эпик 1", "Описание эпика 1", Status.NEW, new ArrayList<>());
+        subtask1 = new Subtask(3, "Подзадача 1", "Описание подзадачи 1", Status.NEW, 2,
+                LocalDateTime.now().plusHours(1), Duration.ofMinutes(15));
+        subtask2 = new Subtask(4, "Подзадача 2", "Описание подзадачи 2", Status.IN_PROGRESS, 2,
+                LocalDateTime.now().plusHours(2), Duration.ofMinutes(20));
+
+        manager.newTask(task);
+        manager.newEpic(epic);
+        manager.newSubtasks(subtask1);
+        manager.newSubtasks(subtask2);
+    }
+
+    @Test
+    public void addAndSearchForDifferentTasks() {
+        assertEquals(task, manager.searchTaskByID(1), "Задача не найдена");
+        assertEquals(epic, manager.searchEpicByID(2), "Эпик не найдена");
+        assertEquals(subtask1, manager.searchSubtaskByID(3), "Подзадача не найдена");
+    }
+
+    @Test
+    public void taskDoesNotChangeWhenAddedToManager() {
+        Task addedTask = manager.searchTaskByID(1);
+
+        assertEquals(task.getId(), addedTask.getId(), "id не должно изменяться при добавлении в менеджер");
+        assertEquals(task.getName(), addedTask.getName(), "имя не должно изменяться при добавлении в менеджер");
+        assertEquals(task.getDescription(), addedTask.getDescription(), "описание не должно изменяться при добавлении в менеджер");
+        assertEquals(task.getStatus(), addedTask.getStatus(), "статус не должен изменяться при добавлении в менеджер");
+    }
+
+    @Test
+    void canDeleteAllTasks() {
+        manager.deleteAllTasks();
+        manager.deleteAllEpics();
+        manager.deleteAllSubtasks();
+
+        assertNull(manager.searchTaskByID(1));
+        assertNull(manager.searchEpicByID(2));
+        assertNull(manager.searchSubtaskByID(3));
+        assertNull(manager.searchSubtaskByID(4));
+    }
+
+    @Test
+    public void canDeleteTasksById() {
+        manager.deleteTaskByID(1);
+        manager.deleteSubtaskByID(3);
+        manager.deleteEpicByID(2);
+
+        assertNull(manager.searchTaskByID(1));
+        assertNull(manager.searchEpicByID(2));
+        assertNull(manager.searchSubtaskByID(3));
+    }
+
+    @Test
+    public void canUpdateTasks() {
+        Task newTask = new Task(1, "Обновленная задача", "Новое описание", Status.DONE,
+                LocalDateTime.now().plusHours(3), Duration.ofMinutes(45));
+        Epic newEpic = new Epic(2, "Обновленный эпик", "Новое описание", Status.DONE, new ArrayList<>());
+        Subtask newSubtask = new Subtask(3, "Обновленная подзадача", "Новое описание", Status.DONE, 2,
+                LocalDateTime.now().plusHours(4), Duration.ofMinutes(10));
+
+        manager.updateTask(newTask);
+        manager.updateEpic(newEpic);
+        manager.updateSubtask(newSubtask);
+        assertEquals(newTask, manager.searchTaskByID(1), "Задача не обновлена");
+        assertEquals(newEpic, manager.searchEpicByID(2), "Эпик не обновлен");
+        assertEquals(newSubtask, manager.searchSubtaskByID(3), "Подзадача не обновлена");
+    }
+
+    @Test
+    public void searchMethodsAddedToHistory() {
+        List<Task> tasks = new ArrayList<>();
+        tasks.add(manager.searchSubtaskByID(3));
+        tasks.add(manager.searchTaskByID(1));
+        tasks.add(manager.searchEpicByID(2));
+        tasks.add(manager.searchSubtaskByID(4));
+
+        assertEquals(tasks, manager.getHistory());
+        assertEquals(epic, manager.getHistory().get(2));
+    }
+
+    @Test
+    public void printSubtasksOfCertainEpic() {
+        ArrayList<Subtask> subtasks = manager.printSubtasksСertainEpic(2);
+        assertEquals(manager.printAllSubtasks(), subtasks);
+    }
+
+    @Test
+    void prioritiesSetCorrectly() {
+        Task task1 = new Task(5, "Ранняя задача", "Описание", Status.NEW,
+                LocalDateTime.now().minusHours(1), Duration.ofMinutes(30));
+        manager.newTask(task1);
+
+        assertEquals(task1, manager.getPrioritizedTasks().first());
+    }
+
+    @Test
+    public void notSaveRepeats() {
+        manager.searchTaskByID(1);
+        manager.searchTaskByID(1);
+        manager.searchTaskByID(1);
+
+        assertEquals(1, manager.getHistory().size());
+    }
+
+    @Test
+    public void checkTaskOverlap() {
+        Task task1 = new Task(5, "Пересекающаяся задача", "Описание", Status.NEW,
+                task.getStartTime().plusMinutes(10), Duration.ofMinutes(20));
+        IllegalArgumentException exception = assertThrows(
+                IllegalArgumentException.class,
+                () -> manager.newTask(task1),
+                "Ожидалось исключение при добавлении пересекающейся задачи"
+        );
+
+        assertEquals("Задачи пересекаются", exception.getMessage());
+    }
+}
\ No newline at end of file
diff --git a/test/tasks/SubtaskTest.java b/test/tasks/SubtaskTest.java
index 7d2f166..3680cfe 100644
--- a/test/tasks/SubtaskTest.java
+++ b/test/tasks/SubtaskTest.java
@@ -2,14 +2,19 @@
 
 import org.junit.jupiter.api.Test;
 
+import java.time.Duration;
+import java.time.LocalDateTime;
+
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 class SubtaskTest {
 
     @Test
     public void subtestsAreEqualIfTheIDsAreEqual() {
-        Subtask subtask1 = new Subtask(2, "подзадача 1", "Описание подзадачи 1", Status.NEW, 1);
-        Subtask subtask2 = new Subtask(2, "подзадача 1", "Описание подзадачи 1", Status.NEW, 1);
+        Subtask subtask1 = new Subtask(2, "подзадача 1", "Описание подзадачи 1", Status.NEW, 1,
+                LocalDateTime.now().plusHours(1), Duration.ofMinutes(20));
+        Subtask subtask2 = new Subtask(2, "подзадача 1", "Описание подзадачи 1", Status.NEW, 1,
+                LocalDateTime.now().plusHours(1), Duration.ofMinutes(20));
         assertEquals(subtask2, subtask1, "Подзадачи не равны");
     }
 }
\ No newline at end of file
diff --git a/test/tasks/TaskTest.java b/test/tasks/TaskTest.java
index fc67e32..bb567bb 100644
--- a/test/tasks/TaskTest.java
+++ b/test/tasks/TaskTest.java
@@ -2,14 +2,19 @@
 
 import org.junit.jupiter.api.Test;
 
+import java.time.Duration;
+import java.time.LocalDateTime;
+
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 class TaskTest {
 
     @Test
     public void testsAreEqualIfTheIDsAreEqual() {
-        Task task1 = new Task(1, "Задача 1", "Описание задачи 1", Status.NEW);
-        Task task2 = new Task(1, "Задача 1", "Описание задачи 1", Status.NEW);
+        Task task1 = new Task(1, "Задача 1", "Описание задачи 1", Status.NEW,
+                LocalDateTime.now(), Duration.ofMinutes(10));
+        Task task2 = new Task(1, "Задача 1", "Описание задачи 1", Status.NEW,
+                LocalDateTime.now(), Duration.ofMinutes(10));
         assertEquals(task2, task1, "Задачи не равны");
     }
 }
\ No newline at end of file


Reviews:
user: login: Ivanov-s-tmn
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-04T09:06:14Z
user: login: Ivanov-s-tmn
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-06T08:04:55Z

Review comments:
diff_hunk: @@ -5,15 +5,14 @@
 import tasks.Subtask;
 import tasks.Task;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
 
 public class InMemoryTaskManager implements TaskManager {
     private int id = 1;
     protected HashMap<Integer, Task> tasks = new HashMap<>();
     protected HashMap<Integer, Epic> epics = new HashMap<>();
-    protected HashMap<Integer, Subtask> subtasks = new HashMap<>();
+    protected static HashMap<Integer, Subtask> subtasks = new HashMap<>();
path: src/managers/InMemoryTaskManager.java
user: login: Ivanov-s-tmn
body: Почему статик? Это делает хешмапу общей для всех экземпляров таск менеджера, а для нас это не подходит
created_at: 2025-05-04T08:54:09Z
author_association: NONE
diff_hunk: @@ -59,37 +64,42 @@ public List<Subtask> printAllSubtasks() {
         return new ArrayList<>(subtasks.values());
     }
 
+    public List<Task> getAllTasks() {
+        List<Task> allTasks = new ArrayList<>();
+        allTasks.addAll(printAllTasks());
+        allTasks.addAll(printAllSubtasks());
+        return allTasks;
+    }
path: src/managers/InMemoryTaskManager.java
user: login: Ivanov-s-tmn
body: Лишние методы добавлять не нужно, у нас в интерфейсе определено основное поведение менеджера и лишний раз расширять его не нужно
created_at: 2025-05-04T08:56:09Z
author_association: NONE
diff_hunk: @@ -114,9 +124,17 @@ public Subtask searchSubtaskByID(int id) {
         return subtask;
     }
 
+    // тот же поиск подзадачи, но без добавления в историю
+    public static Subtask getSubtask(int id) {
+        return subtasks.get(id);
+    }
path: src/managers/InMemoryTaskManager.java
user: login: Ivanov-s-tmn
body: Лишнее
created_at: 2025-05-04T08:57:36Z
author_association: NONE
diff_hunk: @@ -1,38 +1,68 @@
 package tasks;
 
+import managers.InMemoryTaskManager;
+
+import java.time.Duration;
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Objects;
 
 public class Epic extends Task {
     private ArrayList<Integer> subtask = new ArrayList<>();
 
     public Epic(int id, String name, String description, Status status, ArrayList<Integer> subtask) {
-        super(id, name, description, status);
+        super(id, name, description, status, null, null);
         this.subtask = subtask;
     }
 
+    public ArrayList<Integer> getSubtask() {
+        return subtask;
+    }
+
+    public void setSubtask(int subtask) {
+        this.subtask.add(subtask);
+    }
+
     @Override
-    public String toString() {
-        return "{" +
-                "id='" + getId() + '\'' +
-                ", name='" + getName() + '\'' +
-                ", description='" + getDescription() + '\'' +
-                ", status=" + getStatus() +
-                ", subTask=" + subtask +
-                '}';
+    public LocalDateTime getStartTime() {
+        return subtask.stream()
+                .map(InMemoryTaskManager::getSubtask)
+                .map(Subtask::getStartTime)
+                .min(LocalDateTime::compareTo)
+                .orElse(LocalDateTime.MAX);
     }
 
-    public ArrayList<Integer> getSubtask() {
-        return subtask;
+    @Override
+    public Duration getDuration() {
+        return subtask.stream()
+                .map(InMemoryTaskManager::getSubtask)
+                .map(Subtask::getDuration)
+                .reduce(Duration.ZERO, Duration::plus);
+    }
+
+    @Override
+    public LocalDateTime getEndTime() {
+        return subtask.stream()
+                .map(InMemoryTaskManager::getSubtask)
+                .map(Subtask::getStartTime)
+                .max(LocalDateTime::compareTo)
+                .orElse(LocalDateTime.MIN);
path: src/tasks/Epic.java
user: login: Ivanov-s-tmn
body: Расчет временных полей эпика можно вынести так же в таск менеджер и сделать по аналогии с методом расчета статуса, плюс, это все можно сделать за один цикл. Плюс, должны быть не только геттеры, но и в целом должны быть заданы значения полей через сеттеры. 

Для эпика нужно добавить поле endTime и задавать его при расчете (для таски и сабтаски это не нужно)
created_at: 2025-05-04T08:58:24Z
author_association: NONE
diff_hunk: @@ -191,16 +212,29 @@ private void checkStatus(int id) {
     //Получение списка всех подзадач определённого эпика.
     @Override
     public ArrayList<Subtask> printSubtasksСertainEpic(int id) {
-        ArrayList<Integer> listSubtaks = epics.get(id).getSubtask();
-        ArrayList<Subtask> subtasks1 = new ArrayList<>();
-        for (int idSubtask : listSubtaks) {
-            subtasks1.add(subtasks.get(idSubtask));
-        }
-        return subtasks1;
+        return epics.get(id).getSubtask().stream()
+                .map(subtasks::get)
+                .collect(Collectors.toCollection(ArrayList::new));
     }
 
     @Override
     public List<Task> getHistory() {
         return historyManager.getHistory();
     }
+
+    @Override
+    public TreeSet<Task> getPrioritizedTasks() {
+        TreeSet<Task> prioritizedTasks = new TreeSet<>(Comparator.comparing(Task::getStartTime,
+                Comparator.nullsLast(Comparator.naturalOrder())));
+        prioritizedTasks.addAll(tasks.values());
+        prioritizedTasks.addAll(subtasks.values());
+        return prioritizedTasks;
+    }
+
+    @Override
+    public boolean taskNotOverlap(Task task) {
path: src/managers/InMemoryTaskManager.java
user: login: Ivanov-s-tmn
body: Метод должен быть приватным, он проверяет на пересечение перед добавлением задач в методах таск менеджера и не нужен вне этого класса
created_at: 2025-05-04T08:59:15Z
author_association: NONE
diff_hunk: @@ -191,16 +212,29 @@ private void checkStatus(int id) {
     //Получение списка всех подзадач определённого эпика.
     @Override
     public ArrayList<Subtask> printSubtasksСertainEpic(int id) {
-        ArrayList<Integer> listSubtaks = epics.get(id).getSubtask();
-        ArrayList<Subtask> subtasks1 = new ArrayList<>();
-        for (int idSubtask : listSubtaks) {
-            subtasks1.add(subtasks.get(idSubtask));
-        }
-        return subtasks1;
+        return epics.get(id).getSubtask().stream()
+                .map(subtasks::get)
+                .collect(Collectors.toCollection(ArrayList::new));
     }
 
     @Override
     public List<Task> getHistory() {
         return historyManager.getHistory();
     }
+
+    @Override
+    public TreeSet<Task> getPrioritizedTasks() {
+        TreeSet<Task> prioritizedTasks = new TreeSet<>(Comparator.comparing(Task::getStartTime,
+                Comparator.nullsLast(Comparator.naturalOrder())));
+        prioritizedTasks.addAll(tasks.values());
+        prioritizedTasks.addAll(subtasks.values());
+        return prioritizedTasks;
+    }
+
+    @Override
+    public boolean taskNotOverlap(Task task) {
+        return getAllTasks().stream()
path: src/managers/InMemoryTaskManager.java
user: login: Ivanov-s-tmn
body: Обходить нужно тогда уж отсортированный список и лучшим выходом будет ввести новое поле отсортированного списка в таск менеджере
created_at: 2025-05-04T09:00:52Z
author_association: NONE
diff_hunk: @@ -61,6 +69,32 @@ public void setName(String name) {
         this.name = name;
     }
 
+    public void setDuration(Duration duration) {
+        this.duration = duration;
+    }
+
+    public void setStartTime(LocalDateTime startTime) {
+        this.startTime = startTime;
+    }
+
+    public boolean isOverlap(Task task) {
+        if (this.startTime == null || task.startTime == null) {
+            return false;
+        }
+        return this.startTime.isBefore(task.getEndTime()) &&
+                task.startTime.isBefore(this.getEndTime());
path: src/tasks/Task.java
user: login: Ivanov-s-tmn
body: Проверка не покрывает все случаи пересечения, интервал может быть перекрыт как полностью так и частично
created_at: 2025-05-04T09:02:14Z
author_association: NONE
path: test/managers/TaskManagerTest.java
user: login: Ivanov-s-tmn
body: Должны быть покрыты тестами все методы интерфейса `TaskManager`, в том числе и новый функционал отсортированного списка
created_at: 2025-05-04T09:05:27Z
author_association: NONE
path: .idea/misc.xml
user: login: Ivanov-s-tmn
body: директорию .idea стоит добавить в исключения gitignore файла, это локальная директория для IntellijIdea и она не нужна в репозитории
created_at: 2025-05-04T09:06:13Z
author_association: NONE
diff_hunk: @@ -209,6 +200,40 @@ private void checkStatus(int id) {
         }
     }
 
+    private void calculateTimeEpic(Epic epic) {
+        if (epic.getSubtask().isEmpty()) {
+            epic.setStartTime(null);
+            epic.setDuration(null);
+            epic.setEndTime(null);
+            return;
+        }
+
+        LocalDateTime start = null;
+        LocalDateTime end = null;
path: src/managers/InMemoryTaskManager.java
user: login: Ivanov-s-tmn
body: Можно использовать константы `LocalDateTime.MIN` и `LocalDateTime.MAX` для задания начальных значений, чтобы не работать с null
created_at: 2025-05-06T07:03:57Z
author_association: NONE
diff_hunk: @@ -3,15 +3,14 @@
 import org.junit.jupiter.api.Test;
 import tasks.Status;
 import tasks.Subtask;
-import tasks.Task;
 
 import java.time.Duration;
 import java.time.LocalDateTime;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-class InMemoryTaskManagerTest extends TaskManagerTest<InMemoryTaskManager> {
+class InMemoryTaskManagerTest extends managers.TaskManagerTest<InMemoryTaskManager> {
path: test/managers/InMemoryTaskManagerTest.java
user: login: Ivanov-s-tmn
body: Зачем обращение через пакет `managers.TaskManagerTest<InMemoryTaskManager>`?
created_at: 2025-05-06T08:03:13Z
author_association: NONE

PR comments:
user: login: zvv24
created_at: 2025-05-05T09:13:03Z
body: To github.com:zvv24/java-kanban.git
 ! [rejected]        HEAD -> sprint_8-solution-time-and-duration (non-fast-forward)
error: failed to push some refs to 'github.com:zvv24/java-kanban.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. If you want to integrate the remote changes,
hint: use 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Пытался разобраться с это ошибкой, надеюсь сделал все правильно 
author_association: OWNER