diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 1d591a3f91d..bf7e93e11a5 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -102,7 +102,7 @@ Given below is the Sequence Diagram for interactions within the `Logic` componen The `Model`, * stores a `UserPref` object that represents the user’s preferences. -* stores the address book data. +* stores the wishful shrinking data. * exposes 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. * does not depend on any of the other three components. @@ -149,6 +149,100 @@ The following sequence diagram shows how the undo operation works: #### Design consideration: * Workflow must be consistent with other adding commands e.g add ingredients, consumption. +### Eat recipe feature + +Eat Recipe feature is used to record the user daily consumption. This feature will work with list consumption +feature to output the total calories' user ate . + +#### Implementation +Substitutability is used in Command and Parser: +* `EatRecipeCommand` extends `Command` +* `EatRecipeCommandParser` implements `Parser` + +Given bellow is the simplified step on how eat recipe is done: + +Step 1: + +User input is change into command. +![EatRecipeStep1](images/EatRecipeStep1.png) + +Step 2: + +Execute the command (make a copy of recipe from recipeList). +![EatRecipeStep2](images/EatRecipeStep2.png) + +Step 3: + +Add the copy recipe into consumptionList. +![EatRecipeStep3](images/EatRecipeStep3.png) + + +The following sequence diagram shows how eat recipe operation works when `execute(eatR 1)` API call: + +![EatRecipeSequenceDiagram](images/EatRecipeSequenceDiagram.png) +
:information_source: +**Note:** The lifeline for `EatRecipeCommandParser` should end at the destroy marker (X) but due to a limitation of +PlantUML, the lifeline reaches the end of diagram. +
+ +1. `LogicManager` receive user input and undergoes logic operation for output. +1. `LogicManager` will pass the input to `WishfulShrinkingParser`. +1. `WishfulShrinkingParser` create `EatRecipeCommandParser` to parse and validate the user input. +1. `EatRecipeCommandParser` create `EatRecipeCommand` with successfully parsed input. +1. `LogicManager` execute `EatRecipeCommand`. +1. `EatRecipeCommand` get the list of recipe. +1. Get related recipe detail using the user input. +1. Pass the recipe to `Model` which responsible in adding it to consumption list. +1. `EatRecipeCommand` return a `CommandResult` back to `LogicManager`. + +
:information_source: +**Note:** Delete a recipe in recipeList would not affect the consumptionList +
+ +#### Design consideration: +##### Aspect 1: Concern while adding a new feature +* Workflow must be consistent with other adding commands e.g. add recipe and ingredient. +##### Aspect 2: What are the informations to extract from a recipe and save in consumptionList +* **Alternative 1 (current choice):** Saves all the informations in recipe. + * Pros: Easy to implement. + * Cons: May have performance issues in terms of memory usage. + +* **Alternative 2:** Saves the recipe's data that going to use while listing consumption. + * Pros: Will use less memory (only the information being used is copied into consumptionList). + * Cons: Not future proof (need to restructure the whole command if wanted to show more information from the recipe) + +### List Consumption feature + +List Consumption feature is used to list out all the recipes that user ate. This feature will also calculate +the total calories. + +#### Implementation +Substitutability is used in Command and Parser: +* `ListConsumptionCommand` extends `Command` + +The following sequence diagram shows how eat recipe operation works when `execute(calories)` API call: + +![ListConsumptionSequenceDiagram](images/ListConsumptionSequenceDiagram.png) + +1. `LogicManager` receive user input and undergoes logic operation for output. +1. `LogicManager` will pass the input to `WishfulShrinkingParser`. +1. `WishfulShrinkingParser` create `ListConsumptionCommandParser` to parse and validate the user input. +1. `LogicManager` execute `ListConsumptionCommand`. +1. `ListConsumptionCommand` get the consumption list. +1. `ListConsumptionCommand` return a `CommandResult` back to `LogicManager`. + +#### Design consideration: +##### Aspect 1: Concern while adding a new feature +* Workflow must be consistent with other adding commands e.g. list recipe and ingredient. +##### Aspect 2: What are the informations to list from a recipe in consumption list +* **Alternative 1 (current choice):** Listing recipe with name and calories. + * Pros: Cleaner UI. + * Cons: Other details that is not used become an extra data in memory. + +* **Alternative 2:** Listing the whole recipe's information. + * Pros: All the data saved are being used. + * Cons: Showing too much unimportant information. + ### \[Proposed\] Data archiving _{Explain here how the data archiving feature will be implemented}_ diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 359e46d58b7..77c04022575 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -27,7 +27,7 @@ Wishful Shrinking is a **desktop app for managing your diet, keeping track of yo * **`recipe`** : Lists all recipes. - * **`addR`**` n/salad i/lettuce, carrots, olive oil` : Adds a `salad` recipe to Wishful Shrinking. + * **`addR`**` n/salad i/lettuce, carrots, olive oil c/40` : Adds a `salad` recipe to Wishful Shrinking. * **`deleteR`**`3` : Deletes the 3rd recipe shown in the current list. @@ -44,7 +44,16 @@ Wishful Shrinking is a **desktop app for managing your diet, keeping track of yo **:information_source: Notes about the command format:**
* Words in `UPPER_CASE` are the parameters to be supplied by the user.
- e.g. in `add n/TITLE`, `TITLE` is a parameter which can be used as `addR n/salad`. + e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `addR n/salad`. + +* Items in square brackets are optional.
+ e.g `n/NAME [t/TAG]` can be used as `n/Salad t/healthy` or as `n/Salad`. + +* Items with `…`​ after them can be used more than 1 times.
+ e.g. `[t/TAG]…​` can be used as `t/healthy`, `t/healthy t/low calories` etc. + +* Parameters can be in any order.
+ e.g. if the command specifies `n/NAME i/INGREDIENTS`, `i/INGREDIENTS n/NAME` is also acceptable. ### Viewing help : `help` @@ -63,25 +72,28 @@ Format: `exit` ## Recipe -### Adding a recipe: `add` +### Adding a recipe: `addR` Adds a recipe to Recipes Collection. -Format: `addR n/TITLE i/INGREDIENTS` +Format: `addR n/TITLE i/INGREDIENT[, MORE INGREDIENT] c/CALORIES img/IMAGE inst/INSTRUCTION... [t/TAG]...` + +* `INGREDIENT` can take in an optional `Quantity` e.g. i/Tomato -2 whole + * there is a compulsory space before `-` Examples: -* `addR n/salad i/lettuce, carrots, olive oil` -* `addR n/sandwiches i/breads, cheese` +* `addR n/salad i/lettuce, tomato, olive oil c/40` +* `addR n/sandwiches i/breads, cheese -2 sclices c/80` -### Listing all recipes : `list` +### Listing all recipes : `recipes` Shows a list of all recipes in the Recipes Collection. -Format: `recipe` +Format: `recipes` -### Deleting a recipe : `delete` +### Deleting a recipe : `deleteR` Deletes the specified recipe from Recipes Collection. @@ -135,14 +147,14 @@ Examples: * `addF i/banana, green peas, salmon fish` -### Listing all ingredients : `list` +### Listing all ingredients : `fridge` Shows a list of all ingredients in the fridge. Format: `fridge` -### Deleting an ingredient : `delete` +### Deleting an ingredient : `deleteF` Deletes the specified ingredient from Fridge. @@ -173,7 +185,7 @@ Examples: ## Consumption -### Eating a recipe : `add` +### Eating a recipe : `eatR` Add the specified recipe to the Consumption Collection from Recipes Collection. @@ -188,6 +200,13 @@ Examples: * `searchR n/salad` followed by `eatR 1` deletes the 1st recipe in the results of the `search` command. +### Listing all recipes eaten : `calories` + +Shows a list of all recipes eat by the user. + +Format: `calories` + + ### Deleting a recipe eaten: `deleteC` Deletes the specified recipe from consumption list. @@ -207,7 +226,7 @@ Examples: Wishful Shrinking data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually. -### Remark `[coming in v1.3]` +### Remark `[coming in v1.4]` _{give a remark to the recipe}_ @@ -228,15 +247,16 @@ _{give a remark to the recipe}_ Features | Format, Examples --------|------------------ -**Add recipe** | `addR n/TITLE i/INGREDIENTS`
e.g., `addR n/salad i/lettuce, carrots, olive oil` +**Add recipe** | `addR n/TITLE i/INGREDIENT[, MORE INGREDIENT] c/CALORIES img/IMAGE inst/INSTRUCTION... [t/TAG]...`
e.g., `addR n/salad i/lettuce, carrots, olive oil c/80` **Add Ingredient to the fridge** | `addF i/INGREDIENTS`
e.g., `addF i/banana, green peas, salmon fish` **Delete recipe** | `deleteR INDEX`
e.g., `deleteR 3` **Delete Ingredient from the fridge** | `deleteF INDEX`
e.g., `deleteF 3` **Delete recipe eaten**| `deleteC INDEX`
e.g., `deleteC 3` -**Search recipe** | `searchR i/INGREDIENT` OR `searchR n/TITLE` OR `searchR t/TAG`
e.g., `searchR i/lettuce` `searchR n/salad` `searchR t/healthy` +**Search recipe** | `searchR i/INGREDIENT` OR `searchR n/TITLE` OR `searchR t/TAG`
e.g. `searchR i/lettuce`, `searchR n/salad`, `searchR t/healthy` **Search Ingredient in the fridge** | `searchF KEYWORD`
e.g., `searchF avocado` -**List recipe** | `recipe` +**List recipe** | `recipeS` **List ingredients in the fridge** | `fridge` +**List recipes eaten** | `calories` **Recommend recipe** | `recommend` **Eat recipe**| `eatR INDEX`
e.g., `eatR 3` **Help** | `help` diff --git a/docs/diagrams/EatRecipeSequenceDiagram.puml b/docs/diagrams/EatRecipeSequenceDiagram.puml new file mode 100644 index 00000000000..15aa4cf64fc --- /dev/null +++ b/docs/diagrams/EatRecipeSequenceDiagram.puml @@ -0,0 +1,92 @@ +@startuml +!include style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":WishfulShrinkingParser" as WishfulShrinkingParser LOGIC_COLOR +participant ":EatRecipeCommandParser" as EatRecipeCommandParser LOGIC_COLOR +participant "command :EatRecipeCommand" as EatRecipeCommand LOGIC_COLOR +participant ":CommandResult" as CommandResult LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":Model" as Model MODEL_COLOR +participant ":WishfulShrinking" as WishfulShrinking MODEL_COLOR +participant ":ConsumptionList" as ConsumptionList MODEL_COLOR +end box + +[-> LogicManager : execute("eatR 1") +activate LogicManager + +LogicManager -> WishfulShrinkingParser : parseCommand("eatR 1") +activate WishfulShrinkingParser + +create EatRecipeCommandParser +WishfulShrinkingParser -> EatRecipeCommandParser +activate EatRecipeCommandParser + +EatRecipeCommandParser --> WishfulShrinkingParser +deactivate EatRecipeCommandParser + +WishfulShrinkingParser -> EatRecipeCommandParser : parse("1") +activate EatRecipeCommandParser + +create EatRecipeCommand +EatRecipeCommandParser -> EatRecipeCommand +activate EatRecipeCommand + +EatRecipeCommand --> EatRecipeCommandParser +deactivate EatRecipeCommand + +EatRecipeCommandParser --> WishfulShrinkingParser : command +deactivate EatRecipeCommandParser +'Hidden arrow to position the destroy marker below the end of the activation bar. +EatRecipeCommandParser -[hidden]-> WishfulShrinkingParser +destroy EatRecipeCommandParser + +WishfulShrinkingParser --> LogicManager : command +deactivate WishfulShrinkingParser + +LogicManager -> EatRecipeCommand : execute() +activate EatRecipeCommand + +EatRecipeCommand -> Model : getFilteredRecipeList() +activate Model + +Model --> EatRecipeCommand : List +deactivate Model + +Model --> EatRecipeCommand +deactivate Model + +EatRecipeCommand -> Model : addConsumption(1) +activate Model + +Model -> WishfulShrinking : addConsumption(1) +activate WishfulShrinking + +WishfulShrinking --> ConsumptionList: eat(1) +activate ConsumptionList + +ConsumptionList --> WishfulShrinking +deactivate ConsumptionList + +WishfulShrinking --> Model +deactivate WishfulShrinking + +Model --> EatRecipeCommand +deactivate Model + +create CommandResult +EatRecipeCommand -> CommandResult +activate CommandResult + +CommandResult --> EatRecipeCommand +deactivate CommandResult + +EatRecipeCommand --> LogicManager : result +deactivate EatRecipeCommand + +[<--LogicManager +deactivate LogicManager +@enduml diff --git a/docs/diagrams/EatRecipeStep1.puml b/docs/diagrams/EatRecipeStep1.puml new file mode 100644 index 00000000000..1dcfe76b7b1 --- /dev/null +++ b/docs/diagrams/EatRecipeStep1.puml @@ -0,0 +1,20 @@ +@startuml +!include style.puml +skinparam ClassFontColor #000000 +skinparam ClassBorderColor #000000 + +title Step 1 + +class userInput +class command + +package CollectionList { + class recipeList + class consumptionList +} + +recipeList -[hidden]right-> consumptionList +userInput -[hidden]up- recipeList +userInput -> command + +@end diff --git a/docs/diagrams/EatRecipeStep2.puml b/docs/diagrams/EatRecipeStep2.puml new file mode 100644 index 00000000000..79799ade276 --- /dev/null +++ b/docs/diagrams/EatRecipeStep2.puml @@ -0,0 +1,22 @@ +@startuml +!include style.puml +skinparam ClassFontColor #000000 +skinparam ClassBorderColor #000000 + +title Step 2 + +class userInput +class command +class recipe + +package CollectionList { + class recipeList + class consumptionList +} + +recipeList -[hidden]right-> consumptionList +userInput -> command +command -[hidden]right> recipe +recipeList -down-> recipe + +@end diff --git a/docs/diagrams/EatRecipeStep3.puml b/docs/diagrams/EatRecipeStep3.puml new file mode 100644 index 00000000000..a51015c79f9 --- /dev/null +++ b/docs/diagrams/EatRecipeStep3.puml @@ -0,0 +1,22 @@ +@startuml +!include style.puml +skinparam ClassFontColor #000000 +skinparam ClassBorderColor #000000 + +title Step 3 + +class userInput +class command +class recipe + +package CollectionList { + class recipeList + class consumptionList +} + +recipeList -[hidden]right-> consumptionList +userInput -> command +command -[hidden]right> recipe +recipe -up-> consumptionList + +@end diff --git a/docs/diagrams/ListConsumptionSequenceDiagram.puml b/docs/diagrams/ListConsumptionSequenceDiagram.puml new file mode 100644 index 00000000000..d52e995a5b3 --- /dev/null +++ b/docs/diagrams/ListConsumptionSequenceDiagram.puml @@ -0,0 +1,52 @@ +@startuml +!include style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":WishfulShrinkingParser" as WishfulShrinkingParser LOGIC_COLOR +participant "command :ListConsumptionCommand" as ListConsumptionCommand 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("calories") +activate LogicManager + +LogicManager -> WishfulShrinkingParser : parseCommand("calories") +activate WishfulShrinkingParser + +create ListConsumptionCommand +WishfulShrinkingParser -> ListConsumptionCommand +activate ListConsumptionCommand + +ListConsumptionCommand --> WishfulShrinkingParser +deactivate ListConsumptionCommand + +WishfulShrinkingParser --> LogicManager : command +deactivate WishfulShrinkingParser + +LogicManager -> ListConsumptionCommand : execute() +activate ListConsumptionCommand + +ListConsumptionCommand -> Model : getFilteredConsumptionList() +activate Model + +Model --> ListConsumptionCommand : ObservableList +deactivate Model + +create CommandResult +ListConsumptionCommand -> CommandResult +activate CommandResult + +CommandResult --> ListConsumptionCommand +deactivate CommandResult + +ListConsumptionCommand --> LogicManager : result +deactivate ListConsumptionCommand + +[<--LogicManager +deactivate LogicManager +@enduml diff --git a/docs/images/EatRecipeSequenceDiagram.png b/docs/images/EatRecipeSequenceDiagram.png new file mode 100644 index 00000000000..645d8089f57 Binary files /dev/null and b/docs/images/EatRecipeSequenceDiagram.png differ diff --git a/docs/images/EatRecipeStep1.png b/docs/images/EatRecipeStep1.png new file mode 100644 index 00000000000..291a203ea08 Binary files /dev/null and b/docs/images/EatRecipeStep1.png differ diff --git a/docs/images/EatRecipeStep2.png b/docs/images/EatRecipeStep2.png new file mode 100644 index 00000000000..aa1efe59a48 Binary files /dev/null and b/docs/images/EatRecipeStep2.png differ diff --git a/docs/images/EatRecipeStep3.png b/docs/images/EatRecipeStep3.png new file mode 100644 index 00000000000..3c745243cf8 Binary files /dev/null and b/docs/images/EatRecipeStep3.png differ diff --git a/docs/images/ListConsumptionSequenceDiagram.png b/docs/images/ListConsumptionSequenceDiagram.png new file mode 100644 index 00000000000..3e9921cf4a0 Binary files /dev/null and b/docs/images/ListConsumptionSequenceDiagram.png differ diff --git a/src/main/java/seedu/address/logic/commands/EatRecipeCommand.java b/src/main/java/seedu/address/logic/commands/EatRecipeCommand.java index 233226b4467..5792df75fff 100644 --- a/src/main/java/seedu/address/logic/commands/EatRecipeCommand.java +++ b/src/main/java/seedu/address/logic/commands/EatRecipeCommand.java @@ -16,7 +16,7 @@ public class EatRecipeCommand extends Command { public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a recipe to the daily consumption. " + "Parameters: INDEX (must be a positive integer)\n" - + "Example: " + COMMAND_WORD + "1"; + + "Example: " + COMMAND_WORD + " 1"; public static final String MESSAGE_EAT_RECIPE_SUCCESS = "Eat %1$s"; @@ -40,6 +40,7 @@ private String extractString(Recipe recipe) { @Override public CommandResult execute(Model model) throws CommandException { requireNonNull(model); + assert(targetIndex.getZeroBased() >= 0); List lastShownList = model.getFilteredRecipeList(); if (targetIndex.getZeroBased() >= lastShownList.size()) { diff --git a/src/main/java/seedu/address/model/commons/Calories.java b/src/main/java/seedu/address/model/commons/Calories.java index 9efb1c3878a..d30f1e3de5a 100644 --- a/src/main/java/seedu/address/model/commons/Calories.java +++ b/src/main/java/seedu/address/model/commons/Calories.java @@ -17,6 +17,7 @@ public class Calories { */ public Calories(Integer calories) { requireNonNull(calories); + assert(calories >= 0); value = calories; }