Skip to content

Commit

Permalink
Detect scheduling anomalies
Browse files Browse the repository at this point in the history
Previously, events could overlap, leading to scheduling conflicts.

Overlapping events reduce the clarity of the schedule and make task
management confusing.

Let's,
* add a method to detect overlapping events
* throw an exception if a new event clashes with another event
  • Loading branch information
Gra7ityIC3 committed Sep 12, 2024
1 parent 2774ca4 commit 2f4cf87
Show file tree
Hide file tree
Showing 12 changed files with 63 additions and 43 deletions.
7 changes: 4 additions & 3 deletions src/main/java/morgana/commands/AddCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

/**
* Represents an abstract command to add a task to the task list.
* Concrete subclasses should implement the {@link #createTask(String)} method
* Concrete subclasses should implement the {@link #createTask(String, TaskList)} method
* to define how the task is created based on the user's input.
*/
public abstract class AddCommand extends Command {
Expand All @@ -30,7 +30,7 @@ public AddCommand(String args) {

@Override
public String execute(TaskList tasks, Storage storage) throws MorganaException {
Task task = createTask(args);
Task task = createTask(args, tasks);
tasks.add(task);
storage.save(tasks);
return MESSAGE_SUCCESS.formatted(task, tasks.size(), tasks.size() > 1 ? "s" : "");
Expand All @@ -40,10 +40,11 @@ public String execute(TaskList tasks, Storage storage) throws MorganaException {
* Creates a task based on the provided arguments.
*
* @param args The string containing the task details.
* @param tasks TODO
* @return The created {@code Task}.
* @throws MorganaException If an error occurs while creating the task.
*/
abstract Task createTask(String args) throws MorganaException;
abstract Task createTask(String args, TaskList tasks) throws MorganaException;

@Override
public String getStyleClass() {
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/morgana/commands/DeadlineCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import morgana.exceptions.MorganaException;
import morgana.task.Deadline;
import morgana.task.Task;
import morgana.task.TaskList;

/**
* Represents a command to add a {@link Deadline} to the task list.
Expand All @@ -29,7 +30,7 @@ public DeadlineCommand(String args) {
}

@Override
Task createTask(String args) throws MorganaException {
Task createTask(String args, TaskList tasks) throws MorganaException {
String[] fields = args.split(" /by ");
if (fields.length != 2) {
throw new MorganaException(MESSAGE_INVALID_COMMAND_FORMAT);
Expand Down
18 changes: 15 additions & 3 deletions src/main/java/morgana/commands/EventCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
import static morgana.util.DateTimeUtil.COMPACT_PATTERN;
import static morgana.util.DateTimeUtil.parseDateTime;

import java.time.LocalDateTime;

import morgana.exceptions.MorganaException;
import morgana.task.Event;
import morgana.task.Task;
import morgana.task.TaskList;

/**
* Represents a command to add an {@link Event} to the task list.
Expand All @@ -22,18 +25,27 @@ public class EventCommand extends AddCommand {
/**
* Constructs an {@code EventCommand} with the specified arguments.
*
* @param args The string containing the task description, start date/time, and end date/time.
* @param args The string containing the task description and time period.
*/
public EventCommand(String args) {
super(args);
}

@Override
Task createTask(String args) throws MorganaException {
Task createTask(String args, TaskList tasks) throws MorganaException {
String[] fields = args.split(" /from | /to ");
if (fields.length != 3) {
throw new MorganaException(MESSAGE_INVALID_COMMAND_FORMAT);
}
return new Event(fields[0], parseDateTime(fields[1]), parseDateTime(fields[2]));

LocalDateTime start = parseDateTime(fields[1]);
LocalDateTime end = parseDateTime(fields[2]);
assert start.isBefore(end) : "Event start time must be before end time";

Event event = tasks.findClashingEvent(start, end);
if (event != null) {
throw new MorganaException("Event clashes with another event:\n" + event);
}
return new Event(fields[0], start, end);
}
}
2 changes: 1 addition & 1 deletion src/main/java/morgana/commands/FindCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import morgana.task.TaskList;

/**
* Represents a command to find tasks that match a given keyword in their description.
* Represents a command to find tasks that contain a given keyword in their description.
*/
public class FindCommand extends Command {
public static final String COMMAND_WORD = "find";
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/morgana/commands/TodoCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import morgana.exceptions.MorganaException;
import morgana.task.Task;
import morgana.task.TaskList;
import morgana.task.Todo;

/**
Expand All @@ -23,7 +24,7 @@ public TodoCommand(String args) {
}

@Override
Task createTask(String description) throws MorganaException {
Task createTask(String description, TaskList tasks) throws MorganaException {
if (description.isEmpty()) {
throw new MorganaException(MESSAGE_EMPTY_DESCRIPTION);
}
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/morgana/parser/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
/**
* The {@code Parser} class is responsible for interpreting user input and
* creating the corresponding {@link Command} objects. It also provides utility
* methods for parsing task indices and date/time strings.
* methods for parsing task indices and task strings into {@link Task} objects.
*/
public class Parser {
/**
Expand Down Expand Up @@ -73,12 +73,12 @@ public static int parseTaskIndex(String args) throws MorganaException {
}

/**
* Parses a string representation of a task from a file and converts it into a {@link Task} object.
* Parses a task string from a file and converts it into a {@link Task} object.
*
* @param line The input string representing a task, as stored in a file.
* @return The {@code Task} object created from the input string.
*/
public static Task parseTaskFromString(String line) throws MorganaException {
public static Task parseTask(String line) throws MorganaException {
String[] fields = line.split(" \\| ");
assert fields.length >= 3 : "Expected at least 3 fields for a task, got: " + fields.length;

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/morgana/storage/Storage.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public List<Task> load() throws MorganaException {
List<Task> tasks = new ArrayList<>();
try (Scanner sc = new Scanner(file)) {
while (sc.hasNextLine()) {
tasks.add(Parser.parseTaskFromString(sc.nextLine()));
tasks.add(Parser.parseTask(sc.nextLine()));
}
} catch (FileNotFoundException e) {
throw new MorganaException("Failed to load tasks from file: " + e.getMessage());
Expand Down
17 changes: 7 additions & 10 deletions src/main/java/morgana/task/Deadline.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,26 @@
import java.time.LocalDateTime;

/**
* Represents a task with a description and a deadline.
* Represents a task with a description and a due date.
*/
public class Deadline extends Task {
private final LocalDateTime by;
private final LocalDateTime dueDate;

/**
* Constructs a {@code Deadline} task with the specified description and deadline.
*
* @param description The description of the task.
* @param by The deadline of the task.
* Constructs a {@code Deadline} with the specified description and due date.
*/
public Deadline(String description, LocalDateTime by) {
public Deadline(String description, LocalDateTime dueDate) {
super(TaskType.DEADLINE, description);
this.by = by;
this.dueDate = dueDate;
}

@Override
public String toFileFormat() {
return "%s | %s".formatted(super.toFileFormat(), by.format(COMPACT_FORMATTER));
return "%s | %s".formatted(super.toFileFormat(), dueDate.format(COMPACT_FORMATTER));
}

@Override
public String toString() {
return "%s (by: %s)".formatted(super.toString(), by.format(VERBOSE_FORMATTER));
return "%s (by: %s)".formatted(super.toString(), dueDate.format(VERBOSE_FORMATTER));
}
}
15 changes: 9 additions & 6 deletions src/main/java/morgana/task/Event.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,22 @@ public class Event extends Task {
private final LocalDateTime end;

/**
* Constructs an {@code Event} task with the specified description,
* start date/time, and end date/time.
*
* @param description The description of the event.
* @param start The start date and time of the event.
* @param end The end date and time of the event.
* Constructs an {@code Event} with the specified description and time period.
*/
public Event(String description, LocalDateTime start, LocalDateTime end) {
super(TaskType.EVENT, description);
this.start = start;
this.end = end;
}

public LocalDateTime getStart() {
return start;
}

public LocalDateTime getEnd() {
return end;
}

@Override
public String toFileFormat() {
return "%s | %s | %s".formatted(
Expand Down
4 changes: 1 addition & 3 deletions src/main/java/morgana/task/Task.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ public void markAsDone(boolean isDone) {
}

/**
* Converts the task to a format suitable for saving to a file.
*
* @return A string representing the task in a format suitable for file storage.
* Returns a string representing the task in a format suitable for file storage.
*/
public String toFileFormat() {
return "%s | %s | %s".formatted(type, getStatusIcon(), description);
Expand Down
25 changes: 17 additions & 8 deletions src/main/java/morgana/task/TaskList.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static morgana.common.Messages.MESSAGE_INVALID_TASK_NUMBER;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
Expand All @@ -24,8 +25,6 @@ public TaskList() {

/**
* Constructs a {@code TaskList} with an initial list of tasks.
*
* @param tasks The initial list of tasks.
*/
public TaskList(List<Task> tasks) {
this.tasks = tasks;
Expand All @@ -40,18 +39,13 @@ public int size() {

/**
* Adds a task to the end of the list.
*
* @param task The task to add.
*/
public void add(Task task) {
tasks.add(task);
}

/**
* Removes the task at the specified index from the list and returns it.
*
* @param index The index of the task to remove.
* @return The task that was removed.
*/
public Task remove(int index) throws MorganaException {
validateIndex(index);
Expand Down Expand Up @@ -82,7 +76,6 @@ private void validateIndex(int index) throws MorganaException {
/**
* Finds tasks in the list that contain the given keyword in their description.
*
* @param keyword The keyword to search for in the task description.
* @return A formatted string listing the matching tasks.
*/
public String find(String keyword) {
Expand All @@ -96,6 +89,22 @@ public String find(String keyword) {
return sb.toString();
}

/**
* Finds and returns the first {@link Event} that clashes with the given time period.
*
* @return The clashing {@code event} or {@code null} if there is no clash.
*/
public Event findClashingEvent(LocalDateTime start, LocalDateTime end) {
for (Task task : tasks) {
if (task instanceof Event event
&& start.isBefore(event.getEnd())
&& end.isAfter(event.getStart())) {
return event;
}
}
return null;
}

@Override
public String toString() {
StringBuilder sb = new StringBuilder("Here are the tasks in your list:\n");
Expand Down
4 changes: 1 addition & 3 deletions src/main/java/morgana/task/Todo.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
*/
public class Todo extends Task {
/**
* Constructs a {@code Todo} task with the specified description.
*
* @param description The description of the task.
* Constructs a {@code Todo} with the specified description.
*/
public Todo(String description) {
super(TaskType.TODO, description);
Expand Down

0 comments on commit 2f4cf87

Please sign in to comment.