Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
16 changes: 16 additions & 0 deletions .idea/checkstyle-idea.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
# java-kanban
Repository for homework project.

Проект - Трекер задач.

## Автор
Ксения
3 changes: 3 additions & 0 deletions java-kanban.iml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="CheckStyle-IDEA-Module" serialisationVersion="2">
<option name="activeLocationsIds" />
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
Expand Down
7 changes: 6 additions & 1 deletion src/model/Epic.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public ArrayList<Integer> getSubtaskIds() {
}

public void setSubtaskIds(ArrayList<Integer> subtaskIds) {
this.subtaskIds = subtaskIds;
this.subtaskIds = new ArrayList<>(subtaskIds);
}

// Очищение всех ID подзадач
Expand All @@ -34,6 +34,11 @@ public void removeSubtaskId(Integer subtaskId) {
subtaskIds.remove(subtaskId);
}

@Override
public TaskType getType() {
return TaskType.EPIC;
}

@Override
public String toString() {
return "Epic{" +
Expand Down
5 changes: 5 additions & 0 deletions src/model/Subtask.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ public void setEpicId(int epicId) {
this.epicId = epicId;
}

@Override
public TaskType getType() {
return TaskType.SUBTASK;
}

@Override
public void setId(int id) {
if (id == this.getEpicId()) {
Expand Down
4 changes: 4 additions & 0 deletions src/model/Task.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ public Task(String name, String description, Status status) {
this.status = status;
}

public TaskType getType() {
return TaskType.TASK;
}

public int getId() {
return id;
}
Expand Down
7 changes: 7 additions & 0 deletions src/model/TaskType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package model;

Comment thread
ksupyl marked this conversation as resolved.
public enum TaskType {
TASK,
EPIC,
SUBTASK
}
267 changes: 267 additions & 0 deletions src/service/FileBackedTaskManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
package service;

import model.Epic;
import model.Status;
import model.Subtask;
import model.Task;
import model.TaskType;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.TreeMap;

public class FileBackedTaskManager extends InMemoryTaskManager {
private final File file;

public FileBackedTaskManager(File file) {
this.file = file;
}

// Сохраняет текущее состояние менеджера в CSV-файл
private void save() {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
writer.write("id,type,name,status,description,epic");
writer.newLine();

TreeMap<Integer, Task> allTasks = new TreeMap<>();

for (Task task : getTasks()) {
allTasks.put(task.getId(), task);
}

for (Epic epic : getEpics()) {
allTasks.put(epic.getId(), epic);
}

for (Subtask subtask : getSubtasks()) {
allTasks.put(subtask.getId(), subtask);
}

for (Task task : allTasks.values()) {
writer.write(toString(task));
writer.newLine();
}
} catch (IOException e) {
throw new ManagerSaveException("Failed to save tasks to file: " + file, e);
}
}

// Преобразует задачу в строку формата CSV
private String toString(Task task) {
StringBuilder builder = new StringBuilder();

builder.append(task.getId()).append(",");
builder.append(task.getType()).append(",");

builder.append(task.getName()).append(",");
builder.append(task.getStatus()).append(",");
builder.append(task.getDescription()).append(",");

if (task instanceof Subtask) {
Subtask subtask = (Subtask) task;
builder.append(subtask.getEpicId());
}

return builder.toString();
}

// Преобразует строку CSV в объект задачи
private static Task fromString(String value) {
String[] fields = value.split(",", -1);

int id = Integer.parseInt(fields[0]);
TaskType taskType = TaskType.valueOf(fields[1]);
String name = fields[2];
Status status = Status.valueOf(fields[3]);
String description = fields[4];

Task task;

if (taskType == TaskType.TASK) {
task = new Task(name, description, status);
} else if (taskType == TaskType.EPIC) {
task = new Epic(name, description);
task.setStatus(status);
} else {
int epicId = Integer.parseInt(fields[5]);
task = new Subtask(name, description, status, epicId);
}

task.setId(id);
return task;
}

// Восстанавливает менеджер из CSV-файла
public static FileBackedTaskManager loadFromFile(File file) {
FileBackedTaskManager manager = new FileBackedTaskManager(file);
int maxId = 0;

try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line = reader.readLine(); // пропуск заголовка

while ((line = reader.readLine()) != null) {
if (line.isBlank()) {
continue;
}

Task task = fromString(line);

Comment thread
ksupyl marked this conversation as resolved.
switch (task.getType()) {
case TASK:
manager.putLoadedTask(task);
break;
case EPIC:
manager.putLoadedEpic((Epic) task);
break;
case SUBTASK:
manager.putLoadedSubtask((Subtask) task);
break;
}

if (task.getId() > maxId) {
maxId = task.getId();
}
}

manager.setNextId(maxId + 1);
return manager;
} catch (IOException e) {
throw new ManagerSaveException("Failed to load tasks from file: " + file, e);
}
}

// После каждого изменения сохраняем состояние менеджера в файл
@Override
public void clearTasks() {
super.clearTasks();
save();
}

@Override
public void clearEpics() {
super.clearEpics();
save();
}

@Override
public void clearSubtasks() {
super.clearSubtasks();
save();
}

@Override
public Task createTask(Task task) {
Task createdTask = super.createTask(task);
save();
return createdTask;
}

@Override
public Epic createEpic(Epic epic) {
Epic createdEpic = super.createEpic(epic);
save();
return createdEpic;
}

@Override
public Subtask createSubtask(Subtask subtask) {
Subtask createdSubtask = super.createSubtask(subtask);
save();
return createdSubtask;
}

@Override
public void updateTask(Task task) {
super.updateTask(task);
save();
}

@Override
public void updateEpic(Epic epic) {
super.updateEpic(epic);
save();
}

@Override
public void updateSubtask(Subtask subtask) {
super.updateSubtask(subtask);
save();
}

@Override
public void deleteTask(int id) {
super.deleteTask(id);
save();
}

@Override
public void deleteEpic(int id) {
super.deleteEpic(id);
save();
}

@Override
public void deleteSubtask(int id) {
super.deleteSubtask(id);
save();
}

// Демонстрационный сценарий работы файлового менеджера
public static void main(String[] args) {
File file = new File("tasks.csv");

FileBackedTaskManager manager = new FileBackedTaskManager(file);

// Создание обычных задач
Task task1 = new Task("Task1", "Description of task 1", Status.NEW);
Task task2 = new Task("Task2", "Description of task 2", Status.NEW);
manager.createTask(task1);
manager.createTask(task2);

// Создание эпика
Epic epic1 = new Epic("Epic1", "Description of epic 1");
manager.createEpic(epic1);

// Создание подзадач для эпика
Subtask subtask1 = new Subtask("Subtask1", "Description of subtask 1", Status.NEW, epic1.getId());
Subtask subtask2 = new Subtask("Subtask2", "Description of subtask 2", Status.NEW, epic1.getId());
manager.createSubtask(subtask1);
manager.createSubtask(subtask2);

// Меняем статус одной подзадачи для проверки пересчёта эпика
subtask1.setStatus(Status.DONE);
manager.updateSubtask(subtask1);

// Загрузка нового менеджера из того же файла
FileBackedTaskManager loadedManager = FileBackedTaskManager.loadFromFile(file);

// Вывод данных из нового менеджера
System.out.println("Обычные задачи из загруженного менеджера:");
for (Task task : loadedManager.getTasks()) {
System.out.println(task);
}

System.out.println("Эпики из загруженного менеджера:");
for (Epic epic : loadedManager.getEpics()) {
System.out.println(epic);
}

System.out.println("Подзадачи из загруженного менеджера:");
for (Subtask subtask : loadedManager.getSubtasks()) {
System.out.println(subtask);
}

// Проверка, что данные действительно загрузились
if (loadedManager.getTasks().size() == manager.getTasks().size()
&& loadedManager.getEpics().size() == manager.getEpics().size()
&& loadedManager.getSubtasks().size() == manager.getSubtasks().size()) {
System.out.println("Данные успешно сохранены и загружены.");
} else {
System.out.println("Ошибка: данные после загрузки не совпадают.");
}
}
}
28 changes: 27 additions & 1 deletion src/service/InMemoryTaskManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ public void updateEpic(Epic epic) {
}

// Метод для обновления статуса Эпик при обновлении Подзадач
private void updateEpicStatus(Epic epic) {
protected void updateEpicStatus(Epic epic) {
if (epic.getSubtaskIds().isEmpty()) {
epic.setStatus(Status.NEW);
return;
Expand Down Expand Up @@ -276,4 +276,30 @@ public ArrayList<Subtask> getEpicSubtasks(int epicId) {
}
return result;
}

// Служебные методы для восстановления менеджера из файла
protected void putLoadedTask(Task task) {
tasks.put(task.getId(), task);
}

protected void putLoadedEpic(Epic epic) {
epics.put(epic.getId(), epic);
}

protected void putLoadedSubtask(Subtask subtask) {
subtasks.put(subtask.getId(), subtask);

Epic epic = epics.get(subtask.getEpicId());
if (epic != null) {
epic.addSubtaskId(subtask.getId());
}
}

protected void setNextId(int nextId) {
this.nextId = nextId;
}

protected ArrayList<Epic> getLoadedEpics() {
return new ArrayList<>(epics.values());
}
}
Loading
Loading