Skip to content

Commit 1c0d92d

Browse files
authored
Merge pull request #11 from weixue123/branch-B-Reminders
Branch b reminders
2 parents 4aa6d45 + 4642d9f commit 1c0d92d

20 files changed

+701
-190
lines changed

data/test.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
T | 0 | CS2103 Quiz 1 |
2-
D | 1 | BT4013 Quiz 2 | 2021-02-06 23:30
3-
E | 0 | CS2103 Quiz 3 | 2021-02-06 23:30
1+
T | 0 | CS2103 Quiz |
2+
D | 0 | CS2103 Quiz | 2021-02-12 00:19
3+
E | 0 | CS2103 Quiz | 2021-02-12 00:19

src/main/java/duke/commands/ListCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public void execute(TaskList tasks) {
1616
}
1717

1818
/**
19-
* Returns false as searching for tasks should not terminate the application.
19+
* Returns false as listing tasks should not terminate the application.
2020
*
2121
* @return false
2222
*/
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package duke.commands;
2+
3+
import duke.tasks.Deadline;
4+
import duke.tasks.Event;
5+
import duke.tasks.Task;
6+
import duke.tasks.TaskList;
7+
8+
/**
9+
* Handles the logic of generating reminders w.r.t. the tasks in the to-do list.
10+
*/
11+
public class ReminderCommand extends Command {
12+
private final int urgencyDays;
13+
14+
/**
15+
* Initializes a command to list out the overdue and urgent tasks in the to-do list.
16+
*
17+
* @param urgencyDays Number of days to use when determining if a <code>Deadline</code>
18+
* or an <code>Event</code> is urgent.
19+
*/
20+
public ReminderCommand(int urgencyDays) {
21+
this.urgencyDays = urgencyDays;
22+
}
23+
24+
/**
25+
* Does nothing.
26+
*
27+
* @param tasks A collection of <code>Task</code> objects representing the application's state.
28+
*/
29+
public void execute(TaskList tasks) {
30+
}
31+
32+
/**
33+
* Returns false as listing reminders should not terminate the application.
34+
*
35+
* @return false
36+
*/
37+
public boolean isExit() {
38+
return false;
39+
}
40+
41+
/**
42+
* Creates a response to display the existing tasks to the users. The output will
43+
* take the form of a multi-line string, with each row displaying one task with its
44+
* index, description and status.
45+
*
46+
* @param tasks A collection of <code>Task</code> objects representing the application's state.
47+
* @return A <code>String</code> displaying the existing tasks.
48+
*/
49+
public String getResponse(TaskList tasks) {
50+
return this.getOverdueTasksResponse(tasks) + "\n" + this.getUrgentTasksResponse(tasks, this.urgencyDays);
51+
}
52+
53+
private String getOverdueTasksResponse(TaskList tasks) {
54+
TaskList overdueTasks = this.getOverdueTasks(tasks);
55+
int numOverdue = overdueTasks.getSize();
56+
57+
if (numOverdue == 0) {
58+
return "You do not have any overdue tasks!\n";
59+
} else {
60+
return "Oh no... You have " + numOverdue + " overdue task(s):\n" + overdueTasks.getTaskListAsString();
61+
}
62+
}
63+
64+
private String getUrgentTasksResponse(TaskList tasks, int urgencyDays) {
65+
TaskList urgentTasks = this.getUrgentTasks(tasks, urgencyDays);
66+
int numUrgent = urgentTasks.getSize();
67+
68+
if (numUrgent == 0) {
69+
return "You do not have any urgent tasks!\n";
70+
} else {
71+
return "You have " + numUrgent + " task(s) that are due in less than " + urgencyDays + " day(s):\n"
72+
+ urgentTasks.getTaskListAsString();
73+
}
74+
}
75+
76+
/**
77+
* Obtains a <code>TaskList</code> of overdue tasks.
78+
*
79+
* @param tasks A collection of <code>Task</code> objects representing the application's state.
80+
* @return A filtered <code>TaskList</code> comprising only the overdue tasks.
81+
*/
82+
private TaskList getOverdueTasks(TaskList tasks) {
83+
TaskList overdueTasks = new TaskList();
84+
85+
for (Task task : tasks.getListOfTasks()) {
86+
boolean overdue = false;
87+
88+
if (task instanceof Event) {
89+
overdue = ((Event) task).isOverdue();
90+
} else if (task instanceof Deadline) {
91+
overdue = ((Deadline) task).isOverdue();
92+
}
93+
94+
if (overdue) {
95+
overdueTasks.addTask(task);
96+
}
97+
}
98+
99+
return overdueTasks;
100+
}
101+
102+
/**
103+
* Obtains a <code>TaskList</code> of urgent tasks.
104+
*
105+
* @param tasks A collection of <code>Task</code> objects representing the application's state.
106+
* @return A filtered <code>TaskList</code> comprising only the urgent tasks.
107+
*/
108+
private TaskList getUrgentTasks(TaskList tasks, int urgencyInDays) {
109+
assert urgencyInDays > 0;
110+
TaskList urgentTasks = new TaskList();
111+
112+
for (Task task : tasks.getListOfTasks()) {
113+
boolean urgent = false;
114+
115+
if (task instanceof Event) {
116+
urgent = ((Event) task).isUrgent(urgencyInDays);
117+
} else if (task instanceof Deadline) {
118+
urgent = ((Deadline) task).isUrgent(urgencyInDays);
119+
}
120+
121+
if (urgent) {
122+
urgentTasks.addTask(task);
123+
}
124+
}
125+
126+
return urgentTasks;
127+
}
128+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package duke.exceptions;
2+
3+
public class InvalidUrgencyDaysException extends Exception {
4+
5+
public InvalidUrgencyDaysException() {
6+
super("You need to input a positive integer to specify the urgency level :O");
7+
}
8+
}

src/main/java/duke/tasks/Deadline.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,22 @@ public Deadline(String description, LocalDateTime byDateTime) {
2020
this.byDateTime = byDateTime;
2121
}
2222

23+
/**
24+
* Retrieves the task's deadline time.
25+
*
26+
* @return The task's deadline.
27+
*/
28+
public LocalDateTime getByDateTime() {
29+
return this.byDateTime;
30+
}
31+
2332
/**
2433
* Converts the task's deadline to a <code>String</code>.
2534
*
2635
* @return A formatted date string corresponding to the task's deadline.
2736
*/
2837
public String getByDateTimeString() {
29-
return this.byDateTime.format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm"));
38+
return this.getByDateTime().format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm"));
3039
}
3140

3241
/**
@@ -37,4 +46,33 @@ public String getByDateTimeString() {
3746
public String getStatusString() {
3847
return "[D]" + super.getStatusString() + " (by: " + this.getByDateTimeString() + ")";
3948
}
49+
50+
/**
51+
* Determines if the <code>Deadline</code> is overdue.
52+
*
53+
* @return True if the deadline is later than the current time, and false otherwise.
54+
*/
55+
public boolean isOverdue() {
56+
if (this.isDone()) {
57+
return false;
58+
}
59+
60+
return LocalDateTime.now().isAfter(this.getByDateTime());
61+
}
62+
63+
/**
64+
* Determines if the <code>Deadline</code> is urgent.
65+
*
66+
* @param urgencyInDays Number of days to use when determining if the <code>Deadline</code>
67+
* is urgent.
68+
* @return True if the deadline is within <code>urgencyInDays</code> of the current time.
69+
*/
70+
public boolean isUrgent(int urgencyInDays) {
71+
if (this.isDone()) {
72+
return false;
73+
}
74+
75+
LocalDateTime urgencyMark = this.getByDateTime().minusDays(urgencyInDays);
76+
return LocalDateTime.now().isAfter(urgencyMark) && !this.isOverdue();
77+
}
4078
}

src/main/java/duke/tasks/Event.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,22 @@ public Event(String description, LocalDateTime atDateTime) {
2020
this.atDateTime = atDateTime;
2121
}
2222

23+
/**
24+
* Retrieves the event's time.
25+
*
26+
* @return The event's time.
27+
*/
28+
public LocalDateTime getAtDateTime() {
29+
return this.atDateTime;
30+
}
31+
2332
/**
2433
* Converts the event's time to a <code>String</code>.
2534
*
2635
* @return A formatted date string corresponding to the event's time.
2736
*/
2837
public String getAtDateTimeString() {
29-
return this.atDateTime.format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm"));
38+
return this.getAtDateTime().format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm"));
3039
}
3140

3241
/**
@@ -37,4 +46,33 @@ public String getAtDateTimeString() {
3746
public String getStatusString() {
3847
return "[E]" + super.getStatusString() + " (at: " + this.getAtDateTimeString() + ")";
3948
}
49+
50+
/**
51+
* Determines if the <code>Event</code> is overdue.
52+
*
53+
* @return True if the deadline is later than the current time, and false otherwise.
54+
*/
55+
public boolean isOverdue() {
56+
if (this.isDone()) {
57+
return false;
58+
}
59+
60+
return LocalDateTime.now().isAfter(this.getAtDateTime());
61+
}
62+
63+
/**
64+
* Determines if the <code>Event</code> is urgent.
65+
*
66+
* @param urgencyInDays Number of days to use when determining if the <code>Deadline</code>
67+
* is urgent.
68+
* @return True if the deadline is within <code>urgencyInDays</code> of the current time.
69+
*/
70+
public boolean isUrgent(int urgencyInDays) {
71+
if (this.isDone()) {
72+
return false;
73+
}
74+
75+
LocalDateTime urgencyMark = this.getAtDateTime().minusDays(urgencyInDays);
76+
return LocalDateTime.now().isAfter(urgencyMark) && !this.isOverdue();
77+
}
4078
}

src/main/java/duke/ui/Parser.java

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
import duke.commands.FindCommand;
1717
import duke.commands.InvalidInputCommand;
1818
import duke.commands.ListCommand;
19+
import duke.commands.ReminderCommand;
1920
import duke.exceptions.InvalidActionException;
2021
import duke.exceptions.InvalidDateTimeFormatException;
22+
import duke.exceptions.InvalidUrgencyDaysException;
2123
import duke.exceptions.MissingDeadlineException;
2224
import duke.exceptions.MissingDescriptionException;
2325
import duke.exceptions.MissingEventTimeException;
@@ -39,26 +41,27 @@ public class Parser {
3941
private static final String TODO = "TODO";
4042
private static final String DEADLINE = "DEADLINE";
4143
private static final String EVENT = "EVENT";
44+
private static final String REMINDER = "REMINDER";
4245

4346
private static final ArrayList<String> validActions =
44-
new ArrayList<>(Arrays.asList(BYE, LIST, DONE, DELETE, FIND, TODO, DEADLINE, EVENT));
45-
46-
public static ArrayList<String> getValidActions() {
47-
return validActions;
48-
}
47+
new ArrayList<>(Arrays.asList(BYE, LIST, DONE, DELETE, FIND, REMINDER, TODO, DEADLINE, EVENT));
4948

5049
/**
5150
* Parses a line of raw user input, converting it into a <code>Command</code> object that
5251
* handles all of the application's logic. Accordingly, the output <code>Command</code> object
53-
* will be used to (1) alter the application's state, (2) computes responses to the users, and
54-
* (3) determine whether to terminate the application.
52+
* will be used to:
53+
* (1) alter the application's state
54+
* (2) computes responses to the users
55+
* (3) determine whether to terminate the application
5556
*
5657
* @param input A line of raw user input.
5758
* @return Returns a <code>Command</code> object which will be used to execute the desired responses.
5859
*/
5960
public static Command parse(String input) {
61+
// If the input is valid, getExceptionMessage will return null.
62+
// If the input is invalid, getExceptionMessage will return an appropriate message to be displayed.
6063
String exceptionMessage = getExceptionMessage(input);
61-
if (!exceptionMessage.equals("")) {
64+
if (exceptionMessage != null) {
6265
return new InvalidInputCommand(exceptionMessage);
6366
}
6467

@@ -76,6 +79,8 @@ public static Command parse(String input) {
7679
return new DoneCommand(Integer.parseInt(description));
7780
case DELETE:
7881
return new DeleteCommand(Integer.parseInt(description));
82+
case REMINDER:
83+
return new ReminderCommand(Integer.parseInt(description));
7984
case FIND:
8085
return new FindCommand(description);
8186
case TODO:
@@ -184,6 +189,13 @@ private static boolean isInteger(String str) {
184189
return true;
185190
}
186191

192+
private static boolean isPositiveInteger(String str) {
193+
if (!isInteger(str)) {
194+
return false;
195+
}
196+
return Integer.parseInt(str) > 0;
197+
}
198+
187199
/**
188200
* Converts an input date or datetime string into a <code>LocalDateTime</code> object.
189201
*
@@ -238,6 +250,10 @@ private static String getExceptionMessage(String input) {
238250
throw new TaskNumberNotIntException();
239251
}
240252

253+
if (action.equals(REMINDER) && (!isPositiveInteger(description))) {
254+
throw new InvalidUrgencyDaysException();
255+
}
256+
241257
if (action.equals(DEADLINE) && byDateTimeString.length() == 0) {
242258
throw new MissingDeadlineException();
243259
}
@@ -259,10 +275,11 @@ private static String getExceptionMessage(String input) {
259275
| TaskNumberNotIntException
260276
| MissingDeadlineException
261277
| MissingEventTimeException
262-
| InvalidDateTimeFormatException e) {
278+
| InvalidDateTimeFormatException
279+
| InvalidUrgencyDaysException e) {
263280
return e.getMessage();
264281
}
265282

266-
return "";
283+
return null;
267284
}
268285
}

0 commit comments

Comments
 (0)