diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 5d313334..b86851ef 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,10 +1,93 @@ +import java.text.ParseException; + public class Duke { + private Storage storage; + private Parser parser; + private TaskList tasks; + private Ui ui; + + public Duke() { + ui = new Ui(); + storage = new Storage(); + parser = new Parser(); + tasks = new TaskList(storage.load()); + } + + public void run() { + ui.showWelcome(); + String day; + + String userInput = ui.readUserInput(); + + while(!userInput.equals("bye")) { + String[] firstBox = parser.firstFilter(userInput); // return a string array with commands and description + String commands = firstBox[0]; + try { + switch (commands) { + case "list": + ui.showTaskList(tasks.getTaskList()); + break; + + case "done": + tasks.runDone(userInput); + storage.save(); + break; + + case "delete": + tasks.runDelete(userInput); + storage.save(); + break; + + case "find": + tasks.runFind(userInput); + break; + + case "todo": + try { + if (firstBox[1].isBlank()){ + throw new DukeException("☹ OOPS!!! The description of a todo cannot be empty."); + }else { + tasks.runToDo(firstBox[1]); + } + }catch(DukeException e) { + e.printStackTrace(); + }finally{ + storage.save(); + break; + } + + case "deadline": + String[] secondBox = parser.secondFilter(firstBox[1] , "deadline"); + day = parser.dayExtractor(secondBox); + String timeInString = parser.timeFormatter(secondBox[1].trim() , day); + tasks.runDeadline(secondBox[0] , timeInString); + storage.save(); + break; + + case "event": + secondBox = parser.secondFilter(firstBox[1] , "event"); + timeInString = parser.timeFormatter(secondBox[1] , parser.dayExtractor(secondBox)); + tasks.runEvent(secondBox[0] , timeInString); + storage.save(); + break; + + default: + throw new DukeException("☹ OOPS!!! I'm sorry, but I don't know what that means :-("); + } + + + }catch(DukeException | ParseException e) { + e.printStackTrace(); + }finally { + userInput = ui.readUserInput().trim(); + } + + } + ui.showExit(); + } + public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); + new Duke().run(); + } } diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java new file mode 100644 index 00000000..8f852484 --- /dev/null +++ b/src/main/java/DukeException.java @@ -0,0 +1,6 @@ +public class DukeException extends Exception { + public DukeException(){} + public DukeException(String msg){ + super(msg); + } +} \ No newline at end of file diff --git a/src/main/java/Parser.java b/src/main/java/Parser.java new file mode 100644 index 00000000..969a8d10 --- /dev/null +++ b/src/main/java/Parser.java @@ -0,0 +1,94 @@ +import duke.Deadline; +import duke.Event; +import duke.Task; +import duke.ToDo; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; + +public class Parser { + private static final String WHITESPACE = " "; + + public void loadParse(ArrayList taskList , String input) { + String[] arr = input.split(" \\| "); + String taskType = arr[0].trim(); + String taskStatus = arr[1].trim(); + String taskDescription = arr[2].trim(); + String taskTime = ""; + + if (taskType.equals("T")) { + Task todo = new ToDo(taskDescription); + if (taskStatus.equals("\u2713")) { + todo.markAsDone(); + } + taskList.add(todo); + }else if (taskType.equals("D")) { + taskTime = arr[3].trim(); + Task deadline = new Deadline(taskDescription , taskTime); + if (taskStatus.equals("\u2713")) { + deadline.markAsDone(); + } + taskList.add(deadline); + }else { + taskTime = arr[3].trim(); + Task event = new Event(taskDescription , taskTime); + if (taskStatus.equals("\u2713")) { + event.markAsDone(); + } + taskList.add(event); + } + } + + public String dayExtractor(String[] secondBox) { + String day = secondBox[1].trim().split("/")[0]; + return day; + } + + public String timeFormatter(String dateInString , String day) throws ParseException { + DateFormat parser = new SimpleDateFormat("dd/M/yyyy HHmm"); + DateFormat stFormatter = new SimpleDateFormat("d'st of' MMMM yyyy , ha"); + DateFormat ndFormatter = new SimpleDateFormat("d'nd of' MMMM yyyy , ha"); + DateFormat rdFormatter = new SimpleDateFormat("d'rd of' MMMM yyyy , ha"); + DateFormat thFormatter = new SimpleDateFormat("d'th of' MMMM yyyy , ha"); + + String output; + + Date convertedDate = parser.parse(dateInString); + if (day.equals("1")){ + output = stFormatter.format(convertedDate); + }else if (day.equals("2")) { + output = ndFormatter.format(convertedDate); + }else if (day.equals("3")) { + output = rdFormatter.format(convertedDate); + }else{ + output = thFormatter.format(convertedDate); + } + return output; + } + + public String[] firstFilter(String userInput) { + String[] filter = userInput.split(" "); + String firstWord = filter[0]; + StringBuilder str = new StringBuilder(); + for (int i = 1 ; i < filter.length ; i++) { + str.append(filter[i]); + str.append(WHITESPACE); + } + String[] result = {firstWord , str.toString().trim()}; + + return result; + } + + public String[] secondFilter(String newString , String firstWord) { + String[] filter; + if (firstWord.equals("deadline")) { + filter = newString.split(" /by "); + }else{ + filter = newString.split(" /at "); + } + return filter; + } +} diff --git a/src/main/java/Storage.java b/src/main/java/Storage.java new file mode 100644 index 00000000..2cd235e9 --- /dev/null +++ b/src/main/java/Storage.java @@ -0,0 +1,96 @@ +import duke.Task; + +import java.io.*; +import java.util.ArrayList; + +public class Storage { + + private ArrayList taskList = new ArrayList<>(); + Parser parser = new Parser(); + + public ArrayList load() { + File file = new File("/Users/qianjie/Desktop/duke/src/main/java/data/duke.txt"); + FileReader fileReader = null; + BufferedReader bufferedReader = null; + try { + fileReader = new FileReader(file); + bufferedReader = new BufferedReader(fileReader); + + String input = bufferedReader.readLine(); + + while (input != null) { + parser.loadParse(taskList , input); + input = bufferedReader.readLine(); + } + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + }finally { + try { + if (fileReader != null) { + fileReader.close(); + } + }catch (IOException e) { + e.printStackTrace(); + } + try { + if (bufferedReader != null) { + bufferedReader.close(); + } + }catch (IOException e) { + e.printStackTrace(); + } + return taskList; + + } + } + + public void save () { + FileWriter fileWriter = null; + BufferedWriter bufferedWriter = null; + try{ + File file = new File("/Users/qianjie/Desktop/duke/src/main/java/data/duke.txt"); + fileWriter = new FileWriter(file , false); + bufferedWriter = new BufferedWriter(fileWriter); + for (Task t : taskList) { + String taskType = t.getType(); + String taskStatus = t.getStatusIcon(); + String taskDescription = t.getDescription(); + String taskTime = t.getTime(); + + if (taskType.equals("T")) { + bufferedWriter.write(taskType + " | " + taskStatus + " | " + taskDescription); + bufferedWriter.newLine(); + + }else{ + bufferedWriter.write(taskType + " | " + taskStatus + " | " + taskDescription + " | " + taskTime); + bufferedWriter.newLine(); + } + + + bufferedWriter.flush(); + } + + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (fileWriter != null) { + fileWriter.close(); + } + }catch (IOException e) { + e.printStackTrace(); + } + try { + if (bufferedWriter != null) { + bufferedWriter.close(); + } + }catch (IOException e) { + e.printStackTrace(); + } + } + + } +} diff --git a/src/main/java/TaskList.java b/src/main/java/TaskList.java new file mode 100644 index 00000000..22ac6374 --- /dev/null +++ b/src/main/java/TaskList.java @@ -0,0 +1,81 @@ +import duke.Deadline; +import duke.Event; +import duke.Task; +import duke.ToDo; + +import java.util.ArrayList; + +public class TaskList { + public TaskList() {} + public TaskList(ArrayList taskList) { + this.taskList = taskList; + } + + private ArrayList taskList = new ArrayList<>(); + Ui ui = new Ui(); + //Storage storage = new Storage(); + + public ArrayList getTaskList() { + return taskList; + } + + public void runDone(String userInput) { + int index = Integer.parseInt(userInput.split(" ")[1]); + Task chosenTask = taskList.get(index - 1); + chosenTask.markAsDone(); + ui.showDone(taskList , index); + //storage.save(); + } + + public void runDelete(String userInput) { + int index = Integer.parseInt(userInput.split(" ")[1]); + ui.showDelete(taskList , index); + taskList.remove(index - 1); + ui.showTaskListSize(taskList); + //storage.save(); + } + + public void runFind(String userInput) { + int index = 0 ; + ArrayList searchResults = new ArrayList<>(); + String keyword = userInput.split(" ")[1]; + for (Task task : taskList) { + String description = task.getDescription(); + if (description.contains(keyword)) { + searchResults.add(task); + } + } + ui.showMatchTasks(searchResults , index); + } + + public void runToDo(String description) { + Task toDoTask = new ToDo(description); + taskList.add(toDoTask); + ui.showAddTodoTask(taskList , toDoTask); + //storage.save(); + } + + public void runDeadline(String description , String time) { + + Task deadlineTask = new Deadline(description , time); + taskList.add(deadlineTask); + ui.showAddDeadlineTask(taskList , deadlineTask); + //storage.save(); + } + + public void runEvent(String description , String time) { + Task eventTask = new Event(description , time); + taskList.add(eventTask); + ui.showAddEventTask(taskList , eventTask); + //storage.save(); + } + + + + + + + + + +} diff --git a/src/main/java/Ui.java b/src/main/java/Ui.java new file mode 100644 index 00000000..883a6555 --- /dev/null +++ b/src/main/java/Ui.java @@ -0,0 +1,102 @@ +import duke.Task; + +import java.util.ArrayList; +import java.util.Scanner; + +public class Ui { + private Scanner scanner; + + public Ui() { + scanner = new Scanner(System.in); + } + + public String readUserInput() { + return scanner.nextLine(); + } + + public void showWelcome() { + String logo = " ____ _ \n" + + "| _ \\ _ _| | _____ \n" + + "| | | | | | | |/ / _ \\\n" + + "| |_| | |_| | < __/\n" + + "|____/ \\__,_|_|\\_\\___|\n"; + //showLine(); + //System.out.println("Hello from\n" + logo); + System.out.println("Hello! I'm Duke\nWhat can I do for you?"); + //showLine(); + } + + public void showTaskList(ArrayList taskList) { + //showLine(); + System.out.println("Here are the tasks in your list:"); + for (int i = 0; i < taskList.size(); i++) { + System.out.println((i + 1) + ". " + taskList.get(i)); + } + //showLine(); + } + + public void showExit() { + System.out.println("Bye. Hope to see you again soon!"); + } + + public void showDone(ArrayList taskList , int index) { + //showLine(); + System.out.println("Nice! I've marked this task as done:"); + System.out.println(taskList.get(index - 1)); + //showLine(); + } + + public void showDelete(ArrayList taskList , int index) { + //showLine(); + System.out.println("Noted. I've removed this task:"); + System.out.println(taskList.get(index - 1)); + } + + public void showTaskListSize(ArrayList taskList) { + System.out.println("Now you have " + taskList.size() + " tasks in the list."); + //showLine(); + } + + public void showMatchTasks(ArrayList searchResults , int index) { + //showLine(); + System.out.println("Here are the matching tasks in your list:"); + for (Task results : searchResults) { + index++; + System.out.println(index + "." + results); + } + //showLine(); + } + + public void showAddTodoTask(ArrayList taskList , Task todoTask) { + //showLine(); + System.out.println("Got it. I've added this task:"); + System.out.println(todoTask); + System.out.println("Now you have " + taskList.size() + " tasks in the list."); + //showLine(); + } + + public void showAddDeadlineTask(ArrayList taskList , Task deadlineTask) { + //showLine(); + System.out.println("Got it. I've added this task:"); + System.out.println(deadlineTask); + System.out.println("Now you have " + taskList.size() + " tasks in the list."); + //showLine(); + } + + public void showAddEventTask(ArrayList taskList , Task eventTask) { + //showLine(); + System.out.println("Got it. I've added this task:"); + System.out.println(eventTask); + System.out.println("Now you have " + taskList.size() + " tasks in the list."); + //showLine(); + } + + public void showError (String message) { + System.out.println("☹ OOPS!!!" + message); + } + + public void showLine() { + System.out.println("____________________________________________________________"); + } + +} diff --git a/src/main/java/data/duke.txt b/src/main/java/data/duke.txt new file mode 100644 index 00000000..c864b09e --- /dev/null +++ b/src/main/java/data/duke.txt @@ -0,0 +1,8 @@ +D | ✓ | return book | 20th of October 2017 , 6PM +E | ✘ | read book | 11th of September 2011 , 6PM +D | ✘ | return book | 10th of October 2019 , 7PM +D | ✘ | return book | 10th of October 2019 , 7PM +D | ✘ | return book | 10th of October 2019 , 7PM +D | ✘ | return book | 10th of October 2019 , 7PM +D | ✘ | return book | 10th of October 2019 , 7PM +D | ✘ | return book | 10th of October 2019 , 7PM diff --git a/src/main/java/duke/Deadline.java b/src/main/java/duke/Deadline.java new file mode 100644 index 00000000..21e93443 --- /dev/null +++ b/src/main/java/duke/Deadline.java @@ -0,0 +1,14 @@ +package duke; + +public class Deadline extends Task { + + public Deadline(String description , String time) { + super(description); + this.time = time; + this.type = "D"; + } + + public String toString() { + return "[" + this.type + "][" + this.getStatusIcon() + "] " + this.description + " (by: " + time + ")"; + } +} diff --git a/src/main/java/duke/Event.java b/src/main/java/duke/Event.java new file mode 100644 index 00000000..3b12c2bb --- /dev/null +++ b/src/main/java/duke/Event.java @@ -0,0 +1,15 @@ +package duke; + +public class Event extends Task { + + public Event(String description , String time) { + super(description); + this.time = time; + this.type = "E"; + } + public String toString() { + return "[" + this.type +"][" + this.getStatusIcon() + "] " + this.description + " (at: " + time + ")"; + } + + +} diff --git a/src/main/java/duke/Task.java b/src/main/java/duke/Task.java new file mode 100644 index 00000000..4ae4c441 --- /dev/null +++ b/src/main/java/duke/Task.java @@ -0,0 +1,42 @@ +package duke; + +public abstract class Task{ + + protected String description; + protected boolean isDone; + protected String type; + protected String time; + + public Task(String description) { + this.description = description; + this.isDone = false; + this.type = ""; + this.time = ""; + } + + public String getStatusIcon() { + return (isDone ? "\u2713" : "\u2718"); + } + + public String getType() { + return this.type; + } + + public String getDescription() { + return this.description; + } + + public String getTime() { + return this.time; + } + + public void markAsDone() { + this.isDone = true; + } + + public String toString() { + return "[" + this.getStatusIcon() + "] " + this.description; + } + +} + diff --git a/src/main/java/duke/ToDo.java b/src/main/java/duke/ToDo.java new file mode 100644 index 00000000..bb1fe45a --- /dev/null +++ b/src/main/java/duke/ToDo.java @@ -0,0 +1,12 @@ +package duke; + +public class ToDo extends Task { + public ToDo(String description) { + super(description); + this.type = "T"; + } + + public String toString() { + return "[" + this.type + "][" + this.getStatusIcon() + "] " + this.description; + } +} diff --git a/src/main/java/text-ui-test/ACTUAL.TXT b/src/main/java/text-ui-test/ACTUAL.TXT new file mode 100644 index 00000000..e7e457ca --- /dev/null +++ b/src/main/java/text-ui-test/ACTUAL.TXT @@ -0,0 +1,6 @@ +Hello! I'm Duke +What can I do for you? +Got it. I've added this task: +[D][✘] return book (by: 10th of October 2019 , 7PM) +Now you have 8 tasks in the list. +Bye. Hope to see you again soon! diff --git a/src/main/java/text-ui-test/EXPECTED.txt b/src/main/java/text-ui-test/EXPECTED.txt new file mode 100644 index 00000000..e7e457ca --- /dev/null +++ b/src/main/java/text-ui-test/EXPECTED.txt @@ -0,0 +1,6 @@ +Hello! I'm Duke +What can I do for you? +Got it. I've added this task: +[D][✘] return book (by: 10th of October 2019 , 7PM) +Now you have 8 tasks in the list. +Bye. Hope to see you again soon! diff --git a/src/main/java/text-ui-test/input.txt b/src/main/java/text-ui-test/input.txt new file mode 100644 index 00000000..75d0b131 --- /dev/null +++ b/src/main/java/text-ui-test/input.txt @@ -0,0 +1,2 @@ +deadline return book /by 10/10/2019 1900 +bye \ No newline at end of file diff --git a/src/main/java/text-ui-test/runtest.sh b/src/main/java/text-ui-test/runtest.sh new file mode 100755 index 00000000..e562d837 --- /dev/null +++ b/src/main/java/text-ui-test/runtest.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +# create bin directory if it doesn't exist +if [ ! -d "../bin" ] +then + mkdir ../bin +fi + +# delete output from previous run +if [ -e "./ACTUAL.TXT" ] +then + rm ACTUAL.TXT +fi + +# compile the code into the bin folder, terminates if error occurred +if ! javac -cp ~/Desktop/duke/src -Xlint:none -d ~/Desktop/duke/bin ~/Desktop/duke/src/main/java/*.java +then + echo "********** BUILD FAILURE **********" + exit 1 +fi + +# run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT +java -classpath ~/Desktop/duke/bin Duke < input.txt > ACTUAL.TXT + +# compare the output to the expected output +diff ACTUAL.TXT EXPECTED.TXT +if [ $? -eq 0 ] +then + echo "Test result: PASSED" + exit 0 +else + echo "Test result: FAILED" + exit 1 +fi \ No newline at end of file diff --git a/src/test/java/DukeTest.java b/src/test/java/DukeTest.java new file mode 100644 index 00000000..b1573688 --- /dev/null +++ b/src/test/java/DukeTest.java @@ -0,0 +1,10 @@ +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DukeTest { + @Test + public void dummyTest(){ + assertEquals(2, 2); + } +} diff --git a/src/test/java/duke/DeadlineTest.java b/src/test/java/duke/DeadlineTest.java new file mode 100644 index 00000000..437fcfba --- /dev/null +++ b/src/test/java/duke/DeadlineTest.java @@ -0,0 +1,25 @@ +package duke; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DeadlineTest { + @Test + void testToString() { + Deadline newDeadline = new Deadline("I need to test the code", "20/11/2019 1800"); + assertEquals("[D]" + "[\u2718]" + " " + "I need to test the code (by: tonight)", newDeadline.toString()); + } + + @Test + void getStatusIcon() { + Deadline newDeadline = new Deadline("I need to test the code", "20/11/2019 1800"); + assertEquals("\u2718", newDeadline.getStatusIcon()); + } + + @Test + void markAsDone() { + Deadline newDeadline = new Deadline("I need to test the code", "20/11/2019 1800"); + newDeadline.markAsDone(); + assertEquals("\u2713", newDeadline.getStatusIcon()); + } +} diff --git a/src/test/java/duke/EventTest.java b/src/test/java/duke/EventTest.java new file mode 100644 index 00000000..75900472 --- /dev/null +++ b/src/test/java/duke/EventTest.java @@ -0,0 +1,25 @@ +package duke; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class EventTest { + @Test + void testToString() { + Event newEvent = new Event("project meeting", "20/11/2019 1800"); + assertEquals("[E]" + "[\u2718]" + " " + "project meeting (at: 7th May)", newEvent.toString()); + } + + @Test + void getStatusIcon() { + Event newEvent = new Event("project meeting", "20/11/2019 1800"); + assertEquals("\u2718", newEvent.getStatusIcon()); + } + + @Test + void markAsDone() { + Event newEvent = new Event("project meeting", "20/11/2019 1800"); + newEvent.markAsDone(); + assertEquals("\u2713", newEvent.getStatusIcon()); + } +} diff --git a/src/test/java/duke/TodoTest.java b/src/test/java/duke/TodoTest.java new file mode 100644 index 00000000..a5a16a2d --- /dev/null +++ b/src/test/java/duke/TodoTest.java @@ -0,0 +1,26 @@ +package duke; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class TodoTest { + + @Test + void testToString() { + ToDo newTodo = new ToDo("I need to test the code"); + assertEquals("[T]" + "[\u2718]" + " " + "I need to test the code" , newTodo.toString()); + } + + @Test + void getStatusIcon() { + ToDo newToDo = new ToDo("I need to test the code"); + assertEquals("\u2718", newToDo.getStatusIcon()); + } + + @Test + void markAsDone() { + ToDo newToDo = new ToDo("I need to test the code"); + newToDo.markAsDone(); + assertEquals("\u2713", newToDo.getStatusIcon()); + } +}