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.

This portfolio serves to demonstrate my proficiency in the various aspects of software engineering such as coding, project management and technical writing skills in crafting documentation that fits the target user. My role was to design and implement the code for the goals feature and switch feature which will be further elaborated in the following sections. Also included are the details of the relevant documentation I have written in the user and developer guide to assist users and other developers to understand these features.

Summary of contributions

  • Major enhancement: added the goals feature I implemented the commands and functionality related to the goals feature.

    • What it does: Auto generated goals for a recipe every time a recipe’s ingredients are added or edited. Based on these goals, when recipe is marked as cooked, an archive of past cooked meals can be seen as well as a pie chart representing the goals distribution can be seen under the goals tab.

    • Justification: This feature improves the product significantly because a user using a healthy recipe database would want to see their history of cooked meals as well as statistics of their food distribution (represented by the goals distribution).

    • Highlights: This enhancement affects existing add and edit commands and commands to be added in future such as planning. It required an in-depth analysis of design alternatives so as to achieve the most accurate results. The implementation too was challenging as it required changes to existing commands as well as working on all parts of the code such as creating a new json file to store records, working with ui and fxml and listeners with pie charts. A great deal of designing and abstraction was needed where code had to be continually changed and rewritten to be optimised and make proper use of inheritance of ingredients for efficiency in calculating quantity.

  • Minor enhancement: added the ability to switch between tabs I implemented the switch command that allows for switching between tabs. A great deal of planning and understanding of the front-end code was needed in order to integrate the switch command. I designed and abstracted out the front end into 4 main tabs.

  • * Functional code and test code

  • * example code

  • Other contributions:

    • Project management:

      • Managed the issues covered for each milestone. Added each feature as issue and assigned it to teammates.

      • Initiated testing of the product before v1.4 and reported bugs and assigned them to person in charge. bugs

      • Did the major refactoring of code from addressbook to recipebook, adding classes and fields such as goal class, time class and steps class and deleting unecessary fields 22

    • Enhancements to existing features:

      • Updated the GUI color scheme and changed logo of HYBB(Pull requests #69)

      • Created all 4 tabs and guided teammates on how to fill these tabs with their respective data. #118

      • Wrote additional tests for existing features to increase coverage (Pull requests #173, #38)

    • Documentation:

      • Wrote the overview, FAQs and updated command summary, help command, introduction, switch and goals commands

      • wrote NFR, use cases and user stories PR

      • Updated the UI and storage models in Developer’s guide and wrote manual testing.

    • Community:

      • PRs reviewed (with non-trivial review comments): #115, #172, all,

      • Reviewed other team: #89

      • Reported bugs and suggestions for other teams in the class during tutorials and peer testing

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.

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.

Goals feature (Harshita)

The main functionalities and commands associated with the entire goals feature are add, addIngredient, edit, editIngredient, cooked, listGoals and 'removeGoals'. Goals are auto-generated and added to a recipe every time add, addIngredient, edit or editIngredient is executed.

Details of Implementation (Auto-generation of goals)

The following sequence diagram shows how goals are generated through the example of addIngredient command execution

AddSequenceDiagram
Figure 1. Add command sequence diagram
AddRefSequenceDiagram
Figure 2. Reference Frame for Add command sequence diagram

A recipe is initially created with an empty goals set from parser and calculateGoals() is then called in the AddCommand.

Each ingredient type that is associated with a goal (Vegetable, Protein, Fruit, Grain) is listed as an enum type in MainIngredientType. This ensures that invalid goals are not created and simplifies the mapping between MainIngredientType and Goal.

The calculation of goals then occurs through looping through each ingredient type and executing the method call to Recipe#calculateIngredientQuantity(). This would obtain the total quantity for each ingredient, firstly by calling Ingredient#getMainIngredientType() to ensure the validity of ingredients beings calculated (e.g. any instance of 'Other' ingredient would throw an InvalidStateException). Secondly, by obtaining the quantity in grams through the method calls to Ingredient#getQuantity()' and 'Quantity#convertToGram().

After the calculation for each main ingredient type is completed, an instance of MainIngredientTypeMagnitude is created. It acts as a container to store the quantities and conduct the checks for whether these quantities meet the minimum quantity requirement for their respective food group. This calculation and checks are done through the method call to MainIngredientTypeMagnitude#getMainTypes() which would then return a set of MainIngredientType that successfully met the minimum requirement.

Lastly, after looping through this set and creating each goal with the mapping from MainIngredientType to Goal done (e.g. MainIngredientType.FRUIT leads to the creation of goal with goal name generated as "Fruity Fiesta"), the goals will be updated in the particular instance of Recipe r and Model#addRecipe(r) would then update RecipeBook in storage.

The immutability of each object is supported to ensure the correctness of undo and redo functionality.

Details of Implementation (Statistics of cooked recipes)

CookedActivityDiagram
Figure 3. Activity diagram when a cooked command is entered

After CookedCommand#execute(model) is called, the series of checks shown in the above diagram is done to determine if the recipe can be marked as cooked. With multiple recipes inputted (eg cooked 1 2 3, the series of checks will loop through for for each recipe.

The checks ensure that all the recipes inputted are valid, else the CookedCommand throws an exception and terminates. If successful, a new Record containing the Name, current Date and set of Goals associated with the recipe is created and Model#addRecord(record) would then update CookedRecordBook in storage.

Furthermore, if the recipe marked as cooked was included in the Planned Recipes for the day, it will be removed from the planned list.

With reference to the structure of the CookedRecords Model,

ModelRecordClassDiagram
Figure 4. Class diagram of Record

We can see above that once a record is added to the UniqueRecordList two Observable lists will be updated for each addition of Record. Firstly, it is the internalRecordsList that stores unique Record. Secondly, based on this list, an internalGoalsTally that stores GoalCount will be updated each time. This GoalCount consists of one of the four main goal and its respective tally and this observable list is what the pie chart will be listening to for updates and will change each time the internalGoalsTally has been updated as well.

Hence the cooked command is essential in not only archiving data, but also giving the user personalised statistics on their overall goal distribution that resembles the Healthy Eating Plate. The immutability of each object is supported to ensure the correctness of undo and redo functionality as well.

Design Considerations

Aspect: How goals are being tagged
  • Alternative 1 (current choice): System generates tags for each recipe based on food algorithm.

    • Pros: Higher accuracy and makes use of inputs of ingredients class.

    • Cons: Would require several criteria checks that may not be intuitive and would require the use of artificial intelligence for the highest accuracy.

  • Alternative 2 : User chooses from 4 given goals and user adds the tags to the recipes.

    • Pros: Easy to implement. User can filter their preferred goals easily.

    • Cons: Is dependant on user’s understanding and not universal understanding of what may be deemed healthy.

Alternative 1 was chosen as standardising the goals give the recipes more meaning, especially when we are able to calculate statistics and present in in an meaningful and appealing way for users when it models the Healthy eating Plate. Furthermore, custom goals would not have checks would not have been implemented. for users to filter preferred recipes, the command favourite as been implemented.

Aspect: How to determine the criteria for each goal
  • Alternative 1 (current choice): Check by quantity

    • Pros: More accurate and can be modelled against ideal ratio of a healthy meal.

    • Cons: Harder to implement as we need to standardise the ingredient measurements, not as intuitive.

  • Alternative 2 : Check by variety

    • Pros: Easy to implement.

    • Cons: Not as accurate as one grain of rice or 1 grape would still be counted as variety despite the small portion.

Alternative 1 was chosen because of its higher accuracy, although conversion between different measurement may be overestimated. The command deleteGoal was then created in order to enable users to delete goals they deem inaccurate.

Aspect: How the check for goal is done
  • Alternative 1 (current choice): Check every time a recipe is added or edited and store this data

    • Pros: More consistent for the user in keeping track of their goals.

    • Cons: Harder to implement as repetitive checks are needed every time ingredients are added or modified. Will be more expensive to calculate with a larger database.

  • Alternative 2 : Calculate the goals for each recipe every time it is retrieved from storage and set in RecipeList.

    • Pros: Easier to implement as only one check is needed for when the recipes are set.

    • Cons: Goals will reset each time the application is open. If goal has been deleted by user with deleteGoal, it will not be updated the next time the user opens the application as the checks will be the same.

Alternative 1 was chosen as it optimizes the function of deleteGoal`, taking user preference into consideration.

Aspect: How to store data for records
  • Alternative 1 (current choice): Store in a json file called records and calculate goal tally the first time it is set and update accordingly

    • Pros: A custom date can be set and it will be easier to iterate through the list to obtain goal tally.

    • Cons: Duplicate data will be stored and is harder to implement.

  • Alternative 2 : Use recipebook and add boolean attribute isCooked

    • Pros: Easy to implement.

    • Cons: Restricted usage, unable to implement date and do statistical analysis for the user.

  • Alternative 3 : Store goal tally in a new json file.

    • Pros: No need to iterate through recipe list each time and would be less expensive with a larger database.

    • Cons: Only contains four values.

Alternative 1 was chosen as it optimizes the functions and uses of a Record and the scale for a personal data base is smaller, storage would not be an issue. Records need to be iterated through when set initially anyway, hence the association between GoalCount and Record makes the tally process more efficient.