Overview
ZeroToOne is a desktop application that serves as an all-in-one exercise tracker and personal aide. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 26 kLoC.
Summary of contributions
-
Major enhancement: added the Workout Session Feature
-
What it does: Allows the user to start a workout session by providing a
WORKOUT_ID
. The session keeps track of the user’s workout by providing a queue of upcoming sets and the progress of the previous set. The session also includes a rest timer that helps users keep to their workout schedule between sets. -
Justification: This feature is a core feature within the app. It helps users keep to their workouts and ensures that even the most tired user will not forget any exercise during a workout session.
-
Highlights: This feature required major design consideration in order to maintain a bug-free, stateful representation of a workout session, with a user-facing experience that automatically logs completed sessions.
-
-
Major enhancement: added the Rest Timer Feature
-
What it does: Seamlessly integrated with the Workout Session Feature, the timer helps users keep to their workout schedule and times rest between sets.
-
Justification: Helps users manage their workout session and keep to their rest time for an optimal workout.
-
Highlights: This feature requires the use of a thread to update the clock. Major design consideration was required to ensure that the timer was not computationally expensive yet reliable, and that the feature was user-facing and integrated with the session feature seamlessly.
-
-
Code contributed:
-
Overview: Reposense
-
Feature | Component | Functional Code | Test Code |
---|---|---|---|
Session feature |
Commands (Start, Stop, Skip, Done) |
||
Parsers |
|||
Models (Ongoing- prefixed) |
|||
Ui |
NA |
||
FXML |
NA |
||
Timer feature |
Found in ModelManager |
NA |
-
Other contributions:
-
Project management:
-
Organised and managed weekly team meetings including taking minutes on google docs.
-
Facilitated task delegation at the inception of the tP.
-
-
Enhancements to existing features:
-
Documentation:
-
Review Contributions:
-
Community:
-
Reviewed other teams documentation: #29
-
-
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. |
Starting A Workout Session [Gabriel Yeo]
Are you ready to start working out now? To begin a new workout session, simply enter the following command into the command box:
start WORKOUT_ID
Example use:
start 1
The User Interface will automatically switch to the “Home” tab. ZeroToOne will display upcoming sets in your workout, guiding you through set by set in your workout.
NOTE:
* This command assumes that you have already created a workout in the application. If you have not, refer to the section on "Managing your workouts" to create a new workout.
* WORKOUT_ID cannot be null and should be a value of a workout from the workout tab.
Completing a Set [Gabriel Yeo]
Completed your exercise set? To mark the current exercise set as complete and move on to the next set, simply enter this command into the command box:
done
The background color of the completed set will turn green, indicating that the set is successfully completed. ZeroToOne will then progress your workout forward, indicating your next set. Additionally, the timer will reset to 00:00 and begin counting your rest for you.
After however many seconds you wish to rest, you may continue on to your next set.
If you were already on your last set, ZeroToOne will automatically stop the workout session after this command is executed and save your session to the Log
.
Skipping An Exercise Set [Gabriel Yeo]
Unable to complete your current exercise set? No worries, it happens to the best of us. To skip the current exercise set, simply enter this command into the command box:
skip
The background color of the completed set will turn red, indicating that the set is incomplete.
This action is otherwise identical to the done
command.
Stopping A Workout Session [Gabriel Yeo]
Need to stop the workout session prematurely? Simply enter this command into the command box:
stop
ZeroToOne will stop the workout that is currently in progress, and save the session into the Log
. All remaining sets are marked as incomplete. The user interface will automatically return to the main screen. If stopping a workout session is successful, you should see the following in the feedback display with your workout name and time:
Stopped workout session: Push Day at 13 Apr 2020, 3:36:17 PM
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. |
Session (Home) [Gabriel Yeo]
Implementation
The Session feature resides on the Home page and is comprised of Start
, Stop
, Done
, and Skip
commands.
OngoingWorkout
, OngoingSession
, OngoingSet
, and OngoingSetList
are models that are vital components of the feature.
The Session feature also seamlessly incorporates a functional timer. Timer functionality is found embedded in the session related functions in ModelManager
.
The activity diagram below demonstrates the actions of a user with this feature.
Start depicts the start of a valid (non-zero sets remaining) workout session.
Upon depletion of all remaining sets, the OngoingWorkout
automatically stops and produces a CompletedWorkout
which is saved.
The only inputs the user is required to give throughout the session are done
(corresponding to the yes of the conditional branch)
and skip
(no of the conditional branch). Stop
is optional.
This is a conscious design choice as elaborated in the next section.
The operations handling these actions are found in OngoingWorkout
:
-
OngoingWorkout#skip()/OngoingWorkout#done()
— removes and returns the next set and updates queue of remaining sets. -
OngoingWorkout#finish()
— creates and returns an immutableCompletedWorkout
object for saving and logging.
Further operations are exposed in the Model
interface as Model#startSession()
and Model#stopSession()
.
The above class diagram briefly depicts how the session related models (in OngoingWorkout
) interact with surrounding classes.
The OngoingWorkout
class has a dependency on Workout
, which has been abstracted for clarity.
In turn, CompletedWorkout
class has a dependency on OngoingWorkout
.
OngoingWorkout
objects are created at the start of a workout session, and can be thought of as 'converted' to CompletedWorkout
objects at the end of a workout session. Workout
and CompletedWorkout
objects are immutable, hence the design choice for using an intermediary, stateful OngoingWorkout
class.
The inner workings of the feature are briefly expounded below through a simple simulation.
Arms Day
is a Workout
with ID = 2
and consists of 2 sets of one exercise called Bench Press
.
Step 1. The user selects an existing Workout
called Arms Day
with ID = 2
and starts a session with start 2
.
-
Logic
andParser
redirect control toStartCommand#execute()
where an instance ofOngoingWorkout
is created with theArms Day
object. The upcoming set of the next exercise is displayed for the user. -
The timer starts counting. This acts as a visual cue for the user that notifies the start of the workout and is essentially a once-off, superfluous action, since it’s main purpose is to time rest between sets.
Step 2. The user completes the first set and types done
.
-
DoneCommand#execute()
is invoked, which in turn callsModel#done()
to obtain the lastCompletedSet
object to display on the UI, and statefully updates the instance ofOngoingWorkout
. -
The rest timer resets to 00:00 and starts counting.
-
The sequence diagram above demonstrates the interaction between the Logic and Model of ZeroToOne. For brevity, some inner details between
OngoingWorkout#done()
and the return ofcs
are omitted.
Step 3. After resting, the user fails the last and final set of Bench Press
and types skip
.
-
SkipCommand#execute()
is invoked. The process is almost identical to the above execution ofdone
except this time the instance ofCompletedSet
is created withisFinished
set tofalse
. -
Since this is the final set of the session,
OngoingWorkout#hasSetLeft()
returns false, andOngoingWorkout#finish()
is called which creates and returns an immutableCompletedWorkout
object. This object is saved and passed on for use by theLog
feature. -
The workout session is now complete, and the timer and UI is reset.
-
The workout session can be viewed in the
Log
tab.
[Note] In the usual flow, the stop
command is not used, and is reserved only for a premature ending of a
workout session, where all remaining sets are marked as incomplete.
Design Considerations
Aspect: Seamless user-first experience
-
Current Implementation: Minimal commands and typing during an ongoing session. Timer functionality is completely automatic.
-
Pros: Less interruption during actual exercising to enter commands.
-
Cons: More experienced users are not able to have a more customizable workout.
-
Aspect: Beginner-friendly set order
-
Current Implementation: Exercises and sets have fixed ordering based on their creation.
-
Pros: Easier for new user to follow a workout session, less typing required during a workout session. Session has simple and predictable behaviour.
-
Cons: Experienced users are not able to have an ad-hoc, customizable workout without creating a new workout with the specific order they want.
-
Appendix A: Effort [ZeroToOne Team]
Feature | AB3 | ZeroToOne |
---|---|---|
LoC |
~10k |
~26k |
Difficulty |
10 |
15 |
Effort |
10 |
15 |
The idea of an exercise app alone itself is not particularly challenging. However, the ZeroToOne team believes that taking a user-experience-first philosophy toward designing an exercise app requires a conscientious design-approach, one that is a challenge.
This is something that we have endeavoured to achieve in this project.
We think that despite the constraints of the CS2103T project, we have managed to demonstrate this to a larger degree.
AB3 deals primarily in the domain of data storage and retrieval. ZeroToOne has taken this one step further, with the ability to:
-
Statefully update new models during a workout session
-
Apply useful statistics across an entire collection of stored data
-
Extend AB3’s models to be more functional
Furthermore, on top of the ~16k LoC added to the project, the ZeroToOne team has managed to:
-
Maintain > 70% test coverage
-
Apply SOLID design principles
-
Maintain a consistent quality of the codebase through stringent PR reviews and hooks.
The largest challenge we faced as a team was communication. Being fast-moving and driven individuals, taking the initiative sometimes meant being able to make decisions for the team as an individual. This meant that it was vital that we were on the same page with our goals and expectations from the project. Thus, we took more time than usual at the beginning of the project to plan our road-map moving forward, delegating work and defining our expectations clearly.
We hope you have enjoyed this journey and learnt as much as we have! - The ZeroToOne Team