Skip to content

Commit

Permalink
Merge pull request #193 from solomonng2001/add-implementation-for-sor…
Browse files Browse the repository at this point in the history
…t-birthday-priority-in-developer-guide

Add DG implementation details for sorting, birthday and priority
  • Loading branch information
getsquared authored Apr 14, 2024
2 parents 0e27bfe + 321c70e commit 5cd8d4a
Show file tree
Hide file tree
Showing 5 changed files with 253 additions and 0 deletions.
72 changes: 72 additions & 0 deletions docs/DeveloperGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ The sequence diagram below shows the execution of `view 1` to view the details o
* In this implementation, `DisplayClient` would simply be a `Person` set by `CommandResult`, similar to the current `feedbackToUser` implementation.
* However, this means `DisplayClient` can only be set after a command, which does not allow us to set `DisplayClient` on application startup.


### Adding notes to client feature

The `remark` command allows users to add an optional note to a client.
Expand All @@ -212,8 +213,36 @@ The `remark` command was implemented according to [Tutorial: Adding a command](h
* While this might make it easier to type, it will also make fixing typos slower, like mentioned in the current behaviour.
* It also means that a separate way of parsing has to be used, instead of `ArgumentMultimap`, deviating from other commands.


### Sorting clients feature

The `sort` command allows users to sort the client list by a specified `sort criteria` that can be `name`, `priority` or `birthday`, and a `sort order` that can be `asc` or `desc`.

#### Implementation

The functionality to `sort` clients is implemented in the `SortCommand` class. The `SortCommandParser` class is responsible for parsing the user input and creating a `SortCommand` object.

The `SortCommandParser` class parses the input arguments by storing the prefixes of their respective values in a `ArgumentMultimap` object, and create a new `SortCommand` object with the parsed `SortCriteria` and `SortOrder`.

The `SortCommand` object does the following:
- `PersonComparator#getComparator(SortCriteria, SortOrder)` is used to get the `Comparator<Person>` object using the `SortCriteria` and `SortOrder`.
- `Model#updateSortPersonComparator(Comparator<Person>)` - Updates the `Comparator<Person>` object used to sort the list of persons in the `Model` component.
- `Model#setDisplayClientAsFirstInSortedFilteredPersonList()` - Updates the displayed client in the UI to the first client in the sorted list of persons.

The following object diagram illustrates the above:
<puml src="diagrams/SortPersonsObjectDiagram.puml" width="600" />

The following sequence diagram shows the `sort` operation:
<puml src="diagrams/SortPersonsSequenceDiagram.puml" width="900" />

#### Design Considerations

In order to keep `ModelManager#filteredPersons` as an immutable `final` field, we have decided not to modify the `filteredPersons` directly. Instead, we do the following:
- we store the `Comparator<Person>` object in `ModelManager#personComparator`, which can be updated by `ModelManager#updateSortPersonComparator(Comparator<Person>)`.
- When a sorted list of persons is needed, we call `ModelManager#getSortedFilteredPersonList()` which returns a new sorted list of persons sorted using the `ModelManager#personComparator`.

This way, the original order of `ModelManager#filteredPersons` is preserved, and we can get a sorted list of persons when needed.


### Updating last met feature
The last met feature allows users to keep track and update their last interaction with their clients.
Expand Down Expand Up @@ -331,6 +360,49 @@ The following sequence diagram shows the addpolicy operation:
### Deleting policy feature


### Extensions to add command and edit command: Add birthday, edit birthday, add priority, edit priority features

The add birthday and edit birthday features allow users to add and edit the birthday of a client. Birthdays support the birthday reminders feature. The birthday is stored in the `Birthday` class, which contains the birthday details such as day, month, and year. The `Birthday` class is part of the `Person` object in the `Model` component.

The add priority and edit priority features allow users to add and edit the priority of a client. Priority supports the sort by priority feature, and helps optimise client management. The priority is stored in the `Priority` class, which contains the priority details such as priority value. The priority value are enumerated, and can be one of the following: `LOW`, `MEDIUM`, `HIGH`, `VIP`. The `Priority` class is part of the `Person` object in the `Model` component.

#### Implementation

The functionality to add and edit birthday and priority is implemented in the `AddCommand` and `EditCommand` classes. The `AddCommandParser` and `EditCommandParser` classes are responsible for parsing the user input and creating an `AddCommand` or `EditCommand` object respectively.

The `AddCommandParser` and `EditCommandParser` classes parse the input arguments by storing the prefixes of their respective values in a `ArgumentMultimap` object, and create a new `AddCommand` or `EditCommand` object with the parsed birthday or priority, amongst other fields.

The `AddCommand` and `EditCommand` objects then communicate with the `Model` component to add or edit the birthday or priority of the client. The `Model` component then adds or edits the `Person` object with the new birthday or priority, amongst other fields.

The `AddCommand` object then communicates with the `Model` component to add a person.
- `Model#addPerson(Person)` - Adds the new client to the existing client list.
- `Model#setDisplayClient(Person)` - Updates the displayed client in the UI to the client that has been added.

The following object diagram illustrates the above:
<puml src="diagrams/AddPersonObjectDiagram.puml" width="600" />

The following sequence diagram shows the `add` operation:
<puml src="diagrams/AddPersonSequenceDiagram.puml" width="900" />

More on `Birthday` class
* Birthday is immutable and stores the day, month and year as a `LocalDate` object, as time is not relevant for birthday.
* The message constraints for birthday utilise the `DateUtil` common class to ensure that the date is valid and in the correct format.
* `DateUtil` class is used to validate (conforms to `DateUtil` date format and is parsable) and parse the string to a `LocalDate` object. `DateUtil` is also used to ensure that the date is not in the future.
* Refer to the `DateUtil` class for more information on the date format and parsing.

More on `Priority` class
* Priority is immutable and stores the priority value as a `PriorityValue` object, which is an enumerated type, to ensure that priority value is a valid type.
* The message constraints for priority utilise the `PriorityValue` enum class which should be responsible for the `toString()` logic for display.
* `PriorityValue` enum class is used to validate the priority value, which is responsible for the possible valid priority values.
* Refer to the `PriorityValue` enum class for more information on the priority values.

More on `PriorityValue` enum class
* `PriorityValue` is an enumerated type that contains the possible valid priority values: `LOW`, `MEDIUM`, `HIGH`, `VIP`.
* When parsing from a string and displaying as a string, the `PriorityValue` allows full form values (`low`, `medium`, `high`, `vip`) and short form values (`l`, `m`, `h`, `v`) to be used interchangeably.
* Parsing from a string to a `PriorityValue` object is case-insensitive, and is handled by `getPriority`.
* Obtaining the all available full form and short form of the `PriorityValue` object is handled by `getFullPriorities()` and `getShortPriorities()` respectively.
* The mapping of the full form strings and short form strings to the enum values is handled through `HashMap<String, PriorityValue> FULL_PRIORITY_MAP` and `HashMap<String, PriorityValue> SHORT_PRIORITY_MAP`, which has a constant time complexity.

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

#### Proposed Implementation
Expand Down
24 changes: 24 additions & 0 deletions docs/diagrams/AddPersonObjectDiagram.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@startuml
!include style.puml
skinparam objectFontColor white

object "<u>:AddCommand</u>" as AddCommand LOGIC_COLOR
object "<u>:AddCommandParser</u>" as AddCommandParser LOGIC_COLOR
object "<u>:AddressBookParser</u>" as AddressBookParser LOGIC_COLOR
object "<u>:Model</u>" as Model MODEL_COLOR
object "<u>:CommandResult</u>" as CommandResult LOGIC_COLOR
object "<u>toAdd:Person</u>" as Person LOGIC_COLOR
object "<u>:ArgumentMultimap</u>" as ArgumentMultimap LOGIC_COLOR
object "<u>:ParserUtil</u>" as ParserUtil LOGIC_COLOR

AddressBookParser --> AddCommandParser : calls
AddressBookParser --> AddCommand
AddCommandParser -> AddCommand
AddCommandParser --> ArgumentMultimap : instantiates
ParserUtil --> ArgumentMultimap : parses
AddCommand --> Person
AddCommand --> Model
AddCommand -right-> CommandResult : outputs
Model -right-> Person : adds
Model --> Person : set client to display as
@enduml
60 changes: 60 additions & 0 deletions docs/diagrams/AddPersonSequenceDiagram.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
@startuml
!include style.puml
skinparam ArrowFontStyle plain

box Logic LOGIC_COLOR_T1
participant ":LogicManager" as LogicManager LOGIC_COLOR
participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
participant "a:AddCommand" as AddCommand LOGIC_COLOR
participant ":CommandResult" as CommandResult LOGIC_COLOR
end box

box Model MODEL_COLOR_T1
participant ":Model" as Model MODEL_COLOR
end box
[-> LogicManager : execute(...)
activate LogicManager

LogicManager -> AddressBookParser : parseCommand(...)
activate AddressBookParser

create AddCommand
AddressBookParser -> AddCommand : AddCommand(...)
activate AddCommand

AddCommand --> AddressBookParser
deactivate AddCommand

AddressBookParser --> LogicManager : a
deactivate AddressBookParser

LogicManager -> AddCommand : execute()
activate AddCommand

AddCommand -> Model : addPerson(toAdd)
activate Model

Model --> AddCommand
deactivate Model

AddCommand -> Model : setDisplayClient(toAdd)
activate Model

Model --> AddCommand
deactivate Model

create CommandResult
AddCommand --> CommandResult
activate CommandResult

CommandResult --> AddCommand
deactivate CommandResult

AddCommand --> LogicManager : result
deactivate AddCommand
AddCommand -[hidden]-> LogicManager : result
destroy AddCommand

[<--LogicManager
deactivate LogicManager
@enduml
29 changes: 29 additions & 0 deletions docs/diagrams/SortPersonsObjectDiagram.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
@startuml
!include style.puml
skinparam objectFontColor white

object "<u>:SortCommand</u>" as SortCommand LOGIC_COLOR
object "<u>:SortCommandParser</u>" as SortCommandParser LOGIC_COLOR
object "<u>:AddressBookParser</u>" as AddressBookParser LOGIC_COLOR
object "<u>:Model</u>" as Model MODEL_COLOR
object "<u>:CommandResult</u>" as CommandResult LOGIC_COLOR
object "<u>sortCriteria:SortCriteria</u>" as SortCriteria LOGIC_COLOR
object "<u>sortOrder:SortOrder</u>" as SortOrder LOGIC_COLOR
object "<u>:Comparator<Person></u>" as Comparator LOGIC_COLOR
object "<u>:ArgumentMultimap</u>" as ArgumentMultimap LOGIC_COLOR
object "<u>:ParserUtil</u>" as ParserUtil LOGIC_COLOR

AddressBookParser --> SortCommandParser : calls
AddressBookParser --> SortCommand
SortCommandParser -> SortCommand
SortCommandParser --> ArgumentMultimap : instantiates
ParserUtil --> ArgumentMultimap : parses
SortCommand --> Model
SortCommand ---> SortCriteria : contains
SortCommand ---> SortOrder : contains
SortCommand --> Comparator : creates
SortCommand -right-> CommandResult : outputs
Comparator --> SortCriteria : uses
Comparator --> SortOrder : uses
Model --> Comparator : updates comparator to sort persons
@enduml
68 changes: 68 additions & 0 deletions docs/diagrams/SortPersonsSequenceDiagram.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
@startuml
!include style.puml
skinparam ArrowFontStyle plain

box Logic LOGIC_COLOR_T1
participant ":LogicManager" as LogicManager LOGIC_COLOR
participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
participant "a:AddCommand" as AddCommand LOGIC_COLOR
participant ":CommandResult" as CommandResult LOGIC_COLOR
end box

box Model MODEL_COLOR_T1
participant ":Model" as Model MODEL_COLOR
participant "<<class>>\nPersonComparator" as PersonComparator MODEL_COLOR
end box

[-> LogicManager : execute(...)
activate LogicManager

LogicManager -> AddressBookParser : parseCommand(...)
activate AddressBookParser

create AddCommand
AddressBookParser -> AddCommand : AddCommand(...)
activate AddCommand

AddCommand --> AddressBookParser
deactivate AddCommand

AddressBookParser --> LogicManager : a
deactivate AddressBookParser

LogicManager -> AddCommand : execute()
activate AddCommand

AddCommand -> PersonComparator : getComparator(sortCriteria, sortOrder)
activate PersonComparator

PersonComparator --> AddCommand : comparator
deactivate PersonComparator

AddCommand -> Model : updateSortPersonComparator(comparator)
activate Model

Model --> AddCommand
deactivate Model

AddCommand -> Model : setDisplayClientAsFirstInSortedFilteredPersonList()
activate Model

Model --> AddCommand
deactivate Model

create CommandResult
AddCommand --> CommandResult
activate CommandResult

CommandResult --> AddCommand
deactivate CommandResult

AddCommand --> LogicManager : result
deactivate AddCommand
AddCommand -[hidden]-> LogicManager : result
destroy AddCommand

[<--LogicManager
deactivate LogicManager
@enduml

0 comments on commit 5cd8d4a

Please sign in to comment.