diff --git a/README.md b/README.md
index c651f00724d0..f2b87a75bc0d 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
[![Build Status](https://travis-ci.org/se-edu/addressbook-level4.svg?branch=master)](https://travis-ci.org/se-edu/addressbook-level4)
[![Coverage Status](https://coveralls.io/repos/github/CS2103AUG2016-F10-C3/main/badge.svg?branch=master)](https://coveralls.io/github/CS2103AUG2016-F10-C3/main?branch=master)
+[![Codacy Badge](https://api.codacy.com/project/badge/Grade/72e712e19dd241cfa8820139dbab0bef)](https://www.codacy.com/app/shwetha-ravi3/main?utm_source=github.com&utm_medium=referral&utm_content=CS2103AUG2016-F10-C3/main&utm_campaign=Badge_Grade)
# Tary
diff --git a/docs/AboutUs.md b/docs/AboutUs.md
index c640ee153033..fefc2d366cc4 100644
--- a/docs/AboutUs.md
+++ b/docs/AboutUs.md
@@ -4,18 +4,22 @@ We are a team based in the [School of Computing, National University of Singapor
## Project Team
-#### [Joshua Lee](http://github.com/lejolly)
-
-Role: Developer
-Responsibilities: UI
-
------
-
#### [Ravi Shwetha](http://github.com/ravishwetha)
-Role: Developer
-Responsibilities: Storage and Testing
+* Components in charge of: [Storage and Testing](https://github.com/se-edu/addressbook-level4/blob/master/docs/DeveloperGuide.md#storage-component)
+* Aspects/tools in charge of: Testing, Git
+* Features implemented:
+ * [Basic undo and multiple undo](https://github.com/se-edu/addressbook-level4/blob/master/docs/UserGuide.md#listing-all-persons--list)
+ * [Edit task](https://github.com/se-edu/addressbook-level4/blob/master/docs/UserGuide.md#deleting-a-person--delete)
+ * [Find searches for exact keywords first](https://github.com/se-edu/addressbook-level4/blob/master/docs/UserGuide.md#deleting-a-person--delete)
+ * [Natural language processing for dates using Natty API](https://github.com/se-edu/addressbook-level4/blob/master/docs/UserGuide.md#deleting-a-person--delete)
+* Code written: [[functional code](A0146130W.md)][[test code](A0146130W.md)][[docs](A0146130W.md)]
+* Other major contributions:
+ * Did the initial refactoring from Person model to Task model [[#133](https://github.com/se-edu/addressbook-level4/pull/152) ]
+ * Set up Coveralls and Collate
+ * Change browser to search task location on google maps
+
-----
#### [Tan Shao Yun](http://github.com/shaocloud)
@@ -23,7 +27,6 @@ Responsibilities: Storage and Testing
Role: Developer
Responsibilities: UI
-
-----
#### [Voon Soo Yin](http://github.com/tessav)
@@ -37,6 +40,6 @@ Responsibilities: UI
#### [Chan Jun Wei](http://github.com/chanjunweimy)
- Role: Module Tutor
+ Role: Module Tutor and Project Supervisor
Code modified from : https://github.com/nus-cs2103-AY1617S1/addressbook-level4
diff --git a/libs/A0146130W.md b/libs/A0146130W.md
index 73c5ea897901..f7882e9c3111 100644
--- a/libs/A0146130W.md
+++ b/libs/A0146130W.md
@@ -73,11 +73,13 @@
###### /src/main/java/seedu/gtd/logic/commands/FindCommand.java
``` java
private final String keywords;
- private final Set keywordSet;
+ private Set keywordSet;
+ private final String cmd;
- public FindCommand(String keywords, Set keywordSet) {
+ public FindCommand(String keywords, Set keywordSet, String cmd) {
this.keywords = keywords;
this.keywordSet = keywordSet;
+ this.cmd = cmd;
}
private String getMessageForTaskListShownSummaryIfExactPhraseNotFound(int displaySize) {
@@ -86,20 +88,68 @@
String MESSAGE_IF_EXACT_PHRASE_NOT_FOUND = "The exact phrase '" + keywords + "' was not found. Listing " + displaySize + " " + task_tasks + " containing the keywords entered instead.";
return String.format(MESSAGE_IF_EXACT_PHRASE_NOT_FOUND);
}
+
+ private String getMessageForTaskListShownSummaryIfExactFieldNotFound(int displaySize) {
+ String task_tasks = (displaySize == 1) ? "task" : "tasks";
+
+ String MESSAGE_IF_EXACT_PHRASE_NOT_FOUND = "The exact phrase '" + keywords + "' was not found in the specified field type. Listing " + displaySize + " " + task_tasks + " containing the keywords entered instead.";
+ return String.format(MESSAGE_IF_EXACT_PHRASE_NOT_FOUND);
+ }
@Override
public CommandResult execute() {
- model.updateFilteredTaskList(keywords, keywordSet);
-
- if(model.getFilteredTaskList().isEmpty()) {
- model.updateFilteredTaskList(keywordSet);
- if(!model.getFilteredTaskList().isEmpty()) return new CommandResult(getMessageForTaskListShownSummaryIfExactPhraseNotFound(model.getFilteredTaskList().size()));
- }
-
+ System.out.println("command: " + cmd);
+
+ // search by parameter if specified
+ if (cmd != "nil") {
+ model.updateFilteredTaskList(keywords, cmd);
+ } else {
+ // search by exact name
+ model.updateFilteredTaskList(keywords, keywordSet);
+ }
+ if (!model.getFilteredTaskList().isEmpty()) {
+ return new CommandResult(getMessageForTaskListShownSummary(model.getFilteredTaskList().size()));
+ }
+
+ // search by keywords
+ model.updateFilteredTaskList(keywords, "nil");
+
+ if (!model.getFilteredTaskList().isEmpty()) {
+ if (cmd == "nil") {
+ return new CommandResult(getMessageForTaskListShownSummaryIfExactPhraseNotFound(model.getFilteredTaskList().size()));
+ } else {
+ return new CommandResult(getMessageForTaskListShownSummaryIfExactFieldNotFound(model.getFilteredTaskList().size()));
+ }
+ }
+
return new CommandResult(getMessageForTaskListShownSummary(model.getFilteredTaskList().size()));
}
}
```
+###### /src/main/java/seedu/gtd/logic/commands/UndoCommand.java
+``` java
+
+package seedu.gtd.logic.commands;
+
+/**
+ * Deletes a task identified using it's last displayed index from the address book.
+ */
+public class UndoCommand extends Command {
+
+ public static final String COMMAND_WORD = "undo";
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Un-does the most recent modification of the task list.";
+ public static final String MESSAGE_SUCCESS = "Undo change";
+
+ public UndoCommand() {}
+
+ @Override
+ public CommandResult execute() {
+ model.undoAddressBookChange();
+ return new CommandResult(MESSAGE_SUCCESS);
+ }
+
+}
+```
###### /src/main/java/seedu/gtd/logic/parser/DateNaturalLanguageProcessor.java
``` java
@@ -109,7 +159,7 @@
public class DateNaturalLanguageProcessor implements NaturalLanguageProcessor {
private static final com.joestelmach.natty.Parser parser = new com.joestelmach.natty.Parser();
- private static final String DATE_FORMAT = "dd/MM/yyyy HH:mm:ss";
+ private static final String DATE_FORMAT = "dd/MM/yyyy HH:mm";
@Override
public String formatString(String naturalLanguageDate) {
@@ -165,6 +215,12 @@ public interface NaturalLanguageProcessor {
return nlp.formatString(dueDateRaw);
}
+ // remove time on date parsed to improve search results
+ private String removeTimeOnDate(String dueDateRaw) {
+ String[] dateTime = dueDateRaw.split(" ");
+ return dateTime[0];
+ }
+
```
###### /src/main/java/seedu/gtd/logic/parser/Parser.java
``` java
@@ -237,11 +293,19 @@ public interface NaturalLanguageProcessor {
``` java
@Override
public synchronized void editTask(int targetIndex, Task task) throws TaskNotFoundException {
+ savePreviousAddressBook();
+ System.out.println("editing task..");
addressBook.editTask(targetIndex, task);
updateFilteredListToShowAll();
indicateAddressBookChanged();
}
+ @Override
+ public void clearTaskList() {
+ savePreviousAddressBook();
+ resetData(AddressBook.getEmptyAddressBook());
+ }
+
```
###### /src/main/java/seedu/gtd/model/task/UniqueTaskList.java
``` java
@@ -258,6 +322,18 @@ public interface NaturalLanguageProcessor {
internalList.set(targetIndex, toEdit);
}
+ public void done(int targetIndex, Task taskdone) throws TaskNotFoundException {
+ System.out.println("in uniquetasklist");
+ System.out.println(taskdone.getName() + " " + taskdone.getisDone());
+ System.out.println("index at final:" + targetIndex);
+ assert taskdone != null;
+ if (invalidIndex(targetIndex)) {
+ throw new TaskNotFoundException();
+ }
+ System.out.println("marked done in model");
+ internalList.set(targetIndex, taskdone);
+ }
+
private boolean invalidIndex(int i) {
if(i < 0 || i >= internalList.size()) return true;
return false;
@@ -312,9 +388,9 @@ public class EditCommandTest extends AddressBookGuiTest {
}
/**
- * Runs the delete command to delete the task at specified index and confirms the result is correct.
- * @param targetIndexOneIndexed e.g. to delete the first task in the list, 1 should be given as the target index.
- * @param currentList A copy of the current list of tasks (before deletion).
+ * Runs the edit command to edit the task at specified index and confirms the result is correct.
+ * @param targetIndexOneIndexed e.g. to edit the first task in the list, 1 should be given as the target index.
+ * @param currentList A copy of the current list of tasks (before editing).
*/
private void assertEditSuccess(int targetIndexOneIndexed, String change, final TestTask[] currentList) {
TestTask taskToEdit = currentList[targetIndexOneIndexed-1]; //-1 because array uses zero indexing
@@ -328,6 +404,69 @@ public class EditCommandTest extends AddressBookGuiTest {
assertResultMessage(String.format(MESSAGE_EDIT_TASK_SUCCESS, expectedRemainder[targetIndexOneIndexed-1]));
}
+}
+```
+###### /src/test/java/guitests/UndoCommandTest.java
+``` java
+
+package guitests;
+
+import org.junit.Test;
+
+import seedu.gtd.testutil.TestTask;
+import seedu.gtd.testutil.TestUtil;
+
+import static org.junit.Assert.assertTrue;
+import static seedu.gtd.logic.commands.UndoCommand.MESSAGE_SUCCESS;;
+
+public class UndoCommandTest extends AddressBookGuiTest {
+
+ @Test
+ public void undo() {
+
+ //undo the addition of the first task
+ TestTask[] currentList = td.getTypicalTasks();
+ TestTask[] previousList = currentList;
+ commandBox.runCommand(td.george.getAddCommand());
+ assertUndoSuccess(previousList);
+
+ //undo editing the dueDate of the last task in the list
+ int targetIndex = currentList.length;
+ String change = "d/2";
+ previousList = currentList;
+ commandBox.runCommand("edit " + targetIndex + " " + change);
+ assertUndoSuccess(previousList);
+
+ //undo deleting a task from the middle of the list
+ targetIndex = currentList.length/2;
+ previousList = currentList;
+ commandBox.runCommand("delete " + targetIndex);
+ assertUndoSuccess(previousList);
+
+ //undo clearing list
+ previousList = currentList;
+ commandBox.runCommand("clear");
+ assertUndoSuccess(previousList);
+
+ //undo marking the middle task as done
+ previousList = currentList;
+ commandBox.runCommand("done " + targetIndex);
+ assertUndoSuccess(previousList);
+ }
+
+ /**
+ * Runs the undo command to undo the last change to the task list
+ */
+ private void assertUndoSuccess(final TestTask[] previousList) {
+ commandBox.runCommand("undo");
+
+ //confirm the list now contains all previous tasks except the deleted task
+ assertTrue(taskListPanel.isListMatching(previousList));
+
+ //confirm the result message is correct
+ assertResultMessage(String.format(MESSAGE_SUCCESS));
+ }
+
}
```
###### /src/test/java/seedu/gtd/testutil/TestUtil.java
diff --git a/libs/addressbooklevel4.md b/libs/addressbooklevel4.md
index 6743ab4432a1..75c99362d388 100644
--- a/libs/addressbooklevel4.md
+++ b/libs/addressbooklevel4.md
@@ -3,10 +3,11 @@
``` java
public static final String COMMAND_WORD = "find";
- public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all tasks whose names contain any of "
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all tasks whose name, date, address, tags and priority contain any of "
+ "the specified keywords (case-sensitive) and displays them as a list with index numbers.\n"
- + "Parameters: KEYWORD [MORE_KEYWORDS]...\n"
- + "Example: " + COMMAND_WORD + " alice bob charlie";
+ + "To search by one particular field type, use t/ for tags, a/ for address, d/ for duedate and p/ for priority.\n"
+ + "Parameters: [FIELDTYPE] KEYWORD [MORE_KEYWORDS]...\n"
+ + "Example: " + COMMAND_WORD + " cs2103, " + COMMAND_WORD + " d/today";
```
###### /src/main/java/seedu/gtd/logic/parser/Parser.java
@@ -30,19 +31,19 @@
// + "(?(?: t/[^/]+)*)"); // variable number of tags
private static final Pattern NAME_TASK_DATA_ARGS_FORMAT =
- Pattern.compile("(?[^/]+) (t|p|a|d|e)/.*");
+ Pattern.compile("(?[^/]+) (t|p|a|d|z)/.*");
private static final Pattern PRIORITY_TASK_DATA_ARGS_FORMAT =
- Pattern.compile(".* p/(?[^/]+) (t|a|d|e)/.*");
+ Pattern.compile(".* p/(?[^/]+) (t|a|d|z)/.*");
private static final Pattern ADDRESS_TASK_DATA_ARGS_FORMAT =
- Pattern.compile(".* a/(?[^/]+) (t|p|d|e)/.*");
+ Pattern.compile(".* a/(?[^/]+) (t|p|d|z)/.*");
private static final Pattern DUEDATE_TASK_DATA_ARGS_FORMAT =
- Pattern.compile(".* d/(?[^/]+) (t|a|p|e)/.*");
+ Pattern.compile(".* d/(?[^/]+) (t|a|p|z)/.*");
private static final Pattern TAGS_TASK_DATA_ARGS_FORMAT =
- Pattern.compile(".* t/(?[^/]+) (d|a|p|e)/.*");
+ Pattern.compile(".* t/(?[^/]+) (d|a|p|z)/.*");
private static final Pattern EDIT_DATA_ARGS_FORMAT =
Pattern.compile("(?\\S+)"
@@ -77,6 +78,9 @@
case DeleteCommand.COMMAND_WORD:
return prepareDelete(arguments);
+
+ case DoneCommand.COMMAND_WORD:
+ return prepareDone(arguments);
case ClearCommand.COMMAND_WORD:
return new ClearCommand();
@@ -85,13 +89,16 @@
return prepareFind(arguments);
case ListCommand.COMMAND_WORD:
- return new ListCommand();
+ return prepareList(arguments);
case ExitCommand.COMMAND_WORD:
return new ExitCommand();
case HelpCommand.COMMAND_WORD:
return prepareHelp(arguments);
+
+ case UndoCommand.COMMAND_WORD:
+ return new UndoCommand();
default:
return new IncorrectCommand(MESSAGE_UNKNOWN_COMMAND);
@@ -149,7 +156,7 @@
}
private String appendEnd(String args) {
- return args + " e/";
+ return args + " z/";
}
private String checkEmptyAndAddDefault(Matcher matcher, String groupName, String defaultValue) {
@@ -196,6 +203,18 @@
return new DeleteCommand(index.get());
}
+
+ private Command prepareDone(String args) {
+
+ Optional index = parseIndex(args);
+ System.out.println("index at preparedone:" + index.get());
+ if(!index.isPresent()){
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, DoneCommand.MESSAGE_USAGE));
+ }
+
+ return new DoneCommand(index.get());
+ }
/**
* Parses arguments in the context of the select task command.
@@ -238,6 +257,37 @@
* @return the prepared command
*/
private Command prepareFind(String args) {
+
+ // check if parameters are specified and pass specified field to FindCommand
+
+ String preprocessedArgs = " " + appendEnd(args.trim());
+ final Matcher addressMatcher = ADDRESS_TASK_DATA_ARGS_FORMAT.matcher(preprocessedArgs);
+ final Matcher priorityMatcher = PRIORITY_TASK_DATA_ARGS_FORMAT.matcher(preprocessedArgs);
+ final Matcher dueDateMatcher = DUEDATE_TASK_DATA_ARGS_FORMAT.matcher(preprocessedArgs);
+ final Matcher tagsMatcher = TAGS_TASK_DATA_ARGS_FORMAT.matcher(preprocessedArgs);
+
+ Set defaultSet = new HashSet();
+
+ if (addressMatcher.matches()) {
+ String addressToBeFound = addressMatcher.group("address");
+ return new FindCommand(addressToBeFound, defaultSet,"address");
+ }
+ if (priorityMatcher.matches()) {
+ String priorityToBeFound = priorityMatcher.group("priority");
+ return new FindCommand(priorityToBeFound, defaultSet, "priority");
+ }
+ if (dueDateMatcher.matches()) {
+ String dueDateToBeFound = dueDateMatcher.group("dueDate");
+ String parsedDueDateToBeFound = removeTimeOnDate(parseDueDate(dueDateToBeFound));
+ return new FindCommand(parsedDueDateToBeFound, defaultSet, "dueDate");
+ }
+ if (tagsMatcher.matches()) {
+ String tagsToBeFound = tagsMatcher.group("tagArguments");
+ return new FindCommand(tagsToBeFound, defaultSet,"tagArguments");
+ }
+
+ // free-form search by keywords
+
final Matcher matcher = KEYWORDS_ARGS_FORMAT.matcher(args.trim());
if (!matcher.matches()) {
return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
@@ -249,8 +299,16 @@
final Set keywordSet = new HashSet<>(Arrays.asList(splitKeywords));
final String keywords = matcher.group("keywords");
- return new FindCommand(keywords, keywordSet);
+ return new FindCommand(keywords, keywordSet, "nil");
}
+
+private Command prepareList(String args) {
+
+ // check if parameters are specified and pass specified field to FindCommand
+
+ //String preprocessedArgs = " " + appendEnd(args.trim());
+ return new ListCommand(args);
+}
/**
* Parses arguments in the context of the help command.
@@ -451,6 +509,7 @@ public class MainApp extends Application {
*/
public AddressBook(ReadOnlyAddressBook toBeCopied) {
this(toBeCopied.getUniqueTaskList(), toBeCopied.getUniqueTagList());
+ System.out.println("start with first method");
}
/**
@@ -458,6 +517,7 @@ public class MainApp extends Application {
*/
public AddressBook(UniqueTaskList tasks, UniqueTagList tags) {
resetData(tasks.getInternalList(), tags.getInternalList());
+ System.out.println("start with second method");
}
public static ReadOnlyAddressBook getEmptyAddressBook() {
@@ -534,6 +594,11 @@ public class MainApp extends Application {
throw new UniqueTaskList.TaskNotFoundException();
}
}
+
+ public void doneTask(int index, Task target) throws TaskNotFoundException {
+ System.out.println("in addressbook");
+ tasks.done(index, target);
+ }
//// tag-level operations
@@ -553,7 +618,7 @@ public class MainApp extends Application {
public List getTaskList() {
return Collections.unmodifiableList(tasks.getInternalList());
}
-
+
@Override
public List getTagList() {
return Collections.unmodifiableList(tags.getInternalList());
@@ -590,8 +655,9 @@ public class MainApp extends Application {
private static final Logger logger = LogsCenter.getLogger(ModelManager.class);
- private final AddressBook addressBook;
+ private AddressBook addressBook;
private final FilteredList filteredTasks;
+ private AddressBook previousAddressBook;
/**
* Initializes a ModelManager with the given AddressBook
@@ -606,6 +672,7 @@ public class MainApp extends Application {
addressBook = new AddressBook(src);
filteredTasks = new FilteredList<>(addressBook.getTasks());
+ previousAddressBook = new AddressBook(addressBook);
}
public ModelManager() {
@@ -615,14 +682,14 @@ public class MainApp extends Application {
public ModelManager(ReadOnlyAddressBook initialData, UserPrefs userPrefs) {
addressBook = new AddressBook(initialData);
filteredTasks = new FilteredList<>(addressBook.getTasks());
+ previousAddressBook = new AddressBook(addressBook);
}
- @Override
- public void resetData(ReadOnlyAddressBook newData) {
+ private void resetData(ReadOnlyAddressBook newData) {
addressBook.resetData(newData);
indicateAddressBookChanged();
}
-
+
@Override
public ReadOnlyAddressBook getAddressBook() {
return addressBook;
@@ -632,15 +699,35 @@ public class MainApp extends Application {
private void indicateAddressBookChanged() {
raise(new AddressBookChangedEvent(addressBook));
}
+
+ private void savePreviousAddressBook() {
+ previousAddressBook = new AddressBook(addressBook);
+ }
+
+ @Override
+ public void undoAddressBookChange() {
+ resetData(previousAddressBook);
+ }
@Override
public synchronized void deleteTask(ReadOnlyTask target) throws TaskNotFoundException {
+ savePreviousAddressBook();
addressBook.removeTask(target);
indicateAddressBookChanged();
}
-
+
+ @Override
+ public synchronized void doneTask(int targetIndex, Task task) throws TaskNotFoundException {
+ savePreviousAddressBook();
+ System.out.println("in model manager");
+ addressBook.doneTask(targetIndex, task);
+ updateFilteredListToShowAll();
+ indicateAddressBookChanged();
+ }
+
@Override
public synchronized void addTask(Task task) throws UniqueTaskList.DuplicateTaskException {
+ savePreviousAddressBook();
addressBook.addTask(task);
updateFilteredListToShowAll();
indicateAddressBookChanged();
@@ -658,7 +745,27 @@ public class MainApp extends Application {
@Override
public void updateFilteredListToShowAll() {
- filteredTasks.setPredicate(null);
+ updateFilteredListToShowAll(new PredicateExpression(new RemoveDoneQualifier()));
+ System.out.println("show all");
+ }
+
+ private void updateFilteredListToShowAll(Expression expression) {
+ filteredTasks.setPredicate(expression::satisfies);
+ }
+
+ @Override
+ public void updateFilteredListToShowRemoved() {
+ updateFilteredListToShowRemoved(new PredicateExpression(new DoneQualifier()));
+ System.out.println("show done list");
+ }
+
+ private void updateFilteredListToShowRemoved(Expression expression) {
+ filteredTasks.setPredicate(expression::satisfies);
+ }
+
+ @Override
+ public void updateFilteredTaskList(Set keywordSet) {
+ updateFilteredTaskList(new PredicateExpression(new NameQualifier(keywordSet)));
}
@Override
@@ -667,8 +774,8 @@ public class MainApp extends Application {
}
@Override
- public void updateFilteredTaskList(Set keywordSet) {
- updateFilteredTaskList(new PredicateExpression(new NameQualifier(keywordSet)));
+ public void updateFilteredTaskList(String keywords, String cmd) {
+ updateFilteredTaskList(new PredicateExpression(new otherFieldsQualifier(keywords, cmd)));
}
private void updateFilteredTaskList(Expression expression) {
@@ -715,10 +822,10 @@ public class MainApp extends Application {
@Override
public boolean run(ReadOnlyTask task) {
- return keywordSet.stream()
- .filter(keyword -> StringUtil.containsIgnoreCase(task.getName().fullName, keyword))
- .findAny()
- .isPresent();
+ return keywordSet.stream()
+ .filter(keyword -> StringUtil.containsIgnoreCase(task.getName().fullName, keyword))
+ .findAny()
+ .isPresent();
}
@Override
@@ -727,6 +834,64 @@ public class MainApp extends Application {
}
}
+ private class otherFieldsQualifier implements Qualifier {
+ protected String nameKeyWords;
+ protected String cmd;
+
+ otherFieldsQualifier(String keywords, String cmd) {
+ this.nameKeyWords = keywords;
+ this.cmd = cmd;
+ }
+
+ @Override
+ public boolean run(ReadOnlyTask task) {
+ if (cmd == "address") {
+ System.out.println("finding address..");
+ String address = task.getAddress().toString().toLowerCase();
+ boolean addressMatch = address.contains(nameKeyWords.toLowerCase());
+ return addressMatch;
+ } else if (cmd == "priority") {
+ System.out.println("finding priority..");
+ String priority = task.getPriority().toString();
+ boolean priorityMatch = priority.contains(nameKeyWords);
+ return priorityMatch;
+ } else if (cmd == "dueDate") {
+ System.out.println("finding dueDate..");
+ String dueDate = task.getDueDate().toString();
+ boolean dueDateMatch = dueDate.contains(nameKeyWords);
+ return dueDateMatch;
+ } else if (cmd == "tagArguments") {
+ System.out.println("finding tags.. ");
+ UniqueTagList tagsList = task.getTags();
+ boolean tagsMatch = tagsList.containSearch(nameKeyWords.toLowerCase());
+ return tagsMatch;
+ }
+
+ // cmd == "nil"
+
+ String taskFullNameLowerCase = task.getName().fullName.toLowerCase();
+ String priority = task.getPriority().toString();
+ String address = task.getAddress().toString().toLowerCase();
+ String dueDate = task.getDueDate().toString();
+ UniqueTagList tagsList = task.getTags();
+
+ boolean nameMatch = taskFullNameLowerCase.contains(nameKeyWords.toLowerCase());
+ boolean addressMatch = address.contains(nameKeyWords.toLowerCase());
+ boolean priorityMatch = priority.contains(nameKeyWords);
+ boolean dueDateMatch = dueDate.contains(nameKeyWords);
+ boolean tagsMatch = tagsList.containSearch(nameKeyWords.toLowerCase());
+ boolean eachWordMatch = false;
+
+ String[] eachWord = nameKeyWords.split(" ");
+ for (String word : eachWord) {
+ System.out.println("each: " + word);
+ eachWordMatch = eachWordMatch || taskFullNameLowerCase.contains(word.toLowerCase());
+ }
+
+ return eachWordMatch || nameMatch || addressMatch || priorityMatch || dueDateMatch || tagsMatch;
+ }
+ }
+
private class orderedNameQualifier extends NameQualifier implements Qualifier {
private String nameKeyWords;
@@ -738,14 +903,36 @@ public class MainApp extends Application {
@Override
public boolean run(ReadOnlyTask task) {
String taskFullNameLowerCase = task.getName().fullName.toLowerCase();
- boolean orderMatch = taskFullNameLowerCase.contains(nameKeyWords.toLowerCase());
+ boolean nameMatch = taskFullNameLowerCase.contains(nameKeyWords.toLowerCase());
boolean eachWordMatch = keywordSet.stream()
.filter(keyword -> StringUtil.containsIgnoreCase(task.getName().fullName, keyword))
.findAny()
.isPresent();
-
- return eachWordMatch && orderMatch;
+ return eachWordMatch && nameMatch;
+ }
+ }
+
+ // to check and return a list of tasks that are already done
+ private class DoneQualifier implements Qualifier {
+
+ DoneQualifier() {}
+
+ @Override
+ public boolean run(ReadOnlyTask task) {
+ return task.getisDone();
+ }
+ }
+
+ // default display tasks that are not yet done
+ private class RemoveDoneQualifier implements Qualifier {
+
+ RemoveDoneQualifier() {}
+
+ @Override
+ public boolean run(ReadOnlyTask task) {
+ System.out.println(task.getName());
+ return !task.getisDone();
}
}
}
@@ -1088,7 +1275,7 @@ public class MainApp extends Application {
List taskList = helper.generateTaskList(2);
// set AB state to 2 tasks
- model.resetData(new AddressBook());
+ model.clearTaskList();
for (Task p : taskList) {
model.addTask(p);
}
diff --git a/src/main/java/seedu/gtd/commons/core/ComponentManager.java b/src/main/java/seedu/gtd/commons/core/ComponentManager.java
index b060116d9461..1b0561e20d5c 100644
--- a/src/main/java/seedu/gtd/commons/core/ComponentManager.java
+++ b/src/main/java/seedu/gtd/commons/core/ComponentManager.java
@@ -27,4 +27,9 @@ public ComponentManager(EventsCenter eventsCenter) {
protected void raise(BaseEvent event){
eventsCenter.post(event);
}
+
+ public void updateFilteredListToShowRemoved() {
+ // TODO Auto-generated method stub
+
+ }
}
diff --git a/src/main/java/seedu/gtd/logic/commands/ClearCommand.java b/src/main/java/seedu/gtd/logic/commands/ClearCommand.java
index 91ec6ad13767..7689aeadc00c 100644
--- a/src/main/java/seedu/gtd/logic/commands/ClearCommand.java
+++ b/src/main/java/seedu/gtd/logic/commands/ClearCommand.java
@@ -17,7 +17,7 @@ public ClearCommand() {}
@Override
public CommandResult execute() {
assert model != null;
- model.resetData(AddressBook.getEmptyAddressBook());
+ model.clearTaskList();
return new CommandResult(MESSAGE_SUCCESS);
}
}
diff --git a/src/main/java/seedu/gtd/logic/commands/DoneCommand.java b/src/main/java/seedu/gtd/logic/commands/DoneCommand.java
new file mode 100644
index 000000000000..03fc01b26c9c
--- /dev/null
+++ b/src/main/java/seedu/gtd/logic/commands/DoneCommand.java
@@ -0,0 +1,70 @@
+package seedu.gtd.logic.commands;
+
+import seedu.gtd.commons.core.Messages;
+import seedu.gtd.commons.core.UnmodifiableObservableList;
+import seedu.gtd.commons.exceptions.IllegalValueException;
+import seedu.gtd.model.task.ReadOnlyTask;
+import seedu.gtd.model.task.Task;
+import seedu.gtd.model.task.UniqueTaskList.TaskNotFoundException;
+
+/**
+ * Mark a task as done, identified using it's last displayed index from the address book.
+ */
+public class DoneCommand extends Command {
+
+ public static final String COMMAND_WORD = "done";
+
+ public static final String MESSAGE_USAGE = COMMAND_WORD
+ + ": Marks a task as done, by the index number used in the last task listing.\n"
+ + "Parameters: INDEX (must be a positive integer)\n"
+ + "Example: " + COMMAND_WORD + " 1";
+
+ public static final String MESSAGE_DONE_TASK_SUCCESS = "Done Task: %1$s";
+
+ public final int targetIndex;
+
+ public DoneCommand(int targetIndex) {
+ this.targetIndex = targetIndex;
+ }
+
+
+ @Override
+ public CommandResult execute() {
+
+ UnmodifiableObservableList lastShownList = model.getFilteredTaskList();
+
+ if (lastShownList.size() < targetIndex) {
+ indicateAttemptToExecuteIncorrectCommand();
+ return new CommandResult(Messages.MESSAGE_INVALID_TASK_DISPLAYED_INDEX);
+ }
+
+ ReadOnlyTask toEdit = lastShownList.get(targetIndex-1);
+ Task taskToUpdate = new Task(toEdit);
+
+ try {
+ taskToUpdate = updateTask(taskToUpdate, "done", "true");
+ System.out.println("IS IT DONE? " + taskToUpdate.getisDone());
+ } catch (IllegalValueException ive) {
+ return new CommandResult(ive.getMessage());
+ }
+
+ assert model != null;
+ try {
+ System.out.println("in donecommand.java");
+ System.out.println(taskToUpdate.getName() + " " + taskToUpdate.getisDone());
+ System.out.println("index at donecommand:" + targetIndex);
+ model.doneTask(targetIndex-1, taskToUpdate);
+
+ } catch (TaskNotFoundException e) {
+ assert false : "The target task cannot be missing";
+ }
+ return new CommandResult(String.format(MESSAGE_DONE_TASK_SUCCESS, taskToUpdate));
+
+ }
+
+ private Task updateTask(Task taskToUpdate, String detailType, String newDetail) throws IllegalValueException {
+ taskToUpdate.edit(detailType, newDetail);
+ return taskToUpdate;
+ }
+
+}
diff --git a/src/main/java/seedu/gtd/logic/commands/ListCommand.java b/src/main/java/seedu/gtd/logic/commands/ListCommand.java
index c887f37c3849..62a8fdd111ab 100644
--- a/src/main/java/seedu/gtd/logic/commands/ListCommand.java
+++ b/src/main/java/seedu/gtd/logic/commands/ListCommand.java
@@ -9,12 +9,21 @@ public class ListCommand extends Command {
public static final String COMMAND_WORD = "list";
public static final String MESSAGE_USAGE = COMMAND_WORD + ": Shows a list of all tasks in the task list.";
public static final String MESSAGE_SUCCESS = "Listed all tasks";
-
- public ListCommand() {}
+ private String arg;
+
+ public ListCommand(String arg) {
+ this.arg = arg;
+ }
@Override
public CommandResult execute() {
- model.updateFilteredListToShowAll();
+ System.out.println("args:" + arg);
+ if (arg.equals(" done")) {
+ System.out.println("in done");
+ model.updateFilteredListToShowRemoved();
+ } else {
+ model.updateFilteredListToShowAll();
+ }
return new CommandResult(MESSAGE_SUCCESS);
}
}
diff --git a/src/main/java/seedu/gtd/logic/commands/UndoCommand.java b/src/main/java/seedu/gtd/logic/commands/UndoCommand.java
new file mode 100644
index 000000000000..48cb8fe8b1d6
--- /dev/null
+++ b/src/main/java/seedu/gtd/logic/commands/UndoCommand.java
@@ -0,0 +1,23 @@
+//@@author A0146130W
+
+package seedu.gtd.logic.commands;
+
+/**
+ * Deletes a task identified using it's last displayed index from the address book.
+ */
+public class UndoCommand extends Command {
+
+ public static final String COMMAND_WORD = "undo";
+ public static final String MESSAGE_USAGE = COMMAND_WORD + ": Un-does the most recent modification of the task list.";
+ public static final String MESSAGE_SUCCESS = "Undo change";
+ public static final String MESSAGE_UNDO_LIMIT_REACHED = "Undo limit reached!";
+
+ public UndoCommand() {}
+
+ @Override
+ public CommandResult execute() {
+ if(model.undoAddressBookChange()) return new CommandResult(MESSAGE_SUCCESS);
+ else return new CommandResult(MESSAGE_UNDO_LIMIT_REACHED);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/seedu/gtd/logic/parser/Parser.java b/src/main/java/seedu/gtd/logic/parser/Parser.java
index df231533d940..ef24c3577d7d 100644
--- a/src/main/java/seedu/gtd/logic/parser/Parser.java
+++ b/src/main/java/seedu/gtd/logic/parser/Parser.java
@@ -35,19 +35,19 @@ public class Parser {
// + "(?(?: t/[^/]+)*)"); // variable number of tags
private static final Pattern NAME_TASK_DATA_ARGS_FORMAT =
- Pattern.compile("(?[^/]+) (t|p|a|d|e)/.*");
+ Pattern.compile("(?[^/]+) (t|p|a|d|z)/.*");
private static final Pattern PRIORITY_TASK_DATA_ARGS_FORMAT =
- Pattern.compile(".* p/(?[^/]+) (t|a|d|e)/.*");
+ Pattern.compile(".* p/(?[^/]+) (t|a|d|z)/.*");
private static final Pattern ADDRESS_TASK_DATA_ARGS_FORMAT =
- Pattern.compile(".* a/(?[^/]+) (t|p|d|e)/.*");
+ Pattern.compile(".* a/(?[^/]+) (t|p|d|z)/.*");
private static final Pattern DUEDATE_TASK_DATA_ARGS_FORMAT =
- Pattern.compile(".* d/(?[^/]+) (t|a|p|e)/.*");
+ Pattern.compile(".* d/(?[^/]+) (t|a|p|z)/.*");
private static final Pattern TAGS_TASK_DATA_ARGS_FORMAT =
- Pattern.compile(".* t/(?[^/]+) (d|a|p|e)/.*");
+ Pattern.compile(".* t/(?[^/]+) (d|a|p|z)/.*");
private static final Pattern EDIT_DATA_ARGS_FORMAT =
Pattern.compile("(?\\S+)"
@@ -82,6 +82,9 @@ public Command parseCommand(String userInput) {
case DeleteCommand.COMMAND_WORD:
return prepareDelete(arguments);
+
+ case DoneCommand.COMMAND_WORD:
+ return prepareDone(arguments);
case ClearCommand.COMMAND_WORD:
return new ClearCommand();
@@ -90,13 +93,16 @@ public Command parseCommand(String userInput) {
return prepareFind(arguments);
case ListCommand.COMMAND_WORD:
- return new ListCommand();
+ return prepareList(arguments);
case ExitCommand.COMMAND_WORD:
return new ExitCommand();
case HelpCommand.COMMAND_WORD:
return prepareHelp(arguments);
+
+ case UndoCommand.COMMAND_WORD:
+ return new UndoCommand();
default:
return new IncorrectCommand(MESSAGE_UNKNOWN_COMMAND);
@@ -154,7 +160,7 @@ private Command prepareAdd(String args){
}
private String appendEnd(String args) {
- return args + " e/";
+ return args + " z/";
}
private String checkEmptyAndAddDefault(Matcher matcher, String groupName, String defaultValue) {
@@ -260,6 +266,18 @@ private Command prepareDelete(String args) {
return new DeleteCommand(index.get());
}
+
+ private Command prepareDone(String args) {
+
+ Optional index = parseIndex(args);
+ System.out.println("index at preparedone:" + index.get());
+ if(!index.isPresent()){
+ return new IncorrectCommand(
+ String.format(MESSAGE_INVALID_COMMAND_FORMAT, DoneCommand.MESSAGE_USAGE));
+ }
+
+ return new DoneCommand(index.get());
+ }
/**
* Parses arguments in the context of the select task command.
@@ -346,6 +364,14 @@ private Command prepareFind(String args) {
final String keywords = matcher.group("keywords");
return new FindCommand(keywords, keywordSet, "nil");
}
+
+private Command prepareList(String args) {
+
+ // check if parameters are specified and pass specified field to FindCommand
+
+ //String preprocessedArgs = " " + appendEnd(args.trim());
+ return new ListCommand(args);
+}
/**
* Parses arguments in the context of the help command.
diff --git a/src/main/java/seedu/gtd/model/AddressBook.java b/src/main/java/seedu/gtd/model/AddressBook.java
index 7a3870ad77fa..0679722d8926 100644
--- a/src/main/java/seedu/gtd/model/AddressBook.java
+++ b/src/main/java/seedu/gtd/model/AddressBook.java
@@ -6,6 +6,7 @@
import seedu.gtd.model.task.ReadOnlyTask;
import seedu.gtd.model.task.Task;
import seedu.gtd.model.task.UniqueTaskList;
+import seedu.gtd.model.task.UniqueTaskList.TaskNotFoundException;
import java.util.*;
import java.util.stream.Collectors;
@@ -32,6 +33,7 @@ public AddressBook() {}
*/
public AddressBook(ReadOnlyAddressBook toBeCopied) {
this(toBeCopied.getUniqueTaskList(), toBeCopied.getUniqueTagList());
+ System.out.println("start with first method");
}
/**
@@ -39,6 +41,7 @@ public AddressBook(ReadOnlyAddressBook toBeCopied) {
*/
public AddressBook(UniqueTaskList tasks, UniqueTagList tags) {
resetData(tasks.getInternalList(), tags.getInternalList());
+ System.out.println("start with second method");
}
public static ReadOnlyAddressBook getEmptyAddressBook() {
@@ -126,6 +129,11 @@ public boolean removeTask(ReadOnlyTask key) throws UniqueTaskList.TaskNotFoundEx
throw new UniqueTaskList.TaskNotFoundException();
}
}
+
+ public void doneTask(int index, Task target) throws TaskNotFoundException {
+ System.out.println("in addressbook");
+ tasks.done(index, target);
+ }
//// tag-level operations
@@ -145,7 +153,7 @@ public String toString() {
public List getTaskList() {
return Collections.unmodifiableList(tasks.getInternalList());
}
-
+
@Override
public List getTagList() {
return Collections.unmodifiableList(tags.getInternalList());
diff --git a/src/main/java/seedu/gtd/model/Model.java b/src/main/java/seedu/gtd/model/Model.java
index 543e8bc4c1bc..80d2d050f0d0 100644
--- a/src/main/java/seedu/gtd/model/Model.java
+++ b/src/main/java/seedu/gtd/model/Model.java
@@ -11,14 +11,14 @@
* The API of the Model component.
*/
public interface Model {
- /** Clears existing backing model and replaces with the provided new data. */
- void resetData(ReadOnlyAddressBook newData);
-
/** Returns the AddressBook */
ReadOnlyAddressBook getAddressBook();
/** Deletes the given task. */
void deleteTask(ReadOnlyTask target) throws UniqueTaskList.TaskNotFoundException;
+
+ /** Marks the given task as done. */
+ void doneTask(int targetIndex, Task target) throws UniqueTaskList.TaskNotFoundException;
/** Adds the given task */
void addTask(Task task) throws UniqueTaskList.DuplicateTaskException;
@@ -31,6 +31,9 @@ public interface Model {
/** Updates the filter of the filtered task list to show all tasks */
void updateFilteredListToShowAll();
+
+ /** Updates the filter of the filtered task list to show all tasks */
+ void updateFilteredListToShowRemoved();
/** Updates the filter of the filtered task list to filter by the given exact phrase
* @param keywordSet */
@@ -41,4 +44,11 @@ public interface Model {
/** Updates the filter of the filtered task list to filter by the right parameter*/
void updateFilteredTaskList(String keywords, String cmd);
+
+ /** Un-does a change to the AddressBook
+ * @return true if undo command was effective or false if undo is not possible, i.e the stack of previous task list states is empty */
+ boolean undoAddressBookChange();
+
+ /** Clears all tasks */
+ void clearTaskList();
}
diff --git a/src/main/java/seedu/gtd/model/ModelManager.java b/src/main/java/seedu/gtd/model/ModelManager.java
index 7262ebfaf20a..c9b07f935eea 100644
--- a/src/main/java/seedu/gtd/model/ModelManager.java
+++ b/src/main/java/seedu/gtd/model/ModelManager.java
@@ -15,6 +15,7 @@
import java.util.Arrays;
import java.util.Set;
+import java.util.Stack;
import java.util.logging.Logger;
/**
@@ -26,8 +27,9 @@ public class ModelManager extends ComponentManager implements Model {
private static final Logger logger = LogsCenter.getLogger(ModelManager.class);
- private final AddressBook addressBook;
+ private AddressBook addressBook;
private final FilteredList filteredTasks;
+ private Stack previousAddressBook;
/**
* Initializes a ModelManager with the given AddressBook
@@ -42,6 +44,8 @@ public ModelManager(AddressBook src, UserPrefs userPrefs) {
addressBook = new AddressBook(src);
filteredTasks = new FilteredList<>(addressBook.getTasks());
+ previousAddressBook = new Stack();
+ previousAddressBook.push(new AddressBook(addressBook));
}
public ModelManager() {
@@ -51,14 +55,15 @@ public ModelManager() {
public ModelManager(ReadOnlyAddressBook initialData, UserPrefs userPrefs) {
addressBook = new AddressBook(initialData);
filteredTasks = new FilteredList<>(addressBook.getTasks());
+ previousAddressBook = new Stack();
+ previousAddressBook.push(new AddressBook(addressBook));
}
- @Override
- public void resetData(ReadOnlyAddressBook newData) {
+ private void resetData(ReadOnlyAddressBook newData) {
addressBook.resetData(newData);
indicateAddressBookChanged();
}
-
+
@Override
public ReadOnlyAddressBook getAddressBook() {
return addressBook;
@@ -68,15 +73,41 @@ public ReadOnlyAddressBook getAddressBook() {
private void indicateAddressBookChanged() {
raise(new AddressBookChangedEvent(addressBook));
}
+
+ private void savePreviousAddressBook() {
+ previousAddressBook.push(new AddressBook(addressBook));
+ }
+
+ @Override
+ public boolean undoAddressBookChange() {
+ if(previousAddressBook.isEmpty()) {
+ return false;
+ }
+ else{
+ resetData(previousAddressBook.pop());
+ return true;
+ }
+ }
@Override
public synchronized void deleteTask(ReadOnlyTask target) throws TaskNotFoundException {
+ savePreviousAddressBook();
addressBook.removeTask(target);
indicateAddressBookChanged();
}
-
+
+ @Override
+ public synchronized void doneTask(int targetIndex, Task task) throws TaskNotFoundException {
+ savePreviousAddressBook();
+ System.out.println("in model manager");
+ addressBook.doneTask(targetIndex, task);
+ updateFilteredListToShowAll();
+ indicateAddressBookChanged();
+ }
+
@Override
public synchronized void addTask(Task task) throws UniqueTaskList.DuplicateTaskException {
+ savePreviousAddressBook();
addressBook.addTask(task);
updateFilteredListToShowAll();
indicateAddressBookChanged();
@@ -85,11 +116,19 @@ public synchronized void addTask(Task task) throws UniqueTaskList.DuplicateTaskE
//@@author A0146130W
@Override
public synchronized void editTask(int targetIndex, Task task) throws TaskNotFoundException {
+ savePreviousAddressBook();
+ System.out.println("editing task..");
addressBook.editTask(targetIndex, task);
updateFilteredListToShowAll();
indicateAddressBookChanged();
}
+ @Override
+ public void clearTaskList() {
+ savePreviousAddressBook();
+ resetData(AddressBook.getEmptyAddressBook());
+ }
+
//@@author addressbook-level4
//=========== Filtered Task List Accessors ===============================================================
@@ -100,7 +139,22 @@ public UnmodifiableObservableList getFilteredTaskList() {
@Override
public void updateFilteredListToShowAll() {
- filteredTasks.setPredicate(null);
+ updateFilteredListToShowAll(new PredicateExpression(new RemoveDoneQualifier()));
+ System.out.println("show all");
+ }
+
+ private void updateFilteredListToShowAll(Expression expression) {
+ filteredTasks.setPredicate(expression::satisfies);
+ }
+
+ @Override
+ public void updateFilteredListToShowRemoved() {
+ updateFilteredListToShowRemoved(new PredicateExpression(new DoneQualifier()));
+ System.out.println("show done list");
+ }
+
+ private void updateFilteredListToShowRemoved(Expression expression) {
+ filteredTasks.setPredicate(expression::satisfies);
}
@Override
@@ -252,4 +306,27 @@ public boolean run(ReadOnlyTask task) {
return eachWordMatch && nameMatch;
}
}
+
+ // to check and return a list of tasks that are already done
+ private class DoneQualifier implements Qualifier {
+
+ DoneQualifier() {}
+
+ @Override
+ public boolean run(ReadOnlyTask task) {
+ return task.getisDone();
+ }
+ }
+
+ // default display tasks that are not yet done
+ private class RemoveDoneQualifier implements Qualifier {
+
+ RemoveDoneQualifier() {}
+
+ @Override
+ public boolean run(ReadOnlyTask task) {
+ System.out.println(task.getName());
+ return !task.getisDone();
+ }
+ }
}
diff --git a/src/main/java/seedu/gtd/model/task/ReadOnlyTask.java b/src/main/java/seedu/gtd/model/task/ReadOnlyTask.java
index 90a2a3b5aba6..6f18661b506c 100644
--- a/src/main/java/seedu/gtd/model/task/ReadOnlyTask.java
+++ b/src/main/java/seedu/gtd/model/task/ReadOnlyTask.java
@@ -12,6 +12,7 @@ public interface ReadOnlyTask {
DueDate getDueDate();
Address getAddress();
Priority getPriority();
+ boolean getisDone();
/**
* The returned TagList is a deep copy of the internal TagList,
@@ -55,4 +56,5 @@ default String tagsString() {
return buffer.substring(0, buffer.length() - separator.length());
}
}
+
}
diff --git a/src/main/java/seedu/gtd/model/task/Task.java b/src/main/java/seedu/gtd/model/task/Task.java
index 97b0121d0c64..c0a6dfc0e68f 100644
--- a/src/main/java/seedu/gtd/model/task/Task.java
+++ b/src/main/java/seedu/gtd/model/task/Task.java
@@ -15,14 +15,27 @@ public class Task implements ReadOnlyTask {
private Name name;
private DueDate dueDate;
+ private DueDate startDate;
+ private DueDate endDate;
private Address address;
private Priority priority;
+ private boolean isDone;
private UniqueTagList tags;
/**
* Every field must be present and not null.
*/
+ public Task(Name name, DueDate dueDate, Address address, Priority priority, UniqueTagList tags, boolean isDone) {
+ assert !CollectionUtil.isAnyNull(name, dueDate, address, priority, tags);
+ this.name = name;
+ this.dueDate = dueDate;
+ this.address = address;
+ this.priority = priority;
+ this.tags = new UniqueTagList(tags); // protect internal tags from changes in the arg list
+ this.isDone = isDone;
+ }
+
public Task(Name name, DueDate dueDate, Address address, Priority priority, UniqueTagList tags) {
assert !CollectionUtil.isAnyNull(name, dueDate, address, priority, tags);
this.name = name;
@@ -30,6 +43,7 @@ public Task(Name name, DueDate dueDate, Address address, Priority priority, Uniq
this.address = address;
this.priority = priority;
this.tags = new UniqueTagList(tags); // protect internal tags from changes in the arg list
+ this.isDone = false;
}
/**
@@ -58,6 +72,11 @@ public Address getAddress() {
public Priority getPriority() {
return priority;
}
+
+ @Override
+ public boolean getisDone() {
+ return isDone;
+ }
@Override
public UniqueTagList getTags() {
@@ -80,12 +99,17 @@ public void setPriority(Priority priority) {
this.priority = priority;
}
+ public void setisDone(boolean isdone) {
+ this.isDone = isdone;
+ }
+
public void edit(String detailType, String newDetail) throws IllegalValueException {
switch(detailType) {
case "dueDate": setDueDate(new DueDate(newDetail)); break;
case "address": setAddress(new Address(newDetail)); break;
case "priority": setPriority(new Priority(newDetail)); break;
+ case "done": setisDone(true); break;
default: setName(new Name(newDetail));
}
}
diff --git a/src/main/java/seedu/gtd/model/task/UniqueTaskList.java b/src/main/java/seedu/gtd/model/task/UniqueTaskList.java
index f0e977f275ee..76645f087dc7 100644
--- a/src/main/java/seedu/gtd/model/task/UniqueTaskList.java
+++ b/src/main/java/seedu/gtd/model/task/UniqueTaskList.java
@@ -74,6 +74,18 @@ public void edit(int targetIndex, Task toEdit) throws TaskNotFoundException {
internalList.set(targetIndex, toEdit);
}
+ public void done(int targetIndex, Task taskdone) throws TaskNotFoundException {
+ System.out.println("in uniquetasklist");
+ System.out.println(taskdone.getName() + " " + taskdone.getisDone());
+ System.out.println("index at final:" + targetIndex);
+ assert taskdone != null;
+ if (invalidIndex(targetIndex)) {
+ throw new TaskNotFoundException();
+ }
+ System.out.println("marked done in model");
+ internalList.set(targetIndex, taskdone);
+ }
+
private boolean invalidIndex(int i) {
if(i < 0 || i >= internalList.size()) return true;
return false;
diff --git a/src/main/java/seedu/gtd/storage/XmlAdaptedTask.java b/src/main/java/seedu/gtd/storage/XmlAdaptedTask.java
index 48117b44e48e..9c041c345ee5 100644
--- a/src/main/java/seedu/gtd/storage/XmlAdaptedTask.java
+++ b/src/main/java/seedu/gtd/storage/XmlAdaptedTask.java
@@ -23,6 +23,8 @@ public class XmlAdaptedTask {
private String address;
@XmlElement(required = true)
private String priority;
+ @XmlElement(required = true)
+ private boolean isDone;
@XmlElement
private List tagged = new ArrayList<>();
@@ -43,6 +45,7 @@ public XmlAdaptedTask(ReadOnlyTask source) {
dueDate = source.getDueDate().value;
address = source.getAddress().value;
priority = source.getPriority().value;
+ isDone = source.getisDone();
tagged = new ArrayList<>();
for (Tag tag : source.getTags()) {
tagged.add(new XmlAdaptedTag(tag));
@@ -63,7 +66,8 @@ public Task toModelType() throws IllegalValueException {
final DueDate dueDate = new DueDate(this.dueDate);
final Address address = new Address(this.address);
final Priority priority = new Priority(this.priority);
+ final boolean isDone = this.isDone;
final UniqueTagList tags = new UniqueTagList(taskTags);
- return new Task(name, dueDate, address, priority, tags);
+ return new Task(name, dueDate, address, priority, tags, isDone);
}
}
diff --git a/src/test/java/guitests/EditCommandTest.java b/src/test/java/guitests/EditCommandTest.java
index f2eb71b15f29..bf16e9083dad 100644
--- a/src/test/java/guitests/EditCommandTest.java
+++ b/src/test/java/guitests/EditCommandTest.java
@@ -45,9 +45,9 @@ public void edit() {
}
/**
- * Runs the delete command to delete the task at specified index and confirms the result is correct.
- * @param targetIndexOneIndexed e.g. to delete the first task in the list, 1 should be given as the target index.
- * @param currentList A copy of the current list of tasks (before deletion).
+ * Runs the edit command to edit the task at specified index and confirms the result is correct.
+ * @param targetIndexOneIndexed e.g. to edit the first task in the list, 1 should be given as the target index.
+ * @param currentList A copy of the current list of tasks (before editing).
*/
private void assertEditSuccess(int targetIndexOneIndexed, String change, final TestTask[] currentList) {
TestTask taskToEdit = currentList[targetIndexOneIndexed-1]; //-1 because array uses zero indexing
diff --git a/src/test/java/guitests/UndoCommandTest.java b/src/test/java/guitests/UndoCommandTest.java
new file mode 100644
index 000000000000..2e691df10c31
--- /dev/null
+++ b/src/test/java/guitests/UndoCommandTest.java
@@ -0,0 +1,93 @@
+//@@author A0146130W
+
+package guitests;
+
+import org.junit.Test;
+
+import seedu.gtd.testutil.TestTask;
+
+import static org.junit.Assert.assertTrue;
+import static seedu.gtd.logic.commands.UndoCommand.MESSAGE_SUCCESS;
+import static seedu.gtd.logic.commands.UndoCommand.MESSAGE_UNDO_LIMIT_REACHED;
+
+import java.util.Stack;;
+
+public class UndoCommandTest extends AddressBookGuiTest {
+
+ @Test
+ public void undo() {
+
+ //undo the addition of the first task
+ TestTask[] currentList = td.getTypicalTasks();
+ Stack previousList = new Stack();
+ previousList.push(currentList);
+ commandBox.runCommand(td.george.getAddCommand());
+ assertUndoSuccess(previousList.pop());
+
+ //undo editing the dueDate of the last task in the list
+ int targetIndex = currentList.length;
+ String change = "d/2";
+ previousList.push(currentList);
+ commandBox.runCommand("edit " + targetIndex + " " + change);
+ assertUndoSuccess(previousList.pop());
+
+ //undo deleting a task from the middle of the list
+ targetIndex = currentList.length/2;
+ previousList.push(currentList);
+ commandBox.runCommand("delete " + targetIndex);
+ assertUndoSuccess(previousList.pop());
+
+ //undo clearing list
+ previousList.push(currentList);
+ commandBox.runCommand("clear");
+ assertUndoSuccess(previousList.pop());
+
+ //undo marking the middle task as done
+ previousList.push(currentList);
+ commandBox.runCommand("done " + targetIndex);
+ assertUndoSuccess(previousList.pop());
+
+ /*
+ //undo multiple times
+ previousList.push(currentList);
+ commandBox.runCommand("edit " + targetIndex + " " + change);
+ previousList.push(currentList);
+ commandBox.runCommand(td.george.getAddCommand());
+ previousList.push(currentList);
+ commandBox.runCommand("delete " + targetIndex);
+ previousList.push(currentList);
+ commandBox.runCommand("done " + targetIndex);
+ previousList.push(currentList);
+ commandBox.runCommand("clear");
+ assertMultipleUndoSuccess(previousList);
+ */
+ }
+
+ /**
+ * Runs the undo command to undo the last change to the task list
+ */
+ private void assertUndoSuccess(final TestTask[] previousList) {
+ commandBox.runCommand("undo");
+
+ //confirm the list now contains all previous tasks except the deleted task
+ assertTrue(taskListPanel.isListMatching(previousList));
+
+ //confirm the result message is correct
+ assertResultMessage(String.format(MESSAGE_SUCCESS));
+ }
+
+ private void assertMultipleUndoSuccess(final Stack previousList) {
+
+ //run undo multiple times and verify list each time
+ for(int i=1; i < previousList.size(); i++) {
+ commandBox.runCommand("undo");
+ assertTrue(taskListPanel.isListMatching(previousList.pop()));
+ assertResultMessage(String.format(MESSAGE_SUCCESS));
+ }
+
+ //verify that the undo limit message is shown when undo limit is reached
+ commandBox.runCommand("undo");
+ assertResultMessage(String.format(MESSAGE_UNDO_LIMIT_REACHED));
+ }
+
+}
diff --git a/src/test/java/seedu/gtd/logic/LogicManagerTest.java b/src/test/java/seedu/gtd/logic/LogicManagerTest.java
index 71889d47fe0c..57d476796a59 100644
--- a/src/test/java/seedu/gtd/logic/LogicManagerTest.java
+++ b/src/test/java/seedu/gtd/logic/LogicManagerTest.java
@@ -303,7 +303,7 @@ private void assertIndexNotFoundBehaviorForCommand(String commandWord) throws Ex
List taskList = helper.generateTaskList(2);
// set AB state to 2 tasks
- model.resetData(new AddressBook());
+ model.clearTaskList();
for (Task p : taskList) {
model.addTask(p);
}
diff --git a/src/test/java/seedu/gtd/testutil/TestTask.java b/src/test/java/seedu/gtd/testutil/TestTask.java
index a983ef564eff..2736b4090271 100644
--- a/src/test/java/seedu/gtd/testutil/TestTask.java
+++ b/src/test/java/seedu/gtd/testutil/TestTask.java
@@ -13,6 +13,7 @@ public class TestTask implements ReadOnlyTask {
private Address address;
private Priority priority;
private UniqueTagList tags;
+ private boolean isDone;
public TestTask() {
tags = new UniqueTagList();
@@ -23,6 +24,7 @@ public TestTask(Name name, DueDate dueDate, Address address, Priority priority,
this.dueDate = dueDate;
this.address = address;
this.priority = priority;
+ this.isDone = false;
this.tags = new UniqueTagList(tags); // protect internal tags from changes in the arg list
}
@@ -51,6 +53,11 @@ public Name getName() {
public DueDate getDueDate() {
return dueDate;
}
+
+ @Override
+ public boolean getisDone() {
+ return isDone;
+ }
@Override
public Address getAddress() {