-
Notifications
You must be signed in to change notification settings - Fork 228
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
[Cao Peng] iP #236
base: master
Are you sure you want to change the base?
[Cao Peng] iP #236
Changes from 19 commits
3b19ba1
a75fcee
7a16622
ea64e59
e495edd
73e3146
fcc4ab3
303035e
0067f9d
8fc7617
39ffa63
4a0753b
8f2c0fe
1544949
f3caea8
815dc30
fde4727
d1a82f3
fcdd560
d99334b
8f3229d
17a87a7
f1060fc
6c910c4
86d417f
0bdf504
3d5ec70
9ad3eb1
7dabba0
863725e
501e936
7963ef4
7d300e3
bd02cf9
57ec9c8
7096f31
99365d5
9dc0f28
97e5396
03cde79
599c846
4c4b0b8
1f4a1b5
8d54d93
76d5460
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 @@ | ||
[T][X] homework1 |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Manifest-Version: 1.0 | ||
Main-Class: duke.Duke | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package duke; | ||
|
||
import duke.command.Command; | ||
import duke.exception.DukeException; | ||
|
||
import java.util.ArrayList; | ||
|
||
/** | ||
* the agent program to run duke.Duke | ||
*/ | ||
public class Duke { | ||
private static final String FILE_PATH = "./data/duke.txt"; | ||
private Ui ui; | ||
private TaskList tasks; | ||
private Storage storage; | ||
private Parser parser; | ||
|
||
public Duke() { | ||
this.ui = new Ui(); | ||
this.parser = new Parser(); | ||
this.storage = new Storage(FILE_PATH); | ||
|
||
try { | ||
this.tasks = new TaskList(storage.load()); | ||
} catch (DukeException e) { | ||
ui.printMsg(e.getMessage()); | ||
this.tasks = new TaskList(new ArrayList<>()); | ||
} | ||
} | ||
|
||
public static void main(String[] args) { | ||
new Duke().run(); | ||
} | ||
|
||
public void run() { | ||
ui.printGreetingMsg(); | ||
|
||
boolean isExit = false; | ||
while(!isExit) { | ||
String fullCommand = ui.readCommand(); | ||
ui.printLine(); | ||
try { | ||
Command command = parser.parseCommand(fullCommand); | ||
command.execute(tasks, ui, storage); | ||
isExit = command.isExit(); | ||
} catch (DukeException e) { | ||
ui.printMsg(e.getMessage()); | ||
} | ||
ui.printLine(); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package duke; | ||
|
||
import duke.command.*; | ||
import duke.exception.DukeException; | ||
import duke.exception.EmptyTodoDescriptionException; | ||
import duke.exception.UnknownCommandException; | ||
import duke.task.Deadline; | ||
import duke.task.Event; | ||
import duke.task.Task; | ||
import duke.task.ToDo; | ||
|
||
import java.time.LocalDate; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
/** | ||
* deals with parsing the user command | ||
*/ | ||
public class Parser { | ||
|
||
/** | ||
* @param fullCommand the user command | ||
* @return a duke.command.Command object which encapsulates the information of a parsed user command | ||
* @throws DukeException exception when there is an parsing error | ||
*/ | ||
Comment on lines
+21
to
+25
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. Maybe a short summary of the method could be written as the first sentence for this method header. |
||
public Command parseCommand(String fullCommand) throws DukeException { | ||
if (fullCommand.equals("bye")) { | ||
return new ExitCommand(); | ||
} else if (fullCommand.equals("list")) { | ||
return new ListCommand(); | ||
} else { | ||
String[] parsedCommand = fullCommand.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. Plural form could be used for this String array to make the variable name sound more like a collection of string values. |
||
|
||
try { | ||
switch (parsedCommand[0]) { | ||
case "done", "delete": | ||
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. Do note that there should be no indentation for case clauses as to adhere to the Java coding standard. I noticed the same issue in the other classes as well. Perhaps consider configuring your IDE to help with this styling? |
||
int taskId = Integer.parseInt(parsedCommand[1]) - 1; | ||
if (parsedCommand[0].equals("done")) { | ||
return new DoneCommand(fullCommand, taskId); | ||
} else { | ||
return new DeleteCommand(fullCommand, taskId); | ||
} | ||
case "find": | ||
return new FindCommand(fullCommand, fullCommand.replaceFirst("find ", "")); | ||
case "todo", "deadline", "event": | ||
Task task = parseTask(parsedCommand[0], fullCommand.replaceFirst(parsedCommand[0] + " ", "")); | ||
return new AddCommand(fullCommand, task); | ||
default: | ||
throw new UnknownCommandException(); | ||
} | ||
} catch (DukeException e) { | ||
throw e; | ||
} catch (Exception e) { | ||
throw new DukeException("duke.command.Command parsing error!"); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* @param taskType the type of the task | ||
* @param taskStr part of the user command which represents a task | ||
* @return a duke.task.Task object in the user command | ||
* @throws DukeException exception when there is a task parsing error | ||
*/ | ||
private Task parseTask(String taskType, String taskStr) throws DukeException { | ||
String pattern; | ||
Pattern r; | ||
Matcher m; | ||
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. A more meaningful naming suggestion: String input, Pattern pattern, Matcher matcher. I found this issue in the Storage class as well. |
||
|
||
if (taskType.equals("todo") && taskStr.isEmpty()) { | ||
throw new EmptyTodoDescriptionException(); | ||
} | ||
|
||
try { | ||
switch (taskType) { | ||
case "todo": | ||
return new ToDo(taskStr); | ||
case "deadline": | ||
pattern = "(.*) /by (.*)$"; | ||
r = Pattern.compile(pattern); | ||
m = r.matcher(taskStr); | ||
if (m.find()) { | ||
return new Deadline(m.group(1), LocalDate.parse(m.group(2))); | ||
} | ||
case "event": | ||
pattern = "(.*) /at (.*)$"; | ||
r = Pattern.compile(pattern); | ||
m = r.matcher(taskStr); | ||
if (m.find()) { | ||
return new Event(m.group(1), LocalDate.parse(m.group(2))); | ||
} | ||
default: | ||
throw new UnknownCommandException(); | ||
} | ||
} catch (DukeException e) { | ||
throw e; | ||
} catch (Exception e) { | ||
throw new DukeException("duke.task.Task parsing error!"); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package duke; | ||
|
||
import duke.exception.DukeException; | ||
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.time.LocalDate; | ||
import java.time.format.DateTimeFormatter; | ||
import java.util.ArrayList; | ||
import java.util.Scanner; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
/** | ||
* Deals with loading tasks from the file and saving tasks in the file. | ||
*/ | ||
public class Storage { | ||
private String filePath; | ||
private String dirPath; | ||
|
||
/** | ||
* @param filePath The file path of the file which is used to store task list. | ||
*/ | ||
public Storage(String filePath) { | ||
this.filePath = filePath; | ||
parseFilePath(); | ||
} | ||
|
||
/** | ||
* Extracts directory path from the file path. | ||
*/ | ||
public void parseFilePath() { | ||
String pattern = "(.*)/(.*)$"; | ||
Pattern r = Pattern.compile(pattern); | ||
Matcher m = r.matcher(filePath); | ||
if (m.find()) { | ||
this.dirPath = m.group(1); | ||
} | ||
} | ||
|
||
/** | ||
* Loads task list from the file and returns the task list. | ||
* @return The task list which is loaded from the file. | ||
* @throws DukeException Exception if there is error when loading from the file. | ||
*/ | ||
public ArrayList<Task> load() throws DukeException { | ||
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. Can this method name be loadTasksFromStorage to explain the method more intuitively? |
||
// create the folder called data if not found | ||
ArrayList<Task> tasks = new ArrayList<>(); | ||
|
||
File dir = new File(dirPath); | ||
if (!dir.exists() || !dir.isDirectory()) { | ||
dir.mkdir(); | ||
} | ||
|
||
File file = new File(filePath); | ||
try { | ||
Scanner sc = new Scanner(file); | ||
while (sc.hasNextLine()) { | ||
tasks.add(parseTask(sc.nextLine())); | ||
} | ||
sc.close(); | ||
return tasks; | ||
} catch (FileNotFoundException e) { | ||
throw new DukeException("Cannot load from file!"); | ||
} | ||
} | ||
|
||
/** | ||
* Parses the task string to a duke.task.Task object. | ||
* @param str The string which represents a single task. | ||
* @return A duke.task.Task object which represents a task as the string. | ||
* @throws DukeException Exception if there is error when parsing the task string. | ||
*/ | ||
public Task parseTask(String str) throws DukeException { | ||
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. Should this method be private instead, because it is independent of the whole program and is only used by the load method from the same class as an encapsulation? |
||
try { | ||
char typeLabel = str.charAt(1); | ||
boolean isDone = str.charAt(4) == 'X'; | ||
String body = str.substring(7); | ||
String pattern; | ||
Pattern r; | ||
Matcher m; | ||
switch (typeLabel) { | ||
case 'T': | ||
return new ToDo(body, isDone); | ||
case 'D': | ||
pattern = "(.*) \\(by: (.*)\\)"; | ||
r = Pattern.compile(pattern); | ||
m = r.matcher(body); | ||
if (m.find()) { | ||
LocalDate deadline = LocalDate.parse(m.group(2), DateTimeFormatter.ofPattern("MMM dd yyyy")); | ||
return new Deadline(m.group(1), isDone, deadline); | ||
} | ||
case 'E': | ||
pattern = "(.*) \\(at: (.*)\\)"; | ||
r = Pattern.compile(pattern); | ||
m = r.matcher(body); | ||
if (m.find()) { | ||
LocalDate time = LocalDate.parse(m.group(2), DateTimeFormatter.ofPattern("MMM dd yyyy")); | ||
return new Event(m.group(1), isDone, time); | ||
} | ||
default: | ||
throw new Exception(); | ||
} | ||
} catch (Exception e) { | ||
throw new DukeException("error occurs and loading from file is suspended!"); | ||
} | ||
} | ||
|
||
/** | ||
* Saves the task list to the file. | ||
* @param tasks The TaskList object whose string representation will be saved to the file. | ||
* @throws DukeException Exception when there is an error when saving task list to the file. | ||
*/ | ||
public void save(TaskList tasks) throws DukeException { | ||
// make the data directory if not found | ||
File dir = new File(dirPath); | ||
if (!dir.exists() || !dir.isDirectory()) { | ||
dir.mkdir(); | ||
} | ||
|
||
try { | ||
FileWriter writer = new FileWriter(filePath); | ||
writer.write(tasks.toString()); | ||
writer.flush(); | ||
writer.close(); | ||
} catch (IOException e) { | ||
throw new DukeException("Save to file error!"); | ||
} | ||
} | ||
} |
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.
Java coding standards stated that the imported classes should always be listed explicitly. I understand why you have imported * from duke.command package, but to comply with the guideline, would it be better to import explicitly instead?