diff --git a/src/main/java/Deadline.java b/src/main/java/Deadline.java new file mode 100644 index 0000000000..3fc9e71bb8 --- /dev/null +++ b/src/main/java/Deadline.java @@ -0,0 +1,40 @@ +public class Deadline extends Task { + + private String by; + + public Deadline(String description, String by) { + super(description); + this.by = by; + } + + + private static void checkFormat(String formattedString) throws DukeException { + int byIndex = formattedString.indexOf("/by "); + if (byIndex == -1) + byIndex = formattedString.length(); + + String keyword = formattedString.split(" ", 2)[0]; + + if (!keyword.startsWith("deadline")) + throw new DukeException("I can't seem to find the deadline keyword"); + else if (formattedString.length() <= 9 || formattedString.substring(9, byIndex).isEmpty()) + throw new DukeException("the description of deadline cannot be empty"); + else if (byIndex == formattedString.length() || formattedString.length() < byIndex + 5) + throw new DukeException("the [/by] time of deadline cannot be empty"); + } + + //Format: "Deadline: [description] /by [on] + public static Deadline create(String formattedString) throws DukeException { + checkFormat(formattedString); + + int onIndex = formattedString.indexOf("/by"); + return new Deadline(formattedString.substring(9, onIndex), + formattedString.substring(onIndex + 4)); + } + + @Override + public String toString() { + char statusIcon = this.isDone ? 'X' : ' '; + return String.format("[%c] Deadline: %s(by: %s)", statusIcon, this.description, this.by); + } +} diff --git a/src/main/java/Duke.java b/src/main/java/Duke.java index 5d313334cc..2b56c66e82 100644 --- a/src/main/java/Duke.java +++ b/src/main/java/Duke.java @@ -1,10 +1,106 @@ +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Scanner; +import java.util.function.Consumer; +import java.util.function.Function; + public class Duke { + + private static final ArrayList taskList = new ArrayList<>(); + public static void main(String[] args) { + String sectionBreak = "------------------------------------------"; String logo = " ____ _ \n" + "| _ \\ _ _| | _____ \n" + "| | | | | | | |/ / _ \\\n" + "| |_| | |_| | < __/\n" + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); + + System.out.println("\nHello buddy! I am"); + System.out.println(logo); + System.out.println("What can I do for you?"); + System.out.println(sectionBreak); + + Scanner sc=new Scanner(System.in); + + Hashtable> commandTable = new Hashtable<>(); + commandTable.put("list", (x) -> printTaskList()); + commandTable.put("event", (x) -> AddTask(x, Event::create)); + commandTable.put("deadline", (x) -> AddTask(x, Deadline::create)); + commandTable.put("todo", (x) -> AddTask(x, ToDo::create)); + commandTable.put("done", Duke::MarkTask); + commandTable.put("delete", Duke::DeleteTask); + + + while (true) { + String input = sc.nextLine(); + + if (input.equals("bye")) break; + + String keyword = input.split(" ", 2)[0]; + try { + if (commandTable.containsKey(keyword)) + commandTable.get(keyword).accept(input); + else + throw new DukeException("I'm not sure what you mean"); + } catch (DukeException e) { + System.out.println(e); + } + System.out.println(sectionBreak); + } + + System.out.println("Bye. Hope to see you soon!"); + System.out.println(sectionBreak); + } + + private static void AddTask(String formattedString, Function create) { + Task e = create.apply(formattedString); + taskList.add(e); + System.out.printf("added: %s\n", e); + } + + private static void printTaskList() { + for (int i = 0; i < taskList.size(); i++) { + System.out.printf("%d. %s\n", i + 1, taskList.get(i)); + } + } + + private static int getId(String input, String prefix) throws DukeException { + String idString = ""; + try { + if (!input.startsWith(prefix) || input.length() <= prefix.length()) + throw new DukeException("you did not specify a task id"); + + idString = input.substring(prefix.length()); + return Integer.parseInt(idString); + + } catch (NumberFormatException e) { + String msg = String.format("\"%s\" is not a valid integer", idString); + throw new DukeException(msg); + } + } + + private static void MarkTask(String input) { + int taskId = -1; + try { + taskId = getId(input, "done "); + Task t = taskList.get(taskId - 1); + t.markAsDone(); + System.out.println("Cool, I've marked this task as done\n" + t); + } catch (IndexOutOfBoundsException e) { + System.out.printf("Oops, Task #%d doesn't exist\n", taskId); + } + } + + private static void DeleteTask(String input) { + int taskId = -1; + try { + taskId = getId(input, "delete "); + Task t = taskList.get(taskId - 1); + taskList.remove(taskId); + System.out.println("Okay, I've removed this task\n" + t); + } catch (IndexOutOfBoundsException e) { + System.out.printf("Oops, Task #%d doesn't exist\n", taskId); + } } } diff --git a/src/main/java/DukeException.java b/src/main/java/DukeException.java new file mode 100644 index 0000000000..4ce7b372fd --- /dev/null +++ b/src/main/java/DukeException.java @@ -0,0 +1,11 @@ +public class DukeException extends RuntimeException { + + public DukeException(String message) { + super(message); + } + + @Override + public String toString() { + return String.format("Oops, %s :(", this.getMessage()); + } +} diff --git a/src/main/java/Event.java b/src/main/java/Event.java new file mode 100644 index 0000000000..8e0a77def3 --- /dev/null +++ b/src/main/java/Event.java @@ -0,0 +1,39 @@ +public class Event extends Task { + + private String on; + + public Event(String description, String on) { + super(description); + this.on = on; + } + + private static void checkFormat(String formattedString) throws DukeException { + int onIndex = formattedString.indexOf("/on "); + if (onIndex == -1) + onIndex = formattedString.length(); + + String keyword = formattedString.split(" ", 2)[0]; + + if (!keyword.startsWith("event")) + throw new DukeException("I can't seem to find the event keyword"); + else if (formattedString.length() <= 6 || formattedString.substring(6, onIndex).isEmpty()) + throw new DukeException("the description of event cannot be empty"); + else if (onIndex == formattedString.length() || formattedString.length() < onIndex + 5) + throw new DukeException("the [/on] time of event cannot be empty"); + } + + //Format: "Event: [description] /by [on] + public static Event create(String formattedString) throws DukeException { + checkFormat(formattedString); + + int onIndex = formattedString.indexOf("/on "); + return new Event(formattedString.substring(6, onIndex), + formattedString.substring(onIndex + 4)); + } + + @Override + public String toString() { + char statusIcon = this.isDone ? 'X' : ' '; + return String.format("[%c] Event: %s(on: %s)", statusIcon, this.description, this.on); + } +} diff --git a/src/main/java/Task.java b/src/main/java/Task.java new file mode 100644 index 0000000000..84a1c9a3b5 --- /dev/null +++ b/src/main/java/Task.java @@ -0,0 +1,19 @@ +public abstract class Task { + protected String description; + protected boolean isDone; + + public Task(String description) { + this.description = description; + this.isDone = false; + } + + public void markAsDone() { + this.isDone = true; + } + + @Override + public String toString() { + char statusIcon = this.isDone ? 'X' : ' '; + return String.format("[%c] %s", statusIcon, this.description); + } +} \ No newline at end of file diff --git a/src/main/java/ToDo.java b/src/main/java/ToDo.java new file mode 100644 index 0000000000..51fb13e36e --- /dev/null +++ b/src/main/java/ToDo.java @@ -0,0 +1,27 @@ +public class ToDo extends Task { + + public ToDo(String description) { + super(description); + } + + private static void checkFormat(String formattedString) throws DukeException { + String keyword = formattedString.split(" ", 2)[0]; + + if (!keyword.equals("todo")) + throw new DukeException("I can't seem to find the todo keyword"); + else if (formattedString.length() <= 5 || formattedString.substring(5).isEmpty()) + throw new DukeException("the description of todo cannot be empty"); + } + + public static ToDo create(String formattedString) throws DukeException { + checkFormat(formattedString); + return new ToDo(formattedString.substring(5)); + } + + + @Override + public String toString() { + char statusIcon = this.isDone ? 'X' : ' '; + return String.format("[%c] ToDo: %s", statusIcon, this.description); + } +} diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 657e74f6e7..a9871eadd0 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,7 +1,73 @@ -Hello from + +Hello buddy! I am ____ _ | _ \ _ _| | _____ | | | | | | | |/ / _ \ | |_| | |_| | < __/ |____/ \__,_|_|\_\___| +What can I do for you? +------------------------------------------ +added: [ ] Event: dinner (on: 27th March) +------------------------------------------ +1. [ ] Event: dinner (on: 27th March) +------------------------------------------ +added: [ ] Deadline: homework (by: 30th April) +------------------------------------------ +1. [ ] Event: dinner (on: 27th March) +2. [ ] Deadline: homework (by: 30th April) +------------------------------------------ +added: [ ] ToDo: visit the gym +------------------------------------------ +1. [ ] Event: dinner (on: 27th March) +2. [ ] Deadline: homework (by: 30th April) +3. [ ] ToDo: visit the gym +------------------------------------------ +Cool, I've marked this task as done +[X] Event: dinner (on: 27th March) +------------------------------------------ +1. [X] Event: dinner (on: 27th March) +2. [ ] Deadline: homework (by: 30th April) +3. [ ] ToDo: visit the gym +------------------------------------------ +Cool, I've marked this task as done +[X] Deadline: homework (by: 30th April) +------------------------------------------ +1. [X] Event: dinner (on: 27th March) +2. [X] Deadline: homework (by: 30th April) +3. [ ] ToDo: visit the gym +------------------------------------------ +Okay, I've removed this task +[X] Deadline: homework (by: 30th April) +------------------------------------------ +1. [X] Event: dinner (on: 27th March) +2. [X] Deadline: homework (by: 30th April) +------------------------------------------ +Oops, the [/on] time of event cannot be empty :( +------------------------------------------ +Oops, the [/on] time of event cannot be empty :( +------------------------------------------ +Oops, the description of event cannot be empty :( +------------------------------------------ +Oops, the [/by] time of deadline cannot be empty :( +------------------------------------------ +Oops, the [/by] time of deadline cannot be empty :( +------------------------------------------ +Oops, the description of deadline cannot be empty :( +------------------------------------------ +Oops, the description of todo cannot be empty :( +------------------------------------------ +Oops, you did not specify a task id :( +------------------------------------------ +Oops, "a" is not a valid integer :( +------------------------------------------ +Oops, Task #4 doesn't exist +------------------------------------------ +Oops, you did not specify a task id :( +------------------------------------------ +Oops, "3.14" is not a valid integer :( +------------------------------------------ +Oops, Task #8 doesn't exist +------------------------------------------ +Bye. Hope to see you soon! +------------------------------------------ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e69de29bb2..6897784646 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -0,0 +1,26 @@ +event dinner /on 27th March +list +deadline homework /by 30th April +list +todo visit the gym +list +done 1 +list +done 2 +list +delete 2 +list +event lunch +event lunch /on +event +deadline project +deadline project /by +deadline +todo +done +done a +done 4 +delete +delete 3.14 +delete 8 +bye diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh index e169618a34..7452b155ea 100644 --- a/text-ui-test/runtest.sh +++ b/text-ui-test/runtest.sh @@ -13,7 +13,7 @@ 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/*.java then echo "********** BUILD FAILURE **********" exit 1 @@ -24,7 +24,7 @@ java -classpath ../bin Duke < input.txt > ACTUAL.TXT # convert to UNIX format cp EXPECTED.TXT EXPECTED-UNIX.TXT -dos2unix ACTUAL.TXT EXPECTED-UNIX.TXT +# dos2unix ACTUAL.TXT EXPECTED-UNIX.TXT # compare the output to the expected output diff ACTUAL.TXT EXPECTED-UNIX.TXT