From c3fb9ce3c4f20be31a627943da247b341422b769 Mon Sep 17 00:00:00 2001 From: Petr Date: Sun, 22 Jun 2025 16:46:50 +0300 Subject: [PATCH 01/47] =?UTF-8?q?=D0=97=D0=B0=D0=BC=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=87=D0=B0=D1=81=D1=82=D1=8C=20=D1=86=D0=B8?= =?UTF-8?q?=D0=BA=D0=BB=D0=BE=D0=B2=20for=20=D0=BD=D0=B0=20forEach=20?= =?UTF-8?q?=D0=B8=D0=BB=D0=B8=20Stream?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/Main.java | 12 +++--------- src/service/InMemoryTaskManager.java | 13 +++---------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/app/Main.java b/src/app/Main.java index d97f939..b609b10 100644 --- a/src/app/Main.java +++ b/src/app/Main.java @@ -66,9 +66,7 @@ private static TaskManager getTaskManager() { private static void printAllTasks(TaskManager manager) { System.out.println(); System.out.println("Задачи:"); - for (Task task : manager.getTasks()) { - System.out.println(task); - } + manager.getTasks().forEach(System.out::println); System.out.println(); System.out.println("Эпики:"); @@ -82,15 +80,11 @@ private static void printAllTasks(TaskManager manager) { System.out.println(); System.out.println("Подзадачи:"); - for (Task subtask : manager.getSubTasks()) { - System.out.println(subtask); - } + manager.getSubTasks().forEach(System.out::println); System.out.println(); System.out.println("История:"); - for (Task task : manager.getHistory()) { - System.out.println(task); - } + manager.getHistory().forEach(System.out::println); System.out.println(); } } \ No newline at end of file diff --git a/src/service/InMemoryTaskManager.java b/src/service/InMemoryTaskManager.java index 397d292..47940b3 100644 --- a/src/service/InMemoryTaskManager.java +++ b/src/service/InMemoryTaskManager.java @@ -64,9 +64,7 @@ public void removeAllEpics() { public void removeAllSubTasks() { List epics = getEpics(); - for (Epic epic : epics) { - epic.unlinkAllSubtasks(); - } + epics.forEach(Epic::unlinkAllSubtasks); allSubTasks.clear(); } @@ -110,9 +108,7 @@ public List getAllSubTasksOfEpic(int id) { List subTaskList = new ArrayList<>(); Epic epic = getEpicById(id); - for (Integer subTaskId : epic.getSubTaskIdList()) { - subTaskList.add(getSubTaskById(subTaskId)); - } + epic.getSubTaskIdList().forEach(subTaskId -> subTaskList.add(getSubTaskById(subTaskId))); return subTaskList; } @@ -205,10 +201,7 @@ public void removeEpicById(int id) { if (allEpics.containsKey(id)) { Epic epic = getEpicById(id); List relatedSubTasks = epic.getSubTaskIdList(); - - for (Integer subTaskId : relatedSubTasks) { - removeSubTaskById(subTaskId); - } + relatedSubTasks.forEach(this::removeSubTaskById); allEpics.remove(id); historyManager.remove(id); } else { From d32756c362c64aba1a66f79784cbe1fd59d40e58 Mon Sep 17 00:00:00 2001 From: Petr Date: Sun, 22 Jun 2025 18:34:37 +0300 Subject: [PATCH 02/47] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BF=D0=BE=D0=BB=D1=8F=20duration=20=D0=B8=20s?= =?UTF-8?q?tartTime=20=D0=B2=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=20Task?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/model/Task.java | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/model/Task.java b/src/model/Task.java index 2f3060f..7877c14 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -1,19 +1,36 @@ package model; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.Objects; +import java.util.Optional; public class Task { private final String title; private final String description; private final Status status; + private Duration duration; + private LocalDateTime startTime; private int id; - public Task(String title, String description, Status status) { + protected Task(String title, String description, Status status) { this.title = title; this.description = description; this.status = status; } + public Task(String title, String description, Status status, Duration duration) { + this(title, description, status); + this.duration = duration; + } + + public Task(String title, String description, Status status, Duration duration, LocalDateTime startTime) { + this(title, description, status, duration); + this.startTime = startTime; + } + + + public int getId() { return id; } @@ -34,6 +51,11 @@ public Status getStatus() { return status; } + public Optional getEndTime() { + return Optional.ofNullable(startTime) + .map(time -> time.plus(duration)); + } + public String toCSV(int headersCount) { return String.format("%s,%s,%s,%s,%s", id, "TASK", title, status, description); } From 0ac412aae18b883f835142e581f4e86f16964522 Mon Sep 17 00:00:00 2001 From: Petr Date: Sun, 22 Jun 2025 20:14:16 +0300 Subject: [PATCH 03/47] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=B2=D1=8B=D1=87=D0=B8=D1=81=D0=BB=D1=8F=D0=B5?= =?UTF-8?q?=D0=BC=D1=8B=D0=B5=20=D0=BF=D0=BE=D0=BB=D1=8F=20=D0=B2=20Epic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/model/Epic.java | 22 ++++++++++++++ src/model/Task.java | 16 ++++++++++ src/service/InMemoryTaskManager.java | 22 ++++++++++++-- src/service/TaskManager.java | 7 ++++- .../utils/SubtaskStartTimeComparator.java | 30 +++++++++++++++++++ 5 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 src/service/utils/SubtaskStartTimeComparator.java diff --git a/src/model/Epic.java b/src/model/Epic.java index 6a412bf..a2e96d7 100644 --- a/src/model/Epic.java +++ b/src/model/Epic.java @@ -1,9 +1,12 @@ package model; +import java.time.*; import java.util.*; +import java.util.stream.Collectors; public class Epic extends Task { private Map relatedSubTaskMap; + private LocalDateTime endTime; public Epic(String title, String description) { super(title, description, Status.NEW); @@ -15,6 +18,10 @@ public Epic(String title, String description, Status status) { relatedSubTaskMap = new HashMap<>(); } + public void setEndTime(LocalDateTime endTime) { + this.endTime = endTime; + } + public List getSubTaskIdList() { return new ArrayList<>(relatedSubTaskMap.keySet()); } @@ -59,6 +66,21 @@ public void updateSubTask(SubTask subTask) { } } + public void updateTimeFrame(TreeSet sortedSubTasks) { + TreeSet allSubTasks = sortedSubTasks.stream() + .filter(s -> s.getStartTime().isPresent()) + .collect(Collectors.toCollection(TreeSet::new)); + + Duration totalDuration = Duration.ofMinutes( + allSubTasks.stream() + .reduce(0L, (subtotal, subTask) -> subtotal + subTask.getDuration().toMinutes(), Long::sum) + ); + LocalDateTime startTime = allSubTasks.getFirst().getStartTime().get(); + setStartTime(startTime); + setDuration(totalDuration); + setEndTime(startTime.plus(totalDuration)); + } + @Override public Status getStatus() { boolean isAllNew = true; diff --git a/src/model/Task.java b/src/model/Task.java index 7877c14..f6eace7 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -56,6 +56,22 @@ public Optional getEndTime() { .map(time -> time.plus(duration)); } + protected void setStartTime(LocalDateTime startTime) { + this.startTime = startTime; + } + + protected void setDuration(Duration duration) { + this.duration = duration; + } + + public Duration getDuration() { + return duration; + } + + public Optional getStartTime() { + return Optional.ofNullable(startTime); + } + public String toCSV(int headersCount) { return String.format("%s,%s,%s,%s,%s", id, "TASK", title, status, description); } diff --git a/src/service/InMemoryTaskManager.java b/src/service/InMemoryTaskManager.java index 47940b3..8c9470c 100644 --- a/src/service/InMemoryTaskManager.java +++ b/src/service/InMemoryTaskManager.java @@ -3,6 +3,7 @@ import java.util.*; import model.*; +import service.utils.SubtaskStartTimeComparator; public class InMemoryTaskManager implements TaskManager { protected final Map allTasks = new HashMap<>(); @@ -104,14 +105,26 @@ public SubTask getSubTaskById(int id) { } @Override - public List getAllSubTasksOfEpic(int id) { - List subTaskList = new ArrayList<>(); + public TreeSet getAllSubTasksOfEpic(int id) { + TreeSet subTaskList = new TreeSet<>(new SubtaskStartTimeComparator()); Epic epic = getEpicById(id); epic.getSubTaskIdList().forEach(subTaskId -> subTaskList.add(getSubTaskById(subTaskId))); return subTaskList; } + @Override + public void updateEpicTimeFrame(int epicId) { + Epic epic = getEpicById(epicId); + TreeSet sortedSubTasks = getAllSubTasksOfEpic(epicId); + epic.updateTimeFrame(sortedSubTasks); + } + + @Override + public void updateEpicTimeFrame(Epic epic){ + updateEpicTimeFrame(epic.getId()); + } + @Override public int createTask(Task task) { int newId = generateUniqueId(); @@ -139,6 +152,8 @@ public int createSubTask(SubTask subTask) { relatedEpic.addSubTask(subTask.getId(), subTask.getStatus()); allSubTasks.put(newId, subTask); + updateEpicTimeFrame(relatedEpic); + return newId; } @@ -179,6 +194,8 @@ public void updateSubTask(SubTask subTask, int id) { newEpic.addSubTask(id, subTask.getStatus()); } allSubTasks.put(id, subTask); + + updateEpicTimeFrame(subTask.getEpicId()); } else { System.out.printf("Ошибка при вызове updateSubTask(SubTask subTask, int id): " + "Ошибка обновления подзадачи id %d - подзадача не найдена." + "%n", id); @@ -219,6 +236,7 @@ public void removeSubTaskById(int id) { epic.unlinkSubTask(id); allSubTasks.remove(id); historyManager.remove(id); + updateEpicTimeFrame(subTask.getEpicId()); } else { System.out.printf("Ошибка при вызове removeSubTaskById(int id): " + "Невозможно удалить подзадачу id %d по id: подзадача не найдена." + "%n", id); diff --git a/src/service/TaskManager.java b/src/service/TaskManager.java index 8acfea8..bdce4ae 100644 --- a/src/service/TaskManager.java +++ b/src/service/TaskManager.java @@ -1,6 +1,7 @@ package service; import java.util.List; +import java.util.Set; import model.*; @@ -25,7 +26,7 @@ public interface TaskManager { SubTask getSubTaskById(int id); - List getAllSubTasksOfEpic(int id); + Set getAllSubTasksOfEpic(int id); int createTask(Task task); @@ -37,6 +38,10 @@ public interface TaskManager { void updateEpic(Epic epic, int id); + void updateEpicTimeFrame(int epicId); + + void updateEpicTimeFrame(Epic epic); + void updateSubTask(SubTask subTask, int id); void removeTaskById(int id); diff --git a/src/service/utils/SubtaskStartTimeComparator.java b/src/service/utils/SubtaskStartTimeComparator.java new file mode 100644 index 0000000..47cde78 --- /dev/null +++ b/src/service/utils/SubtaskStartTimeComparator.java @@ -0,0 +1,30 @@ +package service.utils; + +import java.time.LocalDateTime; +import java.util.Comparator; +import java.util.Optional; + +import model.SubTask; + +public class SubtaskStartTimeComparator implements Comparator { + + @Override + public int compare(SubTask o1, SubTask o2){ + Optional timeA = o1.getStartTime(); + Optional timeB = o2.getStartTime(); + + if (timeA.isEmpty() && timeB.isEmpty()) { + return 0; + } + + if (timeA.isPresent() && timeB.isEmpty()) { + return -1; + } + + if (timeA.isEmpty()) { + return 1; + } + + return timeA.get().compareTo(timeB.get()); + } +} From 6455d501ff63ee7ba837ce53aabcc3a7353a98a0 Mon Sep 17 00:00:00 2001 From: Petr Date: Sun, 22 Jun 2025 20:25:42 +0300 Subject: [PATCH 04/47] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=B2=D1=8B=D1=87=D0=B8=D1=81=D0=BB=D1=8F=D0=B5?= =?UTF-8?q?=D0=BC=D1=8B=D0=B5=20=D0=BF=D0=BE=D0=BB=D1=8F=20=D0=B2=20Epic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/InMemoryTaskManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/service/InMemoryTaskManager.java b/src/service/InMemoryTaskManager.java index 8c9470c..0cac84b 100644 --- a/src/service/InMemoryTaskManager.java +++ b/src/service/InMemoryTaskManager.java @@ -176,6 +176,7 @@ public void updateEpic(Epic epic, int id) { epic.setRelatedSubTaskMap(bufferedMap); epic.setId(id); allEpics.put(id, epic); + updateEpicTimeFrame(epic); } @Override From 6a941cd20b6ea579a161c07c3f47a4e8512cf082 Mon Sep 17 00:00:00 2001 From: Petr Date: Sun, 22 Jun 2025 21:27:43 +0300 Subject: [PATCH 05/47] =?UTF-8?q?=D0=A5=D1=80=D0=B0=D0=BD=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=87=D0=B8=20=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B4=D0=B7=D0=B0=D0=B4=D0=B0=D1=87=D0=B8=20=D0=B2=20?= =?UTF-8?q?=D0=BF=D0=BE=D1=80=D1=8F=D0=B4=D0=BA=D0=B5=20=D0=BF=D1=80=D0=B8?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D1=82=D0=B5=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/InMemoryTaskManager.java | 34 +++++++++++++++++-- src/service/TaskManager.java | 7 ++-- ...ator.java => TaskStartTimeComparator.java} | 6 ++-- 3 files changed, 39 insertions(+), 8 deletions(-) rename src/service/utils/{SubtaskStartTimeComparator.java => TaskStartTimeComparator.java} (79%) diff --git a/src/service/InMemoryTaskManager.java b/src/service/InMemoryTaskManager.java index 0cac84b..41dbe71 100644 --- a/src/service/InMemoryTaskManager.java +++ b/src/service/InMemoryTaskManager.java @@ -1,14 +1,16 @@ package service; import java.util.*; +import java.util.stream.Collectors; import model.*; -import service.utils.SubtaskStartTimeComparator; +import service.utils.TaskStartTimeComparator; public class InMemoryTaskManager implements TaskManager { protected final Map allTasks = new HashMap<>(); protected final Map allEpics = new HashMap<>(); protected final Map allSubTasks = new HashMap<>(); + private TreeSet sortedTasksAndSubTasks = new TreeSet<>(new TaskStartTimeComparator()); private final IdGenerator idGenerator; private final HistoryManager historyManager; @@ -53,6 +55,9 @@ public List getSubTasks() { @Override public void removeAllTasks() { allTasks.clear(); + sortedTasksAndSubTasks = sortedTasksAndSubTasks.stream() + .filter(task -> task instanceof SubTask) + .collect(Collectors.toCollection(TreeSet::new)); } @Override @@ -67,6 +72,10 @@ public void removeAllSubTasks() { epics.forEach(Epic::unlinkAllSubtasks); allSubTasks.clear(); + + sortedTasksAndSubTasks = sortedTasksAndSubTasks.stream() + .filter(task -> !(task instanceof SubTask)) + .collect(Collectors.toCollection(TreeSet::new)); } @Override @@ -106,13 +115,18 @@ public SubTask getSubTaskById(int id) { @Override public TreeSet getAllSubTasksOfEpic(int id) { - TreeSet subTaskList = new TreeSet<>(new SubtaskStartTimeComparator()); + TreeSet subTaskList = new TreeSet<>(new TaskStartTimeComparator()); Epic epic = getEpicById(id); epic.getSubTaskIdList().forEach(subTaskId -> subTaskList.add(getSubTaskById(subTaskId))); return subTaskList; } + @Override + public TreeSet getPrioritizedTasks() { + return sortedTasksAndSubTasks; + } + @Override public void updateEpicTimeFrame(int epicId) { Epic epic = getEpicById(epicId); @@ -130,6 +144,7 @@ public int createTask(Task task) { int newId = generateUniqueId(); task.setId(newId); allTasks.put(newId, task); + addTaskToTreeSet(task); return newId; } @@ -151,17 +166,26 @@ public int createSubTask(SubTask subTask) { Epic relatedEpic = getEpicById(subTask.getEpicId()); relatedEpic.addSubTask(subTask.getId(), subTask.getStatus()); allSubTasks.put(newId, subTask); - + addTaskToTreeSet(subTask); updateEpicTimeFrame(relatedEpic); return newId; } + @Override + public void addTaskToTreeSet(Task task){ + if (task.getStartTime().isPresent()) { + sortedTasksAndSubTasks.add(task); + } + } + @Override public void updateTask(Task task, int id) { if (allTasks.containsKey(id)) { task.setId(id); allTasks.put(id, task); + sortedTasksAndSubTasks.remove(getTaskById(id)); + addTaskToTreeSet(task); } else { System.out.printf("Ошибка при вызове updateTask(Task task, int id): " + "Ошибка обновления задачи id %d - задача не найдена" + "%n", id); @@ -195,6 +219,8 @@ public void updateSubTask(SubTask subTask, int id) { newEpic.addSubTask(id, subTask.getStatus()); } allSubTasks.put(id, subTask); + sortedTasksAndSubTasks.remove(getSubTaskById(id)); + addTaskToTreeSet(subTask); updateEpicTimeFrame(subTask.getEpicId()); } else { @@ -208,6 +234,7 @@ public void removeTaskById(int id) { if (allTasks.containsKey(id)) { allTasks.remove(id); historyManager.remove(id); + sortedTasksAndSubTasks.remove(getTaskById(id)); } else { System.out.printf("Ошибка при вызове removeTaskById(int id):" + " Невозможно удалить задачу id %d по id: задача не найдена." + "%n", id); @@ -238,6 +265,7 @@ public void removeSubTaskById(int id) { allSubTasks.remove(id); historyManager.remove(id); updateEpicTimeFrame(subTask.getEpicId()); + sortedTasksAndSubTasks.remove(getSubTaskById(id)); } else { System.out.printf("Ошибка при вызове removeSubTaskById(int id): " + "Невозможно удалить подзадачу id %d по id: подзадача не найдена." + "%n", id); diff --git a/src/service/TaskManager.java b/src/service/TaskManager.java index bdce4ae..fa55f75 100644 --- a/src/service/TaskManager.java +++ b/src/service/TaskManager.java @@ -1,7 +1,6 @@ package service; -import java.util.List; -import java.util.Set; +import java.util.*; import model.*; @@ -28,12 +27,16 @@ public interface TaskManager { Set getAllSubTasksOfEpic(int id); + TreeSet getPrioritizedTasks(); + int createTask(Task task); int createEpic(Epic epic); int createSubTask(SubTask subTask); + void addTaskToTreeSet(Task task); + void updateTask(Task task, int id); void updateEpic(Epic epic, int id); diff --git a/src/service/utils/SubtaskStartTimeComparator.java b/src/service/utils/TaskStartTimeComparator.java similarity index 79% rename from src/service/utils/SubtaskStartTimeComparator.java rename to src/service/utils/TaskStartTimeComparator.java index 47cde78..8372e21 100644 --- a/src/service/utils/SubtaskStartTimeComparator.java +++ b/src/service/utils/TaskStartTimeComparator.java @@ -4,12 +4,12 @@ import java.util.Comparator; import java.util.Optional; -import model.SubTask; +import model.Task; -public class SubtaskStartTimeComparator implements Comparator { +public class TaskStartTimeComparator implements Comparator { @Override - public int compare(SubTask o1, SubTask o2){ + public int compare(Task o1, Task o2){ Optional timeA = o1.getStartTime(); Optional timeB = o2.getStartTime(); From 7353c6ad0470e7e7b3789fe96fa5f1286e7ecadd Mon Sep 17 00:00:00 2001 From: Petr Date: Sun, 22 Jun 2025 22:58:40 +0300 Subject: [PATCH 06/47] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D1=83?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=87=20=D0=BD=D0=B0=20=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D1=81=D0=B5=D1=87=D0=B5=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/model/Task.java | 2 +- src/service/InMemoryTaskManager.java | 68 ++++++++++++++++++++++++---- src/service/TaskManager.java | 4 ++ 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/src/model/Task.java b/src/model/Task.java index f6eace7..dcc1262 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -56,7 +56,7 @@ public Optional getEndTime() { .map(time -> time.plus(duration)); } - protected void setStartTime(LocalDateTime startTime) { + public void setStartTime(LocalDateTime startTime) { this.startTime = startTime; } diff --git a/src/service/InMemoryTaskManager.java b/src/service/InMemoryTaskManager.java index 41dbe71..436fdd3 100644 --- a/src/service/InMemoryTaskManager.java +++ b/src/service/InMemoryTaskManager.java @@ -10,9 +10,9 @@ public class InMemoryTaskManager implements TaskManager { protected final Map allTasks = new HashMap<>(); protected final Map allEpics = new HashMap<>(); protected final Map allSubTasks = new HashMap<>(); - private TreeSet sortedTasksAndSubTasks = new TreeSet<>(new TaskStartTimeComparator()); private final IdGenerator idGenerator; private final HistoryManager historyManager; + private TreeSet sortedTasksAndSubTasks = new TreeSet<>(new TaskStartTimeComparator()); public InMemoryTaskManager(IdGenerator idGenerator, HistoryManager historyManager) { this.idGenerator = idGenerator; @@ -128,23 +128,36 @@ public TreeSet getPrioritizedTasks() { } @Override - public void updateEpicTimeFrame(int epicId) { - Epic epic = getEpicById(epicId); - TreeSet sortedSubTasks = getAllSubTasksOfEpic(epicId); - epic.updateTimeFrame(sortedSubTasks); + public boolean checkForOverlap(Task a, Task b) { + if (a.getEndTime().isPresent() && b.getStartTime().isPresent()) { + return a.getEndTime().get().isAfter(b.getStartTime().get()); + } + + return false; } @Override - public void updateEpicTimeFrame(Epic epic){ - updateEpicTimeFrame(epic.getId()); + public boolean checkForAnyOverlaps(Task taskA) { + return getPrioritizedTasks().stream() + .anyMatch(taskB -> checkForOverlap(taskA, taskB)); } @Override public int createTask(Task task) { + if (checkForAnyOverlaps(task)) { + System.out.printf("Ошибка добавления задачи %d:" + + " обнаружено наложение времени выполнения. \n" + + "Задача добавлена без указания времени начала выполнения.", task.getId()); + task.setStartTime(null); + } + int newId = generateUniqueId(); task.setId(newId); allTasks.put(newId, task); - addTaskToTreeSet(task); + + if (task.getStartTime().isPresent()) { + addTaskToTreeSet(task); + } return newId; } @@ -160,20 +173,30 @@ public int createEpic(Epic epic) { @Override public int createSubTask(SubTask subTask) { + if (checkForAnyOverlaps(subTask)) { + System.out.printf("Ошибка добавления подзадачи %d:" + + " обнаружено наложение времени выполнения. \n" + + "Подзадача добавлена без указания времени начала выполнения.", subTask.getId()); + subTask.setStartTime(null); + } int newId = generateUniqueId(); subTask.setId(newId); Epic relatedEpic = getEpicById(subTask.getEpicId()); relatedEpic.addSubTask(subTask.getId(), subTask.getStatus()); allSubTasks.put(newId, subTask); - addTaskToTreeSet(subTask); + + if (subTask.getStartTime().isPresent()) { + addTaskToTreeSet(subTask); + } + updateEpicTimeFrame(relatedEpic); return newId; } @Override - public void addTaskToTreeSet(Task task){ + public void addTaskToTreeSet(Task task) { if (task.getStartTime().isPresent()) { sortedTasksAndSubTasks.add(task); } @@ -181,6 +204,12 @@ public void addTaskToTreeSet(Task task){ @Override public void updateTask(Task task, int id) { + if (checkForAnyOverlaps(task)) { + System.out.printf("Ошибка обновления задачи %d:" + + " обнаружено наложение времени выполнения. \n" + + "Задача не была обновлена.", task.getId()); + return; + } if (allTasks.containsKey(id)) { task.setId(id); allTasks.put(id, task); @@ -203,8 +232,27 @@ public void updateEpic(Epic epic, int id) { updateEpicTimeFrame(epic); } + @Override + public void updateEpicTimeFrame(int epicId) { + Epic epic = getEpicById(epicId); + TreeSet sortedSubTasks = getAllSubTasksOfEpic(epicId); + epic.updateTimeFrame(sortedSubTasks); + } + + @Override + public void updateEpicTimeFrame(Epic epic) { + updateEpicTimeFrame(epic.getId()); + } + @Override public void updateSubTask(SubTask subTask, int id) { + if (checkForAnyOverlaps(subTask)) { + System.out.printf("Ошибка обновления подзадачи %d:" + + " обнаружено наложение времени выполнения. \n" + + "Подзадача не была обновлена.", subTask.getId()); + return; + } + if (allSubTasks.containsKey(id)) { SubTask oldSubTask = getSubTaskById(id); Epic oldEpic = getEpicById(oldSubTask.getEpicId()); diff --git a/src/service/TaskManager.java b/src/service/TaskManager.java index fa55f75..39eaf7b 100644 --- a/src/service/TaskManager.java +++ b/src/service/TaskManager.java @@ -29,6 +29,10 @@ public interface TaskManager { TreeSet getPrioritizedTasks(); + boolean checkForOverlap(Task a, Task b); + + boolean checkForAnyOverlaps(Task task); + int createTask(Task task); int createEpic(Epic epic); From 363ff2528ed9f5986362f92129bc63066b743bc6 Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 00:03:35 +0300 Subject: [PATCH 07/47] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20toString(),=20hashCode(),=20equals()=20=D1=83=20?= =?UTF-8?q?=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D0=BE=D0=B2=20=D0=B7=D0=B0=D0=B4?= =?UTF-8?q?=D0=B0=D1=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/model/Epic.java | 3 +++ src/model/SubTask.java | 3 +++ src/model/Task.java | 35 ++++++++++++++++++++++++++++++++--- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/model/Epic.java b/src/model/Epic.java index a2e96d7..34ade9d 100644 --- a/src/model/Epic.java +++ b/src/model/Epic.java @@ -142,6 +142,9 @@ public String toString() { ", title='" + super.getTitle() + '\'' + ", description.length='" + super.getDescription().length() + '\'' + ", status=" + getStatus() + + ", startTime=" + super.getFormatterStartTime() + + ", duration=" + super.getDuration().toMinutes() + " min" + + ", endTime=" + super.getFormattedEndTime() + '}'; } } diff --git a/src/model/SubTask.java b/src/model/SubTask.java index 60ea069..374ea1c 100644 --- a/src/model/SubTask.java +++ b/src/model/SubTask.java @@ -49,6 +49,9 @@ public String toString() { ", title='" + super.getTitle() + '\'' + ", description.length='" + super.getDescription().length() + '\'' + ", status=" + super.getStatus() + + ", startTime=" + super.getFormatterStartTime() + + ", duration=" + super.getDuration().toMinutes() + " min" + + ", endTime=" + super.getFormattedEndTime() + '}'; } } diff --git a/src/model/Task.java b/src/model/Task.java index dcc1262..18e4e2e 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -2,10 +2,13 @@ import java.time.Duration; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.Objects; import java.util.Optional; public class Task { + public final static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm dd.MM.yyyy"); + private final String title; private final String description; private final Status status; @@ -29,8 +32,6 @@ public Task(String title, String description, Status status, Duration duration, this.startTime = startTime; } - - public int getId() { return id; } @@ -72,13 +73,34 @@ public Optional getStartTime() { return Optional.ofNullable(startTime); } + protected String getFormatterStartTime() { + String startTimeString = "N/A"; + + if (getStartTime().isPresent()) { + startTimeString = getStartTime().get().format(formatter); + } + + return startTimeString; + } + + protected String getFormattedEndTime() { + String endTimeString = "N/A"; + + if (getEndTime().isPresent()) { + endTimeString = getEndTime().get().format(formatter); + } + + return endTimeString; + } + public String toCSV(int headersCount) { return String.format("%s,%s,%s,%s,%s", id, "TASK", title, status, description); } @Override public int hashCode() { - return Objects.hash(getId(), getTitle(), getDescription(), getStatus()); + return Objects.hash(getId(), getTitle(), getDescription(), + getStatus(), getStartTime(), getDuration(), getEndTime()); } @Override @@ -97,16 +119,23 @@ public boolean equals(Object object) { return (this.id == task.id && Objects.equals(this.title, task.title) && Objects.equals(this.description, task.description) + && Objects.equals(this.getStartTime(), task.getStartTime()) + && Objects.equals(this.duration, task.getDuration()) + && Objects.equals(this.getEndTime(), task.getEndTime()) && this.getStatus() == task.getStatus()); } @Override public String toString() { + return "Task{" + "id=" + getId() + ", title='" + getTitle() + '\'' + ", description.length='" + getDescription().length() + '\'' + ", status=" + getStatus() + + ", startTime=" + getFormatterStartTime() + + ", duration=" + getDuration().toMinutes() + " min" + + ", endTime=" + getFormattedEndTime() + '}'; } } From d4099169e8459e211ed48dea1937d485a69db7c0 Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 01:04:11 +0300 Subject: [PATCH 08/47] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D1=8B=20=D1=81?= =?UTF-8?q?=D0=BE=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F/=D0=B7?= =?UTF-8?q?=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B8=20=D0=B8=D0=B7=20CSV?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/model/SubTask.java | 15 +++++++++++++- src/model/Task.java | 4 +++- src/service/FileBackedTaskManager.java | 28 ++++++++++++++++++++++---- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/model/SubTask.java b/src/model/SubTask.java index 374ea1c..f46939d 100644 --- a/src/model/SubTask.java +++ b/src/model/SubTask.java @@ -1,15 +1,28 @@ package model; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.Objects; public class SubTask extends Task { private final int epicId; - public SubTask(String title, String description, Status status, int epicId) { + protected SubTask(String title, String description, Status status, int epicId) { super(title, description, status); this.epicId = epicId; } + public SubTask(String title, String description, Status status, int epicId, Duration duration) { + this(title, description, status, epicId); + super.setDuration(duration); + } + + public SubTask(String title, String description, Status status, int epicId, + Duration duration, LocalDateTime startTime) { + this(title, description, status, epicId, duration); + super.setStartTime(startTime); + } + public int getEpicId() { return epicId; } diff --git a/src/model/Task.java b/src/model/Task.java index 18e4e2e..4e64d67 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -94,7 +94,9 @@ protected String getFormattedEndTime() { } public String toCSV(int headersCount) { - return String.format("%s,%s,%s,%s,%s", id, "TASK", title, status, description); + return String.format("%s,%s,%s,%s,%s,%s,%s", + id, "TASK", title, status, description, + getFormatterStartTime(), getDuration().toMinutes()); } @Override diff --git a/src/service/FileBackedTaskManager.java b/src/service/FileBackedTaskManager.java index b6d2671..e2f327c 100644 --- a/src/service/FileBackedTaskManager.java +++ b/src/service/FileBackedTaskManager.java @@ -3,6 +3,8 @@ import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.Path; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.ArrayList; import model.*; @@ -12,7 +14,8 @@ public class FileBackedTaskManager extends InMemoryTaskManager implements TaskManager { private final Path saveFilePath; - private final String[] headers = new String[]{"id", "type", "name", "status", "description", "epic"}; + private final String[] headers = new String[]{"id", "type", "name", "status", "description", + "start_time", "duration", "epic"}; public FileBackedTaskManager(IdGenerator idGenerator, HistoryManager historyManager, Path saveFilePath) { super(idGenerator, historyManager); @@ -88,11 +91,19 @@ private String getAllTasksAsCSV() { } public void loadTask(String[] data) { + Task task; String title = data[2]; String description = data[4]; Status status = Status.valueOf(data[3]); int id = Integer.parseInt(data[0]); - Task task = new Task(title, description, status); + Duration duration = Duration.ofMinutes(Long.parseLong(data[6])); + + if (data[5].equals("N/A")) { + task = new Task(title, description, status, duration); + } else { + LocalDateTime startTime = LocalDateTime.parse(data[5], Task.formatter); + task = new Task(title, description, status, duration, startTime); + } createTask(task, id); } @@ -106,12 +117,21 @@ public void loadEpic(String[] data) { } public void loadSubTask(String[] data) { + SubTask subTask; String title = data[2]; String description = data[4]; Status status = Status.valueOf(data[3]); - int epicId = Integer.parseInt(data[5]); + int epicId = Integer.parseInt(data[7]); int id = Integer.parseInt(data[0]); - SubTask subTask = new SubTask(title, description, status, epicId); + Duration duration = Duration.ofMinutes(Long.parseLong(data[6])); + + if (data[5].equals("N/A")) { + subTask = new SubTask(title, description, status, epicId, duration); + } else { + LocalDateTime startTime = LocalDateTime.parse(data[5], Task.formatter); + subTask = new SubTask(title, description, status, epicId, duration, startTime); + } + createSubTask(subTask, id); } From fa70f19cc4bf0c66ab78ac6726a12d1a38e709b1 Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 01:37:39 +0300 Subject: [PATCH 09/47] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=B8=20=D0=BF=D0=BE=D1=84=D0=B8=D0=BA=D1=81?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D0=B8=D0=BC=D0=B8=D1=82=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D1=8E=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82?= =?UTF-8?q?=D0=B5=D0=BB=D1=8C=D1=81=D0=BA=D0=B8=D1=85=20=D1=81=D1=86=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=D1=80=D0=B8=D0=B5=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/Main.java | 15 +++++++---- src/model/Epic.java | 26 +++++++++++++++---- src/model/Task.java | 26 ++++++++++++------- src/service/FileBackedTaskManager.java | 11 +++++--- src/service/InMemoryTaskManager.java | 24 +++++++++++------ .../utils/TaskStartTimeComparator.java | 2 +- 6 files changed, 71 insertions(+), 33 deletions(-) diff --git a/src/app/Main.java b/src/app/Main.java index b609b10..48bd7f8 100644 --- a/src/app/Main.java +++ b/src/app/Main.java @@ -1,5 +1,8 @@ package app; +import java.time.Duration; +import java.time.LocalDateTime; + import model.*; import service.Managers; import service.TaskManager; @@ -42,16 +45,18 @@ public static void main(String[] args) { private static TaskManager getTaskManager() { TaskManager manager = Managers.getDefault(); - Task taskA = new Task("Задача A", "Описание задачи A", Status.NEW); - Task taskB = new Task("Задача B", "Описание задачи B", Status.DONE); + Task taskA = new Task("Задача A", "Описание задачи A", Status.NEW, + Duration.ofMinutes(100), LocalDateTime.now().plus(Duration.ofMinutes(200))); + Task taskB = new Task("Задача B", "Описание задачи B", Status.DONE, + Duration.ofMinutes(15), LocalDateTime.now()); Epic epicA = new Epic("Эпик A", "Описание эпика с тремя подзадачами"); Epic epicB = new Epic("Эпик B", "Описание эпика без подзадач"); SubTask subTaskA = new SubTask("Подзадача A1", "Подзадача 1 эпика A", - Status.NEW, 3); + Status.NEW, 3, Duration.ofMinutes(100), LocalDateTime.now().plus(Duration.ofMinutes(300))); SubTask subTaskB = new SubTask("Подзадача A2", "Подзадача 2 эпика A", - Status.DONE, 3); + Status.DONE, 3, Duration.ofMinutes(42), LocalDateTime.now().plus(Duration.ofHours(4))); SubTask subTaskC = new SubTask("Подзадача A3", "Подзадача 3 эпика A", - Status.NEW, 3); + Status.NEW, 3, Duration.ofMinutes(50), LocalDateTime.now().plus(Duration.ofDays(1))); manager.createTask(taskA); // id = 1 manager.createTask(taskB); // id = 2 diff --git a/src/model/Epic.java b/src/model/Epic.java index 34ade9d..9039bce 100644 --- a/src/model/Epic.java +++ b/src/model/Epic.java @@ -1,6 +1,7 @@ package model; -import java.time.*; +import java.time.Duration; +import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; @@ -73,12 +74,20 @@ public void updateTimeFrame(TreeSet sortedSubTasks) { Duration totalDuration = Duration.ofMinutes( allSubTasks.stream() - .reduce(0L, (subtotal, subTask) -> subtotal + subTask.getDuration().toMinutes(), Long::sum) + .reduce(0L, (subtotal, subTask) -> subtotal + subTask.getDuration().toMinutes(), Long::sum) ); - LocalDateTime startTime = allSubTasks.getFirst().getStartTime().get(); + + LocalDateTime startTime; + if (allSubTasks.isEmpty()) { + startTime = null; + setEndTime(null); + } else { + startTime = allSubTasks.getFirst().getStartTime().get(); + setEndTime(startTime.plus(totalDuration)); + } setStartTime(startTime); setDuration(totalDuration); - setEndTime(startTime.plus(totalDuration)); + } @Override @@ -136,6 +145,13 @@ public boolean equals(Object object) { @Override public String toString() { + String durationString; + + try { + durationString = String.valueOf(super.getDuration().toMinutes()); + } catch (NullPointerException e) { + durationString = "N/A"; + } return "Epic{" + "subTaskIdList=" + getSubTaskIdList() + ", id=" + super.getId() + @@ -143,7 +159,7 @@ public String toString() { ", description.length='" + super.getDescription().length() + '\'' + ", status=" + getStatus() + ", startTime=" + super.getFormatterStartTime() + - ", duration=" + super.getDuration().toMinutes() + " min" + + ", duration=" + durationString + " min" + ", endTime=" + super.getFormattedEndTime() + '}'; } diff --git a/src/model/Task.java b/src/model/Task.java index 4e64d67..5e22745 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -7,7 +7,7 @@ import java.util.Optional; public class Task { - public final static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm dd.MM.yyyy"); + public final static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm dd.MM.yyyy"); private final String title; private final String description; @@ -23,8 +23,8 @@ protected Task(String title, String description, Status status) { } public Task(String title, String description, Status status, Duration duration) { - this(title, description, status); - this.duration = duration; + this(title, description, status); + this.duration = duration; } public Task(String title, String description, Status status, Duration duration, LocalDateTime startTime) { @@ -57,22 +57,22 @@ public Optional getEndTime() { .map(time -> time.plus(duration)); } - public void setStartTime(LocalDateTime startTime) { - this.startTime = startTime; + public Duration getDuration() { + return duration; } protected void setDuration(Duration duration) { this.duration = duration; } - public Duration getDuration() { - return duration; - } - public Optional getStartTime() { return Optional.ofNullable(startTime); } + public void setStartTime(LocalDateTime startTime) { + this.startTime = startTime; + } + protected String getFormatterStartTime() { String startTimeString = "N/A"; @@ -94,9 +94,15 @@ protected String getFormattedEndTime() { } public String toCSV(int headersCount) { + String duration; + try { + duration = String.valueOf(getDuration().toMinutes()); + } catch (NullPointerException e) { + duration = "0"; + } return String.format("%s,%s,%s,%s,%s,%s,%s", id, "TASK", title, status, description, - getFormatterStartTime(), getDuration().toMinutes()); + getFormatterStartTime(), duration); } @Override diff --git a/src/service/FileBackedTaskManager.java b/src/service/FileBackedTaskManager.java index e2f327c..3bf869a 100644 --- a/src/service/FileBackedTaskManager.java +++ b/src/service/FileBackedTaskManager.java @@ -14,7 +14,7 @@ public class FileBackedTaskManager extends InMemoryTaskManager implements TaskManager { private final Path saveFilePath; - private final String[] headers = new String[]{"id", "type", "name", "status", "description", + private final String[] headers = new String[]{"id", "type", "title", "status", "description", "start_time", "duration", "epic"}; public FileBackedTaskManager(IdGenerator idGenerator, HistoryManager historyManager, Path saveFilePath) { @@ -30,10 +30,13 @@ public static void main(String[] args) throws IOException { File testFile = File.createTempFile("test", "csv"); testFile.deleteOnExit(); FileBackedTaskManager managerA = Managers.getFileBacked(testFile); - Task taskA = new Task("Задача 1", "Описание задачи 1", Status.NEW); - Task taskB = new Task("Задача 2", "Описание задачи 2", Status.DONE); + Task taskA = new Task("Задача 1", "Описание задачи 1", Status.NEW, + Duration.ofMinutes(30), LocalDateTime.now()); + Task taskB = new Task("Задача 2", "Описание задачи 2", Status.DONE, + Duration.ofMinutes(90), LocalDateTime.now()); Epic epicA = new Epic("Эпик 1", "Описание эпика"); - SubTask subTaskA = new SubTask("Подзадача 1", "Описание подзадачи", Status.NEW, 3); + SubTask subTaskA = new SubTask("Подзадача 1", "Описание подзадачи", Status.NEW, + 3, Duration.ofMinutes(10), LocalDateTime.now()); int taskAId = managerA.createTask(taskA); int taskBId = managerA.createTask(taskB); diff --git a/src/service/InMemoryTaskManager.java b/src/service/InMemoryTaskManager.java index 436fdd3..51e0fef 100644 --- a/src/service/InMemoryTaskManager.java +++ b/src/service/InMemoryTaskManager.java @@ -145,9 +145,11 @@ public boolean checkForAnyOverlaps(Task taskA) { @Override public int createTask(Task task) { if (checkForAnyOverlaps(task)) { - System.out.printf("Ошибка добавления задачи %d:" - + " обнаружено наложение времени выполнения. \n" - + "Задача добавлена без указания времени начала выполнения.", task.getId()); + System.out.printf(""" + Ошибка добавления задачи %d:\ + обнаружено наложение времени выполнения.\s + Задача добавлена без указания времени начала выполнения.\s + """, task.getId()); task.setStartTime(null); } @@ -174,9 +176,11 @@ public int createEpic(Epic epic) { @Override public int createSubTask(SubTask subTask) { if (checkForAnyOverlaps(subTask)) { - System.out.printf("Ошибка добавления подзадачи %d:" - + " обнаружено наложение времени выполнения. \n" - + "Подзадача добавлена без указания времени начала выполнения.", subTask.getId()); + System.out.printf(""" + Ошибка добавления подзадачи %d:\ + обнаружено наложение времени выполнения.\s + Подзадача добавлена без указания времени начала выполнения.\s + """, subTask.getId()); subTask.setStartTime(null); } int newId = generateUniqueId(); @@ -282,7 +286,9 @@ public void removeTaskById(int id) { if (allTasks.containsKey(id)) { allTasks.remove(id); historyManager.remove(id); - sortedTasksAndSubTasks.remove(getTaskById(id)); + if (getTaskById(id) != null) { + sortedTasksAndSubTasks.remove(getTaskById(id)); + } } else { System.out.printf("Ошибка при вызове removeTaskById(int id):" + " Невозможно удалить задачу id %d по id: задача не найдена." + "%n", id); @@ -313,7 +319,9 @@ public void removeSubTaskById(int id) { allSubTasks.remove(id); historyManager.remove(id); updateEpicTimeFrame(subTask.getEpicId()); - sortedTasksAndSubTasks.remove(getSubTaskById(id)); + if (getSubTaskById(id) != null) { + sortedTasksAndSubTasks.remove(getSubTaskById(id)); + } } else { System.out.printf("Ошибка при вызове removeSubTaskById(int id): " + "Невозможно удалить подзадачу id %d по id: подзадача не найдена." + "%n", id); diff --git a/src/service/utils/TaskStartTimeComparator.java b/src/service/utils/TaskStartTimeComparator.java index 8372e21..8de467b 100644 --- a/src/service/utils/TaskStartTimeComparator.java +++ b/src/service/utils/TaskStartTimeComparator.java @@ -9,7 +9,7 @@ public class TaskStartTimeComparator implements Comparator { @Override - public int compare(Task o1, Task o2){ + public int compare(Task o1, Task o2) { Optional timeA = o1.getStartTime(); Optional timeB = o2.getStartTime(); From 2c3fe8c73dededf757e6d5fe922cf6499b321b0d Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 02:28:56 +0300 Subject: [PATCH 10/47] =?UTF-8?q?=D0=90=D0=BB=D0=B3=D0=BE=D1=80=D0=B8?= =?UTF-8?q?=D1=82=D0=BC=20=D0=BF=D0=BE=D0=B8=D1=81=D0=BA=D0=B0=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D1=81=D0=B5=D1=87=D0=B5=D0=BD=D0=B8=D0=B9=20?= =?UTF-8?q?=D1=83=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=20=D0=B4=D0=BE=20O(l?= =?UTF-8?q?og(n))?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/model/Task.java | 22 ++++++++++- src/service/InMemoryTaskManager.java | 39 +++++++++++-------- src/service/TaskManager.java | 4 +- .../utils/TaskStartTimeComparator.java | 30 -------------- 4 files changed, 45 insertions(+), 50 deletions(-) delete mode 100644 src/service/utils/TaskStartTimeComparator.java diff --git a/src/model/Task.java b/src/model/Task.java index 5e22745..d4326b2 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -6,7 +6,7 @@ import java.util.Objects; import java.util.Optional; -public class Task { +public class Task implements Comparable { public final static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm dd.MM.yyyy"); private final String title; @@ -105,6 +105,26 @@ public String toCSV(int headersCount) { getFormatterStartTime(), duration); } + @Override + public int compareTo(Task task) { + Optional timeA = this.getStartTime(); + Optional timeB = task.getStartTime(); + + if (timeA.isEmpty() && timeB.isEmpty()) { + return 0; + } + + if (timeA.isPresent() && timeB.isEmpty()) { + return -1; + } + + if (timeA.isEmpty()) { + return 1; + } + + return timeA.get().compareTo(timeB.get()); + } + @Override public int hashCode() { return Objects.hash(getId(), getTitle(), getDescription(), diff --git a/src/service/InMemoryTaskManager.java b/src/service/InMemoryTaskManager.java index 51e0fef..72e7832 100644 --- a/src/service/InMemoryTaskManager.java +++ b/src/service/InMemoryTaskManager.java @@ -1,10 +1,10 @@ package service; +import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; import model.*; -import service.utils.TaskStartTimeComparator; public class InMemoryTaskManager implements TaskManager { protected final Map allTasks = new HashMap<>(); @@ -12,7 +12,7 @@ public class InMemoryTaskManager implements TaskManager { protected final Map allSubTasks = new HashMap<>(); private final IdGenerator idGenerator; private final HistoryManager historyManager; - private TreeSet sortedTasksAndSubTasks = new TreeSet<>(new TaskStartTimeComparator()); + private TreeSet sortedTasksAndSubTasks = new TreeSet<>(); public InMemoryTaskManager(IdGenerator idGenerator, HistoryManager historyManager) { this.idGenerator = idGenerator; @@ -115,7 +115,7 @@ public SubTask getSubTaskById(int id) { @Override public TreeSet getAllSubTasksOfEpic(int id) { - TreeSet subTaskList = new TreeSet<>(new TaskStartTimeComparator()); + TreeSet subTaskList = new TreeSet<>(); Epic epic = getEpicById(id); epic.getSubTaskIdList().forEach(subTaskId -> subTaskList.add(getSubTaskById(subTaskId))); @@ -128,23 +128,30 @@ public TreeSet getPrioritizedTasks() { } @Override - public boolean checkForOverlap(Task a, Task b) { - if (a.getEndTime().isPresent() && b.getStartTime().isPresent()) { - return a.getEndTime().get().isAfter(b.getStartTime().get()); + public boolean checkForOverlaps(Task task) { + if (task.getStartTime().isEmpty() || task.getEndTime().isEmpty()) { + return false; } - return false; - } + LocalDateTime taskStart = task.getStartTime().get(); + LocalDateTime taskEnd = task.getEndTime().get(); - @Override - public boolean checkForAnyOverlaps(Task taskA) { - return getPrioritizedTasks().stream() - .anyMatch(taskB -> checkForOverlap(taskA, taskB)); + Task previousTask = sortedTasksAndSubTasks.floor(task); + if (previousTask != null && previousTask.getEndTime().isPresent()) { + return taskStart.isAfter(previousTask.getEndTime().get()); + } + + Task nextTask = sortedTasksAndSubTasks.ceiling(task); + if (nextTask != null && nextTask.getStartTime().isPresent()) { + return taskEnd.isBefore(nextTask.getStartTime().get()); + } + + return false; } @Override public int createTask(Task task) { - if (checkForAnyOverlaps(task)) { + if (checkForOverlaps(task)) { System.out.printf(""" Ошибка добавления задачи %d:\ обнаружено наложение времени выполнения.\s @@ -175,7 +182,7 @@ public int createEpic(Epic epic) { @Override public int createSubTask(SubTask subTask) { - if (checkForAnyOverlaps(subTask)) { + if (checkForOverlaps(subTask)) { System.out.printf(""" Ошибка добавления подзадачи %d:\ обнаружено наложение времени выполнения.\s @@ -208,7 +215,7 @@ public void addTaskToTreeSet(Task task) { @Override public void updateTask(Task task, int id) { - if (checkForAnyOverlaps(task)) { + if (checkForOverlaps(task)) { System.out.printf("Ошибка обновления задачи %d:" + " обнаружено наложение времени выполнения. \n" + "Задача не была обновлена.", task.getId()); @@ -250,7 +257,7 @@ public void updateEpicTimeFrame(Epic epic) { @Override public void updateSubTask(SubTask subTask, int id) { - if (checkForAnyOverlaps(subTask)) { + if (checkForOverlaps(subTask)) { System.out.printf("Ошибка обновления подзадачи %d:" + " обнаружено наложение времени выполнения. \n" + "Подзадача не была обновлена.", subTask.getId()); diff --git a/src/service/TaskManager.java b/src/service/TaskManager.java index 39eaf7b..fb169ed 100644 --- a/src/service/TaskManager.java +++ b/src/service/TaskManager.java @@ -29,9 +29,7 @@ public interface TaskManager { TreeSet getPrioritizedTasks(); - boolean checkForOverlap(Task a, Task b); - - boolean checkForAnyOverlaps(Task task); + boolean checkForOverlaps(Task task); int createTask(Task task); diff --git a/src/service/utils/TaskStartTimeComparator.java b/src/service/utils/TaskStartTimeComparator.java deleted file mode 100644 index 8de467b..0000000 --- a/src/service/utils/TaskStartTimeComparator.java +++ /dev/null @@ -1,30 +0,0 @@ -package service.utils; - -import java.time.LocalDateTime; -import java.util.Comparator; -import java.util.Optional; - -import model.Task; - -public class TaskStartTimeComparator implements Comparator { - - @Override - public int compare(Task o1, Task o2) { - Optional timeA = o1.getStartTime(); - Optional timeB = o2.getStartTime(); - - if (timeA.isEmpty() && timeB.isEmpty()) { - return 0; - } - - if (timeA.isPresent() && timeB.isEmpty()) { - return -1; - } - - if (timeA.isEmpty()) { - return 1; - } - - return timeA.get().compareTo(timeB.get()); - } -} From a8b79d40ea2aa8df8e7d556ee8a235601970071b Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 02:37:44 +0300 Subject: [PATCH 11/47] =?UTF-8?q?=D0=90=D0=BB=D0=B3=D0=BE=D1=80=D0=B8?= =?UTF-8?q?=D1=82=D0=BC=20=D0=BF=D0=BE=D0=B8=D1=81=D0=BA=D0=B0=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D1=81=D0=B5=D1=87=D0=B5=D0=BD=D0=B8=D0=B9=20?= =?UTF-8?q?=D1=83=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=20=D0=B4=D0=BE=20O(l?= =?UTF-8?q?og(n))?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/InMemoryTaskManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/service/InMemoryTaskManager.java b/src/service/InMemoryTaskManager.java index 72e7832..fd1731b 100644 --- a/src/service/InMemoryTaskManager.java +++ b/src/service/InMemoryTaskManager.java @@ -138,12 +138,12 @@ public boolean checkForOverlaps(Task task) { Task previousTask = sortedTasksAndSubTasks.floor(task); if (previousTask != null && previousTask.getEndTime().isPresent()) { - return taskStart.isAfter(previousTask.getEndTime().get()); + return taskStart.isBefore(previousTask.getEndTime().get()); } Task nextTask = sortedTasksAndSubTasks.ceiling(task); if (nextTask != null && nextTask.getStartTime().isPresent()) { - return taskEnd.isBefore(nextTask.getStartTime().get()); + return taskEnd.isAfter(nextTask.getStartTime().get()); } return false; From 67571bc9384829d3c231f15ac2aaad9678f530f8 Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 04:32:43 +0300 Subject: [PATCH 12/47] =?UTF-8?q?=D0=92=D0=BE=D0=B7=D0=B2=D1=80=D0=B0?= =?UTF-8?q?=D1=89=D0=B0=D1=82=D1=8C=20Optional=20=D0=B2=20=D0=BC=D0=B5?= =?UTF-8?q?=D1=82=D0=BE=D0=B4=D0=B0=D1=85=20=D0=BF=D0=BE=D0=B8=D1=81=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=87=20=D0=B8=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=B4=D0=B7=D0=B0=D0=B4=D0=B0=D1=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/InMemoryTaskManager.java | 40 +++++++++++++++------------- src/service/TaskManager.java | 4 +-- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/service/InMemoryTaskManager.java b/src/service/InMemoryTaskManager.java index fd1731b..b9686f4 100644 --- a/src/service/InMemoryTaskManager.java +++ b/src/service/InMemoryTaskManager.java @@ -79,14 +79,14 @@ public void removeAllSubTasks() { } @Override - public Task getTaskById(int id) { + public Optional getTaskById(int id) { if (allTasks.containsKey(id)) { Task task = allTasks.get(id); historyManager.addTask(task); - return task; + return Optional.of(task); } System.out.println("Ошибка при вызове getTaskById(int id): Задачи с id " + id + " не существует"); - return null; + return Optional.empty(); } @Override @@ -102,14 +102,14 @@ public Epic getEpicById(int id) { } @Override - public SubTask getSubTaskById(int id) { + public Optional getSubTaskById(int id) { if (allSubTasks.containsKey(id)) { SubTask subTask = allSubTasks.get(id); historyManager.addTask(subTask); - return subTask; + return Optional.of(subTask); } else { System.out.println("Ошибка при вызове getSubTaskById(int id): Подзадачи с id " + id + " не существует"); - return null; + return Optional.empty(); } } @@ -118,7 +118,11 @@ public TreeSet getAllSubTasksOfEpic(int id) { TreeSet subTaskList = new TreeSet<>(); Epic epic = getEpicById(id); - epic.getSubTaskIdList().forEach(subTaskId -> subTaskList.add(getSubTaskById(subTaskId))); + epic.getSubTaskIdList().forEach(subTaskId -> { + if (getSubTaskById(subTaskId).isPresent()) { + subTaskList.add(getSubTaskById(subTaskId).get()); + } + }); return subTaskList; } @@ -224,7 +228,9 @@ public void updateTask(Task task, int id) { if (allTasks.containsKey(id)) { task.setId(id); allTasks.put(id, task); - sortedTasksAndSubTasks.remove(getTaskById(id)); + if (getTaskById(id).isPresent()) { + sortedTasksAndSubTasks.remove(getTaskById(id).get()); + } addTaskToTreeSet(task); } else { System.out.printf("Ошибка при вызове updateTask(Task task, int id): " @@ -264,8 +270,8 @@ public void updateSubTask(SubTask subTask, int id) { return; } - if (allSubTasks.containsKey(id)) { - SubTask oldSubTask = getSubTaskById(id); + if (allSubTasks.containsKey(id) && getSubTaskById(id).isPresent()) { + SubTask oldSubTask = getSubTaskById(id).get(); Epic oldEpic = getEpicById(oldSubTask.getEpicId()); Epic newEpic = getEpicById(subTask.getEpicId()); @@ -278,7 +284,7 @@ public void updateSubTask(SubTask subTask, int id) { newEpic.addSubTask(id, subTask.getStatus()); } allSubTasks.put(id, subTask); - sortedTasksAndSubTasks.remove(getSubTaskById(id)); + sortedTasksAndSubTasks.remove(oldSubTask); addTaskToTreeSet(subTask); updateEpicTimeFrame(subTask.getEpicId()); @@ -293,8 +299,8 @@ public void removeTaskById(int id) { if (allTasks.containsKey(id)) { allTasks.remove(id); historyManager.remove(id); - if (getTaskById(id) != null) { - sortedTasksAndSubTasks.remove(getTaskById(id)); + if (getTaskById(id).isPresent()) { + sortedTasksAndSubTasks.remove(getTaskById(id).get()); } } else { System.out.printf("Ошибка при вызове removeTaskById(int id):" @@ -318,17 +324,15 @@ public void removeEpicById(int id) { @Override public void removeSubTaskById(int id) { - if (allSubTasks.containsKey(id)) { - SubTask subTask = getSubTaskById(id); + if (allSubTasks.containsKey(id) && getSubTaskById(id).isPresent()) { + SubTask subTask = getSubTaskById(id).get(); Epic epic = getEpicById(subTask.getEpicId()); epic.unlinkSubTask(id); allSubTasks.remove(id); historyManager.remove(id); updateEpicTimeFrame(subTask.getEpicId()); - if (getSubTaskById(id) != null) { - sortedTasksAndSubTasks.remove(getSubTaskById(id)); - } + sortedTasksAndSubTasks.remove(subTask); } else { System.out.printf("Ошибка при вызове removeSubTaskById(int id): " + "Невозможно удалить подзадачу id %d по id: подзадача не найдена." + "%n", id); diff --git a/src/service/TaskManager.java b/src/service/TaskManager.java index fb169ed..982135b 100644 --- a/src/service/TaskManager.java +++ b/src/service/TaskManager.java @@ -19,11 +19,11 @@ public interface TaskManager { void removeAllSubTasks(); - Task getTaskById(int id); + Optional getTaskById(int id); Epic getEpicById(int id); - SubTask getSubTaskById(int id); + Optional getSubTaskById(int id); Set getAllSubTasksOfEpic(int id); From 2b52421edb354607e0b43a006e8fb4c75474ec48 Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 04:52:33 +0300 Subject: [PATCH 13/47] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=81=D1=82=D0=B0=D1=80=D1=8B=D0=B5?= =?UTF-8?q?=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=BA=D0=BB=D0=B0=D1=81?= =?UTF-8?q?=D1=81=D0=B0=20Task?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/model/TaskTest.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/model/TaskTest.java b/test/model/TaskTest.java index 122136f..35f1120 100644 --- a/test/model/TaskTest.java +++ b/test/model/TaskTest.java @@ -1,5 +1,8 @@ package model; +import java.time.Duration; +import java.time.LocalDateTime; + import org.junit.jupiter.api.*; import static org.junit.jupiter.api.Assertions.*; @@ -33,9 +36,11 @@ void shouldNotConsiderTwoIdenticalTasksWithDifferentIdEqual() { @Test @DisplayName("Метод toCSV() возвращает корректную строку в формате CSV") void shouldReturnValidCSV() { - Task taskA = new Task("Тестовая задача", "Описание тестовой задачи", Status.NEW); + Task taskA = new Task("Тестовая задача", "Описание тестовой задачи", + Status.NEW, Duration.ofMinutes(35), + LocalDateTime.of(2025, 6, 23, 4, 40)); taskA.setId(1); - String expectedCSV = "1,TASK,Тестовая задача,NEW,Описание тестовой задачи"; + String expectedCSV = "1,TASK,Тестовая задача,NEW,Описание тестовой задачи,04:40 23.06.2025,35"; assertEquals(expectedCSV, taskA.toCSV(5)); } From 97c6a050c2b0b911205f23f8a33a76955ad6def1 Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 04:59:14 +0300 Subject: [PATCH 14/47] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=81=D1=82=D0=B0=D1=80=D1=8B=D0=B5?= =?UTF-8?q?=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=BA=D0=BB=D0=B0=D1=81?= =?UTF-8?q?=D1=81=D0=B0=20SubTask?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/model/SubTaskTest.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/model/SubTaskTest.java b/test/model/SubTaskTest.java index c21009b..07a72ae 100644 --- a/test/model/SubTaskTest.java +++ b/test/model/SubTaskTest.java @@ -1,5 +1,8 @@ package model; +import java.time.Duration; +import java.time.LocalDateTime; + import org.junit.jupiter.api.*; import service.*; @@ -57,9 +60,11 @@ void shouldNotLetAddingSubTaskAsItsOwnEpic() { @DisplayName("Метод toCSV() возвращает корректную строку в формате CSV") void shouldReturnValidCSV() { SubTask subTask = new SubTask("Тестовая подзадача", - "Описание тестовой подзадачи", Status.DONE, 4); + "Описание тестовой подзадачи", Status.DONE,4, + Duration.ofMinutes(20), + LocalDateTime.of(2025,6, 23, 4, 56)); subTask.setId(6); - String expectedCSV = "6,SUBTASK,Тестовая подзадача,DONE,Описание тестовой подзадачи,4"; + String expectedCSV = "6,SUBTASK,Тестовая подзадача,DONE,Описание тестовой подзадачи,04:56 23.06.2025,20,4"; assertEquals(expectedCSV, subTask.toCSV(6)); } From 2f65473235ca6119871bb587833f93adf3ef9a53 Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 05:06:53 +0300 Subject: [PATCH 15/47] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=81=D1=82=D0=B0=D1=80=D1=8B=D0=B5=20=D1=82?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D1=8B=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D0=B0?= =?UTF-8?q?=20Task?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/model/TaskTest.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/test/model/TaskTest.java b/test/model/TaskTest.java index 35f1120..20c2841 100644 --- a/test/model/TaskTest.java +++ b/test/model/TaskTest.java @@ -8,14 +8,18 @@ import static org.junit.jupiter.api.Assertions.*; class TaskTest { + private final LocalDateTime testDateTime = LocalDateTime.of(2025, 6, 23, 4, 40); + private final Duration testDuration = Duration.ofMinutes(35); @Test @DisplayName("Две одинаковые задачи должны быть равны при сравнении через equals()") void shouldConsiderTwoIdenticalTasksEqual() { - Task taskA = new Task("Тестовая задача", "Описание тестовой задачи", Status.NEW); + Task taskA = new Task("Тестовая задача", "Описание тестовой задачи", + Status.NEW, testDuration, testDateTime); taskA.setId(1); - Task taskB = new Task("Тестовая задача", "Описание тестовой задачи", Status.NEW); + Task taskB = new Task("Тестовая задача", "Описание тестовой задачи", + Status.NEW, testDuration, testDateTime); taskB.setId(1); assertEquals(taskA, taskB); @@ -25,9 +29,11 @@ void shouldConsiderTwoIdenticalTasksEqual() { @DisplayName("Две одинаковые по содержимому задачи не должны быть равны при разных ID") void shouldNotConsiderTwoIdenticalTasksWithDifferentIdEqual() { - Task taskA = new Task("Тестовая задача", "Описание тестовой задачи", Status.NEW); + Task taskA = new Task("Тестовая задача", "Описание тестовой задачи", + Status.NEW, testDuration, testDateTime); taskA.setId(1); - Task taskB = new Task("Тестовая задача", "Описание тестовой задачи", Status.NEW); + Task taskB = new Task("Тестовая задача", "Описание тестовой задачи", + Status.NEW, testDuration, testDateTime); taskB.setId(2); assertNotEquals(taskA, taskB); @@ -37,8 +43,7 @@ void shouldNotConsiderTwoIdenticalTasksWithDifferentIdEqual() { @DisplayName("Метод toCSV() возвращает корректную строку в формате CSV") void shouldReturnValidCSV() { Task taskA = new Task("Тестовая задача", "Описание тестовой задачи", - Status.NEW, Duration.ofMinutes(35), - LocalDateTime.of(2025, 6, 23, 4, 40)); + Status.NEW, testDuration, testDateTime); taskA.setId(1); String expectedCSV = "1,TASK,Тестовая задача,NEW,Описание тестовой задачи,04:40 23.06.2025,35"; From 053b567fe317dbf972f78de549c0f703f6c21f4b Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 05:12:53 +0300 Subject: [PATCH 16/47] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=81=D1=82=D0=B0=D1=80=D1=8B=D0=B5=20=D1=82?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D1=8B=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D0=B0?= =?UTF-8?q?=20SubTask?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/model/SubTaskTest.java | 21 +++++++++++++-------- test/model/TaskTest.java | 4 ++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/test/model/SubTaskTest.java b/test/model/SubTaskTest.java index 07a72ae..b324fcf 100644 --- a/test/model/SubTaskTest.java +++ b/test/model/SubTaskTest.java @@ -20,11 +20,13 @@ static void initEnv() { @DisplayName("Две одинаковых подзадачи должны быть равны при сравнении через equals()") void shouldConsiderTwoIdenticalSubTasksEqual() { SubTask subTaskA = new SubTask("Тестовая подзадача", - "Описание тестовой подзадачи", Status.NEW, 1); + "Описание тестовой подзадачи", Status.NEW, 1, + TaskTest.testDuration, TaskTest.testDateTime); subTaskA.setId(1); SubTask subTaskB = new SubTask("Тестовая подзадача", - "Описание тестовой подзадачи", Status.NEW, 1); + "Описание тестовой подзадачи", Status.NEW, 1, + TaskTest.testDuration, TaskTest.testDateTime); subTaskB.setId(1); assertEquals(subTaskA, subTaskB); @@ -34,11 +36,13 @@ void shouldConsiderTwoIdenticalSubTasksEqual() { @DisplayName("Две одинаковых по содержанию подзадачи не должны быть равны при разных ID") void shouldNotConsiderTwoIdenticalSubTasksWithDifferentIdEqual() { SubTask subTaskA = new SubTask("Тестовая подзадача", - "Описание тестовой подзадачи", Status.NEW, 1); + "Описание тестовой подзадачи", Status.NEW, 1, + TaskTest.testDuration, TaskTest.testDateTime); subTaskA.setId(1); SubTask subTaskB = new SubTask("Тестовая подзадача", - "Описание тестовой подзадачи", Status.NEW, 1); + "Описание тестовой подзадачи", Status.NEW, 1, + TaskTest.testDuration, TaskTest.testDateTime); subTaskB.setId(2); assertNotEquals(subTaskA, subTaskB); @@ -49,7 +53,8 @@ void shouldNotConsiderTwoIdenticalSubTasksWithDifferentIdEqual() { void shouldNotLetAddingSubTaskAsItsOwnEpic() { taskManager.createEpic(new Epic("Эпик", "Описание эпика")); taskManager.createSubTask(new SubTask("Подзадача 1 эпика 1", - "Описание подзадачи 1 эпика 1", Status.NEW, 1)); + "Описание подзадачи 1 эпика 1", Status.NEW, 1, + TaskTest.testDuration, TaskTest.testDateTime)); assertThrows(NullPointerException.class, () -> taskManager.createSubTask(new SubTask("Подзадача 1 эпика 1", @@ -61,10 +66,10 @@ void shouldNotLetAddingSubTaskAsItsOwnEpic() { void shouldReturnValidCSV() { SubTask subTask = new SubTask("Тестовая подзадача", "Описание тестовой подзадачи", Status.DONE,4, - Duration.ofMinutes(20), - LocalDateTime.of(2025,6, 23, 4, 56)); + TaskTest.testDuration, + TaskTest.testDateTime); subTask.setId(6); - String expectedCSV = "6,SUBTASK,Тестовая подзадача,DONE,Описание тестовой подзадачи,04:56 23.06.2025,20,4"; + String expectedCSV = "6,SUBTASK,Тестовая подзадача,DONE,Описание тестовой подзадачи,04:40 23.06.2025,35,4"; assertEquals(expectedCSV, subTask.toCSV(6)); } diff --git a/test/model/TaskTest.java b/test/model/TaskTest.java index 20c2841..17d3253 100644 --- a/test/model/TaskTest.java +++ b/test/model/TaskTest.java @@ -8,8 +8,8 @@ import static org.junit.jupiter.api.Assertions.*; class TaskTest { - private final LocalDateTime testDateTime = LocalDateTime.of(2025, 6, 23, 4, 40); - private final Duration testDuration = Duration.ofMinutes(35); + protected static final LocalDateTime testDateTime = LocalDateTime.of(2025, 6, 23, 4, 40); + protected static final Duration testDuration = Duration.ofMinutes(35); @Test @DisplayName("Две одинаковые задачи должны быть равны при сравнении через equals()") From 42113d8667aa6bc0f38baa4481952470494d9263 Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 05:21:54 +0300 Subject: [PATCH 17/47] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=81=D1=82=D0=B0=D1=80=D1=8B=D0=B5=20=D1=82?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D1=8B=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D0=B0?= =?UTF-8?q?=20Epic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/model/EpicTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/model/EpicTest.java b/test/model/EpicTest.java index 2dcc9d2..26c0fb6 100644 --- a/test/model/EpicTest.java +++ b/test/model/EpicTest.java @@ -89,7 +89,7 @@ void shouldCreateEpicWithStatus() { @Test @DisplayName("Метод toCSV() возвращает корректную строку в формате CSV") void shouldReturnValidCSV() { - String expectedCSV = "1,EPIC,Тестовый эпик,NEW,Описание тестового эпика"; + String expectedCSV = "1,EPIC,Тестовый эпик,NEW,Описание тестового эпика,N/A,0"; assertEquals(expectedCSV, epicA.toCSV(5)); } From 02f6aaaf8989b3b1eaa5a3ffc22969d7039a5340 Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 05:22:25 +0300 Subject: [PATCH 18/47] Code style --- test/model/EpicTest.java | 3 ++- test/model/SubTaskTest.java | 9 ++++----- test/model/TaskTest.java | 6 ++++-- test/service/FileBackedTaskManagerTest.java | 3 ++- test/service/InMemoryHistoryManagerTest.java | 9 +++++---- test/service/InMemoryTaskManagerTest.java | 6 ++++-- test/service/ManagersTest.java | 3 ++- test/service/utils/UtilsTest.java | 6 ++++-- 8 files changed, 27 insertions(+), 18 deletions(-) diff --git a/test/model/EpicTest.java b/test/model/EpicTest.java index 26c0fb6..8ec8e05 100644 --- a/test/model/EpicTest.java +++ b/test/model/EpicTest.java @@ -4,7 +4,8 @@ import org.junit.jupiter.api.*; -import service.*; +import service.Managers; +import service.TaskManager; import static org.junit.jupiter.api.Assertions.*; diff --git a/test/model/SubTaskTest.java b/test/model/SubTaskTest.java index b324fcf..a85af23 100644 --- a/test/model/SubTaskTest.java +++ b/test/model/SubTaskTest.java @@ -1,10 +1,9 @@ package model; -import java.time.Duration; -import java.time.LocalDateTime; - import org.junit.jupiter.api.*; -import service.*; + +import service.Managers; +import service.TaskManager; import static org.junit.jupiter.api.Assertions.*; @@ -65,7 +64,7 @@ void shouldNotLetAddingSubTaskAsItsOwnEpic() { @DisplayName("Метод toCSV() возвращает корректную строку в формате CSV") void shouldReturnValidCSV() { SubTask subTask = new SubTask("Тестовая подзадача", - "Описание тестовой подзадачи", Status.DONE,4, + "Описание тестовой подзадачи", Status.DONE, 4, TaskTest.testDuration, TaskTest.testDateTime); subTask.setId(6); diff --git a/test/model/TaskTest.java b/test/model/TaskTest.java index 17d3253..888ac91 100644 --- a/test/model/TaskTest.java +++ b/test/model/TaskTest.java @@ -3,9 +3,11 @@ import java.time.Duration; import java.time.LocalDateTime; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; class TaskTest { protected static final LocalDateTime testDateTime = LocalDateTime.of(2025, 6, 23, 4, 40); diff --git a/test/service/FileBackedTaskManagerTest.java b/test/service/FileBackedTaskManagerTest.java index 2b8c5a8..a4d0f87 100644 --- a/test/service/FileBackedTaskManagerTest.java +++ b/test/service/FileBackedTaskManagerTest.java @@ -1,7 +1,8 @@ package service; import java.io.*; -import java.lang.reflect.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import org.junit.jupiter.api.*; diff --git a/test/service/InMemoryHistoryManagerTest.java b/test/service/InMemoryHistoryManagerTest.java index a52785d..107af6c 100644 --- a/test/service/InMemoryHistoryManagerTest.java +++ b/test/service/InMemoryHistoryManagerTest.java @@ -1,10 +1,11 @@ package service; -import model.*; -import service.InMemoryHistoryManager.*; +import java.util.*; + import org.junit.jupiter.api.*; -import java.util.*; +import model.*; +import service.InMemoryHistoryManager.Node; import static org.junit.jupiter.api.Assertions.*; @@ -120,7 +121,7 @@ void shouldBeEqualIfIdentical() { // Намеренное использование assertTrue вместо assertEquals, // чтобы проверить метод equals() - assertTrue(testNodeB.equals(copyOfTestNodeB)); + assertEquals(testNodeB, copyOfTestNodeB); assertNotEquals(testNodeB, testNodeC); } } diff --git a/test/service/InMemoryTaskManagerTest.java b/test/service/InMemoryTaskManagerTest.java index 989d76e..d9f5d44 100644 --- a/test/service/InMemoryTaskManagerTest.java +++ b/test/service/InMemoryTaskManagerTest.java @@ -1,9 +1,11 @@ package service; -import model.*; +import java.util.ArrayList; +import java.util.List; + import org.junit.jupiter.api.*; -import java.util.*; +import model.*; import static org.junit.jupiter.api.Assertions.*; diff --git a/test/service/ManagersTest.java b/test/service/ManagersTest.java index dc0dc1b..915bf62 100644 --- a/test/service/ManagersTest.java +++ b/test/service/ManagersTest.java @@ -2,7 +2,8 @@ import java.io.*; import java.nio.file.Path; -import java.util.*; +import java.util.ArrayList; +import java.util.LinkedList; import org.junit.jupiter.api.*; diff --git a/test/service/utils/UtilsTest.java b/test/service/utils/UtilsTest.java index ba8541e..d23885c 100644 --- a/test/service/utils/UtilsTest.java +++ b/test/service/utils/UtilsTest.java @@ -3,9 +3,11 @@ import java.io.*; import java.util.ArrayList; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; public class UtilsTest { From ea66c335b24a9924742aaddc195f2104a0a93ec3 Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 19:03:50 +0300 Subject: [PATCH 19/47] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BA=D0=BE=D0=BD=D1=81=D1=82=D0=B0=D0=BD=D1=82?= =?UTF-8?q?=D1=8B=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2=D1=8B=D1=85=20?= =?UTF-8?q?=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D0=B9=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20Duration/LocalDateTime?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/common/TestTimeConstants.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 test/common/TestTimeConstants.java diff --git a/test/common/TestTimeConstants.java b/test/common/TestTimeConstants.java new file mode 100644 index 0000000..10529c2 --- /dev/null +++ b/test/common/TestTimeConstants.java @@ -0,0 +1,18 @@ +package common; + +import java.time.Duration; +import java.time.LocalDateTime; + +public class TestTimeConstants { + public static LocalDateTime date1 = LocalDateTime.of(2025, 6, 1, 10,0); + public static LocalDateTime date2 = LocalDateTime.of(2025, 6, 2, 10,0); + public static LocalDateTime date3 = LocalDateTime.of(2025, 6, 3, 10,0); + + public static final Duration duration30 = Duration.ofMinutes(30); + public static final Duration duration60 = Duration.ofHours(1); + public static final Duration duration90 = Duration.ofMinutes(90); + + public TestTimeConstants() { + + } +} From f56bbc6912df397bc291c43b12641256d3b17519 Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 19:04:15 +0300 Subject: [PATCH 20/47] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D0=B8=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D1=81=D1=82=D0=B0=D1=80=D1=8B=D0=B5=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81?= =?UTF-8?q?=D0=B0=20InMemoryTaskManager?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/service/InMemoryTaskManagerTest.java | 49 ++++++++++++----------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/test/service/InMemoryTaskManagerTest.java b/test/service/InMemoryTaskManagerTest.java index d9f5d44..230c2d7 100644 --- a/test/service/InMemoryTaskManagerTest.java +++ b/test/service/InMemoryTaskManagerTest.java @@ -7,13 +7,15 @@ import model.*; +import static common.TestTimeConstants.*; + import static org.junit.jupiter.api.Assertions.*; public class InMemoryTaskManagerTest { - Task task = new Task("Задача", "Описание задачи", Status.NEW); + Task task = new Task("Задача", "Описание задачи", Status.NEW, duration30, date1); Epic epic = new Epic("Эпик", "Описание эпика"); SubTask subTask = new SubTask("Подзадача", "Описание подзадачи", - Status.DONE, 2); + Status.DONE,2, duration60, date2); private TaskManager taskManager; @BeforeEach @@ -27,38 +29,38 @@ void addTasksOfEachType() { @Test @DisplayName("Класс InMemoryTaskManager корректно получает задачи (добавлены в @BeforeEach методе)") void shouldAddTasksCorrectly() { - assertEquals(task, taskManager.getTaskById(1)); + assertEquals(task, taskManager.getTaskById(1).get()); assertEquals(epic, taskManager.getEpicById(2)); - assertEquals(subTask, taskManager.getSubTaskById(3)); + assertEquals(subTask, taskManager.getSubTaskById(3).get()); assertEquals(subTask.getEpicId(), 2); } @Test @DisplayName("Класс InMemoryTaskManager обеспечивает неизменность задачи при добавлении") void shouldNotModifyTaskWhenAdded() { - Task task = new Task("Оригинальная задача", "Описание", Status.NEW); + Task task = new Task("Оригинальная задача", "Описание", Status.NEW, duration90, date3); int addedTaskId = taskManager.createTask(task); - assertEquals(task, taskManager.getTaskById(addedTaskId)); + assertEquals(task, taskManager.getTaskById(addedTaskId).get()); } @Test @DisplayName("Класс InMemoryTaskManager корректно удаляет задачи") void shouldDeleteTaskCorrectly() { taskManager.removeTaskById(1); - assertNull(taskManager.getTaskById(1)); + assertTrue(taskManager.getTaskById(1).isEmpty()); } @Test @DisplayName("Записи о просмотрах удаляются из истории при удалении задачи") void shouldDeleteViewHistoryRecordsCorrectly() { - Task task = taskManager.getTaskById(1); - List expectedHistory = new ArrayList<>(List.of(epic, task)); + Task task = taskManager.getTaskById(1).get(); + List expectedHistory = new ArrayList<>(List.of(epic, subTask, task)); assertEquals(expectedHistory, taskManager.getHistory()); taskManager.removeTaskById(1); - assertEquals(new ArrayList(List.of(epic)), taskManager.getHistory()); + assertEquals(new ArrayList<>(List.of(epic, subTask)), taskManager.getHistory()); } @Test @@ -66,14 +68,14 @@ void shouldDeleteViewHistoryRecordsCorrectly() { void shouldDeleteEpicCorrectly() { taskManager.removeEpicById(2); assertNull(taskManager.getEpicById(2)); - assertNull(taskManager.getSubTaskById(3)); + assertTrue(taskManager.getSubTaskById(3).isEmpty()); } @Test @DisplayName("Класс InMemoryTaskManager корректно удаляет подзадачу из эпика") void shouldDeleteSubTaskCorrectly() { taskManager.removeSubTaskById(3); - assertNull(taskManager.getSubTaskById(3)); + assertTrue(taskManager.getSubTaskById(3).isEmpty()); assertTrue(taskManager.getEpicById(2).getSubTaskIdList().isEmpty()); } @@ -81,15 +83,15 @@ void shouldDeleteSubTaskCorrectly() { @DisplayName("Класс InMemoryTaskManager корректно обновляет задачи") void shouldUpdateTasksCorrectly() { taskManager.updateTask(new Task("Задача новая", "Описание другой задачи", - Status.NEW), 1); + Status.NEW, duration30, date3), 1); assertNotEquals(task, taskManager.getTaskById(1)); taskManager.updateEpic(new Epic("Эпик новый", "Описание другого эпика"), 2); - assertNotEquals(task, taskManager.getEpicById(2)); + assertNotEquals(epic, taskManager.getEpicById(2)); assertEquals(subTask.getId(), taskManager.getEpicById(2).getSubTaskIdList().getFirst()); taskManager.updateSubTask(new SubTask("Подзадача новая", "Описание другой подзадачи", - Status.NEW, 2), 3); + Status.NEW, 2, duration90, date1), 3); assertNotEquals(subTask, taskManager.getSubTaskById(3)); } @@ -97,21 +99,22 @@ void shouldUpdateTasksCorrectly() { @DisplayName("История просмотров сохраняет состояние задачи на момент её просмотра") void shouldPreserveTaskStateAsWhenAdded() { TaskManager taskManager = Managers.getDefault(); - Task originalTask = new Task("Оригинал", "Описание оригинала", Status.NEW); + Task originalTask = new Task("Оригинал", "Описание оригинала", Status.NEW, duration90, date3); // Добавляем задачу в менеджер и дёргаем get, чтобы она попала в историю int addedTaskId = taskManager.createTask(originalTask); - taskManager.getTaskById(1); + taskManager.getTaskById(addedTaskId).get(); // Проверяем, что первая (единственная) запись в истории - исходная задача assertEquals(taskManager.getHistory().getFirst(), originalTask); // Создаём обновлённую задачу и через updateTask заменяем исходную задачу в менеджере - Task updatedTask = new Task("Уже не оригинал", "Другое описание", Status.IN_PROGRESS); + Task updatedTask = new Task("Уже не оригинал", "Другое описание", + Status.IN_PROGRESS, duration30, date2); taskManager.updateTask(updatedTask, addedTaskId); // Проверяем, что в менеджере лежит уже обновлённая задача + дёргаем get, чтобы обновить историю - assertEquals(updatedTask, taskManager.getTaskById(1)); + assertEquals(updatedTask, taskManager.getTaskById(addedTaskId).get()); // Проверяем, что первая (единственная) запись в истории - обновлённая задача assertEquals(taskManager.getHistory().getFirst(), updatedTask); @@ -121,15 +124,15 @@ void shouldPreserveTaskStateAsWhenAdded() { @DisplayName("InMemoryTaskManager проверяет сгенерированный ID на уникальность при добавлении задачи") void shouldAvoidExistingIdConflict() { int existingTaskId = taskManager.createTask(task); - Task existingTask = taskManager.getTaskById(existingTaskId); + Task existingTask = taskManager.getTaskById(existingTaskId).get(); - Task newTask = new Task("Задача", "Описание", Status.NEW); + Task newTask = new Task("Задача", "Описание", Status.NEW, duration60, date2); newTask.setId(existingTaskId); int newTaskId = taskManager.createTask(newTask); assertNotEquals(existingTaskId, newTaskId); - assertEquals(existingTask, taskManager.getTaskById(existingTaskId)); - assertEquals(newTask, taskManager.getTaskById(newTaskId)); + assertEquals(existingTask, taskManager.getTaskById(existingTaskId).get()); + assertEquals(newTask, taskManager.getTaskById(newTaskId).get()); } } From f6d449ce9d767307530d8dedb421105efcbb187f Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 19:56:21 +0300 Subject: [PATCH 21/47] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D0=B8=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D1=81=D1=82=D0=B0=D1=80=D1=8B=D0=B5=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81?= =?UTF-8?q?=D0=B0=20Managers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/service/ManagersTest.java | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/test/service/ManagersTest.java b/test/service/ManagersTest.java index 915bf62..6747809 100644 --- a/test/service/ManagersTest.java +++ b/test/service/ManagersTest.java @@ -15,6 +15,7 @@ public class ManagersTest { File testFile; + private final int headersCount = 8; @BeforeEach void initTestFile() throws IOException { @@ -53,10 +54,10 @@ void shouldReturnCorrectlyInitializedHistoryManager() { void shouldReturnCorrectlyInitializedFileBackedManager() throws IOException { Path testFilePath = testFile.toPath(); String testFileString = testFile.toString(); - String taskCSV = "1,TASK,Task1,NEW,Description task1,"; + String taskCSV = "1,TASK,Task1,NEW,Description task1,19:20 28.09.2005,40,"; try (BufferedWriter writer = new BufferedWriter(new FileWriter(testFile))) { - writer.write("id,type,name,status,description,epic"); + writer.write("id,type,name,status,description,start_time,duration,epic"); writer.write("\n"); writer.write(taskCSV); } catch (IOException e) { @@ -67,12 +68,12 @@ void shouldReturnCorrectlyInitializedFileBackedManager() throws IOException { FileBackedTaskManager managerFromPath = Managers.getFileBacked(testFilePath); FileBackedTaskManager managerFromString = Managers.getFileBacked(testFileString); - String expectedFromFile = Utils.csvCommaEqualizer(6, - managerFromFile.getTaskById(1).toCSV(6)); - String expectedFromPath = Utils.csvCommaEqualizer(6, - managerFromPath.getTaskById(1).toCSV(6)); - String expectedFromString = Utils.csvCommaEqualizer(6, - managerFromString.getTaskById(1).toCSV(6)); + String expectedFromFile = Utils.csvCommaEqualizer(headersCount, + managerFromFile.getTaskById(1).get().toCSV(headersCount)); + String expectedFromPath = Utils.csvCommaEqualizer(headersCount, + managerFromPath.getTaskById(1).get().toCSV(headersCount)); + String expectedFromString = Utils.csvCommaEqualizer(headersCount, + managerFromString.getTaskById(1).get().toCSV(headersCount)); assertEquals(expectedFromFile, taskCSV); assertEquals(expectedFromPath, taskCSV); @@ -92,10 +93,10 @@ void shouldThrowManagerLoadException() { void shouldCorrectlyLoadFromCSVFile() throws IOException { try (BufferedWriter writer = new BufferedWriter(new FileWriter(testFile))) { writer.write(""" - id,type,name,status,description,epic - 1,TASK,Task1,NEW,Description task1, - 2,EPIC,Epic2,DONE,Description epic2, - 3,SUBTASK,Sub Task2,DONE,Description sub task3,2 + id,type,name,status,description,start_time,duration,epic + 1,TASK,Task1,NEW,Description task1,19:11 06.10.2015,28 + 2,EPIC,Epic2,DONE,Description epic2,,, + 3,SUBTASK,Sub Task2,DONE,Description sub task3,06:15 01.01.2027,900,2 """); } catch (IOException e) { e.printStackTrace(); @@ -103,8 +104,8 @@ void shouldCorrectlyLoadFromCSVFile() throws IOException { FileBackedTaskManager manager = Managers.getFileBacked(testFile); - assertEquals("3,SUBTASK,Sub Task2,DONE,Description sub task3,2", - manager.getSubTaskById(3).toCSV(6)); + assertEquals("3,SUBTASK,Sub Task2,DONE,Description sub task3,06:15 01.01.2027,900,2", + manager.getSubTaskById(3).get().toCSV(headersCount)); } @Test @@ -112,8 +113,8 @@ void shouldCorrectlyLoadFromCSVFile() throws IOException { void shouldThrowManagerLoadExceptionForInvalidCSV() { try (BufferedWriter writer = new BufferedWriter(new FileWriter(testFile))) { writer.write(""" - id,type,name,status,description,epic - 1,INVALID_TYPE,Task1,NEW,Description task1, + id,type,name,status,description,start_time,duration,epic + 1,INVALID_TYPE,Task1,NEW,Description task1,06:15 01.01.2027,90, NOT_A_CSV_LINE """); } catch (IOException e) { From 62622e2ddb4b831943581fbb96823f9ec6be9787 Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 20:15:02 +0300 Subject: [PATCH 22/47] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D0=B8=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D1=81=D1=82=D0=B0=D1=80=D1=8B=D0=B5=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81?= =?UTF-8?q?=D0=B0=20FileBackedTaskManager?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/service/FileBackedTaskManagerTest.java | 57 ++++++++++++--------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/test/service/FileBackedTaskManagerTest.java b/test/service/FileBackedTaskManagerTest.java index a4d0f87..da78ec7 100644 --- a/test/service/FileBackedTaskManagerTest.java +++ b/test/service/FileBackedTaskManagerTest.java @@ -8,6 +8,8 @@ import model.*; +import static common.TestTimeConstants.*; + import static org.junit.jupiter.api.Assertions.*; public class FileBackedTaskManagerTest { @@ -21,10 +23,10 @@ void initTestFile() throws IOException { testSaveFile = File.createTempFile("test", "csv"); testSaveFile.deleteOnExit(); String testCSVData = """ - id,type,name,status,description,epic - 1,TASK,Task1,NEW,Description task1, - 2,EPIC,Epic2,DONE,Description epic2, - 3,SUBTASK,Sub Task2,DONE,Description sub task3,2 + id,type,title,status,description,start_time,duration,epic + 1,TASK,Task1,NEW,Description task1,19:11 06.10.2015,28 + 2,EPIC,Epic2,DONE,Description epic2,,, + 3,SUBTASK,Sub Task2,DONE,Description sub task3,06:15 01.01.2027,900,2 """; try (BufferedWriter writer = new BufferedWriter(new FileWriter(testSaveFile))) { @@ -50,13 +52,14 @@ String readFileContent(File file) throws IOException { void initManager() throws IOException { initTestFile(); manager = Managers.getFileBacked(testSaveFile); - task = new Task("Задача", "Описание задачи", Status.NEW); + task = new Task("Задача", "Описание задачи", Status.NEW, duration30, date1); task.setId(1); epic = new Epic("Эпик", "Описание эпика"); epic.setId(2); - subTask = new SubTask("Подзадача", "Описание подзадачи", Status.DONE, 2); + subTask = new SubTask("Подзадача", "Описание подзадачи", + Status.DONE, 2, duration60, date2); subTask.setId(3); } @@ -76,10 +79,10 @@ void shouldReturnAllTasksInValidCSVString() throws NoSuchMethodException, method.setAccessible(true); String expectedCSV = """ - id,type,name,status,description,epic - 1,TASK,Задача,NEW,Описание задачи, - 2,EPIC,Эпик,NEW,Описание эпика, - 3,SUBTASK,Подзадача,DONE,Описание подзадачи,2 + id,type,title,status,description,start_time,duration,epic + 1,TASK,Задача,NEW,Описание задачи,10:00 01.06.2025,30, + 2,EPIC,Эпик,NEW,Описание эпика,10:00 02.06.2025,60, + 3,SUBTASK,Подзадача,DONE,Описание подзадачи,10:00 02.06.2025,60,2 """; String actualCSV = (String) method.invoke(manager); @@ -93,7 +96,7 @@ void shouldSetCorrectId() throws NoSuchMethodException, InvocationTargetExceptio Method epicMethod = manager.getClass().getDeclaredMethod("createEpic", Epic.class, int.class); Method subTaskMethod = manager.getClass().getDeclaredMethod("createSubTask", SubTask.class, int.class); SubTask subTaskTest = new SubTask("Поздача тест", "Описание подзадачи", - Status.DONE, 100); + Status.DONE, 100, duration90, date3); taskMethod.setAccessible(true); epicMethod.setAccessible(true); subTaskMethod.setAccessible(true); @@ -102,43 +105,47 @@ void shouldSetCorrectId() throws NoSuchMethodException, InvocationTargetExceptio epicMethod.invoke(manager, epic, 100); subTaskMethod.invoke(manager, subTaskTest, 101); - assertEquals(manager.getTaskById(99), task); + assertEquals(manager.getTaskById(99).get(), task); assertEquals(manager.getEpicById(100), epic); - assertEquals(manager.getSubTaskById(101), subTaskTest); + assertEquals(manager.getSubTaskById(101).get(), subTaskTest); } @Test @DisplayName("Методы loadTask/Epic/SubTask корректно создают задачи из массива полей, полученного из CSV") void shouldLoadTasksCorrectly() { - String[] taskCSV = new String[]{"100", "TASK", "Название задачи", "NEW", "Описание задачи"}; + String[] taskCSV = new String[]{"100", "TASK", "Название задачи", "NEW", "Описание задачи", + "10:00 02.06.2025", "60"}; manager.loadTask(taskCSV); - Task task = new Task("Название задачи", "Описание задачи", Status.NEW); + Task task = new Task("Название задачи", "Описание задачи", Status.NEW, duration60, date2); task.setId(100); - String[] epicCSV = new String[]{"101", "EPIC", "Название эпика", "DONE", "Описание эпика"}; + String[] epicCSV = new String[]{"101", "EPIC", "Название эпика", "DONE", "Описание эпика", + "10:00 03.06.2025", "30"}; manager.loadEpic(epicCSV); Epic epic = new Epic("Название эпика", "Описание эпика", Status.DONE); epic.setId(101); - String[] subTaskCSV = new String[]{"102", "SUBTASK", "Название подзадачи", "NEW", "Описание подзадачи", "101"}; + String[] subTaskCSV = new String[]{"102", "SUBTASK", "Название подзадачи", "NEW", "Описание подзадачи", + "10:00 03.06.2025", "30", "101"}; manager.loadSubTask(subTaskCSV); SubTask subTask = new SubTask("Название подзадачи", "Описание подзадачи", - Status.NEW, 101); + Status.NEW, 101, duration30, date3); subTask.setId(102); epic.addSubTask(102, Status.NEW); - assertEquals(manager.getTaskById(100), task); + assertEquals(manager.getTaskById(100).get(), task); assertEquals(manager.getEpicById(101), epic); - assertEquals(manager.getSubTaskById(102), subTask); + assertEquals(manager.getSubTaskById(102).get(), subTask); } @Test @DisplayName("Переопределённые реализации стандартных методов менеджера корректно автосохраняют задачи в файл") void shouldAutosaveCorrectly() { - String taskCSV = "4,TASK,Название задачи,NEW,описание задачи,"; - String subtaskCSV = "5,SUBTASK,Подзадача,NEW,описание,2"; - Task testTask = new Task("Название задачи", "описание задачи", Status.NEW); - SubTask testSubTask = new SubTask("Подзадача", "описание", Status.NEW, 2); + String taskCSV = "4,TASK,Название задачи,NEW,описание задачи,10:00 03.06.2025,30,"; + String subtaskCSV = "5,SUBTASK,Подзадача,NEW,описание,10:00 01.06.2025,60,2"; + Task testTask = new Task("Название задачи", "описание задачи", Status.NEW, duration30, date3); + SubTask testSubTask = new SubTask("Подзадача", "описание", + Status.NEW, 2, duration60, date1); try { String contentBeforeSave = readFileContent(testSaveFile); @@ -166,7 +173,7 @@ void shouldHandleEmptySaveFile() { Managers.getDefaultHistory(), emptyFile); String taskCsv = "1,TASK,Title,NEW,Description,"; - manager.createTask(new Task("Title", "Description", Status.NEW)); + manager.createTask(new Task("Title", "Description", Status.NEW, duration90, date1)); assertTrue(readFileContent(emptyFile).contains(taskCsv)); } catch (IOException e) { From 3f28e8735ccdb6a313ea1ef6014657008c32b9c1 Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 20:24:52 +0300 Subject: [PATCH 23/47] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D0=B8=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D1=81=D1=82=D0=B0=D1=80=D1=8B=D0=B5=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81?= =?UTF-8?q?=D0=B0=20InMemoryHistoryManager?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/service/InMemoryHistoryManagerTest.java | 28 ++++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/test/service/InMemoryHistoryManagerTest.java b/test/service/InMemoryHistoryManagerTest.java index 107af6c..ab11b66 100644 --- a/test/service/InMemoryHistoryManagerTest.java +++ b/test/service/InMemoryHistoryManagerTest.java @@ -8,12 +8,13 @@ import service.InMemoryHistoryManager.Node; import static org.junit.jupiter.api.Assertions.*; +import static common.TestTimeConstants.*; public class InMemoryHistoryManagerTest { - private static final Task task = new Task("Задача", "Описание задачи", Status.NEW); + private static final Task task = new Task("Задача", "Описание задачи", Status.NEW, duration30, date1); private static final Epic epic = new Epic("Эпик", "Описание эпика"); private static final SubTask subTask = new SubTask("Подзадача", "Описание подзадачи", - Status.DONE, 2); + Status.DONE, 2, duration60, date2); private HistoryManager historyManager; @BeforeEach @@ -37,10 +38,27 @@ void shouldAddTasksToHistory() { @Test @DisplayName("Задачи корректно удаляются из истории по ID задачи") void shouldRemoveViewRecordByTaskId() { - List expectedHistory = new ArrayList<>(List.of(task, subTask)); + // Из начала истории + List expectedHistory = new ArrayList<>(List.of(epic, subTask)); + historyManager.remove(1); + + assertEquals(expectedHistory, historyManager.getHistory()); + + initHistoryManager(); + + // Из середины истории + expectedHistory = new ArrayList<>(List.of(task, subTask)); historyManager.remove(2); assertEquals(expectedHistory, historyManager.getHistory()); + + initHistoryManager(); + + // Из конца истории + expectedHistory = new ArrayList<>(List.of(task, epic)); + historyManager.remove(3); + + assertEquals(expectedHistory, historyManager.getHistory()); } @Test @@ -57,7 +75,7 @@ void shouldKeepOnlyUniqueLatestViews() { // Обновление записи из начала истории (head node) initHistoryManager(); - Task updatedTask = new Task("Задача", "Описание задачи", Status.DONE); + Task updatedTask = new Task("Задача", "Описание задачи", Status.DONE, duration30, date1); updatedTask.setId(1); expectedHistory = new ArrayList<>(List.of(epic, subTask, updatedTask)); @@ -68,7 +86,7 @@ void shouldKeepOnlyUniqueLatestViews() { // Обновление записи из конца истории (tail node) initHistoryManager(); Task updatedSubTask = new SubTask("Подзадача", "Описание подзадачи", - Status.NEW, 2); + Status.NEW, 2, duration60, date2); updatedSubTask.setId(3); expectedHistory = new ArrayList<>(List.of(task, epic, updatedSubTask)); From 5c66a6f9d6a266af9c9e2c7c30ca3749ddfef125 Mon Sep 17 00:00:00 2001 From: Petr Date: Mon, 23 Jun 2025 20:34:07 +0300 Subject: [PATCH 24/47] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B5=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D1=8B=20=D0=B2=20EpicTest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/model/EpicTest.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/model/EpicTest.java b/test/model/EpicTest.java index 8ec8e05..f31a633 100644 --- a/test/model/EpicTest.java +++ b/test/model/EpicTest.java @@ -48,20 +48,33 @@ void shouldUpdateEpicStatusCorrectly() { taskManager.createEpic(epicA); + // NO SUBTASKS = NEW assertEquals(Status.NEW, taskManager.getEpicById(1).getStatus()); + // NEW + NEW = NEW taskManager.createSubTask(new SubTask("Подзадача", "Описание подзадачи", Status.NEW, 1)); taskManager.createSubTask(new SubTask("Подзадача", "Описание подзадачи", Status.NEW, 1)); assertEquals(Status.NEW, taskManager.getEpicById(1).getStatus()); + // IN_PROGRESS + IN_PROGRESS = IN_PROGRESS taskManager.updateSubTask(new SubTask("Подзадача", - "Описание подзадачи", Status.DONE, 1), 2); + "Описание подзадачи", Status.IN_PROGRESS, 1), 2); + taskManager.updateSubTask(new SubTask("Подзадача", + "Описание подзадачи", Status.IN_PROGRESS, 1), 3); assertEquals(Status.IN_PROGRESS, taskManager.getEpicById(1).getStatus()); + // NEW + DONE = IN_PROGRESS + taskManager.updateSubTask(new SubTask("Подзадача", + "Описание подзадачи", Status.NEW, 1), 2); taskManager.updateSubTask(new SubTask("Подзадача", "Описание подзадачи", Status.DONE, 1), 3); + assertEquals(Status.IN_PROGRESS, taskManager.getEpicById(1).getStatus()); + + // DONE + DONE = DONE + taskManager.updateSubTask(new SubTask("Подзадача", + "Описание подзадачи", Status.DONE, 1), 2); assertEquals(Status.DONE, taskManager.getEpicById(1).getStatus()); } From 590636cb989fb2fb9e5e03de1066360cd7568819 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 00:35:12 +0300 Subject: [PATCH 25/47] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B5=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D1=8B=20=D0=B2=20TaskTest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/model/TaskTest.java | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/test/model/TaskTest.java b/test/model/TaskTest.java index 888ac91..9a0f9c4 100644 --- a/test/model/TaskTest.java +++ b/test/model/TaskTest.java @@ -3,8 +3,7 @@ import java.time.Duration; import java.time.LocalDateTime; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; @@ -12,14 +11,17 @@ class TaskTest { protected static final LocalDateTime testDateTime = LocalDateTime.of(2025, 6, 23, 4, 40); protected static final Duration testDuration = Duration.ofMinutes(35); + private final Task taskA = new Task("Тестовая задача", "Описание тестовой задачи", + Status.NEW, testDuration, testDateTime); + + @BeforeEach + void initTask() { + taskA.setId(1); + } @Test @DisplayName("Две одинаковые задачи должны быть равны при сравнении через equals()") void shouldConsiderTwoIdenticalTasksEqual() { - - Task taskA = new Task("Тестовая задача", "Описание тестовой задачи", - Status.NEW, testDuration, testDateTime); - taskA.setId(1); Task taskB = new Task("Тестовая задача", "Описание тестовой задачи", Status.NEW, testDuration, testDateTime); taskB.setId(1); @@ -31,9 +33,6 @@ void shouldConsiderTwoIdenticalTasksEqual() { @DisplayName("Две одинаковые по содержимому задачи не должны быть равны при разных ID") void shouldNotConsiderTwoIdenticalTasksWithDifferentIdEqual() { - Task taskA = new Task("Тестовая задача", "Описание тестовой задачи", - Status.NEW, testDuration, testDateTime); - taskA.setId(1); Task taskB = new Task("Тестовая задача", "Описание тестовой задачи", Status.NEW, testDuration, testDateTime); taskB.setId(2); @@ -44,12 +43,18 @@ void shouldNotConsiderTwoIdenticalTasksWithDifferentIdEqual() { @Test @DisplayName("Метод toCSV() возвращает корректную строку в формате CSV") void shouldReturnValidCSV() { - Task taskA = new Task("Тестовая задача", "Описание тестовой задачи", - Status.NEW, testDuration, testDateTime); - taskA.setId(1); + String expectedCSV = "1,TASK,Тестовая задача,NEW,Описание тестовой задачи,04:40 23.06.2025,35"; assertEquals(expectedCSV, taskA.toCSV(5)); } + @Test + @DisplayName("Время окончания задачи должно расчитываться корректно") + void shouldCalculateEndTimeCorrectly() { + LocalDateTime expectedEndTime = testDateTime.plus(testDuration); + + assertEquals(expectedEndTime, taskA.getEndTime().get()); + } + } \ No newline at end of file From d92056fd243e7bf3df8433456e23b7b65f2705a1 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 01:00:57 +0300 Subject: [PATCH 26/47] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B5=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D1=8B=20=D0=B2=20EpicTest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/model/Epic.java | 12 ++++++++++-- test/model/EpicTest.java | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/model/Epic.java b/src/model/Epic.java index 9039bce..5645041 100644 --- a/src/model/Epic.java +++ b/src/model/Epic.java @@ -74,7 +74,9 @@ public void updateTimeFrame(TreeSet sortedSubTasks) { Duration totalDuration = Duration.ofMinutes( allSubTasks.stream() - .reduce(0L, (subtotal, subTask) -> subtotal + subTask.getDuration().toMinutes(), Long::sum) + .reduce( + 0L, + (subtotal, subTask) -> subtotal + subTask.getDuration().toMinutes(), Long::sum) ); LocalDateTime startTime; @@ -83,13 +85,19 @@ public void updateTimeFrame(TreeSet sortedSubTasks) { setEndTime(null); } else { startTime = allSubTasks.getFirst().getStartTime().get(); - setEndTime(startTime.plus(totalDuration)); + SubTask lastSubTask = allSubTasks.getLast(); + setEndTime(lastSubTask.getStartTime().get().plus(lastSubTask.getDuration())); } setStartTime(startTime); setDuration(totalDuration); } + @Override + public Optional getEndTime() { + return Optional.ofNullable(endTime); + } + @Override public Status getStatus() { boolean isAllNew = true; diff --git a/test/model/EpicTest.java b/test/model/EpicTest.java index f31a633..9dd785e 100644 --- a/test/model/EpicTest.java +++ b/test/model/EpicTest.java @@ -8,6 +8,7 @@ import service.TaskManager; import static org.junit.jupiter.api.Assertions.*; +import static common.TestTimeConstants.*; class EpicTest { private static Epic epicA; @@ -107,4 +108,20 @@ void shouldReturnValidCSV() { assertEquals(expectedCSV, epicA.toCSV(5)); } + @Test + @DisplayName("Время начала/окончание выполнение эпика и его продолжительность рассчитываются корректно") + void shouldCalculateEpicTimeFrameCorrectly() { + TaskManager taskManager = Managers.getDefault(); + + taskManager.createEpic(epicA); + taskManager.createSubTask(new SubTask("Подзадача1", + "Описание подзадачи1", Status.NEW, 1, duration30, date1)); + taskManager.createSubTask(new SubTask("Подзадача2", + "Описание подзадачи2", Status.NEW, 1, duration60, date2)); + + assertEquals(date1, epicA.getStartTime().get()); + assertEquals(date2.plus(duration60), epicA.getEndTime().get()); + assertEquals(duration90, epicA.getDuration()); + } + } \ No newline at end of file From 163fb898af56c768f33fb43ca4249d0f7c80f3c3 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 02:10:51 +0300 Subject: [PATCH 27/47] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D1=82=D0=B5=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...tTimeConstants.java => TestConstants.java} | 12 +++---- test/model/EpicTest.java | 16 ++++----- test/model/SubTaskTest.java | 33 ++++++++++++++----- test/model/TaskTest.java | 15 ++++----- test/service/FileBackedTaskManagerTest.java | 3 +- test/service/InMemoryTaskManagerTest.java | 5 ++- test/service/ManagersTest.java | 2 +- 7 files changed, 49 insertions(+), 37 deletions(-) rename test/common/{TestTimeConstants.java => TestConstants.java} (77%) diff --git a/test/common/TestTimeConstants.java b/test/common/TestConstants.java similarity index 77% rename from test/common/TestTimeConstants.java rename to test/common/TestConstants.java index 10529c2..330c421 100644 --- a/test/common/TestTimeConstants.java +++ b/test/common/TestConstants.java @@ -3,16 +3,16 @@ import java.time.Duration; import java.time.LocalDateTime; -public class TestTimeConstants { - public static LocalDateTime date1 = LocalDateTime.of(2025, 6, 1, 10,0); - public static LocalDateTime date2 = LocalDateTime.of(2025, 6, 2, 10,0); - public static LocalDateTime date3 = LocalDateTime.of(2025, 6, 3, 10,0); - +public class TestConstants { public static final Duration duration30 = Duration.ofMinutes(30); public static final Duration duration60 = Duration.ofHours(1); public static final Duration duration90 = Duration.ofMinutes(90); + public static final int headersCount = 8; + public static LocalDateTime date1 = LocalDateTime.of(2025, 6, 1, 10, 0); + public static LocalDateTime date2 = LocalDateTime.of(2025, 6, 2, 10, 0); + public static LocalDateTime date3 = LocalDateTime.of(2025, 6, 3, 10, 0); - public TestTimeConstants() { + public TestConstants() { } } diff --git a/test/model/EpicTest.java b/test/model/EpicTest.java index 9dd785e..f99854a 100644 --- a/test/model/EpicTest.java +++ b/test/model/EpicTest.java @@ -7,8 +7,8 @@ import service.Managers; import service.TaskManager; +import static common.TestConstants.*; import static org.junit.jupiter.api.Assertions.*; -import static common.TestTimeConstants.*; class EpicTest { private static Epic epicA; @@ -54,28 +54,28 @@ void shouldUpdateEpicStatusCorrectly() { // NEW + NEW = NEW taskManager.createSubTask(new SubTask("Подзадача", - "Описание подзадачи", Status.NEW, 1)); + "Описание подзадачи", Status.NEW, 1, duration60)); taskManager.createSubTask(new SubTask("Подзадача", - "Описание подзадачи", Status.NEW, 1)); + "Описание подзадачи", Status.NEW, 1, duration60)); assertEquals(Status.NEW, taskManager.getEpicById(1).getStatus()); // IN_PROGRESS + IN_PROGRESS = IN_PROGRESS taskManager.updateSubTask(new SubTask("Подзадача", - "Описание подзадачи", Status.IN_PROGRESS, 1), 2); + "Описание подзадачи", Status.IN_PROGRESS, 1, duration60), 2); taskManager.updateSubTask(new SubTask("Подзадача", - "Описание подзадачи", Status.IN_PROGRESS, 1), 3); + "Описание подзадачи", Status.IN_PROGRESS, 1, duration60), 3); assertEquals(Status.IN_PROGRESS, taskManager.getEpicById(1).getStatus()); // NEW + DONE = IN_PROGRESS taskManager.updateSubTask(new SubTask("Подзадача", - "Описание подзадачи", Status.NEW, 1), 2); + "Описание подзадачи", Status.NEW, 1, duration60), 2); taskManager.updateSubTask(new SubTask("Подзадача", - "Описание подзадачи", Status.DONE, 1), 3); + "Описание подзадачи", Status.DONE, 1, duration60), 3); assertEquals(Status.IN_PROGRESS, taskManager.getEpicById(1).getStatus()); // DONE + DONE = DONE taskManager.updateSubTask(new SubTask("Подзадача", - "Описание подзадачи", Status.DONE, 1), 2); + "Описание подзадачи", Status.DONE, 1, duration60), 2); assertEquals(Status.DONE, taskManager.getEpicById(1).getStatus()); } diff --git a/test/model/SubTaskTest.java b/test/model/SubTaskTest.java index a85af23..133ee11 100644 --- a/test/model/SubTaskTest.java +++ b/test/model/SubTaskTest.java @@ -5,6 +5,7 @@ import service.Managers; import service.TaskManager; +import static common.TestConstants.*; import static org.junit.jupiter.api.Assertions.*; class SubTaskTest { @@ -20,12 +21,12 @@ static void initEnv() { void shouldConsiderTwoIdenticalSubTasksEqual() { SubTask subTaskA = new SubTask("Тестовая подзадача", "Описание тестовой подзадачи", Status.NEW, 1, - TaskTest.testDuration, TaskTest.testDateTime); + duration60, date1); subTaskA.setId(1); SubTask subTaskB = new SubTask("Тестовая подзадача", "Описание тестовой подзадачи", Status.NEW, 1, - TaskTest.testDuration, TaskTest.testDateTime); + duration60, date1); subTaskB.setId(1); assertEquals(subTaskA, subTaskB); @@ -36,12 +37,12 @@ void shouldConsiderTwoIdenticalSubTasksEqual() { void shouldNotConsiderTwoIdenticalSubTasksWithDifferentIdEqual() { SubTask subTaskA = new SubTask("Тестовая подзадача", "Описание тестовой подзадачи", Status.NEW, 1, - TaskTest.testDuration, TaskTest.testDateTime); + duration60, date1); subTaskA.setId(1); SubTask subTaskB = new SubTask("Тестовая подзадача", "Описание тестовой подзадачи", Status.NEW, 1, - TaskTest.testDuration, TaskTest.testDateTime); + duration60, date1); subTaskB.setId(2); assertNotEquals(subTaskA, subTaskB); @@ -53,7 +54,7 @@ void shouldNotLetAddingSubTaskAsItsOwnEpic() { taskManager.createEpic(new Epic("Эпик", "Описание эпика")); taskManager.createSubTask(new SubTask("Подзадача 1 эпика 1", "Описание подзадачи 1 эпика 1", Status.NEW, 1, - TaskTest.testDuration, TaskTest.testDateTime)); + duration60, date1)); assertThrows(NullPointerException.class, () -> taskManager.createSubTask(new SubTask("Подзадача 1 эпика 1", @@ -65,11 +66,25 @@ void shouldNotLetAddingSubTaskAsItsOwnEpic() { void shouldReturnValidCSV() { SubTask subTask = new SubTask("Тестовая подзадача", "Описание тестовой подзадачи", Status.DONE, 4, - TaskTest.testDuration, - TaskTest.testDateTime); + duration60, + date1); subTask.setId(6); - String expectedCSV = "6,SUBTASK,Тестовая подзадача,DONE,Описание тестовой подзадачи,04:40 23.06.2025,35,4"; + String expectedCSV = "6,SUBTASK,Тестовая подзадача,DONE,Описание тестовой подзадачи,10:00 01.06.2025,60,4"; - assertEquals(expectedCSV, subTask.toCSV(6)); + assertEquals(expectedCSV, subTask.toCSV(headersCount)); + } + + @Test + @DisplayName("Подзадача может существовать без указания времени начала") + void shouldCreateValidSubtaskWithoutStartTime() { + Epic epic = new Epic("Название эпика", "Описание эпика"); + SubTask subTask = new SubTask("Тестовая подзадача", + "Описание тестовой подзадачи", Status.DONE, 1, duration90); + taskManager.createEpic(epic); + taskManager.createSubTask(subTask); + assertEquals(subTask, taskManager.getSubTaskById(subTask.getId()).get()); + + assertTrue(epic.getStartTime().isEmpty()); + assertEquals(duration90, epic.getDuration()); } } \ No newline at end of file diff --git a/test/model/TaskTest.java b/test/model/TaskTest.java index 9a0f9c4..f36f716 100644 --- a/test/model/TaskTest.java +++ b/test/model/TaskTest.java @@ -1,18 +1,17 @@ package model; -import java.time.Duration; import java.time.LocalDateTime; import org.junit.jupiter.api.*; +import static common.TestConstants.date1; +import static common.TestConstants.duration60; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; class TaskTest { - protected static final LocalDateTime testDateTime = LocalDateTime.of(2025, 6, 23, 4, 40); - protected static final Duration testDuration = Duration.ofMinutes(35); private final Task taskA = new Task("Тестовая задача", "Описание тестовой задачи", - Status.NEW, testDuration, testDateTime); + Status.NEW, duration60, date1); @BeforeEach void initTask() { @@ -23,7 +22,7 @@ void initTask() { @DisplayName("Две одинаковые задачи должны быть равны при сравнении через equals()") void shouldConsiderTwoIdenticalTasksEqual() { Task taskB = new Task("Тестовая задача", "Описание тестовой задачи", - Status.NEW, testDuration, testDateTime); + Status.NEW, duration60, date1); taskB.setId(1); assertEquals(taskA, taskB); @@ -34,7 +33,7 @@ void shouldConsiderTwoIdenticalTasksEqual() { void shouldNotConsiderTwoIdenticalTasksWithDifferentIdEqual() { Task taskB = new Task("Тестовая задача", "Описание тестовой задачи", - Status.NEW, testDuration, testDateTime); + Status.NEW, duration60, date1); taskB.setId(2); assertNotEquals(taskA, taskB); @@ -44,7 +43,7 @@ void shouldNotConsiderTwoIdenticalTasksWithDifferentIdEqual() { @DisplayName("Метод toCSV() возвращает корректную строку в формате CSV") void shouldReturnValidCSV() { - String expectedCSV = "1,TASK,Тестовая задача,NEW,Описание тестовой задачи,04:40 23.06.2025,35"; + String expectedCSV = "1,TASK,Тестовая задача,NEW,Описание тестовой задачи,10:00 01.06.2025,60"; assertEquals(expectedCSV, taskA.toCSV(5)); } @@ -52,7 +51,7 @@ void shouldReturnValidCSV() { @Test @DisplayName("Время окончания задачи должно расчитываться корректно") void shouldCalculateEndTimeCorrectly() { - LocalDateTime expectedEndTime = testDateTime.plus(testDuration); + LocalDateTime expectedEndTime = date1.plus(duration60); assertEquals(expectedEndTime, taskA.getEndTime().get()); } diff --git a/test/service/FileBackedTaskManagerTest.java b/test/service/FileBackedTaskManagerTest.java index da78ec7..7ce7e84 100644 --- a/test/service/FileBackedTaskManagerTest.java +++ b/test/service/FileBackedTaskManagerTest.java @@ -8,8 +8,7 @@ import model.*; -import static common.TestTimeConstants.*; - +import static common.TestConstants.*; import static org.junit.jupiter.api.Assertions.*; public class FileBackedTaskManagerTest { diff --git a/test/service/InMemoryTaskManagerTest.java b/test/service/InMemoryTaskManagerTest.java index 230c2d7..f1763d3 100644 --- a/test/service/InMemoryTaskManagerTest.java +++ b/test/service/InMemoryTaskManagerTest.java @@ -7,15 +7,14 @@ import model.*; -import static common.TestTimeConstants.*; - +import static common.TestConstants.*; import static org.junit.jupiter.api.Assertions.*; public class InMemoryTaskManagerTest { Task task = new Task("Задача", "Описание задачи", Status.NEW, duration30, date1); Epic epic = new Epic("Эпик", "Описание эпика"); SubTask subTask = new SubTask("Подзадача", "Описание подзадачи", - Status.DONE,2, duration60, date2); + Status.DONE, 2, duration60, date2); private TaskManager taskManager; @BeforeEach diff --git a/test/service/ManagersTest.java b/test/service/ManagersTest.java index 6747809..0a2e448 100644 --- a/test/service/ManagersTest.java +++ b/test/service/ManagersTest.java @@ -11,11 +11,11 @@ import service.exceptions.ManagerLoadException; import service.utils.Utils; +import static common.TestConstants.headersCount; import static org.junit.jupiter.api.Assertions.*; public class ManagersTest { File testFile; - private final int headersCount = 8; @BeforeEach void initTestFile() throws IOException { From be9e42fbe0753cdf3e7c24625288905f0f76d1b9 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 02:11:11 +0300 Subject: [PATCH 28/47] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B9=D1=82=20=D1=82?= =?UTF-8?q?=D0=B5=D1=81=D1=82=20=D0=B2=20InMemoryHistoryManagerTest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/service/InMemoryHistoryManagerTest.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/service/InMemoryHistoryManagerTest.java b/test/service/InMemoryHistoryManagerTest.java index ab11b66..f10c137 100644 --- a/test/service/InMemoryHistoryManagerTest.java +++ b/test/service/InMemoryHistoryManagerTest.java @@ -7,8 +7,8 @@ import model.*; import service.InMemoryHistoryManager.Node; +import static common.TestConstants.*; import static org.junit.jupiter.api.Assertions.*; -import static common.TestTimeConstants.*; public class InMemoryHistoryManagerTest { private static final Task task = new Task("Задача", "Описание задачи", Status.NEW, duration30, date1); @@ -95,6 +95,12 @@ void shouldKeepOnlyUniqueLatestViews() { assertEquals(expectedHistory, historyManager.getHistory()); } + @Test + @DisplayName("Пустая история функционирует корректно") + void emptyHistoryWorksCorrectly() { + assertEquals(Managers.getDefault().getHistory(), Managers.getDefaultHistory().getHistory()); + } + @Nested class NodeTest { Node testNodeA = new Node<>("Node A"); From 10b89a21bb2d08f603e9708a33f62c84cb751047 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 02:12:03 +0300 Subject: [PATCH 29/47] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D1=80=D0=B0=D1=81=D1=87=D1=91=D1=82=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B4=D0=BE=D0=BB=D0=B6=D0=B8=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D0=BE=D1=81=D1=82=D0=B8=20=D1=8D=D0=BF=D0=B8?= =?UTF-8?q?=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/model/Epic.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/model/Epic.java b/src/model/Epic.java index 5645041..76eac11 100644 --- a/src/model/Epic.java +++ b/src/model/Epic.java @@ -68,9 +68,7 @@ public void updateSubTask(SubTask subTask) { } public void updateTimeFrame(TreeSet sortedSubTasks) { - TreeSet allSubTasks = sortedSubTasks.stream() - .filter(s -> s.getStartTime().isPresent()) - .collect(Collectors.toCollection(TreeSet::new)); + TreeSet allSubTasks = sortedSubTasks; Duration totalDuration = Duration.ofMinutes( allSubTasks.stream() @@ -79,6 +77,10 @@ public void updateTimeFrame(TreeSet sortedSubTasks) { (subtotal, subTask) -> subtotal + subTask.getDuration().toMinutes(), Long::sum) ); + allSubTasks = sortedSubTasks.stream() + .filter(s -> s.getStartTime().isPresent()) + .collect(Collectors.toCollection(TreeSet::new)); + LocalDateTime startTime; if (allSubTasks.isEmpty()) { startTime = null; @@ -90,7 +92,6 @@ public void updateTimeFrame(TreeSet sortedSubTasks) { } setStartTime(startTime); setDuration(totalDuration); - } @Override From 91ebf133cf1e4a76c76cc880e8e3bd5a2f40e0c7 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 05:01:10 +0300 Subject: [PATCH 30/47] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D1=82=D0=B8=D0=BF=20=D0=B2=D0=BE=D0=B7?= =?UTF-8?q?=D0=B2=D1=80=D0=B0=D1=89=D0=B0=D0=B5=D0=BC=D0=BE=D0=B3=D0=BE=20?= =?UTF-8?q?=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2=20Man?= =?UTF-8?q?agers.getDefault?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/Managers.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service/Managers.java b/src/service/Managers.java index 4e05c8f..e419de8 100644 --- a/src/service/Managers.java +++ b/src/service/Managers.java @@ -10,7 +10,7 @@ public class Managers { - public static TaskManager getDefault() { + public static InMemoryTaskManager getDefault() { IdGenerator idGenerator = new IdGenerator(); HistoryManager historyManager = getDefaultHistory(); From a3a6c3364fa7e29c4029243c356df480b1161c4a Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 05:02:58 +0300 Subject: [PATCH 31/47] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D1=83=20?= =?UTF-8?q?=D0=BE=D0=B1=D0=BD=D0=B0=D1=80=D1=83=D0=B6=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BB=D0=BE=D0=B6=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D1=81=D0=B5=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B8=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=87=D0=B8/?= =?UTF-8?q?=D0=BF=D0=BE=D0=B4=D0=B7=D0=B0=D0=B4=D0=B0=D1=87=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/InMemoryTaskManager.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/service/InMemoryTaskManager.java b/src/service/InMemoryTaskManager.java index b9686f4..3c7d6dd 100644 --- a/src/service/InMemoryTaskManager.java +++ b/src/service/InMemoryTaskManager.java @@ -219,7 +219,10 @@ public void addTaskToTreeSet(Task task) { @Override public void updateTask(Task task, int id) { + sortedTasksAndSubTasks.remove(task); + if (checkForOverlaps(task)) { + sortedTasksAndSubTasks.add(task); System.out.printf("Ошибка обновления задачи %d:" + " обнаружено наложение времени выполнения. \n" + "Задача не была обновлена.", task.getId()); @@ -263,7 +266,10 @@ public void updateEpicTimeFrame(Epic epic) { @Override public void updateSubTask(SubTask subTask, int id) { + sortedTasksAndSubTasks.remove(getSubTaskById(id).get()); + if (checkForOverlaps(subTask)) { + sortedTasksAndSubTasks.add(getSubTaskById(id).get()); System.out.printf("Ошибка обновления подзадачи %d:" + " обнаружено наложение времени выполнения. \n" + "Подзадача не была обновлена.", subTask.getId()); @@ -284,7 +290,6 @@ public void updateSubTask(SubTask subTask, int id) { newEpic.addSubTask(id, subTask.getStatus()); } allSubTasks.put(id, subTask); - sortedTasksAndSubTasks.remove(oldSubTask); addTaskToTreeSet(subTask); updateEpicTimeFrame(subTask.getEpicId()); From cfd684c876282ae48cda57605228a5f9d7997a4d Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 05:03:52 +0300 Subject: [PATCH 32/47] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B2=D1=8B=D1=87=D0=B8=D1=81=D0=BB=D1=8F=D0=B5?= =?UTF-8?q?=D0=BC=D1=8B=D1=85=20=D0=BF=D0=BE=D0=BB=D0=B5=D0=B9=20=D1=8D?= =?UTF-8?q?=D0=BF=D0=B8=D0=BA=D0=B0=20=D0=BF=D1=80=D0=B8=20=D0=B2=D1=8B?= =?UTF-8?q?=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B5=20=D0=B2=20CSV?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/FileBackedTaskManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/service/FileBackedTaskManager.java b/src/service/FileBackedTaskManager.java index 3bf869a..969dccd 100644 --- a/src/service/FileBackedTaskManager.java +++ b/src/service/FileBackedTaskManager.java @@ -78,6 +78,7 @@ private String getAllTasksAsCSV() { for (Task task : allTasks) { if (task instanceof Epic epic) { + epic.updateTimeFrame(getAllSubTasksOfEpic(epic.getId())); result.append( csvCommaEqualizer(headers.length, epic.toCSV(headers.length))); } else if (task instanceof SubTask subTask) { From 103c13eb942546026c67e6cd61e801e64e03a432 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 05:04:57 +0300 Subject: [PATCH 33/47] =?UTF-8?q?=D0=92=D1=8B=D0=BD=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=B8=20=D0=BE=D0=B1=D1=89=D0=B8=D0=B5=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D1=8B=20TaskManager=20=D0=B2=20=D0=B0=D0=B1=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=B0=D0=BA=D1=82=D0=BD=D1=8B=D0=B9=20=D0=BA=D0=BB=D0=B0?= =?UTF-8?q?=D1=81=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/service/FileBackedTaskManagerTest.java | 95 +++++-------- test/service/InMemoryTaskManagerTest.java | 137 +------------------ test/service/TaskManagerTest.java | 142 ++++++++++++++++++++ 3 files changed, 184 insertions(+), 190 deletions(-) create mode 100644 test/service/TaskManagerTest.java diff --git a/test/service/FileBackedTaskManagerTest.java b/test/service/FileBackedTaskManagerTest.java index 7ce7e84..50770b0 100644 --- a/test/service/FileBackedTaskManagerTest.java +++ b/test/service/FileBackedTaskManagerTest.java @@ -3,6 +3,7 @@ import java.io.*; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.Optional; import org.junit.jupiter.api.*; @@ -11,28 +12,12 @@ import static common.TestConstants.*; import static org.junit.jupiter.api.Assertions.*; -public class FileBackedTaskManagerTest { +public class FileBackedTaskManagerTest extends TaskManagerTest { File testSaveFile; - FileBackedTaskManager manager; - Task task; - Epic epic; - SubTask subTask; void initTestFile() throws IOException { testSaveFile = File.createTempFile("test", "csv"); testSaveFile.deleteOnExit(); - String testCSVData = """ - id,type,title,status,description,start_time,duration,epic - 1,TASK,Task1,NEW,Description task1,19:11 06.10.2015,28 - 2,EPIC,Epic2,DONE,Description epic2,,, - 3,SUBTASK,Sub Task2,DONE,Description sub task3,06:15 01.01.2027,900,2 - """; - - try (BufferedWriter writer = new BufferedWriter(new FileWriter(testSaveFile))) { - writer.write(testCSVData); - } catch (IOException e) { - e.printStackTrace(); - } } String readFileContent(File file) throws IOException { @@ -47,34 +32,23 @@ String readFileContent(File file) throws IOException { } } - @BeforeEach - void initManager() throws IOException { - initTestFile(); - manager = Managers.getFileBacked(testSaveFile); - task = new Task("Задача", "Описание задачи", Status.NEW, duration30, date1); - task.setId(1); - - epic = new Epic("Эпик", "Описание эпика"); - epic.setId(2); - - subTask = new SubTask("Подзадача", "Описание подзадачи", - Status.DONE, 2, duration60, date2); - subTask.setId(3); + @Override + protected Optional createTaskManager() { + try { + initTestFile(); + return Optional.of(Managers.getFileBacked(testSaveFile)); + } catch (IOException e) { + System.out.println(e.getMessage()); + return Optional.empty(); + } } @Test @DisplayName("Метод getAllTasksAsCSV возвращает валидное CSV представление всех задач") void shouldReturnAllTasksInValidCSVString() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - // Предварительно очистим менеджер от задач, подгруженных из файла при инициализации - manager.removeAllTasks(); - manager.removeAllEpics(); - - manager.createTask(task); - manager.createEpic(epic); - manager.createSubTask(subTask); - Method method = manager.getClass().getDeclaredMethod("getAllTasksAsCSV"); + Method method = taskManager.getClass().getDeclaredMethod("getAllTasksAsCSV"); method.setAccessible(true); String expectedCSV = """ @@ -83,7 +57,7 @@ void shouldReturnAllTasksInValidCSVString() throws NoSuchMethodException, 2,EPIC,Эпик,NEW,Описание эпика,10:00 02.06.2025,60, 3,SUBTASK,Подзадача,DONE,Описание подзадачи,10:00 02.06.2025,60,2 """; - String actualCSV = (String) method.invoke(manager); + String actualCSV = (String) method.invoke(taskManager); assertEquals(expectedCSV, actualCSV); } @@ -91,22 +65,22 @@ void shouldReturnAllTasksInValidCSVString() throws NoSuchMethodException, @Test @DisplayName("Реализации createTask/Epic/Subtask, принимающие id в параметре, корректно задают переданный id") void shouldSetCorrectId() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Method taskMethod = manager.getClass().getDeclaredMethod("createTask", Task.class, int.class); - Method epicMethod = manager.getClass().getDeclaredMethod("createEpic", Epic.class, int.class); - Method subTaskMethod = manager.getClass().getDeclaredMethod("createSubTask", SubTask.class, int.class); + Method taskMethod = taskManager.getClass().getDeclaredMethod("createTask", Task.class, int.class); + Method epicMethod = taskManager.getClass().getDeclaredMethod("createEpic", Epic.class, int.class); + Method subTaskMethod = taskManager.getClass().getDeclaredMethod("createSubTask", SubTask.class, int.class); SubTask subTaskTest = new SubTask("Поздача тест", "Описание подзадачи", Status.DONE, 100, duration90, date3); taskMethod.setAccessible(true); epicMethod.setAccessible(true); subTaskMethod.setAccessible(true); - taskMethod.invoke(manager, task, 99); - epicMethod.invoke(manager, epic, 100); - subTaskMethod.invoke(manager, subTaskTest, 101); + taskMethod.invoke(taskManager, task, 99); + epicMethod.invoke(taskManager, epic, 100); + subTaskMethod.invoke(taskManager, subTaskTest, 101); - assertEquals(manager.getTaskById(99).get(), task); - assertEquals(manager.getEpicById(100), epic); - assertEquals(manager.getSubTaskById(101).get(), subTaskTest); + assertEquals(taskManager.getTaskById(99).get(), task); + assertEquals(taskManager.getEpicById(100), epic); + assertEquals(taskManager.getSubTaskById(101).get(), subTaskTest); } @Test @@ -114,45 +88,50 @@ void shouldSetCorrectId() throws NoSuchMethodException, InvocationTargetExceptio void shouldLoadTasksCorrectly() { String[] taskCSV = new String[]{"100", "TASK", "Название задачи", "NEW", "Описание задачи", "10:00 02.06.2025", "60"}; - manager.loadTask(taskCSV); + taskManager.loadTask(taskCSV); Task task = new Task("Название задачи", "Описание задачи", Status.NEW, duration60, date2); task.setId(100); String[] epicCSV = new String[]{"101", "EPIC", "Название эпика", "DONE", "Описание эпика", "10:00 03.06.2025", "30"}; - manager.loadEpic(epicCSV); + taskManager.loadEpic(epicCSV); Epic epic = new Epic("Название эпика", "Описание эпика", Status.DONE); epic.setId(101); String[] subTaskCSV = new String[]{"102", "SUBTASK", "Название подзадачи", "NEW", "Описание подзадачи", "10:00 03.06.2025", "30", "101"}; - manager.loadSubTask(subTaskCSV); + taskManager.loadSubTask(subTaskCSV); SubTask subTask = new SubTask("Название подзадачи", "Описание подзадачи", Status.NEW, 101, duration30, date3); subTask.setId(102); epic.addSubTask(102, Status.NEW); - assertEquals(manager.getTaskById(100).get(), task); - assertEquals(manager.getEpicById(101), epic); - assertEquals(manager.getSubTaskById(102).get(), subTask); + assertEquals(taskManager.getTaskById(100).get(), task); + assertEquals(taskManager.getEpicById(101), epic); + assertEquals(taskManager.getSubTaskById(102).get(), subTask); } @Test @DisplayName("Переопределённые реализации стандартных методов менеджера корректно автосохраняют задачи в файл") void shouldAutosaveCorrectly() { String taskCSV = "4,TASK,Название задачи,NEW,описание задачи,10:00 03.06.2025,30,"; - String subtaskCSV = "5,SUBTASK,Подзадача,NEW,описание,10:00 01.06.2025,60,2"; + String subtaskCSV = "5,SUBTASK,Подзадача,NEW,описание,11:00 01.06.2025,60,2"; + Task testTask = new Task("Название задачи", "описание задачи", Status.NEW, duration30, date3); + testTask.setId(4); + SubTask testSubTask = new SubTask("Подзадача", "описание", - Status.NEW, 2, duration60, date1); + Status.NEW, 2, duration60, date1.plus(duration60)); + testSubTask.setId(5); + try { String contentBeforeSave = readFileContent(testSaveFile); assertFalse(contentBeforeSave.contains(taskCSV)); assertFalse(contentBeforeSave.contains(subtaskCSV)); - manager.createTask(testTask); - manager.createSubTask(testSubTask); + taskManager.createTask(testTask); + taskManager.createSubTask(testSubTask); String contentAfterSave = readFileContent(testSaveFile); assertTrue(contentAfterSave.contains(taskCSV)); diff --git a/test/service/InMemoryTaskManagerTest.java b/test/service/InMemoryTaskManagerTest.java index f1763d3..f41e091 100644 --- a/test/service/InMemoryTaskManagerTest.java +++ b/test/service/InMemoryTaskManagerTest.java @@ -1,137 +1,10 @@ package service; -import java.util.ArrayList; -import java.util.List; +import java.util.Optional; -import org.junit.jupiter.api.*; - -import model.*; - -import static common.TestConstants.*; -import static org.junit.jupiter.api.Assertions.*; - -public class InMemoryTaskManagerTest { - Task task = new Task("Задача", "Описание задачи", Status.NEW, duration30, date1); - Epic epic = new Epic("Эпик", "Описание эпика"); - SubTask subTask = new SubTask("Подзадача", "Описание подзадачи", - Status.DONE, 2, duration60, date2); - private TaskManager taskManager; - - @BeforeEach - void addTasksOfEachType() { - taskManager = Managers.getDefault(); - taskManager.createTask(task);// id=1 - taskManager.createEpic(epic); // id=2 - taskManager.createSubTask(subTask); // id=3, epicId=2 - } - - @Test - @DisplayName("Класс InMemoryTaskManager корректно получает задачи (добавлены в @BeforeEach методе)") - void shouldAddTasksCorrectly() { - assertEquals(task, taskManager.getTaskById(1).get()); - assertEquals(epic, taskManager.getEpicById(2)); - assertEquals(subTask, taskManager.getSubTaskById(3).get()); - assertEquals(subTask.getEpicId(), 2); - } - - @Test - @DisplayName("Класс InMemoryTaskManager обеспечивает неизменность задачи при добавлении") - void shouldNotModifyTaskWhenAdded() { - Task task = new Task("Оригинальная задача", "Описание", Status.NEW, duration90, date3); - int addedTaskId = taskManager.createTask(task); - - assertEquals(task, taskManager.getTaskById(addedTaskId).get()); +public class InMemoryTaskManagerTest extends TaskManagerTest { + @Override + protected Optional createTaskManager() { + return Optional.of(Managers.getDefault()); } - - @Test - @DisplayName("Класс InMemoryTaskManager корректно удаляет задачи") - void shouldDeleteTaskCorrectly() { - taskManager.removeTaskById(1); - assertTrue(taskManager.getTaskById(1).isEmpty()); - } - - @Test - @DisplayName("Записи о просмотрах удаляются из истории при удалении задачи") - void shouldDeleteViewHistoryRecordsCorrectly() { - Task task = taskManager.getTaskById(1).get(); - List expectedHistory = new ArrayList<>(List.of(epic, subTask, task)); - - assertEquals(expectedHistory, taskManager.getHistory()); - - taskManager.removeTaskById(1); - assertEquals(new ArrayList<>(List.of(epic, subTask)), taskManager.getHistory()); - } - - @Test - @DisplayName("Класс InMemoryTaskManager корректно удаляет эпики и подзадачи") - void shouldDeleteEpicCorrectly() { - taskManager.removeEpicById(2); - assertNull(taskManager.getEpicById(2)); - assertTrue(taskManager.getSubTaskById(3).isEmpty()); - } - - @Test - @DisplayName("Класс InMemoryTaskManager корректно удаляет подзадачу из эпика") - void shouldDeleteSubTaskCorrectly() { - taskManager.removeSubTaskById(3); - assertTrue(taskManager.getSubTaskById(3).isEmpty()); - assertTrue(taskManager.getEpicById(2).getSubTaskIdList().isEmpty()); - } - - @Test - @DisplayName("Класс InMemoryTaskManager корректно обновляет задачи") - void shouldUpdateTasksCorrectly() { - taskManager.updateTask(new Task("Задача новая", "Описание другой задачи", - Status.NEW, duration30, date3), 1); - assertNotEquals(task, taskManager.getTaskById(1)); - - taskManager.updateEpic(new Epic("Эпик новый", "Описание другого эпика"), 2); - assertNotEquals(epic, taskManager.getEpicById(2)); - assertEquals(subTask.getId(), taskManager.getEpicById(2).getSubTaskIdList().getFirst()); - - taskManager.updateSubTask(new SubTask("Подзадача новая", "Описание другой подзадачи", - Status.NEW, 2, duration90, date1), 3); - assertNotEquals(subTask, taskManager.getSubTaskById(3)); - } - - @Test - @DisplayName("История просмотров сохраняет состояние задачи на момент её просмотра") - void shouldPreserveTaskStateAsWhenAdded() { - TaskManager taskManager = Managers.getDefault(); - Task originalTask = new Task("Оригинал", "Описание оригинала", Status.NEW, duration90, date3); - - // Добавляем задачу в менеджер и дёргаем get, чтобы она попала в историю - int addedTaskId = taskManager.createTask(originalTask); - taskManager.getTaskById(addedTaskId).get(); - - // Проверяем, что первая (единственная) запись в истории - исходная задача - assertEquals(taskManager.getHistory().getFirst(), originalTask); - - // Создаём обновлённую задачу и через updateTask заменяем исходную задачу в менеджере - Task updatedTask = new Task("Уже не оригинал", "Другое описание", - Status.IN_PROGRESS, duration30, date2); - taskManager.updateTask(updatedTask, addedTaskId); - - // Проверяем, что в менеджере лежит уже обновлённая задача + дёргаем get, чтобы обновить историю - assertEquals(updatedTask, taskManager.getTaskById(addedTaskId).get()); - - // Проверяем, что первая (единственная) запись в истории - обновлённая задача - assertEquals(taskManager.getHistory().getFirst(), updatedTask); - } - - @Test - @DisplayName("InMemoryTaskManager проверяет сгенерированный ID на уникальность при добавлении задачи") - void shouldAvoidExistingIdConflict() { - int existingTaskId = taskManager.createTask(task); - Task existingTask = taskManager.getTaskById(existingTaskId).get(); - - Task newTask = new Task("Задача", "Описание", Status.NEW, duration60, date2); - newTask.setId(existingTaskId); - int newTaskId = taskManager.createTask(newTask); - - assertNotEquals(existingTaskId, newTaskId); - assertEquals(existingTask, taskManager.getTaskById(existingTaskId).get()); - assertEquals(newTask, taskManager.getTaskById(newTaskId).get()); - } - } diff --git a/test/service/TaskManagerTest.java b/test/service/TaskManagerTest.java new file mode 100644 index 0000000..69d6ee5 --- /dev/null +++ b/test/service/TaskManagerTest.java @@ -0,0 +1,142 @@ +package service; + +import java.util.*; + +import org.junit.jupiter.api.*; + +import model.*; + +import static common.TestConstants.*; +import static org.junit.jupiter.api.Assertions.*; + +abstract class TaskManagerTest { + protected T taskManager; + protected Task task = new Task("Задача", "Описание задачи", Status.NEW, duration30, date1); + protected Epic epic = new Epic("Эпик", "Описание эпика"); + protected SubTask subTask = new SubTask("Подзадача", "Описание подзадачи", + Status.DONE, 2, duration60, date2); + + protected abstract Optional createTaskManager(); + + @BeforeEach + void init(){ + if (createTaskManager().isPresent()) { + taskManager = createTaskManager().get(); + } else { + throw new RuntimeException("Ошибка создания экземпляра менеджера"); + } + taskManager.createTask(task);// id=1 + taskManager.createEpic(epic); // id=2 + taskManager.createSubTask(subTask); // id=3, epicId=2 + } + + @Test + @DisplayName("TaskManager корректно получает задачи (добавлены в @BeforeEach методе)") + void shouldAddTasksCorrectly() { + assertEquals(task, taskManager.getTaskById(1).get()); + assertEquals(epic, taskManager.getEpicById(2)); + assertEquals(subTask, taskManager.getSubTaskById(3).get()); + assertEquals(subTask.getEpicId(), 2); + } + + @Test + @DisplayName("TaskManager обеспечивает неизменность задачи при добавлении") + void shouldNotModifyTaskWhenAdded() { + Task task = new Task("Оригинальная задача", "Описание", Status.NEW, duration90, date3); + int addedTaskId = taskManager.createTask(task); + + assertEquals(task, taskManager.getTaskById(addedTaskId).get()); + } + + @Test + @DisplayName("TaskManager корректно удаляет задачи") + void shouldDeleteTaskCorrectly() { + taskManager.removeTaskById(1); + assertTrue(taskManager.getTaskById(1).isEmpty()); + } + + @Test + @DisplayName("Записи о просмотрах удаляются из истории при удалении задачи") + void shouldDeleteViewHistoryRecordsCorrectly() { + Task task = taskManager.getTaskById(1).get(); + List expectedHistory = new ArrayList<>(List.of(epic, subTask, task)); + + assertEquals(expectedHistory, taskManager.getHistory()); + + taskManager.removeTaskById(1); + assertEquals(new ArrayList<>(List.of(epic, subTask)), taskManager.getHistory()); + } + + @Test + @DisplayName("TaskManager корректно удаляет эпики и подзадачи") + void shouldDeleteEpicCorrectly() { + taskManager.removeEpicById(2); + assertNull(taskManager.getEpicById(2)); + assertTrue(taskManager.getSubTaskById(3).isEmpty()); + } + + @Test + @DisplayName("TaskManager корректно удаляет подзадачу из эпика") + void shouldDeleteSubTaskCorrectly() { + taskManager.removeSubTaskById(3); + assertTrue(taskManager.getSubTaskById(3).isEmpty()); + assertTrue(taskManager.getEpicById(2).getSubTaskIdList().isEmpty()); + } + + @Test + @DisplayName("TaskManager корректно обновляет задачи") + void shouldUpdateTasksCorrectly() { + taskManager.updateTask(new Task("Задача новая", "Описание другой задачи", + Status.NEW, duration30, date3), 1); + assertNotEquals(task, taskManager.getTaskById(1).get()); + + taskManager.updateEpic(new Epic("Эпик новый", "Описание другого эпика"), 2); + assertNotEquals(epic, taskManager.getEpicById(2)); + assertEquals(subTask.getId(), taskManager.getEpicById(2).getSubTaskIdList().getFirst()); + + taskManager.updateSubTask(new SubTask("Подзадача новая", "Описание другой подзадачи", + Status.NEW, 2, duration60, date2), 3); + assertNotEquals(subTask, taskManager.getSubTaskById(3).get()); + } + + @Test + @DisplayName("История просмотров сохраняет состояние задачи на момент её просмотра") + void shouldPreserveTaskStateAsWhenAdded() { + TaskManager taskManager = Managers.getDefault(); + Task originalTask = new Task("Оригинал", "Описание оригинала", Status.NEW, duration90, date3); + + // Добавляем задачу в менеджер и дёргаем get, чтобы она попала в историю + int addedTaskId = taskManager.createTask(originalTask); + taskManager.getTaskById(addedTaskId).get(); + + // Проверяем, что первая (единственная) запись в истории - исходная задача + assertEquals(taskManager.getHistory().getFirst(), originalTask); + + // Создаём обновлённую задачу и через updateTask заменяем исходную задачу в менеджере + Task updatedTask = new Task("Уже не оригинал", "Другое описание", + Status.IN_PROGRESS, duration30, date2); + taskManager.updateTask(updatedTask, addedTaskId); + + // Проверяем, что в менеджере лежит уже обновлённая задача + дёргаем get, чтобы обновить историю + assertEquals(updatedTask, taskManager.getTaskById(addedTaskId).get()); + + // Проверяем, что первая (единственная) запись в истории - обновлённая задача + assertEquals(taskManager.getHistory().getFirst(), updatedTask); + } + + @Test + @DisplayName("InMemoryTaskManager проверяет сгенерированный ID на уникальность при добавлении задачи") + void shouldAvoidExistingIdConflict() { + int existingTaskId = taskManager.createTask(task); + Task existingTask = taskManager.getTaskById(existingTaskId).get(); + + Task newTask = new Task("Задача", "Описание", Status.NEW, duration60, date2); + newTask.setId(existingTaskId); + int newTaskId = taskManager.createTask(newTask); + + assertNotEquals(existingTaskId, newTaskId); + assertEquals(existingTask, taskManager.getTaskById(existingTaskId).get()); + assertEquals(newTask, taskManager.getTaskById(newTaskId).get()); + } + +} \ No newline at end of file From 6d4b85aa137cf6269314cac26df495007bf48a0d Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 05:06:29 +0300 Subject: [PATCH 34/47] Code style --- src/model/Epic.java | 18 +++++++++--------- test/service/FileBackedTaskManagerTest.java | 3 ++- test/service/TaskManagerTest.java | 4 ++-- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/model/Epic.java b/src/model/Epic.java index 76eac11..e4e5d28 100644 --- a/src/model/Epic.java +++ b/src/model/Epic.java @@ -19,10 +19,6 @@ public Epic(String title, String description, Status status) { relatedSubTaskMap = new HashMap<>(); } - public void setEndTime(LocalDateTime endTime) { - this.endTime = endTime; - } - public List getSubTaskIdList() { return new ArrayList<>(relatedSubTaskMap.keySet()); } @@ -94,11 +90,6 @@ public void updateTimeFrame(TreeSet sortedSubTasks) { setDuration(totalDuration); } - @Override - public Optional getEndTime() { - return Optional.ofNullable(endTime); - } - @Override public Status getStatus() { boolean isAllNew = true; @@ -126,6 +117,15 @@ public Status getStatus() { } } + @Override + public Optional getEndTime() { + return Optional.ofNullable(endTime); + } + + public void setEndTime(LocalDateTime endTime) { + this.endTime = endTime; + } + @Override public String toCSV(int headersCount) { return super.toCSV(headersCount).replace("TASK", "EPIC"); diff --git a/test/service/FileBackedTaskManagerTest.java b/test/service/FileBackedTaskManagerTest.java index 50770b0..97a4f33 100644 --- a/test/service/FileBackedTaskManagerTest.java +++ b/test/service/FileBackedTaskManagerTest.java @@ -5,7 +5,8 @@ import java.lang.reflect.Method; import java.util.Optional; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; import model.*; diff --git a/test/service/TaskManagerTest.java b/test/service/TaskManagerTest.java index 69d6ee5..21f7925 100644 --- a/test/service/TaskManagerTest.java +++ b/test/service/TaskManagerTest.java @@ -9,7 +9,7 @@ import static common.TestConstants.*; import static org.junit.jupiter.api.Assertions.*; -abstract class TaskManagerTest { +abstract class TaskManagerTest { protected T taskManager; protected Task task = new Task("Задача", "Описание задачи", Status.NEW, duration30, date1); protected Epic epic = new Epic("Эпик", "Описание эпика"); @@ -19,7 +19,7 @@ abstract class TaskManagerTest { protected abstract Optional createTaskManager(); @BeforeEach - void init(){ + void init() { if (createTaskManager().isPresent()) { taskManager = createTaskManager().get(); } else { From edd4522bafb164b75d2dffefe6bdcefdf1b8a827 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 06:01:02 +0300 Subject: [PATCH 35/47] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=82=D0=B5=D1=81=D1=82=20=D0=BD=D0=B0=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D1=83=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B5=D1=81=D0=B5=D1=87=D0=B5=D0=BD=D0=B8=D0=B9=20=D0=B2=D1=80?= =?UTF-8?q?=D0=B5=D0=BC=D0=B5=D0=BD=D0=B8=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/service/TaskManagerTest.java | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/service/TaskManagerTest.java b/test/service/TaskManagerTest.java index 21f7925..f914842 100644 --- a/test/service/TaskManagerTest.java +++ b/test/service/TaskManagerTest.java @@ -1,5 +1,6 @@ package service; +import java.time.Duration; import java.util.*; import org.junit.jupiter.api.*; @@ -139,4 +140,24 @@ void shouldAvoidExistingIdConflict() { assertEquals(newTask, taskManager.getTaskById(newTaskId).get()); } + @Test + @DisplayName("Корректная проверка на пересечение временных интервалов у задач") + void shouldCorrectlyCheckForOverlaps() { + // Пересечение есть + Task anotherTask = new Task("Ещё задача", "Очередная задача...", Status.NEW, + duration30, date1.plus(Duration.ofMinutes(10))); + + taskManager.createTask(anotherTask); // id=4, start_time = N/A + // Добавилась без start_time + assertTrue(taskManager.getTaskById(4).get().getStartTime().isEmpty()); + taskManager.removeTaskById(4); + + // Пересечения нет + anotherTask = new Task("Ещё задача", "Очередная задача...", Status.NEW, + duration30, date3); + taskManager.createTask(anotherTask); + + // Добавилась с указанием времени + assertEquals(anotherTask, taskManager.getTaskById(4).get()); + } } \ No newline at end of file From 0b745be40494ebe2f008b202d9ffa36962e14257 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 06:02:35 +0300 Subject: [PATCH 36/47] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BC=D0=B5=D1=85=D0=B0=D0=BD=D0=B8=D0=B7=D0=BC?= =?UTF-8?q?=20=D1=80=D0=B0=D1=81=D0=BF=D1=80=D0=B5=D0=B4=D0=B5=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=BE=D1=81=D0=B2=D0=BE=D0=B1=D0=BE=D0=B4?= =?UTF-8?q?=D0=B8=D0=B2=D1=88=D0=B8=D1=85=D1=81=D1=8F=20ID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/IdGenerator.java | 14 ++++++++++++ src/service/InMemoryTaskManager.java | 32 ++++++++++++++++++---------- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/service/IdGenerator.java b/src/service/IdGenerator.java index 2046a29..26879f2 100644 --- a/src/service/IdGenerator.java +++ b/src/service/IdGenerator.java @@ -1,9 +1,23 @@ package service; +import java.util.*; + public class IdGenerator { private int id = 1; + private TreeSet freeIdSet = new TreeSet<>(); public int generateId() { return id++; } + + public Optional getFreeId(){ + if (!freeIdSet.isEmpty()) { + return Optional.of(freeIdSet.getFirst()); + } + return Optional.empty(); + } + + public void addFreeId(int id){ + freeIdSet.add(id); + } } \ No newline at end of file diff --git a/src/service/InMemoryTaskManager.java b/src/service/InMemoryTaskManager.java index 3c7d6dd..fb9ef3e 100644 --- a/src/service/InMemoryTaskManager.java +++ b/src/service/InMemoryTaskManager.java @@ -24,12 +24,16 @@ private int generateUniqueId() { allIds.addAll(allTasks.keySet()); allIds.addAll(allEpics.keySet()); allIds.addAll(allSubTasks.keySet()); - - int id; - do { - id = idGenerator.generateId(); - } while (allIds.contains(id)); - return id; + Optional freeId = idGenerator.getFreeId(); + + if (freeId.isEmpty()) { + int id; + do { + id = idGenerator.generateId(); + } while (allIds.contains(id)); + return id; + } + return freeId.get(); } @Override @@ -54,6 +58,7 @@ public List getSubTasks() { @Override public void removeAllTasks() { + allTasks.keySet().forEach(idGenerator::addFreeId); allTasks.clear(); sortedTasksAndSubTasks = sortedTasksAndSubTasks.stream() .filter(task -> task instanceof SubTask) @@ -63,6 +68,7 @@ public void removeAllTasks() { @Override public void removeAllEpics() { removeAllSubTasks(); + allEpics.keySet().forEach(idGenerator::addFreeId); allEpics.clear(); } @@ -71,6 +77,7 @@ public void removeAllSubTasks() { List epics = getEpics(); epics.forEach(Epic::unlinkAllSubtasks); + allSubTasks.keySet().forEach(idGenerator::addFreeId); allSubTasks.clear(); sortedTasksAndSubTasks = sortedTasksAndSubTasks.stream() @@ -157,7 +164,7 @@ public boolean checkForOverlaps(Task task) { public int createTask(Task task) { if (checkForOverlaps(task)) { System.out.printf(""" - Ошибка добавления задачи %d:\ + Ошибка добавления задачи id=%d: \ обнаружено наложение времени выполнения.\s Задача добавлена без указания времени начала выполнения.\s """, task.getId()); @@ -188,8 +195,8 @@ public int createEpic(Epic epic) { public int createSubTask(SubTask subTask) { if (checkForOverlaps(subTask)) { System.out.printf(""" - Ошибка добавления подзадачи %d:\ - обнаружено наложение времени выполнения.\s + Ошибка добавления подзадачи id=%d: \ + обнаружено наложение времени выполнения.\s Подзадача добавлена без указания времени начала выполнения.\s """, subTask.getId()); subTask.setStartTime(null); @@ -302,11 +309,12 @@ public void updateSubTask(SubTask subTask, int id) { @Override public void removeTaskById(int id) { if (allTasks.containsKey(id)) { - allTasks.remove(id); - historyManager.remove(id); if (getTaskById(id).isPresent()) { sortedTasksAndSubTasks.remove(getTaskById(id).get()); } + allTasks.remove(id); + historyManager.remove(id); + idGenerator.addFreeId(id); } else { System.out.printf("Ошибка при вызове removeTaskById(int id):" + " Невозможно удалить задачу id %d по id: задача не найдена." + "%n", id); @@ -321,6 +329,7 @@ public void removeEpicById(int id) { relatedSubTasks.forEach(this::removeSubTaskById); allEpics.remove(id); historyManager.remove(id); + idGenerator.addFreeId(id); } else { System.out.printf("Ошибка при вызове removeEpicById(int id): " + "Невозможно удалить эпик id %d по id - эпик не найден." + "%n", id); @@ -338,6 +347,7 @@ public void removeSubTaskById(int id) { historyManager.remove(id); updateEpicTimeFrame(subTask.getEpicId()); sortedTasksAndSubTasks.remove(subTask); + idGenerator.addFreeId(id); } else { System.out.printf("Ошибка при вызове removeSubTaskById(int id): " + "Невозможно удалить подзадачу id %d по id: подзадача не найдена." + "%n", id); From 15b481ca22bb430d288914d18f76d1a30fae2206 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 06:09:03 +0300 Subject: [PATCH 37/47] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4?= =?UTF-8?q?=D0=BE=D0=B2=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=87/=D0=BF=D0=BE=D0=B4=D0=B7?= =?UTF-8?q?=D0=B0=D0=B4=D0=B0=D1=87=20=D0=BF=D0=BE=20ID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/InMemoryTaskManager.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/service/InMemoryTaskManager.java b/src/service/InMemoryTaskManager.java index fb9ef3e..4744402 100644 --- a/src/service/InMemoryTaskManager.java +++ b/src/service/InMemoryTaskManager.java @@ -235,6 +235,7 @@ public void updateTask(Task task, int id) { + "Задача не была обновлена.", task.getId()); return; } + if (allTasks.containsKey(id)) { task.setId(id); allTasks.put(id, task); @@ -309,9 +310,8 @@ public void updateSubTask(SubTask subTask, int id) { @Override public void removeTaskById(int id) { if (allTasks.containsKey(id)) { - if (getTaskById(id).isPresent()) { - sortedTasksAndSubTasks.remove(getTaskById(id).get()); - } + Optional task = getTaskById(id); + task.ifPresent(sortedTasksAndSubTasks::remove); allTasks.remove(id); historyManager.remove(id); idGenerator.addFreeId(id); @@ -338,8 +338,9 @@ public void removeEpicById(int id) { @Override public void removeSubTaskById(int id) { - if (allSubTasks.containsKey(id) && getSubTaskById(id).isPresent()) { - SubTask subTask = getSubTaskById(id).get(); + Optional subTaskOptional = getSubTaskById(id); + if (allSubTasks.containsKey(id) && subTaskOptional.isPresent()) { + SubTask subTask = subTaskOptional.get(); Epic epic = getEpicById(subTask.getEpicId()); epic.unlinkSubTask(id); From c47d4fb9d6d79e4d06f444db32a96275e048c912 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 06:28:12 +0300 Subject: [PATCH 38/47] CodeStyle + Refactor --- test/model/TaskTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/model/TaskTest.java b/test/model/TaskTest.java index f36f716..8291225 100644 --- a/test/model/TaskTest.java +++ b/test/model/TaskTest.java @@ -6,8 +6,7 @@ import static common.TestConstants.date1; import static common.TestConstants.duration60; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.*; class TaskTest { private final Task taskA = new Task("Тестовая задача", "Описание тестовой задачи", @@ -25,7 +24,7 @@ void shouldConsiderTwoIdenticalTasksEqual() { Status.NEW, duration60, date1); taskB.setId(1); - assertEquals(taskA, taskB); + assertTrue(taskA.equals(taskB)); } @Test From 376ad66193d8fa8051c34720eef44977220be49d Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 06:29:08 +0300 Subject: [PATCH 39/47] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=80=D0=B0=D1=81=D1=87=D1=91=D1=82=20=D0=B2?= =?UTF-8?q?=D1=8B=D1=87=D0=B8=D1=81=D0=BB=D1=8F=D0=B5=D0=BC=D1=8B=D1=85=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D0=B5=D0=B9=20=D1=8D=D0=BF=D0=B8=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20=D0=B7=D0=B0=D0=B3?= =?UTF-8?q?=D1=80=D1=83=D0=B7=D0=BA=D0=B8=20=D0=B8=D0=B7=20=D1=84=D0=B0?= =?UTF-8?q?=D0=B9=D0=BB=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/Managers.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/service/Managers.java b/src/service/Managers.java index e419de8..c1a2ba2 100644 --- a/src/service/Managers.java +++ b/src/service/Managers.java @@ -57,6 +57,8 @@ private static FileBackedTaskManager loadFromFile(File file) throws ManagerLoadE System.out.println("Во время чтения файла сохранения произошла ошибка: " + e); throw new ManagerLoadException("Ошибка при чтении CSV строки: " + e.getMessage()); } + + manager.getEpics().forEach(epic -> epic.updateTimeFrame(manager.getAllSubTasksOfEpic(epic.getId()))); } return manager; From b5e79355701ef1d4c661501d2eac09679774e188 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 06:29:21 +0300 Subject: [PATCH 40/47] Code style --- src/service/IdGenerator.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/service/IdGenerator.java b/src/service/IdGenerator.java index 26879f2..5ef3ea0 100644 --- a/src/service/IdGenerator.java +++ b/src/service/IdGenerator.java @@ -1,23 +1,24 @@ package service; -import java.util.*; +import java.util.Optional; +import java.util.TreeSet; public class IdGenerator { private int id = 1; - private TreeSet freeIdSet = new TreeSet<>(); + private final TreeSet freeIdSet = new TreeSet<>(); public int generateId() { return id++; } - public Optional getFreeId(){ + public Optional getFreeId() { if (!freeIdSet.isEmpty()) { return Optional.of(freeIdSet.getFirst()); } return Optional.empty(); } - public void addFreeId(int id){ + public void addFreeId(int id) { freeIdSet.add(id); } } \ No newline at end of file From ba161e49680d1b223f6556d9722156ebb7b30a91 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 06:29:49 +0300 Subject: [PATCH 41/47] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=B4=D0=B5=D0=BC=D0=BE=D0=BD=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=BE=D0=BD=D0=BD=D1=8B=D0=B5=20=D1=81=D1=86?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=D1=80=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/Main.java | 13 ++++++++----- src/service/FileBackedTaskManager.java | 14 ++++++++------ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/app/Main.java b/src/app/Main.java index 48bd7f8..8e7beb8 100644 --- a/src/app/Main.java +++ b/src/app/Main.java @@ -45,18 +45,21 @@ public static void main(String[] args) { private static TaskManager getTaskManager() { TaskManager manager = Managers.getDefault(); + LocalDateTime testDateTime = LocalDateTime.now(); + Duration testDuration = Duration.ofMinutes(30); + Task taskA = new Task("Задача A", "Описание задачи A", Status.NEW, - Duration.ofMinutes(100), LocalDateTime.now().plus(Duration.ofMinutes(200))); + testDuration, testDateTime); Task taskB = new Task("Задача B", "Описание задачи B", Status.DONE, - Duration.ofMinutes(15), LocalDateTime.now()); + testDuration, testDateTime.plus(Duration.ofHours(1))); Epic epicA = new Epic("Эпик A", "Описание эпика с тремя подзадачами"); Epic epicB = new Epic("Эпик B", "Описание эпика без подзадач"); SubTask subTaskA = new SubTask("Подзадача A1", "Подзадача 1 эпика A", - Status.NEW, 3, Duration.ofMinutes(100), LocalDateTime.now().plus(Duration.ofMinutes(300))); + Status.NEW, 3, testDuration, testDateTime.plus(Duration.ofHours(2))); SubTask subTaskB = new SubTask("Подзадача A2", "Подзадача 2 эпика A", - Status.DONE, 3, Duration.ofMinutes(42), LocalDateTime.now().plus(Duration.ofHours(4))); + Status.DONE, 3, testDuration, testDateTime.plus(Duration.ofHours(3))); SubTask subTaskC = new SubTask("Подзадача A3", "Подзадача 3 эпика A", - Status.NEW, 3, Duration.ofMinutes(50), LocalDateTime.now().plus(Duration.ofDays(1))); + Status.NEW, 3, testDuration, testDateTime.plus(Duration.ofHours(4))); manager.createTask(taskA); // id = 1 manager.createTask(taskB); // id = 2 diff --git a/src/service/FileBackedTaskManager.java b/src/service/FileBackedTaskManager.java index 969dccd..598b03c 100644 --- a/src/service/FileBackedTaskManager.java +++ b/src/service/FileBackedTaskManager.java @@ -29,14 +29,16 @@ public FileBackedTaskManager(IdGenerator idGenerator, HistoryManager historyMana public static void main(String[] args) throws IOException { File testFile = File.createTempFile("test", "csv"); testFile.deleteOnExit(); + LocalDateTime testDateTime = LocalDateTime.of(2025, 6, 1, 22, 0); FileBackedTaskManager managerA = Managers.getFileBacked(testFile); + Task taskA = new Task("Задача 1", "Описание задачи 1", Status.NEW, - Duration.ofMinutes(30), LocalDateTime.now()); + Duration.ofMinutes(30), testDateTime); Task taskB = new Task("Задача 2", "Описание задачи 2", Status.DONE, - Duration.ofMinutes(90), LocalDateTime.now()); + Duration.ofMinutes(90), testDateTime.plus(Duration.ofMinutes(35))); Epic epicA = new Epic("Эпик 1", "Описание эпика"); SubTask subTaskA = new SubTask("Подзадача 1", "Описание подзадачи", Status.NEW, - 3, Duration.ofMinutes(10), LocalDateTime.now()); + 3, Duration.ofMinutes(10), testDateTime.plus(Duration.ofDays(1))); int taskAId = managerA.createTask(taskA); int taskBId = managerA.createTask(taskB); @@ -45,10 +47,10 @@ public static void main(String[] args) throws IOException { FileBackedTaskManager managerB = Managers.getFileBacked(testFile); - if (managerA.getTaskById(taskAId).equals(managerB.getTaskById(taskAId)) - && managerA.getTaskById(taskBId).equals(managerB.getTaskById(taskBId)) + if (managerA.getTaskById(taskAId).get().equals(managerB.getTaskById(taskAId).get()) + && managerA.getTaskById(taskBId).get().equals(managerB.getTaskById(taskBId).get()) && managerA.getEpicById(epicAId).equals(managerB.getEpicById(epicAId)) - && managerA.getSubTaskById(subTaskAId).equals(managerB.getSubTaskById(subTaskAId))) { + && managerA.getSubTaskById(subTaskAId).get().equals(managerB.getSubTaskById(subTaskAId).get())) { System.out.println("Менеджеры, созданные из одного и того же файла, имеют одинаковый набор задач."); } From da7b4edab3f2deafeafe807eeef83b4296ac8442 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 06:41:46 +0300 Subject: [PATCH 42/47] Code style --- src/service/IdGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service/IdGenerator.java b/src/service/IdGenerator.java index 5ef3ea0..934ad4e 100644 --- a/src/service/IdGenerator.java +++ b/src/service/IdGenerator.java @@ -4,8 +4,8 @@ import java.util.TreeSet; public class IdGenerator { - private int id = 1; private final TreeSet freeIdSet = new TreeSet<>(); + private int id = 1; public int generateId() { return id++; From 760c55d6e768e15d7068230f6fa45d2fad7bd779 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 07:42:18 +0300 Subject: [PATCH 43/47] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D1=83?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D0=BA=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82?= =?UTF-8?q?=D0=BD=D0=BE=D0=B5=20=D1=80=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=87=20=D0=BF?= =?UTF-8?q?=D0=BE=20=D0=BF=D1=80=D0=B8=D0=BE=D1=80=D0=B8=D1=82=D0=B5=D1=82?= =?UTF-8?q?=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/service/TaskManagerTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/service/TaskManagerTest.java b/test/service/TaskManagerTest.java index f914842..c7b757a 100644 --- a/test/service/TaskManagerTest.java +++ b/test/service/TaskManagerTest.java @@ -160,4 +160,16 @@ void shouldCorrectlyCheckForOverlaps() { // Добавилась с указанием времени assertEquals(anotherTask, taskManager.getTaskById(4).get()); } + + @Test + @DisplayName("Задачи с/без времени начала попадают/не попадают в список приоритетных") + void shouldCorrectlyAddPrioritizedTasks() { + Task notPriorityTask = new Task("Не приоритет", "Не очень срочная задача", + Status.NEW, duration30); + taskManager.createTask(notPriorityTask); + + assertTrue(taskManager.getPrioritizedTasks().contains(task)); + assertFalse(taskManager.getPrioritizedTasks().contains(notPriorityTask)); + + } } \ No newline at end of file From 7ac0841093e12683da69ea5ff8c14b670ba25a85 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 07:57:07 +0300 Subject: [PATCH 44/47] Refactor --- src/service/InMemoryTaskManager.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/service/InMemoryTaskManager.java b/src/service/InMemoryTaskManager.java index 4744402..d3cc8db 100644 --- a/src/service/InMemoryTaskManager.java +++ b/src/service/InMemoryTaskManager.java @@ -125,11 +125,7 @@ public TreeSet getAllSubTasksOfEpic(int id) { TreeSet subTaskList = new TreeSet<>(); Epic epic = getEpicById(id); - epic.getSubTaskIdList().forEach(subTaskId -> { - if (getSubTaskById(subTaskId).isPresent()) { - subTaskList.add(getSubTaskById(subTaskId).get()); - } - }); + epic.getSubTaskIdList().forEach(stId -> getSubTaskById(stId).ifPresent(subTaskList::add)); return subTaskList; } From 4e00560f0b730ab4520c896ad6d1117b39721274 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 09:17:52 +0300 Subject: [PATCH 45/47] Refactor --- src/model/Task.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/model/Task.java b/src/model/Task.java index d4326b2..3c2d8be 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -53,8 +53,7 @@ public Status getStatus() { } public Optional getEndTime() { - return Optional.ofNullable(startTime) - .map(time -> time.plus(duration)); + return Optional.ofNullable(startTime).map(time -> time.plus(duration)); } public Duration getDuration() { From b3ad7e091aac5d3c112be7212e83502dfb8bb464 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 09:45:30 +0300 Subject: [PATCH 46/47] Refactor --- src/model/Task.java | 9 ++++----- src/service/FileBackedTaskManager.java | 5 +++-- src/service/utils/Utils.java | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/model/Task.java b/src/model/Task.java index 3c2d8be..e09862d 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -2,13 +2,12 @@ import java.time.Duration; import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import java.util.Objects; import java.util.Optional; -public class Task implements Comparable { - public final static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm dd.MM.yyyy"); +import service.utils.Utils; +public class Task implements Comparable { private final String title; private final String description; private final Status status; @@ -76,7 +75,7 @@ protected String getFormatterStartTime() { String startTimeString = "N/A"; if (getStartTime().isPresent()) { - startTimeString = getStartTime().get().format(formatter); + startTimeString = getStartTime().get().format(Utils.formatter); } return startTimeString; @@ -86,7 +85,7 @@ protected String getFormattedEndTime() { String endTimeString = "N/A"; if (getEndTime().isPresent()) { - endTimeString = getEndTime().get().format(formatter); + endTimeString = getEndTime().get().format(Utils.formatter); } return endTimeString; diff --git a/src/service/FileBackedTaskManager.java b/src/service/FileBackedTaskManager.java index 598b03c..8f9bdbf 100644 --- a/src/service/FileBackedTaskManager.java +++ b/src/service/FileBackedTaskManager.java @@ -9,6 +9,7 @@ import model.*; import service.exceptions.ManagerSaveException; +import service.utils.Utils; import static service.utils.Utils.csvCommaEqualizer; @@ -107,7 +108,7 @@ public void loadTask(String[] data) { if (data[5].equals("N/A")) { task = new Task(title, description, status, duration); } else { - LocalDateTime startTime = LocalDateTime.parse(data[5], Task.formatter); + LocalDateTime startTime = LocalDateTime.parse(data[5], Utils.formatter); task = new Task(title, description, status, duration, startTime); } createTask(task, id); @@ -134,7 +135,7 @@ public void loadSubTask(String[] data) { if (data[5].equals("N/A")) { subTask = new SubTask(title, description, status, epicId, duration); } else { - LocalDateTime startTime = LocalDateTime.parse(data[5], Task.formatter); + LocalDateTime startTime = LocalDateTime.parse(data[5], Utils.formatter); subTask = new SubTask(title, description, status, epicId, duration, startTime); } diff --git a/src/service/utils/Utils.java b/src/service/utils/Utils.java index 43d1484..aebc0a7 100644 --- a/src/service/utils/Utils.java +++ b/src/service/utils/Utils.java @@ -2,9 +2,11 @@ import java.io.*; import java.nio.charset.StandardCharsets; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; public class Utils { + public static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm dd.MM.yyyy"); public static int substringCounter(String s, String substring) { int substringCount = 0; From d294ec9787b9abd88e3f3ceba57999555e1e128d Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 24 Jun 2025 20:43:06 +0300 Subject: [PATCH 47/47] =?UTF-8?q?=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20toString()=20=D1=83=20=D0=BA?= =?UTF-8?q?=D0=BB=D0=B0=D1=81=D1=81=D0=BE=D0=B2=20=D0=B7=D0=B0=D0=B4=D0=B0?= =?UTF-8?q?=D1=87=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20String.format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/model/Epic.java | 21 +++++++++++---------- src/model/SubTask.java | 21 +++++++++++---------- src/model/Task.java | 20 ++++++++++---------- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/model/Epic.java b/src/model/Epic.java index e4e5d28..9386a23 100644 --- a/src/model/Epic.java +++ b/src/model/Epic.java @@ -161,15 +161,16 @@ public String toString() { } catch (NullPointerException e) { durationString = "N/A"; } - return "Epic{" + - "subTaskIdList=" + getSubTaskIdList() + - ", id=" + super.getId() + - ", title='" + super.getTitle() + '\'' + - ", description.length='" + super.getDescription().length() + '\'' + - ", status=" + getStatus() + - ", startTime=" + super.getFormatterStartTime() + - ", duration=" + durationString + " min" + - ", endTime=" + super.getFormattedEndTime() + - '}'; + return String.format("Epic{subTaskIdList=%s, id=%d, title='%s', description.length='%d', " + + "status=%s, startTime=%s, duration=%s min, endTime=%s}", + getSubTaskIdList(), + super.getId(), + super.getTitle(), + super.getDescription().length(), + super.getStatus(), + super.getFormatterStartTime(), + durationString, + super.getFormattedEndTime() + ); } } diff --git a/src/model/SubTask.java b/src/model/SubTask.java index f46939d..a222e7b 100644 --- a/src/model/SubTask.java +++ b/src/model/SubTask.java @@ -56,15 +56,16 @@ public boolean equals(Object object) { @Override public String toString() { - return "SubTask{" + - "epicId=" + getEpicId() + - ", id=" + super.getId() + - ", title='" + super.getTitle() + '\'' + - ", description.length='" + super.getDescription().length() + '\'' + - ", status=" + super.getStatus() + - ", startTime=" + super.getFormatterStartTime() + - ", duration=" + super.getDuration().toMinutes() + " min" + - ", endTime=" + super.getFormattedEndTime() + - '}'; + return String.format("SubTask{epicId=%d, id=%d, title='%s', description.length='%d', " + + "status=%s, startTime=%s, duration=%d min, endTime=%s}", + getEpicId(), + super.getId(), + super.getTitle(), + super.getDescription().length(), + super.getStatus(), + super.getFormatterStartTime(), + super.getDuration().toMinutes(), + super.getFormattedEndTime() + ); } } diff --git a/src/model/Task.java b/src/model/Task.java index e09862d..a5f9b1c 100644 --- a/src/model/Task.java +++ b/src/model/Task.java @@ -153,15 +153,15 @@ public boolean equals(Object object) { @Override public String toString() { - - return "Task{" + - "id=" + getId() + - ", title='" + getTitle() + '\'' + - ", description.length='" + getDescription().length() + '\'' + - ", status=" + getStatus() + - ", startTime=" + getFormatterStartTime() + - ", duration=" + getDuration().toMinutes() + " min" + - ", endTime=" + getFormattedEndTime() + - '}'; + return String.format("Task{id=%d, title='%s', description.length='%d', " + + "status=%s, startTime=%s, duration=%d min, endTime=%s}", + getId(), + getTitle(), + getDescription().length(), + getStatus(), + getFormatterStartTime(), + getDuration().toMinutes(), + getFormattedEndTime() + ); } }