First, fork this repo, and clone the fork into your computer.
If you plan to use IntelliJ IDEA (highly recommended):
Import the project as a Gradle project: Follow the guide se-edu/guides IDEA: Importing a Gradle project to import the project into IDEA.
Note: Importing a Gradle project is slightly different from importing a normal Java project.
ByteCeps.java
and try a few commands../gradlew check
and ensure they all pass.This section provides a high-level explanation of the design and implementation of ByteCeps, supported by UML diagrams and short code snippets to illustrate the flow of data and interactions between the components.
Given below is a quick overview of the main components of ByteCeps and how they interact with each other.
Main components of the architecture
ByteCeps is the entrypoint for the application to launch and shut down.
The bulk of ByteCep’s work is done by the following components:
Other notable components:
Activity
and child classesThe Activity
class serves as a parent class to Exercise
, ExerciseLog
, Workout
, WorkoutLog
and Day
classes for the ease of usage of ActivityManager
classes (see below).
Note: The Day
class acts as a container class for Workout
, for use in WeeklyProgramManager
ActivityManager
and child classesThe ActivityManager
and inheritors are responsible for managing an ArrayList
of activities. The basic functions of an ActivityManager
include:
add()
: Adding an activity to the ArrayList
delete()
: Deleting an activity from the ArrayList
retrieve()
: Retrieving an activity from the ArrayList
by namegetListString()
: Getting the string containing all the activities contained in the ActivityManager
.execute()
: Executing all commands related to the ActivityManager
and returning the required user input.ExerciseManager
classExerciseManager
is responsible for tracking and manipulating all exercises added to ByteCeps
by the user.
WorkoutManager
classWorkoutManager
is responsible for tracking and manipulating all workouts created by the user.
WeeklyProgramManager
classWeeklyProgram
is responsible for tracking and manipulating the weekly training program set by the user.
ByteCeps streamlines the management of exercise-related tasks by following a general multi-step pattern. Here’s how these operations are carried out:
Step 1 - Input Processing:
The user’s input is received and processed by ByteCeps, which involves parsing the command through the Parser
class. User input examples include:
exercise /add Pushups
for adding an exercise.exercise /edit Pushups /to Pullups
for editing an exercise name from Pushups to Pullups.exercise /delete Pushups
for deleting the Pushups exercise.exercise /list
for listing all exercises.exercise /search Pushups
for finding all instances of the Pushups exercise.Step 2 - Command Identification:
The Parser
class determines the type of exercise operation and extracts any necessary parameters. For instance, the exercise /add
command will be recognized, and the exercise name Pushups
will be parsed as the parameter.
Step 3 - Command Validation: The input is then validated using ExerciseValidator
class to ensure that the command and parameters provided meet the expected format and criteria for processing.
Step 4 - Command Execution: The appropriate action is taken by the ExerciseManager
class.
ExerciseManager
creates a new Exercise
instance and adds it to the ExerciseManager's activitySet
.ExerciseManager
locates the existing Exercise
, updates its details, and then updates the activitySet
accordingly.ExerciseManager
finds the targeted Exercise
in the activitySet
and removes it.ExerciseManager
retrieves all the exercises from the activitySet
and formats them into a list for display.activitySet
for exercises that match the search criteria provided by the user, and presenting the results.Step 5 - Result Display: After the command is executed, a message indicating the success or failure of the operation is generated and displayed to the user. This feedback is crucial for confirming the effect of the user’s command on the system.
Here is the sequence diagram for the exercise /add pushups
command to illustrate the five-step process:
ByteCeps streamlines the management of exercise-related tasks by following a general multi-step pattern. Here’s how these operations are carried out:
Step 1 - Input Processing:
The user’s input is received and processed by ByteCeps, which involves parsing the command through the Parser
class. User input examples include:
workout /create LegDay
for creating a workout plan.workout /edit LegDay /to CardioBlast
for editing a workout plan name from LegDay to CardioBlast.workout /delete LegDay
for deleting the LegDay workout plan.workout /list
for listing all workout plans.workout /search HighIntensity
for finding all workout plans containing HighIntensity.Step 2 - Command Identification:
The Parser
class determines the type of workout operation and extracts any necessary parameters. For instance, the workout /create
command will be recognized, and the workout plan name LegDay
will be parsed as the parameter.
Step 3 - Command Validation: The input is then validated using WorkoutValidator
class to ensure that the command and parameters provided meet the expected format and criteria for processing.
Step 4 - Command Execution: The appropriate action is taken by the WorkoutManager
class.
WorkoutManager
creates a new Workout
instance and adds it to the WorkoutManager's activitySet
.WorkoutManager
locates the existing Workout
, updates its details, and then updates the activitySet
accordingly.WorkoutManager
finds the targeted Workout
in the activitySet
and removes it.WorkoutManager
retrieves all the workouts from the activitySet
and formats them into a list for display.activitySet
for workouts that match the search criteria provided by the user, and presenting the results.Step 5 - Result Display: After the command is executed, a message indicating the success or failure of the operation is generated and displayed to the user. This feedback is crucial for confirming the effect of the user’s command on the system.
Here is the sequence diagram for the workout /delete LegDay
command to illustrate the five-step process:
The ByteCeps application facilitates workout management, including the assignment and unassignment of exercises to workout plans. The process is outlined in the sequence diagram provided and follows a standard operational pattern as described below:
ByteCeps streamlines the management of exercise-related tasks by following a general multi-step pattern. Here’s how these operations are carried out:
Step 1 - Input Processing:
The user’s input is received and processed by ByteCeps, which involves parsing the command through the Parser
class. User input examples include:
workout /assign Pushups /to LegDay
to assign the exercise Pushups
to the workout plan LegDay
.workout /unassign Pushups /from LegDay
to unassign the exercise Pushups
to the workout plan LegDay
.Step 2 - Command Identification:
The Parser
class determines the type of workout operation and extracts any necessary parameters. For instance, the workout /assign
command will be recognized, workout plan name LegDay
and exercise name Pushups
will be parsed as the parameter.
Step 3 - Command Validation: The input is then validated using WorkoutValidator
class to ensure that the command and parameters provided meet the expected format and criteria for processing.
Step 4 - Command Execution: The appropriate action is taken by the WorkoutManager
class.
WorkoutManager
calls executeAssignAction
which initiates the process to assign an exercise to a workout plan. It communicates with the ExerciseManager
to retrieve the specified Exercise
object. Simultaneously, it retrieves the specified Workout
object to which the exercise will be added. The Workout
object’s addExercise
method is called to include the exercise within the workout plan.WorkoutManager
calls executeUnassignAction
which initiates the process to unassign an exercise to a workout plan. It first retrieves the Workout
object corresponding to LegDay
by calling the retrieve method on the WorkoutManager
. With the Workout
object obtained, it attempts to find and remove the Exercise
object representing Pushups
. If the Exercise
is present in the Workout
, it is removed from the workout’s exercise list.Step 5 - Result Display: After the command is executed, a message indicating the success or failure of the operation is generated and displayed to the user. This feedback is crucial for confirming the effect of the user’s command on the system.
Here is the sequence diagram for the workout /assign Pushups /to LegDay
command to illustrate the five-step process:
The feature to list all exercises within a specific workout plan is crucial for users to review their workout regimen. This section outlines the sequence of operations triggered by the workout /info workoutplan
command, culminating in the display of all associated exercises to the user.
Step 1 - Input Processing:
The user’s input is received and processed by ByteCeps, which involves parsing the command through the Parser
class. The user initiates the process by inputting the command workout /info workoutplan
.
Step 2 - Command Identification:
The Parser
class determines the type of workout operation and extracts any necessary parameters. For instance, the workout /info
command will be recognized, workout plan name workoutplan
will be parsed as the parameter.
Step 3 - Command Validation: The input is then validated using WorkoutValidator
class to ensure that the command and parameters provided meet the expected format and criteria for processing.
Step 4 - Command Execution: The appropriate action is taken by the WorkoutManager
class.
WorkoutManager
proceeds to execute the executeInfoAction
, specifically tailored for fetching details about the workout plan named workoutplan
.WorkoutManager
retrieves the Workout
object corresponding to workoutplan
. The WorkoutManager
then searches its records and returns the Workout
object to the WorkoutManager
.WorkoutManager
then invokes the getExerciseList
method on the retrieved Workout
object to obtain a list of all exercises included in the workout plan.Exercise
in the list, the WorkoutManager
calls the getName
method to retrieve the name of the exercise. These names are compiled into a comprehensive message detailing all exercises within the workout plan.Step 5 - Result Display: After the command is executed, a message indicating the success or failure of the operation is generated and displayed to the user. This feedback is crucial for confirming the effect of the user’s command on the system.
Here is the sequence diagram for the workout /info workoutplan
command to illustrate the five-step process:
ByteCeps streamlines the management of the user’s weekly program by following the same general multi-step pattern as above for workout and exercise management. Namely, the steps consist:
The first 2 steps will be omitted in the sequence diagrams following this overview for brevity purposes, as they are similar to the explanations offered in workout and exercise management.
The following are the possible commands the WeeklyProgramManager
object can run:
program /list
to list out the weekly program.program /assign LegDay /to Monday
for assigning a workout to a specific day.program /log Squats /weight 90 100 110 /reps 12 10 8 /sets 3
for logging a specific exercise done today.program /clear
for clearing the entire weekly workout plan.program /clear Monday
for clearing a specific day’s workout plan.program /today
for viewing today’s workout.The sequence diagram below gives the high-level overview of the command program /log <EXERCISE_NAME> /weight <WEIGHT> /sets <NUMBER_OF_SETS> /reps <NUMBER_OF_REPS> /date <DATE>
being run:
execute()
method of WeeklyProgramManager
calls the executeLogAction()
methodaddWorkoutLog()
function of the WorkoutLogManager
, of which is elaborated below.messageToUser
is returned to the UserInterface
.To dive deeper into how the WorkoutLogsManager
works, we must first understand the several layers that are required to be implemented in order for this feature to work.
The implementation thus is as follows:
Step 1 - Parsing & Validation
executeLogAction()
method is called, it must first extract the various parameters of the command.Step 2 - Adding a Workout Log
addWorkoutLog()
method of WorkoutLogsManager
WorkoutLog
is created and added into the LinkedHashSet
of the WorkoutLogsManager
WorkoutLog
silently failsWorkoutLog
contains a LinkedHashSet
of a variable number of ExerciseLog
.Step 3 - Adding an Exercise Log
addExerciseLog()
method of WorkoutLogsManager
ExerciseLog
with the information, retrieves the WorkoutLog
based on the given date, and finally calls the addExerciseLog
method of the WorkoutLog
instance with the new ExerciseLog
instance.Step 4 - Feedback to User
printMessage()
methodBelow shows the sequence diagram of the process, focusing on the flow after the executeLogAction()
method is called.
Below is the sequence diagram of the command program /assign <workout> /to <day>
being run:
execute()
method of WeeklyProgramManager
calls the executeAssignAction()
method.Workout
object, and assigns it to be contained in the appropriate Day
object.messageToUser
is returned to the UserInterface
.Below is the sequence diagram of the command program /today
being run.
The validation of user input has been omitted for purposes of brevity.
Date
object.Day
object.Workout
contained in the Day
object is retrieved.Workout
, along with Date
and Day
is then converted to the messageToUser:String
, which is returned to execute()
and ByteCeps
for printing.This is the sequence diagram of the command program /clear <day [optional]>
being run.
The validation of user input has been omitted for purposes of brevity.
executeClearAction()
method clears all workouts in the WeeklyProgramManager
object.Day
object is removed from WeeklyProgramManager
object, and a new Day
object with no workout assigned is constructed in its place.To implement a help menu for the user, where they can view the formatting of any command corresponding to any specific BYTE-CEPS functionality, 3 classes work together:
If the user enters the command help
alone, they will be shown the following guidance message for accessing help menus:
[BYTE-CEPS]> To access the help menu for command guidance, please type:
help /COMMAND_TYPE_FLAG
Available command types (type exactly as shown):
exercise
workout
program
To view this message again, enter 'help' alone
How the command help
is processed and executed will be described below. This is to demonstrate how the 3 aforementioned classes interact to show a user the guidance message for accessing help menus:
Step 1 - Input Processing:
The user’s input is received and processed by ByteCeps, which involves parsing the command through the Parser
class. The user initiates the process by inputting the command help
.
Step 2 - Command Identification:
The Parser
class determines the type of help operation and extracts any necessary parameters. In this case, the help
is recognised as the command.
Step 3 - Command Validation: The input is then validated using HelpValidator
class to ensure that the parameters provided meet the expected format and criteria for processing.
Here, validation will fail as help
is not accompanied by any parameters. An exception, with an error message specifying this, is thrown.
Step 4 - Command Execution: The appropriate action is taken by the HelpMenuManager
class.
HelpMenuManager
proceeds to catch this exception, and check the error message is as expected.HelpMenuManager
calls getHelpGuidanceString(), which returns the desired guidance message String.HelpMenuManager
rethrows the exception.Step 5 - Result Display
help
, the user is shown the received error message, informing them of the invalid command format without proceeding further into the sequence.This is a sequence diagram of the command help
provided to visually illustrate the described example above.
If the user enters the command help /COMMAND_TYPE
where COMMAND_TYPE
is one of the 3 possible flags:
exercise
workout
program
They will be shown a numbered list of functionalities associated with the specific flag.
How the command help /program
is processed and executed will be described below. This is to demonstrate how the 3 aforementioned classes interact to show a user a help menu which details the associated functionalities of a flag (for which they can see command formats).
Step 1 - Input Processing:
The user’s input is received and processed by ByteCeps, which involves parsing the command through the Parser
class. The user initiates the process by inputting the command help /program
.
Step 2 - Command Identification:
The Parser
class determines the type of help operation and extracts any necessary parameters. In this case, the help /program
is recognised as the command.
Step 3 - Command Validation: The input is then validated using HelpValidator
class to ensure that the parameters provided meet the expected format and criteria for processing.
If validation fails, an exception is thrown with an accompanying error message. If validation succeeds, command execution proceeds.
Step 4 - Command Execution: The appropriate action is taken by the HelpMenuManager
class.
HelpMenuManager
proceeds to execute the generateAllActions
method, which retrieves the array of program
help menu items, PROGRAM_FLAG_FUNCTIONS
, from the static HelpStrings
class and appends each String into a single String that contains a numbered list. This is then returned.Step 5 - Result Display
program
help menu is presented to the user.This is a sequence diagram of the command help /program
provided to visually illustrate the described example above.
How the command help /exercise 1
is processed and executed will be described below to demonstrate how the 3 aforementioned classes interact to show a user command formats.
Step 1 - Input Processing:
The user’s input is received and processed by ByteCeps, which involves parsing the command through the Parser
class. The user initiates the process by inputting the command help /exercise 1
.
Step 2 - Command Identification:
The Parser
class determines the type of help operation and extracts any necessary arguments. In this case, the help /exercise
is recognised as the command, and 1
is recognised as the parameter.
Step 3 - Command Validation: The input is then validated using HelpValidator
class to ensure that the parameters provided meet the expected format and criteria for processing.
If validation fails, an exception is thrown with an accompanying error message. If validation succeeds, command execution proceeds.
Step 4 - Command Execution: The appropriate action is taken by the HelpMenuManager
class.
HelpMenuManager
proceeds to execute the getFlagFormat
method, which first converts the String parameter 1
to its corresponding Integer index 0
then calls the getExerciseFlagFormats
method for retrieving a single String command format from the exercise
command formats menu.HelpMenuManager
retrieves the specific String command format at the index 0
in the list of exercise
command formats found in the static HelpStrings
class.Step 5 - Result Display
1
/index 0
in the exercise
help menu) is presented to the user.This is a sequence diagram of the command help /exercise 1
provided to visually illustrate the described example above.
Storage
classA Storage
object is responsible for reading from and writing to .json
files, so that user data is saved in between sessions.
data.json
The storage.save()
method is called with the ExerciseManager
, WorkoutManager
, WeeklyProgramManager
and WorkoutLogsManager
objects being passed in as input.
NOTE: plantUML does not allow for termination of lifelines after destroying an object (:FileWriter
), but note that the lifeline should end after the red cross.
JSONObject
, jsonArchive
, is created.ExerciseManager
and WorkoutManager
objects have their list of multiple Activity
classes converted into an Array
, which is then .put()
into jsonArchive
.WeeklyProgramManager
and WorkoutLogsManager
objects have their own exportToJSON
method which is called. The results are again .put()
into jsonArchive
.FileWriter
object is created, which writes jsonArchive
converted to a String
to the appropriate filePath
.Storage
object calls the UserInterface
directly to print the success message.data.json
The storage.load()
method is called with the empty ExerciseManager
, WorkoutManager
, WeeklyProgramManager
and WorkoutLogsManager
objects being passed in as input.
These objects are to be updated in the method.
data.json
file detected, a new File
is created and the empty ExerciseManager
, WorkoutManager
, WeeklyProgramManager
and WorkoutLogsManager
is returned without modification.JSONObject
called jsonArchive
, loaded from data.json
is created.ActivityManager
object is then loaded sequentially using jsonArchive
as input.ActivityManager
classFrom the last sequence diagram, we see that each ActivityManager
class is loaded from jsonArchive
via its own method.
For example, the WorkoutManager
object is loaded from the loadWorkouts()
method. The below sequence diagram shows how loadWorkouts()
is run.
The loading of other ActivityManager
objects is similar in nature.
jsonWorkoutArray
is first retrieved from jsonArchive
.jsonWorkout
in jsonWorkoutArray
is retrieved.Workout
objects contained in WorkoutManager
.jsonExercisesInWorkout
inside each jsonWorkout
is retrieved.jsonExercise
in jsonExercisesInWorkout
is used to assign the correct exercises in ExerciseManager
to each Workout
object.CascadingDeletionProcessor
classThis class is a utility class that is responsible for handling cascading deletions (e.g., when an exercise assigned to an existing workout is deleted from ByteCeps
by the user).
It removes the required Workout
/Exercise
objects from the Workout
/WeeklyProgramManager
silently whenever a delete
command is called.
Its only public method, checkForCascadingDeletions()
, is run after executing a parsed command.
If the command entered by the user starts with exercise /delete
and is executed successfully, the private method removeDeletedExerciseFromWorkouts()
is run:
removeDeletedExerciseFromWorkouts()
iterates through every Workout
in WorkoutManager
.exerciseName
matches that of an exercise in the Workout
, the exercise is deleted from the workout too.If the command entered by the user starts with workout /delete
and is executed successfully, the private method removeDeletedWorkoutsFromProgram()
is run:
Days
in WeeklyProgramManager
is stored as oldWorkoutsInProgram
.removeDeletedWorkoutsFromProgram()
iterates through every Day
in oldWorkoutsInProgram
.Workout
assigned to a particular Day
matches that of the deleted Workout
,
that particular Day
is deleted from newWorkoutsInProgram
.Day
with no Workout
assigned to it is added to newWorkoutsInProgram
in replacement of the deleted Day
.BYTE-CEPS, a CLI-based all-in-one tool for setting and tracking fitness goals. Whether you’re a tech-savvy fitness enthusiast or just starting your fitness journey, BYTE-CEPS offers the simplicity and efficiency of a CLI interface to help you maintain or improve your fitness through self-managed routines.
ByteCeps offers a streamlined and comprehensive platform to manage exercise routines, track workout progress, and design personalized fitness programs with ease and efficiency for fitness enthusiasts and professionals.
With ByteCeps, achieve your fitness objectives efficiently, effectively, and enjoyably, unlocking your full potential for a healthier, fitter lifestyle.
Version | As a … | I want to … | So that I can … |
---|---|---|---|
v1.0 | user | create an exercise entry | begin tracking my exercises |
v1.0 | user | create edit an exercise entry | modify an exercise to suit my needs |
v1.0 | user | delete an exercise entry | remove unwanted exercises that I will not do |
v1.0 | user | add an exercise to a workout plan | customise my workout plan |
v1.0 | user | edit an exercise in a workout plan | modify the workout plan to suit my needs |
v1.0 | user | delete an exercise from workout plan | remove unwanted exercises from a workout plan |
v1.0 | user | list all exercises in a workout plan | see the details of my planned exercises |
v1.0 | user | choose the workout plan for a day | organise and structure my daily workout routine |
v1.0 | user | display my workout for the day | know what exercises I should be doing today |
v1.0 | user | display my workout for the week | have a weekly overview of what I should do |
v2.0 | user | export my workout plan to Json | share with other fitness enthusiasts |
v2.0 | user | import my workout plan to Json | bring my progress across devices |
v2.0 | user | search for exercises | build my workout plan faster |
v2.0 | user | search for workout plans | identify which is the suitable workout for me |
v2.0 | fitness enthusiast | record the amount of weight lifted | track my progress over time |
v2.0 | fitness enthusiast | track the number of sets performed for each exercise session | follow my workout plan effectively |
v2.0 | fitness professional | monitor the repetitions completed for each exercise | evaluate my performance |
v2.0 | fitness professional | log my exercise data for a specific date | accurately track my progress over time |
v2.0 | fitness professional | view a list of dates on which I have logged exercise entries | track my consistency and adherence to my workout routine |
v2.0 | fitness professional | review specific exercise logs for a particular date | analyze my workout details and progress on that specific day |
v2.1 | fitness professional | log multiple sets of an exercise, including different weights and reps for each set | have a comprehensive log of my exercise sessions to monitor variations in my performance and strength training progress |
v2.1 | fitness professional | access and review historical workout data with detailed breakdowns by exercise, set, weight, and repetition | analyze trends in my performance and identify areas for improvement or adjustment in my training regime |
v2.1 | fitness enthusiast | be able to overwrite an incorrect log entry for a workout | ensure my workout history is accurate and reflects what I actually performed |
Note: This section serves to provide a quick start for manual testing on BYTE-CEPS. This list is not exhaustive. Developers are expected to conduct more extensive tests.
java -jar byteceps.jar
.exercise /add pushups
pushups
has been added.exercise /add push-ups!
exercise /add pushups
exercise /add PUSHUPS
exercise /delete pushups
pushup
has been deleted.exercise /delete situps
exercise /delete PUSHUPS
exercise /list
exercise /list
exercise /edit pushups /to Decline pushups
pushups
to Decline pushups
exercise /edit crunches /to Incline crunches
exercise /edit Decline pushups /to Decline-pushups!
exercise /edit Decline pushups /to Decline pushups
exercise /search push
pushups
, including pushups
and Decline pushups
exercise /search pullups
exercise /search Decline pushups
Decline
pushups exercise, ensuring that exact matches are correctly prioritized over partial matches.exercise /search decline pushups
after deleting decline pushups
decline pushups
, confirming that the deletion was processed correctly.workout /create Leg Day
leg day
has been created.exercise /add push-ups!
workout /create Arm-Day
workout /create LEG DAY
workout /delete leg day
leg day
has been deleted.workout /delete back day
workout /delete LEG DAY
workout /list
workout /list
workout /edit leg day /to back day
leg day
to back day
workout /edit chest day /to pull day
chest day
does not exist.workout /edit Full Body Day /to Full Body Day-
workout /edit Full Body Day /to Full Body Day
workout /search day
day
, including leg day
and back day
exercise /search chest
exercise /search leg day
leg day
workout plan, ensuring that exact matches are correctly prioritized over partial matches.workout /search leg day
after deleting leg day
leg day
, confirming that the deletion was processed correctly.workout /assign pushups /to Push Day
pushups
have been assigned to Push Day
.workout /assign squats /to Nonexistent Plan
workout /assign Nonexistent exercise /to Push Day
workout /assign PUSHUPS /to PUSH DAY
pushups
have been assigned to Push Day
as both the workout plan & exercise name are case insensitive.workout /unassign pushups /from Push Day
pushups
have been removed from Push Day
.workout /unassign squats /from Nonexistent Plan
workout /unassign Nonexistent exercise /from Push Day
workout /unassign PUSHUPS /from PUSH DAY
pushups
have been unassigned from Push Day
as both the workout plan & exercise name are case insensitive.workout /info Push Day
Push Day
. If the workout plan is empty, the system should indicate that there are no exercises.workout /info Newbie Plan
(assuming no exercises have been assigned to Newbie Plan
)Newbie Plan
.workout /info PUSH DAY
push day
confirming case insensitivity.program /assign Push Day /to Monday
Push Day
has been assigned to Monday.program /assign Leg Day /to Monday
program /assign Push Day /to Mon
program /assign test /to Mon
test
Push Day
is assigned to Monday
, then execute program /today
Push Day
.program /today
program /list
Rest days
where no workouts are assigned.program /clear Monday
program /clear Sunday
(assuming no workout is assigned to Sunday)program /clear
program /log benchpress /weight 125 /sets 1 /reps 5
(MUST create exercise & workout plan first & have a workout plan assigned for the day you are logging.)program /log benchpress /weight 100 110 120 /sets 3 /reps 5 4 3
program /log nonexistent /weight 100 /sets 1 /reps 10
program /log benchpress /weight 130 120 /sets 2 /reps 8 9 /date 2024-03-25
(There must be a workout assigned to the date first)program /log benchpress /weight 130 120 /sets 2 /reps 8 9 /date 2024-2-31
(There must be a workout assigned to the date first)program /log nonexistent /weight 100 /sets 1 /reps 10
program /log benchpress /weight 130 120 /sets 2 /reps 8 9 /date 2024-03-25
(There must be a workout assigned to the date first)program /log benchpress /weight 130 120 /sets 2 /reps 8 9 /date 2024-2-31
(There must be a workout assigned to the date first)program /log benchpress /weight 100 /sets 3
(missing reps)program /log benchpress /weight -10 /sets 3 /reps 100
program /history
program /history 2024-03-27
help /exercis
help /exercise
help /exercise 3
help /program 100
help /workout abc
help /
/
shelp /exercise 1 /list
help
bye
exit