From 96f087e776abd0297890fbc40e0a2f477ca12e3d Mon Sep 17 00:00:00 2001 From: Chang Ji-xuan Date: Sun, 10 Sep 2023 17:32:04 +0800 Subject: [PATCH] Added UI,Parser, Storage and TaskList --- src/main/java/Command.java | 13 ++ src/main/java/Duke.java | 245 ++++++++++++++++--------------- src/main/java/DukeException.java | 10 ++ src/main/java/Parser.java | 43 ++++++ src/main/java/Storage.java | 32 ++++ src/main/java/Task.java | 1 + src/main/java/TaskList.java | 4 + src/main/java/TaskReader.java | 17 +-- src/main/java/TaskWriter.java | 1 - src/main/java/Ui.java | 56 +++++++ 10 files changed, 295 insertions(+), 127 deletions(-) create mode 100644 src/main/java/Command.java create mode 100644 src/main/java/DukeException.java create mode 100644 src/main/java/Parser.java create mode 100644 src/main/java/Storage.java create mode 100644 src/main/java/Ui.java diff --git a/src/main/java/Command.java b/src/main/java/Command.java new file mode 100644 index 0000000000..5ac1dc781f --- /dev/null +++ b/src/main/java/Command.java @@ -0,0 +1,13 @@ +public enum Command { + TODO, + DEADLINE, + EVENT, + LIST, + DONE, + DELETE, + FIND, + EXIT, + INVALID, + UNMARK, + MARK +} diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 6e8b68afcb..e7ff734ec9 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -7,141 +7,156 @@ public class Duke { - //private Storage storage; - //private TaskList tasks; - //private Ui ui; - - - - public static void main(String[] args) { - String name = "Johnnythesnake"; - System.out.println("Hello I'm " + name + "\n" + "What can I do for you? Aside from completing your CS2103 project for you"); - Scanner scanner = new Scanner(System.in); - String filename = "tasks.txt"; - // Create a File object with the filename - File file = new File(filename); - - TaskList tasks = new TaskList(); - if (file.exists()) { - tasks = TaskReader.readTasksFromFile(filename); - System.out.println(tasks); + private final Storage storage; + private TaskList tasks; + private final Ui ui; + + public Duke(String filePath) { + ui = new Ui(); + storage = new Storage(filePath); + try { + tasks = storage.load(); + } catch (DukeException e) { + ui.showLoadingError(); + tasks = new TaskList(); } - while (true) { - System.out.println("Enter a command: "); - String command = scanner.nextLine(); - if (command.equalsIgnoreCase("bye")) { // bye exits the code - Exit exit = new Exit(); - System.out.println(exit.exitMessage()); - break; - } else if (command.equalsIgnoreCase("list")) { //list shows the task list - tasks.listOfTasks(); - } else if (command.startsWith("unmark")) { // unmark the task in question - int taskNumber = Integer.parseInt(command.substring(7)) - 1; - if (taskNumber < tasks.size()) { - tasks.unmarkTask(taskNumber);; - } - } else if (command.startsWith("mark")) { // mark the task in question - int taskNumber = Integer.parseInt(command.substring(5)) - 1; - if (taskNumber < tasks.size()) { - tasks.markTaskAsDone(taskNumber); - } - - - } else if (command.startsWith("todo")) { - String description = command.substring(4).trim(); // Trim any leading/trailing spaces - - try { - if (description.isEmpty()) { - throw new EmptyTodoException(); - } + } - Todo todo = new Todo(description, false); - tasks.addTask(todo); - } catch (EmptyTodoException e) { - System.out.println(e.getMessage()); - } - } else if (command.startsWith("deadline")) { - // Split the input - String descriptionDeadline = command.substring(8).trim(); // Remove "deadline" and leading spaces + public void run() { + ui.showWelcomeMessage(); - if (descriptionDeadline.isEmpty()) { + while (true) { + String userInput = ui.getUserInput(); + Command command = Parser.parseCommand(userInput); + String description = Parser.parseDescription(userInput); + switch (command) { + case EXIT: + storage.save(tasks, "tasks.txt"); + ui.closeScanner(); + ui.showExitMessage(); + return; + case LIST: + ui.showTaskList(tasks); + break; + case UNMARK: try { - throw new EmptyDeadlineException(); - } catch (EmptyDeadlineException e) { - System.out.println(e.getMessage()); + int taskNumber = Integer.parseInt(description) - 1; + if (taskNumber >= 0 && taskNumber < tasks.size()) { + tasks.unmarkTask(taskNumber); + } else { + ui.showError("Task number out of range."); + } + } catch (NumberFormatException e) { + ui.showError("Invalid task number. Please provide a valid integer."); } - } else { - // Find the index of the deadline separator "/" - int separatorIndex = descriptionDeadline.indexOf('/'); - - if (separatorIndex != -1) { // Ensure the separator exists in the input - // Extract the task description and deadline - - String description = descriptionDeadline.substring(0, separatorIndex).trim(); - String deadline = descriptionDeadline.substring(separatorIndex + 4).trim(); - String pattern = "\\d{4}/\\d{2}/\\d{2}"; - Pattern datePattern = Pattern.compile(pattern); - Matcher matcher = datePattern.matcher(deadline); - if (matcher.find()) { - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); - LocalDate localDateDeadline = LocalDate.parse(deadline, formatter); - Deadline deadlineTask = new Deadline(description,false, localDateDeadline); - tasks.addTask(deadlineTask); - + break; + case MARK: + try { + int taskNumber = Integer.parseInt(description) - 1; + if (taskNumber >= 0 && taskNumber < tasks.size()) { + tasks.markTaskAsDone(taskNumber); } else { - System.out.println("Please input your deadline in YYYY/MM/DD format"); + ui.showError("Task number out of range."); } - } else { - System.out.println("Invalid input format for deadline. Please input in the following format: /by "); + } catch (NumberFormatException e) { + ui.showError("Invalid task number. Please provide a valid integer."); } - } - } else if (command.startsWith("event")) { - // split the input - String descriptionStartEndTime = command.substring(5).trim(); // Remove "event" and leading spaces - if (descriptionStartEndTime.isEmpty()) { + break; + case TODO: try { - throw new EmptyEventException(); - } catch (EmptyEventException e) { + if (description.isEmpty()) { + throw new EmptyTodoException(); + } + Todo todo = new Todo(description, false); + tasks.addTask(todo); + + } catch (EmptyTodoException e) { System.out.println(e.getMessage()); } - } else { - // Find the indices of the time separators - int fromIndex = descriptionStartEndTime.indexOf("/from"); - int toIndex = descriptionStartEndTime.indexOf("/to"); - - if (fromIndex != -1 && toIndex != -1) { - // Extract the task description, startTime, and endTime - String description = descriptionStartEndTime.substring(0, fromIndex).trim(); - String startTime = descriptionStartEndTime.substring(fromIndex + 5, toIndex).trim(); - String endTime = descriptionStartEndTime.substring(toIndex + 3).trim(); - - // Create a new Event object - Event eventTask = new Event(description, false, startTime, endTime); - tasks.addTask(eventTask); + break; + case DEADLINE: + if (description.isEmpty()) { + try { + throw new EmptyDeadlineException(); + } catch (EmptyDeadlineException e) { + System.out.println(e.getMessage()); + } } else { - System.out.println("Invalid input format for event command."); + // Find the index of the deadline separator "/" + int separatorIndex = description.indexOf('/'); + + if (separatorIndex != -1) { // Ensure the separator exists in the input + // Extract the task description and deadline + + String descriptionString = description.substring(0, separatorIndex).trim(); + String deadline = description.substring(separatorIndex + 4).trim(); + String pattern = "\\d{4}/\\d{2}/\\d{2}"; + Pattern datePattern = Pattern.compile(pattern); + Matcher matcher = datePattern.matcher(deadline); + if (matcher.find()) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); + LocalDate localDateDeadline = LocalDate.parse(deadline, formatter); + Deadline deadlineTask = new Deadline(descriptionString, false, localDateDeadline); + tasks.addTask(deadlineTask); + + } else { + System.out.println("Please input your deadline in YYYY/MM/DD format"); + } + } else { + System.out.println("Invalid input format for deadline. Please input in the following format: /by "); + } } - } - } else if (command.startsWith("delete")) { - int taskNumber = Integer.parseInt(command.substring(7)) - 1; - if (taskNumber < tasks.size()) { - tasks.deleteTask(taskNumber); + break; + case EVENT: + if (description.isEmpty()) { + try { + throw new EmptyEventException(); + } catch (EmptyEventException e) { + System.out.println(e.getMessage()); + } + } else { + // Find the indices of the time separators + int fromIndex = description.indexOf("/from"); + int toIndex = description.indexOf("/to"); - } + if (fromIndex != -1 && toIndex != -1) { + // Extract the task description, startTime, and endTime + String descriptionString = description.substring(0, fromIndex).trim(); + String startTime = description.substring(fromIndex + 5, toIndex).trim(); + String endTime = description.substring(toIndex + 3).trim(); + // Create a new Event object + Event eventTask = new Event(descriptionString, false, startTime, endTime); + tasks.addTask(eventTask); - } else { - try { - throw new UnknownInputException(); - } catch (UnknownInputException e) { - System.out.println(e.getMessage()); - } + } else { + System.out.println("Invalid input format for event command."); + } + } + break; + case DELETE: + try { + int taskNumber = Integer.parseInt(description) - 1; + if (taskNumber >= 0 && taskNumber < tasks.size()) { + tasks.deleteTask(taskNumber); + } else { + ui.showError("Task number out of range."); + } + } catch (NumberFormatException e) { + ui.showError("Invalid task number. Please provide a valid integer."); + } + break; + case INVALID: + ui.showError("Invalid command. Please try again."); + break; } - } - TaskWriter.writeTasksToFile(tasks, "tasks.txt"); + } + + public static void main(String[] args) { + new Duke("tasks.txt").run(); } } diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java new file mode 100644 index 0000000000..a2b0016b6e --- /dev/null +++ b/src/main/java/DukeException.java @@ -0,0 +1,10 @@ +public class DukeException extends Exception { + public DukeException(String message) { + super(message); + } +} + + + + + diff --git a/src/main/java/Parser.java b/src/main/java/Parser.java new file mode 100644 index 0000000000..0d606262c7 --- /dev/null +++ b/src/main/java/Parser.java @@ -0,0 +1,43 @@ +public class Parser { + public static Command parseCommand(String userInput) { + String[] inputParts = userInput.split(" ", 2); // Split input into two parts: command and arguments + String command = inputParts[0].toUpperCase(); // Convert command to uppercase for case-insensitivity + + + switch (command) { + case "TODO": + return Command.TODO; + case "DEADLINE": + return Command.DEADLINE; + case "EVENT": + return Command.EVENT; + case "LIST": + return Command.LIST; + case "DONE": + return Command.DONE; + case "DELETE": + return Command.DELETE; + case "FIND": + return Command.FIND; + case "BYE": + return Command.EXIT; + case "UNMARK": + return Command.UNMARK; + case "MARK": + return Command.MARK; + default: + return Command.INVALID; + } + + + } + + public static String parseDescription(String userInput) { + String[] parts = userInput.split(" ", 2); // Split input into command and arguments + if (parts.length > 1) { + return parts[1]; + } + return ""; + } + +} diff --git a/src/main/java/Storage.java b/src/main/java/Storage.java new file mode 100644 index 0000000000..6bcb914522 --- /dev/null +++ b/src/main/java/Storage.java @@ -0,0 +1,32 @@ +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.ArrayList; +import java.util.List; + +public class Storage { + public String filePath; + + public Storage(String filePath) { + + this.filePath = filePath; + } + + public TaskList load() throws DukeException { + TaskList tasks = new TaskList(); + File file = new File(filePath); + if (file.exists()) { + tasks = TaskReader.readTasksFromFile(filePath); + System.out.println(tasks); + } + + return tasks; + } + + public void save(TaskList tasks, String filePath) { + TaskWriter.writeTasksToFile(tasks, filePath); + } +} diff --git a/src/main/java/Task.java b/src/main/java/Task.java index 13a11f5cec..4602a13e20 100644 --- a/src/main/java/Task.java +++ b/src/main/java/Task.java @@ -12,6 +12,7 @@ public String getName() { } public void setName(String name) { + this.name = name; } diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java index 27594974ff..e04457c0a1 100644 --- a/src/main/java/TaskList.java +++ b/src/main/java/TaskList.java @@ -14,6 +14,10 @@ public void addTask(Task task) { System.out.println("Now you have " + tasks.size() + " tasks in the list."); } + public void addTaskFromStorage(Task task) { + tasks.add(task); + } + public boolean isEmpty() { return tasks.isEmpty(); } diff --git a/src/main/java/TaskReader.java b/src/main/java/TaskReader.java index 2e0ad831a7..217ee1cf77 100644 --- a/src/main/java/TaskReader.java +++ b/src/main/java/TaskReader.java @@ -2,7 +2,6 @@ import java.io.FileReader; import java.io.IOException; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; import java.time.LocalDate; public class TaskReader { @@ -14,7 +13,7 @@ public static TaskList readTasksFromFile(String filename) { while ((line = reader.readLine()) != null) { Task task = parseTaskFromLine(line); if (task != null) { - tasks.addTask(task); + tasks.addTaskFromStorage(task); } } } catch (IOException e) { @@ -34,16 +33,12 @@ private static Task parseTaskFromLine(String line) { // Parse Deadline task String description = line.substring(6, line.indexOf("(by:")).trim(); boolean isMarked = line.charAt(4) == 'X'; - int startIndex = line.indexOf("(by: "); // Find the starting index of "(by: " - int endIndex = line.indexOf(")", startIndex); // Find the ending index of ")" + String dateSubstring = extractDeadline(line); + String formattedDate = DateConverter.convertDate(dateSubstring); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); + LocalDate deadline = LocalDate.parse(formattedDate, formatter); + return new Deadline(description, isMarked, deadline); - if (startIndex != -1 && endIndex != -1) { - String dateSubstring = line.substring(startIndex + 5, endIndex); - String formattedDate = DateConverter.convertDate(dateSubstring); - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); - LocalDate deadline = LocalDate.parse(formattedDate, formatter); - return new Deadline(description, isMarked, deadline); - } } else if (line.startsWith("[E]")) { // Parse Event task String description = line.substring(6, line.indexOf("(from:")).trim(); diff --git a/src/main/java/TaskWriter.java b/src/main/java/TaskWriter.java index f688b0e8a4..dae371eee1 100644 --- a/src/main/java/TaskWriter.java +++ b/src/main/java/TaskWriter.java @@ -1,4 +1,3 @@ -import java.util.ArrayList; import java.io.FileWriter; import java.io.BufferedWriter; import java.io.IOException; diff --git a/src/main/java/Ui.java b/src/main/java/Ui.java new file mode 100644 index 0000000000..988542e4fb --- /dev/null +++ b/src/main/java/Ui.java @@ -0,0 +1,56 @@ +import java.util.Scanner; + +public class Ui { + private Scanner scanner; + + public Ui() { + scanner = new Scanner(System.in); + } + + public String getUserInput() { + System.out.print("Enter a command: "); + return scanner.nextLine().trim(); + } + + public void showWelcomeMessage() { + String name = "Johnnythesnake"; + System.out.println("Hello, I'm " + name); + System.out.println("What can I do for you? Aside from completing your CS2103 project for you"); + } + + public void showExitMessage() { + System.out.println("Goodbye! Have a great day!"); + } + + public void showTaskList(TaskList tasks) { + tasks.listOfTasks(); + } + + public void showMarkedAsDone(int taskNumber) { + System.out.println("Task " + (taskNumber + 1) + " marked as done."); + } + + public void showUnmarked(int taskNumber) { + System.out.println("Task " + (taskNumber + 1) + " unmarked."); + } + + public void showTaskAdded() { + System.out.println("Task added."); + } + + public void showTaskDeleted(int taskNumber) { + System.out.println("Task " + (taskNumber + 1) + " deleted."); + } + + public void showError(String errorMessage) { + System.out.println("Error: " + errorMessage); + } + + public void showLoadingError() { + System.out.println("Error loading tasks from storage."); + } + public void closeScanner() { + scanner.close(); + } +} +