Overview
ExerHealth is a desktop application that is created by me and another 4 Computer Science students. It enables users to track important information about their exercises and also provides other functionality such as the ability to create their own fitness regimes and the ability to provide statistical analysis of their activities. Users can also define their own properties which they wish to track for their exercises.
Below is a screenshot of our application:
Summary of contributions
-
Major enhancement 1: Provided a feature that allows user to define their own custom properties and remove them.
-
What it does: Users can simply add in or remove their own custom properties should they wish to keep track of extra/lesser properties for each exercise.
-
Justification: This feature provides greater flexibility among various users if they wish to include more information which they wish to track. This customisation can help users to tailor suit the app for their personal use.
-
Highlights: This feature complements well with the suggestion feature. By having custom properties, users can now produce exercise suggestions based on the custom properties they had created. Furthermore, the implementation of this feature is quite challenging as there are a few aspects to take note of: the representation of custom properties in each exercise, the tracking of custom properties that have been created and storage of custom properties.
-
-
Minor enhancement 1: Added a
viewcustom
command that allows user to view the custom properties that they have defined. -
Minor enhancement 2: Designed the centre panel UI for exercises. This design helps to display both the default and custom properties of each exercise to the user.
-
Minor enhancement 3: Added a
select
command that allows user to select a specific exercise/regime/schedule/suggestion which they wish to view. -
Code contributed: [Code Contribution]
-
Other contributions:
-
Enhancements to existing features:
-
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. |
Custom properties custom
/ viewcustom
Adding custom properties: custom
Adds in a custom property which you can define for the exercises.
Once a new custom property is created, you can simply use the prefix name which you defined for the
property in the add
and edit
command to include information for the new property.
Format: custom s/PREFIX_NAME f/FULL_NAME p/PARAMETER_TYPE
The following names and prefix names have been used for existing add / edit command parameters and properties and so, cannot be used. |
Names used |
Prefix names used |
Name |
n |
Date |
d |
Calories |
c |
Quantity |
q |
Unit |
u |
Muscle |
m |
- |
t |
- |
i |
Example:
-
custom s/r f/Rating p/Number
Creates a Rating
property for each of your exercises.
Expected Result:
You can now add a new exercise with Rating
!
-
add t/exercise n/Dancing d/07/11/2019 c/400 q/2 u/hours r/5
Expected Result:
Removing custom properties: custom
Removes a custom property which you have previously defined either from a single exercise or from ExerHealth.
In the second case, you will still be able to add back the deleted custom property if you wish to.
Format: custom rm/FULL_NAME [i/INDEX]
Example:
-
custom rm/Rating
Before the execution, the Rating
property will be present in exercises that have it.
After the execution, the Rating
property will be removed from all of the exercises and the app
as illustrated in the next few figures.
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. |
Custom feature
Rationale
A quick conversation with a few of our friends revealed that there are many properties which they intend to keep track for exercises. However, it is unlikely that we can implement all of these properties for the exercises as there may be too much overhead and we can never be certain that we have met all of the users' needs.
Overview
This feature is facilitated by both PropertyBook
and CustomProperty
. Whenever a user
adds a newly defined custom property, a CustomProperty
object will be created which is stored in
PropertyBook
. Its corresponding prefix and full name will be tracked by PropertyBook
to avoid
clashes in their uses.
Current Implementation
CustomProperty
encapsulates a single custom property that the user defines. It contains
information such as name, prefix and parameter type of the custom property. The parameter type is supported by
an enumeration class ParameterType
and is restricted to one of the following 3 types: Number
, Text
, Date
.
PropertyBook
serves as a singleton class that helps to manage all of the custom properties that have been
defined by the user. This class acts as an access point for any information relating to the creation or deletion
of custom properties.
To keep track of the custom properties and its relevant information, the following are used:
-
customProperties
: A set containing all of theCustomProperty
objects that have been created. -
customPrefixes
: A set containing all of thePrefix
objects associated with existing custom properties. -
customFullNames
: A set containing the full names of the existing custom properties. -
defaultPrefixes
: A set containing all of thePrefix
objects associated with default properties and parameter types. -
defaultFullNames
: A set containing all of the full names of default properties.
Custom names and prefixes are separated from its default counterparts to ensure that the default names and prefixes
will always be present when the PropertyBook
is first initialised.
To help facilitate PropertyBook
in its custom properties management, the following main methods are implemented:
-
PropertyBook#isPrefixUsed(Prefix)
: Checks if the given prefix has been used by a default or custom property. -
PropertyBook#isFullNameUsed(String)
: Checks if the given name has been used by a default or custom property. -
PropertyBook#isFullNameUsedByCustomProperty(String)
: Checks if the given name has been used by a custom property -
PropertyBook#addCustomProperty(CustomProperty)
: Adds the new custom property. Each time a custom property is added, the prefix set inCliSyntax
is also updated. -
PropertyBook#removeCustomProperty(CustomProperty)
: Removes a pre-defined custom property. Its associated prefix is also removed from the prefix set inCliSyntax
.
All of the crucial associations mentioned above are summarised in the next class diagram.
PropertyBook
and CustomProperty
Adding Custom Properties
To add a new custom property for the exercises, the user can do it through the command custom s/PREFIX_NAME f/FULL_NAME
p/PARAMETER_TYPE
. Examples include custom s/r f/Rating p/Number
and custom s/ed f/Ending Date p/Date
.
The following sequence diagram will illustrate how the custom operation works when a custom property is successfully added.
For further clarity, one can identify the above diagram with the following sequence of steps:
Step 1: User first defines the custom property they wish to add for the exercises.
Step 2: The custom property will be parsed by the app’s parser and a new CustomProperty
object is created.
Step 3: This CustomProperty
object will be returned together with a newly created CustomAddCommand
object.
Step 4: The execute
method of the CustomAddCommand
method will be called and the CustomProperty
object
will be added to PropertyBook
.
Step 5: Finally, a CommandResult
object will be created and returned.
The above steps illustrate the main success scenario. However, not all additions of a custom property will be successful. The next activity diagram shows the workflow when a new custom property is defined.
Once a custom property is successfully added into PropertyBook
, the user can use the prefix of the custom property in
add
or edit
command.
Removing Custom Properties
Should a user wish to remove a custom property from all of the exercises, he/she can simply make use of the command
custom rm/FULL_NAME
. A custom property that has been removed from the PropertyBook
can be re-added back if the user chooses to.
Alternatively, if the user wishes to remove a custom property just from a single exercise, he/she can choose to enter custom rm/FULL_NAME i/INDEX
instead.
The next sequence diagram illustrates what happens when a custom property is removed from the PropertyBook
. If a custom property
is removed from a single exercise instead, only the selected exercise will be updated.
Design Considerations
Aspect: PropertyBook
design
-
Choice 1 (Current choice): Represent
PropertyBook
as a singleton class that will act as the only access point for the addition and removal of custom properties.-
Pros: Having a singleton helps to provide more utility for methods that rely on the
CustomProperty
objects that have been created. -
Cons: It makes testing much difficult as the results from the previous test cases are carried over. Furthermore, it increases coupling across the code base.
-
-
Choice 2: Represent
PropertyBook
as a usual Java object that can be instantiated many times.-
Pros: This reduces coupling and makes testing easier as a new
PropertyBook
object independent of the other tests can be created for different tests. -
Cons: There could be situations where 2 instances of
PropertyBook
objects are created and the addition of a custom property is done to only one instance and not in the other.
-
After much consideration, Choice 1 was implemented with the following reasons:
-
AddCommandParser
andEditCommandParser
have to gain access to theCustomProperty
in order to ensure that the values entered for the custom properties in the add/edit commands are valid. However, as theExerciseBookParser
in the original code base only takes in aString
as a parameter, there has to be another way of retrieving the custom properties. While we can change theExerciseBookParser
to take in a data structure containingCustomProperty
objects, this does not seem good as its responsibility is just to ensure that a predefined command is entered and is passed to the correct command parser.A slightly better choice in this case is to make the data structure holding theCustomProperty
objects a static variable and parsers that require it can access it directly. -
If the data structure holding the
CustomProperty
object is to be made static, it means that this information is shared among all of thePropertyBook
instances if Choice 2 is implemented. Thus,PropertyBook
is acting like a singleton and so, a singleton class will be appropriate.