Overview
My team of 5 computer science students were tasked with changing a basic command line application. Our team decided to morph the application into ExerHealth. ExerHealth is a desktop application used for tracking and scheduling the user’s exercises. The application contains statistical analysis of exercises that users have completed in the past. Additionally, it also acts as a personal trainer by suggesting different exercises which both beginners and advanced users can choose from to incorporate into their exercise regimes. The user interacts with it using a command line interface, and it has a GUI created with JavaFX.
Below is a screenshot of what our desktop application looks like:
Summary of contributions
-
Major enhancement: added the ability to search for suggestions
-
What it does: The command
suggest
allows the user to search for suggestions. -
Justification: This feature gives new users a starting point in their exercise regime. This feature also offers experienced users suggestions based on the type of exercises the user wishes to do.
-
Highlights: This enhancement works well with existing features, such as Custom Properties, and can be expanded upon. It requires an in-depth analysis of design alternatives to ensure that future extensions or further enhancements can be smooth. The implementation was also challenging as it required multiple new predicate and utility classes.
-
-
Minor enhancement 1: Added the display panel on the left hand side of the UI to show the respective information after a command is executed (Pull request #121).
-
Minor enhancement 2: Allowed the command box to be automatically focused on upon opening the application so that user does not need to click on the box to start typing (Pull request #128).
-
Code contributed: RepoSense
-
Other contributions:
-
Project management:
-
Enhancements to existing features:
-
Refactored the GUI (Pull request #121)
-
-
Community:
-
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. |
Suggesting ideas: suggest
Suggests basic exercises
Recommends exercises from ExerHealth’s inbuilt database for beginners.
Format: suggest s/basic
Suggests possible exercises
Suggests exercises matching specified tags.
Based on matching muscle tags
Format: suggest s/possible o/OPERATION_TYPE [m/MUSCLE]… CUSTOM_PROPERTY_PREFIX_NAME/VALUE]…
Based on matching custom properties
Similar to matching muscles tags, you can search for suggestions with matching custom property tags.
After creating custom properties and tracking exercises, you can search for suggestions with those custom properties.
Example: Suppose you have created a new custom property and have been tracking a few exercises with said custom property:
-
custom s/r f/Rating p/Number
-
add t/exercise n/Run d/03/11/2019 c/200 q/10 u/km m/Legs r/8
-
add t/exercise n/Bench Press d/05/11/2019 c/150 q/40 u/kg m/Chest r/8
Then, the following input will display a list of exercises which are tagged with Chest
and have a rating of 8
.
suggest s/possible o/and m/Chest r/8
Thus the command will display only the exercise named "Bench Press".
Expected Result:
Chest
tag and a rating of 8
are shown.The input, suggest s/possible o/or m/Chest r/8
, however, will display a list of exercises tagged with Chest
or have a rating of 8
.
Expected Result:
Chest
tag and exercises with a rating of 8
are shown.As shown above, the two previously added exercises, "Bench Press and "Run", are displayed because they each have a rating of 8
.
In addition to the tracked exercises, ExerHealth also displays suggestions in its database. Hence it will display the exercise named "Push Ups" as it has a Chest
tag.
Duplicates
Sometimes, you may want to track exercises of the same name. Instead of displaying all suggestions of the same name, suggest
displays the information of the most recently tracked exercise of that name.
As can be seen below, there are two exercises named "Bench Press".
Expected Result:
Bench Press
exercise is displayedAs seen from the image above, the information from the "Bench Press" on "06/11/2019" is displayed instead of the one on "05/11/2019" (observe that the calories are different).
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. |
Suggest
Rationale
Beginners now have a plethora of choices, which may overwhelm them when they are deciding on what exercises to do. Thus, we decided to provide users with sample exercise routines to reduce the inertia of starting this lifestyle change. On the other hand, regular gym goers may face a repetitive and mundane exercise routine or may want to experiment with different exercises. As such, to put it briefly, we decided to give users the ability to discover exercises based on the characteristics they are interested in.
This feature presents a cohesive function that all users can benefit from. It also makes our application well-rounded so that users can better achieve their fitness goals.
Overview
The sample exercise routines are currently implemented in ExerHealth’s database as a hard-coded set of exercises.
More importantly, the SuggestPossible
command which caters to more experienced gym goers utilises the exercises that the user
has already done, in addition to ExerHealth’s database. Hence, we allow users to search for suggestions
based on Muscle
and CustomProperty
.
Current Implementation
The SuggestBasic
command displays a list of exercises from our database to the user.
The SuggestPossible
command is created by parsing the user’s inputs to form a Predicate
before filtering ExerHealth’s database and the user’s tracked exercises.
The following activity diagram summarizes what happens when a user enters a SuggestPossible
command:
SuggestPossible
commandIn detail, when a SuggestPossible
command is entered, the Logic
component is responsible for parsing the inputs into a Predicate
.
The Predicate
is then used to instantiate a SuggestPossible
command, and later used to filter a list of Exercise
when the command is executed.
The interactions between the multiple objects can be captured using a sequence diagram.
The following sequence diagram shows the sequence flow when a user enters a valid SuggestPossible
command:
SuggestPossibleCommand
.From the sequence diagram:
-
When the
LogicManager
receives theexecute
command, it calls theparseCommand
method ofExerciseBookParser
. -
ExerciseBookParser
will receivesuggest
as the command type and instantiateSuggestCommandParser
to further parse the command. -
SuggestCommandParser
will receives/possible
as the suggest type and calls theparsePredicate
method ofParserUtil
to parse the user input to create anExercisePredicate
object (namedp
in the diagram). -
SuggestCommandParser
will instantiateSuggestPossibleCommand
with theExercisePredicate
as the constructor parameter. -
The
SuggestPossibleCommand
object is then returned toSuggestCommandParser
, followed byExerciseBookParser
, and lastly back toLogicManager
to execute. -
LogicManager
will proceed toexecute
SuggestPossibleCommand
. -
SuggestPossibleCommand
then calls theupdateSuggestedExerciseList
method inModelManager
, passing in the predicate to filter the list of suggest exercises. -
SuggestPossibleCommand
creates a newCommandResult
to be returned.
In step 3, the process in which the ExercisePredicate
object is created can be explored deeper.
ExercisePredicate
is createdFrom the sequence diagram above:
-
ParserUtil
createsExerciseMusclePredicate
andExerciseCustomPropertyPredicate
with the input parameters. -
Since there were no CustomProperty tags to filter,
ParserUtil
createsExercisePredicate
with only themusclesPredicate
and the booleanisStrict
. -
The resulting
ExercisePredicate
is then returned toParserUtil
, followed bySuggestCommandParser
.
A SuggestPossibleCommand
contains an ExercisePredicate
object.
An ExercisePredicate
object contains a list
of BasePropertyPredicate
,
where each contains either a Collection
of Muscle
or CustomProperty
.
The diagram below shows the structure of a ExercisePredicate
object.
Creating classes such as ExerciseCustomPropertyPredicate
and ExerciseMusclePredicate
allows us to conduct better testing because we can compare the Collection
of Muscle
/CustomProperty
between different predicates.
Design Considerations
Aspect: Implementation of predicate creation
-
Choice 1:
SuggestPossibleCommand
to handle the predicates.-
Pros:
-
Easy to implement and understand. The class
SuggestPossibleCommand
contains the parsing and creation of the predicate all in one place as it stores the tags, and creates the predicate and filters the list of exercises.
-
-
Cons:
-
Violation of Single Responsibility Principle (SRP) as
SuggestPossibleCommand
updates the model and creates the predicate.
-
-
-
Choice 2 (current choice): Predicate class to handle all predicates.
-
Pros:
-
Adheres to SRP and Separation of Concern (SoC).
-
-
Cons:
-
Increases the complexity of the code as more classes are needed, and also increases the lines of code written.
-
-