Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/AY2324S1-CS2103T-W15-2/tp
Browse files Browse the repository at this point in the history
…into 292-final-edit-ppp
  • Loading branch information
mingyuanc committed Nov 12, 2023
2 parents 57769f4 + 7d41c44 commit 533966c
Show file tree
Hide file tree
Showing 22 changed files with 476 additions and 294 deletions.
12 changes: 6 additions & 6 deletions docs/DeveloperGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,8 @@ The diagram above shows how the folder structure is implemented in ProfBook,

* The hierarchy is as such: `Root` -> `Group` -> `Student`
* As many of the operations are repeated (e.g., tasks operations and children operation), we decided to abstract out
these logic into their own classes which is represented by `TaskListManager` and `ChildrenManager` respectively.
* `ChildrenManager` manages the children which is of type `IChildElement`
these logic into their own classes which is represented by `TaskListManager` and `ChildManager` respectively.
* `ChildManager` manages the children which is of type `IChildElement`
* We also created a wrapper class (e.g. `ChildrenAndTaskListManager`) for classes that require both of those
aforementioned functionalities (e.g, `Group` and potentially in the future `TutorialSlot`)

Expand Down Expand Up @@ -291,14 +291,14 @@ In our current hierarchy, `Root` -> `Group` -> `Student`, `Student` and `Group`
whereas `Root` and `Group` are required to manage children. The `Model` component briefly mentioned this implementation,
but I will delve into it more comprehensively.

We first created interfaces to represent the required logic for each of the manager, namely `IChildrenManager`
and `ITaskListManager`. Then we created concrete classes such as `ChildrenManager` and `TaskListManager` to encapsulate
We first created interfaces to represent the required logic for each of the manager, namely `IChildManager`
and `ITaskListManager`. Then we created concrete classes such as `ChildManager` and `TaskListManager` to encapsulate
the aforementioned logic. The purpose of these classes was so that should a folder type, e.g. `Student`, require a
Manager functionality, we could just extend from said Manager thus reducing on repeated code. Due to the limitation of
Java, classes are not able to extend from multiple classes. To remedy this, we created a wrapper
class, `ChildrenAndTaskListManager`.

It is important to note that `ChildrenManager` is a generic class that accepts classes that implements
It is important to note that `ChildManager` is a generic class that accepts classes that implements
the `IChildElement` interface. This was done to reduce repeated code while introducing a degree of polymorphism.

In our implementation, only the parents have reference to the child. This reference is stored by using
Expand Down Expand Up @@ -1621,7 +1621,7 @@ in the overall effort.
*relative** paths. This component played a crucial role in managing navigation and executing dynamic commands within
our application.

- **ChildrenManager Component:** The component was instrumental in representing the hierarchical structure in our
- **ChildManager Component:** The component was instrumental in representing the hierarchical structure in our
application. We successfully leveraged this component to perform operations related to child entities, optimizing the
handling of students within groups and groups within the ProfBook.

Expand Down
4 changes: 2 additions & 2 deletions docs/diagrams/ProfBookClassDiagram.puml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ skinparam arrowColor MODEL_COLOR
skinparam classBackgroundColor MODEL_COLOR

Package ProfBook as ProfBookPackage <<Rectangle>>{
Class "ChildrenManager" as ChildrenManager
Class "ChildManager" as ChildrenManager
Class "<<interface>>\nIChildElement" as IChildElement
Class "<<interface>>\nIChildManager" as IChildManager
Class "{abstract}\nChildrenAndTaskListManager" as ChildrenAndTaskListManager
Class "{abstract}\nChildAndTaskListManager" as ChildrenAndTaskListManager
Class Root
Class Group
Class Student
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ public class CreateDeadlineCommand extends Command {
+ " -d, --desc Description of the deadline task\n"
+ " -dt, --datetime Deadline of the task\n"
+ " Format: yyyy-MM-dd HH:mm\n"
+ " \'yyyy\': year, \'MM\': month, 'dd\': day,\n"
+ " \'HH\': hour (24-hour format), 'mm\': minutes.\n"
+ " 'yyyy': year, 'MM': month, 'dd': day,\n"
+ " 'HH': hour (24-hour format), 'mm': minutes.\n"
+ "\n"
+ "Option: \n"
+ " path Valid path to group or student\n"
Expand Down Expand Up @@ -78,7 +78,7 @@ public class CreateDeadlineCommand extends Command {

public static final CreateDeadlineCommand HELP_MESSAGE = new CreateDeadlineCommand() {
@Override
public CommandResult execute(Model model) throws CommandException {
public CommandResult execute(Model model) {
return new CommandResult(MESSAGE_USAGE);
}
};
Expand Down Expand Up @@ -190,15 +190,12 @@ private CommandResult addTaskToAllStuInGrp(Model model) throws CommandException
ChildOperation<Student> groupOper = model.groupChildOperation(path);

// Check whether all children already have the task
if (groupOper.checkIfAllChildrenHaveTask(deadline, 1)) {
if (groupOper.doAllChildrenHaveTasks(deadline, 1)) {
throw new CommandException(String.format(MESSAGE_ALL_CHILDREN_HAVE_TASK, "student"));
}

// Check whether at least one of the children has the task
boolean warning = false;
if (groupOper.checkIfAnyChildHasTask(deadline, 1)) {
warning = true;
}
boolean warning = groupOper.doAnyChildrenHaveTasks(deadline, 1);

groupOper.addTaskToAllChildren(deadline, 1);
model.updateList();
Expand All @@ -217,15 +214,12 @@ private CommandResult addTaskToAllStuInRoot(Model model) throws CommandException
ChildOperation<Group> operation = model.rootChildOperation();

// Check whether all children already have the task
if (operation.checkIfAllChildrenHaveTask(deadline, 2)) {
if (operation.doAllChildrenHaveTasks(deadline, 2)) {
throw new CommandException(String.format(MESSAGE_ALL_CHILDREN_HAVE_TASK, "student"));
}

// Check whether at least one of the children has the task
boolean warning = false;
if (operation.checkIfAnyChildHasTask(deadline, 2)) {
warning = true;
}
boolean warning = operation.doAnyChildrenHaveTasks(deadline, 2);

operation.addTaskToAllChildren(deadline, 2);
model.updateList();
Expand Down Expand Up @@ -258,15 +252,12 @@ private CommandResult addTaskToAllGrpInRoot(Model model) throws CommandException
ChildOperation<Group> rootOper = model.rootChildOperation();

// Check whether all children already have the task
if (rootOper.checkIfAllChildrenHaveTask(deadline, 1)) {
if (rootOper.doAllChildrenHaveTasks(deadline, 1)) {
throw new CommandException(String.format(MESSAGE_ALL_CHILDREN_HAVE_TASK, "group"));
}

// Check whether at least one of the children has the task
boolean warning = false;
if (rootOper.checkIfAnyChildHasTask(deadline, 1)) {
warning = true;
}
boolean warning = rootOper.doAnyChildrenHaveTasks(deadline, 1);

rootOper.addTaskToAllChildren(deadline, 1);
model.updateList();
Expand Down
23 changes: 7 additions & 16 deletions src/main/java/seedu/address/logic/commands/CreateTodoCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public class CreateTodoCommand extends Command {

public static final CreateTodoCommand HELP_MESSAGE = new CreateTodoCommand() {
@Override
public CommandResult execute(Model model) throws CommandException {
public CommandResult execute(Model model) {
return new CommandResult(MESSAGE_USAGE);
}
};
Expand Down Expand Up @@ -185,15 +185,12 @@ private CommandResult addTaskToAllStuInGrp(Model model) throws CommandException
ChildOperation<Student> groupOper = model.groupChildOperation(path);

// Check whether all children already have the task
if (groupOper.checkIfAllChildrenHaveTask(todo, 1)) {
if (groupOper.doAllChildrenHaveTasks(todo, 1)) {
throw new CommandException(String.format(MESSAGE_ALL_CHILDREN_HAVE_TASK, "student"));
}

// Check whether at least one of the children has the task
boolean warning = false;
if (groupOper.checkIfAnyChildHasTask(todo, 1)) {
warning = true;
}
boolean warning = groupOper.doAnyChildrenHaveTasks(todo, 1);

groupOper.addTaskToAllChildren(todo, 1);
model.updateList();
Expand All @@ -212,15 +209,12 @@ private CommandResult addTaskToAllStuInRoot(Model model) throws CommandException
ChildOperation<Group> operation = model.rootChildOperation();

// Check whether all children already have the task
if (operation.checkIfAllChildrenHaveTask(todo, 2)) {
if (operation.doAllChildrenHaveTasks(todo, 2)) {
throw new CommandException(String.format(MESSAGE_ALL_CHILDREN_HAVE_TASK, "student"));
}

// Check whether at least one of the children has the task
boolean warning = false;
if (operation.checkIfAnyChildHasTask(todo, 2)) {
warning = true;
}
boolean warning = operation.doAnyChildrenHaveTasks(todo, 2);

operation.addTaskToAllChildren(todo, 2);
model.updateList();
Expand Down Expand Up @@ -253,15 +247,12 @@ private CommandResult addTaskToAllGrpInRoot(Model model) throws CommandException
ChildOperation<Group> rootOper = model.rootChildOperation();

// Check whether all children already have the task
if (rootOper.checkIfAllChildrenHaveTask(todo, 1)) {
if (rootOper.doAllChildrenHaveTasks(todo, 1)) {
throw new CommandException(String.format(MESSAGE_ALL_CHILDREN_HAVE_TASK, "group"));
}

// Check whether at least one of the children has the task
boolean warning = false;
if (rootOper.checkIfAnyChildHasTask(todo, 1)) {
warning = true;
}
boolean warning = rootOper.doAnyChildrenHaveTasks(todo, 1);

rootOper.addTaskToAllChildren(todo, 1);
model.updateList();
Expand Down
68 changes: 41 additions & 27 deletions src/main/java/seedu/address/model/ChildOperation.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

import seedu.address.commons.core.LogsCenter;
import seedu.address.model.id.Id;
import seedu.address.model.profbook.ChildrenAndTaskListManager;
import seedu.address.model.profbook.ChildAndTaskListManager;
import seedu.address.model.profbook.IChildElement;
import seedu.address.model.profbook.IChildrenManager;
import seedu.address.model.profbook.IChildManager;
import seedu.address.model.profbook.exceptions.DuplicateChildException;
import seedu.address.model.profbook.exceptions.NoSuchChildException;
import seedu.address.model.task.ITaskListManager;
Expand All @@ -23,14 +23,14 @@
*/
public class ChildOperation<T extends IChildElement<T>> implements IChildOperation<T> {
public static final String MESSAGE_ALL_CHILDREN_MUST_BE_TASK_LIST_MANAGER =
"All children must be task list manager.";
"All children must be task list manager.";
public static final String MESSAGE_INVALID_LEVEL = "Invalid level.";

private final IChildrenManager<T> baseDir;
private final IChildManager<T> baseDir;

private final Logger logger = LogsCenter.getLogger(ChildOperation.class);

public ChildOperation(IChildrenManager<T> baseDir) {
public ChildOperation(IChildManager<T> baseDir) {
this.baseDir = baseDir;
}

Expand Down Expand Up @@ -117,57 +117,68 @@ public int numOfChildren() {
}

@Override
public void addTaskToAllChildren(Task task, int level) {
public boolean doAllChildrenHaveTasks(Task task, int level) {
List<IChildElement<?>> children = getAllTaskListManagerChildrenAtLevel(level);

for (IChildElement<?> child : children) {
Task clonedTask = task.clone();

//Defensive programming - check if getAllTaskListManagerChildrenAtLevel works as expected
if (!(child instanceof ITaskListManager)) {
throw new IllegalArgumentException(MESSAGE_ALL_CHILDREN_MUST_BE_TASK_LIST_MANAGER);
}

ITaskListManager tlm = (ITaskListManager) child;
if (tlm.contains(task)) {
continue;
// Type casting is safe as we checked earlier
ITaskListManager taskListManager = (ITaskListManager) child;
if (!taskListManager.contains(task)) {
return false;
}
tlm.addTask(clonedTask);
}
return true;
}

@Override
public boolean checkIfAllChildrenHaveTask(Task task, int level) {
public boolean doAnyChildrenHaveTasks(Task task, int level) {
List<IChildElement<?>> children = getAllTaskListManagerChildrenAtLevel(level);

for (IChildElement<?> child : children) {

//Defensive programming - check if getAllTaskListManagerChildrenAtLevel works as expected
if (!(child instanceof ITaskListManager)) {
throw new IllegalArgumentException(MESSAGE_ALL_CHILDREN_MUST_BE_TASK_LIST_MANAGER);
}
ITaskListManager tlm = (ITaskListManager) child;
if (!tlm.contains(task)) {
return false;

// Type casting is safe as we checked earlier
ITaskListManager taskListManager = (ITaskListManager) child;
if (taskListManager.contains(task)) {
return true;
}
}

return true;
return false;
}

@Override
public boolean checkIfAnyChildHasTask(Task task, int level) {
public void addTaskToAllChildren(Task task, int level) {
List<IChildElement<?>> children = getAllTaskListManagerChildrenAtLevel(level);

for (IChildElement<?> child : children) {
Task clonedTask = task.clone();

//Defensive programming - check if getAllTaskListManagerChildrenAtLevel works as expected
if (!(child instanceof ITaskListManager)) {
throw new IllegalArgumentException(MESSAGE_ALL_CHILDREN_MUST_BE_TASK_LIST_MANAGER);
}
ITaskListManager tlm = (ITaskListManager) child;
if (tlm.contains(task)) {
return true;

// Type casting is safe as we checked earlier
ITaskListManager taskListManager = (ITaskListManager) child;
if (taskListManager.contains(task)) {
continue;
}
taskListManager.addTask(clonedTask);
}

return false;
}


@Override
public boolean equals(Object o) {
if (this == o) {
Expand All @@ -189,12 +200,15 @@ private List<IChildElement<?>> getAllTaskListManagerChildrenAtLevel(int level) {
List<IChildElement<?>> children = new ArrayList<>(getAllChildren());
while (--level > 0) {
List<IChildElement<?>> list = new ArrayList<>();

for (IChildElement<?> child : children) {
if (child instanceof ChildrenAndTaskListManager<?, ?>) {
ChildrenAndTaskListManager<?, ?> ctlm = (ChildrenAndTaskListManager<?, ?>) child;
list.addAll(ctlm.getAllChildren());
} else {
throw new IllegalArgumentException(MESSAGE_INVALID_LEVEL);

if (child instanceof ChildAndTaskListManager<?, ?>) { // If child is a group directory
ChildAndTaskListManager<?, ?> childrenAndTaskListManager =
(ChildAndTaskListManager<?, ?>) child; // type casting is safe as we checked earlier
list.addAll(childrenAndTaskListManager.getAllChildren());
} else { // If child is a student directory
throw new IllegalArgumentException(MESSAGE_INVALID_LEVEL); // Student does not have any child

Check warning on line 211 in src/main/java/seedu/address/model/ChildOperation.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/model/ChildOperation.java#L211

Added line #L211 was not covered by tests
}
}
children = new ArrayList<>(list);
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/seedu/address/model/IChildOperation.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* @param <T> Type of the child
*/
public interface IChildOperation<T extends IChildElement<T>> {

/**
* Adds the child to list of children
*
Expand Down Expand Up @@ -77,14 +78,14 @@ public interface IChildOperation<T extends IChildElement<T>> {
* The {@code level} must be level of task list manager.
* e.g. Group level and student level.
*/
boolean checkIfAllChildrenHaveTask(Task task, int level);
boolean doAllChildrenHaveTasks(Task task, int level);

/**
* Returns {@code true} if at least one child at {@code level} has the task.
* The {@code level} must be level of task list manager.
* e.g. Group level and student level.
*/
boolean checkIfAnyChildHasTask(Task task, int level);
boolean doAnyChildrenHaveTasks(Task task, int level);

/**
* Returns Number of current children
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,31 @@
* Interface for classes that operations that involve a task list, ensures that all basic functions are present to
* interact with TaskListManager instance
*/
public interface ITaskOperations {
public interface ITaskOperation {

/**
* Checks if current task is present
* Adds the tasks to the task list granted it does not result in a duplicate
*
* @param t The task in question
*/
boolean hasTask(Task t);
void addTask(Task t);

/**
* Check if index is between 0 and task list size.
*/
boolean isValidIndex(int index);

/**
* Return the size of the task list.
* Checks if current task is present
*
* @param t The task in question
*/
int getTaskListSize();
boolean hasTask(Task t);

/**
* Adds a new tasks to the task list.
* Task must not be duplicated class.
*
* @param t The task in question
* Return the current size of the task list.
*/
void addTask(Task t);
int getTaskListSize();

/**
* Deletes the task at the specified index
Expand Down
Loading

0 comments on commit 533966c

Please sign in to comment.