Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/AY2324S1-CS2103-F13-2/tp
Browse files Browse the repository at this point in the history
…into help
  • Loading branch information
nixonwidjaja committed Oct 26, 2023
2 parents 914d682 + 090a5c9 commit 6f25637
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 152 deletions.
191 changes: 59 additions & 132 deletions docs/DeveloperGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,112 +154,39 @@ Classes used by multiple components are in the `seedu.addressbook.commons` packa

This section describes some noteworthy details on how certain features are implemented.

### \[Proposed\] Undo/redo feature
### Undo/redo feature

#### Proposed Implementation

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:
The implementation involves creating an `AddressBookList` class which extends from `ArrayList<AddressBook>` to store the history of `AddressBook`.
`AddressBookList` also stores an integer `index` as a pointer to the current `AddressBook` and an `ArrayList<String>` of commands input by the user called `pastCommands`.

* `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.
Whenever `AddressBook` is changed, it will store its copy and append it to the `AddressBookList`, increment `index` by 1, and append the command
which modifies the `AddressBook` to `pastCommands`.

These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively.
When `AddressBookList#undo()` is called, the current `AddressBook` changes to `AddressBookList.get(index - 1)` and `index` is decremented by 1.
If the current `index` is at 0, `AddressBookList` will throw an error stating there is no command to undo.

Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
If after undoing some command the user decides to modify the `AddressBook` with new commands, `AddressBookList` will overwrite all `AddressBook` after that particular state.
For example, currently `AddressBookList` has 10 `AddressBook` in it and the current state is at `AddressBookList.get(5)`. Then, the user adds an employee. All `AddressBook`
at index 6 to 9 will be deleted and `AddressBookList.get(6)` will now contain the new `AddressBook` that has the new employee in it.

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.
When `AddressBookList#redo()` is called, the current `AddressBook` changes to `AddressBookList.get(index + 1)` and `index` is incremented by 1.
If the current `index` is at `AddressBookList.size() - 1`, `AddressBookList` will throw an error stating there is no command to redo.

![UndoRedoState0](images/UndoRedoState0.png)
`AddressBookList` sits in `ModelManager` class where it will be modifed whenever `ModelManager#addPerson()`, `ModelManager#deletePerson()`, and `ModelManager#setPerson()`
are called, i.e., whenever `AddressBook` is changed. `ModelManager#undo()` will call `AddressBookList#undo()` and `ModelManager#redo()` will call `AddressBookList#redo()`.

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.

![UndoRedoState1](images/UndoRedoState1.png)
#### Design Considerations

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`.

![UndoRedoState2](images/UndoRedoState2.png)

<div markdown="span" class="alert alert-info">: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`.

</div>

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.

![UndoRedoState3](images/UndoRedoState3.png)

<div markdown="span" class="alert alert-info">: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.

</div>

The following sequence diagram shows how the undo operation works:

![UndoSequenceDiagram](images/UndoSequenceDiagram.png)

<div markdown="span" class="alert alert-info">: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.

</div>

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.

<div markdown="span" class="alert alert-info">: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.

</div>

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.

![UndoRedoState4](images/UndoRedoState4.png)

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.

![UndoRedoState5](images/UndoRedoState5.png)

The following activity diagram summarizes what happens when a user executes a new command:

<img src="images/CommitActivityDiagram.png" width="250" />

#### Design considerations:

**Aspect: How undo & redo executes:**

* **Alternative 1 (current choice):** Saves the entire address book.
* **Alternative 1 (current choice):** Stores the entire address book.
* Pros: Easy to implement.
* Cons: May have performance issues in terms of memory usage.

* **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}_

### Export Data Feature

#### Proposed Implementation

The proposed export mechanism is facilitated by `AddressBook`. Additionally, the operation is exposed in the Model interface which allows users to perform `filter` operation to discard selected portions of the Model interface before exporting.

The primary operations that aid in this mechanism are:
* `getFilteredPersonList()` -- Used in conjunction with `filter` operation so that the model will display the latest Persons of interest.
* `generateListPeople()` -- Performs extracting of Person objects from the latest model and obtaining the Person's attributes.
* `generateFile()` -- Creates a directory for exported CSVs and a File object containing the filename imposed by the user.
* `PrintWri

#### Design considerations:

**Aspect: How undo & redo executes:**

* **Alternative 1 (current choice):** Saves the entire address book.
* Pros: Easy to implement.
* Cons: May have performance issues in terms of memory usage.

* **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}_
* **Alternative 2:** Stores only the changes between address book versions. For example, only store the employee being added when the user adds an employee.
* Pros: Less memory.
* Cons: More complications on the logic side: undoing `add` = `delete`, undoing `clear` = `add` back all employees, etc.

### Export Data Feature

Expand Down Expand Up @@ -291,7 +218,7 @@ The following activity diagram summarizes what happens when a user attempts to e

<img src="images/ExportActivityDiagram.png" width="250" />

#### Design considerations:
#### Design Considerations

**Aspect: How exports executes:**

Expand All @@ -303,6 +230,45 @@ The following activity diagram summarizes what happens when a user attempts to e
* Pros: User can perform better categorisation of data according to organisation's needs.
* Cons: Harder to implement since program needs to know which locations are out-of-bounds. Example: src files.

### Birthday Feature

#### Implementation

The birthday feature extends HR Insight by allowing the user to view birthdays in a given month.
This operation is exposed in the Command Interface as `Command#BirthdayCommand`.

Given below is an example usage scenario and how the birthday mechanism behaves at each step.

Step 1: The user launches the application for the first time.

Step 2: The user executes `add n/John Doe ... ` to add a new employee.

Step 3: After adding a few employees into the application, he/she wants to view the birthdays in the month of January
to prepare the birthday celebrations in advance. The `birthday m/1` command will display all employees with birthdays
in the month of January.

Step 4: The user then realises that today is the first day of a new month and he/she wants to view which employees
have birthdays in the current month. The `birthday` command without providing the month will display all employees with
birthdays in the current month.

The following sequence diagram shows how the `birthday` command works:

![SequenceDiagram](images/BirthdayCommand.png)

### Reasoning
The birthday command is designed to show users birthday by month instead of week/day as month gives the user a broader
range to work with. Furthermore, it is also a common practice for companies to have 1 celebration for all employees'
birthdays in a month rather than having multiple individual celebrations. Hence, this feature is designed to show
birthdays by month.

### Aspect: How birthday executes:
* **Alternative 1 (current choice)** : Allows the user to view birthday in a month
* Pros: Allows the user to view birthdays in a broader range.
* Cons: User cannot view birthdays that occur across multiple months
* **Alternative 2**: Allows the user to view birthdays in multiple months
* Pros: User will be able to view birthdays across multiple months with only one use of the command.<Br>
(e.g. `birthday m/2,3` returns all birthdays in February and March )
* Cons: We must ensure that every month given by the user is valid and mention which months have no birthdays.

--------------------------------------------------------------------------------------------------------------------

Expand Down Expand Up @@ -674,45 +640,6 @@ The following activity diagram summarizes what happens when a user attempts to e
* Pros: User can perform better categorisation of data according to organisation's needs.
* Cons: Harder to implement since program needs to know which locations are out-of-bounds. Example: src files.

### \[Implemented\] Birthday Feature

#### Implementation

The birthday feature extends HR Insight by allowing the user to view birthdays in a given month.
This operation is exposed in the Command Interface as `Command#BirthdayCommand`.

Given below is an example usage scenario and how the birthday mechanism behaves at each step.

Step 1: The user launches the application for the first time.

Step 2: The user executes `add n/John Doe ... ` to add a new employee.

Step 3: After adding a few employees into the application, he/she wants to view the birthdays in the month of January
to prepare the birthday celebrations in advance. The `birthday m/1` command will display all employees with birthdays
in the month of January.

Step 4: The user then realises that today is the first day of a new month and he/she wants to view which employees
have birthdays in the current month. The `birthday` command without providing the month will display all employees with
birthdays in the current month.

The following sequence diagram shows how the `birthday` command works:

![SequenceDiagram](/Users/remuslum/Downloads/CS2103_tP/tp/docs/images/BirthdayCommand.png)

### Reasoning
The birthday command is designed to show users birthday by month instead of week/day as month gives the user a broader
range to work with. Furthermore, it is also a common practice for companies to have 1 celebration for all employees'
birthdays in a month rather than having multiple individual celebrations. Hence, this feature is designed to show
birthdays by month.

### Aspect: How birthday executes:
* **Alternative 1 (current choice)** : Allows the user to view birthday in a month
* Pros: Allows the user to view birthdays in a broader range.
* Cons: User cannot view birthdays that occur across multiple months
* **Alternative 2**: Allows the user to view birthdays in multiple months
* Pros: User will be able to view birthdays across multiple months with only one use of the command.
* (e.g. `birthday m/2,3` returns all birthdays in February and March )
* Cons: We must ensure that every month given by the user is valid and mention which months have no birthdays.
--------------------------------------------------------------------------------------------------------------------

## **Documentation, logging, testing, configuration, dev-ops**
Expand Down
Loading

0 comments on commit 6f25637

Please sign in to comment.