PROJECT: HealthyBaby


Overview

HealthyBaby (HYBB) is a desktop application targeted towards university students that provides users with a database of quick, easy, and healthy recipes. HYBB helps alleviate the challenges faced while maintaining healthy eating habits, easing the transition from eating out everyday to cooking healthy meals regularly.

The user interacts with HYBB using a Command Line Interface, and it has a Graphical User Interface created with JavaFX.

It is written in Java, and has about 18 kLoC.

Summary of contributions

  • Major enhancement: Added the Planning feature

    • What it does: Allows the user to plan and remove the plans for a recipe on a certain date. The user is also able to obtain all ingredients required for the planned recipes on a simple grocery list.

    • Justification: Assists users in making healthy cooking easier as the user can plan for recipes containing Goals for the nutritional food group that they want to focus on. Users can save money and reduce food wastage by planning for recipes with similar ingredients and purchasing only items that they need using the grocery list command.

    • Highlights: This enhancement is affected by recipes being modified, as the plans of the modified recipe needs to be updated as well. Ensuring that each plan is deleted or updated after each modification was challenging as HYBB supports many recipe customisation methods (9 in total).

  • Minor enhancement: Added Ingredient and Quantity classes to allow HYBB to estimate the portion of each food group in the recipes.

  • Code contributed: RepoSense

  • Other contributions:

    • Project management:

      • Managed releases v1.2.1 - v1.3.1 (3 releases) on GitHub

    • Enhancements to existing features:

      • Did cosmetic tweaks to the GUI: (Pull requests #192, #195)

    • Documentation:

      • Did cosmetic tweaks to existing contents of the User Guide: #14

    • Community:

      • PRs reviewed (with non-trivial review comments): #3, #26, #33

      • Reported bugs and suggestions for other teams in the class (example: 1)

    • Tools:

      • Integrated AppVeyor and CoverAll to the repo (#23)

Contributions to the User Guide

Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users.

HealthyBaby’s User Interface (Beatrice)

Upon opening HYBB, you will see our Graphical User Interface.

AnnotatedUserInterface
Figure 1. HealthyBaby’s User Interface

The Command Box is where you can enter commands to tell HYBB what to do.
The Result Box is where you can see whether the command you have given was successful or unsuccessful.
The Tab Panel can be clicked to switch between tabs.
Alternatively, if you wish to switch between tabs by typing instead of clicking, you can type switch [tab name] into the Command Box instead.
For more information, please refer to [Switch the current tab: switch].
The Display Panel displays the information for the current tab you are on.

Planning Command (Beatrice)

Most of the planning commands take place in the planning tab.
Switch to the planning tab by typing switch planning or by clicking on Planning from the Tab Panel.

You should get the following interface:

PlanTab
Figure 2. Planning Tab

The Display Panel for the planing tab lists all the plans that you have made.

You can the see the details of each plan from the list of plans.

PlanTab Plan
Figure 3. Details of each plan

Plan a recipe: plan (Beatrice)

Plans a recipe that you would like to cook on a certain day in the future.
Format: plan [recipe index] [d/yyyy-mm-dd]

Example 1: plan 1 d/2020-05-27
Plans the recipe at recipe index 1 on 27 May 2020 and adds this plan into the plan list.

Example 2: plan 1 2 3 d/2020-05-27
Plans the recipes at recipe indexes 1, 2 and 3 on 27 May 2020 and adds these three plans into the plan list.

As long as at least one index is specified, you can plan as many recipes as you want in one go. For example, we can plan for five recipes in one command. plan 1 2 3 4 5 d/2020-05-27 will plan for the recipes at recipe indexes 1, 2, 3, 4 and 5 on 27 May 2020.
Valid indexes are integer numbers ranging from 1 to the current plan list size. If one of the indexes given was invalid, the command will not be successful.
Valid dates start from the today’s date and are in the format yyyy-mm-dd. This means that we cannot make a plan on yesterday’s date.

Delete a plan: deletePlan (Beatrice)

Deletes a plan.
Format: deletePlan [plan index]…​

Example 1: deletePlan 3
Deletes the 3rd plan.

Example 2: deletePlan 3 5 8
Deletes the 3rd, 5th and 8th plan.

As long as at least one index is specified, you can delete as many plans as you want in one go. For example, we can delete five plans in one command. deletePlan 1 2 3 4 5 will delete all plans at plan indexes 1, 2, 3, 4 and 5.
Valid indexes are integer numbers ranging from 1 to the current plan list size. If one of the indexes given was invalid, the command will not be successful.
Using the cooked command in [Track cooked meals: cooked (Harshita)] will automatically delete today’s plan for the recipe that is cooked.

Clear all planned recipes: clearPlan (Beatrice)

Clears all the plans you have made.
Format: clearPlan

All plans will be removed.
You can undo this command if it was performed by accident.

Obtain ingredients for planned recipes: groceryList (Beatrice)

Lists the ingredients needed for all recipes that have been planned.
Click on 'Copy' to copy all the ingredients into your clipboard.
Simplify your next grocery shopping experience by pasting this list into your preferred social networking application (like Telegram or Whatsapp) and sending it to yourself for an easy reference from your mobile phone.
Alternatively, you can paste the list into a word document and print it out.

You can print this list out by pasting the text into a word document to Format: groceryList

If no plans have been made, the grocery list will not be generated.

View this week’s planned recipes: viewWeek [Coming in v2.0]

View all the plans for the week.
Format: viewWeek

View this month’s planned recipes: viewMonth [Coming in v2.0]

View all the plans for the month.
Format: viewMonth

Contributions to the Developer Guide

Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project.

Edit command (Beatrice)

The edit feature allows users to edit the properties of a Recipe with ease using the edit command.

This feature is facilitated by the EditCommand class.

The following activity diagram illustrates how the EditCommand is used.

EditActivityDiagram
Figure 4. Activity Diagram for edit command
Implementation

This section explains how the edit command is implemented.

  1. User specified arguments are passed to the EditCommandParser and the arguments are broken up by the ArgumentTokenizer and ArgumentMultimap.

  2. The arguments will then be parsed by ParserUtil and passed into EditRecipeDescriptor. An error will be thrown if the inputs were invalid or if no properties of the Recipe were edited.

  3. A new EditCommand object will be created containing the new properties of the Recipe.

  4. EditCommand#execute() will then get the latest list of recipes from Model and obtain the Recipe that is being edited.

  5. This Recipe is passed into EditCommand#createEditedRecipe() which creates a new Recipe with the edited properties.

  6. Model#setRecipe() will then replace the Recipe being edited with the new Recipe and update the list of recipes and plans.

  7. The success message will be returned to the user by the CommandResult.

The following sequence diagram summarizes the steps taken so far:

EditSequenceDiagram
Figure 5. Edit sequence diagram
The lifeline for EditCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The details of some methods, like the the usage of EditRecipeDecriptor, was omitted to reduce clutter in the diagram.

The edited recipe will be updated in both the list of recipes and plans. The following section explains in detail the implementation behind how each list is updated in the RecipeBook and PlannedBook class.

  1. Continuing off from Step 8, ModelManager#setRecipe() will be called to replace the target Recipe with the edited Recipe. (ModelManager implements Model)

  2. The target and edited Recipe is passed into RecipeBook#setRecipe() and UniqueRecipeList#setRecipe(), which will replace the target with the edited Recipe in the recipe list.

  3. The same arguments are then passed into PlannedBook#setRecipe() which will get a list of all the plans that uses the target Recipe from PlannedRecipeMap.

  4. If there are no plans that uses Recipe, the process stops. However if plans exists, the PlannedBook will iterate through each old plan and update each plan.

Step 4. is an example of how the PlannedRecipeMap can be used to ease the cost of updating each plan.

The following sequence diagram summarizes how the Recipe and all its related Plan are updated when the Recipe is edited.

EditModelSequenceDiagram
Figure 6. Edit sequence diagram focusing on Model
Design Considerations
Aspect: How recipes are edited
  • Alternative 1 (current choice): The EditRecipeDescriptor class is used to make sense of user input and mimics the Recipe class with the same properties.

    • Pros: Multiple fields can be edited in one go.

    • Cons: Might make testing harder since there are many properties in a Recipe and an edit command can take on any combination of each property.

  • Alternative 2: Allow each property in the Recipe to have its own edit command.

    • Pros: Implementation of each command will be simpler.

    • Cons: Editing a recipe will be harder and more troublesome for the user.

We decided to stick with alternative 1, which is the implementation inherited by AB3, as we believe that being able to edit multiple fields in one go provides much more versatility and convenience to the user. Additionally, although there are many properties to test, it is still a finite number and testing can be done with adequate time.

Aspect: Data structure to support plans

Please refer to Aspect: Data structure to support plans for the design considerations for plans.

Plan command (Beatrice)

The plan feature allows users to plan for recipes that they wish to cook at a certain date.
This feature is facilitated by the PlanCommand class.

Implementation

This section explains how the plan command is implemented.

  1. User specified arguments are passed to the PlanCommandParser which uses ArgumentTokenizer and ArgumentMultimap to break up the user input.

  2. The arguments are parsed by ParserUtil and if no invalid inputs were found, a PlanCommand object will be created.

  3. PlanCommand#execute() gets the latest list of recipes from Model.

  4. For every Index, a new Plan object is created and added into the Model. This is done by passing the Plan and the Recipe that is being planned into the UniquePlannedList and PlannedRecipeMap.

  5. The Plan is added to the UniquePlannedList and the Plan is added to the list of plans at the Recipe key in the PlannedRecipeMap.

  6. The success message will be returned to the user by the CommandResult.

The diagram below summarises the steps taken:

PlanningSequenceDiagram
Figure 7. Plan sequence diagram
The lifeline for EditCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.

Design Considerations

Aspect: Data structure to support plans
  • Alternative 1 (current choice): Use a UniquePlannedList with an ObservableList to display the list of plans, and an internal PlannedRecipeMap that maintains the mapping between a Recipe and all plans that were made for the recipe.

    • Pros: The UniquePlannedList provides the list of plans and updates the UI for every change in plan. In the background, the PlannedRecipeMap is maintained and used to ease the cost of iterating through an entire list of plans to search for all the plans that uses a specific Recipe.

    • Cons: Performance might not be optimised as UniqueRecipeList still uses a list.

  • Alternative 2: Maintain the recipes and plans in one ObservableMap instead.

    • Pros: Performance will be better by using a Map than a List.

    • Cons: There are no official javafx classes that supports an sorted ObservableMap or a filtered ObservableMap. We will have to write and maintain our own implementation or import from other libraries.

We decided to use alternative 1, as the cons of alternative 2 are too heavy. The plans need to be sorted in a chronological order, and future implementations of the viewWeek and viewMonth command will require the plans to be filtered as well.
Additionally, we would not have enough time in the scope of this project to write a fully functional implementation, and importing from other libraries introduces the risk of running into bugs if the the dependencies were not maintained in the future.