By: AY1920S2-CS2103T-F11-2
Since: Feb 2020
Licence: MIT
Refer to the guide here.
The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.
💡
|
The .puml files used to create diagrams in this document can be found in the diagrams folder.
Refer to the Using PlantUML guide to learn how to create and edit diagrams.
|
-
At app launch: Initializes the components in the correct sequence, and connects them up with each other.
-
At shut down: Shuts down the components and invokes cleanup method where necessary.
Commons
represents a collection of classes used by multiple other components.
The following class plays an important role at the architecture level:
-
LogsCenter
: Used by many classes to write log messages to the App’s log file.
The rest of the App consists of four components.
Each of the four components
-
Defines its API in an
interface
with the same name as the Component. -
Exposes its functionality using a
{Component Name}Manager
class.
For example, the Logic
component (see the class diagram given below) defines it’s API in the Logic.java
interface and exposes its functionality using the LogicManager.java
class.
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delete 1
.
The sections below give more details of each component.
API : Ui.java
The UI consists of a MainWindow
that is made up of parts e.g.CommandBox
, ResultDisplay
, ClientListPanel
, StatusBarFooter
etc. All these, including the MainWindow
, inherit from the abstract UiPart
class.
The UI
component uses JavaFx UI framework. The layout of these UI parts are defined in matching .fxml
files that are in the src/main/resources/view
folder. For example, the layout of the MainWindow
is specified in MainWindow.fxml
The UI
component,
-
Executes user commands using the
Logic
component. -
Listens for changes to
Model
data so that the UI can be updated with the modified data.
API :
Logic.java
-
Logic
uses theAddressBookParser
class to parse the user command. -
This results in a
Command
object which is executed by theLogicManager
. -
The command execution can affect the
Model
(e.g. adding a client). -
The result of the command execution is encapsulated as a
CommandResult
object which is passed back to theUi
. -
In addition, the
CommandResult
object can also instruct theUi
to perform certain actions, such as displaying help to the user.
Given below is the Sequence Diagram for interactions within the Logic
component for the execute("delete 1")
API call.
ℹ️
|
The lifeline for DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
|
API : Model.java
The Model
,
-
stores a
UserPref
object that represents the user’s preferences. -
stores the Address Book data.
-
exposes an unmodifiable
ObservableList<Client>
that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. -
does not depend on any of the other three components.
API : Storage.java
The Storage
component,
-
can save
UserPref
objects in json format and read it back. -
can save the Address Book data in json format and read it back.
This section describes some noteworthy details on how certain features are implemented.
This feature allows users to save their previously entered commands and to retrieve them using the "up" and "down" arrow keys, similar to what most modern CLIs offer.
This command history mechanism is facilitated by the model CommandHistory
, and the storage code in CommandHistoryStorage
. The behaviour of this feature mimics most modern CLIs, namely:
-
The empty string,
""
, will not be stored in the history -
Commands that are similar to the most recently stored command in the history will not be stored (ie. duplicate commands will not be stored)
-
All other user input, be it valid or invalid commands, will be stored
-
There is a maximum size of the stored history (100 in this case, for performance reasons discussed in the later section)
-
Pressing the "up" arrow key will browse backwards towards the least recently entered commands
-
Pressing the "down" arrow key will browse forwards towards the most recently entered commands
-
The caret position must be at the end of the command when browsing the history
-
Persistent storage of the command history is supported (ie. a user can quit the app and come back to the same history as his previous usage of the app)
Since all entered user inputs should be stored, be it valid or invalid commands, and since detection of the "up" and "down" arrow keys must occur in the CommandBox
class found in the UI, we have decided to let CommandBox
directly interact with CommandHistory
. In other words, CommandBox
will call CommandHistory#add
, CommandHistory#getNextCommand
, and CommandHistory#getPrevCommand
. A simplified class diagram of the classes involved in this feature is given below:
In designing this feature, we had to decide on the underlying data structure to store the command history. Currently, each line of command is stored in an ArrayList<String>
. The alternative is to store the commands in a LinkedList<String>
.
Data Structure | Pros and Cons |
---|---|
Array list |
Pros: Much easier to manipulate using indices Cons: Slower performance when list has the maximum number of commands stored and has to shift all indices back by 1 when removing the oldest command |
Linked list |
Pros: Fast removal of the oldest command Cons: Harder to implement as pointers have to be manipulated |
In the interest of saving developement time and better code readability, we decided to use an array list to store the commands. Since we have capped the maximum size of history to be 100, we found out through testing that this causes no observable nor significant lag when the list reaches the maximum capacity and has to reassign all 100 indices.
Moreover, the implementation of CommandHistoryStorage#saveCommandHistory
will rewrite the whole data file in storage (as opposed to appending the file with the newly entered command). This decision was made to protect the integrity of the storage file, making sure that it always has the exact same data as what is stored in the CommandHistory
model. As such, this rewriting of the file during maximum capacity of the history will be the bigger bottleneck in term of performance, as opposed to the reassignment of indices.
As such, the choice of 100 as the maximum size of the command history is thus chosen. This number must be small enough to not cause the app to lag when the whole history is being written to storage, as well as be big enough to satisfy the user. Ultimately, we felt that 100 is a very generous estimate given that a user really only needs the past few commands at any point of time.
We are using java.util.logging
package for logging. The LogsCenter
class is used to manage the logging levels and logging destinations.
-
The logging level can be controlled using the
logLevel
setting in the configuration file (See Section 3.3, “Configuration”) -
The
Logger
for a class can be obtained usingLogsCenter.getLogger(Class)
which will log messages according to the specified logging level -
Currently log messages are output through:
Console
and to a.log
file.
Logging Levels
-
SEVERE
: Critical problem detected which may possibly cause the termination of the application -
WARNING
: Can continue, but with caution -
INFO
: Information showing the noteworthy actions by the App -
FINE
: Details that is not usually noteworthy but may be useful in debugging e.g. print the actual list instead of just its size
Refer to the guide here.
Refer to the guide here.
Refer to the guide here.
Target user profile:
-
has a need to manage a significant number of gym clients and their information (clients' details and exercises)
-
prefer desktop apps over other types
-
can type fast
-
prefers typing over mouse input
-
is reasonably comfortable using CLI apps
-
wants to book facilities easily [v2.0]
Value proposition: Keep track of your gym training schedule and clients' exercises faster than a typical mouse/GUI driven app
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
|
coach for fitness competitors |
record the cliental bests of my clients |
monitor their progress |
|
coach for fitness competitors |
record the exercise type and intensity my clients have done for the day |
know if they are on track for their competitions |
|
coach for fitness competitors |
record the date and time of my clients’ training sessions and keep track of which day they work out |
|
|
coach with many fitness competitors |
view my overall schedule for the day/week |
|
|
coach that communicates with my clients |
display visualisations(graphs/charts) |
convey the client’s training progress better |
|
coach |
add new profiles to the app to keep track of new clients |
|
|
coach |
list all my clients |
|
|
coach |
edit a client’s details |
change and update an existing client’s details |
|
coach |
delete my client |
|
|
coach |
search my client by typing their name |
find my client’s information easily |
|
coach |
add, edit and delete new exercises that are not found in the application |
|
|
coach |
look for user help |
get help on how to use the features |
|
coach with many clients |
be reminded of my daily schedule at the start of the day |
track my appointments |
|
forgetful coach with many clients |
look at my records on clients |
know what exercises they are weak in or require more assistance |
|
coach with a tight schedule |
display my open slots |
plan for training more effectively |
|
coach with many clients |
set clientalised goals for my clients |
plan a workout routine that is achievable |
|
coach with many different clients |
easily export the data of a client (to a CSV file) |
backup and store that data in another format |
|
coach |
track my clients by using a tag |
easily view the clients I want to |
|
coach with clients all over SG |
find the nearest gym based on where my client stays |
|
|
coach with a tight schedule |
view a summary page to present to me just the important data, configurable by me |
|
|
coach |
track my total earnings from all my clients |
|
|
coach that likes to vary my clients’ training |
choose from a list of different exercises with the same purposes |
|
|
coach for fitness competitors |
view incoming competitions of my clients |
be reminded to focus on them more |
|
coach who wants to visually track the progress of my clients |
store photos to monitor the changes in my client’s physique |
|
|
coach |
check if the gym I am going to is closed |
|
|
coach |
use the timer in the application |
seamlessly execute the time interval of the workout planned |
|
coach |
book the facilities required by the workout |
|
|
coach |
see upcoming competitions or meet |
plan for my clients to attend them |
|
coach for fitness competitors |
record the food intake of my clients |
know if they are following my diet plan for them |
|
coach |
monitor my clients caloric intake |
know he is meeting his dietary requirements |
|
coach |
manage the payment fee/payment day of the clients |
charge them accordingly |
{More to be added}
(For all use cases below, the System is the FitBiz
and the Actor is the user
, unless specified otherwise)
MSS
-
User requests to add a client
-
FitBiz adds the client
Use case ends.
Extensions
-
2a. The input format is invalid.
-
2a1. FitBiz shows an error message
Use case resumes at step 1.
-
MSS
-
User requests to view all the available information of client
-
FitBiz shows a list of clients
-
User requests to view a specific client in the list
-
FitBiz shows all available information of the client
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
-
3a. The given name is invalid.
-
3a1. FitBiz shows an error message.
Use case resumes at step 2.
-
MSS
-
User requests to edit a client’s cliental details
-
FitBiz shows a list of clients
-
User requests to edit a specific client in the list and inputs the attributes and values
-
FitBiz edits client’s details
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
-
3a. The input format is invalid.
-
3a1. FitBiz shows an error message.
Use case resumes at step 2.
-
MSS
-
User requests to delete a client
-
FitBiz shows a list of clients
-
User requests to delete a specific client in the list
-
FitBiz deletes the client
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
-
3a. The given format is invalid.
-
3a1. FitBiz shows an error message.
Use case resumes at step 2.
-
MSS
-
User requests to list all existing clients
-
FitBiz lists all existing clients
Use case ends.
Extensions
-
2a. The input format is invalid.
-
2a1. FitBiz shows an error message.
Use case resumes at step 1.
-
MSS
-
User requests to add an exercise to a client
-
FitBiz shows a list of clients
-
User requests to add exercise to a specific client in the list
-
FitBiz add exercise to the client
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
-
3a. The given name is invalid.
-
3a1. FitBiz shows an error message.
Use case resumes at step 2.
-
MSS
-
User requests to start a timer
-
FitBiz starts a timer for the specified duration
Use case ends.
Extensions
-
2a. The input format is invalid.
-
2a1. FitBiz shows an error message.
Use case resumes at step 1.
-
MSS
-
User requests to filter clients based on an attribute
-
FitBiz filters clients based on specified attribute
Use case ends.
Extensions
-
2a. The input format is invalid.
-
2a1. FitBiz shows an error message.
Use case resumes at step 1.
-
MSS
-
User requests to view a client’s cliental best
-
FitBiz lists all clients
-
User requests to view the cliental best of a specific client on the list
-
FitBiz displays the cliental best
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
-
3a. The input format is invalid.
-
3a1. FitBiz shows an error message.
Use case resumes at step 2.
-
MSS
-
User requests to view schedule for the day or the time specified
-
FitBiz shows the schedule
Use case ends.
Extensions
-
2a. The input format is invalid.
-
2a1. FitBiz shows an error message.
Use case resumes at step 1.
-
MSS
-
User requests to export a client’s training record to a CSV file
-
FitBiz shows a list of clients
-
User requests to export a specific client’s training record in the list
-
FitBiz exports the client’s training records
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
-
3a. The given name is invalid.
-
3a1. FitBiz shows an error message.
Use case resumes at step 2.
-
MSS
-
User requests to view graph visualisations of a client’s progress
-
FitBiz shows a list of clients
-
User requests to view the training graph of a specific client in the list
-
Fitbiz shows the training graph of the client
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
-
3a. The given name is invalid.
-
3a1. FitBiz shows an error message.
Use case resumes at step 2.
-
{More to be added}
-
Should work on any mainstream OS as long as it has Java
11
or above installed. -
Should be able to hold up to 1000 clients without a noticeable sluggishness in performance for typical usage.
-
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.
-
Should work without the need for Internet in the program.
-
Should work reliably.
-
Should be able to store data in a human-readable format.
-
Should be for a single user.
-
Should not use DBMS to store data.
-
Should not exceed 100Mb in file size.
{More to be added}
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. |
-
Initial launch
-
Download the jar file and copy into an empty folder
-
Double-click the jar file
Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
-
-
Saving window preferences
-
Resize the window to an optimum size. Move the window to a different location. Close the window.
-
Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-
{ more test cases … }
-
Deleting a client while all clients are listed
-
Prerequisites: List all clients using the
list
command. Multiple clients in the list. -
Test case:
delete 1
Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated. -
Test case:
delete 0
Expected: No client is deleted. Error details shown in the status message. Status bar remains the same. -
Other incorrect delete commands to try:
delete
,delete x
(where x is larger than the list size) {give more}
Expected: Similar to previous.
-
{ more test cases … }