getFilteredPlayerList() {
+ return model.getFilteredPlayerList();
+ }
+
@Override
public Path getAddressBookFilePath() {
return model.getAddressBookFilePath();
diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/seedu/address/logic/commands/ClearCommand.java
deleted file mode 100644
index 9c86b1fa6e4..00000000000
--- a/src/main/java/seedu/address/logic/commands/ClearCommand.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-
-import seedu.address.model.AddressBook;
-import seedu.address.model.Model;
-
-/**
- * Clears the address book.
- */
-public class ClearCommand extends Command {
-
- public static final String COMMAND_WORD = "clear";
- public static final String MESSAGE_SUCCESS = "Address book has been cleared!";
-
-
- @Override
- public CommandResult execute(Model model) {
- requireNonNull(model);
- model.setAddressBook(new AddressBook());
- return new CommandResult(MESSAGE_SUCCESS);
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/seedu/address/logic/commands/Command.java
index 64f18992160..dcdcf996a3e 100644
--- a/src/main/java/seedu/address/logic/commands/Command.java
+++ b/src/main/java/seedu/address/logic/commands/Command.java
@@ -1,6 +1,6 @@
package seedu.address.logic.commands;
-import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.logic.commands.task.exceptions.CommandException;
import seedu.address.model.Model;
/**
diff --git a/src/main/java/seedu/address/logic/commands/CommandResult.java b/src/main/java/seedu/address/logic/commands/CommandResult.java
index 92f900b7916..30792f5aa8a 100644
--- a/src/main/java/seedu/address/logic/commands/CommandResult.java
+++ b/src/main/java/seedu/address/logic/commands/CommandResult.java
@@ -1,9 +1,13 @@
package seedu.address.logic.commands;
import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.core.Tabs.DEFAULT;
import java.util.Objects;
+import seedu.address.model.image.Image;
+
+
/**
* Represents the result of a command execution.
*/
@@ -11,19 +15,47 @@ public class CommandResult {
private final String feedbackToUser;
- /** Help information should be shown to the user. */
+ /**
+ * Help information should be shown to the user.
+ */
private final boolean showHelp;
- /** The application should exit. */
+ /**
+ * The application should exit.
+ */
private final boolean exit;
+ private final int tabPane;
+
+ /**
+ * The background image of StrategyBoard should be changed
+ */
+ private final boolean isLoadImage;
+
+ /**
+ * The background image of StrategyBoard
+ */
+ private final Image image;
+
+ /**
+ * The application should export image in user-selected directory.
+ */
+ private final boolean isExportCommand;
+
/**
* Constructs a {@code CommandResult} with the specified fields.
+ *
+ * Specifically used for load-court and export commands.
*/
- public CommandResult(String feedbackToUser, boolean showHelp, boolean exit) {
+ public CommandResult(String feedbackToUser, boolean showHelp, boolean exit, int tabPane,
+ boolean isLoadImage, Image image, boolean isExportCommand) {
this.feedbackToUser = requireNonNull(feedbackToUser);
this.showHelp = showHelp;
+ this.isLoadImage = isLoadImage;
+ this.image = image;
this.exit = exit;
+ this.tabPane = tabPane;
+ this.isExportCommand = isExportCommand;
}
/**
@@ -31,7 +63,7 @@ public CommandResult(String feedbackToUser, boolean showHelp, boolean exit) {
* and other fields set to their default value.
*/
public CommandResult(String feedbackToUser) {
- this(feedbackToUser, false, false);
+ this(feedbackToUser, false, false, DEFAULT, false, null, false);
}
public String getFeedbackToUser() {
@@ -46,6 +78,22 @@ public boolean isExit() {
return exit;
}
+ public int getTabPane() {
+ return tabPane;
+ }
+
+ public boolean isLoadImageCommand() {
+ return isLoadImage;
+ }
+
+ public Image getBackgroundImage() {
+ return image;
+ }
+
+ public boolean isExportCommand() {
+ return isExportCommand;
+ }
+
@Override
public boolean equals(Object other) {
if (other == this) {
@@ -60,12 +108,27 @@ public boolean equals(Object other) {
CommandResult otherCommandResult = (CommandResult) other;
return feedbackToUser.equals(otherCommandResult.feedbackToUser)
&& showHelp == otherCommandResult.showHelp
- && exit == otherCommandResult.exit;
+ && exit == otherCommandResult.exit
+ && tabPane == otherCommandResult.tabPane
+ && isLoadImage == otherCommandResult.isLoadImage
+ && image == otherCommandResult.image;
}
@Override
public int hashCode() {
- return Objects.hash(feedbackToUser, showHelp, exit);
+ return Objects.hash(feedbackToUser, showHelp, exit, tabPane, isLoadImage, image);
}
+ @Override
+ public String toString() {
+ return "CommandResult{"
+ + "feedbackToUser='" + feedbackToUser + '\''
+ + ", showHelp=" + showHelp
+ + ", exit=" + exit
+ + ", tabPane=" + tabPane
+ + ", isLoadImage=" + isLoadImage
+ + ", image=" + image
+ + ", isExportCommand=" + isExportCommand
+ + '}';
+ }
}
diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java
deleted file mode 100644
index 02fd256acba..00000000000
--- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.List;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.exceptions.CommandException;
-import seedu.address.model.Model;
-import seedu.address.model.person.Person;
-
-/**
- * Deletes a person identified using it's displayed index from the address book.
- */
-public class DeleteCommand extends Command {
-
- public static final String COMMAND_WORD = "delete";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD
- + ": Deletes the person identified by the index number used in the displayed person list.\n"
- + "Parameters: INDEX (must be a positive integer)\n"
- + "Example: " + COMMAND_WORD + " 1";
-
- public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s";
-
- private final Index targetIndex;
-
- public DeleteCommand(Index targetIndex) {
- this.targetIndex = targetIndex;
- }
-
- @Override
- public CommandResult execute(Model model) throws CommandException {
- requireNonNull(model);
- List lastShownList = model.getFilteredPersonList();
-
- if (targetIndex.getZeroBased() >= lastShownList.size()) {
- throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
- }
-
- Person personToDelete = lastShownList.get(targetIndex.getZeroBased());
- model.deletePerson(personToDelete);
- return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, personToDelete));
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof DeleteCommand // instanceof handles nulls
- && targetIndex.equals(((DeleteCommand) other).targetIndex)); // state check
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/seedu/address/logic/commands/ExitCommand.java
index 3dd85a8ba90..3c4d3cde3e3 100644
--- a/src/main/java/seedu/address/logic/commands/ExitCommand.java
+++ b/src/main/java/seedu/address/logic/commands/ExitCommand.java
@@ -1,5 +1,7 @@
package seedu.address.logic.commands;
+import static seedu.address.commons.core.Tabs.DEFAULT;
+
import seedu.address.model.Model;
/**
@@ -13,7 +15,7 @@ public class ExitCommand extends Command {
@Override
public CommandResult execute(Model model) {
- return new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, true);
+ return new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, true, DEFAULT, false, null, false);
}
}
diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java
deleted file mode 100644
index d6b19b0a0de..00000000000
--- a/src/main/java/seedu/address/logic/commands/FindCommand.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package seedu.address.logic.commands;
-
-import static java.util.Objects.requireNonNull;
-
-import seedu.address.commons.core.Messages;
-import seedu.address.model.Model;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-
-/**
- * Finds and lists all persons in address book whose name contains any of the argument keywords.
- * Keyword matching is case insensitive.
- */
-public class FindCommand extends Command {
-
- public static final String COMMAND_WORD = "find";
-
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose names contain any of "
- + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n"
- + "Parameters: KEYWORD [MORE_KEYWORDS]...\n"
- + "Example: " + COMMAND_WORD + " alice bob charlie";
-
- private final NameContainsKeywordsPredicate predicate;
-
- public FindCommand(NameContainsKeywordsPredicate predicate) {
- this.predicate = predicate;
- }
-
- @Override
- public CommandResult execute(Model model) {
- requireNonNull(model);
- model.updateFilteredPersonList(predicate);
- return new CommandResult(
- String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size()));
- }
-
- @Override
- public boolean equals(Object other) {
- return other == this // short circuit if same object
- || (other instanceof FindCommand // instanceof handles nulls
- && predicate.equals(((FindCommand) other).predicate)); // state check
- }
-}
diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/seedu/address/logic/commands/HelpCommand.java
index bf824f91bd0..f8269c9c759 100644
--- a/src/main/java/seedu/address/logic/commands/HelpCommand.java
+++ b/src/main/java/seedu/address/logic/commands/HelpCommand.java
@@ -1,5 +1,7 @@
package seedu.address.logic.commands;
+import static seedu.address.commons.core.Tabs.DEFAULT;
+
import seedu.address.model.Model;
/**
@@ -16,6 +18,6 @@ public class HelpCommand extends Command {
@Override
public CommandResult execute(Model model) {
- return new CommandResult(SHOWING_HELP_MESSAGE, true, false);
+ return new CommandResult(SHOWING_HELP_MESSAGE, true, false, DEFAULT, false, null, false);
}
}
diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/person/AddPersonCommand.java
similarity index 79%
rename from src/main/java/seedu/address/logic/commands/AddCommand.java
rename to src/main/java/seedu/address/logic/commands/person/AddPersonCommand.java
index 71656d7c5c8..ec6580ea81a 100644
--- a/src/main/java/seedu/address/logic/commands/AddCommand.java
+++ b/src/main/java/seedu/address/logic/commands/person/AddPersonCommand.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.commands;
+package seedu.address.logic.commands.person;
import static java.util.Objects.requireNonNull;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
@@ -7,16 +7,18 @@
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
-import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.person.Person;
/**
* Adds a person to the address book.
*/
-public class AddCommand extends Command {
+public class AddPersonCommand extends Command {
- public static final String COMMAND_WORD = "add";
+ public static final String COMMAND_WORD = "add-p";
public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a person to the address book. "
+ "Parameters: "
@@ -41,7 +43,7 @@ public class AddCommand extends Command {
/**
* Creates an AddCommand to add the specified {@code Person}
*/
- public AddCommand(Person person) {
+ public AddPersonCommand(Person person) {
requireNonNull(person);
toAdd = person;
}
@@ -61,7 +63,7 @@ public CommandResult execute(Model model) throws CommandException {
@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
- || (other instanceof AddCommand // instanceof handles nulls
- && toAdd.equals(((AddCommand) other).toAdd));
+ || (other instanceof AddPersonCommand // instanceof handles nulls
+ && toAdd.equals(((AddPersonCommand) other).toAdd));
}
}
diff --git a/src/main/java/seedu/address/logic/commands/person/AddPersonTagCommand.java b/src/main/java/seedu/address/logic/commands/person/AddPersonTagCommand.java
new file mode 100644
index 00000000000..d0e29e52e41
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/person/AddPersonTagCommand.java
@@ -0,0 +1,121 @@
+package seedu.address.logic.commands.person;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.name.Name;
+import seedu.address.model.note.Note;
+import seedu.address.model.person.Address;
+import seedu.address.model.person.Email;
+import seedu.address.model.person.Person;
+import seedu.address.model.person.Phone;
+import seedu.address.model.tag.Tag;
+
+public class AddPersonTagCommand extends Command {
+ public static final String COMMAND_WORD = "tag-add-p";
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Add a tag to a person from our contact list. "
+ + "Parameters: "
+ + "INDEX (must be a positive integer) "
+ + "TAG NAME (must be non-empty)\n"
+ + "Example: " + COMMAND_WORD + " "
+ + "1 "
+ + "friend";
+ public static final String MESSAGE_ADD_TAG_SUCCESS = "Added tag: %1$s";
+ public static final String MESSAGE_DUPLICATE_TAG = "This person already has this tag!";
+
+ public final Index index;
+ public final String tagName;
+
+ /**
+ * Public constructor for AddTagCommand
+ *
+ * @param index Index of person to add tag to
+ * @param tagName Name of tag
+ */
+ public AddPersonTagCommand(Index index, String tagName) {
+ requireAllNonNull(index, tagName);
+
+ this.index = index;
+ this.tagName = tagName;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredPersonList();
+
+ // Exception when index out of bounds
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ }
+
+
+ Person personToEdit = lastShownList.get(index.getZeroBased());
+ Person editedPerson = addTagToPerson(personToEdit);
+
+
+ // Exception when a duplicate tag is added
+ Tag testTag = new Tag(this.tagName);
+ if (personToEdit.getTags().contains(testTag)) {
+ throw new CommandException(MESSAGE_DUPLICATE_TAG);
+ }
+
+ model.setPerson(personToEdit, editedPerson);
+ model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+ return new CommandResult(String.format(MESSAGE_ADD_TAG_SUCCESS, this.tagName));
+ }
+
+ /**
+ * Creates and returns a {@code Person} with a new tag {@code tagName} added to
+ * {@code personToEdit}
+ *
+ * @param personToEdit Person to be edited
+ * @return New Person object with the tag added (tag list updated)
+ */
+ private Person addTagToPerson(Person personToEdit) throws CommandException {
+ // Keep all other fields the same
+ Name updatedName = personToEdit.getName();
+ Phone updatedPhone = personToEdit.getPhone();
+ Email updatedEmail = personToEdit.getEmail();
+ Address updatedAddress = personToEdit.getAddress();
+ List updatedStrengths = personToEdit.getStrengths();
+ List updatedWeaknesses = personToEdit.getWeaknesses();
+ List updatedMisc = personToEdit.getMiscellaneous();
+
+ // Changing tags
+ // Make modifiable copy since Person#getTags returns an unmodifiable Set
+ Set tagList = new HashSet<>(personToEdit.getTags());
+ try {
+ tagList.add(new Tag(this.tagName));
+ } catch (Exception e) {
+ throw new CommandException(Messages.MESSAGE_INVALID_TAG);
+ }
+
+
+ return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, tagList,
+ updatedStrengths, updatedWeaknesses, updatedMisc);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+
+ return other == this // short circuit if same object
+ || (other instanceof AddPersonTagCommand // instanceof handles nulls
+ && (index.equals(((AddPersonTagCommand) other).index)
+ && tagName.equals((((AddPersonTagCommand) other).tagName))));
+ }
+
+}
+
diff --git a/src/main/java/seedu/address/logic/commands/person/ClearPersonCommand.java b/src/main/java/seedu/address/logic/commands/person/ClearPersonCommand.java
new file mode 100644
index 00000000000..14ac2e9ee9d
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/person/ClearPersonCommand.java
@@ -0,0 +1,63 @@
+package seedu.address.logic.commands.person;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import seedu.address.logic.EditTaskDescriptor;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.model.AddressBook;
+import seedu.address.model.Model;
+import seedu.address.model.name.Name;
+import seedu.address.model.tag.Tag;
+import seedu.address.model.task.Date;
+import seedu.address.model.task.EndTime;
+import seedu.address.model.task.StartTime;
+import seedu.address.model.task.Task;
+
+/**
+ * Clears the address book.
+ */
+public class ClearPersonCommand extends Command {
+
+ public static final String COMMAND_WORD = "clear-p";
+ public static final String MESSAGE_SUCCESS = "Address book has been cleared!";
+
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ List unfilteredTaskList = model.getUnfilteredTaskList();
+
+ // update tasks after clearing the address book
+ for (Task task: unfilteredTaskList) {
+ EditTaskDescriptor editTaskDescriptor = new EditTaskDescriptor();
+ Set persons = new HashSet<>();
+ editTaskDescriptor.setPersons(persons);
+ Task editedTask = createEditedTask(task, editTaskDescriptor);
+ model.setTask(task, editedTask);
+ }
+ model.setAddressBook(new AddressBook());
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+
+ /**
+ * Creates and returns a {@code Task} with the details of {@code taskToEdit}
+ * edited with {@code editTaskDescriptor}.
+ */
+ public static Task createEditedTask(Task taskToEdit, EditTaskDescriptor editTaskDescriptor) {
+ requireNonNull(taskToEdit);
+
+ Name updatedName = editTaskDescriptor.getName().orElse(taskToEdit.getName());
+ Date updatedDate = editTaskDescriptor.getDate().orElse(taskToEdit.getDate());
+ StartTime updatedStartTime = editTaskDescriptor.getStartTime().orElse(taskToEdit.getStartTime());
+ EndTime updatedEndTime = editTaskDescriptor.getEndTime().orElse(taskToEdit.getEndTime());
+ Set updatedTags = editTaskDescriptor.getTags().orElse(taskToEdit.getTags());
+ Set updatedPersons = editTaskDescriptor.getPersons().orElse(taskToEdit.getPersons());
+ return new Task(updatedName, updatedDate,
+ updatedStartTime, updatedEndTime, updatedTags, updatedPersons);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/person/DeletePersonCommand.java b/src/main/java/seedu/address/logic/commands/person/DeletePersonCommand.java
new file mode 100644
index 00000000000..762e6336458
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/person/DeletePersonCommand.java
@@ -0,0 +1,94 @@
+package seedu.address.logic.commands.person;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.EditTaskDescriptor;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.name.Name;
+import seedu.address.model.person.Person;
+import seedu.address.model.tag.Tag;
+import seedu.address.model.task.Date;
+import seedu.address.model.task.EndTime;
+import seedu.address.model.task.StartTime;
+import seedu.address.model.task.Task;
+
+/**
+ * Deletes a person identified using it's displayed index from the address book.
+ */
+public class DeletePersonCommand extends Command {
+
+ public static final String COMMAND_WORD = "del-p";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Deletes the person identified by the index number used in the displayed person list.\n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 1";
+
+ public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Person: %1$s";
+
+ private final Index targetIndex;
+
+ public DeletePersonCommand(Index targetIndex) {
+ this.targetIndex = targetIndex;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownPersonList = model.getFilteredPersonList();
+ List unfilteredTaskList = model.getUnfilteredTaskList();
+
+ if (targetIndex.getZeroBased() >= lastShownPersonList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ }
+
+ Person personToDelete = lastShownPersonList.get(targetIndex.getZeroBased());
+
+ // update tasks after the deletion of person
+ for (Task task: unfilteredTaskList) {
+ if (task.getPersons().contains(personToDelete.getName())) {
+ EditTaskDescriptor editTaskDescriptor = new EditTaskDescriptor();
+ Set persons = new HashSet<>(task.getPersons());
+ persons.remove(personToDelete.getName());
+ editTaskDescriptor.setPersons(persons);
+ Task editedTask = createEditedTask(task, editTaskDescriptor);
+ model.setTask(task, editedTask);
+ }
+ }
+ model.deletePerson(personToDelete);
+ return new CommandResult(String.format(MESSAGE_DELETE_PERSON_SUCCESS, personToDelete));
+ }
+
+ /**
+ * Creates and returns a {@code Task} with the details of {@code taskToEdit}
+ * edited with {@code editTaskDescriptor}.
+ */
+ public static Task createEditedTask(Task taskToEdit, EditTaskDescriptor editTaskDescriptor) {
+ assert taskToEdit != null;
+
+ Name updatedName = editTaskDescriptor.getName().orElse(taskToEdit.getName());
+ Date updatedDate = editTaskDescriptor.getDate().orElse(taskToEdit.getDate());
+ StartTime updatedStartTime = editTaskDescriptor.getStartTime().orElse(taskToEdit.getStartTime());
+ EndTime updatedEndTime = editTaskDescriptor.getEndTime().orElse(taskToEdit.getEndTime());
+ Set updatedTags = editTaskDescriptor.getTags().orElse(taskToEdit.getTags());
+ Set updatedPersons = editTaskDescriptor.getPersons().orElse(taskToEdit.getPersons());
+ return new Task(updatedName, updatedDate,
+ updatedStartTime, updatedEndTime, updatedTags, updatedPersons);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof DeletePersonCommand // instanceof handles nulls
+ && targetIndex.equals(((DeletePersonCommand) other).targetIndex)); // state check
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/person/DeletePersonTagCommand.java b/src/main/java/seedu/address/logic/commands/person/DeletePersonTagCommand.java
new file mode 100644
index 00000000000..c2f437daa27
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/person/DeletePersonTagCommand.java
@@ -0,0 +1,113 @@
+package seedu.address.logic.commands.person;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.name.Name;
+import seedu.address.model.note.Note;
+import seedu.address.model.person.Address;
+import seedu.address.model.person.Email;
+import seedu.address.model.person.Person;
+import seedu.address.model.person.Phone;
+import seedu.address.model.tag.Tag;
+
+public class DeletePersonTagCommand extends Command {
+ public static final String COMMAND_WORD = "tag-del-p";
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Delete a tag from a person in our contact list. "
+ + "Parameters: "
+ + "INDEX (must be a positive integer) "
+ + "TAG NAME (must be non-empty)\n"
+ + "Example: " + COMMAND_WORD + " "
+ + "1 "
+ + "friend";
+ public static final String MESSAGE_DELETE_TAG_SUCCESS = "Deleted tag: %1$s";
+ public static final String MESSAGE_INVALID_TAG = "This person does not have this tag!";
+
+ private final Index index;
+ private final String tagName;
+
+ /**
+ * Public constructor for DeleteTagCommand
+ * @param index Index of person to delete tag from
+ * @param tagName Name of tag
+ */
+
+ public DeletePersonTagCommand(Index index, String tagName) {
+ requireAllNonNull(index, tagName);
+
+ this.index = index;
+ this.tagName = tagName;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredPersonList();
+
+ // Exception when index out of bounds
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ }
+
+
+ Person personToEdit = lastShownList.get(index.getZeroBased());
+ Person editedPerson = deleteTagFromPerson(personToEdit);
+
+ // Exception when a non-existent tag is indicated for deletion
+ Tag testTag = new Tag(this.tagName);
+ if (!personToEdit.getTags().contains(testTag)) {
+ throw new CommandException(MESSAGE_INVALID_TAG);
+ }
+
+ model.setPerson(personToEdit, editedPerson);
+ model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+ return new CommandResult(String.format(MESSAGE_DELETE_TAG_SUCCESS, this.tagName));
+ }
+
+ /**
+ * Creates and returns a {@code Person} with a new tag {@code tagName} added to
+ * {@code personToEdit}
+ *
+ * @param personToEdit Person to be edited
+ * @return New Person object with the tag added (tag list updated)
+ */
+ private Person deleteTagFromPerson(Person personToEdit) {
+ // Keep all other fields the same
+ Name updatedName = personToEdit.getName();
+ Phone updatedPhone = personToEdit.getPhone();
+ Email updatedEmail = personToEdit.getEmail();
+ Address updatedAddress = personToEdit.getAddress();
+ List updatedStrengths = personToEdit.getStrengths();
+ List updatedWeaknesses = personToEdit.getWeaknesses();
+ List updatedMisc = personToEdit.getMiscellaneous();
+
+ // Changing tags
+ // Make modifiable copy since Person#getTags returns an unmodifiable Set
+ Set tagList = new HashSet<>(personToEdit.getTags());
+ tagList.remove(new Tag(this.tagName));
+
+ return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, tagList,
+ updatedStrengths, updatedWeaknesses, updatedMisc);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+
+ return other == this // short circuit if same object
+ || (other instanceof DeletePersonTagCommand // instanceof handles nulls
+ && (index.equals(((DeletePersonTagCommand) other).index)
+ && tagName.equals((((DeletePersonTagCommand) other).tagName))));
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/person/EditPersonCommand.java
similarity index 55%
rename from src/main/java/seedu/address/logic/commands/EditCommand.java
rename to src/main/java/seedu/address/logic/commands/person/EditPersonCommand.java
index 7e36114902f..c3b8cb98319 100644
--- a/src/main/java/seedu/address/logic/commands/EditCommand.java
+++ b/src/main/java/seedu/address/logic/commands/person/EditPersonCommand.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.commands;
+package seedu.address.logic.commands.person;
import static java.util.Objects.requireNonNull;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
@@ -8,30 +8,36 @@
import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
-import java.util.Collections;
import java.util.HashSet;
import java.util.List;
-import java.util.Optional;
import java.util.Set;
import seedu.address.commons.core.Messages;
import seedu.address.commons.core.index.Index;
-import seedu.address.commons.util.CollectionUtil;
-import seedu.address.logic.commands.exceptions.CommandException;
+import seedu.address.logic.EditPersonDescriptor;
+import seedu.address.logic.EditTaskDescriptor;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
import seedu.address.model.Model;
+import seedu.address.model.name.Name;
+import seedu.address.model.note.Note;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
import seedu.address.model.tag.Tag;
+import seedu.address.model.task.Date;
+import seedu.address.model.task.EndTime;
+import seedu.address.model.task.StartTime;
+import seedu.address.model.task.Task;
/**
* Edits the details of an existing person in the address book.
*/
-public class EditCommand extends Command {
+public class EditPersonCommand extends Command {
- public static final String COMMAND_WORD = "edit";
+ public static final String COMMAND_WORD = "edit-p";
public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the person identified "
+ "by the index number used in the displayed person list. "
@@ -57,7 +63,7 @@ public class EditCommand extends Command {
* @param index of the person in the filtered person list to edit
* @param editPersonDescriptor details to edit the person with
*/
- public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) {
+ public EditPersonCommand(Index index, EditPersonDescriptor editPersonDescriptor) {
requireNonNull(index);
requireNonNull(editPersonDescriptor);
@@ -69,6 +75,7 @@ public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) {
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
List lastShownList = model.getFilteredPersonList();
+ List unfilteredTaskList = model.getUnfilteredTaskList();
if (index.getZeroBased() >= lastShownList.size()) {
throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
@@ -81,6 +88,21 @@ public CommandResult execute(Model model) throws CommandException {
throw new CommandException(MESSAGE_DUPLICATE_PERSON);
}
+ // update tasks if a person's name is edited
+ for (Task task: unfilteredTaskList) {
+ if (personToEdit.getName().equals(editedPerson.getName())) {
+ break;
+ } else if (task.getPersons().contains(personToEdit.getName())) {
+ EditTaskDescriptor editTaskDescriptor = new EditTaskDescriptor();
+ Set persons = new HashSet<>(task.getPersons());
+ persons.remove(personToEdit.getName());
+ persons.add(editedPerson.getName());
+ editTaskDescriptor.setPersons(persons);
+ Task editedTask = createEditedTask(task, editTaskDescriptor);
+ model.setTask(task, editedTask);
+ }
+ }
+
model.setPerson(personToEdit, editedPerson);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson));
@@ -98,8 +120,28 @@ private static Person createEditedPerson(Person personToEdit, EditPersonDescript
Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail());
Address updatedAddress = editPersonDescriptor.getAddress().orElse(personToEdit.getAddress());
Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags());
+ List updatedStrengthNotes = editPersonDescriptor.getStrengths().orElse(personToEdit.getStrengths());
+ List updatedWeaknessNotes = editPersonDescriptor.getWeaknesses().orElse(personToEdit.getWeaknesses());
+ List updatedMisc = editPersonDescriptor.getMiscellaneous().orElse(personToEdit.getMiscellaneous());
+ return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags,
+ updatedStrengthNotes, updatedWeaknessNotes, updatedMisc);
+ }
- return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags);
+ /**
+ * Creates and returns a {@code Task} with the details of {@code taskToEdit}
+ * edited with {@code editTaskDescriptor}.
+ */
+ public static Task createEditedTask(Task taskToEdit, EditTaskDescriptor editTaskDescriptor) {
+ assert taskToEdit != null;
+
+ Name updatedName = editTaskDescriptor.getName().orElse(taskToEdit.getName());
+ Date updatedDate = editTaskDescriptor.getDate().orElse(taskToEdit.getDate());
+ StartTime updatedStartTime = editTaskDescriptor.getStartTime().orElse(taskToEdit.getStartTime());
+ EndTime updatedEndTime = editTaskDescriptor.getEndTime().orElse(taskToEdit.getEndTime());
+ Set updatedTags = editTaskDescriptor.getTags().orElse(taskToEdit.getTags());
+ Set updatedPersons = editTaskDescriptor.getPersons().orElse(taskToEdit.getPersons());
+ return new Task(updatedName, updatedDate,
+ updatedStartTime, updatedEndTime, updatedTags, updatedPersons);
}
@Override
@@ -110,117 +152,13 @@ public boolean equals(Object other) {
}
// instanceof handles nulls
- if (!(other instanceof EditCommand)) {
+ if (!(other instanceof EditPersonCommand)) {
return false;
}
// state check
- EditCommand e = (EditCommand) other;
+ EditPersonCommand e = (EditPersonCommand) other;
return index.equals(e.index)
&& editPersonDescriptor.equals(e.editPersonDescriptor);
}
-
- /**
- * Stores the details to edit the person with. Each non-empty field value will replace the
- * corresponding field value of the person.
- */
- public static class EditPersonDescriptor {
- private Name name;
- private Phone phone;
- private Email email;
- private Address address;
- private Set tags;
-
- public EditPersonDescriptor() {}
-
- /**
- * Copy constructor.
- * A defensive copy of {@code tags} is used internally.
- */
- public EditPersonDescriptor(EditPersonDescriptor toCopy) {
- setName(toCopy.name);
- setPhone(toCopy.phone);
- setEmail(toCopy.email);
- setAddress(toCopy.address);
- setTags(toCopy.tags);
- }
-
- /**
- * Returns true if at least one field is edited.
- */
- public boolean isAnyFieldEdited() {
- return CollectionUtil.isAnyNonNull(name, phone, email, address, tags);
- }
-
- public void setName(Name name) {
- this.name = name;
- }
-
- public Optional getName() {
- return Optional.ofNullable(name);
- }
-
- public void setPhone(Phone phone) {
- this.phone = phone;
- }
-
- public Optional getPhone() {
- return Optional.ofNullable(phone);
- }
-
- public void setEmail(Email email) {
- this.email = email;
- }
-
- public Optional getEmail() {
- return Optional.ofNullable(email);
- }
-
- public void setAddress(Address address) {
- this.address = address;
- }
-
- public Optional getAddress() {
- return Optional.ofNullable(address);
- }
-
- /**
- * Sets {@code tags} to this object's {@code tags}.
- * A defensive copy of {@code tags} is used internally.
- */
- public void setTags(Set tags) {
- this.tags = (tags != null) ? new HashSet<>(tags) : null;
- }
-
- /**
- * Returns an unmodifiable tag set, which throws {@code UnsupportedOperationException}
- * if modification is attempted.
- * Returns {@code Optional#empty()} if {@code tags} is null.
- */
- public Optional> getTags() {
- return (tags != null) ? Optional.of(Collections.unmodifiableSet(tags)) : Optional.empty();
- }
-
- @Override
- public boolean equals(Object other) {
- // short circuit if same object
- if (other == this) {
- return true;
- }
-
- // instanceof handles nulls
- if (!(other instanceof EditPersonDescriptor)) {
- return false;
- }
-
- // state check
- EditPersonDescriptor e = (EditPersonDescriptor) other;
-
- return getName().equals(e.getName())
- && getPhone().equals(e.getPhone())
- && getEmail().equals(e.getEmail())
- && getAddress().equals(e.getAddress())
- && getTags().equals(e.getTags());
- }
- }
}
diff --git a/src/main/java/seedu/address/logic/commands/person/FindPersonCommand.java b/src/main/java/seedu/address/logic/commands/person/FindPersonCommand.java
new file mode 100644
index 00000000000..30948a6c67d
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/person/FindPersonCommand.java
@@ -0,0 +1,58 @@
+package seedu.address.logic.commands.person;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.model.Model;
+import seedu.address.model.name.PersonNameContainsKeywordsPredicate;
+import seedu.address.model.tag.PersonTagContainsKeywordsPredicate;
+
+/**
+ * Finds and lists all persons in address book whose name contains any of the argument keywords.
+ * Keyword matching is case insensitive.
+ */
+public class FindPersonCommand extends Command {
+
+ public static final String COMMAND_WORD = "find-p";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Finds all persons whose names or tags contain any of "
+ + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n"
+ + "Parameters: "
+ + "[" + PREFIX_NAME + "NAME]... "
+ + "[" + PREFIX_TAG + "TAG]...\n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_NAME + "Alex " + PREFIX_NAME + "Charlotte "
+ + PREFIX_TAG + "friends";
+
+ private final PersonNameContainsKeywordsPredicate namePredicate;
+ private final PersonTagContainsKeywordsPredicate tagPredicate;
+
+ /**
+ * Initialises new object using {@code namePredicate} and {@code tagPredicate}
+ */
+ public FindPersonCommand(PersonNameContainsKeywordsPredicate namePredicate,
+ PersonTagContainsKeywordsPredicate tagPredicate) {
+ this.namePredicate = namePredicate;
+ this.tagPredicate = tagPredicate;
+ }
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ model.updateFilteredPersonList(namePredicate.or(tagPredicate));
+ return new CommandResult(
+ String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size()));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof FindPersonCommand // instanceof handles nulls
+ && namePredicate.equals(((FindPersonCommand) other).namePredicate)
+ && tagPredicate.equals(((FindPersonCommand) other).tagPredicate)); // state check
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/seedu/address/logic/commands/person/ListPersonCommand.java
similarity index 67%
rename from src/main/java/seedu/address/logic/commands/ListCommand.java
rename to src/main/java/seedu/address/logic/commands/person/ListPersonCommand.java
index 84be6ad2596..342fc2f0d5a 100644
--- a/src/main/java/seedu/address/logic/commands/ListCommand.java
+++ b/src/main/java/seedu/address/logic/commands/person/ListPersonCommand.java
@@ -1,16 +1,18 @@
-package seedu.address.logic.commands;
+package seedu.address.logic.commands.person;
import static java.util.Objects.requireNonNull;
import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
import seedu.address.model.Model;
/**
* Lists all persons in the address book to the user.
*/
-public class ListCommand extends Command {
+public class ListPersonCommand extends Command {
- public static final String COMMAND_WORD = "list";
+ public static final String COMMAND_WORD = "list-p";
public static final String MESSAGE_SUCCESS = "Listed all persons";
diff --git a/src/main/java/seedu/address/logic/commands/person/SortStrengthCommand.java b/src/main/java/seedu/address/logic/commands/person/SortStrengthCommand.java
new file mode 100644
index 00000000000..26b94300e74
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/person/SortStrengthCommand.java
@@ -0,0 +1,62 @@
+package seedu.address.logic.commands.person;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.AddressBook;
+import seedu.address.model.Model;
+import seedu.address.model.person.Person;
+
+/**
+ * Sort the list of persons in the address book by total strengths in descending order and display to the user.
+ */
+public class SortStrengthCommand extends Command {
+
+ public static final String COMMAND_WORD = "sort-strength";
+
+ public static final String MESSAGE_SUCCESS = "Sorted all persons by most strengths";
+
+ /**
+ * Comparator that compares two Person objects by their total strengths.
+ * If total strengths of two Person objects are equal, then compare by least total weaknesses
+ */
+ protected static final Comparator BY_STRENGTHS = new Comparator() {
+ @Override
+ public int compare(Person o1, Person o2) {
+ //if total strengths are equal, order by least weaknesses
+ if (o1.getStrengths().size() == o2.getStrengths().size()) {
+ return o1.getWeaknesses().size() - o2.getWeaknesses().size();
+ } else if (o1.getStrengths().size() > o2.getStrengths().size()) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+ };
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownPersonList = model.getUnfilteredPersonList();
+ List newPersonList = new ArrayList<>(lastShownPersonList);
+ AddressBook newAddressBook = new AddressBook();
+
+ if (newPersonList.isEmpty()) {
+ throw new CommandException(Messages.MESSAGE_EMPTY_PERSON_LIST);
+ }
+
+ newPersonList.sort(BY_STRENGTHS);
+ for (Person p : newPersonList) {
+ newAddressBook.addPerson(p);
+ }
+ model.setAddressBook(new AddressBook(newAddressBook)); //update address book with new sorted book
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/person/SortWeaknessCommand.java b/src/main/java/seedu/address/logic/commands/person/SortWeaknessCommand.java
new file mode 100644
index 00000000000..6a92ace65a0
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/person/SortWeaknessCommand.java
@@ -0,0 +1,62 @@
+package seedu.address.logic.commands.person;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.AddressBook;
+import seedu.address.model.Model;
+import seedu.address.model.person.Person;
+
+/**
+ * Sort the list of persons in the address book by total weaknesses in descending order and display to the user.
+ */
+public class SortWeaknessCommand extends Command {
+
+ public static final String COMMAND_WORD = "sort-weakness";
+
+ public static final String MESSAGE_SUCCESS = "Sorted all persons by most weaknesses";
+
+ /**
+ * Comparator that compares two Person objects by their total weaknesses.
+ * If total weaknesses of two Person objects are equal, then compare by least total strengths
+ */
+ protected static final Comparator BY_WEAKNESSES = new Comparator() {
+ @Override
+ public int compare(Person o1, Person o2) {
+ //if total weaknesses are equal, order by least strengths
+ if (o1.getWeaknesses().size() == o2.getWeaknesses().size()) {
+ return o1.getStrengths().size() - o2.getStrengths().size();
+ } else if (o1.getWeaknesses().size() > o2.getWeaknesses().size()) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+ };
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownPersonList = model.getUnfilteredPersonList();
+ List newPersonList = new ArrayList<>(lastShownPersonList);
+ AddressBook newAddressBook = new AddressBook();
+
+ if (newPersonList.isEmpty()) {
+ throw new CommandException(Messages.MESSAGE_EMPTY_PERSON_LIST);
+ }
+
+ newPersonList.sort(BY_WEAKNESSES);
+ for (Person p : newPersonList) {
+ newAddressBook.addPerson(p);
+ }
+ model.setAddressBook(new AddressBook(newAddressBook)); //update address book with new sorted book
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/person/notecommands/AddMiscCommand.java b/src/main/java/seedu/address/logic/commands/person/notecommands/AddMiscCommand.java
new file mode 100644
index 00000000000..bf23b9898c7
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/person/notecommands/AddMiscCommand.java
@@ -0,0 +1,94 @@
+package seedu.address.logic.commands.person.notecommands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.note.Note;
+import seedu.address.model.person.Person;
+
+/**
+ * Adds a miscellaneous note to a person in the address book.
+ */
+public class AddMiscCommand extends Command {
+ public static final String COMMAND_WORD = "misc-add";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Add a miscellaneous note to a selected person from our contact list. "
+ + "Parameters: "
+ + "INDEX (must be a positive integer) "
+ + "NOTE_DESCRIPTION (must be non-empty and not more than 50 characters)\n"
+ + "Example: " + COMMAND_WORD + " "
+ + "1 "
+ + "Surgery Scheduled for tomorrow";
+
+ public static final String MESSAGE_SUCCESS = "New miscellaneous note added: %1$s";
+
+ private final Index index;
+ private final Note misc;
+
+ /**
+ * @param index of the person in the filtered person list to add the misc
+ * @param misc note of the person to be added
+ */
+ public AddMiscCommand(Index index, Note misc) {
+ requireAllNonNull(index, misc);
+
+ this.index = index;
+ this.misc = misc;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredPersonList();
+
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ }
+
+ Person personToEdit = lastShownList.get(index.getZeroBased());
+ List newMiscList = new ArrayList<>(personToEdit.getMiscellaneous());
+
+ if (newMiscList.contains(misc)) { //makes sure note does not already exist for given person
+ throw new CommandException(Messages.MESSAGE_DUPLICATE_MISC);
+ }
+
+ newMiscList.add(misc);
+
+ Person editedPerson = new Person(
+ personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(),
+ personToEdit.getAddress(), personToEdit.getTags(), personToEdit.getStrengths(),
+ personToEdit.getWeaknesses(), newMiscList);
+
+ model.setPerson(personToEdit, editedPerson);
+ model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+
+ return new CommandResult(generateSuccessMessage(editedPerson));
+ }
+
+ /**
+ * Generates a command execution success message
+ * {@code personToEdit}.
+ */
+ private String generateSuccessMessage(Person personToEdit) {
+ return String.format(MESSAGE_SUCCESS, personToEdit);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof AddMiscCommand // instanceof handles nulls
+ && (index.equals(((AddMiscCommand) other).index)
+ && misc.equals(((AddMiscCommand) other).misc)));
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/person/notecommands/AddStrengthCommand.java b/src/main/java/seedu/address/logic/commands/person/notecommands/AddStrengthCommand.java
new file mode 100644
index 00000000000..1746b1abc5e
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/person/notecommands/AddStrengthCommand.java
@@ -0,0 +1,94 @@
+package seedu.address.logic.commands.person.notecommands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.note.Note;
+import seedu.address.model.person.Person;
+
+/**
+ * Adds a strength note to a person in the address book.
+ */
+public class AddStrengthCommand extends Command {
+ public static final String COMMAND_WORD = "strength-add";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Add a strength to a selected person from our contact list. "
+ + "Parameters: "
+ + "INDEX (must be a positive integer) "
+ + "NOTE_DESCRIPTION (must be non-empty and not more than 50 characters)\n"
+ + "Example: " + COMMAND_WORD + " "
+ + "1 "
+ + "Good at defense";
+
+ public static final String MESSAGE_SUCCESS = "New strength added: %1$s";
+
+ private final Index index;
+ private final Note strength;
+
+ /**
+ * @param index of the person in the filtered person list to add the strength
+ * @param strength of the person to be added
+ */
+ public AddStrengthCommand(Index index, Note strength) {
+ requireAllNonNull(index, strength);
+
+ this.index = index;
+ this.strength = strength;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredPersonList();
+
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ }
+
+ Person personToEdit = lastShownList.get(index.getZeroBased());
+ List newStrengthList = new ArrayList<>(personToEdit.getStrengths());
+
+ if (newStrengthList.contains(strength)) { //makes sure note does not already exist for given person
+ throw new CommandException(Messages.MESSAGE_DUPLICATE_STRENGTH);
+ }
+
+ newStrengthList.add(strength);
+
+ Person editedPerson = new Person(
+ personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(),
+ personToEdit.getAddress(), personToEdit.getTags(), newStrengthList, personToEdit.getWeaknesses(),
+ personToEdit.getMiscellaneous());
+
+ model.setPerson(personToEdit, editedPerson);
+ model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+
+ return new CommandResult(generateSuccessMessage(editedPerson));
+ }
+
+ /**
+ * Generates a command execution success message
+ * {@code personToEdit}.
+ */
+ private String generateSuccessMessage(Person personToEdit) {
+ return String.format(MESSAGE_SUCCESS, personToEdit);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof AddStrengthCommand // instanceof handles nulls
+ && (index.equals(((AddStrengthCommand) other).index)
+ && strength.equals(((AddStrengthCommand) other).strength)));
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/person/notecommands/AddWeaknessCommand.java b/src/main/java/seedu/address/logic/commands/person/notecommands/AddWeaknessCommand.java
new file mode 100644
index 00000000000..7b09cc08913
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/person/notecommands/AddWeaknessCommand.java
@@ -0,0 +1,94 @@
+package seedu.address.logic.commands.person.notecommands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.note.Note;
+import seedu.address.model.person.Person;
+
+/**
+ * Adds a weakness note to a person in the address book.
+ */
+public class AddWeaknessCommand extends Command {
+ public static final String COMMAND_WORD = "weakness-add";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Add a weakness to a selected person from our contact list. "
+ + "Parameters: "
+ + "INDEX (must be a positive integer) "
+ + "NOTE_DESCRIPTION (must be non-empty and not more than 50 characters)\n"
+ + "Example: " + COMMAND_WORD + " "
+ + "1 "
+ + "Poor endurance";
+
+ public static final String MESSAGE_SUCCESS = "New weakness added: %1$s";
+
+ private final Index index;
+ private final Note weakness;
+
+ /**
+ * @param index of the person in the filtered person list to add the weakness
+ * @param weakness of the person to be added
+ */
+ public AddWeaknessCommand(Index index, Note weakness) {
+ requireAllNonNull(index, weakness);
+
+ this.index = index;
+ this.weakness = weakness;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredPersonList();
+
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ }
+
+ Person personToEdit = lastShownList.get(index.getZeroBased());
+ List newWeaknessList = new ArrayList<>(personToEdit.getWeaknesses());
+
+ if (newWeaknessList.contains(weakness)) { //makes sure note does not already exist for given person
+ throw new CommandException(Messages.MESSAGE_DUPLICATE_WEAKNESS);
+ }
+
+ newWeaknessList.add(weakness);
+
+ Person editedPerson = new Person(
+ personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(),
+ personToEdit.getAddress(), personToEdit.getTags(), personToEdit.getStrengths(), newWeaknessList,
+ personToEdit.getMiscellaneous());
+
+ model.setPerson(personToEdit, editedPerson);
+ model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+
+ return new CommandResult(generateSuccessMessage(editedPerson));
+ }
+
+ /**
+ * Generates a command execution success message
+ * {@code personToEdit}.
+ */
+ private String generateSuccessMessage(Person personToEdit) {
+ return String.format(MESSAGE_SUCCESS, personToEdit);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof AddWeaknessCommand // instanceof handles nulls
+ && (index.equals(((AddWeaknessCommand) other).index)
+ && weakness.equals(((AddWeaknessCommand) other).weakness)));
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/person/notecommands/DeleteMiscCommand.java b/src/main/java/seedu/address/logic/commands/person/notecommands/DeleteMiscCommand.java
new file mode 100644
index 00000000000..2cc43209149
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/person/notecommands/DeleteMiscCommand.java
@@ -0,0 +1,94 @@
+package seedu.address.logic.commands.person.notecommands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.note.Note;
+import seedu.address.model.person.Person;
+
+/**
+ * Delete a miscellaneous note from a person in the address book
+ */
+public class DeleteMiscCommand extends Command {
+ public static final String COMMAND_WORD = "misc-del";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Delete a miscellaneous note from the note-list of selected person from our contact list. "
+ + "Parameters: "
+ + "INDEX (must be a positive integer) "
+ + "NOTE-INDEX (must be a positive)\n"
+ + "Example: " + COMMAND_WORD + " "
+ + "1 "
+ + "2";
+
+ public static final String MESSAGE_SUCCESS = "Miscellaneous note has been deleted: %1$s";
+
+
+ private final Index index;
+ private final Index noteIndex;
+
+ /**
+ * Constructor of DeleteMiscCommand class
+ * @param index index of the person in the filtered person list
+ * @param noteIndex index of the misc. note from the person's misc-list to be deleted
+ */
+ public DeleteMiscCommand(Index index, Index noteIndex) {
+ requireAllNonNull(index, noteIndex);
+ this.index = index;
+ this.noteIndex = noteIndex;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredPersonList();
+
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ }
+
+ Person personToEdit = lastShownList.get(index.getZeroBased());
+ List newMisc = new ArrayList<>(personToEdit.getMiscellaneous());
+
+ if (noteIndex.getZeroBased() >= newMisc.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_NOTE_DISPLAYED_INDEX);
+ }
+ newMisc.remove(noteIndex.getZeroBased());
+
+ Person editedPerson = new Person(
+ personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(),
+ personToEdit.getAddress(), personToEdit.getTags(),
+ personToEdit.getStrengths(), personToEdit.getWeaknesses(), newMisc);
+
+ model.setPerson(personToEdit, editedPerson);
+ model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+
+ return new CommandResult(generateSuccessMessage(editedPerson));
+ }
+
+ /**
+ * Generates a command execution success message
+ * {@code personToEdit}.
+ */
+ private String generateSuccessMessage(Person personToEdit) {
+ return String.format(MESSAGE_SUCCESS, personToEdit);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this
+ || (other instanceof DeleteMiscCommand
+ && index.equals(((DeleteMiscCommand) other).index)
+ && noteIndex.equals(((DeleteMiscCommand) other).noteIndex));
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/person/notecommands/DeleteStrengthCommand.java b/src/main/java/seedu/address/logic/commands/person/notecommands/DeleteStrengthCommand.java
new file mode 100644
index 00000000000..cdbbdcb02e7
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/person/notecommands/DeleteStrengthCommand.java
@@ -0,0 +1,93 @@
+package seedu.address.logic.commands.person.notecommands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.note.Note;
+import seedu.address.model.person.Person;
+
+/**
+ * Delete a strength from a person in the address book
+ */
+public class DeleteStrengthCommand extends Command {
+ public static final String COMMAND_WORD = "strength-del";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Delete a strength from the strength-list of a selected person from our contact list. "
+ + "Parameters: "
+ + "INDEX (must be a positive integer) "
+ + "NOTE-INDEX (must be a positive)\n"
+ + "Example: " + COMMAND_WORD + " "
+ + "1 "
+ + "2";
+
+ public static final String MESSAGE_SUCCESS = "Strength has been deleted: %1$s";
+
+ private final Index index;
+ private final Index noteIndex;
+
+ /**
+ * Constructor of DeleteStrengthCommand class
+ * @param index index of the person in the filtered person list
+ * @param noteIndex index of the strength from the person's strength-list to be deleted
+ */
+ public DeleteStrengthCommand(Index index, Index noteIndex) {
+ requireAllNonNull(index, noteIndex);
+ this.index = index;
+ this.noteIndex = noteIndex;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredPersonList();
+
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ }
+
+ Person personToEdit = lastShownList.get(index.getZeroBased());
+ List newStrengths = new ArrayList<>(personToEdit.getStrengths());
+
+ if (noteIndex.getZeroBased() >= newStrengths.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_NOTE_DISPLAYED_INDEX);
+ }
+ newStrengths.remove(noteIndex.getZeroBased());
+
+ Person editedPerson = new Person(
+ personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(),
+ personToEdit.getAddress(), personToEdit.getTags(),
+ newStrengths, personToEdit.getWeaknesses(), personToEdit.getMiscellaneous());
+
+ model.setPerson(personToEdit, editedPerson);
+ model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+
+ return new CommandResult(generateSuccessMessage(editedPerson));
+ }
+
+ /**
+ * Generates a command execution success message
+ * {@code personToEdit}.
+ */
+ private String generateSuccessMessage(Person personToEdit) {
+ return String.format(MESSAGE_SUCCESS, personToEdit);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this
+ || (other instanceof DeleteStrengthCommand
+ && index.equals(((DeleteStrengthCommand) other).index)
+ && noteIndex.equals(((DeleteStrengthCommand) other).noteIndex));
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/person/notecommands/DeleteWeaknessCommand.java b/src/main/java/seedu/address/logic/commands/person/notecommands/DeleteWeaknessCommand.java
new file mode 100644
index 00000000000..e54b530006f
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/person/notecommands/DeleteWeaknessCommand.java
@@ -0,0 +1,93 @@
+package seedu.address.logic.commands.person.notecommands;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.note.Note;
+import seedu.address.model.person.Person;
+
+/**
+ * Delete a weakness from a person in the address book
+ */
+public class DeleteWeaknessCommand extends Command {
+ public static final String COMMAND_WORD = "weakness-del";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Delete a weakness from the weakness-list of a selected person from our contact list. "
+ + "Parameters: "
+ + "INDEX (must be a positive integer) "
+ + "NOTE-INDEX (must be a positive)\n"
+ + "Example: " + COMMAND_WORD + " "
+ + "1 "
+ + "2";
+
+ public static final String MESSAGE_SUCCESS = "Weakness has been deleted: %1$s";
+
+ private final Index index;
+ private final Index noteIndex;
+
+ /**
+ * Constructor of DeleteWeaknessCommand class
+ * @param index index of the person in the filtered person list
+ * @param noteIndex index of the weakness from the person's weakness-list to be deleted
+ */
+ public DeleteWeaknessCommand(Index index, Index noteIndex) {
+ requireAllNonNull(index, noteIndex);
+ this.index = index;
+ this.noteIndex = noteIndex;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredPersonList();
+
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
+ }
+
+ Person personToEdit = lastShownList.get(index.getZeroBased());
+ List newWeaknesses = new ArrayList<>(personToEdit.getWeaknesses());
+
+ if (noteIndex.getZeroBased() >= newWeaknesses.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_NOTE_DISPLAYED_INDEX);
+ }
+ newWeaknesses.remove(noteIndex.getZeroBased());
+
+ Person editedPerson = new Person(
+ personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(),
+ personToEdit.getAddress(), personToEdit.getTags(),
+ personToEdit.getStrengths(), newWeaknesses, personToEdit.getMiscellaneous());
+
+ model.setPerson(personToEdit, editedPerson);
+ model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+
+ return new CommandResult(generateSuccessMessage(editedPerson));
+ }
+
+ /**
+ * Generates a command execution success message
+ * {@code personToEdit}.
+ */
+ private String generateSuccessMessage(Person personToEdit) {
+ return String.format(MESSAGE_SUCCESS, personToEdit);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this
+ || (other instanceof DeleteWeaknessCommand
+ && index.equals(((DeleteWeaknessCommand) other).index)
+ && noteIndex.equals(((DeleteWeaknessCommand) other).noteIndex));
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/strategy/AddPlayerCommand.java b/src/main/java/seedu/address/logic/commands/strategy/AddPlayerCommand.java
new file mode 100644
index 00000000000..49a32e225c1
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/strategy/AddPlayerCommand.java
@@ -0,0 +1,62 @@
+package seedu.address.logic.commands.strategy;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.strategy.Player;
+
+/**
+ * Adds a player in the strategy panel
+ */
+public class AddPlayerCommand extends Command {
+ public static final String COMMAND_WORD = "add-player";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Add a player in the strategy panel. "
+ + "Parameters: "
+ + "PLAYER_NAME"
+ + "(must be non-empty, not more than 50 characters and does not contain \"/\")\n"
+ + "Example: " + COMMAND_WORD + " "
+ + "Lionel Messi";
+
+ public static final String MESSAGE_NOT_IMPLEMENTED_YET =
+ "AddPlayer command not implemented yet";
+
+ public static final String MESSAGE_SUCCESS = "New player added: %1$s";
+ public static final String MESSAGE_DUPLICATE_PLAYER = "This player already exists in the PlayerList";
+
+
+ private final Player toAdd;
+
+ /**
+ * Creates an AddPlayerCommand to add the specified {@code Player}.
+ */
+ public AddPlayerCommand(Player player) {
+ requireAllNonNull(player);
+ this.toAdd = player;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+
+ if (model.hasPlayer(toAdd)) {
+ throw new CommandException(MESSAGE_DUPLICATE_PLAYER);
+ }
+
+ model.addPlayer(toAdd);
+ return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd.getName()));
+ }
+
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof AddPlayerCommand // instanceof handles nulls
+ && (toAdd.equals(((AddPlayerCommand) other).toAdd)));
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/strategy/DeletePlayerCommand.java b/src/main/java/seedu/address/logic/commands/strategy/DeletePlayerCommand.java
new file mode 100644
index 00000000000..c10a8812283
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/strategy/DeletePlayerCommand.java
@@ -0,0 +1,66 @@
+package seedu.address.logic.commands.strategy;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.strategy.Player;
+
+/**
+ * Deletes a player in the strategy panel
+ */
+public class DeletePlayerCommand extends Command {
+ public static final String COMMAND_WORD = "del-player";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Delete a player in the strategy panel. "
+ + "Parameters: "
+ + "PLAYER_NAME (must be non-empty and not more than 50 characters)\n"
+ + "Example: " + COMMAND_WORD + " "
+ + "Lionel Messi";
+
+ public static final String MESSAGE_NOT_IMPLEMENTED_YET =
+ "DeletePlayer command not implemented yet";
+
+ public static final String MESSAGE_SUCCESS = "Player deleted: %1$s";
+ public static final String MESSAGE_PLAYER_NOT_FOUND = "Player not found in the list: %1$s";
+
+ private final String playerName;
+
+ /**
+ * @param playerName the name of the player to be added
+ */
+ public DeletePlayerCommand(String playerName) {
+ requireAllNonNull(playerName);
+ this.playerName = playerName;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ if (playerName.replace("/s", "").isEmpty()) {
+ throw new CommandException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddPlayerCommand.MESSAGE_USAGE));
+ }
+
+ Player player = new Player(playerName);
+ if (!model.hasPlayer(player)) {
+ throw new CommandException(
+ String.format(MESSAGE_PLAYER_NOT_FOUND, playerName));
+ }
+ requireNonNull(model);
+ model.deletePlayer(player);
+ return new CommandResult(String.format(MESSAGE_SUCCESS, playerName));
+ }
+
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof DeletePlayerCommand // instanceof handles nulls
+ && (playerName.equals(((DeletePlayerCommand) other).playerName)));
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/strategy/ExportCommand.java b/src/main/java/seedu/address/logic/commands/strategy/ExportCommand.java
new file mode 100644
index 00000000000..a8e361d1418
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/strategy/ExportCommand.java
@@ -0,0 +1,41 @@
+package seedu.address.logic.commands.strategy;
+
+import static seedu.address.commons.core.Tabs.DEFAULT;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+
+import java.util.UUID;
+
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.model.Model;
+
+public class ExportCommand extends Command {
+
+ public static final String COMMAND_WORD = "export";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Exports current Strategy Panel as a .png image into user selected directory. "
+ + "Example: " + COMMAND_WORD;
+
+ public static final String MESSAGE_EXPORT_ACKNOWLEDGEMENT = "Strategy Panel is being exported.";
+
+ private String fileName;
+
+ /**
+ * Constructor for ExportCommand class.
+ */
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireAllNonNull(model);
+ return new CommandResult(MESSAGE_EXPORT_ACKNOWLEDGEMENT, false, false, DEFAULT, false, null, true);
+ }
+
+
+ /**
+ * Randomized file names
+ */
+ private static String imageRandomFileString() {
+ return UUID.randomUUID().toString();
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/strategy/LoadCourtCommand.java b/src/main/java/seedu/address/logic/commands/strategy/LoadCourtCommand.java
new file mode 100644
index 00000000000..29ff3a4c3da
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/strategy/LoadCourtCommand.java
@@ -0,0 +1,78 @@
+package seedu.address.logic.commands.strategy;
+
+import static seedu.address.commons.core.Tabs.DEFAULT;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+
+import java.io.File;
+
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.image.Image;
+
+/**
+ * Loads an image as a background image for use in StrategyPanel.
+ */
+public class LoadCourtCommand extends Command {
+ public static final String COMMAND_WORD = "load-court";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Load an image from '/courts/' directory and sets as background image for the Strategy Panel. "
+ + "Parameters: "
+ + "IMAGE_NAME (" + Image.MESSAGE_CONSTRAINTS + ") "
+ + "Example: " + COMMAND_WORD + " "
+ + "basketball";
+
+ public static final String MESSAGE_SUCCESS = "Image has been loaded: %1$s";
+
+ public static final String MESSAGE_IMAGE_INVALID = "Provided image cannot be loaded!";
+
+ private final Image image;
+
+ /**
+ * Constructor for LoadCourtCommand class.
+ * @param image The image file.
+ */
+ public LoadCourtCommand(Image image) {
+ requireAllNonNull(image);
+ this.image = image;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireAllNonNull(model);
+ if (checkIfThrowsException()) { //throws if the image file cannot be instantiated
+ throw new CommandException(MESSAGE_IMAGE_INVALID);
+
+ }
+
+ return new CommandResult(generateSuccessMessage(image), false, false,
+ DEFAULT, true, this.image, false);
+ }
+
+ /**
+ * Creates a test javafx.scene.image object and checks if it throws an Exception.
+ * @return false if the image file cannot be instantiated
+ */
+ public boolean checkIfThrowsException() {
+ File imagePath = image.getImagePath();
+ javafx.scene.image.Image testImage = new javafx.scene.image.Image((imagePath.toURI().toString()));
+ return testImage.isError();
+ }
+
+ /**
+ * Generates a command execution success message
+ * {@code image}.
+ */
+ private String generateSuccessMessage(Image image) {
+ return String.format(MESSAGE_SUCCESS, image);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this
+ || (other instanceof LoadCourtCommand
+ && (image.equals(((LoadCourtCommand) other).image)));
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/strategy/MovePlayerCommand.java b/src/main/java/seedu/address/logic/commands/strategy/MovePlayerCommand.java
new file mode 100644
index 00000000000..e451b2de7ff
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/strategy/MovePlayerCommand.java
@@ -0,0 +1,78 @@
+package seedu.address.logic.commands.strategy;
+
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PLAYERS;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.strategy.Player;
+
+/**
+ * Moves the player to the specified location in the strategy board.
+ */
+public class MovePlayerCommand extends Command {
+ public static final String COMMAND_WORD = "move";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Moves the player to the specified location.\n"
+ + "Parameters: "
+ + "PLAYER_NAME "
+ + "x/X_COORDINATE (must be non-negative integers no greater than 1000) "
+ + "y/Y_COORDINATE (must be non-negative integers no greater than 600)\n"
+ + "Example: " + COMMAND_WORD + " " + "John" + " " + "x/100" + " " + "y/200";
+
+ public static final String MESSAGE_SUCCESS = "%1$s has been moved to the specified location: (%2$d, %3$d).";
+
+ private final String playerName;
+ private final int xCoordinate;
+ private final int yCoordinate;
+
+ /**
+ * @param playerName the name of the player to move
+ * @param xCoordinate the x coordinate of the location to move to
+ * @param yCoordinate the y coordinate of the location to move to
+ */
+ public MovePlayerCommand(String playerName, int xCoordinate, int yCoordinate) {
+ requireAllNonNull(playerName, xCoordinate, yCoordinate);
+
+ this.playerName = playerName;
+ this.xCoordinate = xCoordinate;
+ this.yCoordinate = yCoordinate;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireAllNonNull(model);
+
+ Player player = new Player(playerName);
+
+ if (!model.hasPlayer(player)) {
+ throw new CommandException(String.format(Messages.MESSAGE_INVALID_PLAYER, playerName));
+ }
+
+ Player editedPlayer = player.toCopy();
+
+ editedPlayer.setXCoord(xCoordinate);
+ editedPlayer.setYCoord(yCoordinate);
+
+ //model.setPlayer(player, editedPlayer);
+ model.deletePlayer(player);
+ model.addPlayer(editedPlayer);
+ model.updateFilteredPlayerList(PREDICATE_SHOW_ALL_PLAYERS);
+
+ return new CommandResult(String.format(MESSAGE_SUCCESS, playerName, xCoordinate, yCoordinate));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof MovePlayerCommand // instanceof handles nulls
+ && (playerName.equals(((MovePlayerCommand) other).playerName))
+ && (xCoordinate == ((MovePlayerCommand) other).xCoordinate)
+ && (yCoordinate == ((MovePlayerCommand) other).yCoordinate));
+ }
+}
+
diff --git a/src/main/java/seedu/address/logic/commands/task/AddTaskCommand.java b/src/main/java/seedu/address/logic/commands/task/AddTaskCommand.java
new file mode 100644
index 00000000000..01accf8b04f
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/task/AddTaskCommand.java
@@ -0,0 +1,116 @@
+package seedu.address.logic.commands.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_CONTACT;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ENDTIME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_STARTTIME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
+
+import java.util.List;
+import java.util.Set;
+
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.name.Name;
+import seedu.address.model.person.Person;
+import seedu.address.model.task.Task;
+
+
+/**
+ * Adds a task to the task list.
+ */
+public class AddTaskCommand extends Command {
+
+ public static final String COMMAND_WORD = "add-t";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a task to the TaskList. "
+ + "Parameters: "
+ + PREFIX_NAME + "NAME "
+ + PREFIX_DATE + "DATE "
+ + PREFIX_STARTTIME + "START TIME "
+ + PREFIX_ENDTIME + "END TIME "
+ + "[" + PREFIX_TAG + "TAG]..."
+ + "[" + PREFIX_CONTACT + "PERSON]...\n"
+ + "Example: " + COMMAND_WORD + " "
+ + PREFIX_NAME + "Investor introduction "
+ + PREFIX_DATE + "08-04-2022 "
+ + PREFIX_STARTTIME + "13:00 "
+ + PREFIX_ENDTIME + "15:00 "
+ + PREFIX_TAG + "funding "
+ + PREFIX_TAG + "meeting "
+ + PREFIX_CONTACT + "Alex Yeoh ";
+
+ public static final String MESSAGE_SUCCESS = "New task added: %1$s";
+ public static final String MESSAGE_DUPLICATE_TASK = "This task already exists in the task book";
+ public static final String MESSAGE_CONTACT_NOT_FOUND =
+ "The person %1$s cannot be found in the current address book";
+ public static final String MESSAGE_SCHEDULE_CONFLICT =
+ "The person %1$s is already involved in a task at this date and time";
+ public static final String MESSAGE_SCHEDULE_CONFLICT_START_END_TIME =
+ "This task ends before or at its specified start time!";
+ private final Task toAdd;
+
+ /**
+ * Creates an AddTaskCommand to add the specified {@code Task}
+ */
+ public AddTaskCommand(Task task) {
+ requireNonNull(task);
+ toAdd = task;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List unfilteredPersonList = model.getUnfilteredPersonList();
+ List unfilteredTaskList = model.getUnfilteredTaskList();
+ Set persons = toAdd.getPersons();
+
+ if (toAdd.hasStartEndTimeConflict()) {
+ throw new CommandException(String.format(MESSAGE_SCHEDULE_CONFLICT_START_END_TIME));
+ }
+
+ //checks if persons exist in the current list
+ for (Name name: persons) {
+ boolean notFound = true;
+ for (Person person: unfilteredPersonList) {
+ if (person.getName().equals(name)) {
+ notFound = false;
+ }
+ }
+ if (notFound) {
+ throw new CommandException(String.format(MESSAGE_CONTACT_NOT_FOUND, name));
+ }
+ }
+
+ //checks if persons are already involved in tasks with conflicting time ranges to the newly added task
+ for (Name name: persons) {
+ for (Task task: unfilteredTaskList) {
+ Set nameList = task.getPersons();
+ if (nameList.contains(name)) {
+ boolean conflictExist = task.hasDateTimeConflict(toAdd);
+ if (conflictExist) {
+ throw new CommandException(String.format(MESSAGE_SCHEDULE_CONFLICT, name));
+ }
+ }
+ }
+ }
+
+ if (model.hasTask(toAdd)) {
+ throw new CommandException(MESSAGE_DUPLICATE_TASK);
+ }
+
+ model.addTask(toAdd);
+ return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof AddTaskCommand // instanceof handles nulls
+ && toAdd.equals(((AddTaskCommand) other).toAdd));
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/task/AddTaskTagCommand.java b/src/main/java/seedu/address/logic/commands/task/AddTaskTagCommand.java
new file mode 100644
index 00000000000..915380a1d4b
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/task/AddTaskTagCommand.java
@@ -0,0 +1,116 @@
+package seedu.address.logic.commands.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_TASKS;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.name.Name;
+import seedu.address.model.tag.Tag;
+import seedu.address.model.task.Date;
+import seedu.address.model.task.EndTime;
+import seedu.address.model.task.StartTime;
+import seedu.address.model.task.Task;
+
+public class AddTaskTagCommand extends Command {
+ public static final String COMMAND_WORD = "tag-add-t";
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Add a tag to a task from our task list. "
+ + "Parameters: "
+ + "INDEX (must be a positive integer) "
+ + "TAG NAME (must be non-empty)\n"
+ + "Example: " + COMMAND_WORD + " "
+ + "1 "
+ + "important";
+ public static final String MESSAGE_DUPLICATE_TAG_T = "This task already has this tag!";
+ public static final String MESSAGE_ADD_TAG_SUCCESS = "Added tag: %1$s";
+
+ public final Index index;
+ public final String tagName;
+
+ /**
+ * Public contructor for AddTagToTaskCommand
+ * @param index Index of target task
+ * @param tagName Tag to be added to the target task
+ */
+ public AddTaskTagCommand(Index index, String tagName) {
+ requireAllNonNull(index, tagName);
+
+ this.index = index;
+ this.tagName = tagName;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredTaskList();
+
+ // Exception when index out of bounds
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+ Task taskToEdit = lastShownList.get(index.getZeroBased());
+ Task editedTask = addTagToTask(taskToEdit);
+
+ // Exception when a duplicate tag is added
+ Tag testTag = new Tag(this.tagName);
+ if (taskToEdit.getTags().contains(testTag)) {
+ throw new CommandException(MESSAGE_DUPLICATE_TAG_T);
+ }
+
+ model.setTask(taskToEdit, editedTask);
+ model.updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+ return new CommandResult(String.format(MESSAGE_ADD_TAG_SUCCESS, this.tagName));
+
+ }
+
+
+ /**
+ * Creates and returns a {@code Task} with a new tag {@code tagName} added to
+ * {@code taskToEdit}
+ *
+ * @param taskToEdit Person to be edited
+ * @return New Task object with the tag added (tag list updated)
+ */
+ private Task addTagToTask(Task taskToEdit) throws CommandException {
+ // Keep all other fields the same
+ Name updatedName = taskToEdit.getName();
+ Date updatedDate = taskToEdit.getDate();
+ StartTime updatedStartTime = taskToEdit.getStartTime();
+ EndTime updatedEndTime = taskToEdit.getEndTime();
+ Set updatedPersons = taskToEdit.getPersons();
+
+ // Changing tags
+ // Make modifiable copy since Task#getTags returns an unmodifiable Set
+ Set tagList = new HashSet<>(taskToEdit.getTags());
+ try {
+ tagList.add(new Tag(this.tagName));
+ } catch (Exception e) {
+ throw new CommandException(Messages.MESSAGE_INVALID_TAG);
+ }
+
+ return new Task(updatedName, updatedDate, updatedStartTime, updatedEndTime, tagList, updatedPersons);
+
+ }
+
+ @Override
+ public boolean equals(Object other) {
+
+ return other == this // short circuit if same object
+ || (other instanceof AddTaskTagCommand // instanceof handles nulls
+ && (index.equals(((AddTaskTagCommand) other).index)
+ && tagName.equals((((AddTaskTagCommand) other).tagName))));
+ }
+
+}
+
+
diff --git a/src/main/java/seedu/address/logic/commands/task/ClearTaskCommand.java b/src/main/java/seedu/address/logic/commands/task/ClearTaskCommand.java
new file mode 100644
index 00000000000..5ea4264d35f
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/task/ClearTaskCommand.java
@@ -0,0 +1,100 @@
+package seedu.address.logic.commands.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE;
+
+import java.util.List;
+
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.TaskBook;
+import seedu.address.model.task.Date;
+import seedu.address.model.task.Task;
+
+/**
+ * Clears the tasks from the task list (either all tasks or only for date specified).
+ */
+public class ClearTaskCommand extends Command {
+
+ public static final String COMMAND_WORD = "clear-t";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Deletes the task identified by the date used in the TaskList, or clears all tasks if date is not "
+ + "provided.\n"
+ + "Parameters: "
+ + "[" + PREFIX_DATE + "DATE]\n"
+ + "Example: " + COMMAND_WORD + " "
+ + PREFIX_DATE + "08-04-2022";
+
+ public static final String MESSAGE_SUCCESS = "Task list has been cleared!";
+ public static final String MESSAGE_SUCCESS_ALT = "Tasks for date specified have been cleared: %1$s";
+ public static final String MESSAGE_INVALID_DATE =
+ "There are no tasks in the list that match the provided date: %1$s";
+ public static final String MESSAGE_EMPTY_LIST = "Task list is empty!";
+
+ private final Date date;
+ private final boolean hasDate;
+
+ /**
+ * Creates a ClearTaskCommand to add the specified {@code Date}
+ */
+ public ClearTaskCommand(Date date) {
+ requireNonNull(date);
+ this.date = date;
+ this.hasDate = true;
+ }
+
+ /**
+ * Creates a ClearTaskCommand to clear all tasks in task list
+ */
+ public ClearTaskCommand() {
+ this.date = null;
+ this.hasDate = false;
+ }
+
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getUnfilteredTaskList();
+ if (lastShownList.isEmpty()) {
+ throw new CommandException(MESSAGE_EMPTY_LIST);
+ }
+
+ //check if task list contains given date
+ if (hasDate && !lastShownList
+ .stream()
+ .anyMatch((task) -> task.getDate()
+ .equals(date))) {
+ throw new CommandException(String.format(MESSAGE_INVALID_DATE, date));
+ }
+
+ if (!hasDate) {
+ model.setTaskBook(new TaskBook());
+ return new CommandResult(MESSAGE_SUCCESS);
+ } else {
+ for (int i = 0; i < lastShownList.size(); i++) {
+ if (lastShownList.get(i).getDate().equals(date)) {
+ Task currentTask = lastShownList.get(i);
+ model.deleteTask(currentTask);
+ --i; //decrement the list to avoid skipping elements
+ }
+ }
+ return new CommandResult(String.format(MESSAGE_SUCCESS_ALT, date));
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ //check to make sure boolean variable is correctly representing date object value
+ assert (hasDate && date != null) || (!hasDate && date == null)
+ : "Boolean variable does not represent date object";
+ return other == this //check if both are the same object reference
+ || (other instanceof ClearTaskCommand
+ && hasDate == (((ClearTaskCommand) other).hasDate) //check if both have dates
+ && (!hasDate || date.equals(((ClearTaskCommand) other).date))); //if they both don't have dates,
+ //return true. Otherwise, check if dates are equivalent
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/task/DeleteTaskCommand.java b/src/main/java/seedu/address/logic/commands/task/DeleteTaskCommand.java
new file mode 100644
index 00000000000..50f0fdc68d6
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/task/DeleteTaskCommand.java
@@ -0,0 +1,55 @@
+package seedu.address.logic.commands.task;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.List;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.task.Task;
+
+/**
+ * Deletes a task identified using its index from the TaskList.
+ */
+public class DeleteTaskCommand extends Command {
+
+ public static final String COMMAND_WORD = "del-t";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Deletes the task identified by the index number used in the TaskList.\n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 1";
+
+ public static final String MESSAGE_DELETE_TASK_SUCCESS = "Deleted Task: %1$s";
+
+ private final Index targetIndex;
+
+ public DeleteTaskCommand(Index targetIndex) {
+ this.targetIndex = targetIndex;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredTaskList();
+
+ if (targetIndex.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ Task taskToDelete = lastShownList.get(targetIndex.getZeroBased());
+ model.deleteTask(taskToDelete);
+ return new CommandResult(String.format(MESSAGE_DELETE_TASK_SUCCESS, taskToDelete));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof DeleteTaskCommand // instanceof handles nulls
+ && targetIndex.equals(((DeleteTaskCommand) other).targetIndex)); // state check
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/task/DeleteTaskTagCommand.java b/src/main/java/seedu/address/logic/commands/task/DeleteTaskTagCommand.java
new file mode 100644
index 00000000000..c4e42908aba
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/task/DeleteTaskTagCommand.java
@@ -0,0 +1,120 @@
+package seedu.address.logic.commands.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_TASKS;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.name.Name;
+import seedu.address.model.tag.Tag;
+import seedu.address.model.task.Date;
+import seedu.address.model.task.EndTime;
+import seedu.address.model.task.StartTime;
+import seedu.address.model.task.Task;
+
+public class DeleteTaskTagCommand extends Command {
+ public static final String COMMAND_WORD = "tag-del-t";
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Delete a tag to a task from our task list. "
+ + "Parameters: "
+ + "INDEX (must be a positive integer) "
+ + "TAG NAME (must be non-empty)\n"
+ + "Example: " + COMMAND_WORD + " "
+ + "1 "
+ + "important";
+
+ public static final String MESSAGE_NO_SUCH_TAG_T = "This task does not have this tag!";
+ public static final String MESSAGE_DEL_TAG_SUCCESS = "Deleted tag: %1$s";
+
+ public final Index index;
+ public final String tagName;
+
+ /**
+ * Public contructor for AddTagToTaskCommand
+ * @param index Index of target task
+ * @param tagName Tag to be added to the target task
+ */
+ public DeleteTaskTagCommand(Index index, String tagName) {
+ requireAllNonNull(index, tagName);
+
+ this.index = index;
+ this.tagName = tagName;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredTaskList();
+
+ // Exception when index out of bounds
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+
+ Task taskToEdit = lastShownList.get(index.getZeroBased());
+ Task editedTask = deleteTagFromTask(taskToEdit);
+
+ // Exception when a non-existent tag is indicated
+ Tag testTag = new Tag(this.tagName);
+ if (!taskToEdit.getTags().contains(testTag)) {
+ throw new CommandException(MESSAGE_NO_SUCH_TAG_T);
+ }
+
+
+ model.setTask(taskToEdit, editedTask);
+ model.updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+ return new CommandResult(String.format(MESSAGE_DEL_TAG_SUCCESS, this.tagName));
+
+ }
+
+
+ /**
+ * Creates and returns a {@code Task} with a new tag {@code tagName} added to
+ * {@code taskToEdit}
+ *
+ * @param taskToEdit Person to be edited
+ * @return New Task object with the tag added (tag list updated)
+ */
+ private Task deleteTagFromTask(Task taskToEdit) throws CommandException {
+ // Keep all other fields the same
+ Name updatedName = taskToEdit.getName();
+ Date updatedDate = taskToEdit.getDate();
+ StartTime updatedStartTime = taskToEdit.getStartTime();
+ EndTime updatedEndTime = taskToEdit.getEndTime();
+ Set updatedPersons = taskToEdit.getPersons();
+
+ // Changing tags
+ // Make modifiable copy since Task#getTags returns an unmodifiable Set
+ Set tagList = new HashSet<>(taskToEdit.getTags());
+ try {
+ tagList.remove(new Tag(this.tagName));
+ } catch (Exception e) {
+ throw new CommandException(Messages.MESSAGE_INVALID_TAG);
+ }
+
+ return new Task(updatedName, updatedDate, updatedStartTime, updatedEndTime, tagList, updatedPersons);
+
+ }
+
+ @Override
+ public boolean equals(Object other) {
+
+ return other == this // short circuit if same object
+ || (other instanceof DeleteTaskTagCommand // instanceof handles nulls
+ && (index.equals(((DeleteTaskTagCommand) other).index)
+ && tagName.equals((((DeleteTaskTagCommand) other).tagName))));
+ }
+
+}
+
+
diff --git a/src/main/java/seedu/address/logic/commands/task/EditTaskCommand.java b/src/main/java/seedu/address/logic/commands/task/EditTaskCommand.java
new file mode 100644
index 00000000000..840bab35366
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/task/EditTaskCommand.java
@@ -0,0 +1,167 @@
+package seedu.address.logic.commands.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_CONTACT;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ENDTIME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_STARTTIME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_TASKS;
+
+import java.util.List;
+import java.util.Set;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.EditTaskDescriptor;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.name.Name;
+import seedu.address.model.person.Person;
+import seedu.address.model.tag.Tag;
+import seedu.address.model.task.Date;
+import seedu.address.model.task.EndTime;
+import seedu.address.model.task.StartTime;
+import seedu.address.model.task.Task;
+
+/**
+ * Edits the details of an existing person in the address book.
+ */
+public class EditTaskCommand extends Command {
+
+ public static final String COMMAND_WORD = "edit-t";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Edits the details of the person identified "
+ + "by the index number used in the displayed person list. "
+ + "Existing values will be overwritten by the input values.\n"
+ + "Parameters: INDEX (must be a positive integer) "
+ + "[" + PREFIX_NAME + "NAME] "
+ + "[" + PREFIX_DATE + "DATE] "
+ + "[" + PREFIX_STARTTIME + "START TIME] "
+ + "[" + PREFIX_ENDTIME + "END TIME] "
+ + "[" + PREFIX_TAG + "TAG]..."
+ + "[" + PREFIX_CONTACT + "PERSON]...\n"
+ + "Example: " + COMMAND_WORD + " 1 "
+ + PREFIX_DATE + "22-12-2022 "
+ + PREFIX_ENDTIME + "23:59";
+
+ public static final String MESSAGE_EDIT_TASK_SUCCESS = "Edited Task: %1$s";
+ public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided.";
+ public static final String MESSAGE_DUPLICATE_TASK = "This task already exists in the address book.";
+ public static final String MESSAGE_CONTACT_NOT_FOUND_IN_LIST =
+ "Unable to edit task as the person %1$s cannot be found in the current address book";
+ public static final String MESSAGE_SCHEDULE_CONFLICT =
+ "The person %1$s is already involved in a task at this date and time";
+ public static final String MESSAGE_SCHEDULE_CONFLICT_START_END_TIME =
+ "This task ends before or at its specified start time!";
+
+ private final Index index;
+ private final EditTaskDescriptor editTaskDescriptor;
+
+ /**
+ * @param index of the task in the filtered task list to edit
+ * @param editTaskDescriptor details to edit the task with
+ */
+ public EditTaskCommand(Index index, EditTaskDescriptor editTaskDescriptor) {
+ requireNonNull(index);
+ requireNonNull(editTaskDescriptor);
+
+ this.index = index;
+ this.editTaskDescriptor = new EditTaskDescriptor(editTaskDescriptor);
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownList = model.getFilteredTaskList();
+ List unfilteredPersonList = model.getUnfilteredPersonList();
+ List unfilteredTaskList = model.getUnfilteredTaskList();
+
+ if (index.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ Task taskToEdit = lastShownList.get(index.getZeroBased());
+ Task editedTask = createEditedTask(taskToEdit, editTaskDescriptor);
+
+ if (!taskToEdit.isSameTask(editedTask) && model.hasTask(editedTask)) {
+ throw new CommandException(MESSAGE_DUPLICATE_TASK);
+ }
+
+ if (editedTask.hasStartEndTimeConflict()) {
+ throw new CommandException(String.format(MESSAGE_SCHEDULE_CONFLICT_START_END_TIME));
+ }
+
+ Set originalPersons = taskToEdit.getPersons();
+ Set editedPersons = editedTask.getPersons();
+
+ for (Name name: editedPersons) {
+ boolean notFound = true;
+ for (Person person: unfilteredPersonList) {
+ if (person.getName().equals(name)) {
+ notFound = false;
+ }
+ }
+
+ if (!originalPersons.containsAll(editedPersons)) {
+ for (Name names : editedPersons) {
+ for (Task task : unfilteredTaskList) {
+ Set nameList = task.getPersons();
+ if (nameList.contains(names)) {
+ boolean conflictExist = task.hasDateTimeConflict(editedTask);
+ if (conflictExist) {
+ throw new CommandException(String.format(MESSAGE_SCHEDULE_CONFLICT, name));
+ }
+ }
+ }
+ }
+ }
+
+
+ if (notFound) {
+ throw new CommandException(String.format(MESSAGE_CONTACT_NOT_FOUND_IN_LIST, name));
+ }
+ }
+
+ model.setTask(taskToEdit, editedTask);
+ model.updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+ return new CommandResult(String.format(MESSAGE_EDIT_TASK_SUCCESS, editedTask));
+ }
+
+ /**
+ * Creates and returns a {@code Task} with the details of {@code taskToEdit}
+ * edited with {@code editTaskDescriptor}.
+ */
+ private static Task createEditedTask(Task taskToEdit, EditTaskDescriptor editTaskDescriptor) {
+ assert taskToEdit != null;
+
+ Name updatedName = editTaskDescriptor.getName().orElse(taskToEdit.getName());
+ Date updatedDate = editTaskDescriptor.getDate().orElse(taskToEdit.getDate());
+ StartTime updatedStartTime = editTaskDescriptor.getStartTime().orElse(taskToEdit.getStartTime());
+ EndTime updatedEndTime = editTaskDescriptor.getEndTime().orElse(taskToEdit.getEndTime());
+ Set updatedTags = editTaskDescriptor.getTags().orElse(taskToEdit.getTags());
+ Set updatedPersons = editTaskDescriptor.getPersons().orElse(taskToEdit.getPersons());
+ return new Task(updatedName, updatedDate, updatedStartTime, updatedEndTime, updatedTags, updatedPersons);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // short circuit if same object
+ if (other == this) {
+ return true;
+ }
+
+ // instanceof handles nulls
+ if (!(other instanceof EditTaskCommand)) {
+ return false;
+ }
+
+ // state check
+ EditTaskCommand e = (EditTaskCommand) other;
+ return index.equals(e.index)
+ && editTaskDescriptor.equals(e.editTaskDescriptor);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/task/FindTaskCommand.java b/src/main/java/seedu/address/logic/commands/task/FindTaskCommand.java
new file mode 100644
index 00000000000..b9e64890edb
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/task/FindTaskCommand.java
@@ -0,0 +1,58 @@
+package seedu.address.logic.commands.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.model.Model;
+import seedu.address.model.name.TaskNameContainsKeywordsPredicate;
+import seedu.address.model.tag.TaskTagContainsKeywordsPredicate;
+
+/**
+ * Finds and lists all tasks in task book whose name or tag contains any of the argument keywords.
+ * Keyword matching is case insensitive.
+ */
+public class FindTaskCommand extends Command {
+
+ public static final String COMMAND_WORD = "find-t";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Finds all tasks whose names or tags contain any of "
+ + "the specified keywords (case-insensitive) and displays them as a list with index numbers.\n"
+ + "Parameters: "
+ + "[" + PREFIX_NAME + "NAME]... "
+ + "[" + PREFIX_TAG + "TAG]...\n"
+ + "Example: " + COMMAND_WORD + " " + PREFIX_NAME + "Meeting " + PREFIX_NAME + "Dinner "
+ + PREFIX_TAG + "friends";
+
+ private final TaskNameContainsKeywordsPredicate namePredicate;
+ private final TaskTagContainsKeywordsPredicate tagPredicate;
+
+ /**
+ * Initialises new object using {@code namePredicate} and {@code tagPredicate}
+ */
+ public FindTaskCommand(TaskNameContainsKeywordsPredicate namePredicate,
+ TaskTagContainsKeywordsPredicate tagPredicate) {
+ this.namePredicate = namePredicate;
+ this.tagPredicate = tagPredicate;
+ }
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ model.updateFilteredTaskList(namePredicate.or(tagPredicate));
+ return new CommandResult(
+ String.format(Messages.MESSAGE_TASKS_LISTED_OVERVIEW, model.getFilteredTaskList().size()));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof FindTaskCommand // instanceof handles nulls
+ && namePredicate.equals(((FindTaskCommand) other).namePredicate)
+ && tagPredicate.equals(((FindTaskCommand) other).tagPredicate)); // state check
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/task/GetPersonCommand.java b/src/main/java/seedu/address/logic/commands/task/GetPersonCommand.java
new file mode 100644
index 00000000000..7abc06b878f
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/task/GetPersonCommand.java
@@ -0,0 +1,97 @@
+package seedu.address.logic.commands.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.core.Tabs.CONTACT_TAB;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
+
+import seedu.address.commons.core.Messages;
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.name.Name;
+import seedu.address.model.person.Person;
+import seedu.address.model.task.Task;
+
+/**
+ * Finds and lists all persons in address book whose name are in the specific task.
+ */
+public class GetPersonCommand extends Command {
+
+ public static final String COMMAND_WORD = "get-person";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Finds and lists all persons tagged to a specific task. "
+ + "The task is identified by the index number used in the TaskList.\n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 1";
+
+ private final Index targetIndex;
+
+ public GetPersonCommand(Index targetIndex) {
+ this.targetIndex = targetIndex;
+ }
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
+ List lastShownList = model.getFilteredTaskList();
+
+ if (targetIndex.getZeroBased() >= lastShownList.size()) {
+ throw new CommandException(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ Task indicatedTask = lastShownList.get(targetIndex.getZeroBased());
+ List keywords = new ArrayList<>();
+ for (Name name: indicatedTask.getPersons()) {
+ keywords.add(name.fullName);
+ }
+ CustomPersonNameContainsKeywordsPredicate predicate =
+ new CustomPersonNameContainsKeywordsPredicate(keywords);
+ model.updateFilteredPersonList(predicate);
+
+ return new CommandResult(
+ String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, model.getFilteredPersonList().size()),
+ false, false, CONTACT_TAB, false, null, false);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof GetPersonCommand // instanceof handles nulls
+ && targetIndex.equals(((GetPersonCommand) other).targetIndex)); // state check
+ }
+
+ /**
+ * Tests that a {@code Person}'s {@code Name} matches any of the keywords given.
+ * This class differs from {@code PersonNameContainsKeywordPredicate} as it takes in keywords that has
+ * more than one word
+ */
+ public static class CustomPersonNameContainsKeywordsPredicate implements Predicate {
+ private final List keywords;
+
+ public CustomPersonNameContainsKeywordsPredicate(List keywords) {
+ this.keywords = keywords;
+ }
+
+ @Override
+ public boolean test(Person person) {
+ return keywords.stream()
+ .anyMatch(keyword -> person.getName().fullName.equals(keyword));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof CustomPersonNameContainsKeywordsPredicate // instanceof handles nulls
+ && keywords.equals(((CustomPersonNameContainsKeywordsPredicate) other).keywords)); // state check
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/commands/task/ListTaskCommand.java b/src/main/java/seedu/address/logic/commands/task/ListTaskCommand.java
new file mode 100644
index 00000000000..eb8e6c4d5c7
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/task/ListTaskCommand.java
@@ -0,0 +1,26 @@
+package seedu.address.logic.commands.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.model.Model.PREDICATE_SHOW_ALL_TASKS;
+
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.model.Model;
+
+/**
+ * Lists all tasks in the task book to the user.
+ */
+public class ListTaskCommand extends Command {
+
+ public static final String COMMAND_WORD = "list-t";
+
+ public static final String MESSAGE_SUCCESS = "Listed all tasks";
+
+
+ @Override
+ public CommandResult execute(Model model) {
+ requireNonNull(model);
+ model.updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/task/SortTaskByDateCommand.java b/src/main/java/seedu/address/logic/commands/task/SortTaskByDateCommand.java
new file mode 100644
index 00000000000..f2cdbf6b3ad
--- /dev/null
+++ b/src/main/java/seedu/address/logic/commands/task/SortTaskByDateCommand.java
@@ -0,0 +1,61 @@
+package seedu.address.logic.commands.task;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.CommandResult;
+import seedu.address.logic.commands.task.exceptions.CommandException;
+import seedu.address.model.Model;
+import seedu.address.model.TaskBook;
+import seedu.address.model.task.Task;
+
+/**
+ * Deletes a task identified using its index from the TaskList.
+ */
+public class SortTaskByDateCommand extends Command {
+
+ public static final String COMMAND_WORD = "sort-date";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Sorts the task list by date, earlier dates first";
+
+ public static final String MESSAGE_SORT_TASKS_SUCCESS = "Sorted tasks by date";
+
+
+ @Override
+ public CommandResult execute(Model model) throws CommandException {
+ requireNonNull(model);
+ List lastShownTaskList = new ArrayList<>(model.getUnfilteredTaskList());
+ List listSortedByDate = new ArrayList<>(sortTaskListByDate(lastShownTaskList));
+ TaskBook newTaskBook = new TaskBook();
+
+ for (Task t : listSortedByDate) {
+ newTaskBook.addTask(t);
+ }
+ model.setTaskBook(newTaskBook);
+
+ return new CommandResult(String.format(MESSAGE_SORT_TASKS_SUCCESS));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof SortTaskByDateCommand); // instanceof handles nulls
+ }
+
+ /**
+ * Sorts a task list by date
+ *
+ * @param oldList List to be sorted
+ * @return List with tasks sorted by date
+ */
+ private List sortTaskListByDate(List oldList) {
+ Collections.sort(oldList, (t1, t2) -> t1.compareTo(t2));
+
+ return oldList;
+ }
+}
diff --git a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java b/src/main/java/seedu/address/logic/commands/task/exceptions/CommandException.java
similarity index 89%
rename from src/main/java/seedu/address/logic/commands/exceptions/CommandException.java
rename to src/main/java/seedu/address/logic/commands/task/exceptions/CommandException.java
index a16bd14f2cd..c54b72efb02 100644
--- a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java
+++ b/src/main/java/seedu/address/logic/commands/task/exceptions/CommandException.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.commands.exceptions;
+package seedu.address.logic.commands.task.exceptions;
/**
* Represents an error which occurs during execution of a {@link Command}.
diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java
deleted file mode 100644
index 1e466792b46..00000000000
--- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import seedu.address.logic.commands.AddCommand;
-import seedu.address.logic.commands.ClearCommand;
-import seedu.address.logic.commands.Command;
-import seedu.address.logic.commands.DeleteCommand;
-import seedu.address.logic.commands.EditCommand;
-import seedu.address.logic.commands.ExitCommand;
-import seedu.address.logic.commands.FindCommand;
-import seedu.address.logic.commands.HelpCommand;
-import seedu.address.logic.commands.ListCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-
-/**
- * Parses user input.
- */
-public class AddressBookParser {
-
- /**
- * Used for initial separation of command word and args.
- */
- private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)");
-
- /**
- * Parses user input into command for execution.
- *
- * @param userInput full user input string
- * @return the command based on the user input
- * @throws ParseException if the user input does not conform the expected format
- */
- public Command parseCommand(String userInput) throws ParseException {
- final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim());
- if (!matcher.matches()) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE));
- }
-
- final String commandWord = matcher.group("commandWord");
- final String arguments = matcher.group("arguments");
- switch (commandWord) {
-
- case AddCommand.COMMAND_WORD:
- return new AddCommandParser().parse(arguments);
-
- case EditCommand.COMMAND_WORD:
- return new EditCommandParser().parse(arguments);
-
- case DeleteCommand.COMMAND_WORD:
- return new DeleteCommandParser().parse(arguments);
-
- case ClearCommand.COMMAND_WORD:
- return new ClearCommand();
-
- case FindCommand.COMMAND_WORD:
- return new FindCommandParser().parse(arguments);
-
- case ListCommand.COMMAND_WORD:
- return new ListCommand();
-
- case ExitCommand.COMMAND_WORD:
- return new ExitCommand();
-
- case HelpCommand.COMMAND_WORD:
- return new HelpCommand();
-
- default:
- throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
- }
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java
index 75b1a9bf119..f2e5871315c 100644
--- a/src/main/java/seedu/address/logic/parser/CliSyntax.java
+++ b/src/main/java/seedu/address/logic/parser/CliSyntax.java
@@ -11,5 +11,10 @@ public class CliSyntax {
public static final Prefix PREFIX_EMAIL = new Prefix("e/");
public static final Prefix PREFIX_ADDRESS = new Prefix("a/");
public static final Prefix PREFIX_TAG = new Prefix("t/");
-
+ public static final Prefix PREFIX_CONTACT = new Prefix("c/");
+ public static final Prefix PREFIX_DATE = new Prefix("d/");
+ public static final Prefix PREFIX_STARTTIME = new Prefix("st/");
+ public static final Prefix PREFIX_ENDTIME = new Prefix("et/");
+ public static final Prefix PREFIX_XCOORD = new Prefix("x/");
+ public static final Prefix PREFIX_YCOORD = new Prefix("y/");
}
diff --git a/src/main/java/seedu/address/logic/parser/Coach2K22Parser.java b/src/main/java/seedu/address/logic/parser/Coach2K22Parser.java
new file mode 100644
index 00000000000..cf1342edd5d
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/Coach2K22Parser.java
@@ -0,0 +1,200 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.commons.core.Messages.MESSAGE_UNKNOWN_COMMAND;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import seedu.address.logic.commands.Command;
+import seedu.address.logic.commands.ExitCommand;
+import seedu.address.logic.commands.HelpCommand;
+import seedu.address.logic.commands.person.AddPersonCommand;
+import seedu.address.logic.commands.person.AddPersonTagCommand;
+import seedu.address.logic.commands.person.ClearPersonCommand;
+import seedu.address.logic.commands.person.DeletePersonCommand;
+import seedu.address.logic.commands.person.DeletePersonTagCommand;
+import seedu.address.logic.commands.person.EditPersonCommand;
+import seedu.address.logic.commands.person.FindPersonCommand;
+import seedu.address.logic.commands.person.ListPersonCommand;
+import seedu.address.logic.commands.person.SortStrengthCommand;
+import seedu.address.logic.commands.person.SortWeaknessCommand;
+import seedu.address.logic.commands.person.notecommands.AddMiscCommand;
+import seedu.address.logic.commands.person.notecommands.AddStrengthCommand;
+import seedu.address.logic.commands.person.notecommands.AddWeaknessCommand;
+import seedu.address.logic.commands.person.notecommands.DeleteMiscCommand;
+import seedu.address.logic.commands.person.notecommands.DeleteStrengthCommand;
+import seedu.address.logic.commands.person.notecommands.DeleteWeaknessCommand;
+import seedu.address.logic.commands.strategy.AddPlayerCommand;
+import seedu.address.logic.commands.strategy.DeletePlayerCommand;
+import seedu.address.logic.commands.strategy.ExportCommand;
+import seedu.address.logic.commands.strategy.LoadCourtCommand;
+import seedu.address.logic.commands.strategy.MovePlayerCommand;
+import seedu.address.logic.commands.task.AddTaskCommand;
+import seedu.address.logic.commands.task.AddTaskTagCommand;
+import seedu.address.logic.commands.task.ClearTaskCommand;
+import seedu.address.logic.commands.task.DeleteTaskCommand;
+import seedu.address.logic.commands.task.DeleteTaskTagCommand;
+import seedu.address.logic.commands.task.EditTaskCommand;
+import seedu.address.logic.commands.task.FindTaskCommand;
+import seedu.address.logic.commands.task.GetPersonCommand;
+import seedu.address.logic.commands.task.ListTaskCommand;
+import seedu.address.logic.commands.task.SortTaskByDateCommand;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.logic.parser.person.AddPersonCommandParser;
+import seedu.address.logic.parser.person.AddPersonTagCommandParser;
+import seedu.address.logic.parser.person.DeletePersonCommandParser;
+import seedu.address.logic.parser.person.DeletePersonTagCommandParser;
+import seedu.address.logic.parser.person.EditPersonCommandParser;
+import seedu.address.logic.parser.person.FindPersonCommandParser;
+import seedu.address.logic.parser.person.notecommands.AddMiscCommandParser;
+import seedu.address.logic.parser.person.notecommands.AddStrengthCommandParser;
+import seedu.address.logic.parser.person.notecommands.AddWeaknessCommandParser;
+import seedu.address.logic.parser.person.notecommands.DeleteMiscCommandParser;
+import seedu.address.logic.parser.person.notecommands.DeleteStrengthCommandParser;
+import seedu.address.logic.parser.person.notecommands.DeleteWeaknessCommandParser;
+import seedu.address.logic.parser.strategy.AddPlayerCommandParser;
+import seedu.address.logic.parser.strategy.DeletePlayerCommandParser;
+import seedu.address.logic.parser.strategy.LoadCourtCommandParser;
+import seedu.address.logic.parser.strategy.MovePlayerCommandParser;
+import seedu.address.logic.parser.task.AddTaskCommandParser;
+import seedu.address.logic.parser.task.AddTaskTagCommandParser;
+import seedu.address.logic.parser.task.ClearTaskCommandParser;
+import seedu.address.logic.parser.task.DeleteTaskCommandParser;
+import seedu.address.logic.parser.task.DeleteTaskTagCommandParser;
+import seedu.address.logic.parser.task.EditTaskCommandParser;
+import seedu.address.logic.parser.task.FindTaskCommandParser;
+import seedu.address.logic.parser.task.GetPersonCommandParser;
+
+/**
+ * Parses user input.
+ */
+public class Coach2K22Parser {
+
+ /**
+ * Used for initial separation of command word and args.
+ */
+ private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?\\S+)(?.*)");
+
+ /**
+ * Parses user input into command for execution.
+ *
+ * @param userInput full user input string
+ * @return the command based on the user input
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public Command parseCommand(String userInput) throws ParseException {
+ final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim());
+ if (!matcher.matches()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE));
+ }
+
+ final String commandWord = matcher.group("commandWord");
+ final String arguments = matcher.group("arguments");
+ switch (commandWord) {
+
+ case AddPersonCommand.COMMAND_WORD:
+ return new AddPersonCommandParser().parse(arguments);
+
+ case AddTaskCommand.COMMAND_WORD:
+ return new AddTaskCommandParser().parse(arguments);
+
+ case EditPersonCommand.COMMAND_WORD:
+ return new EditPersonCommandParser().parse(arguments);
+
+ case EditTaskCommand.COMMAND_WORD:
+ return new EditTaskCommandParser().parse(arguments);
+
+ case DeletePersonCommand.COMMAND_WORD:
+ return new DeletePersonCommandParser().parse(arguments);
+
+ case DeleteTaskCommand.COMMAND_WORD:
+ return new DeleteTaskCommandParser().parse(arguments);
+
+ case ClearPersonCommand.COMMAND_WORD:
+ return new ClearPersonCommand();
+
+ case ClearTaskCommand.COMMAND_WORD:
+ return new ClearTaskCommandParser().parse(arguments);
+
+ case FindPersonCommand.COMMAND_WORD:
+ return new FindPersonCommandParser().parse(arguments);
+
+ case FindTaskCommand.COMMAND_WORD:
+ return new FindTaskCommandParser().parse(arguments);
+
+ case GetPersonCommand.COMMAND_WORD:
+ return new GetPersonCommandParser().parse(arguments);
+
+ case ListPersonCommand.COMMAND_WORD:
+ return new ListPersonCommand();
+
+ case ListTaskCommand.COMMAND_WORD:
+ return new ListTaskCommand();
+
+ case SortStrengthCommand.COMMAND_WORD:
+ return new SortStrengthCommand();
+
+ case SortWeaknessCommand.COMMAND_WORD:
+ return new SortWeaknessCommand();
+
+ case AddStrengthCommand.COMMAND_WORD:
+ return new AddStrengthCommandParser().parse(arguments);
+
+ case AddWeaknessCommand.COMMAND_WORD:
+ return new AddWeaknessCommandParser().parse(arguments);
+
+ case AddMiscCommand.COMMAND_WORD:
+ return new AddMiscCommandParser().parse(arguments);
+
+ case DeleteStrengthCommand.COMMAND_WORD:
+ return new DeleteStrengthCommandParser().parse(arguments);
+
+ case DeleteWeaknessCommand.COMMAND_WORD:
+ return new DeleteWeaknessCommandParser().parse(arguments);
+
+ case DeleteMiscCommand.COMMAND_WORD:
+ return new DeleteMiscCommandParser().parse(arguments);
+
+ case ExitCommand.COMMAND_WORD:
+ return new ExitCommand();
+
+ case HelpCommand.COMMAND_WORD:
+ return new HelpCommand();
+
+ case AddPersonTagCommand.COMMAND_WORD:
+ return new AddPersonTagCommandParser().parse(arguments);
+
+ case DeletePersonTagCommand.COMMAND_WORD:
+ return new DeletePersonTagCommandParser().parse(arguments);
+
+ case AddPlayerCommand.COMMAND_WORD:
+ return new AddPlayerCommandParser().parse(arguments);
+
+ case DeletePlayerCommand.COMMAND_WORD:
+ return new DeletePlayerCommandParser().parse(arguments);
+
+ case LoadCourtCommand.COMMAND_WORD:
+ return new LoadCourtCommandParser().parse(arguments);
+
+ case AddTaskTagCommand.COMMAND_WORD:
+ return new AddTaskTagCommandParser().parse(arguments);
+
+ case DeleteTaskTagCommand.COMMAND_WORD:
+ return new DeleteTaskTagCommandParser().parse(arguments);
+
+ case MovePlayerCommand.COMMAND_WORD:
+ return new MovePlayerCommandParser().parse(arguments);
+
+ case SortTaskByDateCommand.COMMAND_WORD:
+ return new SortTaskByDateCommand();
+
+ case ExportCommand.COMMAND_WORD:
+ return new ExportCommand();
+
+ default:
+ throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java
deleted file mode 100644
index 4fb71f23103..00000000000
--- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package seedu.address.logic.parser;
-
-import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
-
-import java.util.Arrays;
-
-import seedu.address.logic.commands.FindCommand;
-import seedu.address.logic.parser.exceptions.ParseException;
-import seedu.address.model.person.NameContainsKeywordsPredicate;
-
-/**
- * Parses input arguments and creates a new FindCommand object
- */
-public class FindCommandParser implements Parser {
-
- /**
- * Parses the given {@code String} of arguments in the context of the FindCommand
- * and returns a FindCommand object for execution.
- * @throws ParseException if the user input does not conform the expected format
- */
- public FindCommand parse(String args) throws ParseException {
- String trimmedArgs = args.trim();
- if (trimmedArgs.isEmpty()) {
- throw new ParseException(
- String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE));
- }
-
- String[] nameKeywords = trimmedArgs.split("\\s+");
-
- return new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList(nameKeywords)));
- }
-
-}
diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java
index b117acb9c55..ca56e2cf99d 100644
--- a/src/main/java/seedu/address/logic/parser/ParserUtil.java
+++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java
@@ -2,6 +2,7 @@
import static java.util.Objects.requireNonNull;
+import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
@@ -9,11 +10,17 @@
import seedu.address.commons.core.index.Index;
import seedu.address.commons.util.StringUtil;
import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.image.Image;
+import seedu.address.model.name.Name;
+import seedu.address.model.note.Note;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
import seedu.address.model.person.Phone;
+import seedu.address.model.strategy.Player;
import seedu.address.model.tag.Tag;
+import seedu.address.model.task.Date;
+import seedu.address.model.task.EndTime;
+import seedu.address.model.task.StartTime;
/**
* Contains utility methods used for parsing strings in the various *Parser classes.
@@ -22,6 +29,15 @@ public class ParserUtil {
public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer.";
+ public static final String MESSAGE_INVALID_NOTE_INDEX = "Note index is not a non-zero unsigned integer.";
+
+ public static final String MESSAGE_INVALID_IMAGE = "Image does not exit.";
+
+ public static final String MESSAGE_INVALID_IMAGE_NAME = "Image should not contain \'/\' characters.";
+
+ public static final String MESSAGE_DIRECTORY_NOT_EXIST = "The " + Image.FILE_PATH + " directory does not exist!";
+
+ public static final String MESSAGE_INVALID_KEYWORD = "Keywords should be alphanumeric and should not be blank.";
/**
* Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be
* trimmed.
@@ -35,6 +51,40 @@ public static Index parseIndex(String oneBasedIndex) throws ParseException {
return Index.fromOneBased(Integer.parseInt(trimmedIndex));
}
+ /**
+ * Parses {@code imageName} into a {@code Image} and returns it. Leading and trailing whitespaces will be
+ * trimmed.
+ * @throws ParseException if the specified imageName is invalid.
+ */
+ public static Image parseImage(String imageName) throws ParseException {
+ requireNonNull(imageName);
+ String trimmedName = imageName.trim();
+ File folder = new File(Image.FILE_PATH);
+ if (!folder.exists()) {
+ throw new ParseException(MESSAGE_DIRECTORY_NOT_EXIST);
+ }
+ if (trimmedName.contains("/")) {
+ throw new ParseException(MESSAGE_INVALID_IMAGE_NAME);
+ }
+ if (!Image.isValidFile(trimmedName)) {
+ throw new ParseException(MESSAGE_INVALID_IMAGE);
+ }
+ return new Image(trimmedName);
+ }
+
+ /**
+ * Parses {@code oneBasedNoteIndex} into an {@code NoteIndex} and returns it. Leading and trailing whitespaces
+ * will be trimmed.
+ * @throws ParseException if the specified index is invalid (not non-zero unsigned integer).
+ */
+ public static Index parseNoteIndex(String oneBasedNoteIndex) throws ParseException {
+ String trimmedNoteIndex = oneBasedNoteIndex.trim();
+ if (!StringUtil.isNonZeroUnsignedInteger(trimmedNoteIndex)) {
+ throw new ParseException(MESSAGE_INVALID_NOTE_INDEX);
+ }
+ return Index.fromOneBased(Integer.parseInt(trimmedNoteIndex));
+ }
+
/**
* Parses a {@code String name} into a {@code Name}.
* Leading and trailing whitespaces will be trimmed.
@@ -50,6 +100,36 @@ public static Name parseName(String name) throws ParseException {
return new Name(trimmedName);
}
+ /**
+ * Parses a {@code String nameKeyword} into a {@code Name}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code nameKeyword} is invalid or contain spaces.
+ */
+ public static Name parseNameKeyword(String nameKeyword) throws ParseException {
+ requireNonNull(nameKeyword);
+ String trimmedName = nameKeyword.trim();
+ if (!Name.isValidName(trimmedName) || trimmedName.split("\\s+").length != 1) {
+ throw new ParseException(MESSAGE_INVALID_KEYWORD);
+ }
+ return new Name(trimmedName);
+ }
+
+ /**
+ * Parses {@code Collection names} into a {@code Set}.
+ */
+ public static Set parseNames(Collection names) throws ParseException {
+ requireNonNull(names);
+ final Set nameSet = new HashSet<>();
+ for (String name : names) {
+ String trimmedName = name.trim();
+ if (!Name.isValidName(trimmedName)) {
+ throw new ParseException(Name.MESSAGE_CONSTRAINTS);
+ }
+ nameSet.add(new Name(name));
+ }
+ return nameSet;
+ }
/**
* Parses a {@code String phone} into a {@code Phone}.
* Leading and trailing whitespaces will be trimmed.
@@ -95,6 +175,51 @@ public static Email parseEmail(String email) throws ParseException {
return new Email(trimmedEmail);
}
+ /**
+ * Parses a {@code String date} into an {@code Date}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code date} is invalid.
+ */
+ public static Date parseDate(String date) throws ParseException {
+ requireNonNull(date);
+ String trimmedDate = date.trim();
+ if (!Date.isValidDate(trimmedDate)) {
+ throw new ParseException(Date.MESSAGE_CONSTRAINTS);
+ }
+ return new Date(trimmedDate);
+ }
+
+ /**
+ * Parses a {@code String startTime} into an {@code StartTime}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code startTime} is invalid.
+ */
+ public static StartTime parseStartTime(String startTime) throws ParseException {
+ requireNonNull(startTime);
+ String trimmedStartTime = startTime.trim();
+ if (!StartTime.isValidStartTime(trimmedStartTime)) {
+ throw new ParseException(StartTime.MESSAGE_CONSTRAINTS);
+ }
+ return new StartTime(trimmedStartTime);
+ }
+
+ /**
+ * Parses a {@code String endTime} into an {@code EndTime}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code endTime} is invalid.
+ */
+ public static EndTime parseEndTime(String endTime) throws ParseException {
+ requireNonNull(endTime);
+ String trimmedEndTime = endTime.trim();
+ if (!EndTime.isValidEndTime(trimmedEndTime)) {
+ throw new ParseException(EndTime.MESSAGE_CONSTRAINTS);
+ }
+ return new EndTime(trimmedEndTime);
+ }
+
/**
* Parses a {@code String tag} into a {@code Tag}.
* Leading and trailing whitespaces will be trimmed.
@@ -110,6 +235,21 @@ public static Tag parseTag(String tag) throws ParseException {
return new Tag(trimmedTag);
}
+ /**
+ * Parses a {@code String tagKeyword} into a {@code Tag}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code tagKeyword} is invalid.
+ */
+ public static Tag parseTagKeyword(String tagKeyword) throws ParseException {
+ requireNonNull(tagKeyword);
+ String trimmedTag = tagKeyword.trim();
+ if (!Tag.isValidTagName(trimmedTag) || trimmedTag.split("\\s+").length != 1) {
+ throw new ParseException(MESSAGE_INVALID_KEYWORD);
+ }
+ return new Tag(trimmedTag);
+ }
+
/**
* Parses {@code Collection tags} into a {@code Set}.
*/
@@ -121,4 +261,34 @@ public static Set parseTags(Collection tags) throws ParseException
}
return tagSet;
}
+
+ /**
+ * Parses a {@code String note} into a {@code Note}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code note} is invalid.
+ */
+ public static Note parseNote(String note) throws ParseException {
+ requireNonNull(note);
+ String trimmedNote = note.trim();
+ if (!Note.isValidNote(trimmedNote)) {
+ throw new ParseException(Note.MESSAGE_CONSTRAINTS);
+ }
+ return new Note(trimmedNote);
+ }
+
+ /**
+ * Parses a {@code String playerName} into a {@code Player}.
+ * Leading and trailing whitespaces will be trimmed.
+ *
+ * @throws ParseException if the given {@code playerName} is invalid.
+ */
+ public static Player paresPlayer(String playerName) throws ParseException {
+ requireNonNull(playerName);
+ String trimmedPlayerName = playerName.trim();
+ if (!Player.isValidPlayer(trimmedPlayerName)) {
+ throw new ParseException(Player.MESSAGE_NAME_CONSTRAINTS);
+ }
+ return new Player(trimmedPlayerName);
+ }
}
diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/person/AddPersonCommandParser.java
similarity index 71%
rename from src/main/java/seedu/address/logic/parser/AddCommandParser.java
rename to src/main/java/seedu/address/logic/parser/person/AddPersonCommandParser.java
index 3b8bfa035e8..fea09d9af54 100644
--- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/person/AddPersonCommandParser.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.address.logic.parser.person;
import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS;
@@ -7,14 +7,22 @@
import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
-import seedu.address.logic.commands.AddCommand;
+import seedu.address.logic.commands.person.AddPersonCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.Prefix;
import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.name.Name;
+import seedu.address.model.note.Note;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
-import seedu.address.model.person.Name;
import seedu.address.model.person.Person;
import seedu.address.model.person.Phone;
import seedu.address.model.tag.Tag;
@@ -22,20 +30,20 @@
/**
* Parses input arguments and creates a new AddCommand object
*/
-public class AddCommandParser implements Parser {
+public class AddPersonCommandParser implements Parser {
/**
* Parses the given {@code String} of arguments in the context of the AddCommand
* and returns an AddCommand object for execution.
* @throws ParseException if the user input does not conform the expected format
*/
- public AddCommand parse(String args) throws ParseException {
+ public AddPersonCommand parse(String args) throws ParseException {
ArgumentMultimap argMultimap =
ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG);
if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL)
|| !argMultimap.getPreamble().isEmpty()) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE));
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddPersonCommand.MESSAGE_USAGE));
}
Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get());
@@ -43,10 +51,13 @@ public AddCommand parse(String args) throws ParseException {
Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get());
Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get());
Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG));
+ List strengthList = new ArrayList<>();
+ List weaknessList = new ArrayList<>();
+ List miscList = new ArrayList<>();
- Person person = new Person(name, phone, email, address, tagList);
+ Person person = new Person(name, phone, email, address, tagList, strengthList, weaknessList, miscList);
- return new AddCommand(person);
+ return new AddPersonCommand(person);
}
/**
diff --git a/src/main/java/seedu/address/logic/parser/person/AddPersonTagCommandParser.java b/src/main/java/seedu/address/logic/parser/person/AddPersonTagCommandParser.java
new file mode 100644
index 00000000000..d1880a53aa6
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/person/AddPersonTagCommandParser.java
@@ -0,0 +1,73 @@
+package seedu.address.logic.parser.person;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import java.util.ArrayList;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.person.AddPersonTagCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.Prefix;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.tag.Tag;
+
+public class AddPersonTagCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the
+ * {@code AddTagCommand}
+ * and returns a {@code AddTagCommand} object for execution
+ * * @param args Input string by user EXCEPT COMMAND WORD
+ *
+ * @return DeleteTagCommand object with arguments loaded in
+ * @throws ParseException If the user input does not conform to the expected
+ * format
+ */
+ public AddPersonTagCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+
+ // Tokenize all arguments
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, new Prefix(""));
+
+ // Convert the argMultimap into an ArrayList<> for easier access
+ // The @ArgumentTokenizer produces a map with 3 elements:
+ // Element 1: Whitespace
+ // Element 2: Index
+ // Element 3: tagName string
+ ArrayList values = new ArrayList<>(argMultimap.getAllValues(new Prefix("")));
+
+ // Get the index element in the ArrayList
+ int indexInt;
+ try {
+ indexInt = Integer.parseInt(values.get(1));
+ } catch (Exception e) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddPersonTagCommand.MESSAGE_USAGE));
+
+ }
+
+ // Checking if index is a positive integer
+ if (!(indexInt >= 1)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddPersonTagCommand.MESSAGE_USAGE));
+ }
+ Index index = Index.fromOneBased(indexInt); // Convert to fromOneBased index since contact list starts from 1
+
+ // Get the tagName element in the ArrayList
+ String tagName;
+ try {
+ tagName = values.get(2);
+ } catch (IndexOutOfBoundsException e) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddPersonTagCommand.MESSAGE_USAGE));
+ }
+ try {
+ new Tag(tagName);
+ } catch (Exception e) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ AddPersonTagCommand.MESSAGE_USAGE));
+ }
+
+ return new AddPersonTagCommand(index, tagName);
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java b/src/main/java/seedu/address/logic/parser/person/DeletePersonCommandParser.java
similarity index 62%
rename from src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
rename to src/main/java/seedu/address/logic/parser/person/DeletePersonCommandParser.java
index 522b93081cc..87b2427b15d 100644
--- a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/person/DeletePersonCommandParser.java
@@ -1,28 +1,30 @@
-package seedu.address.logic.parser;
+package seedu.address.logic.parser.person;
import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.DeleteCommand;
+import seedu.address.logic.commands.person.DeletePersonCommand;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
import seedu.address.logic.parser.exceptions.ParseException;
/**
* Parses input arguments and creates a new DeleteCommand object
*/
-public class DeleteCommandParser implements Parser {
+public class DeletePersonCommandParser implements Parser {
/**
* Parses the given {@code String} of arguments in the context of the DeleteCommand
* and returns a DeleteCommand object for execution.
* @throws ParseException if the user input does not conform the expected format
*/
- public DeleteCommand parse(String args) throws ParseException {
+ public DeletePersonCommand parse(String args) throws ParseException {
try {
Index index = ParserUtil.parseIndex(args);
- return new DeleteCommand(index);
+ return new DeletePersonCommand(index);
} catch (ParseException pe) {
throw new ParseException(
- String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE), pe);
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeletePersonCommand.MESSAGE_USAGE), pe);
}
}
diff --git a/src/main/java/seedu/address/logic/parser/person/DeletePersonTagCommandParser.java b/src/main/java/seedu/address/logic/parser/person/DeletePersonTagCommandParser.java
new file mode 100644
index 00000000000..3c1ca3298ab
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/person/DeletePersonTagCommandParser.java
@@ -0,0 +1,75 @@
+package seedu.address.logic.parser.person;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import java.util.ArrayList;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.person.AddPersonTagCommand;
+import seedu.address.logic.commands.person.DeletePersonTagCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.Prefix;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.tag.Tag;
+
+public class DeletePersonTagCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the
+ * {@code DeleteTagCommand}
+ * and returns a {@code DeleteTagCommand} object for execution
+ * * @param args Input string by user EXCEPT COMMAND WORD
+ *
+ * @return DeleteTagCommand object with arguments loaded in
+ * @throws ParseException If the user input does not conform to the expected
+ * format
+ */
+ public DeletePersonTagCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+
+ // Tokenize all arguments
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, new Prefix(""));
+
+ // Convert the argMultimap into an ArrayList<> for easier access
+ // The @ArgumentTokenizer produces a map with 3 elements:
+ // Element 1: Whitespace
+ // Element 2: Index
+ // Element 3: tagName string
+ ArrayList values = new ArrayList<>(argMultimap.getAllValues(new Prefix("")));
+
+ // Get the index element in the ArrayList
+ int indexInt;
+ try {
+ indexInt = Integer.parseInt(values.get(1));
+ } catch (Exception e) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ DeletePersonTagCommand.MESSAGE_USAGE));
+ }
+ // Checking if index is a positive integer
+ if (!(indexInt >= 1)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddPersonTagCommand.MESSAGE_USAGE));
+ }
+
+ Index index = Index.fromOneBased(indexInt); // Convert to fromOneBased index since contact list starts from 1
+
+ // Get the tagName element in the ArrayList
+ String tagName;
+ try {
+ tagName = values.get(2);
+ } catch (IndexOutOfBoundsException e) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ DeletePersonTagCommand.MESSAGE_USAGE));
+ }
+ try {
+ new Tag(tagName);
+ } catch (Exception e) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ DeletePersonTagCommand.MESSAGE_USAGE));
+ }
+
+ return new DeletePersonTagCommand(index, tagName);
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/seedu/address/logic/parser/person/EditPersonCommandParser.java
similarity index 81%
rename from src/main/java/seedu/address/logic/parser/EditCommandParser.java
rename to src/main/java/seedu/address/logic/parser/person/EditPersonCommandParser.java
index 845644b7dea..605028c5d4c 100644
--- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java
+++ b/src/main/java/seedu/address/logic/parser/person/EditPersonCommandParser.java
@@ -1,4 +1,4 @@
-package seedu.address.logic.parser;
+package seedu.address.logic.parser.person;
import static java.util.Objects.requireNonNull;
import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
@@ -14,22 +14,26 @@
import java.util.Set;
import seedu.address.commons.core.index.Index;
-import seedu.address.logic.commands.EditCommand;
-import seedu.address.logic.commands.EditCommand.EditPersonDescriptor;
+import seedu.address.logic.EditPersonDescriptor;
+import seedu.address.logic.commands.person.EditPersonCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.tag.Tag;
/**
* Parses input arguments and creates a new EditCommand object
*/
-public class EditCommandParser implements Parser {
+public class EditPersonCommandParser implements Parser {
/**
* Parses the given {@code String} of arguments in the context of the EditCommand
* and returns an EditCommand object for execution.
* @throws ParseException if the user input does not conform the expected format
*/
- public EditCommand parse(String args) throws ParseException {
+ public EditPersonCommand parse(String args) throws ParseException {
requireNonNull(args);
ArgumentMultimap argMultimap =
ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG);
@@ -39,7 +43,8 @@ public EditCommand parse(String args) throws ParseException {
try {
index = ParserUtil.parseIndex(argMultimap.getPreamble());
} catch (ParseException pe) {
- throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE), pe);
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ EditPersonCommand.MESSAGE_USAGE), pe);
}
EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor();
@@ -58,10 +63,10 @@ public EditCommand parse(String args) throws ParseException {
parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags);
if (!editPersonDescriptor.isAnyFieldEdited()) {
- throw new ParseException(EditCommand.MESSAGE_NOT_EDITED);
+ throw new ParseException(EditPersonCommand.MESSAGE_NOT_EDITED);
}
- return new EditCommand(index, editPersonDescriptor);
+ return new EditPersonCommand(index, editPersonDescriptor);
}
/**
diff --git a/src/main/java/seedu/address/logic/parser/person/FindPersonCommandParser.java b/src/main/java/seedu/address/logic/parser/person/FindPersonCommandParser.java
new file mode 100644
index 00000000000..c2e4650854f
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/person/FindPersonCommandParser.java
@@ -0,0 +1,65 @@
+package seedu.address.logic.parser.person;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import seedu.address.logic.commands.person.FindPersonCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.Prefix;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.name.PersonNameContainsKeywordsPredicate;
+import seedu.address.model.tag.PersonTagContainsKeywordsPredicate;
+
+/**
+ * Parses input arguments and creates a new FindCommand object
+ */
+public class FindPersonCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the FindCommand
+ * and returns a FindCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public FindPersonCommand parse(String args) throws ParseException {
+ String trimmedArgs = args.trim();
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_TAG);
+
+ if ((!arePrefixesPresent(argMultimap, PREFIX_NAME) && !arePrefixesPresent(argMultimap, PREFIX_TAG))
+ || trimmedArgs.isEmpty()) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindPersonCommand.MESSAGE_USAGE));
+ }
+
+ List nameKeywords = argMultimap.getAllValues(PREFIX_NAME);
+ List tagKeywords = argMultimap.getAllValues(PREFIX_TAG);
+
+ // checks if names are valid
+ for (String name: nameKeywords) {
+ ParserUtil.parseNameKeyword(name);
+ }
+
+ // check if tags are valid
+ for (String tag: tagKeywords) {
+ ParserUtil.parseTagKeyword(tag);
+ }
+
+ return new FindPersonCommand(new PersonNameContainsKeywordsPredicate(nameKeywords),
+ new PersonTagContainsKeywordsPredicate(tagKeywords));
+ }
+
+ /**
+ * Returns true if none of the prefixes contains empty {@code Optional} values in the given
+ * {@code ArgumentMultimap}.
+ */
+ private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/person/notecommands/AddMiscCommandParser.java b/src/main/java/seedu/address/logic/parser/person/notecommands/AddMiscCommandParser.java
new file mode 100644
index 00000000000..457ed2292cf
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/person/notecommands/AddMiscCommandParser.java
@@ -0,0 +1,32 @@
+package seedu.address.logic.parser.person.notecommands;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.person.notecommands.AddMiscCommand;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.note.Note;
+
+/**
+ * Parses input arguments and creates a new {@code AddMiscCommand} object
+ */
+public class AddMiscCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the {@code AddMiscCommand}
+ * and returns a {@code AddMiscCommand} object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public AddMiscCommand parse(String args) throws ParseException {
+ try {
+ String[] splitArgs = args.trim().split("\\s+", 2);
+ Index index = ParserUtil.parseIndex(splitArgs[0]);
+ Note note = ParserUtil.parseNote(splitArgs[1]);
+ return new AddMiscCommand(index, note);
+ } catch (ParseException | IndexOutOfBoundsException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddMiscCommand.MESSAGE_USAGE), pe);
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/person/notecommands/AddStrengthCommandParser.java b/src/main/java/seedu/address/logic/parser/person/notecommands/AddStrengthCommandParser.java
new file mode 100644
index 00000000000..fdf889f84f1
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/person/notecommands/AddStrengthCommandParser.java
@@ -0,0 +1,32 @@
+package seedu.address.logic.parser.person.notecommands;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.person.notecommands.AddStrengthCommand;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.note.Note;
+
+/**
+ * Parses input arguments and creates a new {@code AddStrengthCommand} object
+ */
+public class AddStrengthCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the {@code AddStrengthCommand}
+ * and returns a {@code AddStrengthCommand} object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public AddStrengthCommand parse(String args) throws ParseException {
+ try {
+ String[] splitArgs = args.trim().split("\\s+", 2);
+ Index index = ParserUtil.parseIndex(splitArgs[0]);
+ Note note = ParserUtil.parseNote(splitArgs[1]);
+ return new AddStrengthCommand(index, note);
+ } catch (ParseException | IndexOutOfBoundsException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddStrengthCommand.MESSAGE_USAGE), pe);
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/person/notecommands/AddWeaknessCommandParser.java b/src/main/java/seedu/address/logic/parser/person/notecommands/AddWeaknessCommandParser.java
new file mode 100644
index 00000000000..e6bdc803709
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/person/notecommands/AddWeaknessCommandParser.java
@@ -0,0 +1,32 @@
+package seedu.address.logic.parser.person.notecommands;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.person.notecommands.AddWeaknessCommand;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.note.Note;
+
+/**
+ * Parses input arguments and creates a new {@code AddWeaknessCommand} object
+ */
+public class AddWeaknessCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the {@code AddWeaknessCommand}
+ * and returns a {@code AddWeaknessCommand} object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public AddWeaknessCommand parse(String args) throws ParseException {
+ try {
+ String[] splitArgs = args.trim().split("\\s+", 2);
+ Index index = ParserUtil.parseIndex(splitArgs[0]);
+ Note note = ParserUtil.parseNote(splitArgs[1]);
+ return new AddWeaknessCommand(index, note);
+ } catch (ParseException | IndexOutOfBoundsException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddWeaknessCommand.MESSAGE_USAGE), pe);
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/person/notecommands/DeleteMiscCommandParser.java b/src/main/java/seedu/address/logic/parser/person/notecommands/DeleteMiscCommandParser.java
new file mode 100644
index 00000000000..f8ea98c3044
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/person/notecommands/DeleteMiscCommandParser.java
@@ -0,0 +1,32 @@
+package seedu.address.logic.parser.person.notecommands;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.person.notecommands.DeleteMiscCommand;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new {@code DeleteMiscCommand} object
+ */
+public class DeleteMiscCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the {@code DeleteMiscCommand}
+ * and returns a {@code DeleteMiscCommand} object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ @Override
+ public DeleteMiscCommand parse(String args) throws ParseException {
+ try {
+ String[] splitArgs = args.trim().split("\\s+", 2);
+ Index index = ParserUtil.parseIndex(splitArgs[0]);
+ Index noteIndex = ParserUtil.parseNoteIndex(splitArgs[1]);
+ return new DeleteMiscCommand(index, noteIndex);
+ } catch (ParseException | IndexOutOfBoundsException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteMiscCommand.MESSAGE_USAGE), pe);
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/person/notecommands/DeleteStrengthCommandParser.java b/src/main/java/seedu/address/logic/parser/person/notecommands/DeleteStrengthCommandParser.java
new file mode 100644
index 00000000000..96131d360e8
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/person/notecommands/DeleteStrengthCommandParser.java
@@ -0,0 +1,32 @@
+package seedu.address.logic.parser.person.notecommands;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.person.notecommands.DeleteStrengthCommand;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new {@code DeleteStrengthCommand} object
+ */
+public class DeleteStrengthCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the {@code DeleteStrengthCommand}
+ * and returns a {@code DeleteStrengthCommand} object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ @Override
+ public DeleteStrengthCommand parse(String args) throws ParseException {
+ try {
+ String[] splitArgs = args.trim().split("\\s+", 2);
+ Index index = ParserUtil.parseIndex(splitArgs[0]);
+ Index noteIndex = ParserUtil.parseNoteIndex(splitArgs[1]);
+ return new DeleteStrengthCommand(index, noteIndex);
+ } catch (ParseException | IndexOutOfBoundsException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteStrengthCommand.MESSAGE_USAGE), pe);
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/person/notecommands/DeleteWeaknessCommandParser.java b/src/main/java/seedu/address/logic/parser/person/notecommands/DeleteWeaknessCommandParser.java
new file mode 100644
index 00000000000..85b77926d55
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/person/notecommands/DeleteWeaknessCommandParser.java
@@ -0,0 +1,32 @@
+package seedu.address.logic.parser.person.notecommands;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.person.notecommands.DeleteWeaknessCommand;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new {@code DeleteWeaknessCommand} object
+ */
+public class DeleteWeaknessCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the {@code DeleteWeaknessCommand}
+ * and returns a {@code DeleteWeaknessCommand} object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ @Override
+ public DeleteWeaknessCommand parse(String args) throws ParseException {
+ try {
+ String[] splitArgs = args.trim().split("\\s+", 2);
+ Index index = ParserUtil.parseIndex(splitArgs[0]);
+ Index noteIndex = ParserUtil.parseNoteIndex(splitArgs[1]);
+ return new DeleteWeaknessCommand(index, noteIndex);
+ } catch (ParseException | IndexOutOfBoundsException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteWeaknessCommand.MESSAGE_USAGE), pe);
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/strategy/AddPlayerCommandParser.java b/src/main/java/seedu/address/logic/parser/strategy/AddPlayerCommandParser.java
new file mode 100644
index 00000000000..88b214a59d6
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/strategy/AddPlayerCommandParser.java
@@ -0,0 +1,31 @@
+package seedu.address.logic.parser.strategy;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.address.logic.commands.strategy.AddPlayerCommand;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.strategy.Player;
+
+/**
+ * Parses input arguments and creates a new AddPlayerCommand object
+ */
+
+public class AddPlayerCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the {@code AddPlayerCommand}
+ * and returns an {@code AddPlayerCommand} object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public AddPlayerCommand parse(String args) throws ParseException {
+ try {
+ String[] splitArgs = args.trim().split("\\s+", 1);
+ Player player = ParserUtil.paresPlayer(splitArgs[0]);
+ return new AddPlayerCommand(player);
+ } catch (IndexOutOfBoundsException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddPlayerCommand.MESSAGE_USAGE), pe);
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/strategy/DeletePlayerCommandParser.java b/src/main/java/seedu/address/logic/parser/strategy/DeletePlayerCommandParser.java
new file mode 100644
index 00000000000..a3748c29871
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/strategy/DeletePlayerCommandParser.java
@@ -0,0 +1,28 @@
+package seedu.address.logic.parser.strategy;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.address.logic.commands.strategy.DeletePlayerCommand;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new DeletePlayerCommand object
+ */
+
+public class DeletePlayerCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the {@code DeletePlayerCommand}
+ * and returns an {@code DELETEPlayerCommand} object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public DeletePlayerCommand parse(String args) throws ParseException {
+ try {
+ String[] splitArgs = args.trim().split("\\s+", 1);
+ return new DeletePlayerCommand(splitArgs[0]);
+ } catch (IndexOutOfBoundsException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeletePlayerCommand.MESSAGE_USAGE), pe);
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/strategy/LoadCourtCommandParser.java b/src/main/java/seedu/address/logic/parser/strategy/LoadCourtCommandParser.java
new file mode 100644
index 00000000000..1deb770380a
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/strategy/LoadCourtCommandParser.java
@@ -0,0 +1,30 @@
+package seedu.address.logic.parser.strategy;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.address.logic.commands.strategy.LoadCourtCommand;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.image.Image;
+
+/**
+ * Parses input arguments and creates a new LoadCourtCommand object
+ */
+public class LoadCourtCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the LoadCourtCommand
+ * and returns a LoadCourtCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public LoadCourtCommand parse(String args) throws ParseException {
+ try {
+ Image image = ParserUtil.parseImage(args);
+ return new LoadCourtCommand(image);
+ } catch (ParseException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, LoadCourtCommand.MESSAGE_USAGE), pe);
+ }
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/strategy/MovePlayerCommandParser.java b/src/main/java/seedu/address/logic/parser/strategy/MovePlayerCommandParser.java
new file mode 100644
index 00000000000..3b364e180bc
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/strategy/MovePlayerCommandParser.java
@@ -0,0 +1,69 @@
+package seedu.address.logic.parser.strategy;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_XCOORD;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_YCOORD;
+
+import java.util.stream.Stream;
+
+import seedu.address.logic.commands.strategy.MovePlayerCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.Prefix;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.strategy.Player;
+
+/**
+ * Parses input arguments and creates a new MovePlayerCommand object.
+ */
+public class MovePlayerCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the MovePlayerCommand
+ * and returns an MovePlayerCommand object for execution.
+ *
+ * @return an MovePlayerCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format.
+ */
+ @Override
+ public MovePlayerCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_XCOORD, PREFIX_YCOORD);
+ if (!arePrefixesPresent(argMultimap, PREFIX_XCOORD, PREFIX_YCOORD)
+ || argMultimap.getPreamble().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, MovePlayerCommand.MESSAGE_USAGE));
+ }
+
+ try {
+ int xCoord = Integer.parseInt(argMultimap.getValue(PREFIX_XCOORD).get());
+ int yCoord = Integer.parseInt(argMultimap.getValue(PREFIX_YCOORD).get());
+ String playerName = argMultimap.getPreamble();
+
+ if (!Player.isValidXCoord(xCoord)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ MovePlayerCommand.MESSAGE_USAGE));
+ }
+
+ if (!Player.isValidYCoord(yCoord)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ MovePlayerCommand.MESSAGE_USAGE));
+ }
+
+ return new MovePlayerCommand(playerName, xCoord, yCoord);
+ } catch (NumberFormatException e) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, MovePlayerCommand.MESSAGE_USAGE));
+ }
+ }
+
+ /**
+ * Returns true if none of the prefixes contains empty {@code Optional} values in the given
+ * {@code ArgumentMultimap}.
+ */
+ private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/task/AddTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/task/AddTaskCommandParser.java
new file mode 100644
index 00000000000..2726e519677
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/task/AddTaskCommandParser.java
@@ -0,0 +1,69 @@
+package seedu.address.logic.parser.task;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_CONTACT;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ENDTIME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_STARTTIME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
+
+import java.util.Set;
+import java.util.stream.Stream;
+
+import seedu.address.logic.commands.task.AddTaskCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.Prefix;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.name.Name;
+import seedu.address.model.tag.Tag;
+import seedu.address.model.task.Date;
+import seedu.address.model.task.EndTime;
+import seedu.address.model.task.StartTime;
+import seedu.address.model.task.Task;
+
+
+/**
+ * Parses input arguments and creates a new AddTaskCommand object
+ */
+public class AddTaskCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the AddTaskCommand
+ * and returns an AddTaskCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public AddTaskCommand parse(String args) throws ParseException {
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_DATE,
+ PREFIX_STARTTIME, PREFIX_ENDTIME, PREFIX_TAG, PREFIX_CONTACT);
+
+ if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_DATE, PREFIX_STARTTIME, PREFIX_ENDTIME)
+ || !argMultimap.getPreamble().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskCommand.MESSAGE_USAGE));
+ }
+
+ Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get());
+ Date date = ParserUtil.parseDate(argMultimap.getValue(PREFIX_DATE).get());
+ StartTime startTime = ParserUtil.parseStartTime(argMultimap.getValue(PREFIX_STARTTIME).get());
+ EndTime endTime = ParserUtil.parseEndTime(argMultimap.getValue(PREFIX_ENDTIME).get());
+ Set tagSet = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG));
+ Set nameSet = ParserUtil.parseNames(argMultimap.getAllValues(PREFIX_CONTACT));
+
+ Task task = new Task(name, date, startTime, endTime, tagSet, nameSet);
+
+ return new AddTaskCommand(task);
+ }
+
+ /**
+ * Returns true if none of the prefixes contains empty {@code Optional} values in the given
+ * {@code ArgumentMultimap}.
+ */
+ private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/task/AddTaskTagCommandParser.java b/src/main/java/seedu/address/logic/parser/task/AddTaskTagCommandParser.java
new file mode 100644
index 00000000000..2cb12583038
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/task/AddTaskTagCommandParser.java
@@ -0,0 +1,75 @@
+package seedu.address.logic.parser.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import java.util.ArrayList;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.person.AddPersonTagCommand;
+import seedu.address.logic.commands.task.AddTaskTagCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.Prefix;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.tag.Tag;
+
+/**
+ * Parses input arguments and creates a new AddTaskCommand object
+ */
+public class AddTaskTagCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the {@code AddTagToTaskCommandParser}
+ * and returns a {@code AddTagToTaskCommand} object for execution
+ * * @param args Input string by user EXCEPT COMMAND WORD
+ *
+ * @return AddTagToTaskCommand object with arguments loaded in
+ * @throws ParseException If the user input does not conform to the expected format
+ */
+
+ public AddTaskTagCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+
+ // Tokenize all arguments
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, new Prefix(""));
+
+ // Convert the argMultimap into an ArrayList<> for easier access
+ // The @ArgumentTokenizer produces a map with 3 elements:
+ // Element 1: Whitespace
+ // Element 2: Index
+ // Element 3: tagName string
+ ArrayList values = new ArrayList<>(argMultimap.getAllValues(new Prefix("")));
+
+ // Get the index element in the ArrayList
+ int indexInt;
+ try {
+ indexInt = Integer.parseInt(values.get(1));
+ } catch (Exception e) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskTagCommand.MESSAGE_USAGE));
+ }
+ // Checking if index is a positive integer
+ if (!(indexInt >= 1)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddPersonTagCommand.MESSAGE_USAGE));
+ }
+
+ Index index = Index.fromOneBased(indexInt); // Convert to fromOneBased index since contact list starts from 1
+
+ // Get the tagName element in the ArrayList
+ String tagName;
+ try {
+ tagName = values.get(2);
+ } catch (IndexOutOfBoundsException e) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddTaskTagCommand.MESSAGE_USAGE));
+ }
+ try {
+ new Tag(tagName);
+ } catch (Exception e) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ AddTaskTagCommand.MESSAGE_USAGE));
+ }
+
+ return new AddTaskTagCommand(index, tagName);
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/task/ClearTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/task/ClearTaskCommandParser.java
new file mode 100644
index 00000000000..5c7128f4771
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/task/ClearTaskCommandParser.java
@@ -0,0 +1,58 @@
+package seedu.address.logic.parser.task;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE;
+
+import java.util.stream.Stream;
+
+import seedu.address.logic.commands.task.ClearTaskCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.Prefix;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.task.Date;
+
+/**
+ * Parses input arguments and creates a new ClearTaskCommand object
+ */
+public class ClearTaskCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the ClearTaskCommand
+ * and returns a ClearTaskCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public ClearTaskCommand parse(String args) throws ParseException {
+ try {
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_DATE);
+
+ //check if the given string is empty (or contains only whitespace)
+ if (args.isBlank()) {
+ return new ClearTaskCommand();
+ }
+
+ if (!arePrefixesPresent(argMultimap, PREFIX_DATE) || !argMultimap.getPreamble().isEmpty()) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ClearTaskCommand.MESSAGE_USAGE));
+ }
+
+ Date date = ParserUtil.parseDate(argMultimap.getValue(PREFIX_DATE).get());
+
+ return new ClearTaskCommand(date);
+ } catch (ParseException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, ClearTaskCommand.MESSAGE_USAGE), pe);
+ }
+ }
+
+ /**
+ * Returns true if none of the prefixes contains empty {@code Optional} values in the given
+ * {@code ArgumentMultimap}.
+ */
+ private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/task/DeleteTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/task/DeleteTaskCommandParser.java
new file mode 100644
index 00000000000..ffd72a2586b
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/task/DeleteTaskCommandParser.java
@@ -0,0 +1,31 @@
+package seedu.address.logic.parser.task;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.task.DeleteTaskCommand;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new DeleteTaskCommand object
+ */
+public class DeleteTaskCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the DeleteTaskCommand
+ * and returns a DeleteTaskCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public DeleteTaskCommand parse(String args) throws ParseException {
+ try {
+ Index index = ParserUtil.parseIndex(args);
+ return new DeleteTaskCommand(index);
+ } catch (ParseException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteTaskCommand.MESSAGE_USAGE), pe);
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/task/DeleteTaskTagCommandParser.java b/src/main/java/seedu/address/logic/parser/task/DeleteTaskTagCommandParser.java
new file mode 100644
index 00000000000..c1dff3663f6
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/task/DeleteTaskTagCommandParser.java
@@ -0,0 +1,80 @@
+package seedu.address.logic.parser.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX;
+
+import java.util.ArrayList;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.person.AddPersonTagCommand;
+import seedu.address.logic.commands.task.DeleteTaskTagCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.Prefix;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.tag.Tag;
+
+/**
+ * Parses input arguments and creates a new AddTaskCommand object
+ */
+public class DeleteTaskTagCommandParser implements Parser {
+ /**
+ * Parses the given {@code String} of arguments in the context of the
+ * {@code DeleteTagFromTaskCommandParser}
+ * and returns a {@code DeleteTagFromTaskCommand} object for execution
+ * * @param args Input string by user EXCEPT COMMAND WORD
+ *
+ * @return DeleteTagFromTaskCommand object with arguments loaded in
+ * @throws ParseException If the user input does not conform to the expected
+ * format
+ */
+
+ public DeleteTaskTagCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+
+ // Tokenize all arguments
+ ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, new Prefix(""));
+
+ // Convert the argMultimap into an ArrayList<> for easier access
+ // The @ArgumentTokenizer produces a map with 3 elements:
+ // Element 1: Whitespace
+ // Element 2: Index
+ // Element 3: tagName string
+ ArrayList values = new ArrayList<>(argMultimap.getAllValues(new Prefix("")));
+
+ // Get the index element in the ArrayList
+ int indexInt;
+ try {
+ indexInt = Integer.parseInt(values.get(1));
+ } catch (Exception e) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteTaskTagCommand.MESSAGE_USAGE));
+
+ }
+ // Checking if index is a positive integer
+ if (!(indexInt >= 1)) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddPersonTagCommand.MESSAGE_USAGE));
+ }
+
+ Index index = Index.fromOneBased(indexInt); // Convert to fromOneBased index since contact list starts from 1
+
+ // Get the tagName element in the ArrayList
+ String tagName;
+ try {
+ tagName = values.get(2);
+ } catch (IndexOutOfBoundsException e) {
+ throw new ParseException(String.format(MESSAGE_INVALID_TASK_DISPLAYED_INDEX,
+ DeleteTaskTagCommand.MESSAGE_USAGE));
+ }
+ try {
+ new Tag(tagName);
+ } catch (Exception e) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ DeleteTaskTagCommand.MESSAGE_USAGE));
+ }
+
+ return new DeleteTaskTagCommand(index, tagName);
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/task/EditTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/task/EditTaskCommandParser.java
new file mode 100644
index 00000000000..ae69f433dfa
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/task/EditTaskCommandParser.java
@@ -0,0 +1,105 @@
+package seedu.address.logic.parser.task;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_CONTACT;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_ENDTIME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_STARTTIME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Optional;
+import java.util.Set;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.EditTaskDescriptor;
+import seedu.address.logic.commands.task.EditTaskCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.name.Name;
+import seedu.address.model.tag.Tag;
+
+/**
+ * Parses input arguments and creates a new EditCommand object
+ */
+public class EditTaskCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the EditTaskCommand
+ * and returns an EditTaskCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public EditTaskCommand parse(String args) throws ParseException {
+ requireNonNull(args);
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_DATE, PREFIX_STARTTIME,
+ PREFIX_ENDTIME, PREFIX_TAG, PREFIX_CONTACT);
+
+ Index index;
+
+ try {
+ index = ParserUtil.parseIndex(argMultimap.getPreamble());
+ } catch (ParseException pe) {
+ throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditTaskCommand.MESSAGE_USAGE), pe);
+ }
+
+ EditTaskDescriptor editTaskDescriptor = new EditTaskDescriptor();
+ if (argMultimap.getValue(PREFIX_NAME).isPresent()) {
+ editTaskDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()));
+ }
+ if (argMultimap.getValue(PREFIX_DATE).isPresent()) {
+ editTaskDescriptor.setDate(ParserUtil.parseDate(argMultimap.getValue(PREFIX_DATE).get()));
+ }
+ if (argMultimap.getValue(PREFIX_STARTTIME).isPresent()) {
+ editTaskDescriptor.setStartTime(ParserUtil.parseStartTime(argMultimap.getValue(PREFIX_STARTTIME).get()));
+ }
+ if (argMultimap.getValue(PREFIX_ENDTIME).isPresent()) {
+ editTaskDescriptor.setEndTime(ParserUtil.parseEndTime(argMultimap.getValue(PREFIX_ENDTIME).get()));
+ }
+ parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editTaskDescriptor::setTags);
+ parsePersonsForEdit(argMultimap.getAllValues(PREFIX_CONTACT)).ifPresent(editTaskDescriptor::setPersons);
+
+ if (!editTaskDescriptor.isAnyFieldEdited()) {
+ throw new ParseException(EditTaskCommand.MESSAGE_NOT_EDITED);
+ }
+
+ return new EditTaskCommand(index, editTaskDescriptor);
+ }
+
+ /**
+ * Parses {@code Collection tags} into a {@code Set} if {@code tags} is non-empty.
+ * If {@code tags} contain only one element which is an empty string, it will be parsed into a
+ * {@code Set} containing zero tags.
+ */
+ private Optional> parseTagsForEdit(Collection tags) throws ParseException {
+ assert tags != null;
+
+ if (tags.isEmpty()) {
+ return Optional.empty();
+ }
+ Collection tagSet = tags.size() == 1 && tags.contains("") ? Collections.emptySet() : tags;
+ return Optional.of(ParserUtil.parseTags(tagSet));
+ }
+
+ /**
+ * Parses {@code Collection persons} into a {@code Set} if {@code persons} is non-empty.
+ * If {@code persons} contain only one element which is an empty string, it will be parsed into a
+ * {@code Set} containing zero persons].
+ */
+ private Optional> parsePersonsForEdit(Collection persons) throws ParseException {
+ assert persons != null;
+
+ if (persons.isEmpty()) {
+ return Optional.empty();
+ }
+ Collection nameSet = persons.size() == 1 && persons.contains("") ? Collections.emptySet() : persons;
+ return Optional.of(ParserUtil.parseNames(nameSet));
+ }
+
+}
diff --git a/src/main/java/seedu/address/logic/parser/task/FindTaskCommandParser.java b/src/main/java/seedu/address/logic/parser/task/FindTaskCommandParser.java
new file mode 100644
index 00000000000..c89061fa2a2
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/task/FindTaskCommandParser.java
@@ -0,0 +1,65 @@
+package seedu.address.logic.parser.task;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
+import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import seedu.address.logic.commands.task.FindTaskCommand;
+import seedu.address.logic.parser.ArgumentMultimap;
+import seedu.address.logic.parser.ArgumentTokenizer;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.Prefix;
+import seedu.address.logic.parser.exceptions.ParseException;
+import seedu.address.model.name.TaskNameContainsKeywordsPredicate;
+import seedu.address.model.tag.TaskTagContainsKeywordsPredicate;
+
+/**
+ * Parses input arguments and creates a new FindTaskCommand object
+ */
+public class FindTaskCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the FindTaskCommand
+ * and returns a FindTaskCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public FindTaskCommand parse(String args) throws ParseException {
+ String trimmedArgs = args.trim();
+ ArgumentMultimap argMultimap =
+ ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_TAG);
+
+ if ((!arePrefixesPresent(argMultimap, PREFIX_NAME) && !arePrefixesPresent(argMultimap, PREFIX_TAG))
+ || trimmedArgs.isEmpty()) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindTaskCommand.MESSAGE_USAGE));
+ }
+
+ List nameKeywords = argMultimap.getAllValues(PREFIX_NAME);
+ List tagKeywords = argMultimap.getAllValues(PREFIX_TAG);
+
+ // checks if names are valid
+ for (String name: nameKeywords) {
+ ParserUtil.parseNameKeyword(name);
+ }
+
+ // check if tags are valid
+ for (String tag: tagKeywords) {
+ ParserUtil.parseTagKeyword(tag);
+ }
+
+ return new FindTaskCommand(new TaskNameContainsKeywordsPredicate(nameKeywords),
+ new TaskTagContainsKeywordsPredicate(tagKeywords));
+ }
+
+ /**
+ * Returns true if none of the prefixes contains empty {@code Optional} values in the given
+ * {@code ArgumentMultimap}.
+ */
+ private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
+ return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
+ }
+}
diff --git a/src/main/java/seedu/address/logic/parser/task/GetPersonCommandParser.java b/src/main/java/seedu/address/logic/parser/task/GetPersonCommandParser.java
new file mode 100644
index 00000000000..0e49680b3ad
--- /dev/null
+++ b/src/main/java/seedu/address/logic/parser/task/GetPersonCommandParser.java
@@ -0,0 +1,31 @@
+package seedu.address.logic.parser.task;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+
+import seedu.address.commons.core.index.Index;
+import seedu.address.logic.commands.task.GetPersonCommand;
+import seedu.address.logic.parser.Parser;
+import seedu.address.logic.parser.ParserUtil;
+import seedu.address.logic.parser.exceptions.ParseException;
+
+/**
+ * Parses input arguments and creates a new GetPersonCommand object
+ */
+public class GetPersonCommandParser implements Parser {
+
+ /**
+ * Parses the given {@code String} of arguments in the context of the GetPersonCommand
+ * and returns a GetPersonCommand object for execution.
+ * @throws ParseException if the user input does not conform the expected format
+ */
+ public GetPersonCommand parse(String args) throws ParseException {
+ try {
+ Index index = ParserUtil.parseIndex(args);
+ return new GetPersonCommand(index);
+ } catch (ParseException pe) {
+ throw new ParseException(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, GetPersonCommand.MESSAGE_USAGE), pe);
+ }
+ }
+
+}
diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java
index d54df471c1f..e2ad197c92e 100644
--- a/src/main/java/seedu/address/model/Model.java
+++ b/src/main/java/seedu/address/model/Model.java
@@ -6,6 +6,8 @@
import javafx.collections.ObservableList;
import seedu.address.commons.core.GuiSettings;
import seedu.address.model.person.Person;
+import seedu.address.model.strategy.Player;
+import seedu.address.model.task.Task;
/**
* The API of the Model component.
@@ -13,6 +15,8 @@
public interface Model {
/** {@code Predicate} that always evaluate to true */
Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true;
+ Predicate PREDICATE_SHOW_ALL_TASKS = unused -> true;
+ Predicate PREDICATE_SHOW_ALL_PLAYERS = unused -> true;
/**
* Replaces user prefs data with the data in {@code userPrefs}.
@@ -44,6 +48,16 @@ public interface Model {
*/
void setAddressBookFilePath(Path addressBookFilePath);
+ /**
+ * Returns the user prefs' task book file path.
+ */
+ Path getTaskBookFilePath();
+
+ /**
+ * Sets the user prefs' task book file path.
+ */
+ void setTaskBookFilePath(Path taskBookFilePath);
+
/**
* Replaces address book data with the data in {@code addressBook}.
*/
@@ -76,6 +90,9 @@ public interface Model {
*/
void setPerson(Person target, Person editedPerson);
+ /** Returns an unmodifiable view of the unfiltered person list */
+ ObservableList getUnfilteredPersonList();
+
/** Returns an unmodifiable view of the filtered person list */
ObservableList getFilteredPersonList();
@@ -84,4 +101,87 @@ public interface Model {
* @throws NullPointerException if {@code predicate} is null.
*/
void updateFilteredPersonList(Predicate predicate);
+
+ /**
+ * Replaces task book data with the data in {@code taskBook}.
+ */
+ void setTaskBook(ReadOnlyTaskBook taskBook);
+
+ /** Returns the TaskBook */
+ ReadOnlyTaskBook getTaskBook();
+
+ /**
+ * Returns true if a task with the same identity as {@code task} exists in the task book.
+ */
+ boolean hasTask(Task task);
+
+ /**
+ * Deletes the given task.
+ * The task must exist in the task book.
+ */
+ void deleteTask(Task target);
+
+ /**
+ * Adds the given task.
+ * {@code task} must not already exist in the task book.
+ */
+ void addTask(Task task);
+
+ /**
+ * Replaces the given task {@code target} with {@code editedTask}.
+ * {@code target} must exist in the task book.
+ * The task identity of {@code editedTask} must not be the same as another existing task in the task book.
+ */
+ void setTask(Task target, Task editedTask);
+
+ /** Returns an unmodifiable view of the unfiltered task list */
+ ObservableList getUnfilteredTaskList();
+
+ /** Returns an unmodifiable view of the filtered task list */
+ ObservableList getFilteredTaskList();
+
+ /**
+ * Updates the filter of the filtered task list to filter by the given {@code predicate}.
+ * @throws NullPointerException if {@code predicate} is null.
+ */
+ void updateFilteredTaskList(Predicate predicate);
+
+ /**
+ * Replaces strategy board data with the data in {@code strategy board}.
+ */
+ void setStrategyBoard(ReadOnlyStrategyBoard strategyBoard);
+
+ /** Returns the Strategy Board. **/
+ ReadOnlyStrategyBoard getStrategyBoard();
+
+ /**
+ * Returns true if a player with the same identity as {@code player} exists in the strategy board.
+ */
+ boolean hasPlayer(Player player);
+
+ /**
+ * Deletes the given player.
+ * The task must exist in the strategy board.
+ */
+ void deletePlayer(Player target);
+
+ /**
+ * Adds the given player.
+ * {@code player} must not already exist in the strategy board.
+ */
+ void addPlayer(Player player);
+
+ /**
+ * Replaces the given player {@code target} with {@code editedPlayer}.
+ */
+ void setPlayer(Player target, Player editedPlayer);
+
+ /** Returns an unmodifiable view of the filtered player list */
+ ObservableList getFilteredPlayerList();
+
+ /**
+ * Updates the filter of the filtered player list to filter by the given {@code predicate}.
+ * @throws NullPointerException if {@code predicate} is null.
+ */
+ void updateFilteredPlayerList(Predicate predicate);
}
diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java
index 86c1df298d7..56746527fad 100644
--- a/src/main/java/seedu/address/model/ModelManager.java
+++ b/src/main/java/seedu/address/model/ModelManager.java
@@ -12,6 +12,8 @@
import seedu.address.commons.core.GuiSettings;
import seedu.address.commons.core.LogsCenter;
import seedu.address.model.person.Person;
+import seedu.address.model.strategy.Player;
+import seedu.address.model.task.Task;
/**
* Represents the in-memory model of the address book data.
@@ -20,24 +22,33 @@ public class ModelManager implements Model {
private static final Logger logger = LogsCenter.getLogger(ModelManager.class);
private final AddressBook addressBook;
+ private final TaskBook taskBook;
+ private final StrategyBoard strategyBoard;
private final UserPrefs userPrefs;
private final FilteredList filteredPersons;
+ private final FilteredList filteredTasks;
+ private final FilteredList filteredPlayers;
/**
* Initializes a ModelManager with the given addressBook and userPrefs.
*/
- public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs) {
- requireAllNonNull(addressBook, userPrefs);
+ public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyTaskBook taskBook,
+ ReadOnlyStrategyBoard strategyBoard, ReadOnlyUserPrefs userPrefs) {
+ requireAllNonNull(addressBook, taskBook, userPrefs);
logger.fine("Initializing with address book: " + addressBook + " and user prefs " + userPrefs);
this.addressBook = new AddressBook(addressBook);
+ this.taskBook = new TaskBook(taskBook);
+ this.strategyBoard = new StrategyBoard(strategyBoard);
this.userPrefs = new UserPrefs(userPrefs);
filteredPersons = new FilteredList<>(this.addressBook.getPersonList());
+ filteredTasks = new FilteredList<>(this.taskBook.getTaskList());
+ filteredPlayers = new FilteredList<>(this.strategyBoard.getPlayerList());
}
public ModelManager() {
- this(new AddressBook(), new UserPrefs());
+ this(new AddressBook(), new TaskBook(), new StrategyBoard(), new UserPrefs());
}
//=========== UserPrefs ==================================================================================
@@ -75,6 +86,17 @@ public void setAddressBookFilePath(Path addressBookFilePath) {
userPrefs.setAddressBookFilePath(addressBookFilePath);
}
+ @Override
+ public Path getTaskBookFilePath() {
+ return userPrefs.getTaskBookFilePath();
+ }
+
+ @Override
+ public void setTaskBookFilePath(Path taskBookFilePath) {
+ requireNonNull(taskBookFilePath);
+ userPrefs.setTaskBookFilePath(taskBookFilePath);
+ }
+
//=========== AddressBook ================================================================================
@Override
@@ -111,6 +133,11 @@ public void setPerson(Person target, Person editedPerson) {
addressBook.setPerson(target, editedPerson);
}
+ @Override
+ public ObservableList getUnfilteredPersonList() {
+ return addressBook.getPersonList();
+ }
+
//=========== Filtered Person List Accessors =============================================================
/**
@@ -128,6 +155,117 @@ public void updateFilteredPersonList(Predicate predicate) {
filteredPersons.setPredicate(predicate);
}
+ //=========== Task Book ================================================================================
+
+ @Override
+ public void setTaskBook(ReadOnlyTaskBook taskBook) {
+ this.taskBook.resetData(taskBook);
+ }
+
+ @Override
+ public ReadOnlyTaskBook getTaskBook() {
+ return taskBook;
+ }
+
+ @Override
+ public boolean hasTask(Task task) {
+ requireNonNull(task);
+ return taskBook.hasTask(task);
+ }
+
+ @Override
+ public void deleteTask(Task target) {
+ taskBook.removeTask(target);
+ }
+
+ @Override
+ public void addTask(Task task) {
+ taskBook.addTask(task);
+ updateFilteredTaskList(PREDICATE_SHOW_ALL_TASKS);
+ }
+
+ @Override
+ public void setTask(Task target, Task editedTask) {
+ requireAllNonNull(target, editedTask);
+
+ taskBook.setTask(target, editedTask);
+ }
+
+ @Override
+ public ObservableList getUnfilteredTaskList() {
+ return taskBook.getTaskList();
+ }
+
+ //=========== Filtered Task List Accessors =============================================================
+
+ /**
+ * Returns an unmodifiable view of the list of {@code Task} backed by the internal list of
+ * {@code versionedTaskBook}
+ */
+ @Override
+ public ObservableList getFilteredTaskList() {
+ return filteredTasks;
+ }
+
+ @Override
+ public void updateFilteredTaskList(Predicate predicate) {
+ requireNonNull(predicate);
+ filteredTasks.setPredicate(predicate);
+ }
+
+ //=========== Strategy Board ================================================================================
+
+ @Override
+ public void setStrategyBoard(ReadOnlyStrategyBoard strategyBoard) {
+ this.strategyBoard.resetData(strategyBoard);
+ }
+
+ @Override
+ public ReadOnlyStrategyBoard getStrategyBoard() {
+ return strategyBoard;
+ }
+
+ @Override
+ public boolean hasPlayer(Player player) {
+ requireNonNull(player);
+ return strategyBoard.hasPlayer(player);
+ }
+
+ @Override
+ public void deletePlayer(Player target) {
+ strategyBoard.removePlayer(target);
+ }
+
+ @Override
+ public void addPlayer(Player player) {
+ strategyBoard.addPlayer(player);
+ updateFilteredPlayerList(PREDICATE_SHOW_ALL_PLAYERS);
+ }
+
+ @Override
+ public void setPlayer(Player target, Player editedPlayer) {
+ requireAllNonNull(target, editedPlayer);
+
+ strategyBoard.setPlayer(target, editedPlayer);
+ }
+
+ //=========== Filtered Player List Accessors =============================================================
+
+ /**
+ * Returns an unmodifiable view of the list of {@code Player} backed by the internal list of
+ * {@code versionedStrategyBoard}
+ */
+ @Override
+ public ObservableList getFilteredPlayerList() {
+ return filteredPlayers;
+ }
+
+ @Override
+ public void updateFilteredPlayerList(Predicate predicate) {
+ requireNonNull(predicate);
+ filteredPlayers.setPredicate(predicate);
+ }
+
@Override
public boolean equals(Object obj) {
// short circuit if same object
@@ -144,7 +282,11 @@ public boolean equals(Object obj) {
ModelManager other = (ModelManager) obj;
return addressBook.equals(other.addressBook)
&& userPrefs.equals(other.userPrefs)
- && filteredPersons.equals(other.filteredPersons);
+ && filteredPersons.equals(other.filteredPersons)
+ && taskBook.equals(other.taskBook)
+ && filteredTasks.equals(other.filteredTasks)
+ && strategyBoard.equals(other.strategyBoard)
+ && filteredPlayers.equals(other.filteredPlayers);
}
}
diff --git a/src/main/java/seedu/address/model/ReadOnlyStrategyBoard.java b/src/main/java/seedu/address/model/ReadOnlyStrategyBoard.java
new file mode 100644
index 00000000000..e0600a8eeb3
--- /dev/null
+++ b/src/main/java/seedu/address/model/ReadOnlyStrategyBoard.java
@@ -0,0 +1,15 @@
+package seedu.address.model;
+
+import javafx.collections.ObservableList;
+import seedu.address.model.strategy.Player;
+
+/**
+ * Unmodifiable view of a strategy board
+ */
+public interface ReadOnlyStrategyBoard {
+ /**
+ * Returns an unmodifiable view of the player list.
+ * This list will not contain any duplicate players.
+ */
+ ObservableList getPlayerList();
+}
diff --git a/src/main/java/seedu/address/model/ReadOnlyTaskBook.java b/src/main/java/seedu/address/model/ReadOnlyTaskBook.java
new file mode 100644
index 00000000000..22b6380fe38
--- /dev/null
+++ b/src/main/java/seedu/address/model/ReadOnlyTaskBook.java
@@ -0,0 +1,15 @@
+package seedu.address.model;
+
+import javafx.collections.ObservableList;
+import seedu.address.model.task.Task;
+
+/**
+ * Unmodifiable view of an task book
+ */
+public interface ReadOnlyTaskBook {
+ /**
+ * Returns an unmodifiable view of the persons list.
+ * This list will not contain any duplicate tasks.
+ */
+ ObservableList getTaskList();
+}
diff --git a/src/main/java/seedu/address/model/StrategyBoard.java b/src/main/java/seedu/address/model/StrategyBoard.java
new file mode 100644
index 00000000000..507d2595329
--- /dev/null
+++ b/src/main/java/seedu/address/model/StrategyBoard.java
@@ -0,0 +1,112 @@
+package seedu.address.model;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.List;
+
+import javafx.collections.ObservableList;
+import seedu.address.model.strategy.Player;
+import seedu.address.model.strategy.UniquePlayerList;
+
+/**
+ * Wraps all data at the strategy-board level
+ * Duplicates are not allowed (by .equals comparison)
+ */
+public class StrategyBoard implements ReadOnlyStrategyBoard {
+ private final UniquePlayerList players;
+ /*
+ * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication
+ * between constructors. See https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
+ *
+ * Note that non-static init blocks are not recommended to use. There are other ways to avoid duplication
+ * among constructors.
+ */
+ {
+ players = new UniquePlayerList();
+ }
+
+ public StrategyBoard() {}
+
+ /**
+ * Creates an StrategyBoard using the Players in the {@code toBeCopied}
+ */
+ public StrategyBoard(ReadOnlyStrategyBoard toBeCopied) {
+ this();
+ resetData(toBeCopied);
+ }
+
+ //// list overwrite operations
+
+ /**
+ * Replaces the contents of the player list with {@code players}.
+ */
+ public void setPlayers(List players) {
+ this.players.setPlayers(players);
+ }
+
+ /**
+ * Resets the existing data of this {@code StrategyBoard} with {@code newData}.
+ */
+ public void resetData(ReadOnlyStrategyBoard newData) {
+ requireNonNull(newData);
+
+ setPlayers(newData.getPlayerList());
+ }
+
+ //// player-level operations
+
+ /**
+ * Returns true if a player with the same identity as {@code player} exists in the address book.
+ */
+ public boolean hasPlayer(Player player) {
+ requireNonNull(player);
+ return players.contains(player);
+ }
+
+ /**
+ * Adds a player to the Strategy Board.
+ * The player must not already exist in the strategy board.
+ */
+ public void addPlayer(Player t) {
+ players.add(t);
+ }
+
+ /**
+ * Removes {@code key} from this {@code StrategyBoard}.
+ * {@code key} must exist in the strategy board.
+ */
+ public void removePlayer(Player key) {
+ players.remove(key);
+ }
+
+ public void setPlayer(Player target, Player editedPlayer) {
+ requireNonNull(editedPlayer);
+
+ players.setPlayer(target, editedPlayer);
+ }
+ //// util methods
+
+ @Override
+ public String toString() {
+ return players.asUnmodifiableObservableList().size() + " players";
+ }
+
+ @Override
+ public ObservableList getPlayerList() {
+ return players.asUnmodifiableObservableList();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof StrategyBoard // instanceof handles nulls
+ && players.equals(((StrategyBoard) other).players));
+ }
+
+ @Override
+ public int hashCode() {
+ return players.hashCode();
+ }
+
+
+}
diff --git a/src/main/java/seedu/address/model/TaskBook.java b/src/main/java/seedu/address/model/TaskBook.java
new file mode 100644
index 00000000000..9cd5a286517
--- /dev/null
+++ b/src/main/java/seedu/address/model/TaskBook.java
@@ -0,0 +1,122 @@
+package seedu.address.model;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.List;
+
+import javafx.collections.ObservableList;
+import seedu.address.model.task.Task;
+import seedu.address.model.task.UniqueTaskList;
+
+
+/**
+ * Wraps all data at the task-book level
+ * Duplicates are not allowed (by .isSameTask comparison)
+ */
+public class TaskBook implements ReadOnlyTaskBook {
+
+
+ private final UniqueTaskList tasks;
+
+ /*
+ * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication
+ * between constructors. See https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
+ *
+ * Note that non-static init blocks are not recommended to use. There are other ways to avoid duplication
+ * among constructors.
+ */
+ {
+ tasks = new UniqueTaskList();
+ }
+
+ public TaskBook() {}
+
+ /**
+ * Creates an TaskBook using the tasks in the {@code toBeCopied}
+ */
+ public TaskBook(ReadOnlyTaskBook toBeCopied) {
+ this();
+ resetData(toBeCopied);
+ }
+
+ //// list overwrite operations
+
+ /**
+ * Replaces the contents of the task list with {@code tasks}.
+ * {@code tasks} must not contain duplicate tasks.
+ */
+ public void setTasks(List tasks) {
+ this.tasks.setTasks(tasks);
+ }
+
+ /**
+ * Resets the existing data of this {@code TaskBook} with {@code newData}.
+ */
+ public void resetData(ReadOnlyTaskBook newData) {
+ requireNonNull(newData);
+
+ setTasks(newData.getTaskList());
+ }
+
+ //// task-level operations
+
+ /**
+ * Returns true if a task with the same identity as {@code task} exists in the task book.
+ */
+ public boolean hasTask(Task task) {
+ requireNonNull(task);
+ return tasks.contains(task);
+ }
+
+ /**
+ * Adds a task to the Task book.
+ * The task must not already exist in the task book.
+ */
+ public void addTask(Task t) {
+ tasks.add(t);
+ }
+
+ /**
+ * Replaces the given task {@code target} in the list with {@code editedTask}.
+ * {@code target} must exist in the task book.
+ * The task identity of {@code editedTask} must not be the same as another existing task in the task book.
+ */
+ public void setTask(Task target, Task editedTask) {
+ requireNonNull(editedTask);
+
+ tasks.setTask(target, editedTask);
+ }
+
+ /**
+ * Removes {@code key} from this {@code TaskBook}.
+ * {@code key} must exist in the task book.
+ */
+ public void removeTask(Task key) {
+ tasks.remove(key);
+ }
+
+ //// util methods
+
+ @Override
+ public String toString() {
+ return tasks.asUnmodifiableObservableList().size() + " tasks";
+ // TODO: refine later
+ }
+
+ @Override
+ public ObservableList getTaskList() {
+ return tasks.asUnmodifiableObservableList();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof TaskBook // instanceof handles nulls
+ && tasks.equals(((TaskBook) other).tasks));
+ }
+
+ @Override
+ public int hashCode() {
+ return tasks.hashCode();
+ }
+}
diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/seedu/address/model/UserPrefs.java
index 25a5fd6eab9..93b00616016 100644
--- a/src/main/java/seedu/address/model/UserPrefs.java
+++ b/src/main/java/seedu/address/model/UserPrefs.java
@@ -15,6 +15,7 @@ public class UserPrefs implements ReadOnlyUserPrefs {
private GuiSettings guiSettings = new GuiSettings();
private Path addressBookFilePath = Paths.get("data" , "addressbook.json");
+ private Path taskBookFilePath = Paths.get("data", "taskbook.json");
/**
* Creates a {@code UserPrefs} with default values.
@@ -56,6 +57,15 @@ public void setAddressBookFilePath(Path addressBookFilePath) {
this.addressBookFilePath = addressBookFilePath;
}
+ public Path getTaskBookFilePath() {
+ return taskBookFilePath;
+ }
+
+ public void setTaskBookFilePath(Path taskBookFilePath) {
+ requireNonNull(taskBookFilePath);
+ this.taskBookFilePath = taskBookFilePath;
+ }
+
@Override
public boolean equals(Object other) {
if (other == this) {
diff --git a/src/main/java/seedu/address/model/image/Image.java b/src/main/java/seedu/address/model/image/Image.java
new file mode 100644
index 00000000000..057a6e8f1a8
--- /dev/null
+++ b/src/main/java/seedu/address/model/image/Image.java
@@ -0,0 +1,59 @@
+package seedu.address.model.image;
+
+import static java.util.Objects.requireNonNull;
+
+import java.io.File;
+/**
+ * Represents an Image in Coach2K22.
+ */
+public class Image {
+ public static final String FILE_PATH = "courts/";
+
+ public static final String MESSAGE_CONSTRAINTS =
+ "Image must be a valid .png image and contained in \'" + FILE_PATH + "\'";
+
+ public final String imageName;
+
+ /**
+ * Constructor for Image class.
+ * @param imageName The name of an image
+ */
+ public Image(String imageName) {
+ requireNonNull(imageName);
+ this.imageName = imageName;
+ }
+
+ /**
+ * Checks if given image name is a valid image.
+ * @param imageName The name of an image
+ * @return true if the image exists
+ */
+ public static Boolean isValidFile(String imageName) {
+ String filePath = FILE_PATH + imageName + ".png";
+ File file = new File(filePath);
+ return file.exists();
+ }
+
+
+ /**
+ * Returns the File format of the image.
+ * @return File object of the given image
+ */
+ public File getImagePath() {
+ String filePath = FILE_PATH + this.imageName + ".png";
+ File file = new File(filePath);
+ return file;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this
+ || (other instanceof Image
+ && imageName.equals(((Image) other).imageName));
+ }
+
+ @Override
+ public String toString() {
+ return this.imageName;
+ }
+}
diff --git a/src/main/java/seedu/address/model/person/Name.java b/src/main/java/seedu/address/model/name/Name.java
similarity index 97%
rename from src/main/java/seedu/address/model/person/Name.java
rename to src/main/java/seedu/address/model/name/Name.java
index 79244d71cf7..30deefd4303 100644
--- a/src/main/java/seedu/address/model/person/Name.java
+++ b/src/main/java/seedu/address/model/name/Name.java
@@ -1,4 +1,4 @@
-package seedu.address.model.person;
+package seedu.address.model.name;
import static java.util.Objects.requireNonNull;
import static seedu.address.commons.util.AppUtil.checkArgument;
diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/name/PersonNameContainsKeywordsPredicate.java
similarity index 58%
rename from src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java
rename to src/main/java/seedu/address/model/name/PersonNameContainsKeywordsPredicate.java
index c9b5868427c..2578e0dcbd8 100644
--- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java
+++ b/src/main/java/seedu/address/model/name/PersonNameContainsKeywordsPredicate.java
@@ -1,17 +1,18 @@
-package seedu.address.model.person;
+package seedu.address.model.name;
import java.util.List;
import java.util.function.Predicate;
import seedu.address.commons.util.StringUtil;
+import seedu.address.model.person.Person;
/**
* Tests that a {@code Person}'s {@code Name} matches any of the keywords given.
*/
-public class NameContainsKeywordsPredicate implements Predicate {
+public class PersonNameContainsKeywordsPredicate implements Predicate {
private final List keywords;
- public NameContainsKeywordsPredicate(List keywords) {
+ public PersonNameContainsKeywordsPredicate(List keywords) {
this.keywords = keywords;
}
@@ -24,8 +25,7 @@ public boolean test(Person person) {
@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
- || (other instanceof NameContainsKeywordsPredicate // instanceof handles nulls
- && keywords.equals(((NameContainsKeywordsPredicate) other).keywords)); // state check
+ || (other instanceof PersonNameContainsKeywordsPredicate // instanceof handles nulls
+ && keywords.equals(((PersonNameContainsKeywordsPredicate) other).keywords)); // state check
}
-
}
diff --git a/src/main/java/seedu/address/model/name/TaskNameContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/name/TaskNameContainsKeywordsPredicate.java
new file mode 100644
index 00000000000..3019779dcf2
--- /dev/null
+++ b/src/main/java/seedu/address/model/name/TaskNameContainsKeywordsPredicate.java
@@ -0,0 +1,32 @@
+package seedu.address.model.name;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+import seedu.address.commons.util.StringUtil;
+import seedu.address.model.task.Task;
+
+/**
+ * Tests that a {@code Task}'s {@code Name} matches any of the keywords given.
+ */
+public class TaskNameContainsKeywordsPredicate implements Predicate {
+ private final List keywords;
+
+ public TaskNameContainsKeywordsPredicate(List keywords) {
+ this.keywords = keywords;
+ }
+
+ @Override
+ public boolean test(Task task) {
+ return keywords.stream()
+ .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(task.getName().fullName, keyword));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof TaskNameContainsKeywordsPredicate // instanceof handles nulls
+ && keywords.equals(((TaskNameContainsKeywordsPredicate) other).keywords)); // state check
+ }
+
+}
diff --git a/src/main/java/seedu/address/model/note/Note.java b/src/main/java/seedu/address/model/note/Note.java
new file mode 100644
index 00000000000..ec0791b10a0
--- /dev/null
+++ b/src/main/java/seedu/address/model/note/Note.java
@@ -0,0 +1,55 @@
+package seedu.address.model.note;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.AppUtil.checkArgument;
+
+/**
+ * Represents a Note in the address book.
+ * Guarantees: immutable; name is valid as declared in {@link #isValidNote(String)}
+ */
+public class Note {
+
+ public static final String MESSAGE_CONSTRAINTS = "Notes should be a String which is no longer than 50 characters";
+ public static final String VALIDATION_REGEX = "\\p{Print}+"; // printable
+ public static final int MAX_LENGTH = 50;
+
+ public final String note;
+
+ /**
+ * Constructs a {@code Note}.
+ *
+ * @param note A valid note string.
+ */
+ public Note(String note) {
+ requireNonNull(note);
+ checkArgument(isValidNote(note), MESSAGE_CONSTRAINTS);
+ this.note = note;
+ }
+
+ /**
+ * Returns true if a given string is a valid note.
+ */
+ public static boolean isValidNote(String test) {
+ return test.matches(VALIDATION_REGEX) && test.length() <= MAX_LENGTH;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof Note // instanceof handles nulls
+ && note.equalsIgnoreCase(((Note) other).note)); // state check
+ }
+
+ @Override
+ public int hashCode() {
+ return note.hashCode();
+ }
+
+ /**
+ * Format state as text for viewing.
+ */
+ public String toString() {
+ return note;
+ }
+
+}
diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java
index 8ff1d83fe89..6ad7754a457 100644
--- a/src/main/java/seedu/address/model/person/Person.java
+++ b/src/main/java/seedu/address/model/person/Person.java
@@ -2,12 +2,17 @@
import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Objects;
import java.util.Set;
+import seedu.address.model.name.Name;
+import seedu.address.model.note.Note;
import seedu.address.model.tag.Tag;
+import seedu.address.model.util.ListUtil;
/**
* Represents a Person in the address book.
@@ -23,17 +28,24 @@ public class Person {
// Data fields
private final Address address;
private final Set tags = new HashSet<>();
+ private final List strengths = new ArrayList<>();
+ private final List weaknesses = new ArrayList<>();
+ private final List miscellaneous = new ArrayList<>();
/**
* Every field must be present and not null.
*/
- public Person(Name name, Phone phone, Email email, Address address, Set tags) {
- requireAllNonNull(name, phone, email, address, tags);
+ public Person(Name name, Phone phone, Email email, Address address, Set tags,
+ List strength, List weaknesses, List misc) {
+ requireAllNonNull(name, phone, email, address, tags, strength, weaknesses, misc);
this.name = name;
this.phone = phone;
this.email = email;
this.address = address;
this.tags.addAll(tags);
+ this.strengths.addAll(strength);
+ this.weaknesses.addAll(weaknesses);
+ this.miscellaneous.addAll(misc);
}
public Name getName() {
@@ -60,6 +72,28 @@ public Set getTags() {
return Collections.unmodifiableSet(tags);
}
+ /**
+ * Returns an immutable note list, which throws {@code UnsupportedOperationException}
+ * if modification is attempted.
+ */
+ public List getStrengths() {
+ return Collections.unmodifiableList(strengths);
+ }
+ /**
+ * Returns an immutable note list, which throws {@code UnsupportedOperationException}
+ * if modification is attempted.
+ */
+ public List getWeaknesses() {
+ return Collections.unmodifiableList(weaknesses);
+ }
+ /**
+ * Returns an immutable note list, which throws {@code UnsupportedOperationException}
+ * if modification is attempted.
+ */
+ public List getMiscellaneous() {
+ return Collections.unmodifiableList(miscellaneous);
+ }
+
/**
* Returns true if both persons have the same name.
* This defines a weaker notion of equality between two persons.
@@ -92,13 +126,16 @@ public boolean equals(Object other) {
&& otherPerson.getPhone().equals(getPhone())
&& otherPerson.getEmail().equals(getEmail())
&& otherPerson.getAddress().equals(getAddress())
- && otherPerson.getTags().equals(getTags());
+ && otherPerson.getTags().equals(getTags())
+ && otherPerson.getStrengths().equals(getStrengths())
+ && otherPerson.getWeaknesses().equals(getWeaknesses())
+ && otherPerson.getMiscellaneous().equals(getMiscellaneous());
}
@Override
public int hashCode() {
// use this method for custom fields hashing instead of implementing your own
- return Objects.hash(name, phone, email, address, tags);
+ return Objects.hash(name, phone, email, address, tags, strengths, weaknesses, miscellaneous);
}
@Override
@@ -117,7 +154,27 @@ public String toString() {
builder.append("; Tags: ");
tags.forEach(builder::append);
}
+
+ List strengths = getStrengths();
+ if (!strengths.isEmpty()) {
+ builder.append("; Strengths: ");
+ ListUtil.toIndexedStringList(strengths)
+ .forEach(builder::append);
+ }
+
+ List weaknesses = getWeaknesses();
+ if (!weaknesses.isEmpty()) {
+ builder.append("; Weaknesses: ");
+ ListUtil.toIndexedStringList(weaknesses)
+ .forEach(builder::append);
+ }
+
+ List miscellaneous = getMiscellaneous();
+ if (!miscellaneous.isEmpty()) {
+ builder.append("; Misc: ");
+ ListUtil.toIndexedStringList(miscellaneous)
+ .forEach(builder::append);
+ }
return builder.toString();
}
-
}
diff --git a/src/main/java/seedu/address/model/strategy/Player.java b/src/main/java/seedu/address/model/strategy/Player.java
new file mode 100644
index 00000000000..4f813f21fb4
--- /dev/null
+++ b/src/main/java/seedu/address/model/strategy/Player.java
@@ -0,0 +1,115 @@
+package seedu.address.model.strategy;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.AppUtil.checkArgument;
+
+import java.util.Objects;
+
+public class Player {
+ public static final String MESSAGE_NAME_CONSTRAINTS = "Player name cannot be empty"
+ + " and must be not more then 24 characters"
+ + " and must not contain \"/\". \n";
+ public static final String MESSAGE_X_CONSTRAINTS = "X coordinate must be an integer between 0 and 1000";
+ public static final String MESSAGE_Y_CONSTRAINTS = "Y coordinate must be an integer between 0 and 600";
+
+ private static final int DEF_XCOORD = 50;
+ private static final int DEF_YCOORD = 500;
+ private static final int X_LIMIT = 1000;
+ private static final int Y_LIMIT = 600;
+
+ private final String name;
+ private int xCoord;
+ private int yCoord;
+
+ /**
+ * Creates a new player without specifying the coordinates
+ */
+ public Player(String name) {
+ requireNonNull(name);
+ checkArgument(isValidPlayer(name), MESSAGE_NAME_CONSTRAINTS);
+ this.name = name;
+ this.xCoord = DEF_XCOORD;
+ this.yCoord = DEF_YCOORD;
+ }
+
+ /**
+ * Creates a new player with specified coordinates
+ */
+ public Player(String name, int xCoord, int yCoord) {
+ requireNonNull(name);
+ checkArgument(isValidPlayer(name), MESSAGE_NAME_CONSTRAINTS);
+ checkArgument(isValidXCoord(xCoord), MESSAGE_X_CONSTRAINTS);
+ checkArgument(isValidYCoord(yCoord), MESSAGE_Y_CONSTRAINTS);
+ this.name = name;
+ this.xCoord = xCoord;
+ this.yCoord = yCoord;
+ }
+
+ /**
+ * Returns true if the given player name is a valid player name.
+ */
+ public static boolean isValidPlayer(String playerName) {
+ return !playerName.isEmpty() && playerName.length() <= 50 && !playerName.contains("/");
+ }
+
+ public static boolean isValidXCoord(int xCoord) {
+ return xCoord >= 0 && xCoord <= X_LIMIT;
+ }
+
+ public static boolean isValidYCoord(int yCoord) {
+ return yCoord >= 0 && yCoord <= Y_LIMIT;
+ }
+
+ //Getters
+ public String getName() {
+ return name;
+ }
+
+ public int getXCoord() {
+ return xCoord;
+ }
+
+ public int getYCoord() {
+ return yCoord;
+ }
+
+ //Setters
+ public void setXCoord(int xCoord) {
+ checkArgument(isValidXCoord(xCoord), MESSAGE_X_CONSTRAINTS);
+ this.xCoord = xCoord;
+ }
+
+ public void setYCoord(int yCoord) {
+ checkArgument(isValidYCoord(yCoord), MESSAGE_Y_CONSTRAINTS);
+ this.yCoord = yCoord;
+ }
+
+ //uti methods
+ public Player toCopy() {
+ return new Player(name, xCoord, yCoord);
+ }
+
+ /**
+ * Returns true if both players have the same name
+ * This defines a stronger notion of equality between two tasks.
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ if (!(other instanceof Player)) {
+ return false;
+ }
+
+ Player otherPlayer = (Player) other;
+ return otherPlayer.getName().equals(getName());
+ }
+
+ @Override
+ public int hashCode() {
+ // use this method for custom fields hashing instead of implementing your own
+ return Objects.hash(name, xCoord, yCoord);
+ }
+}
diff --git a/src/main/java/seedu/address/model/strategy/UniquePlayerList.java b/src/main/java/seedu/address/model/strategy/UniquePlayerList.java
new file mode 100644
index 00000000000..7de747dbd02
--- /dev/null
+++ b/src/main/java/seedu/address/model/strategy/UniquePlayerList.java
@@ -0,0 +1,121 @@
+package seedu.address.model.strategy;
+
+import static java.util.Objects.requireNonNull;
+import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;
+
+import java.util.Iterator;
+import java.util.List;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import seedu.address.model.strategy.exceptions.DuplicatePlayerException;
+import seedu.address.model.strategy.exceptions.PlayerNotFoundException;
+
+/**
+ * A list of players that enforces uniqueness between its elements and does not allow nulls.
+ *
+ * Supports a minimal set of list operations.
+ */
+public class UniquePlayerList implements Iterable {
+ private final ObservableList internalList = FXCollections.observableArrayList();
+ private final ObservableList internalUnmodifiableList =
+ FXCollections.unmodifiableObservableList(internalList);
+
+ /**
+ * Returns true if the list contains an equivalent player as the given argument.
+ */
+ public boolean contains(Player toCheck) {
+ requireNonNull(toCheck);
+ return internalList.stream().anyMatch(toCheck::equals);
+ }
+
+ /**
+ * Adds a player to the list.
+ * The player must not already exist in the list.
+ */
+ public void add(Player toAdd) {
+ requireNonNull(toAdd);
+ if (contains(toAdd)) {
+ throw new DuplicatePlayerException();
+ }
+ internalList.add(toAdd);
+ }
+
+ /**
+ * Removes the equivalent player from the list.
+ * The player must exist in the list.
+ */
+ public void remove(Player toRemove) {
+ requireNonNull(toRemove);
+ if (!internalList.remove(toRemove)) {
+ throw new PlayerNotFoundException();
+ }
+ }
+
+ /**
+ * Replaces the player {@code target} in the list with {@code editedPlayer}.
+ * {@code target} must exist in the list.
+ */
+ public void setPlayer(Player target, Player editedPlayer) {
+ requireNonNull(target);
+ requireNonNull(editedPlayer);
+
+ int index = internalList.indexOf(target);
+ if (index == -1) {
+ throw new PlayerNotFoundException();
+ }
+
+ internalList.set(index, editedPlayer);
+ }
+
+ /**
+ * Replaces the contents of this list with {@code players}.
+ * {@code players} must not contain duplicate players.
+ */
+ public void setPlayers(List players) {
+ requireAllNonNull(players);
+ if (!playersAreUnique(players)) {
+ throw new DuplicatePlayerException();
+ }
+
+ internalList.setAll(players);
+ }
+
+ /**
+ * Returns the backing list as an unmodifiable {@code ObservableList}.
+ */
+ public ObservableList asUnmodifiableObservableList() {
+ return internalUnmodifiableList;
+ }
+
+ @Override
+ public Iterator iterator() {
+ return internalList.iterator();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof UniquePlayerList // instanceof handles nulls
+ && internalList.equals(((UniquePlayerList) other).internalList));
+ }
+
+ @Override
+ public int hashCode() {
+ return internalList.hashCode();
+ }
+
+ /**
+ * Returns true if {@code players} contains only unique players.
+ */
+ private boolean playersAreUnique(List players) {
+ for (int i = 0; i < players.size() - 1; i++) {
+ for (int j = i + 1; j < players.size(); j++) {
+ if (players.get(i).equals(players.get(j))) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/seedu/address/model/strategy/exceptions/DuplicatePlayerException.java b/src/main/java/seedu/address/model/strategy/exceptions/DuplicatePlayerException.java
new file mode 100644
index 00000000000..fd7aa695560
--- /dev/null
+++ b/src/main/java/seedu/address/model/strategy/exceptions/DuplicatePlayerException.java
@@ -0,0 +1,10 @@
+package seedu.address.model.strategy.exceptions;
+
+/**
+ * Indicates that the operation will result in duplicate Players
+ */
+public class DuplicatePlayerException extends RuntimeException {
+ public DuplicatePlayerException() {
+ super("Operation would result in duplicate persons");
+ }
+}
diff --git a/src/main/java/seedu/address/model/strategy/exceptions/PlayerNotFoundException.java b/src/main/java/seedu/address/model/strategy/exceptions/PlayerNotFoundException.java
new file mode 100644
index 00000000000..55a9a605f51
--- /dev/null
+++ b/src/main/java/seedu/address/model/strategy/exceptions/PlayerNotFoundException.java
@@ -0,0 +1,7 @@
+package seedu.address.model.strategy.exceptions;
+
+/**
+ * Signals that the operation is unable to find the specified player.
+ */
+public class PlayerNotFoundException extends RuntimeException {
+}
diff --git a/src/main/java/seedu/address/model/tag/PersonTagContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/tag/PersonTagContainsKeywordsPredicate.java
new file mode 100644
index 00000000000..ddd99515f03
--- /dev/null
+++ b/src/main/java/seedu/address/model/tag/PersonTagContainsKeywordsPredicate.java
@@ -0,0 +1,33 @@
+package seedu.address.model.tag;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+import seedu.address.commons.util.StringUtil;
+import seedu.address.model.person.Person;
+
+/**
+ * Tests that a {@code Person}'s {@code Tag} matches any of the keywords given.
+ */
+public class PersonTagContainsKeywordsPredicate implements Predicate {
+ private final List keywords;
+
+ public PersonTagContainsKeywordsPredicate(List keywords) {
+ this.keywords = keywords;
+ }
+
+ @Override
+ public boolean test(Person person) {
+ return keywords.stream()
+ .anyMatch(keyword -> person.getTags().stream()
+ .anyMatch(tag -> StringUtil.containsWordIgnoreCase(tag.tagName, keyword)));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return other == this // short circuit if same object
+ || (other instanceof PersonTagContainsKeywordsPredicate // instanceof handles nulls
+ && keywords.equals(((PersonTagContainsKeywordsPredicate) other).keywords)); // state check
+ }
+
+}
diff --git a/src/main/java/seedu/address/model/tag/TaskTagContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/tag/TaskTagContainsKeywordsPredicate.java
new file mode 100644
index 00000000000..32f76c07930
--- /dev/null
+++ b/src/main/java/seedu/address/model/tag/TaskTagContainsKeywordsPredicate.java
@@ -0,0 +1,33 @@
+package seedu.address.model.tag;
+
+import java.util.List;
+import java.util.function.Predicate;
+
+import seedu.address.commons.util.StringUtil;
+import seedu.address.model.task.Task;
+
+/**
+ * Tests that a {@code Task}'s {@code Tag} matches any of the keywords given.
+ */
+public class TaskTagContainsKeywordsPredicate implements Predicate {
+ private final List