Skip to content

Commit

Permalink
Merge pull request #528 from Ferusel/tingkai/update-dg
Browse files Browse the repository at this point in the history
Update Developer Guide
  • Loading branch information
RichDom2185 authored Nov 7, 2022
2 parents a7cbfae + c70168a commit 4820eaf
Show file tree
Hide file tree
Showing 12 changed files with 352 additions and 24 deletions.
89 changes: 83 additions & 6 deletions docs/_dg/implementations/ItemFeatures.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,106 @@

#### General Implementation Details

<!-- TODO: ADD ITEM CLASS DIAGRAM -->
The Item functionality is represented by an internal `UniqueItemList` stored in FoodRem. An item is represented as an `Item` object, which is stored within this `UniqueItemList`.

Each `Item` can store a number of attributes. The related attributes are:
* `ItemName`: The name of the Item.
* `ItemQuantity`: The number of units of an Item.
* `ItemUnit`: The unit of measurement of an Item.
* `ItemBoughtDate`: The date when the Item was bought.
* `ItemExpiryDate`: The date when the Item expires.
* `ItemPrice`: The cost of one unit of the Item.
* `ItemRemark`: Any attached remarks to the Item.

Regarding the attributes, here are a few things to note:
* All attributes except `ItemName` is optional.
* The Item value is the `ItemPrice` multiplied by the `ItemQuantity`. This is used for the [Statistics](#statistics-features) feature.

The class diagram is as such:

![model_diagram](images/BetterModelClassDiagram.png)

#### General Design Considerations

The design of Items models very closely to the implementation of a `Person` class in the original AddressBook3 (AB3) codebase, of which FoodRem adapted from. However, there are a few modifications made:
* The `Person` class was modified to fit the business logic of FoodRem. For example, renaming it to `Item`, and including different attributes, as mentioned above.
* Addition of new helper and getter methods
* Addition of [Tags](#tag-related-features), where Items stores its own sets of associated `Tag` objects in an internal `Set<Tag>`.

It should be noted that the `UniqueItemList` referenced in `ModelManager` is immutable. To interact with Items, `ObservableList` instances and its child classes, `FilteredList` and `SortedList`, are used in the Commands. For example, (filtering an item by its tag name)[#filtering-items-by-tag-name] would modify the `filteredItems` list (which is a `FilteredList`).

#### Creating an Item
<!-- TODO: Fill up -->

##### Overview
The `new` command creates a new `Item` in FoodRem, which forms the core business logic of being able to represent an inventory item.

The activity diagram is as such:

![ItemSequenceDiagram](images/NewItemActivityDiagram.png)

The sequence diagram to show the interactions between the different components during a `new` command is as such:

![ItemSequenceDiagram](images/NewItemSequenceDiagram.png)

This diagram excludes the instantiation of the objects that represents attributes in an Item, e.g. `ItemQuantity`, `ItemUnit`. This is because including all of them would cause the UML diagram to be cluttered and too small to read.


##### Feature Details
1. The user specifies an item name for the Item to create. Optionally, the user can specify the item quantity, bought date, expiry date, price, and any remarks.
1. If the item name is not provided, or if an invalid command arguments are provided, the user will be prompted to enter the command correctly via an error message.
1. The item is cross-referenced in the `Model` to check if it already exists. If it already does, then an error is raised to inform the user.
1. If the item storage of FoodRem is full, an error is thrown to inform the user that the maximum item limit is reached, and that no new items can be added.
1. If step 4 completes without any exceptions, then the new `Item` is successfully created and stored inside the Item.

##### Feature Considerations
It should be noted that when checking for duplicates in the `UniqueItemList` inside the `Model`, Items cannot have the same name. This is because allowing Items with the same name will introduce additional complexity for other commands, and also presents confusingly to the user. This is room for improvement, as items ideally can have the same name. For example, the user should ideally have multiple `Potato` items with different bought and expiry dates.

When providing multiple arguments with the same delimiter, the last instance of the repeat delimiter is taken during the `parse` command.

#### Editing an Item
<!-- TODO: Fill up -->

##### Overview

The `edit` feature edits the attached attributes of a specified `Item`, which is specified by the one-indexed `itemList` presented to the user.

The activity diagram is as such:

![ItemSequenceDiagram](images/EditItemActivityDiagram.png)

Here is the activity diagram showing the process of the `edit` command:

![ItemSequenceDiagram](images/EditItemSequenceDiagram.png)

This diagram excludes the instantiation of the objects that represents attributes in an Item, e.g. `ItemQuantity`, `ItemUnit`. This is because including all of them would cause the UML diagram to be cluttered and too small to read.

##### Feature Details
1. The user specifies an item index that represents an `Item` to be edited.
1. If a negative or zero index is provided, an error is thrown and the user is prompted to enter the command correctly via an error message.
1. At least one field to be edited has to be provided. Else, the user will be prompted to enter the command correctly via an error message.
1. The item is cross-referenced in the `Model` to check if it already exists. If it already does, then an error is raised to inform the user.
1. Finally, if an index that is not in the valid range of the Item List is provided, an error is thrown and the user is prompted to enter the command correctly via an error message.
1. If step 4 completes without any exceptions, then the new `Item` is successfully edited.

##### Feature Considerations
Similar to the `new` command, it should be noted that when checking for duplicates in the `UniqueItemList` inside the `Model`, Items cannot have the same name. For example, if an `Item` with the name `Potato` already exists inside the inventory, then you cannot edit an existing `Item` to have the name `Potato`.

When providing multiple arguments with the same delimiter, the last instance of the repeat delimiter is taken during the `parse` command.

#### Sorting an Item

##### Overview

<!-- TODO: ACTIVITY DIAGRAM -->

The `sort` feature sorts the list of items currently displayed to the user by specified [[ flag:flag(s) ]]. It is possible to sort by one or more criteria. A list of available criteria for sorting includes:
The `sort` feature sorts the list of items currently displayed to the user by a specified [[ flag ]]. A list of available criteria for sorting includes:

* Name
* Quantity
* Unit
* Bought Date
* Expiry Date
* Price
* Remarks

Currently, sorting is performed ascendingly. A future implementation will allow sorting either ascendingly or descendingly.

Expand All @@ -54,6 +131,6 @@ Currently, sorting is performed ascendingly. A future implementation will allow

##### Feature Considerations

There is a `SortedList` obtained from an immutable item list. When the `SortCommand` is executed to sort the list of items, one or more comparators are chosen depending on the provided sorting criteria. the comparators are combined into one comparator. The `SortedList` are sorted in the specified order of the Comparators. The UI tracks changes to the `SortedList` and displays the updated sorted item list.
There is a `SortedList` obtained from an immutable item list. When the `SortCommand` is executed to sort the list of items, depending on the input, the appropriate comparator is chosen and applied. The UI tracks changes to the `SortedList` and displays the updated sorted item list.

Notably, the `SortedList` wraps around a `FilteredList`, which wraps around an immutable `ObservableList`.
It should be noted that if multiple comparators are provided as arguments, only the last argument is considered when selecting comparators.
23 changes: 18 additions & 5 deletions docs/_dg/implementations/StatisticsFeatures.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
<!-- markdownlint-disable-file first-line-h1 -->

#### General Implementation Details

The statistics command is implemented as a standalone command that ties together the `Item` and `Tag` class. By performing calculations, it returns relevant statistics to the user.

The class diagram is as such:

<!-- TODO: ADD ITEM CLASS DIAGRAM -->

#### General Design Considerations
The `stats` command calculates and provides users a list of statistics relating to FoodRem's inventory. The list of statistics provided is as follows:
* Top three most expensive items
* Total amount of expired food
* Top three most common tags

#### Displaying Statistics

##### Overview
The activity diagram is as such:

<!-- TODO: ACTIVITY DIAGRAM -->
<!-- TODO: Short Description of Command -->

##### Feature Details
The sequence diagram is as such:

<!-- TODO: SEQUENCE DIAGRAM -->
<!-- TODO: Description of how Command works -->

##### Feature Considerations
##### Feature Details
1. The user calls the `stats` command.
2. FoodRem performs the necessary calculations to obtain the statistics. FoodRem then displays the result to the user.
3. If there are fewer than three items, or if there are fewer than three tags, FoodRem displays a placeholder "-".

<!-- TODO: Command Considerations -->

##### Feature Considerations
The three statistics were chosen as a baseline because they are a good starting point for users to help track their food waste. For example, the user can obtain the total amount of wasted food, which is food whose expiry date has already been passed. Future extensions can include additional statistics, or even provide further arguments to selectively display desired statistics. For example, `stats topThreeMostExpensive` would display the statistics for the top three most expensive items only.
24 changes: 24 additions & 0 deletions docs/diagrams/EditItemActivityDiagram.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@startuml
!pragma useVerticalIf on
start
:User enters edit command;
if () then ([else])
:Error: Invalid index provided;
stop
([Positive index provided]) elseif () then ([else])
:Error: Invalid command format;
stop
([at least one field to be edited is provided]) elseif () then ([else])
:Error: Invalid index provided;
stop
([Item index is in valid range of Item List])elseif () then ([else])
:Error: Item already exists in the Item List;
stop
else ([Edited item does not share a name with any other Items])
endif
:edit command successfully executes.
Item is edited.;
stop

@enduml

110 changes: 110 additions & 0 deletions docs/diagrams/EditItemSequenceDiagram.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@

@startuml
!include style.puml

box Logic LOGIC_COLOR_T1
participant ":LogicManager" as LogicManager LOGIC_COLOR
participant ":FoodRemParser" as FoodRemParser LOGIC_COLOR
participant ":EditCommandParser" as EditCommandParser LOGIC_COLOR
participant ":Index" as Index LOGIC_COLOR
participant "editItemDescriptor:EditItemDescriptor" as EditItemDescriptor LOGIC_COLOR
participant ":EditCommand" as EditCommand LOGIC_COLOR
participant "editedItem:Item" as Item LOGIC_COLOR
participant ":ItemWithMessage" as ItemWithMessage 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("edit 1 n/newname")
activate LogicManager

LogicManager -> FoodRemParser : parseCommand("edit 1 n/newname")
activate FoodRemParser

create EditCommandParser
FoodRemParser -> EditCommandParser
activate EditCommandParser

EditCommandParser --> FoodRemParser
deactivate EditCommandParser

FoodRemParser -> EditCommandParser : parse("edit 1 n/newname")
activate EditCommandParser

create Index
EditCommandParser -> Index
activate Index

Index --> EditCommandParser
deactivate Index

create EditItemDescriptor
EditCommandParser -> EditItemDescriptor
activate EditItemDescriptor

EditItemDescriptor -> EditCommandParser
deactivate EditItemDescriptor
'Hidden arrow to position the destroy marker below the end of the activation bar.
EditItemDescriptor -[hidden]-> EditCommandParser
destroy EditItemDescriptor

create EditCommand
EditCommandParser -> EditCommand
activate EditCommand

EditCommand --> EditCommandParser
deactivate EditCommand

EditCommandParser --> FoodRemParser
deactivate EditCommandParser

FoodRemParser --> LogicManager
deactivate FoodRemParser
destroy EditCommandParser

LogicManager -> EditCommand : execute(model)
activate EditCommand

EditCommand -> Model : getCurrentList()
activate Model

Model --> EditCommand
deactivate Model

EditCommand -> EditCommand : createEditedItem(itemToEdit, editItemDescriptor)
activate EditCommand

create Item
EditCommand -> Item
activate Item

Item --> EditCommand
deactivate Item

EditCommand --> EditCommand
deactivate EditCommand

create ItemWithMessage
EditCommand -> ItemWithMessage
activate ItemWithMessage

ItemWithMessage --> EditCommand
deactivate ItemWithMessage

create CommandResult
EditCommand -> CommandResult
activate CommandResult

CommandResult --> EditCommand
deactivate CommandResult

deactivate EditCommand

[<--LogicManager
deactivate LogicManager
@enduml
21 changes: 21 additions & 0 deletions docs/diagrams/NewItemActivityDiagram.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@startuml
!pragma useVerticalIf on
start
:User enters new command;
if () then ([else])
:Error: Invalid command format;
stop
([Item name is provided and arguments are valid]) elseif () then ([else])
:Error: Item already exists;
stop
([Item does not exist in Item List]) elseif () then ([else])
:Error: Insufficient storage space for Items;
stop
else ([Storage space for Items is available])
endif
:new command successfully executes.
Item is edited.;
stop

@enduml

Loading

0 comments on commit 4820eaf

Please sign in to comment.