-
Notifications
You must be signed in to change notification settings - Fork 316
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Sng Jia Ming Fadi Faris] Duke Increments #345
base: master
Are you sure you want to change the base?
Changes from 19 commits
65f72a8
0112efe
cfd6da7
6e6ace1
ba11701
c80085c
244fb4c
c0d63f6
47514be
6cc2e4d
b382bd3
7fc08ec
72b02cc
a9033c2
1c677e6
31cc0a3
4ea22d1
4065b7f
743b785
8c1dace
126535c
02cf134
9e1c42d
de2854d
625f50e
9e36be2
646cc92
1ebbacc
474710e
e6e293d
e71990a
e32e2e1
615cda1
cc3d359
c878f87
77a0e35
ecd4eb2
57ada88
72e8820
1639538
2220297
e979df1
c8aea88
2a8a2ce
56de869
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/** | ||
* Represents the command to add a task into the arraylist. | ||
*/ | ||
|
||
import java.text.ParseException; | ||
|
||
public class AddCommand extends Command { | ||
private String[] arr; | ||
|
||
public AddCommand(String[] arr) { | ||
this.arr = arr; | ||
} | ||
|
||
@Override | ||
public void execute(TaskList tasks, Ui ui, Storage storage){ | ||
String description = ""; | ||
Task t; | ||
String next = arr[0]; | ||
try { | ||
if (next.equals("todo") || next.equals("deadline") || next.equals("event")) { | ||
if (arr.length == 1) { | ||
throw new EmptyDescriptionException("☹ OOPS!!! The description of a " + next + " cannot be empty."); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may be a little easier to have the message already in toString() method of EmptyDescriptionException, so you only have take in the type as a parameter. E.g throw new EmptyDescriptionException("todo"). Since you will be throwing this exception frequently, you won't need to type the message everytime. :) |
||
} else { | ||
for (int i = 1; i < arr.length; i++) { | ||
description += " " + arr[i]; | ||
} | ||
} | ||
} else { | ||
throw new UnknownTaskException("☹ OOPS!!! I'm sorry, but I don't know what that means :-("); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may be a little easier to have the message already in toString() method of UnknownTaskException :) |
||
} | ||
System.out.println("Got it. I've added this task:"); | ||
if (next.equals("todo")) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if this is better, but it used switch case so that .equals(...) would not be used that often :) |
||
t = new Todos(description.trim()); | ||
} else if (next.equals("deadline")) { | ||
int index = description.indexOf("/"); | ||
String byWhen = description.substring(index + 4); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea! Another idea to split your string by "...".split("/by") instead so you would not need to care about the index:) |
||
String desc = description.substring(1, index - 1); | ||
t = new Deadline(desc, byWhen); | ||
} else { | ||
int index = description.indexOf("/"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a smart idea! You can also split the string by "...".split("/at") so you would not need to count the index. :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to add on, if you use the indexOf("/"), this might not have the intended effect when you have a deadline task initialised with the following command as an example: |
||
String at = description.substring(index + 4); | ||
String desc = description.substring(1, index - 1); | ||
t = new Event(desc, at); | ||
} | ||
tasks.getList().add(t); | ||
ui.printTask(tasks.getList().size(), t); | ||
} catch (DukeException e) { | ||
System.out.println(e.getMessage()); | ||
} catch (ParseException e) { | ||
System.out.println("Date in wrong format"); | ||
} | ||
storage.writeFile(tasks.getList()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/** | ||
* Abstract class to represent the possible commands given to Duke. | ||
*/ | ||
|
||
public abstract class Command { | ||
|
||
/** | ||
* Executes the different commands respectively. | ||
* @param tasks Arraylist of tasks. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it may be a good idea to add attributes like isDone or methods like markAsDone() to encapsulate whether as task is done(needed when we load tasks from the file). Since all tasks need this. :) |
||
* @param ui User interaction that comes with the command. | ||
* @param storage To deal with saving tasks into the file after executing the command. | ||
*/ | ||
public abstract void execute(TaskList tasks, Ui ui, Storage storage); | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/** | ||
* Deadline class to represent a task with a date to be done by. | ||
*/ | ||
|
||
import java.text.ParseException; | ||
import java.util.Date; | ||
import java.text.SimpleDateFormat; | ||
|
||
public class Deadline extends Task { | ||
|
||
protected String by; | ||
protected Date date; | ||
|
||
public Deadline(String description, String by) throws ParseException { | ||
super(description); | ||
this.by = by; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just wondering, why do you need by and date attributes? As I was thinking that since they are similar representations of the same thing, and date can also be used in the toString() method, it is alright to keep date only. :) |
||
this.date = new SimpleDateFormat("dd/MM/yyyy HHmm").parse(by); | ||
} | ||
|
||
public Deadline(String description, boolean isDone, String by) throws ParseException { | ||
super(description, isDone); | ||
this.by = by; | ||
this.date = new SimpleDateFormat("dd/MM/yyyy HHmm").parse(by); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
SimpleDateFormat formatter = new SimpleDateFormat("d MMMM yyyy, hmma"); | ||
String formattedDate = formatter.format(this.date); | ||
return "[D]" + super.toString() + " (by: " + formattedDate + ")"; | ||
} | ||
|
||
@Override | ||
public String print() { | ||
if (this.isDone) { | ||
return "D @ 1 @ " + this.description + " @ " + this.by; | ||
} else { | ||
return "D @ 0 @ " + this.description + " @ " + this.by; | ||
} | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider adding newlines at the end of your files, as it is a general convention. It doesn't really cause any issues beside making GitHub and checkstyle whine, but there is a reason behind doing so, https://stackoverflow.com/questions/729692/why-should-text-files-end-with-a-newline. Hope this gives some insight! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/** | ||
* Represents a command to remove a task from the arraylist. | ||
*/ | ||
|
||
public class DeleteCommand extends Command { | ||
private int taskNumber; | ||
|
||
public DeleteCommand(int taskNumber) { | ||
this.taskNumber = taskNumber; | ||
} | ||
|
||
@Override | ||
public void execute(TaskList tasks, Ui ui, Storage storage) { | ||
Task taskRemoved = tasks.getList().remove(taskNumber); | ||
System.out.println("Noted. I've removed this task:"); | ||
ui.printTask(tasks.getList().size(), taskRemoved); | ||
storage.writeFile(tasks.getList()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/** | ||
* Represents a command that ticks off a task. | ||
*/ | ||
|
||
public class DoneCommand extends Command { | ||
private int taskNumber; | ||
|
||
public DoneCommand(int taskNumber) { | ||
this.taskNumber = taskNumber; | ||
} | ||
@Override | ||
public void execute(TaskList tasks, Ui ui, Storage storage) { | ||
Task taskDone = tasks.getList().get(taskNumber); | ||
taskDone.markAsDone(); | ||
System.out.println("Nice! I've marked this task as done:\n " + taskDone); | ||
storage.writeFile(tasks.getList()); | ||
} | ||
|
||
public int getTaskNumber() { | ||
return taskNumber; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (obj == this) { | ||
return true; | ||
} else if (obj == null || obj.getClass() != this.getClass()) { | ||
return false; | ||
} else { | ||
DoneCommand command = (DoneCommand) obj; | ||
return taskNumber == command.getTaskNumber(); | ||
} | ||
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,37 @@ | ||
/** | ||
* Main driving class for Duke. | ||
*/ | ||
|
||
import java.io.FileNotFoundException; | ||
import java.io.IOException; | ||
import java.text.ParseException; | ||
|
||
public class Duke { | ||
|
||
private Storage storage; | ||
private TaskList list; | ||
private Ui ui; | ||
|
||
public Duke(String file) { | ||
ui = new Ui(); | ||
storage = new Storage(file); | ||
list = new TaskList(storage.load()); | ||
} | ||
|
||
public void run() { | ||
ui.showWelcome(); | ||
boolean isExit = false; | ||
while (!isExit) { | ||
String fullCommand = ui.readCommand(); | ||
Command c = Parser.parse(fullCommand); | ||
c.execute(list, ui, storage); | ||
isExit = c instanceof ExitCommand; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea! |
||
} | ||
} | ||
|
||
|
||
public static void main(String[] args) { | ||
String logo = " ____ _ \n" | ||
+ "| _ \\ _ _| | _____ \n" | ||
+ "| | | | | | | |/ / _ \\\n" | ||
+ "| |_| | |_| | < __/\n" | ||
+ "|____/ \\__,_|_|\\_\\___|\n"; | ||
System.out.println("Hello from\n" + logo); | ||
Duke duke = new Duke("Duke_List.txt"); | ||
duke.run(); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/** | ||
* Represents exceptions specific to Duke. | ||
*/ | ||
|
||
public class DukeException extends Exception { | ||
public DukeException(String message) { | ||
super(message); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
D @ 1 @ art project @ 04/04/2009 1600 | ||
T @ 1 @ borrow book |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/** | ||
* An exception that occurs when a task has no description. | ||
*/ | ||
|
||
public class EmptyDescriptionException extends DukeException { | ||
public EmptyDescriptionException(String message) { | ||
super(message); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/** | ||
* Event class to represent a task that occurs on a certain date. | ||
*/ | ||
|
||
import java.text.ParseException; | ||
import java.util.Date; | ||
import java.text.SimpleDateFormat; | ||
|
||
public class Event extends Task { | ||
protected Date date; | ||
protected String at; | ||
|
||
public Event(String description, String at) throws ParseException { | ||
super(description); | ||
this.at = at; | ||
this.date = new SimpleDateFormat("dd/MM/yyyy HHmm").parse(at); | ||
} | ||
|
||
public Event(String description, boolean isDone, String at) throws ParseException { | ||
super(description, isDone); | ||
this.at = at; | ||
this.date = new SimpleDateFormat("dd/MM/yyyy HHmm").parse(at); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
SimpleDateFormat formatter = new SimpleDateFormat("d MMMM yyyy, hmma"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could also format the date attribute to this format in the constructor, and use it for all your methods, like toString() and more. |
||
String formattedDate = formatter.format(this.date); | ||
return "[E]" + super.toString() + " (at: " + formattedDate + ")"; | ||
} | ||
|
||
@Override | ||
public String print() { | ||
if (this.isDone) { | ||
return "E @ 1 @ " + this.description + " @ " + this.at; | ||
} else { | ||
return "E @ 0 @ " + this.description + " @ " + this.at; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/** | ||
* Represents the command for Duke to terminate. | ||
*/ | ||
|
||
public class ExitCommand extends Command { | ||
@Override | ||
public void execute(TaskList tasks, Ui ui, Storage storage) { | ||
System.out.println("Bye. Hope to see you again soon!"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import java.util.ArrayList; | ||
|
||
public class FindCommand extends Command { | ||
private String description; | ||
|
||
public FindCommand(String description) { | ||
this.description = description; | ||
} | ||
@Override | ||
public void execute(TaskList tasks, Ui ui, Storage storage) { | ||
System.out.println("Here are the matching tasks in your list:"); | ||
ArrayList<Task> matchingTasks = new ArrayList<>(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought about this idea too! I chose to use streams in the end as the code is much simpler, this is a good idea! |
||
int count = 1; | ||
for (Task task : tasks.getList()) { | ||
if (task.getDescription().contains(description)) { | ||
matchingTasks.add(task); | ||
} | ||
} | ||
for (Task task : matchingTasks) { | ||
System.out.println(count + "." + task); | ||
count++; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* Represents a command to print out the tasks in the arraylist. | ||
*/ | ||
|
||
public class ListCommand extends Command { | ||
|
||
@Override | ||
public void execute(TaskList tasks, Ui ui, Storage storage) { | ||
System.out.println("Here are the tasks in your list:"); | ||
int listCount = 1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would recommend streams to simplify your code. |
||
for (Task task : tasks.getList()) { | ||
System.out.println(listCount + "." + task); | ||
listCount++; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Manifest-Version: 1.0 | ||
Main-Class: Duke | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/** | ||
* Parser class to handle user input. | ||
*/ | ||
public class Parser { | ||
|
||
/** | ||
* Parses the input string and determines the type of command given. | ||
* @param str The input string supplied to Duke. | ||
* @return Returns the corresponding command depending on the first word of the input string. | ||
*/ | ||
public static Command parse(String str) { | ||
String[] arr = str.split(" "); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Splitting the string is a good idea! I used contains(...) method instead. |
||
String next = arr[0]; | ||
Command c; | ||
switch (next) { | ||
case "find": | ||
c = new FindCommand(arr[1]); | ||
break; | ||
case "bye": | ||
c = new ExitCommand(); | ||
break; | ||
case "list": | ||
c = new ListCommand(); | ||
break; | ||
case "done": | ||
c = new DoneCommand(Integer.parseInt(arr[1]) - 1); | ||
break; | ||
case "delete": | ||
c = new DeleteCommand(Integer.parseInt(arr[1]) - 1); | ||
break; | ||
default: | ||
c = new AddCommand(arr); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may be more easier to specify the deadline, description, whether it is done and other attributes inside the constructor of AddCommand, since the String input is already split. |
||
break; | ||
} | ||
return c; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's custom to have the class's javadoc comments to be directly above the declaration of the class, after any relevant import statements.