Skip to content
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions data/tasks.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
D | 1 | CS2105 Assignment 0 | 2021-08-29 2359
D | 1 | PC1201 Test 1 (First Mock Test) | 2021-09-02 1400
D | 1 | CS2103 Week 4 Quiz | 2021-08-30 2359
D | 0 | CS3240 Week 4 Quiz | 2021-08-31 2000
T | 0 | Vacuum room floor
T | 0 | Change bedsheet
T | 0 | Download files from LumiNUS
T | 0 | CS2103 Week 3 Deliverables (JUnit)
T | 0 | CS2103 Week 3 Deliverables (Jar)
T | 0 | CS2103 Week 3 Deliverables (Javadocs)
10 changes: 0 additions & 10 deletions src/main/java/Duke.java

This file was deleted.

47 changes: 47 additions & 0 deletions src/main/java/duke/Duke.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package duke;

import duke.command.Command;

import java.io.IOException;

public class Duke {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps add header comment for the class.

Noticed that there is no JavaDocs added throughout. Perhaps it would be good practice to have them, as documentation to improve readability of your code.

private Ui ui;
private Parser parser;
private Storage storage;
private TaskList taskList;

public Duke(String pathName, String fileName) {
ui = new Ui();
parser = new Parser();

try {
storage = new Storage(pathName, fileName);
taskList = storage.loadTasksFromFile();
} catch (DukeException | IOException e) {
ui.displayError(e.getMessage());
taskList = new TaskList();
}
}

public static void main(String[] args) {
new Duke("data", "tasks.txt").run();
}

public void run() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to add headers comments for public methods.

ui.displayWelcome();
boolean isExit = false;

while (!isExit) {
try {
String commandLine = ui.readCommand();
Command command = parser.parse(commandLine);
command.execute(taskList, ui, storage);
isExit = command.isExit();
} catch (DukeException e) {
ui.displayError(e.getMessage());
} finally {
ui.displayLine();
}
}
}
}
7 changes: 7 additions & 0 deletions src/main/java/duke/DukeException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package duke;

public class DukeException extends Exception {
public DukeException(String errorMessage) {
super(errorMessage);
}
}
254 changes: 254 additions & 0 deletions src/main/java/duke/Parser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
package duke;

import duke.command.AddDeadlineCommand;
import duke.command.AddEventCommand;
import duke.command.AddToDoCommand;
import duke.command.Command;
import duke.command.DeleteCommand;
import duke.command.DoneCommand;
import duke.command.ExitCommand;
import duke.command.ListCommand;
import duke.command.PrintCommand;

public class Parser {
public Command parse(String commandLine) throws DukeException {
String[] commandLineParts = commandLine.split("\\s+", 2);

String commandType;
String commandInfo;

if (commandLineParts.length == 2) {
commandType = commandLineParts[0];
commandInfo = commandLineParts[1];

// If user inputs extra text after "bye" or "list" commands
if ((commandType.equals("bye") || commandType.equals("list")) && !commandInfo.equals("")) {
throw new DukeException("INVALID COMMAND. Please try again!");
}
} else { // for "bye" and "list" commands

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments should be indented relative to their position in the code.

commandType = commandLineParts[0];
commandInfo = "";
}

Command command;
int taskNum;
String taskDescription;
String taskInfo;
String date;

switch (commandType) {
case "bye":
command = new ExitCommand(commandType);
break;
case "list":
command = new ListCommand(commandType);
break;
case "done":
taskNum = getTaskNumFromCommand(commandInfo);
command = new DoneCommand(commandType, taskNum);
break;
case "delete":
taskNum = getTaskNumFromCommand(commandInfo);
command = new DeleteCommand(commandType, taskNum);
break;
case "todo":
taskDescription = getTaskDescriptionFromToDoCommand(commandInfo);
command = new AddToDoCommand(commandType, taskDescription);
break;
case "deadline":
taskInfo = getTaskInfoFromDeadlineCommand(commandInfo);
command = new AddDeadlineCommand(commandType, taskInfo);
break;
case "event":
taskInfo = getTaskInfoFromEventCommand(commandInfo);
command = new AddEventCommand(commandType, taskInfo);
break;
case "print":
date = getDateFromPrintCommand(commandInfo);
command = new PrintCommand(commandType, date);
break;
default:
throw new DukeException("INVALID COMMAND. Please try again!");
}

return command;
}

private int getTaskNumFromCommand(String commandInfo) throws DukeException {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps a shorter name would be better e.g. getTaskNum.

if (commandInfo.trim().length() > 0) {
try {
return Integer.parseInt(commandInfo);
} catch (NumberFormatException e) {
throw new DukeException("Please enter a valid task number to be marked as done!");
}
} else {
throw new DukeException("Please enter a task number to be marked as done!");
}
}

private String getTaskDescriptionFromToDoCommand(String commandInfo) throws DukeException {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above, method names could be shorter and more concise, and if they are specific to a command, perhaps it could be a better design to have them in the respective command classes.

This applies to other method names as well.

if (commandInfo.trim().length() > 0) {
return commandInfo;
} else {
throw new DukeException("The description of a todo cannot be empty!");
}
}

private String getTaskInfoFromDeadlineCommand(String commandInfo) throws DukeException {
if (commandInfo.trim().length() > 0) {
String[] deadlineTaskDetails = commandInfo.split("/", 2);

if (deadlineTaskDetails.length == 2) {
if (deadlineTaskDetails[0].trim().length() > 0) {
if (deadlineTaskDetails[1].trim().startsWith("by")) {
String beforeDateTime = deadlineTaskDetails[1].trim();
String[] beforeDateTimeParts = beforeDateTime.split("\\s+", 2);

if (beforeDateTimeParts.length == 2) {
return commandInfo;
} else {
throw new DukeException("INCOMPLETE COMMAND"
+ System.lineSeparator() + "\t"
+ "The date/time of a deadline cannot be empty!"
+ System.lineSeparator() + "\t"
+ "[Note: Enter /by before specifying the date/time]");
}
} else {
throw new DukeException("WRONG COMMAND"
+ System.lineSeparator() + "\t"
+ "Enter /by before specifying the date!");
}
} else {
if (deadlineTaskDetails[1].trim().startsWith("by")) {
String beforeDateTime = deadlineTaskDetails[1].trim();
String[] beforeDateTimeParts = beforeDateTime.split("\\s+", 2);

if (beforeDateTimeParts.length == 2) {
throw new DukeException("INCOMPLETE COMMAND"
+ System.lineSeparator() + "\t"
+ "The description of a deadline cannot be empty!");
} else {
throw new DukeException("INCOMPLETE COMMAND"
+ System.lineSeparator() + "\t"
+ "The description of a deadline cannot be empty!"
+ System.lineSeparator() + "\t"
+ "The date/time of a deadline cannot be empty!"
+ System.lineSeparator() + "\t"
+ "[Note: Enter /by before specifying the date/time]");
}
} else {
throw new DukeException("INCOMPLETE & WRONG COMMAND"
+ System.lineSeparator() + "\t"
+ "The description of a deadline cannot be empty!"
+ System.lineSeparator() + "\t"
+ "Enter /by before specifying the date/time!");
}
}
} else {
throw new DukeException("INCOMPLETE COMMAND"
+ System.lineSeparator() + "\t"
+ "The date/time of a deadline cannot be empty!"
+ System.lineSeparator() + "\t"
+ "[Note: Enter /by before specifying the date/time]");
}
} else {
throw new DukeException("INCOMPLETE COMMAND"
+ System.lineSeparator() + "\t"
+ "The description and date/time of a deadline cannot be empty!"
+ System.lineSeparator() + "\t"
+ "[Note: Enter /by before specifying the date/time]");
}
}
Comment on lines +129 to +189

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid deep nesting, especially if you need more than 3 levels of indentation. In particular, avoid arrowhead style code.


private String getTaskInfoFromEventCommand(String commandInfo) throws DukeException {
if (commandInfo.trim().length() > 0) {
String[] eventTaskDetails = commandInfo.split("/", 2);

if (eventTaskDetails.length == 2) {
if (eventTaskDetails[0].trim().length() > 0) {
if (eventTaskDetails[1].trim().startsWith("at")) {
String startEndDateTime = eventTaskDetails[1].trim();
String[] startEndDateTimeParts = startEndDateTime.split("\\s+", 2);

if (startEndDateTimeParts.length == 2) {
return commandInfo;
} else {
throw new DukeException("INCOMPLETE COMMAND"
+ System.lineSeparator() + "\t"
+ "The date/time of an event cannot be empty!"
+ System.lineSeparator() + "\t"
+ "[Note: Enter /at before specifying the date/time]");
}
} else {
throw new DukeException("WRONG COMMAND"
+ System.lineSeparator() + "\t"
+ "Enter /at before specifying the date!");
}
} else {
if (eventTaskDetails[1].trim().startsWith("at")) {
String startEndDateTime = eventTaskDetails[1].trim();
String[] startEndDateTimeParts = startEndDateTime.split("\\s+", 2);

if (startEndDateTimeParts.length == 2) {
throw new DukeException("INCOMPLETE COMMAND"
+ System.lineSeparator() + "\t"
+ "The description of an event cannot be empty!");
} else {
throw new DukeException("INCOMPLETE COMMAND"
+ System.lineSeparator() + "\t"
+ "The description of an event cannot be empty!"
+ System.lineSeparator() + "\t"
+ "The date/time of an event cannot be empty!"
+ System.lineSeparator() + "\t"
+ "[Note: Enter /at before specifying the date/time]");
}
} else {
throw new DukeException("INCOMPLETE & WRONG COMMAND"
+ System.lineSeparator() + "\t"
+ "The description of an event cannot be empty!"
+ System.lineSeparator() + "\t"
+ "Enter /at before specifying the date/time!");
}
}
} else {
throw new DukeException("INCOMPLETE COMMAND"
+ System.lineSeparator() + "\t"
+ "The date/time of an event cannot be empty!"
+ System.lineSeparator() + "\t"
+ "[Note: Enter /at before specifying the date/time]");
}
} else {
throw new DukeException("INCOMPLETE COMMAND"
+ System.lineSeparator() + "\t"
+ "The description and date/time of an event cannot be empty!"
+ System.lineSeparator() + "\t"
+ "[Note: Enter /at before specifying the date/time]");
}
Comment on lines +198 to +260

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as comment above, avoid deep nesting.

}

private String getDateFromPrintCommand(String commandInfo) throws DukeException {
if (commandInfo.trim().length() > 0) {
if (commandInfo.trim().startsWith("/on")) {
String[] specificDateParts = commandInfo.split("\\s+", 2);

if (specificDateParts.length == 2) {
return specificDateParts[1];
} else {
throw new DukeException("INCOMPLETE COMMAND"
+ System.lineSeparator() + "\t"
+ "The date is not specified!"
+ System.lineSeparator() + "\t"
+ "[Note: Enter /on before specifying the date]");
}
} else {
throw new DukeException("WRONG COMMAND"
+ System.lineSeparator() + "\t"
+ "Enter /on before specifying the date!");
}
} else {
throw new DukeException("INCOMPLETE COMMAND"
+ System.lineSeparator() + "\t"
+ "Enter /on before specifying the date!");
}
}
}
Loading