diff --git a/docs/UserGuide.md b/docs/UserGuide.md
index a88d1485974..4aca54aec2f 100644
--- a/docs/UserGuide.md
+++ b/docs/UserGuide.md
@@ -1,10 +1,11 @@
-| Layout | Page |
-| --- | --- |
-| User Guide | Link |
-| Quick start | Link |
-| Features | Link |
-| Command Summary | Link |
+| Quick Links |
+|-----------------|
+| Glossary |
+| User Guide |
+| Quick start |
+| Features |
+| Command Summary |
Ultimate DivocTracker is a desktop app for managing COVID-19 contacts in school admin, optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, Ultimate DivocTracker can get your contact management tasks done faster than traditional GUI apps.
@@ -15,8 +16,8 @@ Ultimate DivocTracker is a desktop app for managing COVID-19 contacts in school
- Adding a student: add
- Listing all students: list
- Find students by name: find_by_name
- - Find student by status: find_by_status
- - Find student by class: find_by_class
+ - Find student by status: findstatus
+ - Find student by class: findclasscode
- Deleting a student: delete_student
- Update COVID-19 status: update_status
- Exiting the program : exit
@@ -53,22 +54,22 @@ Find an existing student in the application by their name
- Example:
- `find_by_name john`
-## Find a student by status: `find_by_status`
+## Find a student by status: `findstatus`
Find an existing student in the application by their Covid-19 Status
-- Format: `find_by_status STATUS`
+- Format: `findstatus STATUS`
- Returns a list of students with the specified `STATUS`
- `STATUS` is case-insensitive
- Example:
- - `find_by_status positive`
- - `find_by_status negative`
+ - `findstatus positive`
+ - `findstatus negative`
-## Find student by class: `find_by_class`
+## Find student by class: `findclasscode`
Finds an existing student in the address book by their class.
-- Format: `find_by_class CLASS`
+- Format: `findclasscode CLASS`
- Returns a list of students with the specified `CLASS`.
- `CLASS` is case-insensitive
- Example:
- - `find_by_class 4A`
+ - `findclasscode 4A`
## Updating persons status: `update_status`
Updates persons status to the given status.
@@ -111,8 +112,8 @@ AddressBook data are saved as a JSON file `[JAR file location]/data/addressbook.
| Delete a student | `delete_student INDEX`
e.g., `delete_student 3` |
| Edit | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS]`
e.g., `edit 2 n/James Lee e/jameslee@example.com` |
| Find by name | `find_by_name NAME [MORE_NAME]`
e.g., `find_by_name James Jake` |
-| Find by status | `find_by_status STATUS`
e.g., `find_by_status positive` |
-| Find by class | `find_by_class CLASS`
e.g., `find_by_class 4A` |
+| Find by status | `findstatus STATUS`
e.g., `find_by_status positive` |
+| Find by class | `findclasscode CLASS`
e.g., `find_by_class 4A` |
| List | `list` |
| Update status | `update_status INDEX STATUS`
e.g., `update_status 54 positive` |
-| Exit | `exit`
+| Exit | `exit` |
diff --git a/docs/team/fenway17.md b/docs/team/fenway17.md
index 4679e77a2ed..acef2427050 100644
--- a/docs/team/fenway17.md
+++ b/docs/team/fenway17.md
@@ -15,7 +15,11 @@ Given below are my contributions to the project.
* Highlights: Status can be `"Positive"`, `"Negative"` or `"Close-Contact"`
* Credits: *{Collaborators: Yong Rui, Zi Foong}*
-* **New Feature**: --
+* **New Feature**: Command to find persons by Class Code (Pull request [\#56](https://github.com/AY2122S2-CS2103T-T12-1/tp/pull/56))
+ * What it does: Find a list of persons that match the Class Code given.
+ * Justification: Allows admins and users to find all persons in the same class
+ * Highlights: Given Class Code can be part of the full Class Code
+ * Credits: *{}*
* **Code contributed**: [RepoSense link]()
@@ -23,7 +27,7 @@ Given below are my contributions to the project.
* Managed releases `--` - `--` (-- releases) on GitHub
* **Enhancements to existing features**:
- * -- (Pull requests [\#--](), [\#--]())
+ * Fixed multiple checkstyle errors (Pull request [\#49](https://github.com/AY2122S2-CS2103T-T12-1/tp/pull/49))
* -- (Pull requests [\#--](), [\#--]())
* **Documentation**:
@@ -36,7 +40,7 @@ Given below are my contributions to the project.
* Added use cases for developer guide [\#27](https://github.com/AY2122S2-CS2103T-T12-1/tp/pull/27)
* **Community**:
- * PRs reviewed (with non-trivial review comments): [\#32](https://github.com/AY2122S2-CS2103T-T12-1/tp/pull/32)
+ * PRs reviewed (with non-trivial review comments): [\#32](https://github.com/AY2122S2-CS2103T-T12-1/tp/pull/32) [\#63](https://github.com/AY2122S2-CS2103T-T12-1/tp/pull/63)
* Contributed to forum discussions (examples: [1](), [2](), [3](), [4]())
* Reported bugs and suggestions for other teams in the class (examples: [1](), [2](), [3]())
* Some parts of the -- feature I added was adopted by several other class mates ([1](), [2]())
diff --git a/docs/team/lzf834.md b/docs/team/lzf834.md
index e5a496207a0..518e83634ee 100644
--- a/docs/team/lzf834.md
+++ b/docs/team/lzf834.md
@@ -1,20 +1,29 @@
---
-layout: page
-title: Zi Foong's Project Portfolio Page
+Zi Foong's Project Portfolio Page
---
+| Content |
+|------------------|
+| New Features |
+| Code Contributed |
+| Enhancements |
+| Documentations |
+| Community |
### Project: Ultimate Divoc Tracker
Ultimate Divoc Tracker is a desktop app for managing COVID-19 contacts in school admin, optimized for use via a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, Ultimate DivocTracker can get your contact management tasks done faster than traditional GUI apps.
Given below are my contributions to the project.
+* **New Feature**: Find Students by their Covid-19 Status -- (Pull Request [\#55](https://github.com/AY2122S2-CS2103T-T12-1/tp/pull/55))
+ * What it does: Allows the user to find students by their status
+ * Justification: Track students with specific statuses e.g. `Positive` or `Close-Contact`
+ * Credits: *{Collaborators: Yong Rui, Zi Foong}*
+
* **New Feature**: Status attribute for persons -- (Pull Request [\#32](https://github.com/AY2122S2-CS2103T-T12-1/tp/pull/32))
* What it does: Gives each person in the list a status attribute denoting their COVID-19 status.
* Justification: Track COVID-19 status of each person
- * Highlights: Status can be `"Positive"`, `"Negative"` or `"Close-Contact"`
+ * Highlights: Status can be `Positive`, `Negative` or `Close-Contact`
* Credits: *{Collaborators: Yong Rui, Zi Foong}*
-
-* **New Feature**: `To be added soon`
* **Code contributed**: [RepoSense link]()
* **Project management**:
* Managed releases `To be added soon`
@@ -25,8 +34,9 @@ Given below are my contributions to the project.
* User Guide:
* Update AboutUs.md [\#18](https://github.com/AY2122S2-CS2103T-T12-1/tp/pull/18)
* Update Readme.md [\#18](https://github.com/AY2122S2-CS2103T-T12-1/tp/pull/18)
+ * Update for new features `findstatus` and `findclasscode`
* Developer Guide:
- * Editted Glossary
+ * Edited Glossary
* Added User Profile, User Stories and Value Prepositions [\#25](https://github.com/AY2122S2-CS2103T-T12-1/tp/pull/25)
* **Community**:
* PRs reviewed (with non-trivial review comments): [\#32](https://github.com/AY2122S2-CS2103T-T12-1/tp/pull/32)
@@ -36,4 +46,3 @@ Given below are my contributions to the project.
* **Tools**:
* `To be added soon`
* `To be added soon`
-* _{you can add/remove categories in the list above}_
diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java
index 27c0b99dc2a..079b421e42e 100644
--- a/src/main/java/seedu/address/logic/commands/EditCommand.java
+++ b/src/main/java/seedu/address/logic/commands/EditCommand.java
@@ -15,7 +15,9 @@
import java.util.List;
import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
+import javafx.collections.ObservableList;
import seedu.address.commons.core.Messages;
import seedu.address.commons.core.index.Index;
import seedu.address.commons.util.CollectionUtil;
@@ -75,6 +77,7 @@ public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) {
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
List lastShownList = model.getFilteredPersonList();
+ ObservableList studentList = model.getAddressBook().getPersonList();
if (index.getZeroBased() >= lastShownList.size()) {
throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX);
@@ -88,6 +91,24 @@ public CommandResult execute(Model model) throws CommandException {
}
model.setPerson(personToEdit, editedPerson);
+
+ if (personToEdit.getStatus().toString().equals(Status.NEGATIVE)
+ && editedPerson.getStatus().toString().equals(Status.POSITIVE)) {
+
+ List filteredByClassCodeList = studentList.stream()
+ .filter(student -> student.getClassCode().toString().equals(editedPerson.getClassCode().toString())
+ && !student.isSamePerson(editedPerson))
+ .collect(Collectors.toList());
+
+ for (int i = 0; i < filteredByClassCodeList.size(); i++) {
+ Person currentPerson = filteredByClassCodeList.get(i);
+ EditPersonDescriptor tempDescriptor = new EditPersonDescriptor();
+ tempDescriptor.setStatus(new Status(Status.CLOSE_CONTACT));
+ Person editedPersonStatus = createEditedPerson(currentPerson, tempDescriptor);
+ model.setPerson(currentPerson, editedPersonStatus);
+ }
+ }
+
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, editedPerson));
}
@@ -162,7 +183,7 @@ public EditPersonDescriptor(EditPersonDescriptor toCopy) {
* Returns true if at least one field is edited.
*/
public boolean isAnyFieldEdited() {
- return CollectionUtil.isAnyNonNull(name, phone, email, address, tags);
+ return CollectionUtil.isAnyNonNull(name, phone, email, address, tags, status, classCode);
}
public void setName(Name name) {
diff --git a/src/main/java/seedu/address/model/person/Status.java b/src/main/java/seedu/address/model/person/Status.java
index a26a1ae009f..382665080b7 100644
--- a/src/main/java/seedu/address/model/person/Status.java
+++ b/src/main/java/seedu/address/model/person/Status.java
@@ -13,6 +13,9 @@ public class Status {
public static final String MESSAGE_CONSTRAINTS =
"Status should only be Positive, Negative or Close-Contact";
private static final String[] STATUS_INPUT = {"Positive", "Negative", "Close-Contact"};
+ public static final String POSITIVE = STATUS_INPUT[0];
+ public static final String NEGATIVE = STATUS_INPUT[1];
+ public static final String CLOSE_CONTACT = STATUS_INPUT[2];
public final String value;
/**
diff --git a/src/test/java/seedu/address/logic/commands/FindStatusTest.java b/src/test/java/seedu/address/logic/commands/FindStatusTest.java
new file mode 100644
index 00000000000..df0ad9079ca
--- /dev/null
+++ b/src/test/java/seedu/address/logic/commands/FindStatusTest.java
@@ -0,0 +1,67 @@
+package seedu.address.logic.commands;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.address.commons.core.Messages.MESSAGE_PERSONS_LISTED_OVERVIEW;
+import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess;
+import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.model.Model;
+import seedu.address.model.ModelManager;
+import seedu.address.model.UserPrefs;
+import seedu.address.model.person.StatusContainsKeywordsPredicate;
+
+public class FindStatusTest {
+ private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+ private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs());
+
+ @Test
+ public void equals() {
+ StatusContainsKeywordsPredicate firstPredicate =
+ new StatusContainsKeywordsPredicate(Collections.singletonList("Positive"));
+ StatusContainsKeywordsPredicate secondPredicate =
+ new StatusContainsKeywordsPredicate(Collections.singletonList("Negative"));
+
+ FindStatusCommand findFirstCommand = new FindStatusCommand(firstPredicate);
+ FindStatusCommand findSecondCommand = new FindStatusCommand(secondPredicate);
+
+ // same object -> returns true
+ assertTrue(findFirstCommand.equals(findFirstCommand));
+
+ // same values -> returns true
+ FindStatusCommand findFirstCommandCopy = new FindStatusCommand(firstPredicate);
+ assertTrue(findFirstCommand.equals(findFirstCommandCopy));
+
+ // different types -> returns false
+ assertFalse(findFirstCommand.equals(1));
+
+ // null -> returns false
+ assertFalse(findFirstCommand.equals(null));
+
+ // different person -> returns false
+ assertFalse(findFirstCommand.equals(findSecondCommand));
+ }
+
+ @Test
+ public void execute_zeroKeywords_noPersonFound() {
+ String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 0);
+ StatusContainsKeywordsPredicate predicate = preparePredicate(" ");
+ FindStatusCommand command = new FindStatusCommand(predicate);
+ expectedModel.updateFilteredPersonList(predicate);
+ assertCommandSuccess(command, model, expectedMessage, expectedModel);
+ assertEquals(Collections.emptyList(), model.getFilteredPersonList());
+ }
+
+ /**
+ * Parses {@code userInput} into a {@code StatusContainsKeywordsPredicate}.
+ */
+ private StatusContainsKeywordsPredicate preparePredicate(String userInput) {
+ return new StatusContainsKeywordsPredicate(Arrays.asList(userInput.split("\\s+")));
+ }
+}
diff --git a/src/test/java/seedu/address/logic/parser/FindStatusCommandParserTest.java b/src/test/java/seedu/address/logic/parser/FindStatusCommandParserTest.java
new file mode 100644
index 00000000000..7bcf2cc1536
--- /dev/null
+++ b/src/test/java/seedu/address/logic/parser/FindStatusCommandParserTest.java
@@ -0,0 +1,35 @@
+package seedu.address.logic.parser;
+
+import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure;
+import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess;
+
+import java.util.Arrays;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.logic.commands.FindStatusCommand;
+import seedu.address.model.person.StatusContainsKeywordsPredicate;
+
+public class FindStatusCommandParserTest {
+ private FindStatusCommandParser parser = new FindStatusCommandParser();
+
+ @Test
+ public void parse_emptyArg_throwsParseException() {
+ assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT,
+ FindStatusCommand.MESSAGE_USAGE));
+
+ // multiple whitespaces between keywords
+ assertParseFailure(parser, " \n Positive \n \t Negative \t", String.format(
+ MESSAGE_INVALID_COMMAND_FORMAT, FindStatusCommand.ERRMSG_STATUS));
+ }
+
+ @Test
+ public void parse_validArgs_returnsFindCommand() {
+ // no leading and trailing whitespaces
+ FindStatusCommand expectedFindStatusCommand =
+ new FindStatusCommand(new StatusContainsKeywordsPredicate(Arrays.asList("Positive")));
+ assertParseSuccess(parser, "Positive", expectedFindStatusCommand);
+
+ }
+}
diff --git a/src/test/java/seedu/address/model/person/StatusContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/StatusContainsKeywordsPredicateTest.java
new file mode 100644
index 00000000000..26befc53a29
--- /dev/null
+++ b/src/test/java/seedu/address/model/person/StatusContainsKeywordsPredicateTest.java
@@ -0,0 +1,64 @@
+package seedu.address.model.person;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import seedu.address.testutil.PersonBuilder;
+
+public class StatusContainsKeywordsPredicateTest {
+ @Test
+ public void equals() {
+ List firstPredicateKeywordList = Collections.singletonList("Positive");
+ List secondPredicateKeywordList = Arrays.asList("Positive", "Negative");
+
+ StatusContainsKeywordsPredicate firstPredicate = new
+ StatusContainsKeywordsPredicate(firstPredicateKeywordList);
+ StatusContainsKeywordsPredicate secondPredicate = new
+ StatusContainsKeywordsPredicate(secondPredicateKeywordList);
+
+ // same object -> returns true
+ assertTrue(firstPredicate.equals(firstPredicate));
+
+ // same values -> returns true
+ StatusContainsKeywordsPredicate firstPredicateCopy = new
+ StatusContainsKeywordsPredicate(firstPredicateKeywordList);
+ assertTrue(firstPredicate.equals(firstPredicateCopy));
+
+ // different types -> returns false
+ assertFalse(firstPredicate.equals(1));
+
+ // null -> returns false
+ assertFalse(firstPredicate.equals(null));
+
+ // different person -> returns false
+ assertFalse(firstPredicate.equals(secondPredicate));
+ }
+
+ @Test
+ public void test_statusContainsKeywords_returnsTrue() {
+ // One keyword
+ StatusContainsKeywordsPredicate predicate = new
+ StatusContainsKeywordsPredicate(Collections.singletonList("Positive"));
+ assertTrue(predicate.test(new PersonBuilder().withStatus("Positive").build()));
+
+ // Exception thrown for >1 word in status
+ try {
+ new PersonBuilder().withStatus("Positive Negative").build();
+ } catch (Exception e) {
+ assertTrue(e.getMessage() == Status.MESSAGE_CONSTRAINTS);
+ }
+
+ // Exception thrown for non-conforming syntax in status
+ try {
+ new PersonBuilder().withStatus("Pos").build();
+ } catch (Exception e) {
+ assertTrue(e.getMessage() == Status.MESSAGE_CONSTRAINTS);
+ }
+ }
+}
diff --git a/src/test/java/seedu/address/model/person/StatusTest.java b/src/test/java/seedu/address/model/person/StatusTest.java
new file mode 100644
index 00000000000..c617e058eac
--- /dev/null
+++ b/src/test/java/seedu/address/model/person/StatusTest.java
@@ -0,0 +1,36 @@
+package seedu.address.model.person;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static seedu.address.testutil.Assert.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+public class StatusTest {
+ @Test
+ public void constructor_null_throwsNullPointerException() {
+ assertThrows(NullPointerException.class, () -> new Status(null));
+ }
+
+ @Test
+ public void constructor_invalidEmail_throwsIllegalArgumentException() {
+ String invalidStatus = "";
+ assertThrows(IllegalArgumentException.class, () -> new Status(invalidStatus));
+ }
+
+ @Test
+ public void isValidStatus() {
+ // null Status
+ assertThrows(NullPointerException.class, () -> Status.isValidStatus(null));
+
+ // invalid Statuses
+ assertFalse(Status.isValidStatus("")); // empty string
+ assertFalse(Status.isValidStatus(" ")); // spaces only
+ assertFalse(Status.isValidStatus("abcde")); // not eny of the 3 possible statuses
+
+ // valid Statuses
+ assertTrue(Status.isValidStatus("Positive"));
+ assertTrue(Status.isValidStatus("Negative")); // one character
+ assertTrue(Status.isValidStatus("Close-Contact")); // long Status
+ }
+}