diff --git a/README.md b/README.md index 9d95025bce..da61b7869f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Duke project template +# duke project template This is a project template for a greenfield Java project. It's named after the Java mascot _Duke_. Given below are instructions on how to use it. @@ -15,7 +15,7 @@ Prerequisites: JDK 11, update Intellij to the most recent version. 1. Click `Open or Import`. 1. Select the project directory, and click `OK` 1. If there are any further prompts, accept the defaults. -1. After the importing is complete, locate the `src/main/java/Duke.java` file, right-click it, and choose `Run Duke.main()`. If the setup is correct, you should see something like the below: +1. After the importing is complete, locate the `src/main/java/duke.java` file, right-click it, and choose `Run duke.main()`. If the setup is correct, you should see something like the below: ``` Hello from ____ _ diff --git a/duke.txt b/duke.txt new file mode 100644 index 0000000000..273fb4c833 --- /dev/null +++ b/duke.txt @@ -0,0 +1,3 @@ +T|false|read book +T|false|return book +T|false|borrow book diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java deleted file mode 100644 index 5d313334cc..0000000000 --- a/src/main/java/Duke.java +++ /dev/null @@ -1,10 +0,0 @@ -public class Duke { - public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - } -} diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..2c9a9745c5 --- /dev/null +++ b/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: duke.Duke + diff --git a/src/main/java/duke/Duke.java b/src/main/java/duke/Duke.java new file mode 100644 index 0000000000..9c8796fc8f --- /dev/null +++ b/src/main/java/duke/Duke.java @@ -0,0 +1,30 @@ +package duke; + +import java.io.IOException; + +public class Duke { + private static Storage storage; + private static TaskList tasks; + private static Ui ui; + private static final String FILE_PATH="duke.txt"; + public static int thingsCounted = 0; + + public Duke(String filePath) throws IOException { + ui = new Ui(); + storage = new Storage(filePath); + tasks = new TaskList(); + } + + public void run() throws DukeException { + thingsCounted = storage.readFromFile(tasks); + ui.start(); + ui.count(thingsCounted); + ui.doTasks(tasks); + ui.end(); + storage.writeToFile(tasks); + } + + public static void main(String[] args) throws DukeException, IOException { + new Duke(FILE_PATH).run(); + } +} \ No newline at end of file diff --git a/src/main/java/duke/DukeException.java b/src/main/java/duke/DukeException.java new file mode 100644 index 0000000000..e7ae283939 --- /dev/null +++ b/src/main/java/duke/DukeException.java @@ -0,0 +1,5 @@ +package duke; + +public class DukeException extends Exception { + +} diff --git a/src/main/java/duke/Parser.java b/src/main/java/duke/Parser.java new file mode 100644 index 0000000000..8dc55e7e7d --- /dev/null +++ b/src/main/java/duke/Parser.java @@ -0,0 +1,49 @@ +package duke; + +import java.time.format.DateTimeFormatter; +import java.time.LocalDate; + +public class Parser { + public static String getCommand(String command) { + try{ + if (command.equals("list")) { + return "list"; + } else if (command.equals("bye")) { + return "bye"; + } else if ( command.equals("todo") || command.equals("deadline") + || command.equals("event") || command.equals("done") + || command.equals("delete")) { + throw new DukeException(); + } else if (command.contains("todo")) { + return "todo"; + } else if (command.contains("event")) { + return "event"; + } else if (command.contains("deadline")) { + return "deadline"; + } else if (command.contains("delete")) { + return "delete"; + } else if (command.contains("done")) { + return "done"; + } else if (command.contains("find")) { + return "find"; + } else { + throw new DukeException(); + } + } catch (DukeException e) { + Ui.dealWithException(command); + return "fail"; + } + } + + public static String getDateFormat(String datetime) { + LocalDate date; + String dateForm; + try { + date = LocalDate.parse(datetime); + dateForm = date.format(DateTimeFormatter.ofPattern("MMM dd yyyy")); + } catch (Exception e) { + dateForm = datetime; + } + return dateForm; + } +} diff --git a/src/main/java/duke/Storage.java b/src/main/java/duke/Storage.java new file mode 100644 index 0000000000..b449ecd5d2 --- /dev/null +++ b/src/main/java/duke/Storage.java @@ -0,0 +1,64 @@ +package duke; + +import duke.task.Deadline; +import duke.task.Event; +import duke.task.Task; +import duke.task.Todo; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Scanner; + +public class Storage { + public static ArrayList taskArrayList; + private static File f; + private static String filePath; + public static int fileTasksCounted = 0; + + public static void writeToFile(TaskList tasks){ + try { + FileWriter fw = new FileWriter(filePath); + taskArrayList = tasks.getTasksList(); + for(Task task: taskArrayList) { + fw.write(task.printIntoFile() + "\n"); + } + fw.close(); + } catch (IOException e) { + System.out.println("Error writing file"); + } + } + + public static int readFromFile(TaskList tasks){ + try { + Scanner sc = new Scanner(f); + Task task; + while(sc.hasNext()){ + String[] taskInFile = sc.nextLine().split("\\|"); + if(taskInFile[0].equals("T")){ + task = new Todo(taskInFile[2]); + }else if(taskInFile[0].equals("D")){ + task = new Deadline(taskInFile[2],taskInFile[3]); + }else{ + task = new Event(taskInFile[2], taskInFile[3]); + } + fileTasksCounted++; + if(taskInFile[1].equals("true")){ + task.taskDone(); + } + tasks.add(task); + } + } catch (FileNotFoundException e) { + System.out.println("Error reading file"); + } + return fileTasksCounted; + } + + public Storage(String filePath) throws IOException { + f = new File(filePath); + f.createNewFile(); + this.filePath=filePath; + } +} \ No newline at end of file diff --git a/src/main/java/duke/TaskList.java b/src/main/java/duke/TaskList.java new file mode 100644 index 0000000000..891f8b54ad --- /dev/null +++ b/src/main/java/duke/TaskList.java @@ -0,0 +1,119 @@ +package duke; + +import duke.task.Deadline; +import duke.task.Event; +import duke.task.Task; +import duke.task.Todo; + +import java.util.ArrayList; +import static java.util.stream.Collectors.toList; + +public class TaskList { + public static ArrayList tasksList; + + public TaskList(){ + this.tasksList = new ArrayList<>(); + } + + public TaskList(ArrayList tasksList){ + this.tasksList = tasksList; + } + + public void add(Task task){ + tasksList.add(task); + } + + public Task remove(int index){ + Task removeTask = tasksList.remove(index); + return removeTask; + } + + public Task get(int index){ + Task getTask=tasksList.get(index); + return getTask; + } + + public ArrayList getTasksList(){ + return tasksList; + } + + public static void listTasks() { + int count = 1; + for(Task task : tasksList){ + System.out.print(count + ". "); + System.out.println(task); + count++; + } + } + + public static void findTasks(String command) { + String findText = command.substring(4); + ArrayList findTasks = (ArrayList) tasksList.stream() + .filter((t) -> t.getDescription().contains(findText)) + .collect(toList()); + System.out.println("Here are the matching tasks in your list:"); + int count = 1; + for(Task task : findTasks){ + System.out.print(count + ". "); + System.out.println(task); + count++; + } + if(count==1){ + System.out.println("no matching result"); + } + } + + public static void addTodoTask(String command) throws DukeException{ + String todoDescription; + todoDescription = command.substring(4); + Task task = new Todo(todoDescription); + tasksList.add(task); + Ui.printTask(task); + } + + public static void addDeadlineTask(String command) throws DukeException{ + String deadlineDescription; + String deadlineDate; + int index; + index = command.indexOf("/"); + deadlineDescription = command.substring(9,index-1); + deadlineDate = command.substring(index+4); + Task task = new Deadline(deadlineDescription, deadlineDate); + tasksList.add(task); + Ui.printTask(task); + + } + + public static void addEventTask(String command) throws DukeException{ + String eventDescription; + String eventDate; + int index; + index = command.indexOf("/"); + eventDescription = command.substring(6,index-1); + eventDate = command.substring(index+4); + Task task = new Event(eventDescription, eventDate); + tasksList.add(task); + Ui.printTask(task); + } + + public static void markTaskAsDone(String command, int countTasks) throws DukeException{ + int index = Integer.parseInt(command.substring(4)); + if(index > countTasks){ + throw new DukeException(); + } + tasksList.get(index-1).taskDone(); + System.out.println("Nice! I've marked this task as done:\n" + tasksList.get(index-1)); + } + + public static void delete(String command, int tasksCounted) throws DukeException { + int index = Integer.parseInt(command.substring(6)); + if(index > tasksCounted){ + throw new DukeException(); + } + Task task = tasksList.remove(index - 1); + tasksCounted--; + System.out.println("Noted. I've removed this task: "); + System.out.println(task); + System.out.println("Now you have " + tasksCounted + " tasks in the list."); + } +} \ No newline at end of file diff --git a/src/main/java/duke/Ui.java b/src/main/java/duke/Ui.java new file mode 100644 index 0000000000..fb675c155a --- /dev/null +++ b/src/main/java/duke/Ui.java @@ -0,0 +1,93 @@ +package duke; + +import duke.task.Task; + +import java.util.Scanner; + +public class Ui { + public Parser parser; + public static int tasksCounted = 0; + + public void count(int thingsCounted){ + this.tasksCounted =thingsCounted; + } + + public void doTasks(TaskList tasks) throws DukeException{ + String input; + Scanner in = new Scanner(System.in); + while(in.hasNextLine()){ + input = in.nextLine(); + Ui.printLine(); + String command = parser.getCommand(input); + switch (command) { + case "list": + tasks.listTasks(); + break; + case "done": + tasks.markTaskAsDone(command, tasksCounted); + break; + case "todo": + tasksCounted++; + tasks.addTodoTask(command); + break; + case "deadline": + tasksCounted++; + tasks.addDeadlineTask(command); + break; + case "event": + tasksCounted++; + tasks.addEventTask(command); + break; + case "delete": + tasks.delete(command, tasksCounted); + break; + case "find": + tasks.findTasks(command); + break; + case "bye": + return; + } + Ui.printLine(); + } + } + + public static void printTask(Task task){ + System.out.println("Got it. I've added this task:"); + System.out.println(task); + System.out.println("Now you have " + tasksCounted + " tasks in the list."); + } + + public static void dealWithException(String inputLine){ + if(inputLine.equals("todo")){ + System.out.println("☹ OOPS!!! The description of a todo cannot be empty."); + }else if(inputLine.equals("deadline")){ + System.out.println("☹ OOPS!!! The description of a deadline cannot be empty."); + }else if(inputLine.equals("event")) { + System.out.println("☹ OOPS!!! The description of a event cannot be empty."); + }else if(inputLine.contains("done")) { + System.out.println("☹ OOPS!!! The done index is out of bound."); + }else if(inputLine.contains("delete")) { + System.out.println("☹ OOPS!!! The delete index is out of bound."); + }else{ + System.out.println(("☹ OOPS!!! I'm sorry, but I don't know what that means :-(")); + } + } + + public static void end(){ + System.out.println("Bye. Hope to see you again soon"); + printLine(); + } + + public static void printLine(){ + System.out.println("____________________________________________________________"); + } + + public static void start(){ + String startGreet = "____________________________________________________________\n" + + " Hello! I'm Duke\n" + + " What can I do for you?\n" + + "____________________________________________________________\n"; + + System.out.println(startGreet); + } +} \ No newline at end of file diff --git a/src/main/java/duke/task/Deadline.java b/src/main/java/duke/task/Deadline.java new file mode 100644 index 0000000000..2ed94e0fc9 --- /dev/null +++ b/src/main/java/duke/task/Deadline.java @@ -0,0 +1,27 @@ +package duke.task; + +import duke.Parser; + +public class Deadline extends Task { + + protected String byDate; + protected Parser parser; + + public Deadline(String description, String byDate) { + super(description); + byDate = parser.getDateFormat(byDate); + this.byDate=byDate; + } + + public String getTypeIcon(){ + return "[D]"; + } + + public String toString(){ + return this.getTypeIcon() + this.getStatusIcon() + description + " (by: " + byDate + ")"; + } + + public String printIntoFile(){ + return "D|" + isDone + "|" + description + "|" + this.byDate; + } +} diff --git a/src/main/java/duke/task/Event.java b/src/main/java/duke/task/Event.java new file mode 100644 index 0000000000..506308072a --- /dev/null +++ b/src/main/java/duke/task/Event.java @@ -0,0 +1,26 @@ +package duke.task; + +import duke.Parser; + +public class Event extends Task{ + protected String atDate; + protected Parser parser; + + public Event(String description, String atDate) { + super(description); + atDate = parser.getDateFormat(atDate); + this.atDate=atDate; + } + + public String getTypeIcon(){ + return "[E]"; + } + + public String toString() { + return this.getTypeIcon() + this.getStatusIcon() + description + " (at: " + atDate + ")"; + } + + public String printIntoFile(){ + return "E|" + isDone + "|" + description + "|" + this.atDate; + } +} diff --git a/src/main/java/duke/task/Task.java b/src/main/java/duke/task/Task.java new file mode 100644 index 0000000000..a87ec23f20 --- /dev/null +++ b/src/main/java/duke/task/Task.java @@ -0,0 +1,34 @@ +package duke.task; + +public class Task { + protected String description; + protected boolean isDone; + + public Task(String description) { + this.description = description; + this.isDone = false; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getDescription(){ + return description; + } + public String getStatusIcon() { + return (isDone ? "[\u2713]" : "[\u2718]"); //return tick or X symbols + } + + public void taskDone(){ + this.isDone=true; + } + + public String toString(){ + return this.getStatusIcon() + description; + } + + public String printIntoFile(){ + return "Task|" + isDone + "|" + description + "|"; + } +} diff --git a/src/main/java/duke/task/Todo.java b/src/main/java/duke/task/Todo.java new file mode 100644 index 0000000000..fd3e2b8786 --- /dev/null +++ b/src/main/java/duke/task/Todo.java @@ -0,0 +1,20 @@ +package duke.task; + +public class Todo extends Task{ + + public Todo(String description) { + super(description); + } + + public String getTypeIcon(){ + return "[T]"; + } + + public String toString(){ + return this.getTypeIcon() + this.getStatusIcon() + description; + } + + public String printIntoFile(){ + return "T|" + isDone + "|" + description; + } +} diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 657e74f6e7..64156e390e 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,7 +1,35 @@ -Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| +____________________________________________________________ + Hello! I'm duke + What can I do for you? +____________________________________________________________ +____________________________________________________________ +Got it. I've added this task: +[T][✘]borrow book +Now you have 1 tasks in the list. +____________________________________________________________ +____________________________________________________________ +1. [T][✘]borrow book +____________________________________________________________ +____________________________________________________________ +Got it. I've added this task: +[D][✘]return book (by: Sunday) +Now you have 2 tasks in the list. +____________________________________________________________ +____________________________________________________________ +Got it. I've added this task: +[D][✘]project (at: Mon 2-4pm) +Now you have 3 tasks in the list. +____________________________________________________________ +____________________________________________________________ +1. [T][✘]borrow book +2. [D][✘]return book (by: Sunday) +3. [E][✘]project (at: Mon 2-4pm) +____________________________________________________________ +____________________________________________________________ +Nice! I've marked this task as done: +[D][✓]return book (by: Sunday) +____________________________________________________________ +____________________________________________________________ +Bye. Hope to see you again soon +____________________________________________________________ \ No newline at end of file diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e69de29bb2..55eb8a0066 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -0,0 +1,7 @@ +todo borrow book +list +deadline return book /by Sunday +event project /at Mon 2-4pm +list +done 2 +bye \ No newline at end of file diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat index d0facc6310..1f3b5a5233 100644 --- a/text-ui-test/runtest.bat +++ b/text-ui-test/runtest.bat @@ -7,7 +7,7 @@ REM delete output from previous run del ACTUAL.TXT REM compile the code into the bin folder -javac -cp ..\src -Xlint:none -d ..\bin ..\src\main\java\Duke.java +javac -cp ..\src -Xlint:none -d ..\bin ..\src\main\java\*.java IF ERRORLEVEL 1 ( echo ********** BUILD FAILURE ********** exit /b 1 @@ -15,7 +15,7 @@ IF ERRORLEVEL 1 ( REM no error here, errorlevel == 0 REM run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT -java -classpath ..\bin Duke < input.txt > ACTUAL.TXT +java -classpath ..\bin duke.Duke < input.txt > ACTUAL.TXT REM compare the output to the expected output FC ACTUAL.TXT EXPECTED.TXT diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh index e169618a34..d3aaadd290 100644 --- a/text-ui-test/runtest.sh +++ b/text-ui-test/runtest.sh @@ -13,21 +13,17 @@ then fi # compile the code into the bin folder, terminates if error occurred -if ! javac -cp ../src -Xlint:none -d ../bin ../src/main/java/Duke.java +if ! javac -cp ../src -Xlint:none -d ../bin ../src/main/java/duke/*.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 ../bin Duke < input.txt > ACTUAL.TXT - -# convert to UNIX format -cp EXPECTED.TXT EXPECTED-UNIX.TXT -dos2unix ACTUAL.TXT EXPECTED-UNIX.TXT +java -classpath ../bin duke/Duke < input.txt > ACTUAL.TXT # compare the output to the expected output -diff ACTUAL.TXT EXPECTED-UNIX.TXT +diff ACTUAL.TXT EXPECTED.TXT if [ $? -eq 0 ] then echo "Test result: PASSED"