From 44b296d3f50599f001b0165eba05dcebd688c9d7 Mon Sep 17 00:00:00 2001 From: tessa_voon Date: Wed, 2 Nov 2016 02:44:21 +0800 Subject: [PATCH 1/8] create done command and edit list command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit currently non-persistent marking of done as I’m still trying to figure out how to retrieve tasks from XML with isDone attribute. list now takes in ‘done’ as in ‘list done’ to show the list of tasks that are done. --- .../gtd/commons/core/ComponentManager.java | 5 ++ .../seedu/gtd/logic/commands/DoneCommand.java | 70 +++++++++++++++++++ .../seedu/gtd/logic/commands/ListCommand.java | 15 +++- .../java/seedu/gtd/logic/parser/Parser.java | 37 ++++++++-- .../java/seedu/gtd/model/AddressBook.java | 10 ++- src/main/java/seedu/gtd/model/Model.java | 6 ++ .../java/seedu/gtd/model/ModelManager.java | 50 ++++++++++++- .../seedu/gtd/model/task/ReadOnlyTask.java | 2 + src/main/java/seedu/gtd/model/task/Task.java | 24 +++++++ .../seedu/gtd/model/task/UniqueTaskList.java | 12 ++++ .../seedu/gtd/storage/XmlAdaptedTask.java | 6 +- .../java/seedu/gtd/testutil/TestTask.java | 7 ++ 12 files changed, 231 insertions(+), 13 deletions(-) create mode 100644 src/main/java/seedu/gtd/logic/commands/DoneCommand.java 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/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/parser/Parser.java b/src/main/java/seedu/gtd/logic/parser/Parser.java index df231533d940..7e319b69d218 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,7 +93,7 @@ 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(); @@ -154,7 +157,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 +263,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 +361,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..53128f1b1242 100644 --- a/src/main/java/seedu/gtd/model/Model.java +++ b/src/main/java/seedu/gtd/model/Model.java @@ -19,6 +19,9 @@ public interface Model { /** 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 +34,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 */ diff --git a/src/main/java/seedu/gtd/model/ModelManager.java b/src/main/java/seedu/gtd/model/ModelManager.java index 7262ebfaf20a..a0f9036fd1ad 100644 --- a/src/main/java/seedu/gtd/model/ModelManager.java +++ b/src/main/java/seedu/gtd/model/ModelManager.java @@ -74,6 +74,15 @@ public synchronized void deleteTask(ReadOnlyTask target) throws TaskNotFoundExce addressBook.removeTask(target); indicateAddressBookChanged(); } + + @Override + public synchronized void doneTask(int targetIndex, Task task) throws TaskNotFoundException { + System.out.println("in model manager"); + addressBook.doneTask(targetIndex, task); + updateFilteredListToShowAll(); + indicateAddressBookChanged(); + } + @Override public synchronized void addTask(Task task) throws UniqueTaskList.DuplicateTaskException { @@ -85,6 +94,7 @@ public synchronized void addTask(Task task) throws UniqueTaskList.DuplicateTaskE //@@author A0146130W @Override public synchronized void editTask(int targetIndex, Task task) throws TaskNotFoundException { + System.out.println("editing task.."); addressBook.editTask(targetIndex, task); updateFilteredListToShowAll(); indicateAddressBookChanged(); @@ -100,7 +110,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 +277,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/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() { From 14d235fc0e1fe1fa626249195a3b358ab12641d7 Mon Sep 17 00:00:00 2001 From: ravishwetha Date: Wed, 2 Nov 2016 05:50:03 +0800 Subject: [PATCH 2/8] add undo command --- .../seedu/gtd/logic/commands/UndoCommand.java | 20 +++++++++++++++++++ .../java/seedu/gtd/logic/parser/Parser.java | 3 +++ src/main/java/seedu/gtd/model/Model.java | 3 +++ .../java/seedu/gtd/model/ModelManager.java | 19 ++++++++++++++++-- 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 src/main/java/seedu/gtd/logic/commands/UndoCommand.java 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..7597c7a7c0d7 --- /dev/null +++ b/src/main/java/seedu/gtd/logic/commands/UndoCommand.java @@ -0,0 +1,20 @@ +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); + } + +} \ 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 7e319b69d218..ef24c3577d7d 100644 --- a/src/main/java/seedu/gtd/logic/parser/Parser.java +++ b/src/main/java/seedu/gtd/logic/parser/Parser.java @@ -100,6 +100,9 @@ public Command parseCommand(String userInput) { case HelpCommand.COMMAND_WORD: return prepareHelp(arguments); + + case UndoCommand.COMMAND_WORD: + return new UndoCommand(); default: return new IncorrectCommand(MESSAGE_UNKNOWN_COMMAND); diff --git a/src/main/java/seedu/gtd/model/Model.java b/src/main/java/seedu/gtd/model/Model.java index 53128f1b1242..ac425d798a80 100644 --- a/src/main/java/seedu/gtd/model/Model.java +++ b/src/main/java/seedu/gtd/model/Model.java @@ -47,4 +47,7 @@ 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 */ + void undoAddressBookChange(); } diff --git a/src/main/java/seedu/gtd/model/ModelManager.java b/src/main/java/seedu/gtd/model/ModelManager.java index a0f9036fd1ad..ba3c9deb8e57 100644 --- a/src/main/java/seedu/gtd/model/ModelManager.java +++ b/src/main/java/seedu/gtd/model/ModelManager.java @@ -26,8 +26,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 AddressBook previousAddressBook; /** * Initializes a ModelManager with the given AddressBook @@ -42,6 +43,7 @@ public ModelManager(AddressBook src, UserPrefs userPrefs) { addressBook = new AddressBook(src); filteredTasks = new FilteredList<>(addressBook.getTasks()); + previousAddressBook = new AddressBook(addressBook); } public ModelManager() { @@ -51,6 +53,7 @@ public ModelManager() { public ModelManager(ReadOnlyAddressBook initialData, UserPrefs userPrefs) { addressBook = new AddressBook(initialData); filteredTasks = new FilteredList<>(addressBook.getTasks()); + previousAddressBook = new AddressBook(addressBook); } @Override @@ -68,24 +71,35 @@ public ReadOnlyAddressBook getAddressBook() { 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(); @@ -94,6 +108,7 @@ 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(); From f6d586ca467b09bd1b201dbec1f304fcf411da1f Mon Sep 17 00:00:00 2001 From: ravishwetha Date: Wed, 2 Nov 2016 06:06:46 +0800 Subject: [PATCH 3/8] Enable undo for clear command Now undo can be applied for commands that change the task list: add, edit, delete, clear and done --- .../java/seedu/gtd/logic/commands/ClearCommand.java | 2 +- src/main/java/seedu/gtd/model/Model.java | 6 +++--- src/main/java/seedu/gtd/model/ModelManager.java | 11 ++++++++--- src/test/java/seedu/gtd/logic/LogicManagerTest.java | 2 +- 4 files changed, 13 insertions(+), 8 deletions(-) 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/model/Model.java b/src/main/java/seedu/gtd/model/Model.java index ac425d798a80..ae219c0d25f8 100644 --- a/src/main/java/seedu/gtd/model/Model.java +++ b/src/main/java/seedu/gtd/model/Model.java @@ -11,9 +11,6 @@ * 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(); @@ -50,4 +47,7 @@ public interface Model { /** Un-does a change to the AddressBook */ void 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 ba3c9deb8e57..2d0fa0d402d5 100644 --- a/src/main/java/seedu/gtd/model/ModelManager.java +++ b/src/main/java/seedu/gtd/model/ModelManager.java @@ -56,12 +56,11 @@ public ModelManager(ReadOnlyAddressBook initialData, UserPrefs userPrefs) { 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; @@ -115,6 +114,12 @@ public synchronized void editTask(int targetIndex, Task task) throws TaskNotFoun indicateAddressBookChanged(); } + @Override + public void clearTaskList() { + savePreviousAddressBook(); + resetData(AddressBook.getEmptyAddressBook()); + } + //@@author addressbook-level4 //=========== Filtered Task List Accessors =============================================================== 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); } From 5bb2155da1fd4034c82fe5c070961c26aa41d28c Mon Sep 17 00:00:00 2001 From: ravishwetha Date: Wed, 2 Nov 2016 12:22:54 +0800 Subject: [PATCH 4/8] Add undo command tests and update collate --- libs/A0146130W.md | 165 +++++++++++- libs/addressbooklevel4.md | 243 ++++++++++++++++-- .../seedu/gtd/logic/commands/UndoCommand.java | 2 + src/test/java/guitests/EditCommandTest.java | 6 +- src/test/java/guitests/UndoCommandTest.java | 61 +++++ 5 files changed, 433 insertions(+), 44 deletions(-) create mode 100644 src/test/java/guitests/UndoCommandTest.java 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/logic/commands/UndoCommand.java b/src/main/java/seedu/gtd/logic/commands/UndoCommand.java index 7597c7a7c0d7..ea22e8c79d20 100644 --- a/src/main/java/seedu/gtd/logic/commands/UndoCommand.java +++ b/src/main/java/seedu/gtd/logic/commands/UndoCommand.java @@ -1,3 +1,5 @@ +//@@author A0146130W + package seedu.gtd.logic.commands; /** 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..283bdea5fb62 --- /dev/null +++ b/src/test/java/guitests/UndoCommandTest.java @@ -0,0 +1,61 @@ +//@@author A0146130W + +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)); + } + +} From 670bceaadd379097bc6ce96cf5da746f975930ec Mon Sep 17 00:00:00 2001 From: ravishwetha Date: Wed, 2 Nov 2016 13:21:49 +0800 Subject: [PATCH 5/8] Multiple undo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test doesn’t work, will fix later --- .../seedu/gtd/logic/commands/UndoCommand.java | 5 +- src/main/java/seedu/gtd/model/Model.java | 5 +- .../java/seedu/gtd/model/ModelManager.java | 21 +++++-- src/test/java/guitests/UndoCommandTest.java | 56 +++++++++++++++---- 4 files changed, 65 insertions(+), 22 deletions(-) diff --git a/src/main/java/seedu/gtd/logic/commands/UndoCommand.java b/src/main/java/seedu/gtd/logic/commands/UndoCommand.java index ea22e8c79d20..48cb8fe8b1d6 100644 --- a/src/main/java/seedu/gtd/logic/commands/UndoCommand.java +++ b/src/main/java/seedu/gtd/logic/commands/UndoCommand.java @@ -10,13 +10,14 @@ 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() { - model.undoAddressBookChange(); - return new CommandResult(MESSAGE_SUCCESS); + 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/model/Model.java b/src/main/java/seedu/gtd/model/Model.java index ae219c0d25f8..80d2d050f0d0 100644 --- a/src/main/java/seedu/gtd/model/Model.java +++ b/src/main/java/seedu/gtd/model/Model.java @@ -45,8 +45,9 @@ 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 */ - void undoAddressBookChange(); + /** 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 2d0fa0d402d5..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; /** @@ -28,7 +29,7 @@ public class ModelManager extends ComponentManager implements Model { private AddressBook addressBook; private final FilteredList filteredTasks; - private AddressBook previousAddressBook; + private Stack previousAddressBook; /** * Initializes a ModelManager with the given AddressBook @@ -43,7 +44,8 @@ public ModelManager(AddressBook src, UserPrefs userPrefs) { addressBook = new AddressBook(src); filteredTasks = new FilteredList<>(addressBook.getTasks()); - previousAddressBook = new AddressBook(addressBook); + previousAddressBook = new Stack(); + previousAddressBook.push(new AddressBook(addressBook)); } public ModelManager() { @@ -53,7 +55,8 @@ public ModelManager() { public ModelManager(ReadOnlyAddressBook initialData, UserPrefs userPrefs) { addressBook = new AddressBook(initialData); filteredTasks = new FilteredList<>(addressBook.getTasks()); - previousAddressBook = new AddressBook(addressBook); + previousAddressBook = new Stack(); + previousAddressBook.push(new AddressBook(addressBook)); } private void resetData(ReadOnlyAddressBook newData) { @@ -72,12 +75,18 @@ private void indicateAddressBookChanged() { } private void savePreviousAddressBook() { - previousAddressBook = new AddressBook(addressBook); + previousAddressBook.push(new AddressBook(addressBook)); } @Override - public void undoAddressBookChange() { - resetData(previousAddressBook); + public boolean undoAddressBookChange() { + if(previousAddressBook.isEmpty()) { + return false; + } + else{ + resetData(previousAddressBook.pop()); + return true; + } } @Override diff --git a/src/test/java/guitests/UndoCommandTest.java b/src/test/java/guitests/UndoCommandTest.java index 283bdea5fb62..2e691df10c31 100644 --- a/src/test/java/guitests/UndoCommandTest.java +++ b/src/test/java/guitests/UndoCommandTest.java @@ -5,10 +5,12 @@ 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;; +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 { @@ -17,32 +19,48 @@ public void undo() { //undo the addition of the first task TestTask[] currentList = td.getTypicalTasks(); - TestTask[] previousList = currentList; + Stack previousList = new Stack(); + previousList.push(currentList); commandBox.runCommand(td.george.getAddCommand()); - assertUndoSuccess(previousList); + assertUndoSuccess(previousList.pop()); //undo editing the dueDate of the last task in the list int targetIndex = currentList.length; String change = "d/2"; - previousList = currentList; + previousList.push(currentList); commandBox.runCommand("edit " + targetIndex + " " + change); - assertUndoSuccess(previousList); + assertUndoSuccess(previousList.pop()); //undo deleting a task from the middle of the list targetIndex = currentList.length/2; - previousList = currentList; + previousList.push(currentList); commandBox.runCommand("delete " + targetIndex); - assertUndoSuccess(previousList); + assertUndoSuccess(previousList.pop()); //undo clearing list - previousList = currentList; + previousList.push(currentList); commandBox.runCommand("clear"); - assertUndoSuccess(previousList); + assertUndoSuccess(previousList.pop()); //undo marking the middle task as done - previousList = currentList; + 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); - assertUndoSuccess(previousList); + previousList.push(currentList); + commandBox.runCommand("clear"); + assertMultipleUndoSuccess(previousList); + */ } /** @@ -57,5 +75,19 @@ private void assertUndoSuccess(final TestTask[] 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)); + } } From ee91159add177e5da8347bf5008770857cce0c8c Mon Sep 17 00:00:00 2001 From: ravishwetha Date: Thu, 3 Nov 2016 00:26:35 +0800 Subject: [PATCH 6/8] Update AboutUs.md --- docs/AboutUs.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index c640ee153033..272a4a89f2b6 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -4,18 +4,24 @@ 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 +29,6 @@ Responsibilities: Storage and Testing Role: Developer
Responsibilities: UI - ----- #### [Voon Soo Yin](http://github.com/tessav) @@ -37,6 +42,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 From c3d3c719d76e847c835d7e113fbaaf8733898f37 Mon Sep 17 00:00:00 2001 From: ravishwetha Date: Thu, 3 Nov 2016 00:27:12 +0800 Subject: [PATCH 7/8] Update AboutUs.md --- docs/AboutUs.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 272a4a89f2b6..fefc2d366cc4 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -6,8 +6,6 @@ We are a team based in the [School of Computing, National University of Singapor #### [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 From cbe978bc4e451191e74755c2b60297766287ff27 Mon Sep 17 00:00:00 2001 From: ravishwetha Date: Thu, 3 Nov 2016 00:29:05 +0800 Subject: [PATCH 8/8] Set up Codacy --- README.md | 1 + 1 file changed, 1 insertion(+) 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