Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions files/Task.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
id,type,name,status,description,epic
1,TASK,Task001,NEW,Description,Task,
2,EPIC,Epic001,NEW,Description,Epic,
3,SUBTASK,Subtask001,NEW,Description,Subtask,2
id,type,name,status,description,class,epicId,startTime,duration,endTime
1,TASK,Task001,NEW,Description,Task,Null,2024-02-02T11:00,60,2024-02-02T12:00
2,EPIC,Epic001,NEW,Description,Epic,2,2025-01-01T10:00,140,2025-01-01T12:30
3,SUBTASK,Subtask001,NEW,Description,Subtask,2,2025-01-01T10:00,70,2025-01-01T11:10
4,SUBTASK,Subtask002,NEW,Description,Subtask,2,2025-01-01T11:20,70,2025-01-01T12:30
7 changes: 7 additions & 0 deletions src/exceptions/TaskValidationException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package exceptions;

public class TaskValidationException extends RuntimeException {
public TaskValidationException(String message) {
super(message);
}
}
38 changes: 34 additions & 4 deletions src/managers/FileBackedTaskManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import exceptions.ManagerSaveException;
import tasks.*;
import java.io.*;
import java.time.Duration;
import java.time.LocalDateTime;

public class FileBackedTaskManager extends InMemoryTaskManager {
private final File tasks;
Expand All @@ -14,7 +16,7 @@ public FileBackedTaskManager(File file) {
public void save() {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(tasks))) {
if (tasks.length() == 0) { //прописываем первую строку
writer.write("id,type,name,status,description,epic\n");
writer.write("id,type,name,status,description,class,epicId,startTime,duration,endTime\n");
}
for (Task task : getTaskList()) {
writer.write(toString(task));
Expand Down Expand Up @@ -67,7 +69,18 @@ public String toString(Task task) {
stringBuilder.append(task.getDescription() + ",");
stringBuilder.append(task.getClass().getSimpleName() + ",");
if (task.getClass() == Subtask.class) {
stringBuilder.append(((Subtask) task).getEpicId());
stringBuilder.append(((Subtask) task).getEpicId() + ",");
} else if (task.getClass() == Epic.class) {
stringBuilder.append(task.getId() + ",");
} else {
stringBuilder.append("Null,");
}
if (task.getStartTime() != null && task.getEndTime() != null && task.getDuration() != null) {
stringBuilder.append(task.getStartTime() + ",");
stringBuilder.append(task.getDuration().toMinutes() + ",");
stringBuilder.append(task.getEndTime());
} else {
stringBuilder.append("Null,Null,Null");
}
return stringBuilder.toString();
}
Expand All @@ -77,14 +90,26 @@ public static Task fromString(String value) {

if (TaskType.valueOf(str[1]) == (TaskType.TASK)) {
Task task = new Task(str[2], str[4], TaskStatus.valueOf(str[3]));
if (str[8] == null || str[7] == null) {
task.setDuration(Duration.ofMinutes(Integer.parseInt(str[8])));
task.setStartTime(LocalDateTime.parse(str[7]));
}
task.setId(Integer.parseInt(str[0]));
return task;
} else if (TaskType.valueOf(str[1]) == (TaskType.EPIC)) {
Epic task = new Epic(str[2], str[4], TaskStatus.valueOf(str[3]));
if (str[8] == null || str[7] == null) {
task.setDuration(Duration.ofMinutes(Integer.parseInt(str[8])));
task.setStartTime(LocalDateTime.parse(str[7]));
}
task.setId(Integer.parseInt(str[0]));
return task;
} else {
Subtask task = new Subtask(str[2], str[4], Integer.parseInt(str[6]), TaskStatus.valueOf(str[3]));
if (str[8] == null || str[7] == null) {
task.setDuration(Duration.ofMinutes(Integer.parseInt(str[8])));
task.setStartTime(LocalDateTime.parse(str[7]));
}
task.setId(Integer.parseInt(str[0]));
return task;
}
Expand Down Expand Up @@ -129,12 +154,17 @@ public void updateEpic(Epic epic) {
public static void main(String[] args) {
File file = new File("files/Task.txt");
FileBackedTaskManager fileBackedTaskManager = new FileBackedTaskManager(file);
Task task001 = new Task("Task001", "Description", TaskStatus.NEW);
Task task001 = new Task("Task001", "Description", TaskStatus.NEW,
Duration.ofMinutes(60), LocalDateTime.of(2024, 2, 2, 11, 0));
fileBackedTaskManager.addTask(task001);
Epic epic001 = new Epic("Epic001", "Description",TaskStatus.NEW);
fileBackedTaskManager.addEpic(epic001);
Subtask subtask001 = new Subtask("Subtask001", "Description", epic001.getId(), TaskStatus.NEW);
Subtask subtask001 = new Subtask("Subtask001", "Description", epic001.getId(), TaskStatus.NEW,
Duration.ofMinutes(70), LocalDateTime.of(2025, 1, 1, 10, 0));
fileBackedTaskManager.addSubtask(subtask001);
Subtask subtask002 = new Subtask("Subtask002", "Description", epic001.getId(), TaskStatus.NEW,
Duration.ofMinutes(70), LocalDateTime.of(2025, 1, 1, 11, 20));
fileBackedTaskManager.addSubtask(subtask002);
fileBackedTaskManager.deleteAllEpic();
fileBackedTaskManager.deleteAllSubtask();
fileBackedTaskManager.deleteTaskList();
Expand Down
106 changes: 90 additions & 16 deletions src/managers/InMemoryTaskManager.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
package managers;

import exceptions.TaskValidationException;
import tasks.Epic;
import tasks.Subtask;
import tasks.Task;
import tasks.TaskStatus;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

public class InMemoryTaskManager implements TaskManager {
private int idCounter = 0;
protected final Map<Integer, Task> taskList = new HashMap<>();
protected final Map<Integer, Epic> epicList = new HashMap<>();
protected final Map<Integer, Subtask> subtaskList = new HashMap<>();

protected final Set<Task> prioritizedTasks = new TreeSet<>(Comparator.comparing(Task::getStartTime));
private final HistoryManager historyManager = Managers.getDefaultHistory();

@Override
Expand All @@ -29,14 +30,15 @@ public ArrayList<Epic> getEpicList() {
}

@Override
public ArrayList<Subtask> getEpicSubtask(Integer epicId) { //Выводит список подзадач эпика
ArrayList<Subtask> currentEpic = new ArrayList<>();
for (Subtask subtask : subtaskList.values()) {
if (subtask.getEpicId() == epicId) {
currentEpic.add(subtask);
}
public List<Subtask> getEpicSubtask(Integer epicId) { //Выводит список подзадач эпика
Epic epic = epicList.get(epicId);
if (epic == null) {
return null;
}
return currentEpic;
List<Subtask> epicSub = getAllSubtask();
return epicSub.stream()
.filter(subtask -> subtask.getEpicId() == epicId)
.collect(Collectors.toList());
}

@Override
Expand All @@ -48,6 +50,7 @@ public ArrayList<Subtask> getAllSubtask() {
public void deleteTaskList() {
for (Integer id : taskList.keySet()) {
historyManager.remove(id);
delete(taskList.get(id));
}
taskList.clear();
}
Expand All @@ -56,21 +59,24 @@ public void deleteTaskList() {
public void deleteAllSubtask() {
for (Integer id : subtaskList.keySet()) {
historyManager.remove(id);
delete(subtaskList.get(id));
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Также удалить из prioritizedTasks. Аналогично для deleteTaskList

subtaskList.clear();
for (Epic epic : epicList.values()) { //идем по списку эпиков
checkStatus(epic);
updateEpic(epic);
}
}

@Override
public void deleteAllEpic() {
for (Integer id : epicList.keySet()) {
historyManager.remove(id);
delete(epicList.get(id));
}
epicList.clear();
for (Integer id : subtaskList.keySet()) {
historyManager.remove(id);
delete(subtaskList.get(id));
}
subtaskList.clear();
}
Expand All @@ -81,19 +87,22 @@ public void deleteEpicSubtask(Epic epic) { //удаление подзадача
for (Subtask subtask : subtaskList.values()) {
if (subtask.getEpicId() == epic.getId()) {
idToRemove.add(subtask.getId());
delete(subtask);
}
}
for (Integer key : idToRemove) {
subtaskList.remove(key);
historyManager.remove(key);
}
checkStatus(epic);
updateEpic(epic);
}

@Override
public void removeTaskForId(Integer id) {
taskList.remove(id);
delete(taskList.get(id));
historyManager.remove(id);

}

@Override
Expand All @@ -104,6 +113,7 @@ public void removeEpicForId(Integer id) {
for (Subtask subtask : subtaskList.values()) { //ищем подзадачи по id удаляемого эпика
if (subtask.getEpicId() == id) {
idToRemove.add(subtask.getId());
delete(subtask);
}
}
for (Integer key : idToRemove) {
Expand All @@ -116,8 +126,10 @@ public void removeEpicForId(Integer id) {
public void removeSubtaskForId(Integer id) {
int epicId = subtaskList.get(id).getEpicId();
subtaskList.remove(id);
delete(subtaskList.get(id));
checkStatus(epicList.get(epicId));//проверяем статус эпика из которого удалили подзадачу
historyManager.remove(id);
updateEpic(epicList.get(epicId));
}

@Override
Expand All @@ -143,6 +155,7 @@ public void addTask(Task task) {
idCounter++;
task.setId(idCounter);
taskList.put(task.getId(), task);
add(task);
}

@Override
Expand All @@ -159,7 +172,8 @@ public void addSubtask(Subtask subtask) {
subtask.setId(idCounter);
int currentEpicId = subtask.getEpicId();
subtaskList.put(subtask.getId(), subtask);
checkStatus(epicList.get(currentEpicId)); //проверка статуса эпика после добавления подзадачи
add(subtask);
updateEpic(epicList.get(currentEpicId));
}

@Override
Expand All @@ -175,8 +189,11 @@ public void updateSubtask(Subtask subtask) {

oldSubtask.setTitle(subtask.getTitle());
oldSubtask.setDescription(subtask.getDescription());

delete(oldSubtask);
subtaskList.put(id, oldSubtask);
checkStatus(epicList.get(epicId)); //проверка статуса эпика
add(oldSubtask);
updateEpic(epicList.get(epicId));
}

@Override
Expand All @@ -188,6 +205,8 @@ public void updateEpic(Epic epic) {
oldEpic.setDescription(epic.getDescription());

epicList.put(id, oldEpic);
checkStatus(epic);
updateEpicDuration(epic);
}

public void checkStatus(Epic epic) {
Expand Down Expand Up @@ -228,4 +247,59 @@ public List<Task> getHistory() {
public void deleteHistory() {
historyManager.deleteHistory();
}

public List<Task> getPrioritizedTasks() {
return new ArrayList<>(prioritizedTasks);
}

public void updateEpicDuration(Epic epic) {
List<Subtask> sub = getEpicSubtask(epic.getId());
sub.stream()
.filter(subtask -> subtask.getStartTime() != null)
.forEachOrdered(subtask -> {
if (epic.getStartTime() == null || epic.getStartTime().isAfter(subtask.getStartTime())) {
epic.setStartTime(subtask.getStartTime());
}
if (epic.getEndTime() == null || epic.getEndTime().isBefore(subtask.getEndTime())) {
epic.setEndTime(subtask.getEndTime());
}
});
Duration totalDuration = sub.stream()
.filter(subtask -> subtask.getStartTime() != null)
.map(Subtask::getDuration)
.reduce(Duration.ZERO, Duration::plus);

epic.setDuration(totalDuration);
}

public boolean isCrossed(Task task1, Task task2) {
LocalDateTime start1 = task1.getStartTime();
LocalDateTime end1 = task1.getEndTime();

LocalDateTime start2 = task2.getStartTime();
LocalDateTime end2 = task2.getEndTime();
boolean notCrossed = start1.isAfter(end2) || start2.isAfter(end1);
return !notCrossed;
}

private void add(Task newTask) {
if (newTask.getStartTime() == null) {
return;
}
prioritizedTasks.stream()
.filter(task -> isCrossed(newTask, task))
.findFirst()
.ifPresentOrElse(
task -> {
String message = "Задача пересекается с задачей с id: " + task.getId() + " с началом: "
+ task.getStartTime() + " и концом: " + task.getEndTime();
throw new TaskValidationException(message);
},
() -> prioritizedTasks.add(newTask)
);
}

private void delete(Task task) {
prioritizedTasks.remove(task);
}
}
13 changes: 13 additions & 0 deletions src/tasks/Epic.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package tasks;

import java.time.LocalDateTime;

public class Epic extends Task {
private LocalDateTime endTime;

public Epic(String title, String description, TaskStatus status) {
super(title, description, status);
}
Expand All @@ -19,4 +23,13 @@ public String toString() {
", status=" + getStatus() +
'}';
}

@Override
public LocalDateTime getEndTime() {
return endTime;
}

public void setEndTime(LocalDateTime endTime) {
this.endTime = endTime;
}
}
9 changes: 9 additions & 0 deletions src/tasks/Subtask.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package tasks;

import java.time.Duration;
import java.time.LocalDateTime;

public class Subtask extends Task {
private final int epicId;

Expand All @@ -8,6 +11,12 @@ public Subtask(String title, String description, int epicId, TaskStatus status)
this.epicId = epicId;
}

public Subtask(String title, String description, int epicId, TaskStatus status,
Duration duration, LocalDateTime startTime) {
super(title, description, status, duration, startTime);
this.epicId = epicId;
}

public int getEpicId() {
return epicId;
}
Expand Down
Loading