1. Overview
FitHelper is a desktop diet-and-exercise-recording application made for Users who want to keep fit. It enables users to record their basic profile data, weight records, daily food intake and sports. Rather than just keeping the raw data, FitHelper also provided useful analysis and other customized services, such as calendar view and reminders.
The application is mainly written in Java and built by a considerable 19k Lines of Code. The codebase is well-maintained by reasonable amount of tests. A detailed and comprehensive set of guides are also provided for both application developers and users.
2. Summary of contributions
2.1. Major Enhancement
2.1.1. Build Entry in Model, Storage Part and Its Basic Commands (#143)
-
Content
-
Model Part: Create Entry class (for both food and sport entries) and all of its attributes classes. Modify Model and Model Manager to build a basic skeleton of FitHelper.
-
Storage Part: Create Json-adaptive Entry and Json-adaptive FitHelper main storage. Modify Storage and Storage Manager to enable FitHelper to store both type of entries.
-
Logic Part: Update all command prefix and flags. Create basic commands and corresponding parsers related to Entry, including
add
,edit
,find
,delete
.
-
-
Justification
-
This feature builds the basic skeleton of the whole application in Model and Storage Part.
-
This feature allows other developers to build other features related to Entry, such as Today Page and Calendar Page.
-
2.1.2. Build Profile and Weight in Model, Storage, UI Part and Its Commands
-
Content
-
Model Part: Create Profile class and Weight class and all of their attributes classes. UserProfile and WeightRecords class are built to wrap up user profile and all weight records. They are parallel to the FitHelper class. Modify Model and Model Manager to include the profile system and weight system. (#170, #186, #240)
-
Storage Part: Create Json-adaptive UserProfile main storage and WeightRecords main storage. Establish two separate new databases. (#203, #240, #248)
-
UI Part: Build Profile Page and Weight Page. Profile Page shows a table of user profile data. Weight Page includes a notification indicating the gap to user target weight and two Trend Line Graphs for weight and BMI data. (#186, #203, #242)
-
Logic Part: Enable Profile Page switch and Weight Page switch. Also enable user to update profile’s attributes value and manipulate weight database by corresponding commands and command parsers, including
profile
,update
,weight
,addWeight
,editWeight
,deleteWeight
andclearWeight
. (#203, #214, #240, #311)
-
-
Justification
-
With this feature, all three database for this application are built:
-
FitHelper for entry and diary data (fithelper.json)
-
UserProfile for profile data (userprofile.json)
-
WeightRecords for weight data(weightrecords.json)
-
-
Profile Page and Weight Page are essential to this application, since user’s basic data are used to provide a more customized service, and keeping tracking of user’s weight and providing useful analysis can significantly help the user to keep fit.
-
The profile and weight system are strong linked together, as one command may change both profile and weight database and GUI page.
-
2.2. Code contribution
-
Code contributed: [Functional code]
2.3. Other contributions
-
Project management:
-
Create Milestone
v1.0
-v2.0
, update and close issues regularly on GitHub
-
-
Enhancements to existing features:
-
Updated the GUI color scheme (#214)
-
-
Documentation:
-
Add profile and weight related session to User Guide (#98, #245, #324)
-
Make each session in User Guide aligned in structure, and summarize all prefixes, flags and all command formats (#324)
-
Build Appendix in Developer Guide, including Product Scope, User Stories, Use Cases, NFR, Glossary and Manual Testing (#93, #94, #96, #219)
-
Update Storage part and add weight feature in Developer Guide (#211, #258, #330)
-
-
Community:
3. 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. |
Common Fields and Keywords
-
x/ entry type
-
n/ entry name
-
t/ entry time
-
l/ entry location
-
c/ entry calorie
-
s/ entry status
-
r/ entry remark
-
i/ entry index
-
d/ date in format yyyy-MM-dd
-
m/ mode
-
sh/ date in format of yyyy-MM-dd in calendar
-
dc/ diary content
-
dr/ duration
-
attr/ profile attribute name
-
v/ profile attribute value/ weight value
-
by/ sorting criterion
-
o/ sorting order
-
k/ keywords for searching/checking
-
-f force change flag
Keep User Profile
Profile Page: profile
Profile page serves to be a summary for basic user data.
The profile information includes: Name, Age, Gender, Address, Height, Target Weight, Current Weight and Current BMI.
Format: profile
Update Profile Data : update
Update user data in the profile by attributes. Profile attributes include: Name, Age, Address, Gender, Height and Target Weight.
Every update
command will lead to the profile page.
Format: update [-f] attr/ATTRIBUTE v/VALUE
Examples:
-
update attr/height v/160
-
update -f attr/name v/Alice Wang
Keep Weight Records
Weight Page: weight
Weight page serves to be a summary for user’s weight and BMI changes according to time.
It shows user data in graph for easy understanding. By default, it will generate graph from all history data chronologically.
-
Gap notification
The top notification shows the comparison between user current weight and target weight.-
If current weight is larger than target, the gap between the two will be highlighted.
-
If current weight is the same or less than the target, a succeed notification will be generated.
-
-
Trend Graph - Weight
Display a trend graph of user’s weight according to time. -
Trend Graph - BMI
Display a trend graph of user’s BMI according to time. The BMI value is calculated by weight and height value at that date.
Format: weight
Add Weight Records : addWeight
Add a new weight record into the weight records database. A weight record is related to date and weight value, and a auto-computed BMI value will be stored as well.
Every addWeight
command will lead to the weight page.
If a new weight record is added successfully, two new points will be added into the two trend graphs separately.
Format: addWeight v/WEIGHT_VALUE [d/DATE]
Examples:
-
addWeight v/50.0 d/2020-02-01
-
addWeight v/52.30
Edit Weight Records : editWeight
Edit an existing weight record in the weight records database.
A weight record is identified by its unique date, and user can find the date on the x-axis of the Weight Trend Graph.
User are able to edit the weight value, and corresponding BMI value will be auto-computed using the new weight value and user’s current height.
Every editWeight
command will lead to the weight page.
If a weight record is edited successfully, two new points will change their positions on the two trend graphs separately.
Format: editWeight [d/DATE] v/NEW_WEIGHT_VALUE
Examples:
-
editWeight d/2020-02-01 v/51.0
-
editWeight v/52.40
Delete Weight Records : deleteWeight
Delete an existing weight record in the weight records database.
Same as editWeight
command, a weight record is identified by its unique date, and user can find the date on the x-axis of the Weight Trend Graph.
Every deleteWeight
command will lead to the weight page.
If a weight record is deleted successfully, two corresponding points will be removed from the two trend graphs separately.
Format: deleteWeight [d/DATE]
Examples:
-
deleteWeight d/2020-02-01
-
deleteWeight
Clear Weight Records : clearWeight
Clear all weight records in the weight records database.
Weight Page’s graphs will be empty, and
Profile Page’s Current Weight and Current BMI fields will be Not Available Now
after clear all weight records.
Format: clearWeight
Save the data
fitness log book data are saved in the hard disk automatically after any command that changes the data.
There is no need to save manually.
Command Summary
-
Help - switch to Help Page :
help
-
Entry - switch to DashBoard :
home
-
Entry - add an entry
add x/TYPE n/NAME t/TIME l/LOCATION c/CALORIE …
-
Entry - list all entries or entries of a given date :
list [d/DATE]
-
Entry - view reminders list only :
reminder
-
Entry - edit an entry :
edit x/TYPE i/INDEX [n/NAME] [t/TIME] [l/LOCATION] [c/CALORIE] …
-
Entry - find and list entries by keywords :
find k/KEYWORDS
-
Entry - delete an entry :
delete x/TYPE i/INDEX
-
Entry - sort entry list :
sort [x/TYPE] by/SORT_BY [o/ORDER]
-
Entry - check calorie reference :
check x/TYPE k/KEYWORDS
-
Diary - switch to Diary Page :
diary
-
Diary - add a diary :
addDiary d/DATE dc/CONTENT
-
Diary - edit a diary :
editDiary d/DATE dc/CONTENT
-
Diary - delete a diary :
deleteDiary d/DATE
-
Diary - find a diary :
findDiary [d/DATE] [k/KEYWORDS]
-
Diary - clear all diaries :
clearDiary
-
Clear - clear all entries and diaries :
clear
-
Undo - undo commands related to entries and diaries :
undo
-
Redo - redo commands related to entries and diaries :
redo
-
Calendar - switch to Calendar Page :
calendar
-
Calendar - display from a referenced date :
calendar d/DATE
-
Calendar - change to list mode :
calendar m/ls [d/DATE]
-
Calendar - change to timetable mode :
calendnar m/tb [d/DATE]
-
Calendar - display entries from a particular date :
calendar sh/DATE
-
Today - switch to Today Page :
today
-
Profile - switch to Profile Page:
profile
-
Profile - update profile data:
update [-f] attr/ATTRIBUTE V/VALUE
-
Weight - switch to Weight Page:
weight
-
Weight - add a weight record
addWeight v/VALUE [d/DATE]
-
Weight - edit a weight record
editWeight [d/DATE] v/VALUE
-
Weight - delete a weight record
deleteWeight [d/DATE]
-
Weight - clear all weight records
clearWeight
-
Exit the Program:
exit
orbye
orquit
4. 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. |
Storage component
API : Storage.java
The Storage
component,
-
saves a
UserPrefsStorage
object in json format and can read it back. -
saves a
FitHelperStorage
object in json format (fithelper.json) and can read it back. This database includes all data related to entries and diaries.-
FitHelperStorage
consists of lists ofEntry
andDiary
, and thus these two types of objects can be saved in json format and read back too.
-
-
saves a
UserProfileStorage
object in json format (userprofile.json) and can read it back. This database includes all data related to user profile attributes.-
UserProfileStorage
consists of a list ofProfile
, and objects in type ofProfile
can be saved in json format and read back.
-
-
saves a
WeightRecordsStorage
object in json format (weightrecords.json) and can read it back. This database includes all data related to weight records.-
WeightRecordsStorage
consists of a list ofWeight
, and objects in type ofWeight
can be saved in json format and read back.
-
Add Weight Records
FitHelper allows the user to track with their weight change easily by allowing user to add their current weight and previous weight.
Sample
An example usage scenario and how the addWeight
command behaves at each step is shown below.
Step 1.
-
The user launches the application for the first time.
-
UniqueWeightList
in Model contains no default weights before the user adds any. -
weightrecords.json
in local Storage contains no weight records as well.
Step 2.
-
The user inputs
addWeight
command word, followed byv/WEIGHT_VALUE
and an optionald/DATE
. -
UI
passes the input toLogic
. -
Logic
then uses a fewParser
classes to extract layers of information out as seen from steps 3 to 5.
Step 3.
-
Logic
passes the user input toFitHelperParser
. -
FitHelperParser
identifies that this is aAddWeightCommand
through the command word "addWeight". -
It then creates a
AddWeightCommandParser
to parse the input into aAddWeightCommand
and return back.
Step 4.
-
Logic
gets theAddWeightCommand
and execute it. -
The execution firstly check is the new weight date is after today’s date and if there is already a existing weight in the UniqueList.
-
Both of these two cases will throw corresponding
CommandException
. -
Then the execution add the new
Weight
into model. -
Finally, it returns a
CommandResult
toUI
, containing the response to the user and the displayPage, which equals toWEIGHT
page.
Step 5.
-
UI
displays the response in theCommandResult
. -
In addition, UI will change to display Weight Page after updating Profile Page and Weight Page.
Implementation
Storage
A weight is stored with three attributes in the weightrecords.json
database:
-
date
: the date of the weight record in format ofyyyy-MM-dd
, if no date is provided by the user, the default value is the date of today -
weightValue
: a double value with two decimal places. -
bmi
: the BMI value is also a double value with two decimal places. It is auto-computed and stored, using the formula :BMI = Weight Value(kg) / Height(m)^2
. The Height value gets from user profile inuserprofile.json
database.
Model
-
A single weight is represented as model
Weight
with the attributes ofDate
,WeightValue
, andBmi
. -
In
ModelManager
, all weights are represented byWeightRecords weightRecords
.-
The
WeightRecords
class implementsReadOnlyWeightRecords
interface, and therefore can return an unmodifiable version of a unique list of weights. -
The
WeightRecords
wraps aUniqueWeightList
which allows adding and iterating. Unique here refers to the constraint that no two weight with the same date can exist in the list/database.
-
-
In
ModelManager
, aFilteredList<Weight> filteredWeight
object is used to store and update a filtered version of all weights.-
The FilteredList wraps a
ObservableList
and filters using a providedPredicate
.
-
UI
When user input addWeight
command to UI
, the input is passed to Logic
part as a String
.
After addWeight
command is executed, a CommandResult
with DisplayPage
equals WEIGHT
will be passed back to MainWindow
in UI
part. Then:
-
Firstly, it will call
updateProfilePage()
, since if the newly added weight has the lasted date, Current Weight and Current BMI in uer profile will need to be updated. -
Secondly, it will call
updateWeightPage()
, since if a new weight is added successfully, new points should be added on to Weight Line Chart and BMI Line Chart. The text content of top notification will also be updated if the gap between Current Weight and Target Weight is changed. -
Lastly, it will call
showWeightPage()
. This allows the Main Window auto-switch to Weight Page after eachaddWeight
command by user.
Logic
The Sequence Diagram below shows how the components interact with each other for the mentioned scenario in sample.
Appendix A: Product Scope
Target user profile:
-
has a need to control weight, therefore need to record daily food intake and sports
-
prefer desktop apps over other types
-
can type fast
-
prefers typing over mouse input
-
is reasonably comfortable using CLI apps
Value proposition: achieve fitness control faster than a typical mouse/GUI driven app
Appendix B: Non Functional Requirements
-
Should work on any mainstream OS as long as it has Java
11
or above installed. -
Should be able to hold up to 1000 entries without a noticeable sluggishness in performance for typical usage
-
Should be able to function normally without internet access.
-
A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
-
A user can get response from the system within 5 seconds after command input.
-
A user can be familiar with the system commands and interface within half an hour usage.
{More to be added}
Appendix C: Glossary
Prefix | Meaning | Used in the following Command(s) |
---|---|---|
x/ |
Type of entry |
add, check, delete, edit, find |
i/ |
Index of entry |
edit, delete, edit |
n/ |
Name |
add, edit |
t/ |
Time in format of "date hour minute" |
add, edit |
l/ |
Location |
add, edit |
c/ |
Calorie |
add, edit |
s/ |
Status |
add, edit |
r/ |
Remark |
edit |
d/ |
Date in format of yyyy-MM-dd |
calendar, addWeight |
dr/ |
Duration in format of yyyy-MM-dd yyyy-MM-dd |
add, edit |
dc/ |
Dairy contents |
dairy |
k/ |
Keyword |
check, find |
attr/ |
Attribute in user profile |
update |
v/ |
Attribute Value in user profile |
update, addWeight |
Command | Flag | Meaning |
---|---|---|
Sort |
-a |
Sort in ascending order |
Sort |
-d |
Sort in descending order |
Sort |
-t |
Sort according to time |
Sort |
-c |
Sort according to calorie intake |
Update |
-f |
Force update even with existing value |
Appendix D: Instructions for Manual Testing
Given below are instructions to test the app manually.
These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing. |
Launch and Shutdown
-
Initial launch
-
Download the jar file and copy into an empty folder
-
Double-click the jar file
Expected: Shows the welcome page of FitHelper. On the left hand side, the user can see a list of page name. Users are able to click on the button or using corresponding command to direct to that page. -
The window size is fixed.
-
-
Shutdown
-
Users are able to shutdown the application using CLI with following commands:
-
exit
-
quit
-
bye
-
-
Users can also choose to shutdown the application by clicking on X button on the right top side if the window.
-
User data will be auto-saved if user choose to shutdown the application. Three local data file in json format can be find:
-
fithelper.json
: containg data related to entries and diaries. -
userprofile.json
: containing data related to user profile. -
weightrecords.json
: containing data related to all weight records.
-
-
Adding A New Weight Record
-
Add first weight record while there is no previous weight record in the database.
-
Prerequisites: None. Users are able to use
addWeight
command at any page. -
Test case:
addWeight v/50.0
Expected:-
A new
Weight
is added intoweightrecords
database, withWeightValue
equals 50.0,Date
with default value(today’s date) andBMI
calculated byHeight
. -
The window is automatically directed to weight page. A new point is shown on both Weight Line Graph and BMI Line Graph. The top notification is also updated.
-
In profile page, Current Weight and Current BMI change from "Not Available Now" to the newest value.
-
-
Test case:
addWeight v/49.0 d/2050-01-01
Expected: No new weight record is added since the date is after current date. An error message is shown in the command result box.
-
-
Add new weight record when there is already some previous weight records existing in the database.
-
Prerequisites: None. Users are able to use
addWeight
command at any page. -
Test case:
addWeight v/48.0
Expected: No new weight record is added since there is existing weight record with the same date (by default is today’s date) in the data base. An error message is shown in the command result box. -
Test case :
addWeight v/47.0 d/2020-03-01
Expected:-
A new
Weight
is added intoweightrecords
database, withWeightValue
equals 47.0,Date
with 2020-03-01 andBMI
calculated byHeight
. -
The window is automatically directed to weight page. A new point is shown on both Weight Line Graph and BMI Line Graph, and form a new trend line with previous data points. The top notification is also updated.
-
In profile page, Current Weight and Current BMI remain the same, since the newly added weight record is not the most recent record in the database.
-
-
Sorting entry lists
-
sort and display the entry lists stored in the sample FitHelper
-
Prerequisite: The data stored in FitHelper are the sample data. To restore to sample data, delete all files stored in the data folder and launch the application.
-
Test case:
sort by/time
Expected:-
The application will go to or remain at the dashboard page.
-
Entries in all three lists (Food Entry History, Sports Entry History and Reminders) are sorted by time in the descending order (entry with a later time comes first i.e. at top).
-
-
Test case:
sort x/s by/cal o/a
Expected:-
The application will go to or remain at the dashboard page.
-
Entries in Sports Entry History and Reminders list are sorted by calorie value in the ascending order (entry with a lower calorie value comes first i.e. at top).
-
Entries in Food Entry History list remain unchanged.
-
-
Test case:
sort x/s o/a
Expected:-
The application shows invalid command format error, followed by correct command format and example command in the bottom left corner.
-
-
Checking calorie data
-
search for calorie intake/consumption of common food/sports
-
Prerequisite: None, as long as the application is launched properly.
-
Test case:
check x/s k/swim
Expected:-
The application will go to or remain at the dashboard page.
-
The application shows calorie consumption per hour of common swimming styles in the bottom left corner.
-
-
Test case:
check x/f k/swim
Expected:-
The application will go to or remain at the dashboard page.
-
The application shows no matching results message in the bottom left corner.
-
-
Test case:
check k/swim
Expected:-
The application shows invalid command format error, followed by correct command format and example command in the bottom left corner.
-
-
Saving data
-
Dealing with missing/corrupted data files
-
If the application is launched and shut down at least once, there will be three local database in json format.
-
Delete
fithelper.json
, and launch FitHelper again. All user manipulation on entries and diaries will be cleared.Dashboard
,Today
,Calendar
andDiary
Page will restart with sample data. -
Delete
userprofile.json
, and launch FitHelper again. All user manipulation on user profile will be clear.Profile
page will restart with sample user data. -
Delete
weightrecords.json
, and launch FitHelper again. All user manipulation on weight records will be clear.Profile
page will show Current Weight and Current BMI as "Not Available Now", andWeight
Page will have no data point on the trend line graph.
-