diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 00000000000..0cd51c5fb97
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,25 @@
+name: MarkBind Action
+
+on:
+ push:
+ branches:
+ - master
+
+jobs:
+ build_and_deploy:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Install Graphviz
+ run: sudo apt-get install graphviz
+ - name: Install Java
+ uses: actions/setup-java@v3
+ with:
+ java-version: '11'
+ distribution: 'temurin'
+ - name: Build & Deploy MarkBind site
+ uses: MarkBind/markbind-action@v2
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
+ rootDirectory: './docs'
+ baseUrl: '/tp' # assuming your repo name is tp
+ version: '^5.2.0'
diff --git a/.gitignore b/.gitignore
index 284c4ca7cd9..46fb10c3260 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,10 +14,21 @@ src/main/resources/docs/
/preferences.json
/*.log.*
hs_err_pid[0-9]*.log
+/addressbookdata/
# Test sandbox files
src/test/data/sandbox/
+src/test/data/ExportCommandTest/addressbookdata/
+src/test/data/ExportCommandTest/filteredAddressBook.json
# MacOS custom attributes files created by Finder
.DS_Store
docs/_site/
+docs/_markbind/logs/
+
+# Markbind generated files
+_markbind/
+
+#VSCode files
+.vscode/
+bin/
diff --git a/README.md b/README.md
index 13f5c77403f..85dc43396b8 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,24 @@
-[](https://github.com/se-edu/addressbook-level3/actions)
+[](https://github.com/AY2324S2-CS2103T-T10-1/tp/actions)
+[](https://app.codecov.io/gh/AY2324S2-CS2103T-T10-1/tp)
+
+
+## Avengers Assemble

-* This is **a sample project for Software Engineering (SE) students**.
- Example usages:
- * as a starting point of a course project (as opposed to writing everything from scratch)
- * as a case study
-* The project simulates an ongoing software project for a desktop application (called _AddressBook_) used for managing contact details.
- * It is **written in OOP fashion**. It provides a **reasonably well-written** code base **bigger** (around 6 KLoC) than what students usually write in beginner-level SE modules, without being overwhelmingly big.
- * It comes with a **reasonable level of user and developer documentation**.
-* It is named `AddressBook Level 3` (`AB3` for short) because it was initially created as a part of a series of `AddressBook` projects (`Level 1`, `Level 2`, `Level 3` ...).
-* For the detailed documentation of this project, see the **[Address Book Product Website](https://se-education.org/addressbook-level3)**.
-* This project is a **part of the se-education.org** initiative. If you would like to contribute code to this project, see [se-education.org](https://se-education.org#https://se-education.org/#contributing) for more info.
+Avengers Assemble is a contact management app, meant for use with a Command Line Interface (CLI) while still maintaining the benefits of a Graphical User Interface (GUI).
+
+This application is designed for Head Tutors of the CS1101S Programming Methodology course to manage the contact details of students, tutors and other staff members. Its use cases may also be relevant to Head Tutors of other courses.
+
+### Project Links
+* [Project Website](https://ay2324s2-cs2103t-t10-1.github.io/tp/)
+* [User Guide](https://ay2324s2-cs2103t-t10-1.github.io/tp/UserGuide.html)
+* [Developer Guide](https://ay2324s2-cs2103t-t10-1.github.io/tp/DeveloperGuide.html)
+* [About Us](https://ay2324s2-cs2103t-t10-1.github.io/tp/AboutUs.html)
+
+
+### Acknowledgements
+
+* This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative](https://se-education.org).
+* Libraries used: [JavaFX](https://openjfx.io/), [Jackson](https://github.com/FasterXML/jackson), [JUnit5](https://github.com/junit-team/junit5), [OpenCSV](https://opencsv.sourceforge.net/)
+
diff --git a/build.gradle b/build.gradle
index a2951cc709e..2eae589df69 100644
--- a/build.gradle
+++ b/build.gradle
@@ -58,15 +58,26 @@ dependencies {
implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'linux'
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.7.0'
+ implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-csv', version: '2.7.4'
implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.7.4'
+ implementation 'com.opencsv:opencsv:5.5.2'
+
+ testImplementation('org.junit.platform:junit-platform-launcher:1.5.2')
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: jUnitVersion
+ testImplementation "org.mockito:mockito-core:3.+"
+ testImplementation group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.9'
+ testImplementation group: 'org.powermock', name: 'powermock-module-junit4', version: '1.6.4'
testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: jUnitVersion
}
shadowJar {
- archiveFileName = 'addressbook.jar'
+ archiveFileName = 'avengersassemble.jar'
+}
+
+run {
+ enableAssertions = true
}
defaultTasks 'clean', 'test'
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 00000000000..1748e487fbd
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1,23 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+_markbind/logs/
+
+# Dependency directories
+node_modules/
+
+# Production build files (change if you output the build to a different directory)
+_site/
+
+# Env
+.env
+.env.local
+
+# IDE configs
+.vscode/
+.idea/*
+*.iml
diff --git a/docs/AboutUs.md b/docs/AboutUs.md
index 1c9514e966a..1d248dc406f 100644
--- a/docs/AboutUs.md
+++ b/docs/AboutUs.md
@@ -1,59 +1,57 @@
---
-layout: page
-title: About Us
+ layout: default.md
+ title: "About Us"
---
+# About Us
+
We are a team based in the [School of Computing, National University of Singapore](http://www.comp.nus.edu.sg).
You can reach us at the email `seer[at]comp.nus.edu.sg`
## Project team
-### John Doe
+### Johan Soo
-
+
-[[homepage](http://www.comp.nus.edu.sg/~damithch)]
-[[github](https://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](https://github.com/delishad21)]
-* Role: Project Advisor
+* Role: Developer
+* Responsibilities: Develop Code
-### Jane Doe
+### Ang Leng Khai
-
+
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](http://github.com/zer0legion)]
-* Role: Team Lead
-* Responsibilities: UI
+* Role: Developer
+* Responsibilities: Develop code
-### Johnny Doe
+### Loh Sze Han, Danielle
-
+
-[[github](http://github.com/johndoe)] [[portfolio](team/johndoe.md)]
+[[github](http://github.com/danielleloh)] [[portfolio](team/johndoe.md)]
* Role: Developer
-* Responsibilities: Data
+* Responsibilities: Develop code
-### Jean Doe
+### Pughal Raj
-
+
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](http://github.com/Pughal77)]
* Role: Developer
-* Responsibilities: Dev Ops + Threading
+* Responsibilities: Develop code
-### James Doe
+### Castillo James
-
+
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](http://github.com/jayllo-c)]
* Role: Developer
-* Responsibilities: UI
+* Responsibilities: Develop Code
diff --git a/docs/Configuration.md b/docs/Configuration.md
index 13cf0faea16..32f6255f3b9 100644
--- a/docs/Configuration.md
+++ b/docs/Configuration.md
@@ -1,6 +1,8 @@
---
-layout: page
-title: Configuration guide
+ layout: default.md
+ title: "Configuration guide"
---
+# Configuration guide
+
Certain properties of the application can be controlled (e.g user preferences file location, logging level) through the configuration file (default: `config.json`).
diff --git a/docs/DevOps.md b/docs/DevOps.md
index d2fd91a6001..c725d7c67b7 100644
--- a/docs/DevOps.md
+++ b/docs/DevOps.md
@@ -1,12 +1,15 @@
---
-layout: page
-title: DevOps guide
+ layout: default.md
+ title: "DevOps guide"
+ pageNav: 3
---
-* Table of Contents
-{:toc}
+# DevOps guide
---------------------------------------------------------------------------------------------------------------------
+
+
+
+
## Build automation
@@ -73,7 +76,7 @@ Any warnings or errors will be printed out to the console.
Here are the steps to create a new release.
-1. Update the version number in [`MainApp.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/MainApp.java).
+1. Update the version number in [`MainApp.java`](https://github.com/AY2324S2-CS2103T-T10-1/tp/tree/master/src/main/java/seedu/address/MainApp.java).
1. Generate a fat JAR file using Gradle (i.e., `gradlew shadowJar`).
1. Tag the repo with the version number. e.g. `v0.1`
1. [Create a new release using GitHub](https://help.github.com/articles/creating-releases/). Upload the JAR file you created.
diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md
index 1b56bb5d31b..3106535b761 100644
--- a/docs/DeveloperGuide.md
+++ b/docs/DeveloperGuide.md
@@ -1,34 +1,141 @@
---
-layout: page
-title: Developer Guide
+layout: default.md
+title: "Developer Guide"
---
-* Table of Contents
-{:toc}
+
+# Avengers Assemble Developer Guide
+
+
+## Table of Contents
+
+
--------------------------------------------------------------------------------------------------------------------
+
## **Acknowledgements**
-* {list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well}
+This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative](https://se-education.org).
+
+Features related to the creation and reading of CSV files were made possible through the use of the [OpenCSV](http://opencsv.sourceforge.net/) library.
+
+Our project made use of AI assistance from [GitHub Copilot](https://copilot.github.com/) to finish small snippets of code and to provide suggestions.
--------------------------------------------------------------------------------------------------------------------
-## **Setting up, getting started**
+
+
+## **Setting Up, Getting Started**
Refer to the guide [_Setting up and getting started_](SettingUp.md).
--------------------------------------------------------------------------------------------------------------------
-## **Design**
+
+
+
-
+## **Design**
-:bulb: **Tip:** The `.puml` files used to create diagrams in this document `docs/diagrams` folder. Refer to the [_PlantUML Tutorial_ at se-edu/guides](https://se-education.org/guides/tutorials/plantUml.html) to learn how to create and edit diagrams.
-
+
### Architecture
-
+
The ***Architecture Diagram*** given above explains the high-level design of the App.
@@ -36,7 +143,7 @@ Given below is a quick overview of main components and how they interact with ea
**Main components of the architecture**
-**`Main`** (consisting of classes [`Main`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/Main.java) and [`MainApp`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/MainApp.java)) is in charge of the app launch and shut down.
+**`Main`** (consisting of classes [`Main`](https://github.com/AY2324S2-CS2103T-T10-1/tp/tree/master/src/main/java/seedu/address/Main.java) and [`MainApp`](https://github.com/AY2324S2-CS2103T-T10-1/tp/tree/master/src/main/java/seedu/address/MainApp.java)) is in charge of the app launch and shut down.
* At app launch, it initializes the other components in the correct sequence, and connects them up with each other.
* At shut down, it shuts down the other components and invokes cleanup methods where necessary.
@@ -49,334 +156,3309 @@ The bulk of the app's work is done by the following four components:
[**`Commons`**](#common-classes) represents a collection of classes used by multiple other components.
+
+
**How the architecture components interact with each other**
The *Sequence Diagram* below shows how the components interact with each other for the scenario where the user issues the command `delete 1`.
-
+
Each of the four main components (also shown in the diagram above),
* defines its *API* in an `interface` with the same name as the Component.
-* implements its functionality using a concrete `{Component Name}Manager` class (which follows the corresponding API `interface` mentioned in the previous point.
+* implements its functionality using a concrete `{Component Name}Manager` class (which follows the corresponding API `interface` mentioned in the previous point.)
For example, the `Logic` component defines its API in the `Logic.java` interface and implements its functionality using the `LogicManager.java` class which follows the `Logic` interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component's being coupled to the implementation of a component), as illustrated in the (partial) class diagram below.
-
+
The sections below give more details of each component.
-### UI component
+
-The **API** of this component is specified in [`Ui.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/ui/Ui.java)
+
-
+
+
+### UI Component
+
+The **API** of this component is specified in [`Ui.java`](https://github.com/AY2324S2-CS2103T-T10-1/tp/tree/master/src/main/java/seedu/address/ui/Ui.java)
+
+
The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `StatusBarFooter` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class which captures the commonalities between classes that represent parts of the visible GUI.
-The `UI` component uses the JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the [`MainWindow`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/ui/MainWindow.java) is specified in [`MainWindow.fxml`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/resources/view/MainWindow.fxml)
+The `UI` component uses the JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the [`MainWindow`](https://github.com/AY2324S2-CS2103T-T10-1/tp/tree/master/src/main/java/seedu/address/ui/MainWindow.java) is specified in [`MainWindow.fxml`](https://github.com/AY2324S2-CS2103T-T10-1/tp/tree/master/src/main/resources/view/MainWindow.fxml)
+
+The `CommandBox` takes in user input which is passed onto the `Logic` component for the user input to be parsed and executed. A `CommandResult` is returned after execution and the feedback is displayed to the user through the `ResultDisplay` component of the UI.
+
+For the updating of other components in the UI, after each command execution, `MainWindow` runs an update that calls the update method on `PersonListPanel`, `ExamListPanel` and `StatusBarFooter`.
+
+`PersonListPanel` and `ExamListPanel` update themselves by retrieving the `filteredPersonList` and `examList` from the `Model` component and updating the displayed lists accordingly.
+
+`StatusBarFooter` contains the mean and median feature, and it updates itself by retrieving `ScoreStatistics`
+from the `Model` on update.
+
+
-The `UI` component,
+In summary, the `UI` component:
* executes user commands using the `Logic` component.
-* listens for changes to `Model` data so that the UI can be updated with the modified data.
+* checks for changes to `Model` data so that the UI can be updated with the modified data.
* keeps a reference to the `Logic` component, because the `UI` relies on the `Logic` to execute commands.
-* depends on some classes in the `Model` component, as it displays `Person` object residing in the `Model`.
+* depends on some classes in the `Model` component, as the `UI` updates based on items that are stored in `Model`
-### Logic component
+The sequence diagram below illustrates a more in-depth view of the interactions within the UI component
-**API** : [`Logic.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/logic/Logic.java)
+
-Here's a (partial) class diagram of the `Logic` component:
+#### Considerations For UI
+
+##### Dynamic UI Updates
+
+The UI is designed to update dynamically based on changes in the `Model`. We narrowed down to two design choices for updating the UI components. They are:
+
+1. **Update using listeners embedded into UI components** - This design choice would involve embedding listeners into the UI components that would listen for changes in the `Model` (e.g. adding a listener to filteredPersons in ExamListPanel). This would allow for a more loosely coupled system, but would involve more complex implementation which could get messy as the number of listeners increase.
+2. **Update using a centralized update method** - This design choice involves having a centralized `update` method in the `MainWindow` that would call an `update` method in all other UI components after every command. This would involve a more tightly coupled system and may involve unnecessary updates, but would be easier to implement and maintain.
+
+We chose the second design choice as having a centralized update method would allow for easier maintenance, as there is a clear indicator of how UI components are updated from `MainWindow`. Adding extensions would also be more straightforward as future developers would know where to look for the update logic.
+
+With listeners, the update logic would be scattered across multiple UI component classes, making it much harder to search and add upon the update logic.
+
+One of our main goals was to make our codebase easy to understand and maintain, and we felt that the centralized update method would be more in line with this goal despite the slight increase in coupling and inefficiency.
+
+
-
+
-The sequence diagram below illustrates the interactions within the `Logic` component, taking `execute("delete 1")` API call as an example.
+
-
+### Logic Component
-
:information_source: **Note:** The lifeline for `DeleteCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram.
-
+**API** : [`Logic.java`](https://github.com/AY2324S2-CS2103T-T10-1/tp/tree/master/src/main/java/seedu/address/logic/Logic.java)
+
+Here's a (partial) class diagram of the `Logic` component:
+
+
How the `Logic` component works:
1. When `Logic` is called upon to execute a command, it is passed to an `AddressBookParser` object which in turn creates a parser that matches the command (e.g., `DeleteCommandParser`) and uses it to parse the command.
-1. This results in a `Command` object (more precisely, an object of one of its subclasses e.g., `DeleteCommand`) which is executed by the `LogicManager`.
-1. The command can communicate with the `Model` when it is executed (e.g. to delete a person).
+2. This results in a `Command` object (more precisely, an object of one of its subclasses e.g., `DeleteCommand`) which is executed by the `LogicManager`.
+3. The command can communicate with the `Model` when it is executed (e.g. to delete a person).
Note that although this is shown as a single step in the diagram above (for simplicity), in the code it can take several interactions (between the command object and the `Model`) to achieve.
-1. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `Logic`.
+4. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `Logic`.
+
+
Here are the other classes in `Logic` (omitted from the class diagram above) that are used for parsing a user command:
-
+
How the parsing works:
-* When called upon to parse a user command, the `AddressBookParser` class creates an `XYZCommandParser` (`XYZ` is a placeholder for the specific command name e.g., `AddCommandParser`) which uses the other classes shown above to parse the user command and create a `XYZCommand` object (e.g., `AddCommand`) which the `AddressBookParser` returns back as a `Command` object.
+
+* When called upon to parse a user command, the `AddressBookParser` class creates an `XYZCommandParser` (`XYZ` is a placeholder for the specific command name e.g., `AddCommandParser`)
+* The `XYZCommandParser` uses the other classes shown above to parse the user command and create a `XYZCommand` object (e.g., `AddCommand`) which the `AddressBookParser` returns back as a `Command` object.
* All `XYZCommandParser` classes (e.g., `AddCommandParser`, `DeleteCommandParser`, ...) inherit from the `Parser` interface so that they can be treated similarly where possible e.g, during testing.
-### Model component
-**API** : [`Model.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/model/Model.java)
+
+
+#### Example of Parsing User Input: `delete` Command
+
+The sequence diagram below illustrates the interactions within the `Logic` component, taking a simple `execute("delete 1")` API call as an example.
+
+
-
+**Note:** The lifeline for `DeleteCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram.
+
+
+The following is a more detailed explanation on how user input is parsed into a `Command` object (not mentioned above for simplicity).
+
+##### Using Argument Tokenizer and Argument Multimap
+* After the `XYZCommandParser` is instantiated by the `AddressBookParser`, it uses the `ArgumentTokenizer` class to tokenize the user input string into the arguments.
+ * This is done through the `tokenize` method which returns an `ArgumentMultimap` object.
+* The `ArgumentMultimap` class is then used to extract the relevant arguments.
+
+
+
+**Mandatory Arguments and Multiple Arguments**
+
+* For some commands, some arguments are mandatory and the `arePrefixesPresent` method is used to check if the arguments (i.e the corresponding prefixes) are present in the user input. If not, an exception is thrown.
+* For some commands, multiple arguments under the same category (e.g. two name arguments for an AddCommand) are not allowed. The `ArgumentMultimap` class is used to check for undesirable multiple arguments using the `verifyNoDuplicatePrefixesFor` method. If multiple arguments are present, an exception is thrown.
+
+
+
+**Validation of Arguments**
+
+* Validation of each extracted argument is done using the methods defined in the `ParserUtil` class. This class contains methods to validate different arguments extracted by the `ArgumentMultimap` class based on the `VALIDATION_REGEX` defined in component classes (`Name.java`, `Score.java`, etc.).
+* The parsed arguments are then used to create a `XYZCommand` object to be executed.
+
+
+
+**Note:** Some commands do not require any arguments (e.g., `help`, `clear`, `list`, `exit`). In such cases, the `XYZCommand` class is directly instantiated by the `AddressBookParser` class without the parsing of arguments. As such, any arguments passed to these commands are ignored.
+
+
+
+#### Considerations for Logic
+
+The `Logic` component is designed to be the central component that executes all user commands.
+This design choice was made to ensure that all commands are executed in a consistent manner, and to prevent the duplication of command execution logic across different components.
+By centralizing the command execution logic in the `Logic` component, we ensure that all commands are executed in the same way, regardless of the component that initiates the command execution.
+This design choice also allows for easier maintenance and extensibility, as any changes to the command execution logic can be made in a single location.
+
+
+
+
+
+
+
+### Model Component
+**API** : [`Model.java`](https://github.com/AY2324S2-CS2103T-T10-1/tp/master/src/main/java/seedu/address/model/Model.java)
+
+
The `Model` component,
-* stores the address book data i.e., all `Person` objects (which are contained in a `UniquePersonList` object).
-* stores the currently 'selected' `Person` objects (e.g., results of a search query) as a separate _filtered_ list which is exposed to outsiders as an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.
+* stores the address book data i.e., all `Person` objects (which are contained in a `UniquePersonList` object) and all `Exam` objects (which are contained in a `UniqueExamList` object).
+* stores the currently filtered `Person` objects (e.g., results of a search query) as a separate _filtered_ list which is exposed to outsiders as an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI can update when the data in the list changes.
+* stores the currently selected `Exam` which is exposed to outsiders as an unmodifiable `ObservableValue`. This is used in conjunction with the exam and exam score implementation, and also used to update the highlighted exam on the UI.
+* stores `ScoreStatistics` for the currently selected `Exam`. This statistic is used in conjunction with the mean and median feature. It is also exposed to outsiders as an unmodifiable `ObservableValue` so that the UI can be bound to this value for updating.
* stores a `UserPref` object that represents the user’s preferences. This is exposed to the outside as a `ReadOnlyUserPref` objects.
* does not depend on any of the other three components (as the `Model` represents data entities of the domain, they should make sense on their own without depending on other components)
-
:information_source: **Note:** An alternative (arguably, a more OOP) model is given below. It has a `Tag` list in the `AddressBook`, which `Person` references. This allows `AddressBook` to only require one `Tag` object per unique tag, instead of each `Person` needing their own `Tag` objects.
+
+
+**Note:** An alternative (arguably, a more OOP) model is given below relating to the `Person` class. It has a `Tag` list in the `AddressBook`, which `Person` references. This allows `AddressBook` to only require one `Tag` object per unique tag, instead of each `Person` needing their own `Tag` objects. However, we opted not to use this model. As much as possible, we tried to keep the attributes of `Person` unlinked to other classes to prevent complications in our saving, import and export functionalities.
+
+
+
+
+
+
+#### Saving of Data
+
+The `Storage` component uses the `Jackson` library to convert objects to JSON format. The conversion methods are predefined in the `JsonAdapted` classes for their corresponding objects.
+
+The `Logic` class stores a `StorageManager` object that implements the methods in the `Storage` class. For **every** command that is executed, `Logic` uses `StorageManager` to save the updated `AddressBook` through the `saveAddressBook` method.
+
+The `StorageManager` class calls on the `JsonAddressBookStorage` class to convert all objects in the `AddressBook` to JSON formatting. The converted JSON objects are consolidated in the `JsonSerializableAddressBook` class and it is serialized to JSON format and saved using the `saveJsonToFile` method.
+
+The sequence diagram below illustrates how data is saved within the `Storage` component when the user issues a command.
-
+
-
+
+
+
-### Storage component
+#### Loading of Data
-**API** : [`Storage.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/storage/Storage.java)
+When the application is initialized, the `Storage` component reads the JSON objects from the save file and converts them back to objects that can be used to initialize the `Model` component.
+This is done using the `readJsonFile` method of the `JsonUtil` class which utilizes the methods defined in the `JsonAdapted` classes to convert the saved JSON data back to objects that can be used by the `Model` component.
-
+The sequence diagram below illustrates how data is loaded within the `Storage` component when the application is initialized.
-The `Storage` component,
+
+
+
+In summary, the `Storage` component:
* can save both address book data and user preference data in JSON format, and read them back into corresponding objects.
* inherits from both `AddressBookStorage` and `UserPrefStorage`, which means it can be treated as either one (if only the functionality of only one is needed).
* depends on some classes in the `Model` component (because the `Storage` component's job is to save/retrieve objects that belong to the `Model`)
-### Common classes
+
+
+### Common Classes
Classes used by multiple components are in the `seedu.addressbook.commons` package.
+These classes provide utility functions that are used across different components such as
+`CollectionUtil`, `StringUtil`, `JsonUtil` etc. It also contains app wide constants and exceptions.
--------------------------------------------------------------------------------------------------------------------
+
+
+
+
## **Implementation**
-This section describes some noteworthy details on how certain features are implemented.
+This section describes some noteworthy details on how certain features are implemented
-### \[Proposed\] Undo/redo feature
+
-#### Proposed Implementation
+### General Features
-The proposed undo/redo mechanism is facilitated by `VersionedAddressBook`. It extends `AddressBook` with an undo/redo history, stored internally as an `addressBookStateList` and `currentStatePointer`. Additionally, it implements the following operations:
+As these general features do not require any arguments, the `AddressBookParser` directly instantiates the corresponding command classes.
-* `VersionedAddressBook#commit()` — Saves the current address book state in its history.
-* `VersionedAddressBook#undo()` — Restores the previous address book state from its history.
-* `VersionedAddressBook#redo()` — Restores a previously undone address book state from its history.
+
-These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively.
+#### **Help Command** : `help`
-Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
+The `help` command utilizes the `java.awt.Toolkit` class to copy the user guide link to the user's clipboard.
-Step 1. The user launches the application for the first time. The `VersionedAddressBook` will be initialized with the initial address book state, and the `currentStatePointer` pointing to that single address book state.
+##### Executing the Command
-
+On execution of the `HelpCommand`, the `copyToClipboard` method is called which retrieves the system clipboard
+through `Toolkit.getDefaultToolkit().getSystemClipboard()` and copies the user guide link to the clipboard by using
+`setContents` method.
-Step 2. The user executes `delete 5` command to delete the 5th person in the address book. The `delete` command calls `Model#commitAddressBook()`, causing the modified state of the address book after the `delete 5` command executes to be saved in the `addressBookStateList`, and the `currentStatePointer` is shifted to the newly inserted address book state.
+##### Design Considerations
-
+We designed the help command to copy the user guide link directly to the clipboard as we wanted our application to be
+CLI optimized. This allows our target users to easily access the user guide without having to use their mouse
+to navigate to the user guide link.
-Step 3. The user executes `add n/David …` to add a new person. The `add` command also calls `Model#commitAddressBook()`, causing another modified address book state to be saved into the `addressBookStateList`.
+
-
+#### **Clear Command** : `clear`
-
:information_source: **Note:** If a command fails its execution, it will not call `Model#commitAddressBook()`, so the address book state will not be saved into the `addressBookStateList`.
+The `clear` command allows users to clear all persons and exams from the persons and exams list.
-
+##### Executing the Command
-Step 4. The user now decides that adding the person was a mistake, and decides to undo that action by executing the `undo` command. The `undo` command will call `Model#undoAddressBook()`, which will shift the `currentStatePointer` once to the left, pointing it to the previous address book state, and restores the address book to that state.
+The `ClearCommand` simply sets the `AddressBook` in the `Model` component to a new `AddressBook` object, effectively clearing all persons and exams from the persons and exams list.
-
+##### Design Considerations
-
:information_source: **Note:** If the `currentStatePointer` is at index 0, pointing to the initial AddressBook state, then there are no previous AddressBook states to restore. The `undo` command uses `Model#canUndoAddressBook()` to check if this is the case. If so, it will return an error to the user rather
-than attempting to perform the undo.
+We designed the `clear` command to clear all persons and exams from their respective lists to provide users with a quick and easy way to reset the application to its initial state. This is useful for users who want to start over or clear the application for a fresh start.
-
+
-The following sequence diagram shows how an undo operation goes through the `Logic` component:
+#### **List Command** : `list`
-
+The `list` command allows users to list all persons in the persons list.
-
:information_source: **Note:** The lifeline for `UndoCommand` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
+##### Executing the Command
-
+The `ListCommand` retrieves the `filteredPersonList` from the `Model` component and returns a `CommandResult` object containing the list of persons to be displayed on the UI.
-Similarly, how an undo operation goes through the `Model` component is shown below:
+##### Design Considerations
-
+We designed the `list` command to list all persons in the persons list to provide users with a quick and easy way to view all persons in the persons list. This is useful to revert the UI back to the default view after a find command has been executed which filters the persons displayed on the UI.
-The `redo` command does the opposite — it calls `Model#redoAddressBook()`, which shifts the `currentStatePointer` once to the right, pointing to the previously undone state, and restores the address book to that state.
+
-
:information_source: **Note:** If the `currentStatePointer` is at index `addressBookStateList.size() - 1`, pointing to the latest address book state, then there are no undone AddressBook states to restore. The `redo` command uses `Model#canRedoAddressBook()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.
+
-
+### Contact Management Features
-Step 5. The user then decides to execute the command `list`. Commands that do not modify the address book, such as `list`, will usually not call `Model#commitAddressBook()`, `Model#undoAddressBook()` or `Model#redoAddressBook()`. Thus, the `addressBookStateList` remains unchanged.
+All contacts are stored as `Person` objects in the `UniquePersonList` object under the `AddressBook` of the `Model` component.
+There is an additional `filteredPersons` list stored in the `Model` component that stores the persons currently displayed in the `PersonListPanel` on the UI. This list is updated whenever the user issues a command that might change the persons displayed in the `PersonListPanel`.
-
+
-Step 6. The user executes `clear`, which calls `Model#commitAddressBook()`. Since the `currentStatePointer` is not pointing at the end of the `addressBookStateList`, all address book states after the `currentStatePointer` will be purged. Reason: It no longer makes sense to redo the `add n/David …` command. This is the behavior that most modern desktop applications follow.
+#### **Add Person Command** : `add`
-
+The `add` command allows users to add a person to the persons list.
-The following activity diagram summarizes what happens when a user executes a new command:
+The user can specify the person's:
+* name (`Name`),
+* phone number (`Phone`),
+* address (`Address`),
+* email (`Email`),
-
+and optionally provide additional information such as their:
+* matriculation number (`Matric`),
+* reflection (`Reflection`),
+* studio (`Studio`),
+* and tags (`Tag`).
-#### Design considerations:
+
-**Aspect: How undo & redo executes:**
+##### Parsing User Input
+The `AddCommandParser` class is responsible for parsing user input to extract the details of the person to be added. It uses the `ArgumentTokenizer` to tokenize the input string, extracting prefixes and their associated values. It ensures that all mandatory fields are present and that there are no duplicate prefixes in the user input.
-* **Alternative 1 (current choice):** Saves the entire address book.
- * Pros: Easy to implement.
- * Cons: May have performance issues in terms of memory usage.
+##### Executing the Command
+The `AddCommand` class creates a new `Person` object with the parsed details.
+The `Person` object is then added to the `UniquePersonList` through the `addPerson` method in the `Model` component.
-* **Alternative 2:** Individual command knows how to undo/redo by
- itself.
- * Pros: Will use less memory (e.g. for `delete`, just save the person being deleted).
- * Cons: We must ensure that the implementation of each individual command are correct.
+
-_{more aspects and alternatives to be added}_
+##### Sequence Diagram
-### \[Proposed\] Data archiving
+The sequence diagram below illustrates a more in-depth view of the interactions regarding the parsing of user input.
+It takes an add command: `execute(add n|Dohn Joe p|98765432 a|123 e|dohn@gm.com m|A1234567X s|S1 r|R1)` as an example.
-_{Explain here how the data archiving feature will be implemented}_
+
+
---------------------------------------------------------------------------------------------------------------------
+**Note:** The lifeline for `AddCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram.
+
-## **Documentation, logging, testing, configuration, dev-ops**
+The parsing is detailed as follows:
+
-* [Documentation guide](Documentation.md)
-* [Testing guide](Testing.md)
-* [Logging guide](Logging.md)
-* [Configuration guide](Configuration.md)
-* [DevOps guide](DevOps.md)
+
+
---------------------------------------------------------------------------------------------------------------------
+##### Design Considerations
-## **Appendix: Requirements**
+**Use of `Email` Field as Unique Identifier**
-### Product scope
+We have chosen to use the `Email` field as a unique identifier. Due to the real-world implementation of email addresses, and specifically in NUS, email addresses are unique to each person. This allows for easy identification of persons and prevents the creation of duplicate persons with the same email address.
-**Target user profile**:
+This is opposed to using the `Name` field as a unique identifier, as an app with our proposed scale will likely be handling a large number of persons potentially having the same name. This would make it difficult to identify or keep track of persons with the same name.
-* has a need to manage a significant number of contacts
-* prefer desktop apps over other types
-* can type fast
-* prefers typing to mouse interactions
-* is reasonably comfortable using CLI apps
+**Compulsory and Non-compulsory Fields**
-**Value proposition**: manage contacts faster than a typical mouse/GUI driven app
+We have chosen to make the following fields compulsory as they are essentials and most likely available to the head TA:
+* `Name`
+* `Email`
+* `Phone`
+* `Address`
+The following fields are optional as they may not be available for all persons:
+* `Matric`
+* `Reflection`
+* `Studio`
+* `Tag`
-### User stories
+
-Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*`
+
-| Priority | As a … | I want to … | So that I can… |
-| -------- | ------------------------------------------ | ------------------------------ | ---------------------------------------------------------------------- |
-| `* * *` | new user | see usage instructions | refer to instructions when I forget how to use the App |
-| `* * *` | user | add a new person | |
-| `* * *` | user | delete a person | remove entries that I no longer need |
-| `* * *` | user | find a person by name | locate details of persons without having to go through the entire list |
-| `* *` | user | hide private contact details | minimize chance of someone else seeing them by accident |
-| `*` | user with many persons in the address book | sort persons by name | locate a person easily |
+
-*{More to be added}*
+#### **Edit Person Command** : `edit`
-### Use cases
+The `edit` command allows a user to edit the details of an existing person.
-(For all use cases below, the **System** is the `AddressBook` and the **Actor** is the `user`, unless specified otherwise)
+##### Parsing User Input
-**Use case: Delete a person**
+The `EditCommandParser` class is responsible for parsing user input to extract the index of the person to be edited and the new details of the person.
+It uses the `ArgumentTokenizer` class to tokenize the user input string, extracting the index of the person to be edited and the new details of the person. It ensures that the index is valid and that there are no duplicate prefixes in the user input.
-**MSS**
+##### Executing the Command
-1. User requests to list persons
-2. AddressBook shows a list of persons
-3. User requests to delete a specific person in the list
-4. AddressBook deletes the person
+The `EditCommand` first retrieves the person to be edited from the `Model` component.
+This is done by first retrieving the `filteredPersonList` from the `Model` component using the `getFilteredPersonList` method
+The person to be edited is then retrieved from the `filteredPersonList` using the index provided by the user.
+The `EditCommand` then creates a new `Person` object with the new details provided by the user and the selected person's existing details. The `Person` object is then updated in the `UniquePersonList` through the `setPerson` method in the `Model` component.
- Use case ends.
+##### Activity Diagram
+
+The activity diagram below illustrates the workflow involved in executing the `edit` command. In practice, a `Reject` activity will result in a `CommandException` being thrown.
+
+
+
+
+
+
+
+
+
+#### **Delete Person Command** : `delete`
+
+The `delete` command allows a user to delete a person with the specified index.
+
+##### Parsing User Input
+
+The `DeleteCommandParser` class is responsible for parsing user input to extract the index of the person to be deleted. It uses the `ArgumentTokenizer` to tokenize the input string, extracting the index of the person to be deleted and ensuring that the index is valid.
+
+##### Executing the Command
+
+The `DeleteCommand` class first retrieves the person to be deleted from the `Model` component. This is done by first retrieving the `filteredPersonList` from the `Model` component using the `getFilteredPersonList` method. The person to be deleted is then retrieved from the `filteredPersonList` using the index provided by the user. The `DeleteCommand` then deletes the person from the `UniquePersonList` through the `deletePerson` method in the `Model` component.
+
+##### Sequence Diagram
+
+For more details on the implementation of the `delete` command, refer to the [Delete Command Sequence Diagram](#example-of-parsing-user-input-delete-command).
+
+##### Design Considerations
+
+We have chosen to implement the `delete` command to accept the index of the person to be deleted to maximize convenience for the user. The numbering of the lists will be displayed to the user, making indexing very intuitive.
+
+
+
+
+
+
+
+#### **Find Command** : `find`
+
+The `find` command lets users search for persons by substring matching. The user can select any parameter to search under:
+`NAME`, `EMAIL`, `TAG`, `MATRIC`, `REFLECTION`, `STUDIO`, and `TAGS` can all be used. E.g. to search for all persons under studio `S2`, the user can use `find s|s2`.
+
+The user can also use two other prefixes: `lt` and `mt` to search for persons with scores less than or more than a certain value respectively.
+E.g. `find mt|50` will return all persons with scores more than 50.
+
+The `find` feature makes use of the predicate classes `PersonDetailPredicate` and `ExamPredicate`, as well as the method `updateFilteredPersonList`
+to update the model to show only persons that fulfill the criteria that the user has keyed in.
+
+##### Parsing User Input
+
+The `FindCommandParser` class is responsible for parsing user input to extract search criteria. It uses the `ArgumentTokenizer` to tokenize the input string,
+extracting prefixes and their associated values. Next, the method `verifyNoDuplicatePrefixesFor` ensures that there are no duplicate prefixes in the user input.
+Following that, the `extractPrefixForFindCommand` method ensures that only one valid, non-empty prefix is provided in the input.
+After which, the `extractValidKeyword` method ensures that the keyword provided in the input is valid in the case that the prefix is `mt|` or `lt|`,
+since these two prefixes specifically require a numerical value as the keyword instead of a string value.
+
+##### Executing the Command
+
+The `FindCommand` class is responsible for executing the command for filtering the list in the application.
+
+Using the prefix and keyword from parsing user input, a `FindCommand` is created. the `execute` method is then called by the `LogicManager`.
+
+**Creating Predicate**
+
+
+
+**Note:** The `PersonDetailPredicate` and `ExamPredicate` classes implement the `Predicate` interface to filter contacts based on the search criteria.
+A brief overview of the two classes is given below:
+* `PersonDetailPredicate` takes a prefix and keyword as parameters, allowing it to filter contacts based on specific details like name, phone number, etc.
+* `ExamPredicate` takes a prefix, a keyword, and an exam as parameters, allowing it to filter contacts based on exam scores of a specific exam.
+
+
+
+The find command first checks if an exam is required by checking if the prefix is `mt|` or `lt|`.
+If an exam is required, the `selectedExam` is retrieved from the `model` and passed to the `ExamPredicate` constructor along with the prefix and keyword.
+Otherwise, the `PersonDetailPredicate` class is created with the prefix and keyword.
+
+**Updating Filtered Person List**
+
+The `ModelManager` class implements the `Model` interface and manages the application's data. It maintains a `filteredPersons` list,
+which is a filtered list of contacts based on the applied predicate. The `updateFilteredPersonList` method implemented in `ModelManager`
+updates the filtered list based on the predicate provided.
+
+When the `FindCommand` is executed, the `updateFilteredPersonList` method is called with either the `PersonDetailPredicate` or `ExamPredicate` as a parameter.
+This updates the `filteredPersons` list to show only persons that fulfill the conditions set in the `test` method in either of the predicates.
+
+
+
+**User Interface Interaction**
+
+After the `filteredPersons` list is updated, the user interface is updated such that the `PersonListPanel` now shows persons that fulfill the predicate generated by the original user input.
+
+The following sequence diagram illustrates the `find` command with the user input `find n|Alice`.
+
+
+The next sequence diagram details the creation of the predicate, as well as the updating of the `filteredPersons` list in the `Model` component.
+
+
+
+
+The following activity Diagram illustrates the user execution of the `find` command.
+
+
+The next activity diagram is an expansion of the previous diagram, detailing the case where the user searches for contacts based on exam scores.
+
+
+##### Design Considerations
+
+**User Interface Consistency**
+
+The choice of implementing the command to use prefixes to determine the filter criteria ensures consistency with other commands in the application.
+As this command follows a similar structure to all other commands, it is easier for users to learn and use the application.
+
+**Flexibility in Search Criteria**
+
+By allowing users to specify search criteria using different prefixes (name, phone, email, etc.), the implementation offers flexibility.
+Users can search for contacts based on various details, enhancing the usability of the feature.
-**Extensions**
+In the context of our potential users,
+we considered that users would likely have to sometimes filter students by their classes, or filter people by their roles (student, tutor, professor).
+So we opted to implement this feature with the flexibility of using all prefixes to account for all these potential use cases.
-* 2a. The list is empty.
+Furthermore, with consideration that our potential users will interact with exam scores, we wanted to integrate the find functionality
+to search for contacts based on exam scores. Hence, we decided to introduce the `mt|` and `lt|` prefixes to allow users to search for contacts based on exam scores.
- Use case ends.
+
-* 3a. The given index is invalid.
+**Two Predicate Classes**
- * 3a1. AddressBook shows an error message.
+The implementation of two predicate classes, `PersonDetailPredicate` and `ExamPredicate`, allows for a clear separation of concerns.
- Use case resumes at step 2.
+The `PersonDetailPredicate` class is responsible for filtering contacts based on details like name, phone number, etc.,
+while the `ExamPredicate` class is responsible for filtering contacts based on exam scores.
-*{More to be added}*
+The alternative would be to have a single predicate class that handles all filtering, but this would make this supposed class more complex and harder to maintain.
-### Non-Functional Requirements
+**Predicate-based Filtering**
-1. Should work on any _mainstream OS_ as long as it has Java `11` or above installed.
-2. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage.
-3. A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
+As the `Model` class was built prior to the implementation of this feature, we did our best to re-use available methods
+instead of unnecessarily reprogramming already existing logic. Hence, we decided to craft the command around the idea of a
+custom predicate as the `Model` class already had a `updateFilteredPersonList` method implemented that would filter persons using a predicate.
-*{More to be added}*
+**Extensibility**
-### Glossary
+This design allows for easy extension to accommodate future enhancements or additional search criteria.
+New prefixes can be added to support additional search criteria without significant changes as we merely need to update our `Predicate` logic.
+This ensures that the implementation remains adaptable to evolving requirements and we can upgrade and improve the feature whenever required.
-* **Mainstream OS**: Windows, Linux, Unix, MacOS
-* **Private contact detail**: A contact detail that is not meant to be shared with others
+
+
+
+
+
+
+#### **Delete Shown Command** : `deleteShown`
+
+The `deleteShown` command relies on the `filteredPersons` list in the `Model` component to delete the persons currently displayed in the `PersonListPanel`.
+
+##### Executing the Command
+
+The `deleteShown` command first retrieves the `filteredPersons` list from the `Model` component using the `getFilteredPersonList` method. The `deleteShown` command then iterates through the `filteredPersons` list and deletes all currently shown `Persons` from the `UniquePersonList`.
+
+If the currently filtered list does is not showing between 0 and the total number of existing persons, the `deleteShown` command will throw a `CommandException`.
+
+##### Updating Filtered Person List
+
+After deleting all persons currently displayed in the `PersonListPanel`, the `filteredPersons` list in the `Model` component is updated to show all remaining persons in the persons list.
+
+The following activity diagram illustrates the workflow of the execution of the `deleteShown` command:
+
+
+
+##### Design Considerations
+
+**Reliance on `find` Command**
+
+Similarly to the `copy` command, the `deleteShown` command is designed to be used with the find command, which filters the persons displayed in the `PersonListPanel`. Consequently, the flexibility of the `deleteShown` command relies heavily on the implementation of the `find` command. Due to this dependency, any changes to the `find` command may affect the functionality of the `deleteShown` command.
+
+
+
+
+
+
+
+#### **Import Contacts Command** : `import`
+
+The `import` command allows users to import contacts from a CSV file. Users can specify the file path of the CSV file to
+import contacts from and with the validation and checking of the CSV rows, person objects can be added to the persons list in the application.
+
+##### Parsing User Input
+
+The `ImportCommandParser` class is responsible for parsing user input to extract the file path of the CSV file to be imported. It uses the `ArgumentTokenizer` to tokenize the input string, extracting the file path of the CSV file to be imported.
+
+##### Executing the Command
+
+The `ImportCommand` class first makes use `OpenCSV` library which parses the CSV file into a `List`, with each `String[]`
+representing a row in the CSV file. The `List` is further parsed row by row by the `readCsvFile` method, which
+returns a `Pair`. The key of the returned `Pair` is a `personsData` list containing the `Person` objects successfully parsed from the CSV file and the value is an error report containing all the errors that occurred during the process of reading from the CSV file.
+
+The `ImportCommand` then iterates through the `personsData` list and adds each `Person` object to the `Model` component
+through repeated use of the `AddCommand`. Errors that occur during this process are also added to the error report.
+
+In summary, The import process is done in the following steps:
+1. `ImportCommand` reads the CSV file with the given file path.
+2. The CSV file is parsed and each row is converted into an `AddCommand`
+3. The `AddCommand` is then executed passing the same model as import command.
+4. The `AddCommand` then adds the person to the model.
+
+**Handling duplicate persons**
+
+Duplicate records in the imported CSV file is handled by `AddCommand`, which will check if the person already exists in the model. If the person already exists, the `AddCommand` throws a `CommandException` which is caught by the `ImportCommand` and added to an error report.
+
+**Handling invalid CSV files**
+
+Invalid files are handled by `ImportCommand`, with the help of `ImportCommandParser` and `CsvUtil`. `ImportCommandParser` will check if is a CSV file.
+`CsvUtil` will check if the CSV file is valid and will return a list of persons and an error report. The error report will be displayed to the user if there are any errors.
+
+Overall, the conditions checked are:
+- The file exists
+- The file is a CSV file
+- **The first row of the file is the header row**. In which all compulsory fields for creating a persons object
+ (ie `name`, `email`, `address`, `phone`)are present. Optional headers will be read if present. Headers in the CSV that are not a field in `Person` will be ignored.
+
+If the file is not valid, an error message will be returned.
+
+**Handling duplicate headers in the CSV file**
+
+Handled by CsvUtil. The first occurrence of the header will be used and the rest will be ignored.
+
+
+
+The sequence diagrams below illustrates the interactions within the `Logic` component when the user issues the command `import`.
+
+**Parsing**
+
+
+
+**Execution**
+
+
+
+
+
+**Reference Diagram for each addCommand in importCommand**
+
+
+
+
+
+
+##### Design Considerations
+
+**Usage of `AddCommand`**
+
+The main concern in the increased coupling between `ImportCommand` and `AddCommand`. However, we established that this coupling was actually a good thing, as the incorporation of the `AddCommand` allowed us to reuse the validation and error handling that was already implemented in the `AddCommand`. Furthermore, should we ever need to change the validation and error handling in the `AddCommand`, the `ImportCommand` would automatically inherit these changes. By making `AddCommand` the gate in which all persons are added to the model, we ensure that all persons added to the model are validated and handled in the same way.
+
+
+
+
+
+
+
+#### **Copy Command** : `copy`
+
+The `copy` command enables users to quickly copy the email addresses of the persons currently displayed to them in the
+`PersonListPanel`. The copied emails are stored in the users' clipboard and can be pasted into an email client.
+This feature is useful when users need to send emails to a group of persons.
+
+The copy command is a child of the `command` class and relies on the `filteredPersons` list in the `Model` component,
+as well as the `java.awt` package to copy the emails of all currently displayed persons to the users' clipboard.
+
+##### Parsing User Input
+
+The `CopyCommand` class is instantiated directly by the `AddressBookParser` class when the user inputs the `copy` command.
+This is because the `copy` command does not require any additional arguments from the user.
+
+##### Executing the Command
+
+The `CopyCommand` class is responsible for executing the command for obtaining the emails of the filtered persons and copying them to the clipboard.
+It iterates through the `filteredPersons` list in the `Model` component and extracts the email addresses of each person.
+The email addresses are then concatenated into a single string, separated by commas, and copied to the clipboard using the `java.awt` package.
+
+**User Interface Interaction**
+
+After the `CopyCommand` is executed, the `UI` component updates the `ResultDisplay` to show a message indicating that the emails have been copied to the clipboard.
+
+The following activity diagram summarizes the steps involved in executing the `copy` command:
+
+
+##### Considerations
+
+**Reliance on `find` Command**
+
+The `copy` command is designed to be used with the find command, which filters the persons displayed in the `PersonListPanel`.
+Consequently, the flexibility of the `copy` command relies heavily on the implementation of the `find` command.
+Due to this dependency, any changes to the `find` command may affect the functionality of the `copy` command.
+
+
+
+##### Extensibility
+
+Due to the simplicity of the `copy` command, there are limited opportunities for extending its functionality.
+However, future enhancements could include the ability to copy other details of persons, such as phone numbers or addresses.
+
+##### Alternative Implementations
+
+**Alternative 1: Copying emails of all persons**
+
+Copies the emails of all persons in the persons list, regardless of whether they are currently displayed in the `PersonListPanel`.
+However, this approach may lead to users copying a large number of emails unintentionally, which could be overwhelming.
+Furthermore, it may not be clear to users which emails are being copied.
+
+**Alternative 2: Copying emails into a file**
+
+Instead of copying the emails to the clipboard, the emails could be saved into a file.
+This approach would allow users to access the emails at a later time and would prevent the loss of copied emails if the clipboard is cleared.
+However, it may be less convenient for users who want to paste the emails directly into an email client.
+
+
+
+
+
+
+
+#### **Export Command** : `export`
+
+The `export` command allows users to export the details of each person currently displayed in the `PersonListPanel` to a CSV file. The CSV file is generated in the file `./addressbookdata/avengersassemble.csv`.
+
+The user can first use the `find` feature to filter out the relevant persons, which will be displayed in the `PersonListPanel`.
+The `export` feature also relies on the Jackson Dataformat CSV module and the Jackson Databind module to write the details of persons to the CSV file `./addressbookdata/avengersassemble.csv`.
+
+##### Parsing User Input
+
+The `export` command does not require any additional arguments from the user. Hence, an `ExportCommandParser` class is not required.
+`AddressBookParser` directly creates an `ExportCommand` object.
+
+##### Executing the Command
+
+**Data Retrieval**
+* The `execute` method retrieves the `filteredPersons` list in `Model` by calling the `getFilteredPersonList()` method in `Model`.
+ This list stores the relevant persons currently displayed in the `PersonListPanel`.
+ It then creates a temporary `AddressBook` object and iterates through the `filteredPersons` list to add each person from the list into the `AddressBook`.
+ The data is then written to a JSON file named `filteredaddressbook.json` with the `writeToJsonFile` method in `ExportCommand`.
+
+* The `execute` method also retrieves the address book file path by calling the `getAddressBookFilePath()` method in `Model` (this `AddressBook` stores information of **all** persons and exams).
+ This file path is retrieved to obtain information on the examinations added in the application
+
+The sequence diagram illustrates the interactions between the `Logic` and `Model` components when data is being retrieved from `Model` when `export` is executed:
+
+
+
+
+
+
+
+**JSON File Handling**
+
+The contents of both the JSON files retrieved in the above section is read with the `readJsonFile()` method in `ExportCommand` and returned as JSON trees, `filteredJsonTree` and `unfilteredJsonTree`.
+This method uses Jackson's `ObjectMapper`.
+
+* From the `filteredJsonTree`, the persons array is extracted using the `readPersonsArray()` method in `ExportCommand` to obtain the filtered persons and their data.
+* From the `unfilteredJsonTree`, the exams array is extracted using the `readExamsArray()` method in `ExportCommand` to obtain the exams.
+
+
+
+**CSV Conversion**
+
+A CSV file, `avengersassemble.csv`, to write the data to, is created.
+Its directory is also created using the `createCsvDirectory()` method in `ExportCommand` if the directory does not exist.
+The CSV schema is dynamically built based on the structure of the JSON array using the `buildCsvSchema()` method in `CsvUtil`. This method relies on the Jackson Dataformat CSV module to build the CSV schema.
+The CSV schema and JSON data are used to write to the CSV file using Jackson's `CsvMapper`.
+
+The following sequence diagram shows the interactions within the different classes in the JSON file handling section and CSV conversion section when the `export` command is executed:
+
+
+
+
+
+
+
+
+
+
+##### Design Considerations
+
+**Obtaining Exam Names from `exams` Array in the Address Book File Path**
+* **Alternative 1 (current choice):** Obtaining exam names from `exams` array in the address book file path.
+ * A person in the JSON file will only contain the exam details if they have a score for that exam.
+ Therefore, with this choice, if no one in the filtered person's JSON file contains any score for a specific exam, the exam name will still be exported.
+ * By adopting this alternative, users will be informed about the existence of an exam even if none of the persons in the filtered list have a score for that exam.
+
+* **Alternative 2:** Obtaining exam names directly from `persons` array in the filtered person's JSON file.
+ * This choice will only export an exam if someone in the filtered persons list has a score for that exam.
+
+
+
+**Adding `Exam:` to Exam Names in the CSV Column Headings**
+Since users have the flexibility to determine the names of exams added, there's a possibility of adding an exam with the same name as a field (e.g. `reflection`).
+This could lead to confusion when mapping the CSV schema and JSON data.
+Therefore, appending `Exam:` to the beginning of exam names in the CSV column headings can help mitigate this potential confusion.
+
+
+
+
+
+
+
+#### **Feature: Addition of Optional Fields (Matric)**
+
+The optional `Matric` field enables the user to store the matriculation number of a person. The field is stored as a `Matric` in the `Person` object.
+
+Note: The optional `Studio` and `Reflection` fields are similarly implemented.
+
+##### Implementation Details
+
+The `Matric` class is a simple wrapper class that ensures it is valid according to NUS matriculation number format and is not empty.
+The `Matric` field is used by the `add` and `edit` commands.
+
+##### Parsing User Input: `add`
+
+For the `add` command, as opposed to the `name` and other fields, the parser does not check if a prefix for `Matric` is present. This is because we define the `Matric` field to be optional as contacts (e.g. professors) do not need to have a matriculation number.
+
+The parser also verifies that there are no duplicate prefixes for `Matric` in a single `add` command. A new Person is then created with the `Matric` field set to the parsed `Matric` object.
+
+If there is no `Matric` field present, the `Matric` field of the new `Person` object is set to `null`.
+
+##### Parsing User Input: `edit`
+
+For the `edit` command, the parser will add or update the `Matric` field of the person being edited.
+
+
+
+
+
+#### **Feature: Automatic Tagging of Persons**
+
+A `student` tag is automatically added during the parsing of the `add` command based on the presence of the `Matric` field of the person being added.
+
+##### Implementation Details
+
+During the parsing of the `add` command, the parser will check if the `Matric` field is present, indicating that they are a student.
+The parser also generates `Tag` objects based on the user input. The existing tags are updated with the new automatically generated tag.
+
+The activity diagram is as follows:
+
+
+
--------------------------------------------------------------------------------------------------------------------
-## **Appendix: Instructions for manual testing**
+
-Given below are instructions to test the app manually.
+
-
:information_source: **Note:** These instructions only provide a starting point for testers to work on;
-testers are expected to do more *exploratory* testing.
+### **Exam Features**
+
+There are 4 main commands that are used to interact with the exam feature: `addExam`, `deleteExam`, `selectExam` and `deselectExam`.
+
+All exams are stored in the `UniqueExamList` object in `AddressBook` of the `Model` component. The `Model` component also stores the currently selected exam in the `selectedExam` field.
+
+
+
+
+
+#### **Add Exam Command** : `addExam`
+
+The `addExam` command allows users to add an exam to the application.
+The user can specify the name of the exam and the maximum score of the exam.
+The exam is then added and stored in the `UniqueExamList`.
+
+##### Parsing User Input
+
+The `AddExamCommandParser` is responsible for parsing user input to extract the `name` and the `maxScore` of the exam.
+It uses the `ArgumentTokenizer` to tokenize the input string, extracting `name` and `maxScore`.
+It ensures that `name` and `maxScore` are valid and present in the user input, and that there are no duplicate prefixes in the user input.
+The `name` and `maxScore` are then used to instantiate an `AddExamCommand`.
+
+##### Executing the Command
+
+The `AddExamCommand` class creates a new `Exam` object with the parsed arguments
+It adds the `Exam` to the `UniqueExamList` through the `addExam` method in the `Model` component.
+If the exam already exists in the list, a `CommandException` is thrown.
+
+
+
+
+
+#### **Delete Exam Command** : `deleteExam`
+
+The `deleteExam` command allows users to delete an exam from the application.
+The user can specify the index of the exam to be deleted.
+The exam is then removed from the `UniqueExamList`.
+
+##### Parsing User Input
+
+The `DeleteExamParser` is responsible for parsing user input to extract the `index` of the exam to be deleted.
+It uses the `ArgumentTokenizer` to tokenize the input string, extracting the `index`.
+It ensures that the `index` is valid and present in the user input, and that there are no other prefixes in the user input.
+The `index` is used to instantiate a `DeleteExamCommand`.
+
+##### Executing the Command
+
+The `DeleteExamCommand` uses the index to delete the exam from the `UniqueExamList` in the `Model` component.
+It first retrieves the `UniqueExamList` by using the `getExamList` method in the `Model` component.
+It then retrieves the exam from the `UniqueExamList` using the user provided index.
+If the index is greater than the size of the list, a `CommandException` is thrown.
+Using the retrieved exam, it then deletes the exam from the `UniqueExamList` through the `deleteExam` method in the `Model` component.
+
+
+
+
+
+
+
+#### **Sequence Diagrams Illustrating Exam Modification**
+
+The following two sequence diagram illustrates the interactions between the Logic and Model when an exam is modified. This diagram uses the `addExam` command as an example.
+
+**Parsing**
+
+
+
+**Execution**
+
+
+
+Note: `deleteExam` follows a similar structure, differing in the arguments parsed and the methods called on the `Model` component (e.g. deleting from `UniqueExamList` instead of adding to it).
+
+
+
+
+
+
+
+#### **Select Exam Command** : `selectExam`
+
+The `selectExam` command allows users to select an exam from the `UniqueExamList`.
+The selection of exams is heavily used in conjunction with our exam score features.
+
+##### Parsing User Input
+
+The `SelectExamCommandParser` is responsible for parsing user input to extract the `index` of the exam to be selected.
+It uses the `ArgumentTokenizer` to tokenize the input string, extracting the `index`.
+It ensures that the `index` is valid and present in the user input, and that there are no other prefixes in the user input.
+
+##### Executing the Command
+
+The `SelectExamCommand` uses the index to select an exam from the `UniqueExamList` in the `Model` component.
+It first retrieves the `UniqueExamList` by using the `getExamList` method in the `Model` component.
+It then retrieves the exam from the `UniqueExamList` using the user provided index.
+If the index is greater than the size of the list, a `CommandException` is thrown.
+Using the retrieved exam, it then sets the `selectedExam` field in the `Model` component using the `selectExam` method.
+
+
+
+
+
+#### **Deselect Exam Command** : `deselectExam`
+
+The `deselectExam` command allows users to deselect the currently selected exam.
+
+##### Parsing User Input
+
+The `deselectExam` command does not take any arguments from the user.
+Hence, a `DeselectExamCommandParser` is not required. `AddressBookParser` directly creates a `DeselectExamCommand` object.
+
+##### Executing the Command
+
+The `DeselectExamCommand` uses the `deselectExam` method in the `Model` component to deselect the currently selected exam.
+It sets the `selectedExam` field in the `Model` component to `null`.
+If there is no exam selected, a `CommandException` is thrown.
+
+
+
+
+
+
+
+#### **Sequence Diagrams Illustrating Exam Selection**
+
+The following sequence diagram illustrates the interactions between the Logic and Model when the `SelectExamCommand` is executed.
+
+
+
+Notes:
+- The `ObservableList` object is what is returned when retrieving the `UniqueExamList`. This prevents unwanted modifications to the `UniqueExamList` when retrieving the selected exam.
+- `deselectExam` follows a similar structure as the diagram above, differing in the arguments parsed and the methods called on the `Model` component (i.e. calling `deselectExam` on `Model` instead of `selectExam`).
+
+
+
+
+
+#### **Considerations for Exam Features**
+
+##### Using a Selection System for Exams
+
+We decided to implement a selection system for exams to complement the exam score feature. The application would only display the scores of the selected exam, making it easier for users to manage and view the scores.
+
+Our alternative design was to display the scores of all exams at once on every person. However, this alternative design would have made the UI cluttered and less user-friendly. The selection system allows users to focus on the scores of a specific exam, making it easier to view and manage the scores.
+
+##### Using Index for Exam Selection
+We were initially torn between the selection of exams using the exam name or the index. We eventually settled on using the index as it is easier for users to type and remember short numeric codes rather than potentially long and complex exam names which are more prone to typographical errors.
+
+##### Allowing Deselection of Exams
+We decided to allow users to deselect exams as the exam scores and score statistics are displayed based on the selected exam. Deselecting the exam allows users to get rid of the displayed scores and statistics when they are no longer needed.
+
+##### Extensibility
+The design of the exam feature allows for easy extension to accommodate future enhancements or additional functionalities. Methods for managing exams are implemented in the `Model` component, and the updating of UI for Exams is abstracted into the UI component, Making it easy to add new commands or features related to exams.
+
+
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+
+### **Exam Score Features**
+
+There are 3 main commands that are used to interact with exam scores of each person: `addScore`, `editScore` and `deleteScore`.
+
+
+
+
+
+#### **Add Score Command** : `addScore`
+
+The `addScore` command allows users to add a score for an exam to a person displayed in the application.
+The user should select the exam they want to add a score for, then specify the index of the person they want to add a score for, and the score they want to add.
+The score is then stored in a hashmap named `scores` within the `Person` object in the `Model` component.
+This hashmap maps the selected exam (an `Exam` object) to the specified score (a `Score` object).
+
+##### Parsing User Input
+
+The `AddScoreCommandParser` is responsible for parsing the user input to extract the index of the person in the displayed list to add a score to, and the score to add.
+It uses the `ArgumentTokenizer` to tokenize the input string, extracting the `index` and `score`.
+It also ensures that the `index` and `score` input value is valid, and that there are no duplicate prefixes in the user input.
+The `index` and `score` is then used in instantiating the `AddScoreCommand` by the `AddScoreCommandParser`.
+
+The following sequence diagram illustrates the parsing of an `addScore` command with the user input `addScore 1 s|100`:
+
+
+
+
+
+
+Note: The parsing of an `editScore` command follows a similar structure, differing in the object instantiated at the end of the `parse` method.
+`EditScoreCommandParser` instantiates an `EditScoreCommand` object.
+
+
+##### Executing the Command
+
+The `execute` method in `AddScoreCommand` retrieves the `filteredPersons` list in `Model`, and validates the target index against the list of filtered persons to ensure it is not out of bounds.
+It then fetches the person to add the score for based on the target index.
+It also retrieves the currently selected exam from the `Model`, and validates that the score to be added is not more than the maximum score of the selected exam.
+It adds the score to the person's existing `scores` hashmap using the `addExamScoreToPerson` method in the `Model`.
+
+
+
+The following sequence diagram illustrates the execution of an `addScore` command:
+
+
+
+
+
+
+Note: The execution of an `editScore` command follows a similar structure to the execution of an `addScore` command.
+
+
+
+
+
+
+#### **Edit Score Command** : `editScore`
+
+The `editScore` command allows users to edit a score for an exam of a person displayed in the application.
+The user should select the exam they want to edit the score for, then specify the index of the person they want to edit the score for, and the new score they want to edit to.
+The updated score is then stored in a hashmap named `scores` within the `Person` object in the `Model` component.
+This hashmap maps the selected exam (an `Exam` object) to the updated specified score (a `Score` object).
+
+##### Parsing User Input
+
+The `EditScoreCommandParser` is responsible for parsing the user input to extract the index of the person in the displayed list to edit the score for, and the new score to edit to.
+It uses the `ArgumentTokenizer` to tokenize the input string, extracting the `index` and `score`.
+It also ensures that the `index` and `score` input value is valid, and that there are no duplicate prefixes in the user input.
+The `index` and `score` is then used in instantiating the `EditScoreCommand` by the `EditScoreCommandParser`.
+
+##### Executing the Command
+
+The `execute` method in `EditScoreCommand` retrieves the `filteredPersons` list in `Model`, and validates the target index against the list of filtered persons to ensure it is not out of bounds.
+It then fetches the person to edit the score for based on the target index.
+It also retrieves the currently selected exam from the `Model`, and validates that the score to be added is not more than the maximum score of the selected exam.
+It updates the score for the selected exam in the person's existing `scores` hashmap using the `addExamScoreToPerson` method in `Model`.
+
+
+
+
+
+
+
+#### **Delete Score Command** : `deleteScore`
+
+The `deleteScore` command allows users to delete a score for an exam from a person displayed in the application.
+The user should select the exam they want to delete the score for, then specify the index of the person they want to delete the score for.
+The key-value pair (exam-score) is removed from the `scores` hashmap within the `Person` object.
+This operation removes both the selected exam (key) and the score (value), effectively deleting the score from `Person`.
+
+##### Parsing User Input
+
+The `DeleteScoreCommandParser` is responsible for parsing the user input to extract the index of the person in the displayed list to delete the score for.
+It uses the `ParserUtil` to parse the input string, extracting the `index`.
+It also ensures that the `index` is valid, and that there are no duplicate prefixes (i.e. there is only one `index` value) in the user input.
+The `index` is then used in instantiating the `DeleteScoreCommand` by the `DeleteScoreCommandParser`.
+
+The following sequence diagram illustrates the parsing of an `deleteScore` command with the user input `deleteScore 1`:
+
+
+
+
+
+##### Executing the Command
+
+The `execute` method in `DeleteScoreCommand` retrieves the `filteredPersons` list in `Model`, and validates the target index against the list of filtered persons to ensure it is not out of bounds.
+It then fetches the person to delete the score for based on the target index.
+It also retrieves the currently selected exam from the `Model`.
+It removes the score for the selected exam in the person's existing `scores` hashmap using the `removeExamScoreFromPerson` method in `Model`.
+
+
+
+
+
+
+
+
+
+
+
+#### **Import Exam Scores Command** : `importExamScores`
+
+The `importExamScores` command lets users import exam scores corresponding to existing exams and persons from a CSV file.
+
+##### Parsing User Input
+
+The `ImportExamScoresParser` class is responsible for parsing the user input. It uses the `ArgumentTokenizer` to tokenize the input string, extracting the file path of the CSV file to be imported.
+
+##### Executing the Command
+
+**Parsing CSV File**
+
+The `ImportExamScoresCommand` class reads the CSV file with the given file path.
+The CSV file is parsed with the `OpenCSV` library and a `List` is created, with each `String[]` representing a row in the CSV file.
+
+**File Validation**
+
+After parsing, a mapping of `Exam` objects to an inner mapping of an `email` string to a `Double` score is created. This mapping is used to validate the data in the CSV file.
+If the **file** is invalid, an error message is returned.
+
+The validation workflow for the **file** is as follows:
+
+
+
+
+
+If the file is valid, any invalid entries will be ignored, with the rest being successfully processed.
+
+A **column** will be ignored if:
+1. The column header is not the `email` column, but does not start with `Exam:`.
+2. The column header's name does not correspond to an existing `Exam` object. (i.e. Anything after `Exam:` is not an existing exam name.)
+
+
+
+A **row** will be ignored if:
+1. The `email` value does not correspond to an existing `Person`.
+
+
+
+A **cell** will be ignored if:
+1. The `Double` representing the score for an existing `Person` and `Exam` is not a valid `Score`.
+
+
+
+**Value Validation**
+
+For every valid row:
+
+The `Double` is parsed into a `Score` object.
+
+The `Model` object is then used to:
+* Get the `Exam` object corresponding to the exam name in the row;
+* Get the `Person` object corresponding to the email in the row;
+* And finally add the `Score` object to the correct `Person` for the correct `Exam`.
+
+
+
+##### Concrete Examples of Validation
+
+For concrete examples of the validation process, [refer to the manual testing section of the `importExamScores` command](#importing-exam-scores-importexamscores).
+
+
+
+
+
+
+
+
+#### **Score Statistics Feature**
+
+The exam statistics feature allows users to view the mean and median scores of the selected exam. The statistics are displayed in the `StatusBarFooter` element of the UI on the right side.
+
+The statistics are automatically updated whenever the selected exam is changed or when there are potential modifications to the scores of the selected exam.
+
+When there are no scores for the selected exam, the statistics are displayed as `No scores available`. When no exam is selected, the statistics are not displayed at all.
+
+##### Storage of Exam Statistics
+
+The `ScoreStatistics` class is used to store the mean and median scores of the selected exam. The `Model` component stores the `ScoreStatistics` object for the currently selected exam as a `SimpleObjectProperty`.
+
+##### Updating of Exam Statistics
+
+the `ModelManager` class implements a `updateSelectedExamStatistics` and `getSelectedExamStatistics` method to update the statistics.
+
+`updateSelectedExamStatistics` is called whenever the selected exam is changed or when there are potential modifications to the scores of the selected exam (deletion of a Person, adding of Score, etc.). This ensures that the `selectedExamStatistics` object is always kept up-to-date with the scores of the selected exam.
+
+The sequence diagram below illustrates the interactions within the `Model` component when the score statistics are updated using the `selectExam` command as an example.
+
+
+
+
+
+##### User Interface Interaction
+
+The `StatusBarFooter` element of the UI is initialized with an `ObservableValue` object. This object is bound to the `selectedExamStatistics` object in the `Model` component and is retrieved using the `getSelectedExamStatistics` method.
+
+Whenever a command is executed, the `StatusBarFooter` retrieves the updated statistics and displays them on the right side of the footer which can be seen at the bottom of the UI.
+
+##### Considerations for Exam Statistics Command
+
+**Storage of Exam Statistics**
+
+There were considerations to just avoid the storage of the statistics and calculate them on the fly whenever needed. However, this would have been inefficient as the statistics would have to be recalculated every time the selected exam is changed or when there are potential modifications to the scores of the selected exam. By storing the statistics, we can limit recalculations to only when necessary.
+
+Furthermore, storing the statistics allows us to maintain the code structure of our UI component, which is designed to observe and retrieve data from the `Model` component. If the statistics were to be calculated on the fly, the UI component would have to either calculate the statistics itself or request the `Model` component to calculate the statistics, which would have complicated the code structure by introducing more dependencies between the UI and Model components.
+
+**Using `ScoreStatistics` Class**
+
+The `ScoreStatistics` class was used to store the mean and median scores of the selected exam. This class was chosen as it provides a clean and structured way to store the statistics. The class also provides extensibility, as additional statistics can easily be added in the future by extending the class.
+
+
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+
+
+
+## **Planned Enhancements**
+
+
+
+#### Enhance Input Validation for `find` Command
+
+Currently, the `find` command only validates the `lt` and `mt` prefixes, where other prefixes are not validated. This means that users may search for persons with fields that do not exist to begin with, which is guaranteed to return no results.
+
+##### Planned Implementation
+
+We plan to enhance the `find` command to validate all prefixes other than `lt` and `mt`. This will ensure that users are not able to search for persons with fields that do not exist in the `Person` object.
+
+However, we need to be careful about overzealous input validation where users may still want to search for fields using incomplete parts of a field, and hence we have to balance these two considerations.
+
+For example, an extreme case will be to search for persons with the `Name` field with `~`, which is disallowed to begin with as `~` is not a valid character for a name. We plan to inform the user outright that the search is invalid and will not return any results.
+
+
+
+#### Update UI to Wrap Text
+
+Currently, the `ResultDisplay` box does not wrap text, which means that long lines of text will extend beyond the width of the box. This results in the need for two scroll bars, a horizontal one for the result box and a vertical one for the currently shown list of persons. This is not ideal as it makes the UI less optimized for the target audience, who prefer using a CLI-optimized application and prefer not to use mouse controls to scroll through scroll boxes.
+
+##### Planned Implementation
+
+We plan to modify the `ResultDisplay` box to wrap text so that there is no longer a need for the horizontal scroll bar in the `ResultDisplay` box.
+
+In the case where the wrapped text still exceeds the height of the `ResultDisplay` box, we plan to enable it to dynamically adjust its height as needed.
+
+
+
+#### Primary Key: Use Both `Matric` and `Email`
+
+Currently, only `Email` is used as a unique identifier for `Person` objects. However, this means that two `Person` objects can have different `Email`s but the same `Matric` number. This clashes with the real-life constraint that NUS students, in particular CS1101S students, are put under, where Matriculation numbers are supposed to be unique for each student. Our planned enhancement hence aims to better reflect real-life constraints.
+
+##### Planned Implementation
+
+Currently, the `hasPerson` method in the `Model` class checks for the existence of a `Person` object based on the `Email` field. We plan to modify this method to check for the existence of a `Person` object based on both the `Email` and `Matric` fields. This will ensure that two `Person` objects cannot have the same `Matric` number.
+
+However, more checking needs to be done to ensure persons cannot have different overall unique identifiers, but the same `Email` or `Matric` field. (E.g. two persons cannot have the same `Email` but different `Matric` numbers.)
+
+Additionally, some persons such as staff members and course instructors may not have a `Matric` field. Hence, careful consideration needs to be made to implement this new method of checking for unique identifiers.
+
+
+
+#### UX: Make Sample Data Tags More Relevant and Helpful to the User
+
+Currently, the sample data tags are not very helpful to the user, having tags like `friends`, `neighbors` and `family`. This may pose confusion to users about the context of the application, which is the head TA's management of persons related to CS1101S.
+
+##### Planned Implementation
+
+Remove all `Tag` objects that are in the sample data that border on irrelevancy. This can be done by modifying the `SampleDataUtil` class to not add these tags to the sample data.
+
+Retain all other relevant `Tag` objects like `colleagues` and `student` to better reflect the context of the application.
+
+
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+## **Documentation, Logging, Testing, Configuration, Dev-Ops**
+
+* [Documentation guide](Documentation.md)
+* [Testing guide](Testing.md)
+* [Logging guide](Logging.md)
+* [Configuration guide](Configuration.md)
+* [DevOps guide](DevOps.md)
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+
+
+
+## **Appendix**
+
+
+
+### Appendix A: Product Scope
+
+**Target user profile**:
+
+**Name:** Sarah Johnson,
+**Age:** 23,
+**Occupation:** Head Tutor for CS1101S
+
+* Head tutor for CS1101S course
+* Has a need to manage various aspects of course administration
+* Has a need to schedule classes
+* Has a need to coordinate with teaching assistants
+* Has a need to effectively communicate with students
+* Has a need to manage a significant number of persons
+* Prefer desktop apps over other types
+* Can type fast
+* Prefers typing to mouse interactions
+* Is reasonably comfortable using CLI apps
+
+
+
+**Value proposition**:
+
+* Manage persons faster than a typical mouse/GUI driven app
+* Centralized platform to store and manage person details for all relevant individuals involved in course administration
+* Able to store and manage exam scores for all students in the course
+* Easier access to information through organizing relevant persons into different subgroups
+* Able to set up the application through different data-loading options
+* Able to assist with management of large scale communication
+
+
+
+**Problem scope**:
+
+* The CS1101S Head Tutor will face challenges in effectively organizing and managing contact information within the department due to the large scale the course has to operate on. Existing methods, such as paper-based lists or basic digital spreadsheets, lack the necessary functionality to efficiently handle the diverse needs of proper contact management. There is a need for a user-friendly and offline-capable address book solution tailored specifically to the needs of a single user. This address book system should provide features such as easy contact entry and editing, quick search functionality, customizable categorization options, and the ability to add notes for each contact. Additionally, it should operate offline without requiring an internet connection and should not rely on complex database management systems.
+* While Avengers Assemble will greatly improve contact management and organization for the CS1101S Head Tutor, it will not address broader departmental communication or collaboration needs beyond individual contact management since the application is designed to be a single-user system. It will not facilitate communication between users or provide collaboration tools for group projects or tasks. Additionally, the address book system will not handle complex data analysis or reporting functions beyond basic contact information management. Finally, while the system will provide offline functionality, it will not offer real-time synchronization with online databases or cloud storage solutions.
+
+
+
+
+
+
+
+### Appendix B: User Stories
+
+Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*`
+
+#### General
+
+
+
+
+
+
Priority
+
As a …
+
I want to …
+
So that I can…
+
+
+
* * *
+
potential user exploring the app
+
see the app populated with sample data
+
immediately see an example of the app in use
+
+
+
* * *
+
new user
+
see usage instructions
+
refer to instructions when I forget how to use the App
+
+
+
* * *
+
new user
+
easily clear the example data
+
start using the app with real-life data
+
+
+
* *
+
experienced user
+
use the application offline
+
update and interact with it anywhere
+
+
+
+
+
+#### For Contact Management
+
+
+
+
+
Priority
+
As a …
+
I want to …
+
So that I can…
+
+
+
* * *
+
head tutor using the app
+
import persons from a CSV file
+
easily add a large number of persons to the application
+
+
+
* * *
+
new user
+
save the data I input into the app
+
don't lose the information I've entered
+
+
+
* * *
+
user
+
add a new person
+
make minor additions to the persons in the application
+
+
+
* * *
+
user
+
update and edit person details
+
keep my persons list accurate
+
+
+
* * *
+
user
+
delete a person
+
remove entries that I no longer need
+
+
+
* * *
+
user
+
delete a specific group of entries
+
remove multiple entries that I no longer need more efficiently
+
+
+
* * *
+
user
+
view all saved contacts
+
oversee the data stored within my app
+
+
+
* * *
+
user
+
find a person through their particulars
+
locate details of persons without having to go through the entire list
+
+
+
* * *
+
head tutor using the app
+
categorize my persons into groups
+
manage different groups of students effectively
+
+
+
* * *
+
head tutor using the app
+
copy email addresses of a group
+
effectively communicate with target groups
+
+
+
* * *
+
head tutor using the app
+
export the details of persons to a CSV
+
easily share the details of a group with others
+
+
+
+
+
+
+
+#### For Exam and Score Management
+
+
+
+
Priority
+
As a …
+
I want to …
+
So that I can…
+
+
+
* * *
+
head tutor using the app
+
import assessment scores from a CSV file
+
easily add a large number of scores to the application
+
+
+
* * *
+
head tutor using the app
+
add exams to the app
+
keep track of student performance
+
+
+
* * *
+
head tutor using the app
+
delete exams from the app
+
remove exams that are no longer relevant
+
+
+
* * *
+
head tutor using the app
+
view scores for a specific exam
+
analyze student scores
+
+
+
* * *
+
head tutor using the app
+
add scores to the app
+
keep track of student performance
+
+
+
* * *
+
head tutor using the app
+
edit scores in the app
+
correct errors in the scores
+
+
+
* * *
+
head tutor using the app
+
delete scores from the app
+
remove scores that are no longer relevant
+
+
+
* * *
+
head tutor using the app
+
export scores to a CSV file
+
easily share the scores with others
+
+
+
* * *
+
head tutor using the app
+
view statistics of scores
+
analyze student performance
+
+
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+
+
+
+### Appendix C: Use Cases
+
+(For all use cases below, the **System** is the `AvengersAssemble` and the **Actor** is the `user`, unless specified otherwise)
+
+##### Use Case: UC01 — Getting Help
+
+**MSS:**
+
+1. User requests help information.
+2. AvengersAssemble copies the link to the user guide to the user's clipboard.
+3. User pastes the link into a browser to access the user guide.
+
+ Use case ends.
+
+##### Use Case: UC02 — Clearing Sample Data
+
+**MSS:**
+
+1. User requests to clear the sample data.
+2. AvengersAssemble clears the sample data.
+3. AvengersAssemble displays a message indicating that the sample data has been cleared.
+
+ Use case ends.
+
+##### Use Case: UC03 — Importing Person Details from a CSV File
+
+**MSS:**
+
+1. User requests to import person details from a CSV file.
+2. AvengersAssemble imports the person details from the CSV file.
+3. AvengersAssemble displays a message indicating that the person details have been imported.
+
+ Use case ends.
+
+**Extensions:**
+
+* 1a. The file to be imported is not a CSV file.
+
+ * 1a1. AvengersAssemble displays an error message indicating that the file type is not recognized and should be a CSV file.
+
+ Use case ends.
+
+* 1b. AvengersAssemble cannot find the file to be imported.
+
+ * 1b1. AvengersAssemble displays a message indicating that the file is not recognized.
+
+ Use case ends.
+
+
+
+##### Use Case: UC04 — Adding a Person
+
+**MSS:**
+
+1. User requests to add a new person and inputs details for the new person.
+2. AvengersAssemble saves the new person's information.
+3. AvengersAssemble confirms the addition of the new person.
+
+ Use case ends.
+
+**Extensions:**
+
+* 1a. User does not input all compulsory parameters along with the person.
+
+ * 1a1. AvengersAssemble prompts the user on the proper usage of the command.
+
+ Step 1a1 is repeated until the data entered is correct.
+
+ Use case resumes at step 2.
+
+* 1b. User tries to add a person with an existing email address.
+
+ * 1b1. AvengersAssemble displays an error message informing the user that the email address already exists.
+
+ Step 1b1 is repeated until a valid email address is entered.
+
+ Use case resumes at step 2.
+
+##### Use Case: UC05 — Editing a Person's Details
+
+**MSS:**
+
+1. User requests to edit a specific person with updated details.
+2. AvengersAssemble saves the updated details.
+3. AvengersAssemble confirms the successful update.
+
+ Use case ends.
+
+**Extensions:**
+
+* 1a. User does not input enough parameters along with the person.
+
+ * 1a1. AvengersAssemble prompts the user on the proper usage of the command.
+
+ Step 1a1 is repeated until the data entered is correct.
+
+ Use case resumes at step 2.
+
+* 1b. The selected person does not exist.
+
+ * 1b1. AvengersAssemble displays an error message indicating that the person does not exist.
+
+ Use case ends.
+
+##### Use Case: UC06 — Deleting a Person
+
+**MSS:**
+
+1. User !!requests to list persons (UC08)!!
+2. AvengersAssemble shows a list of persons
+3. User requests to delete a specific person in the list
+4. AvengersAssemble deletes the person
+
+ Use case ends.
+
+**Extensions:**
+
+* 2a. The list is empty.
+
+ Use case ends.
+
+* 3a. The given index is invalid.
+
+ * 3a1. AvengersAssemble shows an error message.
+
+ Use case resumes at step 2.
+
+##### Use Case: UC07 — Deleting All Shown Persons
+
+**MSS:**
+
+1. User !!requests to find group of persons (UC09)!! by desired requirements
+2. User requests to delete all listed persons.
+3. AvengersAssemble deletes all listed persons.
+4. AvengersAssemble displays a message to confirm that all listed persons have been deleted.
+
+ Use case ends.
+
+**Extensions:**
+
+* 2a. No persons are listed.
+
+ * 2a1. AvengersAssemble displays a message indicating that there is no persons to delete.
+
+ Use case ends.
+
+* 2b. User has a filtered view that contains all existing persons.
+
+ * 2b1. AvengersAssemble displays a message indicating that all persons cannot be deleted at once.
+
+ Use case ends.
+
+
+
+##### Use Case: UC08 — Listing All Persons
+
+**MSS:**
+
+1. User requests to list persons.
+2. AvengersAssemble shows the list of persons.
+3. User views the list of persons.
+
+ Use case ends.
+
+**Extensions:**
+
+* 2a. The list is empty.
+
+ * 2a1. AvengersAssemble displays a message indicating that the list is empty.
+
+ Use case ends.
+
+##### Use Case: UC09 — Finding Persons
+
+**MSS:**
+
+1. User requests to find a specific group of persons matching the search criteria.
+2. AvengersAssemble displays a list of persons matching the criteria.
+
+ Use case ends.
+
+**Extensions:**
+
+* 1a. No persons match the search criteria.
+
+ * 1a1. AvengersAssemble displays a message indicating that no persons match the search criteria.
+
+ Use case ends.
+
+
+
+##### Use Case: UC10 — Copying Email Addresses
+
+**MSS:**
+
+1. User requests to copy emails of currently displayed persons.
+2. AvengersAssemble copies the emails of currently displayed persons
+into user's clipboard.
+3. AvengersAssemble notifies the user that emails have been copied.
+4. User can paste emails when composing emails.
+
+ Use case ends.
+
+**Extensions:**
+
+* 2a. No persons currently displayed.
+
+ * 2a1. AvengersAssemble displays a message indicating that no persons are currently displayed.
+
+ Use case ends.
+
+##### Use Case: UC11 — Exporting Persons to CSV
+
+**MSS:**
+
+1. User !!requests to filter persons (UC09)!! by desired requirements
+2. User requests to export all listed persons and details to a CSV file.
+3. AvengersAssemble exports the persons to a CSV file.
+4. AvengersAssemble displays a message to confirm that all listed persons have been exported to a CSV file.
+
+ Use case ends.
+
+**Extensions:**
+
+* 2a. No persons are listed.
+
+ * 2a2. AvengersAssemble displays a message indicating that there is no persons to export.
+
+ Use case ends.
+
+
+
+
+##### Use Case: UC12 — Importing Exam Results from a CSV File
+
+**MSS:**
+
+1. User requests to import exam results from a CSV file.
+2. AvengersAssemble displays a message that all exam results have been imported.
+
+ Use case ends.
+
+**Extensions:**
+
+* 2a. AvengersAssemble cannot find the file specified.
+
+ * 2a1. AvengersAssemble displays a message indicating that the file is not recognized.
+
+ Use case ends.
+
+* 2b. The file to be imported is not a CSV file.
+
+ * 2b1. AvengersAssemble displays an error message indicating that the file type is not recognized and should be a CSV file
+
+ Use case ends.
+
+* 2c. There are duplicate entries in the CSV file.
+
+ * 2c1. AvengersAssemble displays a message indicating that there are duplicate entries in the CSV file, and only the first instance has been kept.
+
+ Use case ends.
+
+* 2d. The CSV file contains invalid entries.
+
+ * 2d1. AvengersAssemble displays a message indicating that there are invalid entries in the CSV file, and all other valid entries have been imported.
+
+ Use case ends.
+
+
+
+##### Use Case: UC13 — Adding an Exam
+
+**MSS:**
+
+1. User requests to add an exam.
+2. AvengersAssemble displays a message that the exam has been added.
+
+ Use case ends.
+
+**Extensions:**
+
+* 1a. User does not input all compulsory parameters along with the exam.
+
+ * 1a1. AvengersAssemble prompts the user on the proper usage of the command.
+
+ Step 1a1 is repeated until the data entered is correct.
+
+ Use case resumes at step 2.
+
+* 1b. User tries to add an exam with an existing name.
+
+ * 1b1. AvengersAssemble displays an error message informing the user that the exam name already exists.
+
+ Step 1b1 is repeated until a valid exam name is entered.
+
+ Use case resumes at step 2.
+
+* 1c. User tries to add an exam with an invalid score.
+
+ * 1c1. AvengersAssemble displays an error message informing the user that the score is invalid.
+
+ Step 1c1 is repeated until a valid score is entered.
+
+ Use case resumes at step 2.
+
+* 1d. User tries to add an exam with an invalid name.
+
+ * 1d1. AvengersAssemble displays an error message informing the user that the name is invalid.
+
+ Step 1d1 is repeated until a valid name is entered.
+
+ Use case resumes at step 2.
+
+
+
+##### Use Case: UC14 — Deleting an Exam
+
+**MSS:**
+
+1. User requests to delete an exam.
+2. AvengersAssemble displays a message that the exam has been deleted.
+
+ Use case ends.
+
+**Extensions:**
+
+* 1a. The exam does not exist.
+
+ * 1a1. AvengersAssemble displays an error message indicating that the exam does not exist.
+
+ Use case ends.
+
+##### Use Case: UC15 — Selecting an Exam
+
+**MSS:**
+
+1. User requests to select an exam.
+2. AvengersAssemble displays the scores of the selected exam.
+
+ Use case ends.
+
+**Extensions:**
+
+* 1a. The exam does not exist.
+
+ * 1a1. AvengersAssemble displays an error message indicating that the exam does not exist.
+
+ Use case ends.
+
+##### Use Case: UC16 — Deselecting an Exam
+
+**MSS:**
+
+1. User requests to deselect an exam.
+2. AvengersAssemble displays the persons without the scores of the selected exam.
+
+ Use case ends.
+
+**Extensions:**
+
+* 1a. The exam does not exist.
+
+ * 1a1. AvengersAssemble displays an error message indicating that the exam does not exist.
+
+ Use case ends.
+
+
+
+##### Use Case: UC17 — Adding Scores to a Student for an Exam
+
+**MSS:**
+
+1. User !!requests to select an exam (UC15)!! to add scores to.
+2. User requests to add scores to a student for the selected exam.
+3. AvengersAssemble displays a message that the scores have been added.
+
+ Use case ends.
+
+**Extensions:**
+
+* 2a. The student does not exist.
+
+ * 2a1. AvengersAssemble displays an error message indicating that the student does not exist.
+
+ Use case ends.
+
+* 2b. The student already has a score for the exam.
+
+ * 2b1. AvengersAssemble displays an error message indicating that the student already has a score for the exam.
+
+ Use case ends.
+
+##### Use Case: UC18 — Editing Scores for a Student for an Exam
+
+**MSS:**
+
+1. User !!requests to select an exam (UC15)!! to edit scores for.
+2. User requests to edit scores for a student for the selected exam.
+3. AvengersAssemble displays a message that the scores have been edited.
+
+ Use case ends.
+
+**Extensions:**
+
+* 2a. The student does not exist.
+
+ * 2a1. AvengersAssemble displays an error message indicating that the student does not exist.
+
+ Use case ends.
+
+* 2b. The student does not have a score for the exam.
+
+ * 2b1. AvengersAssemble displays an error message indicating that the student does not have a score for the exam.
+
+ Use case ends.
+
+* 2c. The score is invalid.
+
+ * 2c1. AvengersAssemble displays an error message indicating that the score is invalid.
+
+ Use case ends.
+
+##### Use Case: UC19 — Deleting Scores for a Student for an Exam
+
+**MSS:**
+
+1. User !!requests to select an exam (UC15)!! to delete scores for.
+2. User requests to delete scores for a student for the selected exam.
+3. AvengersAssemble displays a message that the scores have been deleted.
+
+ Use case ends.
+
+**Extensions:**
+
+* 2a. The student does not exist.
+
+ * 2a1. AvengersAssemble displays an error message indicating that the student does not exist.
+
+ Use case ends.
+
+* 2b. The student does not have a score for the exam.
+
+ * 2b1. AvengersAssemble displays an error message indicating that the student does not have a score for the exam.
+
+ Use case ends.
+
+##### Use Case: UC20 — Viewing Statistics of Scores
+
+**MSS:**
+
+1. User !!requests to select an exam (UC15)!! to view statistics of scores for.
+2. AvengersAssemble displays the statistics of scores for the selected exam.
+
+ Use case ends.
+
+**Extensions:**
+
+* 2a. There are no scores for the exam.
+
+ * 2a1. AvengersAssemble does not display any statistics.
+
+ Use case ends.
+
+##### Use Case: UC21 — Exit Application
+
+**MSS:**
+
+1. User requests to exit the application.
+2. AvengersAssemble exits the application.
+
+ Use case ends.
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+
+
+
+### Appendix D: Non-Functional Requirements
+
+1. Should work on any _mainstream OS_ as long as it has `Java 11` or above installed.
+2. Should be able to hold up to 2000 persons without a noticeable sluggishness in performance for typical usage.
+3. A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
+4. A user should be able to import up to 2000 persons from an external source without a noticeable sluggishness in performance for typical usage.
+5. The application should provide comprehensive documentation and help resources to assist users in understanding how to use the software effectively.
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+
+### Appendix E: Glossary
+
+* **OS** : Operating System
+* **Mainstream OS**: Windows, Linux, MacOS
+* **CLI**: Command Line Interface
+* **CSV**: Comma Separated Values - a file format used to store tabular data
+* **MSS**: Main Success Scenario
+* **UI**: User Interface
+* **GUI**: Graphical User Interface
+* **API**: Application Programming Interface - used to define how the components of this software interact with each other
+* **Matric**: Matriculation number of a student
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+
+
+
+
+### Appendix F: Instructions for Manual Testing
+
+Given below are instructions to test the app manually.
+
+
+
+**Note:** These instructions only provide a starting point for testers to work on;
+testers are expected to do more *exploratory* testing.
+
+
+
+
+
+#### Launch and Shutdown
+
+1. Initial launch.
+ * **Test case:** Launching the app for the first time.
+ 1. Download the jar file and copy into an empty folder.
+ 2. Open Terminal and type the following:
+ ```bash
+ java -jar avengersassemble.jar
+ ```
+ **Expected:** Shows the GUI with a set of sample persons. The window size may not be optimal.
+
+2. Saving window preferences.
+ * **Prerequisites:**
+ * Launch the app.
+ * Resize the window.
+ * Close the app.
+ * **Test case:** Launch the app.
+ **Expected:** The most recent window size and location is retained.
+
+
+3. Shutdown.
+ * **Test case:** `exit`
+ **Expected:** The GUI closes and the application exits.
+
+
+
+
+
+
+#### Saving Data
+
+1. Saving of data.
+ * **Prerequisites:**
+ * The app is a clean state.
+
+ * **Test case:** Launch and exit the app.
+ **Expected:** A new `data/avengersassemble.json` file is created. This is the storage file.
+
+
+1. Dealing with missing or corrupted data files.
+
+ * **Prerequisites:**
+ * There is an existing storage file in the default location.
+
+ * **Test case:** Delete the storage file, then launch and exit the app.
+ **Expected:** A new `data/avengersassemble.json` file populated with sample data is created.
+
+ * **Test case:** Corrupt the `data/avengersassemble.json` file by adding random text to it.
+ **Expected:** The app should ignore the corrupted file and create a new empty `data/avengersassemble.json` file when launched and interacted with.
+
+
+
+
+#### Getting Help: `help`
+
+**Command:** `help`
+**More information on usage:** Getting Help
+
+1. Getting more information on the usage of the app.
+
+ * **Test case:** `help`
+ **Expected:** Link to the user guide is copied to the clipboard. Status message shows that the link has been copied.
+ The link should be accessible from a browser.
+
+
+
+
+
+#### Clearing All Persons and Exams: `clear`
+
+**Command:** `clear`
+**More information on usage:** Clearing All Entries
+
+1. Clearing all contact information from the app.
+
+ * **Prerequisites:**
+ * Ensure that there is at least one person and exam in the app.
+
+ * **Test case:** `clear`
+ **Expected:** All persons and exams are deleted from the list. Status message shows that all persons and exams have been
+ deleted from the app.
+
+
+
+
+
+
+
+#### Importing Persons: `import`
+
+**Command:** `import`
+**More information on usage:** Importing Persons
+
+The import command requires the use of an external CSV file. The test cases below assume that the tests are run on a Windows system, and that the CSV file is located at the path `C:\path\to\file.csv`. Please modify the filepath accordingly based on where your file is stored and your operating system.
+
+
+Note: On Window systems, you can right-click the file and copy the file path, remember to remove the double quotes. On MacOS, you can drag the file into the terminal to get the file path. On Linux, you can use the pwd command to get the current directory and append the file name to it.
+
+
+1. Importing data from a CSV file
+
+ * **Prerequisites**
+ * There is a file at `C:\path\to\file.csv` with the following content:
+ ```
+ name,email,address,phone
+ Alice,alice@gmail.com,wonderland,123
+ ```
+ * Initially, the persons list is empty.
+
+
+
+ * **Test case:** `import i|C:\path\to\file.csv`
+ **Expected:** The person with the following details is added:
+ * Name: `Alice`
+ * Email: `alice@gmail.com`
+ * Address: `wonderland`
+ * Phone: `123`
+
+
+
+2. Importing data from a CSV File that does not exist
+
+ * **Prerequisites**
+ * No CSV file at the path `C:\path\to\file.csv`
+
+
+
+ * **Test case:** `import i|C:\path\to\file.csv`
+ **Expected:** Error message shown in the error report. No change in list of persons.
+
+
+
+3. Importing data from a file that is not a CSV file
+
+ * **Prerequisites**
+ * There is a file at the path `C:\path\to\file.txt`
+
+
+
+ * **Test case:** `import i|C:\path\to\file.txt`
+ **Expected:** Error message shown in the error report. No change in list of persons.
+
+
+
+
+
+4. Importing data from a CSV File with duplicate compulsory headers in header row
+
+ * **Prerequisites**
+ * A CSV file with duplicate compulsory headers (e.g. 2 header columns named 'name') at the path `C:\path\to\file.csv` with the following content:
+ ```
+ name,email,address,phone,name
+ Alice,alice@gmail.com,wonderland,123,bob
+ ```
+ * Initially, the persons list is empty.
+
+
+
+ * **Test case:** `import i|C:\path\to\file.csv`
+ **Expected:** First occurrence of the header is used. Columns with duplicate headers are ignored. The person with the following details is added:
+ * Name: `Alice`
+ * Email: `alice@gmail.com`
+ * Address: `wonderland`
+ * Phone: `123`
+
+
+
+5. Importing data from a CSV file with missing compulsory headers in header row
+
+ * **Prerequisites**
+ * A CSV file with missing compulsory headers at the path `C:\path\to\file.csv` with the following content (missing the `name` header):
+ ```
+ email,address,phone
+ alice@gmail.com,wonderland,123
+ ```
+
+
+
+ * **Test case:** `import i|C:\path\to\file.csv`
+ * **Expected:** Error message shown that `name` header is missing in the error report. No change in list of persons.
+
+
+
+6. Importing data from a CSV file with missing compulsory values in a row
+
+ * **Prerequisites**
+ * A CSV file with missing compulsory values in a row at the path `C:\path\to\file.csv` with the following content:
+ ```
+ name,email,address,phone
+ Alice,,wonderland,123
+ Bob,bob@gmail.com,town,123
+ ```
+ * **Initially, the persons list is empty.**
+
+
+
+ * **Test case:** `import i|C:\path\to\file.csv`
+ * **Expected:** Error message in the results in the display indicating that import has failed with errors. Only one person with the following details is added:
+ * Name: `Bob`
+ * Email: `bob@gmail.com`
+ * Address: `town`
+ * Phone: `123`
+
+
+
+
+
+7. Importing data from a CSV file with extra headers in header row
+
+ * **Prerequisites**
+ * A CSV file with extra headers in header row at the path `C:\path\to\file.csv` with the following content:
+ ```
+ name,email,address,phone,extra
+ Alice,alice@gmail.com,123,123,extra
+ ```
+ * Initially, the persons list is empty.
+
+
+
+ * **Test case:** `import i|C:\path\to\file.csv`
+ * **Expected:** Only the compulsory headers are read. Optional headers are read if present. Extra headers are ignored. The person with the following details is added:
+ * Name: `Alice`
+ * Email: `alice@gmail.com`
+ * Address: `123`
+ * Phone: `123`
+
+
+
+8. Importing data from a CSV file with unequal number of values in a row as the number of headers
+
+ * **Prerequisites**
+ * A CSV file with unequal number of values in a row as the number of headers at the path `C:\path\to\file.csv` with the following content:
+ ```
+ name,email,address,phone
+ Alice,alice@gmail.com,wonderland,123,123
+ Bob,bob@gmail.com,town,123
+ ```
+ * Initially, the persons list is empty.
+
+
+
+ * **Test case:** `import i|C:\path\to\file.csv`
+ **Expected:** Error message in the results in the display indicating that import has failed with errors. Only one person with the following details is added:
+ * Name: `Bob`
+ * Email: `bob@gmail.com`
+ * Address: `town`
+ * Phone: `123`
+
+
+
+9. Importing data from an empty CSV file
+
+ * **Prerequisites**
+ * An empty CSV file at the path `C:\path\to\file.csv`
+
+
+
+ * **Test case:** `import i|C:\path\to\file.csv`
+ * **Expected:** A message that no person is imported is shown. No change in list of persons.
+
+
+
+
+
+
+
+#### Adding a Person: `add`
+
+**Command:** `add`
+**More information on usage:** Adding a Person
+
+1. Adding a person with all fields.
+
+ * **Prerequisites:**
+ * No persons in the list.
+
+ * **Test case:** `add n|Alice p|98765432 a|Hall e|e09123456@u.nus.edu m|A1234567X r|R2 s|S1 t|excelling`
+ **Expected:** A person with the following fields is added to the list:
+ * Name: `Alice`
+ * Phone: `98765432`
+ * Address: `Hall`
+ * Email: `e09123456@u.nus.edu`
+ * Matric: `A1234567X`
+ * Reflection: `R2`
+ * Studio: `S1`
+ * Tags: `excelling`, `student`
+
+
+
+ **Note:** If a `Matric` number is provided, the person is automatically tagged as a `student`.
+
+
+
+ * **Test case (missing `Address` and `Phone` fields):** `add n|Alice e|e09123456@u.nus.edu`
+ **Expected:** An error message is shown indicating that the `Address` and `Phone` fields are missing.
+
+
+
+2. Adding a person with repeated prefixes.
+
+ * **Prerequisites:**
+ * No persons in the list.
+
+ * **Test case (repeating `Name` field):** `add n|Ali n|Ali p|98765432 a|Hall e|test@test.com m|A1234567X`
+ **Expected:** An error message is shown indicating that the `Name` field is repeated.
+
+
+
+3. Adding a person whose `Email` already exists.
+
+ * **Prerequisites:**
+ * A person with email `e1234567@u.nus.edu` already exists in the list.
+
+ * **Test case (`Email` already exists):** `add n|Alice p|987 a|Hall e|e1234567@u.nus.edu`
+ **Expected:** An error message is shown indicating that the email already exists.
+
+
+
+
+4. Adding a person with only compulsory fields.
+
+ * **Prerequisites:**
+ * No persons in the list.
+
+ * **Test case:** `add n|Alice p|98765432 a|Hall e|e09123456@u.nus.edu`
+ **Expected:** A person with the following fields is added to the list:
+ * Name: `Alice`
+ * Phone: `98765432`
+ * Address: `Hall`
+ * Email: `e09123456@u.nus.edu`
+
+
+5. Adding a person with matriculation number
+
+ * **Prerequisites:**
+ * No persons in the list.
+
+ * **Test case:** `add n|Alice p|98765432 a|Hall e|alice@example.com m|A1234567X`
+ **Expected:** A person with the following fields is added to the list:
+ * Name: `Alice`
+ * Phone: `98765432`
+ * Address: `Hall`
+ * Email: `alice@example.com`
+ * Matric: `A1234567X`
+ * Tags: `student`
+
+ Note that the `student` tag is automatically added to the new person.
+
+ * **Test case:** `add n|Alice p|98765432 a|Hall e|alice@example.com`
+ **Expected:** A person with the following fields is added to the list:
+ * Name: `Alice`
+ * Phone: `98765432`
+ * Address: `Hall`
+ * Email: `alice@example.com`
+
+ Note that there is no automatic tagging.
+
+
+
+
+
+
+#### Editing a Person: `edit`
+
+**Command:** `edit`
+**More information on usage:** Editing a Person
+
+1. Editing a person with all fields.
+
+ * **Prerequisites:**
+ * Start with the provided sample data.
+
+ * **Test case:** `edit 1 n|new name p|123 a|new home e|newemail@eg.com m|A0000000X r|R1 s|S1 t|tag1 t|tag2`
+ **Expected:** The first person’s details are updated with all the new values.
+
+ * **Other successful test cases to try:** Include a combination of updating some fields and not updating others.
+ **Expected:** Similar to above.
+
+
+
+2. Editing a person with repeated prefixes.
+
+ * **Prerequisites:**
+ * Start with the provided sample data.
+
+ * **Test case (repeated `n|` prefix):** `edit 1 n|new name n|new name 2 p|123 a|new address`
+ **Expected:** An error message is shown indicating that the `Name` field is repeated.
+
+ * **Other incorrect `edit` commands to try:** Commands with repeated `p|`, `a|`, `e|`, `m|`, `r|`, `s|`, `t|` prefixes.
+ **Expected:** Similar to previous.
+
+
+3. Editing a Person's `Email` to an Existing `Email`.
+
+ * **Prerequisites:**
+ * Start with the provided sample data. Note the emails of the first and second person.
+
+ * **Test case:** `edit 1 e|berniceyu@example.com`
+ **Expected:** An error message is shown indicating that the email already exists.
+
+
+
+
+
+
+#### Deleting a Person: `delete`
+
+**Command:** `delete`
+**More information on usage:** Deleting a Person
+
+1. Deleting a person while all persons are being shown.
+
+ * **Prerequisites:**
+ * List all persons using the `list` command. Multiple persons in the list.
+
+ * **Test case:** `delete 1`
+ **Expected:** First person is deleted from the list. Details of the deleted person shown in the status message.
+
+ * **Test case (invalid index):** `delete 0`
+ **Expected:** No person is deleted. Error details shown in the status message.
+
+ * **Other incorrect `delete` commands to try:** `delete`, `delete x`, `...` (where x is larger than the list size)
+ **Expected:** Similar to previous.
+
+
+2. Deleting a person while some persons are being shown.
+
+ * **Prerequisites:**
+ * Filter persons using the `find` command. Multiple but not all persons in the list.
+
+ * **Test case**: `delete 1`
+ **Expected:** First person in the filtered list is deleted. Details of the deleted person shown in the status message.
+
+ * **Test case**: `delete 0`
+ **Expected:** No person is deleted. Error details shown in the status message.
+
+ * **Other incorrect `delete` commands to try:** `delete`, `delete x`
+ **Expected:** Similar to previous.
+
+
+3. Deleting a person while no persons are being shown.
+
+ * **Prerequisites:**
+ * Filter persons using the `find` command such that there are no persons in the list, or delete all persons with `clear`.
+
+ * **Test case**: `delete 1`
+ **Expected:** No person is deleted. Error details shown in the status message.
+
+
+
+
+
+
+#### Deleting Shown Persons: `deleteShown`
+
+**Command:** `deleteShown`
+**More information on usage:** Deleting Filtered Persons
+
+
+1. Deleting a proper subset of all persons.
+
+ * **Prerequisites:**
+ * Filter persons using the `find` command such that there are multiple, but not all, persons in the list.
+
+ * **Test case:** `deleteShown`
+ **Expected:** All persons currently shown are deleted, and the list is updated to show all remaining persons.
+
+ * **Other successful test cases:** `deleteShown x`
+ **Expected:** Similar to previous, as extraneous parameters for single-word commands are treated as typos and ignored.
+
+
+2. Deleting all persons.
+
+ * **Prerequisites:**
+ * Filter persons using the `find` command such that all persons are shown, or list all persons with `list`.
+
+ * **Test case:** `deleteShown`
+ **Expected:** An error is shown indicating that all persons cannot be deleted at once.
+
+ * **Other incorrect `deleteShown` commands to try:** `deleteShown x`
+ **Expected:** Similar to previous.
+
+
+
+
+#### Listing All Persons: `list`
+
+**Command:** `list`
+**More information on usage:** Listing All Persons
+
+1. Starting with sample data.
+
+ * **Prerequisites:**
+ * Start with the provided sample data.
+
+ * **Test case:** `list`
+ **Expected:** All persons are shown in the list.
+
+ * **Other successful test cases:** `list x`
+ **Expected:** Similar to previous, as extraneous parameters for single-word commands are treated as typos and ignored.
+
+
+2. Starting with a filtered list.
+
+ * **Prerequisites:**
+ * Filter persons using the `find` command such that there are multiple, but not all, persons in the list.
+
+ * **Test case:** `list`
+ **Expected:** All persons in the overall list are shown.
+
+
+
+
+
+
+#### Finding a Person: `find`
+
+**Command:** `find`
+**More information on usage:** Filtering Persons
+
+1. Finding persons by contact details.
+
+ * **Prerequisites:**
+ * Ensure that there are multiple persons in the app.
+
+ * **Test case:** `find n|Alice`
+ **Expected:** Persons with the name "Alice" are shown. Status message shows the number of persons found.
+
+ * **Test case:** `find e|alice`
+ **Expected:** Persons with emails that contain the word "alice" are shown. Status message shows the number of persons found.
+
+ * **Test case:** `find p|123`
+ **Expected:** Persons with phone numbers that contain the digits "123" are shown. Status message shows the number of persons found.
+
+ * **Test case:** `find a|Ang Mo Kio`
+ **Expected:** Persons with addresses that contain the word "Ang Mo Kio" are shown. Status message shows the number of persons found.
+
+ * **Test case:** `find t|student`
+ **Expected:** Persons with the tag "student" are shown. Status message shows the number of persons found.
+
+ * **Test case:** `find m|A123`
+ **Expected:** Persons with matriculation numbers containing "A123" are shown. Status message shows the number of persons found.
+
+ * **Test case:** `find r|R01`
+ **Expected:** Persons with the reflection "R01" are shown. Status message shows the number of persons found.
+
+ * **Test case:** `find s|S01`
+ **Expected:** Persons with the studio "S01" are shown. Status message shows the number of persons found.
+
+
+
+
+2. Finding persons by score.
+
+ * **Prerequisites:**
+ * Ensure that there are multiple persons in the app.
+ * Ensure that at least one exam is added using the `addExam` command. For this example, we shall add a new exam with name `test exam` and maximum score `100`.
+ * Ensure an exam is selected using the `selectExam` command. For this example, we shall select the `test exam`.
+
+ * **Test case:** `find lt|50`
+ **Expected:** Persons with scores less than 50 are shown. Status message shows the number of persons found.
+
+ * **Test case:** `find mt|50`
+ **Expected:** Persons with scores more than 50 are shown. Status message shows the number of persons found.
+
+ * **Test case:** `find lt|-1`
+ **Expected:** An error message is shown indicating that the `score` provided is invalid.
+
+ * **Test case:** `find mt|101`
+ **Expected:** An error message is shown indicating that the `score` provided is greater than the maximum score of the selected exam.
+
+
+3. Finding persons by multiple prefixes.
+
+ * **Prerequisites:**
+ * Ensure that there are multiple persons in the app.
+
+ * **Test case (multiple unique prefixes):** `find n|Alice e|Alice`
+ **Expected:** An error message is shown indicating that the format of the command is incorrect.
+
+ * **Similar incorrect test cases to try:** Any combination of two or more different prefixes
+ **Expected:** Similar to previous.
+
+ * **Test case (multiple duplicate prefixes):** `find n|Alice n|Bob`
+ **Expected:** An error message is shown indicating that the prefix `n` is duplicated.
+
+ * **Similar incorrect test cases to try:** Duplicated `p|`, `a|`, `e|`, `m|`, `r|`, `s|`, `t|`, `mt|`, `lt|` prefixes.
+ **Expected:** Similar to previous.
+
+
+
+
+
+
+
+#### Copying Emails: `copy`
+
+**Command:** `copy`
+**More information on usage:** Copying Emails
+
+1. Copying the emails of all persons.
+
+ * **Prerequisites:**
+ * Ensure that there are multiple persons in the app.
+ * Ensure all persons are displayed using the `list` command.
+
+ * **Test case:** `copy`
+ **Expected:** All emails are copied to the clipboard. Status message shows the number of emails copied.
+
+
+2. Copying the emails of a specific group.
+
+ * **Prerequisites:**
+ * Ensure that there are multiple persons in the app.
+ * Filter the person list using the `find` command.
+
+ * **Test case:** `copy`
+ **Expected:** All emails of the currently displayed persons are copied to the clipboard. Status message shows the number of emails copied.
+
+
+
+
+
+
+
+#### Exporting Data to a CSV File: `export`
+
+**Command:** `export`
+**More information on usage:** Exporting Data to a CSV File
+
+1. Exporting data while all persons are displayed.
+
+ * **Prerequisites:**
+ * Start with the provided sample data.
+ * List all persons using the `list` command.
+
+ * **Test case:** `export`
+ **Expected:** A file named `addressbookdata` containing `avengersassemble.csv` is created in the same directory where the JAR file of the Avengers Assemble is located. All currently displayed persons and their details are exported to the CSV file.
+
+
+2. Exporting data while person list is filtered.
+
+ * **Prerequisites:**
+ * Start with the provided sample data.
+ * Filter the person list using the `find` command.
+
+ * **Test case:** Similar to previous.
+ **Expected:** Similar to previous.
+
+
+3. Exporting data with exams and exam scores added.
+
+ * **Prerequisites:**
+ * Start with the provided sample data.
+ * Add an exam using the `addExam` command. For this example, we shall add an exam with name `Test Exam`.
+ * List all persons using the `list` command.
+
+ * **Test case:** `export`
+ **Expected:** A file named `addressbookdata` containing `avengersassemble.csv` is created in the same directory where the JAR file of the Avengers Assemble is located. All currently displayed persons and their details are exported to the CSV file. A column with column heading `Exam:Test Exam` is present in the same CSV file, but no values are present in that column.
+
+ * **Test case:** Add exam scores to persons in displayed list using `addScore`, then `export`
+ **Expected:** A file named `addressbookdata` containing `avengersassemble.csv` is created in the same directory where the JAR file of the Avengers Assemble is located. All currently displayed persons and their details are exported to the CSV file. A column with column heading `Exam:Test Exam` is present in the same CSV file, with corresponding exam scores for each person included in that column.
+
+
+
+
+
+
+
+#### Adding an Exam: `addExam`
+
+**Command:** `addExam`
+**More information on usage:** Adding an Exam
+
+1. Adding an exam with valid data
+
+ * **Prerequisites:**
+ * No exams in the exams list.
+
+ * **Test case:** `addExam n|Midterm s|100`
+ **Expected:** New exam is added to the exams list. Status message shows the exam added.
+
+ * **Other test cases to try:** `addExam n|Final s|100`
+ **Expected:** New exam is added to the exams list. Status message shows the exam added.
+
+
+2. Adding an exam that already exists
+
+ * **Prerequisites:**
+ * An exam of name: Final, Score: 100 exists in the exams list.
+
+ * **Test case:** `addExam n|Final s|100`
+ **Expected:** Error message shown in the error report. No change in the exams list.
+
+
+3. Adding an exam with missing fields
+
+ * **Prerequisites:**
+ * No exams in the exams list.
+
+ * **Test case (missing score):** `addExam n|Final`
+ **Expected:** Error message shown in the error report. No change in the exams list.
+
+
+
+
+
+#### Deleting an Exam: `deleteExam`
+
+**Command:** `deleteExam`
+**More information on usage:** Deleting an Exam
+
+1. Deleting an exam
+
+ * **Prerequisites:**
+ * Exactly one exam in the exams list. Hence, exam has an index of 1.
+
+ * **Test case:** `deleteExam 1`
+ **Expected:** First exam is deleted from the exams list. Status message shows the exam deleted.
+
+ * **Test case (index out of bounds):** `deleteExam 2`
+ **Expected:** No exam is deleted. Error message shown. No change in the exams list.
+
+ * **Test case (no index):** `deleteExam`
+ **Expected:** No exam is deleted. Error message shown. No change in the exams list.
+
+
+
+
+
+
+
+#### Selecting an Exam: `selectExam`
+
+**Command:** `selectExam`
+**More information on usage:** Selecting an Exam
+
+1. Selecting an exam
+
+ * **Prerequisites:**
+ * Exactly one exam in the exams list. Hence, exam has an index of 1.
+
+ * **Test case:** `selectExam 1`
+ **Expected:** First exam is selected. Status message shows the exam selected.
+
+ * **Test case:** `selectExam 0`
+ **Expected:** No exam is selected. Error message shown. No change in the exams list.
+
+ * **Test case (index out of bounds):** `selectExam 2`
+ **Expected:** No exam is selected. Error message shown. No change in the exams list.
+
+ * **Test case (no index):** `selectExam`
+ **Expected:** No exam is selected. Error message shown. No change in the exams list.
+
+
+
+
+
+#### Deselecting an Exam: `deselectExam`
+
+**Command:** `deselectExam`
+**More information on usage:** Deselecting an Exam
+
+1. Deselecting an exam
+
+ * **Prerequisites:**
+ * An exam has been selected.
+
+ * **Test case:** `deselectExam`
+ **Expected:** Selected exam is deselected. Status message shows the exam deselected.
+
+ * **Test case (no exam selected):** `deselectExam`
+ **Expected:** No exam is deselected. Error message shown. No change in the exams list.
+
+
+
+
+
+
+
+#### Importing Exam Scores: `importExamScores`
+
+**Command:** `importExamScores`
+**More information on usage:** Importing Exam Scores
+
+1. Importing exam scores from a CSV file.
+
+ * **Prerequisites:**
+ * Add an `Exam` to the sample data: `addExam n|Midterm s|100`.
+ * Create a CSV file with the following content:
+ Contents of `/path/to/file.csv`:
+
+ ```
+ email,Exam:Midterm
+ alexyeoh@example.com,50
+ ```
+ * **Test case:** `importExamScores i|/path/to/file.csv`
+ **Expected:** The person with the email of `alexyeoh@example.com` now has a `Midterm` score of `50`.
+
+
+2. Importing an invalid file.
+
+ * **Prerequisites:**
+ * Start with sample data and the `Midterm` exam.
+ * Create a file named `invalid.json`.
+
+ * **Test case:** `importExamScores i|invalid.json`
+ **Expected:** An error message is shown indicating that the file is not a CSV file.
+
+
+3. Importing a CSV file with incorrect formatting.
+
+ * **Prerequisites:**
+ * Start with sample data and the `Midterm` exam.
+ * Create a CSV file with the following content:
+ Contents of `/path/to/file.csv`:
+ ```
+ email,Exam:Midterm,email
+ alexyeoh@example.com,50,alexyeoh@example.com
+ ```
+ * **Test case:** `importExamScores i|/path/to/file.csv`
+ **Expected:** An error message is shown indicating that the email header should exist only in the first column.
+
+ * **Other incorrect `importExamScores` commands to try:** CSV files where email is not the first header.
+ **Expected:** Similar to previous.
+
+
+
+
+4. Importing a CSV file with duplicate entries.
+
+ * **Prerequisites:**
+ * Start with sample data and the `Midterm` exam.
+ * Create a CSV file with the following content:
+ Contents of `/path/to/file.csv`:
+
+ ```
+ email,Exam:Midterm,Exam:Midterm
+ alexyeoh@example.com,50,60
+ ```
+ * **Test case:** `importExamScores i|/path/to/file.csv`
+ **Expected:** A message is shown indicating that there are duplicate entries in the CSV file, and only the first instance has been kept. The `Midterm` score for the person with the email of `alexyeoh@example.com` is `50`.
+
+
+5. Importing a CSV File with invalid entries.
+
+ * **Prerequisites:**
+ * Start with sample data and the `Midterm` exam.
+ * Create a CSV file with the following content:
+ Contents of `/path/to/file.csv`:
+
+ ```
+ email,Exam:Midterm,Exam:Finals
+ alexyeoh@example.com,101,50
+ berniceyu@example.com,50,60
+ nonexistent@example.com,100,100
+ ```
+ * **Test case:** `importExamScores i|/path/to/file.csv`
+ **Expected:** A message is shown indicating that there are invalid entries in the CSV file, and all other valid entries have been imported. The errors shown are as follows:
+
+ * The score for `alexyeoh@example.com` for the `Midterm` exam is invalid.
+ * The person with the email `nonexistent@example.com` does not exist in the given list.
+ * The `Finals` exam does not exist.
+ Note that the `Midterm` score for the person with the email of `berniceyu@example.com` is `50`.
+
+
+ * **Other incorrect `importExamScores` commands to try:** CSV files with a mix of invalid scores, nonexistent emails, and nonexistent exams.
+ **Expected:** Similar to previous.
+
+
+
+
+
+
+#### Adding a Persons's Exam Score: `addScore`
+
+**Command:** `addScore`
+**More information on usage:** Adding an Exam Score
+
+1. Adding a score to a person while all persons are displayed.
+
+ * **Prerequisites:**
+ * Ensure at least one exam is added using the `addExam` command. For this example, we shall add a new exam with name `test exam` and maximum score `100`.
+ * Ensure an exam is selected using the `selectExam` command. For this example, we shall select `test exam` from above.
+ * Ensure all persons are displayed using the `list` command.
+
+ * **Test case:** `addScore 1 s|100`
+ **Expected:** A score of `100` is added to the first person in the list of displayed persons. The score and the name of the corresponding person will be shown in the status message.
+
+ * **Test case:** `addScore 2 s|50.25`
+ **Expected:** A score of `50.25` is added to the second person in the list of displayed persons.The score and the name of the corresponding person will be shown in the status message.
+
+ * **Test case (invalid index input):** `addScore 0 s|100`
+ **Expected:** No score is added to any persons. Error details are shown in the status message.
+
+ * **Test case (no index input):** `addScore s|100`
+ **Expected:** No score is added to any persons. Error details are shown in the status message.
+
+ * **Test case (no score input):** `addScore 3 s|`
+ **Expected:** No score is added to any persons. Error details are shown in the status message.
+
+ * **Test case (score larger than maximum score is input):** `addScore 3 s|101`
+ **Expected:** No score is added to any persons. Error details are shown in the status message.
+
+ * **Test case (negative score input):** `addScore 3 s|-50`
+ **Expected:** No score is added to any persons. Error details are shown in the status message.
+
+ * **Test case (person already contains a score):** `addScore 1 s|50.25`
+ **Expected:** No score is added to any persons. Error details are shown in the status message.
+
+ * **Other incorrect `addScore` commands to try:** `addScore`, `addScore INDEX s|100` (where `INDEX` is larger than the list size), `addScore 3 s|SCORE` (where `SCORE` is non-numeric, is less than 0, more than the maximum score of the selected exams, and/or has more than 2 digits in its fractional part)
+ **Expected:** No score is added to any persons. Error details are shown in the status message.
+
+
+
+
+2. Adding a score to a person while person list is filtered.
+
+ * **Prerequisites:**
+ * Ensure at least one exam is added using the `addExam` command. For this example, we shall add a new exam with name `test exam` and maximum score `100`.
+ * Ensure an exam is selected using the `selectExam` command. For this example, we shall select `test exam` from above.
+ * Filter the person list using the `find` command.
+
+ * **Test case:** Similar to previous.
+ **Expected:** Similar to previous.
+
+
+
+
+
+
+
+#### Editing a Person's Exam Score: `editScore`
+
+**Command:** `editScore`
+**More information on usage:** Editing an Exam Score
+
+1. Editing a score of a person while all persons are displayed.
+
+ * **Prerequisites:**
+ * Ensure at least one exam is added using the `addExam` command. For this example, we shall add a new exam with name `test exam` and maximum score `100`.
+ * Ensure an exam is selected using the `selectExam` command. For this example, we shall select `test exam` from above.
+ * Ensure all persons are displayed using the `list` command.
+ * Ensure that one person in the list has a score for the selected exam using the `addScore` command. For this example, we shall add a score of `100` to the first person in the list.
+
+ * **Test case:** `editScore 1 s|90`
+ **Expected:** The score of `100` is edited to `90` for the first person in the list of displayed persons. The score and the details of the corresponding person will be shown in the status message.
+
+ * **Test case (invalid index input):** `editScore 0 s|90`
+ **Expected:** No person's score is edited. Error details are shown in the status message.
+
+ * **Test case (no index input):** `editScore s|90`
+ **Expected:** No person's score is edited. Error details are shown in the status message.
+
+ * **Test case (no score input):** `editScore 1 s|`
+ **Expected:** No person's score is edited. Error details are shown in the status message.
+
+ * **Test case (score larger than maximum score is input):** `editScore 1 s|101`
+ **Expected:** No score is added to any persons. Error details are shown in the status message.
+
+ * **Test case (person does not contain any score):** `editScore 2 s|90`
+ **Expected:** No score is added to any persons. Error details are shown in the status message.
+
+ * **Other incorrect `editScore` commands to try:** `editScore`, `editScore INDEX s|90` (where `INDEX` is larger than the list size), `editScore 1 s|SCORE` (where `SCORE` is non-numeric, is less than 0, more than the maximum score of the selected exam, and/or has more than 2 digits in its fractional part)
+ **Expected:** No score is added to any persons. Error details are shown in the status message.
+
+
+2. Editing a score of a person while person list is filtered.
+
+ * **Prerequisites:**
+ * Ensure at least one exam is added using the `addExam` command. For this example, we shall add a new exam with name `test exam` and maximum score `100`.
+ * Ensure an exam is selected using the `selectExam` command. For this example, we shall select `test exam` from above.
+ * Filter the person list using the `find` command.
+ * Ensure that one person in the list has a score for the selected exam using the `addScore` command. For this example, we shall add a score of `100` to the first person in the list.
+
+ * **Test case:** Similar to previous.
+ **Expected:** Similar to previous.
+
+
+
+
+
+#### Deleting a Person's Exam Score: `deleteScore`
+
+**Command:** `deleteScore`
+**More information on usage:** Deleting an Exam Score
+
+1. Deleting a score of a person while all persons are displayed.
+
+ * **Prerequisites:**
+ * Ensure at least one exam is added using the `addExam` command. For this example, we shall add a new exam with name `test exam` and maximum score `100`.
+ * Ensure an exam is selected using the `selectExam` command. For this example, we shall select `test exam` from above.
+ * Ensure all persons are displayed using the `list` command.
+ * Ensure that one person in the list has a score for the selected exam using the `addScore` command. For this example, we shall add a score of `100` to the first person in the list.
+
+ * **Test case:** `deleteScore`
+ **Expected:** The score of `100` is deleted from the first person in the list of displayed persons. The details of the corresponding person will be shown in the status message.
+
+ * **Test case (invalid index input):** `deleteScore 0`
+ **Expected:** No person's score is deleted. Error details are shown in the status message.
+
+ * **Test case (person does not contain any score):** `deleteScore 2`
+ **Expected:** No person's score is deleted. Error details are shown in the status message.
+
+ * **Other incorrect `deleteScore` commands to try:** `deleteScore`, `deleteScore INDEX` (where `INDEX` is larger than the list size)
+ **Expected:** No person's score is deleted. Error details are shown in the status message.
+
+
+2. Deleting a score of a person while person list is filtered.
+
+ * **Prerequisites:**
+ * Ensure at least one exam is added using the `addExam` command. For this example, we shall add a new exam with name `test exam` and maximum score `100`.
+ * Ensure an exam is selected using the `selectExam` command. For this example, we shall select `test exam` from above.
+ * Filter the person list using the `find` command.
+ * Ensure that one person in the list has a score for the selected exam using the `addScore` command. For this example, we shall add a score of `100` to the first person in the list.
+
+ * **Test case:** Similar to previous.
+ **Expected:** Similar to previous.
+
+
+
+
+
+
+
+#### Mean and Median of Exam Scores
+
+**More information on usage:** Mean and Median of Exam Scores
+
+1. Mean and median of exam scores while all persons are displayed.
+
+ * **Prerequisites:**
+ * Ensure at least one exam is added using the `addExam` command. For this example, we shall add a new exam with name `test exam` and maximum score `100`.
+ * Ensure an exam is selected using the `selectExam` command. For this example, we shall select `test exam` from above.
+ * Ensure all persons are displayed using the `list` command.
+
+ * **Initially, no scores added to any persons in the list**
+ **Expected:** "No scores available" is displayed at the bottom, right corner of the GUI.
+
+ * **Use `addScore` to add a score of `50` to the first person in the list**
+ **Expected:** A mean score of `50` and a median score of `50` is displayed at the bottom, right corner of the GUI.
+
+ * **Use `addScore` to add a score of `25` to the second person in the list and a score of `27.7` to the third person in the list**
+ **Expected:** the calculated mean value of the three scores (rounded to two decimal places), `50`, `25` and `27.7`, and the median of the three scores, are displayed at the bottom, right corner of the GUI.
+
+
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+
+
+
+### Appendix G: Effort
+
+This section aims to showcase the effort put into Avengers Assemble by our team.
+We will highlight the difficulty level, challenges faced, and effort required in this project.
+
+
+
+#### Difficulty Level
+
+On top of the `Person` entity originally implemented by AB3, Avengers Assemble also incorporates an additional entity of
+`Exam`, with `Score` serving as a connection between the two entities.
+With this additional entity added, considerations had to be made regarding the implementation of
+different features, interactions between each entity, and the management and storage of these
+entities. The consideration of these factors turned out to be more challenging than initially anticipated.
-
+Moreover, in addition to enhancing the original features of AB3 to cater to our target users, Avengers Assemble also introduces
+many new commands to improve the usability of our application, as well as to handle the diverse behaviors and interactions
+of `Person` and `Exam`. This required a significant amount of effort to ensure that the new features were
+implemented correctly and seamlessly integrated with the existing features.
-### Launch and shutdown
+Compared to the individual project, the group project was lower in intensity for each of us in terms of lines of code,
+but the coordination and communication required to ensure that the features were implemented correctly and
+seamlessly integrated with the existing features added a layer of complexity to the project.
-1. Initial launch
+
- 1. Download the jar file and copy into an empty folder
+#### Effort Required
- 1. Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
+##### Enhancements to Existing Features
-1. Saving window preferences
+**Addition of New Fields to Persons**
+New fields such as recitation, studio, matriculation number, was added to persons to align with the context of our application.
- 1. Resize the window to an optimum size. Move the window to a different location. Close the window.
+**Find**
+Our team improved on the existing `find` command of AB3 to allow for more flexibility. With the new improvements, users
+can now find not only based on the name field of persons, but also specify their search based on other fields such as
+`email` and `recitation`. With the addition of the exam score features, we also adapted our `find` command to allow users
+to filter out persons less than or more than a specified score, revamping the way `find` is used and handled.
- 1. Re-launch the app by double-clicking the jar file.
- Expected: The most recent window size and location is retained.
+**Automatic Tagging of Persons**
+In the context of our application, it is mainly used to store students', instructors' and teaching assistants' contacts.
+Hence, on top of the original behavior of the tag feature, we adapted it to automatically tag contacts with a
+matriculation number as students.
-1. _{ more test cases … }_
+**User Interface**
+Enhancements were made to the user interface to improve the user experience. The structure of the user interface was
+modified to accommodate the new features, and the theme of the application was changed to follow the theme of the
+course that we were developing the application for. Furthermore, the logic for the updating of user interface was also
+modified to a more developer-friendly approach which would allow developers to understand and modify the user interface
+more easily.
-### Deleting a person
+
-1. Deleting a person while all persons are being shown
+##### New Features
- 1. Prerequisites: List all persons using the `list` command. Multiple persons in the list.
+**Copy**
+Our team introduced a new copy command which allows for users to copy the email addresses of the currently displayed persons.
+This is to cater to the context of our application, assisting head tutors with the task of making mass announcements.
- 1. Test case: `delete 1`
- Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated.
+**Import and Export**
+To facilitate the handling and managing of large amounts of information, our group introduced the import and export feature to
+allow for flexible data movement externally and internally. These features required extensive effort due to how bug prone
+they were. This is elaborated upon in the challenges section below.
- 1. Test case: `delete 0`
- Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.
+**Exams and Exams Scores**
+The implementation of the exam and exam score features was the most significant addition to our application, requiring adjustments to existing features and the
+introduction of many new commands to handle and manage the addition of exams and exam features. This feature was the most
+complex and required the most effort to implement, as it involved the introduction of a new entity, `Exam`, and the management
+of scores for each person for each exam. This is further elaborated upon in the challenges section below.
- 1. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)
- Expected: Similar to previous.
+
-1. _{ more test cases … }_
+#### Challenges Faced
-### Saving data
+##### Understanding the Existing Codebase
+One of the challenges we faced was understanding the existing codebase of AB3. We had to familiarize ourselves with the
+structure of the codebase, the interactions between the different classes, and the existing features of AB3. This required
+us to spend time reading through the code, discussing the existing features, and identifying potential areas where
+conflicts might arise when adding new features. We also had to consider how to integrate our new features using the existing
+structure in AB3, and how to ensure that the new features did not conflict with the existing features.
-1. Dealing with missing/corrupted data files
+##### Considerations for New Entity `Exam` and its Interactions with `Person`
+Our team wanted to implement a feature that would allow users to manage and store exam scores for each person.
+It was clear from the start that this would require the introduction of a new entity, `Exam`, to store information about
+each exam. However, we found that there was a challenge in determining how to connect the `Person` entity with the `Exam` entity, and how to
+manage and store the scores for each person for each exam. This required careful consideration and planning to ensure that
+the interactions between the two entities were seamless and intuitive for users. We also had to consider how to handle the
+storage of these entities and how to manage the data effectively.
- 1. _{explain how to simulate a missing/corrupted file, and the expected behavior}_
+**Limited User Interface Space for Score Interaction**
-1. _{ more test cases … }_
+One of the greatest challenges was designing a user-friendly interface for score
+interaction within the limited screen space. We had to devise intuitive methods for users to view, input and manage the scores
+of various exams, without overwhelming the interface. This proved to be a greater challenge than initially anticipated,
+as we had to consider trade-offs between functionality and user experience. Lowering the complexity of the interface
+would result in an interface that is easier to read, but might not provide all the necessary information at a glance and
+require more user interactions to access the information. On the other hand, a more complex interface would provide more
+information at a glance, but might overwhelm users with too much information. Striking a balance between these two
+trade-offs was a challenge that required extended discussions and iterations before arriving at a solution that we were
+satisfied with: the selection system for exams.
+
+
+
+**Implementation of Exam and Exam Score Features**
+
+After coming to a consensus in regard to the user interface, implementation for exam features seemed straightforward.
+However, it turned out to be a lot more complex to implement than initially anticipated. Our exam features consisted
+of many sub-features which included the management of exams, the management of scores, the storage of scores in persons,
+and the importing of scores. As we were working in a collaborative environment, we had to consider how to distribute
+the workload in a manner that would prevent conflicts.
+This required early discussions of the structure of the exam and score features, and how they would interact with the existing features of AB3.
+We drafted up diagrams to visualize the interactions between each feature. This helped us to identify potential conflicts
+early on and resolve them through distributing the workload effectively and meeting regularly to discuss progress and issues.
+
+**Data Management for Exams and Scores**
+
+Handling the data for exams and scores was another challenge that we faced. We had to consider how to store the data for
+each exam, how to store the scores for each person for each exam, and how to manage the data effectively.
+The storage for exams was relatively straightforward, as we could create an additional list in the `AddressBook` class to store
+the exams. However, the storage for scores was more complex. We had to decide whether to store all the exam score data
+in corresponding `Exam` objects, or store each persons' exam scores in their corresponding `Person` objects.
+
+There was once again another trade-off to consider: storing all exam score data in the `Exam` objects would make it
+easier to implement exam operations, but would require more complex interactions between the score and person objects.
+On the other hand, storing each person's score in their corresponding `Person` object would make it easier to implement
+operations on persons, but would require more complex interactions for exam management. We had to consider the pros and cons
+of each approach, before deciding on the latter approach, as we concluded that our application was more person-centric.
+
+##### Bug Fixing and Testing
+A significant challenge we faced was the identification and resolution of bugs. Unit tests for our own features were
+relatively straightforward to implement, but we found that identifying edge cases proved to be tricky. Certain features
+were also a lot more bug prone than others, such as the import features, which required extensive testing to ensure that
+all potential errors were caught and proper error messages were displayed. We also had to ensure that the application
+handled these errors gracefully and did not crash when these errors occurred.
+
+
+
+#### Achievements
+Overall, our group successfully implemented the planned features while addressing bugs and managing potential feature flaws.
+Despite initial hesitations about implementing significant new features like exams and exam scores, we overcame the challenge and achieved our goals.
+
+
diff --git a/docs/Documentation.md b/docs/Documentation.md
index 3e68ea364e7..082e652d947 100644
--- a/docs/Documentation.md
+++ b/docs/Documentation.md
@@ -1,29 +1,21 @@
---
-layout: page
-title: Documentation guide
+ layout: default.md
+ title: "Documentation guide"
+ pageNav: 3
---
-**Setting up and maintaining the project website:**
-
-* We use [**Jekyll**](https://jekyllrb.com/) to manage documentation.
-* The `docs/` folder is used for documentation.
-* To learn how set it up and maintain the project website, follow the guide [_[se-edu/guides] **Using Jekyll for project documentation**_](https://se-education.org/guides/tutorials/jekyll.html).
-* Note these points when adapting the documentation to a different project/product:
- * The 'Site-wide settings' section of the page linked above has information on how to update site-wide elements such as the top navigation bar.
- * :bulb: In addition to updating content files, you might have to update the config files `docs\_config.yml` and `docs\_sass\minima\_base.scss` (which contains a reference to `AB-3` that comes into play when converting documentation pages to PDF format).
-* If you are using Intellij for editing documentation files, you can consider enabling 'soft wrapping' for `*.md` files, as explained in [_[se-edu/guides] **Intellij IDEA: Useful settings**_](https://se-education.org/guides/tutorials/intellijUsefulSettings.html#enabling-soft-wrapping)
+# Documentation Guide
+* We use [**MarkBind**](https://markbind.org/) to manage documentation.
+* The `docs/` folder contains the source files for the documentation website.
+* To learn how set it up and maintain the project website, follow the guide [[se-edu/guides] Working with Forked MarkBind sites](https://se-education.org/guides/tutorials/markbind-forked-sites.html) for project documentation.
**Style guidance:**
* Follow the [**_Google developer documentation style guide_**](https://developers.google.com/style).
+* Also relevant is the [_se-edu/guides **Markdown coding standard**_](https://se-education.org/guides/conventions/markdown.html).
-* Also relevant is the [_[se-edu/guides] **Markdown coding standard**_](https://se-education.org/guides/conventions/markdown.html)
-
-**Diagrams:**
-
-* See the [_[se-edu/guides] **Using PlantUML**_](https://se-education.org/guides/tutorials/plantUml.html)
-**Converting a document to the PDF format:**
+**Converting to PDF**
-* See the guide [_[se-edu/guides] **Saving web documents as PDF files**_](https://se-education.org/guides/tutorials/savingPdf.html)
+* See the guide [_se-edu/guides **Saving web documents as PDF files**_](https://se-education.org/guides/tutorials/savingPdf.html).
diff --git a/docs/Gemfile b/docs/Gemfile
deleted file mode 100644
index c8385d85874..00000000000
--- a/docs/Gemfile
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-source "https://rubygems.org"
-
-git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
-
-gem 'jekyll'
-gem 'github-pages', group: :jekyll_plugins
-gem 'wdm', '~> 0.1.0' if Gem.win_platform?
-gem 'webrick'
diff --git a/docs/Logging.md b/docs/Logging.md
index 5e4fb9bc217..589644ad5c6 100644
--- a/docs/Logging.md
+++ b/docs/Logging.md
@@ -1,8 +1,10 @@
---
-layout: page
-title: Logging guide
+ layout: default.md
+ title: "Logging guide"
---
+# Logging guide
+
* We are using `java.util.logging` package for logging.
* The `LogsCenter` class is used to manage the logging levels and logging destinations.
* The `Logger` for a class can be obtained using `LogsCenter.getLogger(Class)` which will log messages according to the specified logging level.
diff --git a/docs/SettingUp.md b/docs/SettingUp.md
index 275445bd551..03df0295bd2 100644
--- a/docs/SettingUp.md
+++ b/docs/SettingUp.md
@@ -1,27 +1,32 @@
---
-layout: page
-title: Setting up and getting started
+ layout: default.md
+ title: "Setting up and getting started"
+ pageNav: 3
---
-* Table of Contents
-{:toc}
+# Setting up and getting started
+
+
--------------------------------------------------------------------------------------------------------------------
## Setting up the project in your computer
-
:exclamation: **Caution:**
+
+**Caution:**
Follow the steps in the following guide precisely. Things will not work out if you deviate in some steps.
-
+
First, **fork** this repo, and **clone** the fork into your computer.
If you plan to use Intellij IDEA (highly recommended):
1. **Configure the JDK**: Follow the guide [_[se-edu/guides] IDEA: Configuring the JDK_](https://se-education.org/guides/tutorials/intellijJdk.html) to to ensure Intellij is configured to use **JDK 11**.
-1. **Import the project as a Gradle project**: Follow the guide [_[se-edu/guides] IDEA: Importing a Gradle project_](https://se-education.org/guides/tutorials/intellijImportGradleProject.html) to import the project into IDEA.
- :exclamation: Note: Importing a Gradle project is slightly different from importing a normal Java project.
+1. **Import the project as a Gradle project**: Follow the guide [_[se-edu/guides] IDEA: Importing a Gradle project_](https://se-education.org/guides/tutorials/intellijImportGradleProject.html) to import the project into IDEA.
+
+ Note: Importing a Gradle project is slightly different from importing a normal Java project.
+
1. **Verify the setup**:
1. Run the `seedu.address.Main` and try a few commands.
1. [Run the tests](Testing.md) to ensure they all pass.
@@ -34,10 +39,11 @@ If you plan to use Intellij IDEA (highly recommended):
If using IDEA, follow the guide [_[se-edu/guides] IDEA: Configuring the code style_](https://se-education.org/guides/tutorials/intellijCodeStyle.html) to set up IDEA's coding style to match ours.
-
:bulb: **Tip:**
+
+ **Tip:**
Optionally, you can follow the guide [_[se-edu/guides] Using Checkstyle_](https://se-education.org/guides/tutorials/checkstyle.html) to find how to use the CheckStyle within IDEA e.g., to report problems _as_ you write code.
-
+
1. **Set up CI**
diff --git a/docs/Testing.md b/docs/Testing.md
index 8a99e82438a..78ddc57e670 100644
--- a/docs/Testing.md
+++ b/docs/Testing.md
@@ -1,12 +1,15 @@
---
-layout: page
-title: Testing guide
+ layout: default.md
+ title: "Testing guide"
+ pageNav: 3
---
-* Table of Contents
-{:toc}
+# Testing guide
---------------------------------------------------------------------------------------------------------------------
+
+
+
+
## Running tests
@@ -19,8 +22,10 @@ There are two ways to run tests.
* **Method 2: Using Gradle**
* Open a console and run the command `gradlew clean test` (Mac/Linux: `./gradlew clean test`)
-
:link: **Link**: Read [this Gradle Tutorial from the se-edu/guides](https://se-education.org/guides/tutorials/gradle.html) to learn more about using Gradle.
-
+
+
+**Link**: Read [this Gradle Tutorial from the se-edu/guides](https://se-education.org/guides/tutorials/gradle.html) to learn more about using Gradle.
+
--------------------------------------------------------------------------------------------------------------------
diff --git a/docs/UserGuide.md b/docs/UserGuide.md
index 7abd1984218..91a9bcf6430 100644
--- a/docs/UserGuide.md
+++ b/docs/UserGuide.md
@@ -1,198 +1,1217 @@
---
-layout: page
-title: User Guide
+ layout: default.md
+ title: "User Guide"
---
-AddressBook Level 3 (AB3) is a **desktop app for managing contacts, 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, AB3 can get your contact management tasks done faster than traditional GUI apps.
+# Avengers Assemble User Guide
-* Table of Contents
-{:toc}
+Avengers Assemble (AA) is a **desktop app for managing contacts**, meant for use with a Command Line Interface (CLI)
+while still having the benefits of a Graphical User Interface (GUI).
+
+The application is designed for **Head Tutors** of the NUS CS1101S Programming Methodology course, who intend to simplify their administrative tasks relating to contact management between students, other teaching assistants, and course instructors.
+
+This user guide provides a comprehensive overview of the Avengers Assemble's features and functionalities, and aims to guide you through its setup and usage. We will walk you through each feature in a structured manner:
+
+1. Installation,
+2. Basic commands like adding and editing, and
+3. Advanced commands like filtering and exporting of data.
+
+By following this guide, you will be able to gain a thorough understanding of Avengers Assemble and maximize its potential to streamline your administrative tasks.
--------------------------------------------------------------------------------------------------------------------
-## Quick start
+
+## Table of Contents
+
+Click below to navigate the user guide:
+
+
-1. Ensure you have Java `11` or above installed in your Computer.
+
-1. Download the latest `addressbook.jar` from [here](https://github.com/se-edu/addressbook-level3/releases).
+--------------------------------------------------------------------------------------------------------------------
-1. Copy the file to the folder you want to use as the _home folder_ for your AddressBook.
+
-1. Open a command terminal, `cd` into the folder you put the jar file in, and use the `java -jar addressbook.jar` command to run the application.
- A GUI similar to the below should appear in a few seconds. Note how the app contains some sample data.
- 
+## Quick Start
-1. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
- Some example commands you can try:
+1. Ensure you have `Java 11` or above installed in your computer.
- * `list` : Lists all contacts.
+2. Download the latest `avengersassemble.jar` [here](https://github.com/AY2324S2-CS2103T-T10-1/tp/releases).
- * `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : Adds a contact named `John Doe` to the Address Book.
+3. Copy the file to the folder you want to use as the _home folder_ for our application.
- * `delete 3` : Deletes the 3rd contact shown in the current list.
+4. Open a command terminal, `cd` into the folder you put the jar file in, and use the `java -jar avengersassemble.jar` command to run the application.
+ ```dtd
+ cd
+ java -jar avengersassemble.jar
+ ```
+ You should see this when the app starts up. Note how it contains some sample data.
- * `clear` : Deletes all contacts.
+
+
+
- * `exit` : Exits the app.
+5. Refer to the [features](#contact-management-features) below for details of each command.
-1. Refer to the [Features](#features) below for details of each command.
+
--------------------------------------------------------------------------------------------------------------------
-## Features
+
+
+
+
+## Outline of Application
+
+The image below shows the outline of the application, with the main sections highlighted:
+
+
+
+
+
+
+The main sections are as follows:
+
+1. **Command Input Box**:
+ * This is where you can type your commands.
+ * Press `Enter` to execute the command.
+2. **Results Box**:
+ * This area displays the results of the commands you have executed.
+ * It will also display any error messages if the command was not executed successfully.
+3. **Persons Display Panel**:
+ * This area displays the list of persons that you have imported or saved into our application.
+ * Each persons is displayed with an index number, name, email, phone number, address, and tags.
+ * Each person is also displayed with their matriculation number, studio group, and reflection group if they have been added.
+ * If an exam is selected, the person's score for that exam will also be displayed if it exists.
+4. **Exams Display Panel**:
+ * This area displays the list of exams that you have added into our application.
+ * Each exam is displayed with an index number, name, and maximum score.
+ * Selected exams will be highlighted in the list.
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+
+
+
+## Contact Management Features
+
+These features are designed to help you manage your contacts effectively and centralizes all contact information in one place.
+You can import contacts from CSV files generated by external sources such as canvas and edurec, manage the contact details of each person in your contact list, and export relevant data as CSV files.
+
+### Legend
+These boxes might offer you additional information of different types:
+
+>**Good to know:**
+>Provides you with supporting information.
-
+
-**:information_source: Notes about the command format:**
+**Important:**
+Provides you with more important information that you should know.
+
-* Words in `UPPER_CASE` are the parameters to be supplied by the user.
- e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`.
+
-* Items in square brackets are optional.
- e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`.
+**Tip:**
+Provides you with tips to use our app more effectively.
-* Items with `…` after them can be used multiple times including zero times.
- e.g. `[t/TAG]…` can be used as ` ` (i.e. 0 times), `t/friend`, `t/friend t/family` etc.
+
+
+
+
+**Caution:**
+Provides you with warnings about potential issues you might face.
+
+
+
+
+
+
+
+### Getting Help : `help`
+
+Copies the link of our user guide to your clipboard. Paste it into a browser to view it.
+
+**Format:** `help`
+
+You will see this message when you have successfully copied the link.
+
+
+
+
+
+
+
+Before we proceed with the commands, here are some important points to note on their formatting. These points will also be repeated in the [command parameter summary](#command-parameter-summary) for you to refer to easily at any point in time.
+
+
+
+**Important:**
+
+* Words in `UPPER_CASE` are the parameters to be supplied by you.
+ > e.g. in `add n|NAME`, `NAME` is a parameter which can be used as `add n|John Doe`.
+
+* Prefixes encased with '[ ]' are optional.
+ > e.g. `n|NAME [t|TAG]` can be used as `n|John Doe t|friend` or as `n|John Doe`.
+
+* Prefixes with '…' after them can be used multiple times.
+ > e.g. `[t|TAG]…` can be used as ` ` (i.e. 0 times), `t|friend` (i.e 1 time), `t|friend t|family` etc.
* Parameters can be in any order.
- e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable.
+ > e.g. if the command specifies `n|NAME p|PHONE_NUMBER`, `p|PHONE_NUMBER n|NAME` is also acceptable.
+
+* Extraneous parameters for commands that do not take in parameters (such as `help` , `list`, `exit`, `copy`, `export` and `clear`) will be ignored.
+ > e.g. if the command specifies `help 123`, it will be interpreted as `help`.
+
+
-* Extraneous parameters for commands that do not take in parameters (such as `help`, `list`, `exit` and `clear`) will be ignored.
- e.g. if the command specifies `help 123`, it will be interpreted as `help`.
+
+**Caution:**
* If you are using a PDF version of this document, be careful when copying and pasting commands that span multiple lines as space characters surrounding line-breaks may be omitted when copied over to the application.
-
-### Viewing help : `help`
+
+
+
-Shows a message explaning how to access the help page.
+
-
+### Clearing All Entries : `clear`
-Format: `help`
+Deletes **all** data from the application. This includes all contact information and examinations.
+**Format:** `clear`
-### Adding a person: `add`
+
-Adds a person to the address book.
+**Caution:**
+Using clear will delete all data in an irreversible manner. Be sure to back up your relevant data by using the `export` command before using this command.
-Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…`
+
+
+
+
+
+
+
+
+### Importing Persons from a CSV File : `import`
+
+Imports all persons and their details from a CSV file of your specification.
+
+**Format:** `import i|FILEPATH`
+
+
+
+**Important:**
+
+* The file path should be **absolute**.
+* This command will only import persons' particulars. To import exam scores, take a look at [`importExamScores`](#importing-exam-scores-from-a-csv-file--importexamscores).
+* All compulsory parameters **must** be present in the column headings (i.e. the first row) of the CSV file you are importing i.e. `name`, `email`, `phone` and `address`.
+* Only values under accepted column headings are read i.e. `name`, `email`, `phone`, `address`, `tags`, `matric`, `reflection` and `studio`
+* The number of headers must match the number of cells for each row.
+* Invalid rows will be skipped and will not be imported!
+
+
+
+**Example:** `import i|/Users/johansoo/Desktop/AvengersAssemble/exam_data.csv`
+imports the data from the CSV file located at `/Users/johansoo/Desktop/AvengersAssemble/exam_data.csv`
+
+You will see this message once you successfully imported the data, with the app showing the details of the imported persons:
+
+
+
+
+
+For more details on the input parameter, [click here](#command-parameter-summary).
+
+
+
+
+
+
+
+### Adding a Person : `add`
+
+Adds a person to your contact list. The person's details are now stored in the application.
+
+**Format:** `add n|NAME p|PHONE_NUMBER e|EMAIL a|ADDRESS [t|TAG]… [m|MATRICULATION_NUMBER] [s|STUDIO] [r|REFLECTION]`
+
+
+
+**Important:**
+
+Each person should have a unique email address. Avengers Assemble does not allow for duplicate email addresses to be added.
+
+
+
+
+
+**Tip:**
-
:bulb: **Tip:**
A person can have any number of tags (including 0)
-
-Examples:
-* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01`
-* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal`
+
+
+> **Note:**
+> For your convenience, a `student` tag will automatically be added to a contact if they are added with a matriculation number.
+> You are free to edit or remove the tags after the person is added with the [`edit`](#editing-a-person--edit) command.
+> For example, a student TA can be added with the `student` tag, and then the `TA` tag can be added to indicate that they are a TA.
+
+**Example:**
+`add n|John Doe p|98765432 e|johnd@example.com a|John street, block 123, #01-01 m|A1234567Z s|S1 r|R2`
+adds a contact John Doe with the respective phone number, email and physical addresses, matriculation number, studio group and reflection group.
+
+You will see this message once you have successfully added a person, indicating their details:
+
+
+
+
-### Listing all persons : `list`
+For more details on each parameter, [click here](#command-parameter-summary).
-Shows a list of all persons in the address book.
+
-Format: `list`
+
-### Editing a person : `edit`
+
-Edits an existing person in the address book.
+### Editing a Person : `edit`
-Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…`
+Edits the details of an existing person in your contact list.
-* Edits the person at the specified `INDEX`. The index refers to the index number shown in the displayed person list. The index **must be a positive integer** 1, 2, 3, …
+**Format:** `edit INDEX [n|NAME] [p|PHONE] [e|EMAIL] [a|ADDRESS] [t|TAG]… [m|MATRICULATION_NUMBER] [s|STUDIO] [r|REFLECTION]`
+
+
+
+**Information:**
+* The person at the specified `INDEX` will be edited. The index **must be a positive integer** (1, 2, 3, …).
* At least one of the optional fields must be provided.
-* Existing values will be updated to the input values.
-* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative.
-* You can remove all the person’s tags by typing `t/` without
- specifying any tags after it.
+* Existing values will be updated to the new values.
+* Editing tags will replace all existing tags i.e. adding of tags is **not cumulative**.
+* You can remove optional fields by typing `t|`, `m|`, `r|` or `s|` respectively without any values.
-Examples:
-* `edit 1 p/91234567 e/johndoe@example.com` Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively.
-* `edit 2 n/Betsy Crower t/` Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags.
+
-### Locating persons by name: `find`
+
-Finds persons whose names contain any of the given keywords.
+**Important:**
-Format: `find KEYWORD [MORE_KEYWORDS]`
+Updating a matriculation number, studio, or reflection field will not automatically update the tags of the person. You will need to manually update the tags if necessary.
-* The search is case-insensitive. e.g `hans` will match `Hans`
-* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans`
-* Only the name is searched.
-* Only full words will be matched e.g. `Han` will not match `Hans`
-* Persons matching at least one keyword will be returned (i.e. `OR` search).
- e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang`
+
-Examples:
-* `find John` returns `john` and `John Doe`
-* `find alex david` returns `Alex Yeoh`, `David Li`
- 
+**Examples:**
-### Deleting a person : `delete`
+1. `edit 2 n|Betsy Crower t|`:
+ * Edits the name of the second person to be `Betsy Crower` and clears all existing tags.
-Deletes the specified person from the address book.
+
-Format: `delete INDEX`
+2. `edit 1 p|91234567 e|johndoe@example.com`:
+ * Edits the phone number and email address of the first person to be `91234567` and `johndoe@example.com` respectively.
-* Deletes the person at the specified `INDEX`.
-* The index refers to the index number shown in the displayed person list.
-* The index **must be a positive integer** 1, 2, 3, …
+You will see this message once you have successfully edited a person, indicating their updated details:
-Examples:
-* `list` followed by `delete 2` deletes the 2nd person in the address book.
-* `find Betsy` followed by `delete 1` deletes the 1st person in the results of the `find` command.
+
+
+
-### Clearing all entries : `clear`
+For more details on each parameter, [click here](#command-parameter-summary).
-Clears all entries from the address book.
+
-Format: `clear`
+
-### Exiting the program : `exit`
+
-Exits the program.
+### Deleting a Person : `delete`
-Format: `exit`
+Deletes the specified person from your contact list.
-### Saving the data
+**Format:** `delete INDEX`
-AddressBook data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually.
+
-### Editing the data file
+**Important:**
-AddressBook data are saved automatically as a JSON file `[JAR file location]/data/addressbook.json`. Advanced users are welcome to update data directly by editing that data file.
+The person at the specified `INDEX` will be deleted. The index **must be a positive integer** (1, 2, 3, …)
-
:exclamation: **Caution:**
-If your changes to the data file makes its format invalid, AddressBook will discard all data and start with an empty data file at the next run. Hence, it is recommended to take a backup of the file before editing it.
-Furthermore, certain edits can cause the AddressBook to behave in unexpected ways (e.g., if a value entered is outside of the acceptable range). Therefore, edit the data file only if you are confident that you can update it correctly.
-
+
+
+**Examples**:
+
+1. `find n|Betsy` followed by `delete 1` deletes the first person in the results of the `find` command.
+2. `list` followed by `delete 1` deletes the first person stored in the app.
+
+You will see this message once you successfully delete a person from your list, indicating the details of the deleted person:
+
+
+
+
+
+
+
+
+
+
+
+### Deleting Filtered Persons : `deleteShown`
+
+Deletes the current filtered list of persons. Requires a [`find`](#filtering-persons--find) command to be run first.
+
+**Format:** `deleteShown`
+
+
+
+**Information:**
+
+* Deletes all persons in the current filtered list of persons.
+* The list of persons is filtered using the most recent [`find`](#filtering-persons--find) command.
+* The remaining list of persons is shown after the [`list`](#listing-all-persons--list) command is executed.
+
+
+
+> **Note:** The application ignores any extraneous parameters as we assume they are typos.
+
+You will see this message once you have successfully deleted the shown persons from your list.
+
+
+
+
+
+
+
+
+
+
+
+### Listing All Persons : `list`
+
+Displays all the persons in your contact list.
+
+**Format:** `list`
+
+> **Note:** The application ignores any extraneous parameters as we assume they are typos.
+
+You will see this message once you have successfully listed all contacts, with the app showing all existing persons in the contact list:
+
+
+
+
+
+
+
+
+
+
+
+### Filtering Persons : `find`
+
+Filters your contacts based on specific criteria you set.
+
+**Format:** `find PREFIX|KEYWORD`
+
+
+
+**Information:**
+* Use this command to search for persons using a specific aspect of their details, as specified by the prefix.
+* The search will return any result that contains the keyword you have specified or matches the condition provided by the user.
+ > e.g. `find e|john` will find any person that contains `john` in their email.
+ > e.g. `find lt|50` will find any person who scored lower than 50 marks for the selected exam.
+ > e.g. `find mt|80.55` will find any person who scored more than 80.55 marks for the selected exam.
+* The search is **case-insensitive**.
+* Only one prefix can be used at a time.
+
+
+
+
+
+**Important: An exam must be selected for this command to work with the `lt|` and `mt|` prefixes!
+You can use the [`selectExam`](#selecting-an-exam--selectexam) command to do so.**
+
+
+
+**Example:** `find n|John`
+returns `john` and `John Doe` if they exist in your contact book.
+
+You will see this message once you have successfully found a person, with the app showing all persons that match your search criteria:
+
+
+
+
+
+For more details on each parameter, [click here](#command-parameter-summary).
+
+
+
+
+
+
+
+### Copying Emails : `copy`
+
+Copies the emails of currently displayed persons into your clipboard.
+
+**Format:** `copy`
+
+
+
+**Information:**
+* The emails copied into your clipboard will have semicolons separating them.
+* Semicolons are used as delimiters to separate the emails when pasted into any email client.
+
+
+
+
+
+**Tip:**
+
+* Use [`list`](#listing-all-persons--list) or [`find`](#filtering-persons--find) to get the list of people you would like to email.
+* The emails are copied into your clipboard such that you may easily broadcast emails to specific groups of people.
+
+
+
+> **Note:** The application ignores any extraneous parameters as we assume they are typos.
+
+You will see this message once you have successfully copied the emails of the persons shown to you, indicating that they have been copied to the clipboard:
+
+
+
+
+
+
+
+
+
+
+
+### Exporting Data to a CSV File : `export`
+
+Exports currently displayed persons and their details to a CSV file of your specification.
+
+**Format:** `export`
+
+> By default, the file will be stored in `addressbookdata/avengersassemble.csv`.
+
+
+
+**Tip:**
+
+You can specify the groups of contacts you want to export using the [`find`](#filtering-persons--find) or [`list`](#listing-all-persons--list) commands before you use this command.
+
+
+
+
+
+**Caution:**
+
+When performing an export, the current information will overwrite any existing CSV files with the same name.
+If you want to preserve the exported data, you should rename it or save it in a separate location.
+
+
+
+You will see this message once you have successfully exported the data:
+
+
+
+
+
+
+
+
+
+### Exiting the Program : `exit`
+
+Exits the program. The app will close automatically.
+
+**Format:** `exit`
+
+> **Note:** The application ignores any extraneous parameters as we assume they are typos.
+
+
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+
+
+
+## Exam Management Features
+
+These features are designed to help you manage exam scores for the persons in your contact list and consolidate all assessment data from canvas, edurec, and source academy.
+You can import exam scores from CSV files generated by these platforms, manage the exam scores of each person in your contact list, and gather statistics on student performance.
+
+
-### Archiving data files `[coming in v2.0]`
+### Importing Exam Scores from a CSV File : `importExamScores`
-_Details coming soon ..._
+Imports all exam results from a CSV file.
+
+**Format:** `importExamScores i|FILEPATH`
+
+
+
+**Information:**
+
+* The file path should be **absolute**.
+* The `email` header **must** be the first column header.
+* Exam names starting with `Exam:` e.g. if your exam is named `Midterms`, the column heading containing the scores for `Midterms` should be named `Exam:Midterms`.
+* This command will only import scores if both the person and exam exists currently in Avengers Assemble. Use [`add`](#add) and [`addExam`](#addexam) to add persons and exams respectively.
+* Duplicate exam headers in the CSV file will be ignored, with only the first occurrence being used.
+* Each row following the header row corresponds to an individual's exam scores,
+ with the first column containing the person's email address and the subsequent columns
+ containing the scores for the exams as specified by the headers.
+* Exam score values should be entered as decimal numbers within the valid score range (0 - maximum score),
+ rounded to a maximum of 2 decimal places.
+
+
+
+
+
+**Caution:**
+
+* Erroneous entries will be ignored, and the application will continue to import the rest of the data.
+* This command will only import persons' exam scores. To import persons' particulars, take a look at [`import`](#importing-persons-from-a-csv-file--import)
+
+
+
+**Example:** `importExamScores i|/Users/johansoo/Desktop/AvengersAssemble/exam_data.csv`
+imports exam results from the CSV file located at `/Users/johansoo/Desktop/AvengersAssemble/exam_data.csv`.
+
+You will see this message once you have successfully imported the exam results:
+
+
+
+
+
+For more details on the parameter, [click here](#command-parameter-summary).
+
+
+
+
+
+### Adding an Exam : `addExam`
+
+Adds an exam into your exam list.
+
+**Format:** `addExam n|NAME s|MAX_SCORE`
+
+
+
+**Important:**
+
+Each exam should have a unique name. Avengers Assemble does not allow for exams with duplicate names to be added.
+
+
+
+**Example:** `addExam n|Midterm s|100`
+Adds an exam with the name "Midterm" and a max score of "100" into your exam list.
+
+You will see this message once you successfully add an exam, including the details of the exam:
+
+
+
+
+
+For more details on each parameter, [click here](#command-parameter-summary).
+
+
+
+
+
+
+
+### Deleting an Exam : `deleteExam`
+
+Removes an exam from your exam list.
+
+**Format:** `deleteExam INDEX`
+
+
+
+**Information:**
+
+* Deletes the exam at the specified `INDEX`.
+* When an exam is deleted, all corresponding records of scores associated with that exam will also be deleted.
+* If the currently selected exam is deleted, it will be deselected.
+
+
+
+**Example:** `deleteExam 3`
+Removes the third exam displayed in Avengers Assemble.
+
+You will see this message once you have successfully deleted an exam, including the details of the exam you are deleting:
+
+
+
+
+
+
+
+
+
+
+
+### Selecting an Exam : `selectExam`
+
+Selects an exam in your exam list.
+
+**Format:** `selectExam INDEX`
+
+
+
+**Information:**
+
+* Selects the exam at the specified `INDEX`.
+* On selection, the exam will become highlighted on the user interface.
+* Selecting an exam will display all scores of persons associated with that exam.
+
+
+
+**Example:** `selectExam 1`
+Selects the first exam displayed on the exam list.
+
+You will see this message once you have successfully selected an exam, including the details of the exam:
+
+
+
+
+
+
+
+
+
+
+
+### Deselecting an Exam : `deselectExam`
+
+Deselects your currently selected exam.
+
+**Format:** `deselectExam`
+
+You will see this message once you have successfully deselected an exam:
+
+
+
+
+
+
+
+
+
+
+
+### Adding an Exam Score : `addScore`
+
+Adds an exam score to a person at the specified index.
+
+**Format:** `addScore INDEX s|SCORE`
+
+
+
+**Important: An exam must be selected for this command to work! You can use the [`selectExam`](#selectexam) command to do so.**
+
+
+
+
+
+**Information:**
+
+* Adds an exam score to the person at the specific `INDEX`.
+* The exam score added will correspond to the currently selected exam.
+* The exam score added **cannot** be greater than the max score of the currently selected exam.
+* The exam score will be displayed on the user interface only when the corresponding exam is selected.
+
+
+
+**Example:** `addScore 1 s|42`
+Adds a score of 42 to the person currently displayed at index 1.
+
+You will see this message once you successfully add a score, including the name of the person you added the score for:
+
+
+
+
+
+For more details on the parameter, [click here](#command-parameter-summary).
+
+
+
+
+
+
+
+### Editing an Exam Score : `editScore`
+
+Edits a specified person's exam score.
+
+**Format:** `editScore INDEX s|SCORE`
+
+
+
+**Information:**
+
+* Edits the exam score of the person at the specific `INDEX`.
+* A person **must** have an exam score for the currently selected exam for this command to work.
+* The exam score edited corresponds to the currently selected exam.
+* The exam score **cannot** be edited to be greater than the max score of the currently selected exam.
+
+
+
+
+
+**Important:**
+
+An exam must be selected for this command to work! You can use the [`selectExam`](#selecting-an-exam--selectexam) command to do so.
+
+
+
+**Example:** `editScore 1 s|25`
+Edits the score of the person currently displayed at index 1 to 25.
+
+You will see this message once you successfully edit a score, including some details of the person you added the score for:
+
+
+
+
+
+For more details on the parameter, [click here](#command-parameter-summary).
+
+
+
+
+
+
+
+### Deleting an Exam Score : `deleteScore`
+
+Deletes a specified person's exam score.
+
+**Format:** `deleteScore INDEX`
+
+
+
+**Information:**
+
+* Deletes the exam score of the person at the specific `INDEX`.
+* A person **must** have an exam score for the currently selected exam for this command to work.
+* The exam score deleted corresponds to the currently selected exam.
+
+
+
+
+
+**Important:**
+
+An exam must be selected for this command to work! You can use the [`selectExam`](#selecting-an-exam--selectexam) command to do so.
+
+
+
+**Example:** `deleteScore 1`
+deletes the score of the person currently displayed at index 1.
+
+You will see this message once you have successfully deleted a score, including some details of the person you added the score for:
+
+
+
+
+
+
+
+
+
+
+
+### Mean and Median of Exam Scores
+
+You can view the mean and median of the scores of the exam currently selected at the bottom right of the application window.
+
+
+
+**Information:**
+
+* When an exam is selected, the mean and median will automatically show up on the right of the footer of the application.
+* The mean and median is calculated based on the currently filtered list of persons.
+* If a person has no score for the selected exam, he is completely excluded from the calculation of mean and median.
+
+
+
+When an exam is selected, the statistics will show on the bottom right of the application:
+
+
+
+
+
+
--------------------------------------------------------------------------------------------------------------------
+
+
+
+
+## Additional Information
+
+### Saving the Data
+
+All data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually.
+
+### Editing the Data File
+
+All data are saved automatically as a JSON file located at `[JAR file location]/data/avengersassemble.json` by default. You can update data directly by editing that data file if you are an advanced user.
+
+
+
+**Caution:**
+
+If your changes to the data file makes its format invalid, Avengers Assemble will discard all data and start with an empty data file at the next run. Hence, it is recommended to take a backup of the file before editing it.
+Furthermore, certain edits can cause the Avengers Assemble application to behave in unexpected ways (e.g., if a value entered is outside the acceptable range). Therefore, edit the data file only if you are confident that you can update it correctly.
+
+
+
+
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+
## FAQ
-**Q**: How do I transfer my data to another Computer?
-**A**: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous AddressBook home folder.
+**Q**: How do I transfer my data to another computer?
+**A**: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous AA home folder.
+
+
--------------------------------------------------------------------------------------------------------------------
-## Known issues
+
+
+## Known Issues
+
+### Using Multiple Screens
+
+If you move the application to a secondary screen, and later switch to using only the primary screen, the GUI will open off-screen. The remedy is to delete the `preferences.json` file created by the application before running the application again.
+
+### Importing on MacOS
+
+On MacOS computers, due to privacy settings, the application may encounter difficulties accessing and importing CSV files from various locations.
+If this issue occurs, transfer the CSV file you want to import to the same folder where the application's JAR file is located, then try again.
-1. **When using multiple screens**, if you move the application to a secondary screen, and later switch to using only the primary screen, the GUI will open off-screen. The remedy is to delete the `preferences.json` file created by the application before running the application again.
+### Exporting Data on Initial Launch
+
+Since the `export` function relies on data stored in your computer's hard disk, there might be some issues exporting it during the first launch of the application.
+If you encounter this problem, you can resolve it by executing any other command (such as `list`) and then attempting the export again.
+
+
+
+--------------------------------------------------------------------------------------------------------------------
+
+
+
+
+
+## Command Summary
+
+Below is a summary of the commands available in Avengers Assemble. Some examples are included for your convenience.
+
+
+
+
+
+
Action
+
Format, Examples
+
+
+
Help
+
help
+
+
+
Clear
+
clear
+
+
+
Import
+
import i|FILEPATH
e.g. import i|C:/Users/alk/Downloads/avengersassemble.csv
e.g. add n|James Ho p|22224444 e|jamesho@example.com a|123, Clementi Rd, 1234665 t|friend t|colleague m|A1234567X
+
+
+
Edit
+
edit INDEX [n|NAME] [p|PHONE_NUMBER] [e|EMAIL] [a|ADDRESS] [t|TAG]… [m|MATRICULATION_NUMBER] [s|STUDIO] [r|REFLECTION]
e.g. edit 2 n|James Lee e|jameslee@example.com m|A1234567X
+
+
+
Delete
+
delete INDEX
e.g. delete 3
+
+
+
Delete Shown Persons
+
deleteShown
+
+
+
List
+
list
+
+
+
Find
+
find PREFIX|KEYWORD
e.g. find n|James
+
+
+
Copy
+
copy
+
+
+
Export to CSV
+
export
+
+
+
Exit
+
exit
+
+
+
Import Exam Scores
+
importExamScores i|FILEPATH
e.g. importExamScores i|C:/Users/alk/Downloads/exam_scores.csv
+
+
+
Add Exam
+
addExam n|NAME s|MAX_SCORE
e.g. addExam n|Midterm s|100
+
+
+
Delete Exam
+
deleteExam INDEX
e.g. deleteExam 3
+
+
+
Select Exam
+
selectExam INDEX
e.g. selectExam 1
+
+
+
Deselect Exam
+
deselectExam
+
+
+
Add Exam Score
+
addScore INDEX s|SCORE
e.g. addScore 1 s|42
+
+
+
Edit Exam Score
+
editScore INDEX s|SCORE
e.g. editScore 1 s|25
+
+
+
Delete Exam Score
+
deleteScore INDEX
e.g. deleteScore 1
+
+
+
+
--------------------------------------------------------------------------------------------------------------------
-## Command summary
-
-Action | Format, Examples
---------|------------------
-**Add** | `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…` e.g., `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague`
-**Clear** | `clear`
-**Delete** | `delete INDEX` e.g., `delete 3`
-**Edit** | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…` e.g.,`edit 2 n/James Lee e/jameslee@example.com`
-**Find** | `find KEYWORD [MORE_KEYWORDS]` e.g., `find James Jake`
-**List** | `list`
-**Help** | `help`
+
+
+
+
+## Command Parameter Summary
+
+Some commands require you to include parameters. These parameters are identified by prefixes. Here are a list of valid prefixes and what they each refer to.
+
+
+
+**Important:**
+
+* Words in `UPPER_CASE` are the parameters to be supplied by you.
+ > e.g. in `add n|NAME`, `NAME` is a parameter which can be used as `add n|John Doe`.
+
+* Prefixes encased with '[ ]' are optional.
+ > e.g. `n|NAME [t|TAG]` can be used as `n|John Doe t|friend` or as `n|John Doe`.
+
+* Prefixes with '…' after them can be used multiple times.
+ > e.g. `[t|TAG]…` can be used as ` ` (i.e. 0 times), `t|friend` (i.e 1 time), `t|friend t|family` etc.
+
+* Parameters can be in any order.
+ > e.g. if the command specifies `n|NAME p|PHONE_NUMBER`, `p|PHONE_NUMBER n|NAME` is also acceptable.
+
+* Extraneous parameters for commands that do not take in parameters (such as `help` , `list`, `exit`, `copy`, `export` and `clear`) will be ignored.
+ > e.g. if the command specifies `help 123`, it will be interpreted as `help`.
+
+
+
+
+
+**Caution:**
+* If you are using a PDF version of this document, be careful when copying and pasting commands that span multiple lines as space characters surrounding line-breaks may be omitted when copied over to the application.
+* Note the same prefix may be used for different purposes such as in the case of `s|` for studios and for scores. In these cases, we ensure no command would have to use the same prefix for multiple purposes.
+
+
+
+
+
+
Prefix
+
What it Refers to
+
Max. Length
+
Constraints
+
+
+
n|
+
Name
+
80
+
Should only contain alphanumeric characters, spaces, and the characters ,, -, ., /, ( and ).
+
+
+
n|
+
Exam Name
+
30
+
Should only contain alphanumeric characters and spaces.
+
+
+
p|
+
Phone Number
+
30
+
It can start with an optional + to indicate the country code, with the rest only containing numbers. It should be at least 3 digits long.
+
+
+
e|
+
Email
+
100
+
Format: local-part@domain Constraints for local part: • Should only contain alphanumeric characters, and the characters +, _, . and -. • Should not start or end with special characters. • Should not have two consecutive special characters. Constraints for domain: • Made up of domain labels separated by periods. • Must end with a domain label of at least 2 characters long. • Domain label should consist of alphanumeric characters separated only by singular hyphens, if any.
+
+
+
a|
+
Address
+
100
+
Can take any values.
+
+
+
i|
+
Path of CSV File to Import
+
-
+
Should be the absolute file path of the CSV file without any inverted commas.
+
+
+
[m| ]
+
Matriculation ID
+
Fixed at 9
+
The first letter must be an uppercase 'A', followed by 7 numbers, and end with an uppercase letter.
+
+
+
[r| ]
+
Reflection Group
+
4
+
The first letter must be an uppercase 'R', followed by any number.
+
+
+
[s| ]
+
Studio Group
+
4
+
The first letter must be an uppercase 'S', followed by any number.
+
+
+
[s| ]
+
Score
+
7 + 2 decimals
+
For exam max scores: the input must be a positive integer. For persons' exam scores: the input must be an integer greater than or equal to zero.
+
+
+
[t| ]…
+
Tags
+
100
+
Should be alphanumeric, and should not contain spaces.
+
+
+
[lt|]
+
Less Than
+
7 + 2 decimals
+
Should be a positive numerical value smaller than the currently selected exam's max score.
+
+
+
[mt| ]
+
More Than
+
7 + 2 decimals
+
Should be a positive numerical value smaller than the currently selected exam's max score.
+
-:information_source: Don’t forget to update `AddressBookParser` to use our new `RemarkCommandParser`!
+Don’t forget to update `AddressBookParser` to use our new `RemarkCommandParser`!
-
+
If you are stuck, check out the sample
[here](https://github.com/se-edu/addressbook-level3/commit/dc6d5139d08f6403da0ec624ea32bd79a2ae0cbf#diff-8bf239e8e9529369b577701303ddd96af93178b4ed6735f91c2d8488b20c6b4a).
@@ -244,7 +247,7 @@ Simply add the following to [`seedu.address.ui.PersonCard`](https://github.com/s
**`PersonCard.java`:**
-``` java
+```java
@FXML
private Label remark;
```
@@ -276,11 +279,11 @@ We change the constructor of `Person` to take a `Remark`. We will also need to d
Unfortunately, a change to `Person` will cause other commands to break, you will have to modify these commands to use the updated `Person`!
-
+
-:bulb: Use the `Find Usages` feature in IntelliJ IDEA on the `Person` class to find these commands.
+Use the `Find Usages` feature in IntelliJ IDEA on the `Person` class to find these commands.
-
+
Refer to [this commit](https://github.com/se-edu/addressbook-level3/commit/ce998c37e65b92d35c91d28c7822cd139c2c0a5c) and check that you have got everything in order!
@@ -291,11 +294,11 @@ AddressBook stores data by serializing `JsonAdaptedPerson` into `json` with the
While the changes to code may be minimal, the test data will have to be updated as well.
-
+
-:exclamation: You must delete AddressBook’s storage file located at `/data/addressbook.json` before running it! Not doing so will cause AddressBook to default to an empty address book!
+You must delete AddressBook’s storage file located at `/data/avengersassemble.json` before running it! Not doing so will cause AddressBook to default to an empty address book!
-
+
Check out [this commit](https://github.com/se-edu/addressbook-level3/commit/556cbd0e03ff224d7a68afba171ad2eb0ce56bbf)
to see what the changes entail.
@@ -308,7 +311,7 @@ Just add [this one line of code!](https://github.com/se-edu/addressbook-level3/c
**`PersonCard.java`:**
-``` java
+```java
public PersonCard(Person person, int displayedIndex) {
//...
remark.setText(person.getRemark().value);
@@ -328,7 +331,7 @@ save it with `Model#setPerson()`.
**`RemarkCommand.java`:**
-``` java
+```java
//...
public static final String MESSAGE_ADD_REMARK_SUCCESS = "Added remark to Person: %1$s";
public static final String MESSAGE_DELETE_REMARK_SUCCESS = "Removed remark from Person: %1$s";
diff --git a/docs/tutorials/RemovingFields.md b/docs/tutorials/RemovingFields.md
index f29169bc924..c73bd379e5e 100644
--- a/docs/tutorials/RemovingFields.md
+++ b/docs/tutorials/RemovingFields.md
@@ -1,8 +1,11 @@
---
-layout: page
-title: "Tutorial: Removing Fields"
+ layout: default.md
+ title: "Tutorial: Removing Fields"
+ pageNav: 3
---
+# Tutorial: Removing Fields
+
> Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.
>
> — Antoine de Saint-Exupery
@@ -10,17 +13,17 @@ title: "Tutorial: Removing Fields"
When working on an existing code base, you will most likely find that some features that are no longer necessary.
This tutorial aims to give you some practice on such a code 'removal' activity by removing the `address` field from `Person` class.
-
+
**If you have done the [Add `remark` command tutorial](AddRemark.html) already**, you should know where the code had to be updated to add the field `remark`. From that experience, you can deduce where the code needs to be changed to _remove_ that field too. The removing of the `address` field can be done similarly.
However, if you have no such prior knowledge, removing a field can take a quite a bit of detective work. This tutorial takes you through that process. **At least have a read even if you don't actually do the steps yourself.**
-
+
-* Table of Contents
-{:toc}
+
+
## Safely deleting `Address`
@@ -50,10 +53,10 @@ Let’s try removing references to `Address` in `EditPersonDescriptor`.
1. Remove the usages of `address` and select `Do refactor` when you are done.
-
+
- :bulb: **Tip:** Removing usages may result in errors. Exercise discretion and fix them. For example, removing the `address` field from the `Person` class will require you to modify its constructor.
-
+ **Tip:** Removing usages may result in errors. Exercise discretion and fix them. For example, removing the `address` field from the `Person` class will require you to modify its constructor.
+
1. Repeat the steps for the remaining usages of `Address`
@@ -71,7 +74,7 @@ A quick look at the `PersonCard` class and its `fxml` file quickly reveals why i
**`PersonCard.java`**
-``` java
+```java
...
@FXML
private Label address;
diff --git a/docs/tutorials/TracingCode.md b/docs/tutorials/TracingCode.md
index 4fb62a83ef6..2b1b0f2d6b7 100644
--- a/docs/tutorials/TracingCode.md
+++ b/docs/tutorials/TracingCode.md
@@ -1,26 +1,30 @@
---
-layout: page
-title: "Tutorial: Tracing code"
+ layout: default.md
+ title: "Tutorial: Tracing code"
+ pageNav: 3
---
+# Tutorial: Tracing code
+
+
> Indeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code. …\[Therefore,\] making it easy to read makes it easier to write.
>
> — Robert C. Martin Clean Code: A Handbook of Agile Software Craftsmanship
When trying to understand an unfamiliar code base, one common strategy used is to trace some representative execution path through the code base. One easy way to trace an execution path is to use a debugger to step through the code. In this tutorial, you will be using the IntelliJ IDEA’s debugger to trace the execution path of a specific user command.
-* Table of Contents
-{:toc}
+
+
## Before we start
Before we jump into the code, it is useful to get an idea of the overall structure and the high-level behavior of the application. This is provided in the 'Architecture' section of the developer guide. In particular, the architecture diagram (reproduced below), tells us that the App consists of several components.
-
+
It also has a sequence diagram (reproduced below) that tells us how a command propagates through the App.
-
+
Note how the diagram shows only the execution flows _between_ the main components. That is, it does not show details of the execution path *inside* each component. By hiding those details, the diagram aims to inform the reader about the overall execution path of a command without overwhelming the reader with too much details. In this tutorial, you aim to find those omitted details so that you get a more in-depth understanding of how the code works.
@@ -37,16 +41,16 @@ As you know, the first step of debugging is to put in a breakpoint where you wan
In our case, we would want to begin the tracing at the very point where the App start processing user input (i.e., somewhere in the UI component), and then trace through how the execution proceeds through the UI component. However, the execution path through a GUI is often somewhat obscure due to various *event-driven mechanisms* used by GUI frameworks, which happens to be the case here too. Therefore, let us put the breakpoint where the `UI` transfers control to the `Logic` component.
-
+
According to the sequence diagram you saw earlier (and repeated above for reference), the `UI` component yields control to the `Logic` component through a method named `execute`. Searching through the code base for an `execute()` method that belongs to the `Logic` component yields a promising candidate in `seedu.address.logic.Logic`.
-
+
-:bulb: **Intellij Tip:** The ['**Search Everywhere**' feature](https://www.jetbrains.com/help/idea/searching-everywhere.html) can be used here. In particular, the '**Find Symbol**' ('Symbol' here refers to methods, variables, classes etc.) variant of that feature is quite useful here as we are looking for a _method_ named `execute`, not simply the text `execute`.
-
+**Intellij Tip:** The ['**Search Everywhere**' feature](https://www.jetbrains.com/help/idea/searching-everywhere.html) can be used here. In particular, the '**Find Symbol**' ('Symbol' here refers to methods, variables, classes etc.) variant of that feature is quite useful here as we are looking for a _method_ named `execute`, not simply the text `execute`.
+
A quick look at the `seedu.address.logic.Logic` (an extract given below) confirms that this indeed might be what we’re looking for.
@@ -67,14 +71,14 @@ public interface Logic {
But apparently, this is an interface, not a concrete implementation.
That should be fine because the [Architecture section of the Developer Guide](../DeveloperGuide.html#architecture) tells us that components interact through interfaces. Here's the relevant diagram:
-
+
Next, let's find out which statement(s) in the `UI` code is calling this method, thus transferring control from the `UI` to the `Logic`.
-
+
-:bulb: **Intellij Tip:** The ['**Find Usages**' feature](https://www.jetbrains.com/help/idea/find-highlight-usages.html#find-usages) can find from which parts of the code a class/method/variable is being used.
-
+**Intellij Tip:** The ['**Find Usages**' feature](https://www.jetbrains.com/help/idea/find-highlight-usages.html#find-usages) can find from which parts of the code a class/method/variable is being used.
+

@@ -87,10 +91,10 @@ Now let’s set the breakpoint. First, double-click the item to reach the corres
Recall from the User Guide that the `edit` command has the format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…` For this tutorial we will be issuing the command `edit 1 n/Alice Yeoh`.
-
+
-:bulb: **Tip:** Over the course of the debugging session, you will encounter every major component in the application. Try to keep track of what happens inside the component and where the execution transfers to another component.
-
+**Tip:** Over the course of the debugging session, you will encounter every major component in the application. Try to keep track of what happens inside the component and where the execution transfers to another component.
+
1. To start the debugging session, simply `Run` \> `Debug Main`
@@ -110,7 +114,7 @@ Recall from the User Guide that the `edit` command has the format: `edit INDEX [
**LogicManager\#execute().**
- ``` java
+ ```java
@Override
public CommandResult execute(String commandText)
throws CommandException, ParseException {
@@ -142,7 +146,7 @@ Recall from the User Guide that the `edit` command has the format: `edit INDEX [

1. _Step into_ the line where user input in parsed from a String to a Command, which should bring you to the `AddressBookParser#parseCommand()` method (partial code given below):
- ``` java
+ ```java
public Command parseCommand(String userInput) throws ParseException {
...
final String commandWord = matcher.group("commandWord");
@@ -157,7 +161,7 @@ Recall from the User Guide that the `edit` command has the format: `edit INDEX [
1. Stepping through the `switch` block, we end up at a call to `EditCommandParser().parse()` as expected (because the command we typed is an edit command).
- ``` java
+ ```java
...
case EditCommand.COMMAND_WORD:
return new EditCommandParser().parse(arguments);
@@ -166,8 +170,10 @@ Recall from the User Guide that the `edit` command has the format: `edit INDEX [
1. Let’s see what `EditCommandParser#parse()` does by stepping into it. You might have to click the 'step into' button multiple times here because there are two method calls in that statement: `EditCommandParser()` and `parse()`.
-
:bulb: **Intellij Tip:** Sometimes, you might end up stepping into functions that are not of interest. Simply use the `step out` button to get out of them!
-
+
+
+ **Intellij Tip:** Sometimes, you might end up stepping into functions that are not of interest. Simply use the `step out` button to get out of them!
+
1. Stepping through the method shows that it calls `ArgumentTokenizer#tokenize()` and `ParserUtil#parseIndex()` to obtain the arguments and index required.
@@ -175,17 +181,17 @@ Recall from the User Guide that the `edit` command has the format: `edit INDEX [

1. As you just traced through some code involved in parsing a command, you can take a look at this class diagram to see where the various parsing-related classes you encountered fit into the design of the `Logic` component.
-
+
1. Let’s continue stepping through until we return to `LogicManager#execute()`.
The sequence diagram below shows the details of the execution path through the Logic component. Does the execution path you traced in the code so far match the diagram?
- 
+
1. Now, step over until you read the statement that calls the `execute()` method of the `EditCommand` object received, and step into that `execute()` method (partial code given below):
**`EditCommand#execute()`:**
- ``` java
+ ```java
@Override
public CommandResult execute(Model model) throws CommandException {
...
@@ -205,25 +211,28 @@ Recall from the User Guide that the `edit` command has the format: `edit INDEX [
* it uses the `updateFilteredPersonList` method to ask the `Model` to populate the 'filtered list' with _all_ persons.
FYI, The 'filtered list' is the list of persons resulting from the most recent operation that will be shown to the user immediately after. For the `edit` command, we populate it with all the persons so that the user can see the edited person along with all other persons. If this was a `find` command, we would be setting that list to contain the search results instead.
To provide some context, given below is the class diagram of the `Model` component. See if you can figure out where the 'filtered list' of persons is being tracked.
-
+
* :bulb: This may be a good time to read through the [`Model` component section of the DG](../DeveloperGuide.html#model-component)
1. As you step through the rest of the statements in the `EditCommand#execute()` method, you'll see that it creates a `CommandResult` object (containing information about the result of the execution) and returns it.
Advancing the debugger by one more step should take you back to the middle of the `LogicManager#execute()` method.
1. Given that you have already seen quite a few classes in the `Logic` component in action, see if you can identify in this partial class diagram some of the classes you've encountered so far, and see how they fit into the class structure of the `Logic` component:
-
+
+
* :bulb: This may be a good time to read through the [`Logic` component section of the DG](../DeveloperGuide.html#logic-component)
1. Similar to before, you can step over/into statements in the `LogicManager#execute()` method to examine how the control is transferred to the `Storage` component and what happens inside that component.
-
:bulb: **Intellij Tip:** When trying to step into a statement such as `storage.saveAddressBook(model.getAddressBook())` which contains multiple method calls, Intellij will let you choose (by clicking) which one you want to step into.
-
+
+
+ **Intellij Tip:** When trying to step into a statement such as `storage.saveAddressBook(model.getAddressBook())` which contains multiple method calls, Intellij will let you choose (by clicking) which one you want to step into.
+
-1. As you step through the code inside the `Storage` component, you will eventually arrive at the `JsonAddressBook#saveAddressBook()` method which calls the `JsonSerializableAddressBook` constructor, to create an object that can be _serialized_ (i.e., stored in storage medium) in JSON format. That constructor is given below (with added line breaks for easier readability):
+1. As you step through the code inside the `Storage` component, you will eventually arrive at the `JsonAddressBook#saveAddressBook()` method which calls the `JsonSerializableAddressBook` constructor, to create an object that can be _serialized_ (i.e., stored in storage medium) in JSON format. That constructor is given below (with added line breaks for easier readability):
**`JsonSerializableAddressBook` constructor:**
- ``` java
+ ```java
/**
* Converts a given {@code ReadOnlyAddressBook} into this class for Jackson use.
*
@@ -243,7 +252,8 @@ Recall from the User Guide that the `edit` command has the format: `edit INDEX [
This is because regular Java objects need to go through an _adaptation_ for them to be suitable to be saved in JSON format.
1. While you are stepping through the classes in the `Storage` component, here is the component's class diagram to help you understand how those classes fit into the structure of the component.
-
+
+
* :bulb: This may be a good time to read through the [`Storage` component section of the DG](../DeveloperGuide.html#storage-component)
1. We can continue to step through until you reach the end of the `LogicManager#execute()` method and return to the `MainWindow#executeCommand()` method (the place where we put the original breakpoint).
@@ -251,7 +261,7 @@ Recall from the User Guide that the `edit` command has the format: `edit INDEX [
1. Stepping into `resultDisplay.setFeedbackToUser(commandResult.getFeedbackToUser());`, we end up in:
**`ResultDisplay#setFeedbackToUser()`**
- ``` java
+ ```java
public void setFeedbackToUser(String feedbackToUser) {
requireNonNull(feedbackToUser);
resultDisplay.setText(feedbackToUser);
diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/seedu/address/MainApp.java
index 3d6bd06d5af..e645d997555 100644
--- a/src/main/java/seedu/address/MainApp.java
+++ b/src/main/java/seedu/address/MainApp.java
@@ -36,7 +36,7 @@
*/
public class MainApp extends Application {
- public static final Version VERSION = new Version(0, 2, 2, true);
+ public static final Version VERSION = new Version(1, 3, 0, false);
private static final Logger logger = LogsCenter.getLogger(MainApp.class);
diff --git a/src/main/java/seedu/address/commons/core/GuiSettings.java b/src/main/java/seedu/address/commons/core/GuiSettings.java
index a97a86ee8d7..fa18f527fdd 100644
--- a/src/main/java/seedu/address/commons/core/GuiSettings.java
+++ b/src/main/java/seedu/address/commons/core/GuiSettings.java
@@ -12,8 +12,8 @@
*/
public class GuiSettings implements Serializable {
- private static final double DEFAULT_HEIGHT = 600;
- private static final double DEFAULT_WIDTH = 740;
+ private static final double DEFAULT_HEIGHT = 1000;
+ private static final double DEFAULT_WIDTH = 1500;
private final double windowWidth;
private final double windowHeight;
diff --git a/src/main/java/seedu/address/commons/exceptions/DataLoadingException.java b/src/main/java/seedu/address/commons/exceptions/DataLoadingException.java
index 9904ba47afe..1f40c4bc423 100644
--- a/src/main/java/seedu/address/commons/exceptions/DataLoadingException.java
+++ b/src/main/java/seedu/address/commons/exceptions/DataLoadingException.java
@@ -7,5 +7,8 @@ public class DataLoadingException extends Exception {
public DataLoadingException(Exception cause) {
super(cause);
}
+ public DataLoadingException(String message) {
+ super(message);
+ }
}
diff --git a/src/main/java/seedu/address/commons/util/CsvUtil.java b/src/main/java/seedu/address/commons/util/CsvUtil.java
new file mode 100644
index 00000000000..0f01210046e
--- /dev/null
+++ b/src/main/java/seedu/address/commons/util/CsvUtil.java
@@ -0,0 +1,270 @@
+package seedu.address.commons.util;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Queue;
+import java.util.Set;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.dataformat.csv.CsvMapper;
+import com.fasterxml.jackson.dataformat.csv.CsvSchema;
+import com.opencsv.CSVParser;
+import com.opencsv.CSVParserBuilder;
+import com.opencsv.CSVReader;
+import com.opencsv.CSVReaderBuilder;
+import com.opencsv.exceptions.CsvException;
+
+import javafx.util.Pair;
+import seedu.address.commons.exceptions.DataLoadingException;
+import seedu.address.logic.commands.exceptions.CommandException;
+
+/**
+ * Utility class for processing CSV files.
+ * Acknowledgement: The methods in this class were made possible with the help of
+ * the [OpenCSV](http://opencsv.sourceforge.net/) library.
+ */
+public class CsvUtil {
+
+ public static final String MESSAGE_ERROR_READING_FILE = "Error reading file: ";
+
+ /**
+ * Reads a CSV file.
+ * Firstly, it checks if the compulsory parameters are present in the header of the csv file (the header
+ * is the first line of the csv file).
+ * Secondly, it only reads the columns that are in compulsoryParameters or optionalParameters.
+ * Values in other headers will be ignored.
+ * Thirdly, it checks if the number of values in each row is the same as the number of headers.
+ * If the check for compulsory parameters fails, the error report will contain the missing compulsory parameters.
+ * If the check for the number of values in each row fails, the error report will contain the rows that do not have
+ * the same number of values as the number of headers.
+ * It is crucial that a dataLoadingException is thrown in the
+ * caller of this method if the error report is not empty.
+ * @param filePath the path of the file
+ * @param compulsoryParameters
+ * @param optionalParameters
+ * @return
+ * A pair in which the first value is the data and the second is the error report. Data can be null if
+ * the file is not read successfully or if any compulsory parameters are missing in the header row of csv file.
+ * @throws IOException
+ */
+ public static Pair>>, String> readCsvFile(
+ Path filePath, HashSet compulsoryParameters, HashSet optionalParameters)
+ throws IOException {
+ List