Fitr Developer Guide
- Fitr Developer Guide
1. Introduction
Fitr is a command line application, helping university students keep track of your food intake and exercises.
This developer guide documents the architecture, software design decisions and implementation of Fitr. This guide is targeted towards current and future developers, who wish to understand and work on this application, as well as designers and software testers.
2. Setting Up
This section explains the prerequisites, and the steps to setting up Fitr on your computer.
2.1 Prerequisites
- You must have JDK 11 or above installed on your computer.
- You must have a GitHub account.
- You must have IntelliJ IDEA IDE installed on your computer.
2.2 Setting up Fitr in your computer
Caution: Follow the steps in the following guide precisely. Things will not work out if you deviate in some steps.
This section provides a step-by-step procedure to set up Fitr in your computer.
- Fork this repository.
- Clone the fork to your computer using Sourcetree or using any other Git GUI.
- Make sure your IDE is configured as JDK 11. If not, follow the steps below:
- Ensure you have the correct JDK version installed in your computer.
- Open IntelliJ (if you are not in the welcome screen, click
File>Close Projectto close the existing project dialog first). - Set up the correct JDK version for Gradle.
- Click
Configure>Project Defaults>Project Structure - Click
New...and set it to the directory of the JDK.
- Click
-
When prompted, import the project as a Gradle project (this can take a few minutes to complete). You can follow the following steps to import the project as a Gradle Project:
Note: Importing a Gradle project is slightly different from importing a normal Java project.- IntelliJ IDEA by default has the Gradle plugin installed. If you have disabled it, click
File>Settings>Pluginsto enable them. - Click
Import Project(orOpen or Importin newer version of IntelliJ). - Locate the
build.gradlefile (not the root folder as you would do in normal importing) and select it. ClickOK. If asked, choose toOpen as Project, notOpen as File. - Click
OKto accept the default settings but do ensure that the selected version ofGradle JVMmatches the JDK 11.
- IntelliJ IDEA by default has the Gradle plugin installed. If you have disabled it, click
2.3 Verifying Setup
- Run Fitr and enter a few commands to ensure that the application functions are as expected. You may refer to the User Guide here or enter
helpto find out what commands are supported in Fitr. - Run the tests to ensure that they all pass, by executing the command
gradlew buildin IntelliJ’s terminal.
3. Design
This section provides an overview of the design of the Fitr application.
3.1 Architecture
This section illustrates the high-level architecture of Fitr, as well as an illustration of the components used in Fitr.

Figure 1: Architecture diagram of Fitr
Figure 1 above explains the high-level design of Fitr. Given below is a quick overview of each component.
The main driver of the application is Fitr is responsible for mainly two phases:
- At app launch: Initialises or loads the respective lists and user profile in the correct sequence and is in charge of connecting the various components with each other.
- At shut down: Shuts down the components and invokes cleanup methods where necessary.
The rest of the App consists of:
-
Ui: The user interface of the application. -
Parser: Handles and parses user commands. -
Command: Handles the various commands Fitr understands. -
User: Contains and handles all information related to user data. -
StorageManager: Reads data from and writes data back into a text file for future use. -
ListManager: Handles all the list operations in Fitr. -
Recommender: Handles the recommendation of the exercises.
Figure 2 below shows how the components work with one another, when a user enters the following command food chicken rice /600 1:

Figure 2: Sequence diagram when adding a food into Fitr
Note: Take note that the lifeline should end at the destroy symbol. Due to a limitation of PlantUML, the lifeline continues after the delete symbol.
In Figure 2 above, the Ui class reads the user’s input, which is then parsed by the Parser class. Once parsed, it creates a new AddFoodCommand class, which is then returned to the Fitr class to be executed. The Food object is created, then added into FoodList. The FoodList is then saved to local storage by the StorageManager class.
3.2 Components
This section expands on the different components seen in the architecture section.
3.2.1 Ui component
The Ui class handles all user inputs and system output.
This component also listens to other components and outputs the desired messages in specified formats.
3.2.2 Parser component
The Parser component takes in the user input from the Ui class and handles the various commands. If the command is invalid, it calls the Ui class to prompt the user until valid commands are entered.
When a valid command is keyed in, the Parser class returns a Command object to execute the command.
3.2.3 Command component
The Command component consists of an abstract Command class and the various different commands that inherit the Command class.
Each type of command class (e.g. addFoodCommand, addExerciseCommand etc) implements an abstract execute() method that carries out the command.
Referring to figure 3, XYZCommand = HelpCommand, RecommendCommand etc.

Figure 3: Command class diagram
3.2.4 User component
The User class contains all information related to the user data (i.e. name, age, height, weight
and gender) and handles all operations on these user data (i.e. getBmi())

Figure 4: User class diagram
Figure 4 above shows the attributes and methods implemented in User class.
The User class has two constructors and implementations differ based on the constructor used.
If a User object is instantiated without parameters (i.e. User user = new User()), the setup method in the
user object will be invoked, allowing users to go through a set of instructions to input their name, age, gender, height, weight and
fitnessLevel.
If a User object is instantiated with defined parameters (i.e. User user = new User(name, age, height, weight
, gender)), the values from the given parameters will be stored within the user class without going through
setup().
On startup, the Fitr class instantiates a Storage object and calls its loadUserProfile() method. This method
returns a User type object and is referenced by a pre-declared User type variable, which is used throughout the
running session.
3.2.5 StorageManager component
Under the StorageManager component, the StorageManager class handles the read and write operations of the various list classes available, such as ExerciseList and FoodList, through classes such as ExerciseStorage and FoodStorage.

Figure 5: StorageManager class diagram
Figure 5 above shows the associations and dependencies present with the StorageManager class.
On startup, the Fitr class creates a new StorageManager object. The StorageManager class will then create the various storage objects required to load that particular file into the program.
This will cause the various storage objects to retrieve the text files from the given file paths and loads the data into the program.
If the files do not exist, the various storage objects will create the files. For example, if the file that contains the user’s exercise data does not exist, the ExerciseStorage object will create a new file to store the user’s exercise data.
Each time there is a change in the FoodList, ExerciseList or User objects, or when the program is exiting, writeExerciseList(), writeFoodList() and writeUserProfile() methods in StorageManager are invoked.
This will save the data onto the respective text files on the hard disk.
3.2.6 ListManager component
Under the ListManager component, the ListManager class handles operations on the exercise, food and goal lists
, such as adding or deleting an item and clearing the lists. Figure 6 below shows the associations and dependencies present with the ListManager class.

Figure 6: ListManager class diagram
On startup, the Fitr class creates a new ListManager object, with StorageManager as its parameter. The ListManager object then creates ExerciseList, FoodList and GoalList objects, and attempt to load the data into the lists through the StorageManager object. If no data is found, then an empty list will be created.
3.2.7 Recommender component
The Recommender component handles the recommendation of the exercises. Based on the user inputs, it either returns a list of type StandardExerciseList full of general or specific workouts. For example, it either recommends a mix of exercises from the 4 different categories of aerobic, upperbody, lowerbody and stretch, or it chooses only workouts from each of the category.
When the Recommend class is instantiated, the constructor calls onto the Storage class to load multiple different StandardExerciseList instances as attributes.
The recommend method in the class then chooses and adds different permutations or combinations of StandardExercise instances from the multiple different StandardExerciseList instances to load into a new instance of StandardExerciseList.

Figure 7: Recommender class diagram
3.2.8 Common classes
Classes used by multiple components are in the fitr.common package.
4. Implementation
This section describes how some of the features in Fitr are implemented.
4.1 Add Exercise and Add Food Command
The AddFoodCommand and AddExerciseCommand are similar in implementation. It simply adds the user input into either the ExerciseList or the Foodlist using the ListManager.

Figure 8: Sequence diagram for AddExerciseCommand
4.2 Edit command
When the user enters an edit command, it first passes through Parser. Once the input is parsed as an edit command, it is then passed to EditCommandParser, where it further parses the user’s input. As the user is able to edit either the individual profile characteristics, food or exercise entries, the EditCommandParser is able parse what the user intends to edit. For example, if the user intends to edit a food entry, the input is then passed to EditEntryCommand, which parses the remaining arguments, and performs the required edit.
Figure 9 below shows the sequence diagram when the user enters edit exercise 25/10/2020 1 push ups /100.

Figure 9: Sequence diagram for edit command
If an edit command is passed to change individual profile characteristics, the EditCommandParser will pass the
input to EditProfileCommand instead. Figure 10 below shows the sequence diagram when the user enters edit name Tom.

Figure 10: Sequence diagram for edit command
4.3 Help command
When the user enters help, the Ui class reads it and passes it through Parser. Once the input is parsed as a help command, the user input is passed to HelpCommand, which calls Ui to print the help message.
Figure 11 below shows the sequence diagram when the user enters help.

Figure 11: Sequence diagram for help command
4.4 View command
The view command allows user to view certain information available in the User class and ListManager class. When
the user enters a view command, the Ui class reads it and passes it through Parser. Once the input is parsed as
a view command, it is then passed to ViewCommand, where it is handled based on the type of view command.
Then the respective view method is called to output the messages via the Ui class.
For example, as illustrated in Figure 12, if you intend to view your goal entry with the command view goal, the input is passed to ViewCommand
, which checks the arguments after ‘view’ and calls the viewGoal() method. It then performs the required steps to
retrieve the goal status for each entry and prints the results using the printCustomMessage() method in the Ui class.

Figure 12: Sequence diagram for view goal command
The sequence diagram in Figure 13 below shows how the ViewCommand class can interact with the User class when the
user keys in view profile.

Figure 13: Sequence diagram for view profile command
4.5 Clear command
The clear command allows the user to clear either the exercise list, food list, or goal list, by specifying in the user’s input as an argument (i.e. clear exercise, clear food, or clear goal). The user is also able to clear all the lists at the same time, if no argument is specified (i.e. clear).
The user’s input is first parsed by the Parser class. It is then passed to the ClearCommand class, which is then executed. The arguments are parsed in the ClearCommand class, and the required list(s) is then cleared. After clearing, it then writes the new empty list(s) to local storage.
Figure 14 below shows the sequence diagram when the user inputs the clear command.

Figure 14: Sequence diagram for clear command
4.6 Delete command
The delete command allows the user to delete an entry from either the exercise list, food list or goal list. The user can only delete one entry each time.
The user’s input is first parsed by the Parser class, which returns a DeleteCommand to Fitr. Then DeleteCommand is executed to delete the entry in the list (i.e. food list, exercise list or goal list) by calling ListManager and update the corresponding local data file by calling StorageManager.
Figure 15 below shows the sequence diagram when the user inputs the delete command.

Figure 15: Sequence diagram for delete command
4.7 Recommend command
The recommend command allows the user to get either a general recommended workout or a workout to a specific body part or type. The commands that can follow recommend are aerobic, upperbody, lowerbody and stretch.
The user’s input is first parsed by the Parser class, which returns a RecommendCommand to Fitr. The RecommendCommand is then executed to recommend workouts. The RecommendCommand calls on the recommend method in Recommender.
The Recommender class then returns a list of type StandardExerciseList. The user input is then read in by the Ui class to determine which StandardExercise objects in the StandardExerciseList should be converted to Exercise and added to the exerciseList of type ExerciseList

Figure 16: Sequence diagram for recommend command
4.8 Tip of the day
Fitr can give an interesting fact or a tip of exercise every time the user opens the app.
When the user opens the program, a TipList is automatically created by Fitr, which loads the tipList from StorageManger and passes it to Fitr. Then Fitr creates a TipManager and passes the tipList to TipManager to generate a random tip. Finally, the tip is passed to Ui and printed in yellow using printMessageInYellow().
Figure 17 below shows the sequence diagram for giving a tip.

Figure 17: Sequence diagram for giving a tip
Appendix A: Product Scope
Target user profile
Our target user profile is university students, at all fitness levels, who values an application that integrates the logging of food, exercises performed, the tracking of calories and goals in one application. It is also aimed at those who prefer typing over mouse interactions and are reasonably comfortable with using command-line applications.
Value proposition
Our application helps users to keep fit without needing them to do extensive research on healthy living or workout options. We will be collecting user information such as age, weight, fitness level, and the application will recommend users preset exercises.
Appendix B: User Stories
Table 1: User stories
| Version | As a … | I want to … | So that I can … |
|---|---|---|---|
| v1.0 | student | enter my food intake | log my calories |
| v1.0 | student | view my past calories intake | track my calories |
| v1.0 | student | store the food I consumed together with its calories in the application | add food that I previously consumed without having to enter the calories again |
| v1.0 | new user | access the help function | I know what to do with the application |
| v1.0 | student | print my past exercise records | see my workout progress |
| v1.0 | student | enter my height and weight | the application can calculate my BMI |
| v1.0 | student | save my past exercise and food records | access my past records at all times |
| v2.0 | student | edit my previous food, exercise and goal entries | fix any mistakes I made previously |
| v2.0 | student | clear my previous food, exercise and goal entries | declutter my exercise and food records |
| v2.0 | student | indicate my fitness level | exercise based on the recommendations of the application |
| v2.0 | student | edit my profile | update my information |
| v2.0 | student | set goals | see if I am on track |
| v2.0 | student | be recommended a set of workout | save time finding exercises to do |
| v2.0 | student | set goals linked to my calories | know my goal status without calculating and comparing my calories |
| v2.0 | student | view my food, exercise and goal entries on a specified date | find my entries easily |
Appendix C: Non-functional Requirements
- This application should work on any mainstream operating system, such as Windows or macOS, as long as Java 11 or above is installed.
- A user with above average typing speed for regular English text should be able to accomplish most of the tasks faster using commands than using the mouse.
Appendix D: Instructions for manual testing
- Initial launch
- Download the latest version of
Fitrfrom here. - Open Command Prompt / Terminal.
- Run the command
java -jar fitr.jar(i.e., run the command in the same folder as the jar file). - If the setup is correct, you should see something like below:
_______ __ __ | ___| |__| | |_ .----. | ___| | | | _| | _| |___| |__| |____| |__| Hello! Welcome to Fitr.
- Download the latest version of
- Clear list feature
- Add a few food entries.
- View food entries, using the command
view food. - Enter the command
clear foodto clear the food list. - View food entries again to check if the list has been cleared (i.e empty).
- If done correctly, you should see something like the following:
The food list is empty...
- Saving your data feature
- Enter a few goal entries.
- View goal entries, using the command
view goal. - Exit the application by entering
bye. - Run Fitr again and view your goal entries with the same
view goalcommand. - If done correctly, you should see the same goals as previously shown.