By: AY1920S1-CS2103T-T12-3      Since: Sep 2019      Licence: MIT

1. Introduction

This section specifies the purpose of this document and design goals of Athletick.

1.1. Purpose

This document describes the software architecture and system design of Athletick, a team management desktop application for coaches and team captains of timing-based performance sports. It also includes some of the design considerations for the implementation of Athletick’s features.

The intended audience of this document includes the developers and software testers of Athletick.

Note the following symbols and formatting used in this document:

This symbol indicates important information.
command

A grey highlight (called a mark-up) indicates that this is a command that can be typed into the command line and executed by the application.

component

Green text with grey highlight indicates a component, class, object or method in the architecture of the application.

1.2. Design goals

Athletick was developed as part of CS2103T, a software engineering module taken in the National University of Singapore. We were tasked to morph a generic address book application that manages contacts into an application that manages something else. At the end of the project, it should be ready to be continued by future developers.

As part of the project constraints, the input to Athletick needs to be primarily Command-Line Interface (CLI). Non-CLI inputs will reduce the suitability of the product to our target users. Taking this into consideration, the following principles guide the design of Athletick:

  1. Detailed Command Syntax Instructions

    In order to make Athletick more user-friendly, we have provided detailed command syntax instructions whenever users enter an erroneous command, allowing them to correct their errors on the fly. This helps users to maintain their workflow without having to switch back and forth between the application and the user guide, enabling them to complete their tasks more efficiently.

  2. Optimised Performance

    Athletick should be able to hold up to 1000 athletes, attendance and performance records without a noticeable sluggishness in performance for typical usage. To achieve this, we have used optimal data structures for storing and retrieval of data.

  3. Designer Friendly

    As Athletick is intended for future student developers like us to make modifications and extensions to its behaviour, adhering to the high-level design architecture strictly was a necessity. This translates to extensive use of abstractions for code clarity. Additionally, we provided Javadoc comments for our classes and methods for developers to understand how they work.

2. Setting up

Refer to the guide here.

3. System design

This section introduces the high-level design of Athletick and gives you a basic understanding of how each component operates and interacts with one another.

3.1. Architecture

ArchitectureDiagram
Figure 1. Architecture Diagram

The Architecture Diagram given above explains the high-level design of Athletick. Given below is a quick overview of each component.

Main has two classes called Main and MainApp. It is responsible for,

  • 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.

  • UI: Displays the UI of Athletick.

  • Logic: Executes commands from the user.

  • Model: Holds the data of Athletick in-memory.

  • Storage: Reads data from, and writes data to, the hard disk.

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 (refer to the class diagram given below) defines it’s API in the Logic.java interface and exposes its functionality using the LogicManager.java class.

LogicComponent
Figure 2. Class Diagram of the Logic Component

How the architecture components interact with each other

The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delete 1.

ArchitectureSequenceDiagram
Figure 3. Component Interactions for delete 1 Command

The sections below give more details of each component.

3.2. UI component

UiClassDiagram
Figure 4. Structure of the UI Component

API : Ui.java

The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, PersonListPanel, 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.

3.3. Logic component

LogicComponent
Figure 5. Structure of the Logic Component

API : Logic.java

  1. Logic uses the AthletickParser class to parse the user command.

  2. This results in a Command object which is executed by the LogicManager.

  3. The command execution can affect the Model (e.g. adding a person).

  4. The result of the command execution is encapsulated as a CommandResult object which is passed back to the Ui.

  5. In addition, the CommandResult object can also instruct the Ui 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.

DeleteSequenceDiagram
Figure 6. Interactions Inside the Logic Component for the delete 1 Command
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.

3.4. Model component

ModelComponent
Figure 7. Structure of the Model Component

API : Model.java

The Model,

  • stores a UserPref object that represents the user’s preferences.

  • stores the Address Book data.

  • exposes an unmodifiable ObservableList<Person> 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.

As a more OOP model, we can store a Tag list in Athletick, which Person can reference. This would allow Athletick to only require one Tag object per unique Tag, instead of each Person needing their own Tag object. An example of how such a model may look like is given below.

BetterModelClassDiagram

3.5. Storage component

storage classdiagram
Figure 8. Structure of the Storage Component

API : Storage.java

The Storage component saves the following data in json format and reads it back as objects when a new session of Athletick is started.

  • UserPref data

  • Athletick data (athlete list)

  • Performance data (Event and Record)

  • TrainingManager data (Training)

Performance and TrainingManager rely on JsonAdaptedPerson as well, since a performance and training record also stores the athlete it is referring to.

3.6. Common classes

Classes used by multiple components are in the seedu.addressbook.commons package.

4. Implementation

This section describes some noteworthy details on how certain features are implemented. We have included our design considerations for you to understand our decision making processes.

4.1. Training feature

Athletick allows users to record training information like the date of training and an athlete’s attendance. This is done using a training command. With this information recorded, Athletick allows users to get the team’s overall attendance rate, and get an overview of all training sessions in a month.

4.1.1. Implementation

A Training class stores the training information. To facilitate management of trainings, a TrainingManager class stores all the Training sessions. The class diagram below shows the interaction of different components to produce the training feature.

training class diagram
Figure 9. Class diagram of the training feature components

A training session is represented by a Training class and it contains information like the date of training and training attendance. The AthletickDate class represents the date of a training session in Training. This class is shared across both the frontend and backend of the application, allowing training information to be used in other features that use AthletickDate. A HashMap<Person, Boolean> represents attendance in Training and indicates whether a Person has attended that training session. If a Person attended, the value associated with him in the HashMap<Person, Boolean> will be true, and false if he did not attend.

The TrainingCommand is an abstract class that extends the Command class and allows users to record training sessions. Users have the ability to add training sessions by indicating members present or members absent using the training or training -a commands. The TrainingCommandPresent and TrainingCommandAbsent are classes that extend TrainingCommand which allows for this polymorphism. They are created by the TrainingCommandParser class.

A TrainingManager stores and manages all Training sessions in Athletick. It contains a list which is used to maintain information of multiple trainings. A Training is added to this list whenever a user executes a training command. The activity diagram below shows how training information is stored after a user executes the training command.

training command activity diagram
Figure 10. Activity diagram showing execution of training command

TrainingManager also provides functions for users to calculate the attendance rate of one individual, or the entire team. The following operations are used for this feature:

  • TrainingManager#getPersonAttendanceRateString — Returns the person’s overall attendance rate in String format.

  • TrainingManager#getAttendanceRateOfAll - Returns a list of everyone’s attendance rate.

These operations are used by the select, attendance and view attendance commands. The following sequence diagram shows how the TrainingManager provides other components with attendance rates.

view attendance sequence diagram
Figure 11. Sequence diagram showing how view attendance command gets attendance rate

TrainingManager also allows users to get the attendance of one particular training using the following operation:

  • TrainingManager#getTrainingAttendanceListOnDate — Returns training attendance on the specified date.

The sequence diagram below shows a use case of how training attendance is obtained from TrainingManager when a calendar command is executed.

calendar sequence diagram
Figure 12. Sequence diagram showing how calendar command gets training attendance

4.1.2. Design Considerations

This section contains some of our considerations for the training feature.

Aspect: How to store attendance information of an individual.

Alternative 1: Make extensions to the Athletick class by storing and tagging each Person with number of trainings attended and total number of trainings.

Alternative 2 (Current Choice): Create separate classes to manage training information.

Pros

It is easy to implement.

Allows storing of specific training information without depending on the Athletick class. This also allows new features to be easily introduced to training in the future.

Cons

Violates software engineering principles (single responsibility principle) and is not useful when we want more detailed information (attendance on specific date) about a training session.

More time needed to design system architecture.

Reason for choosing alternative 2: Training and TrainingManager are created as standalone classes to contain training information. We intend to introduce new features (e.g. training category) in the future and this implementation allows us to easily do so.

Aspect: Which data structure to store training attendance.

Alternative 1: Use a linked list to store training attendance.

Alternative 2 (Current Choice): Use a hash table to store training attendance.

Pros

Most intuitive way to maintain training attendance. Also provides us with functions to easily access and edit data.

Makes obtaining information much quicker.

Cons

Accessing attendance and attendance rate of one person takes more time.

Requires more effort to maintain and requires coding of new functions to edit data.

Reason for choosing alternative 2: The select and attendance commands require the attendance rate of only one person and a hash table provides us with the fastest access time to access attendance information of one person.

Aspect: How to edit training information.

Alternative 1 (Current Choice): Edit by replacing an existing training with a new training on the same date.

Alternative 2: Create a command to support editing of training.

Pros

Users will not need to type lengthy edit commands.

More intuitive to a user who wants to edit.

Cons

Unable to support multiple trainings on same date.

Users have the option to edit date, attendance and even add a person which will require lengthy commands.

Reason for choosing alternative 1: Editing training information would require typing long commands which will be very time-consuming and this defeats the purpose of having a command line interface. Editing training by replacing an old one with the training command makes it editing much quicker.

4.2. Performance feature

Athletick allows users to record an athlete’s performance details from timed trials. With this information recorded, Athletick allows users to get an overview of the team’s capability and progress in specific events.

4.2.1. Implementation

This section explains how Performance is implemented in Athletick.

It is split into 4 sections.

  1. Overview

  2. Adding and deleting of Event

  3. Adding and deleting of Record

  4. Viewing of Event and Record

Overview

ModelManager has a Performance, which has a UniqueEventList. Every Event in Athletick is stored in this UniqueEventList. The class diagram below shows how the different components mentioned interact with one another.

performance classdiagram
Figure 13. Class diagram for showing how Performance is implemented with Model and Logic.

As the name suggests, all Event names are unique in UniqueEventList. This is ensured by UniqueEventList#contains() that checks whether there is an Event with the same name before the Event is added.

Every event has its own HashMap where performances under this event are stored. The key of the HashMap is the Person that the performance records will be under, while the value of the HashMap is a list of Record s under the Person.

This structure allows each Person to have multiple Record s stored in Athletick so their progress over time can be analysed using the AthletickDate and Timing attributes in Record. Additionally, an athlete’s records can be easily retrieved by calling the HashMap#get() method.

Event s are added using the EventCommand, and Record s are added using the PerformanceCommand. In these commands, changes to UniqueEventList are called through Model in EventCommand#execute() and PerformanceCommand#execute() since Model carries a common copy of all the data stored in Athletick.

The Observer Pattern is adopted when displaying Performance data through the UI. Model exposes an unmodifiable ObservableList<Event> through Model#getPerformance that returns a ReadOnlyPerformance. It can be 'observed' and is updated accordingly when data in Performance changes.

Function 1: Adding and Deleting of Event

The following sequence diagram illustrates what happens in Logic and Model when in an example scenario when event freestyle 50m is given as a user input (ie. when the user adds the freestyle 50m event).

addevent sequencediagram
Figure 14. Sequence diagram showing the operations in Logic and Model when an event is added.

Deleting an event (with DeleteEventCommand) does the opposite. The input delete -e freestyle 50m will call Model#deleteEvent(), after making sure the event exists in Athletick by getting a boolean from Model#hasEvent().

Function 2: Adding and Deleting of Record

Operations for Record - adding and deleting - work similarly to that of Event as well, except there are more methods involved as there is a greater degree of nesting.

The workflow for adding a record can be illustrated by the Activity Diagram below.

addrecord activitydiagram
Figure 15. Activity diagram showing how a Record is added to an Event.
Function 3: Viewing of Event and Record

Users can also view all Record s under an Event using view records e/EVENT_NAME. The following sequence diagrams illustrate how the Logic, Ui and Model work together when Record viewing is executed.

viewrecords sequencediagram
Figure 16. Sequence diagram showing how Records are viewed. Interactions in the RecordsPanel are omitted and shown in a separate sequence diagram below.
recordspanel sequencediagram
Figure 17. Reference frame for interactions in the RecordsPanel in the previous sequence diagram.

4.2.2. Design Considerations

This section explains the factors that we took into consideration when deciding on how different aspects of Performance should be implemented.

Aspect: Method of storing performance records for athletes.

Performance records are currently stored in a list for each athlete. Each list is saved as a value for the athlete key in a Performance HashMap.

Alternative 1 (Current Choice): Use a HashMap of Persons as keys and a list of Records as values.

Alternative 2: Create a class that has Persons and list of Records as attributes and store instances of this class in a list.

Pros

  • Retrieving athlete’s individual records is fast - it can be done in O(1) time

  • Checking of records can be done with a simple for-loop

Cons

  • Checking requires using an iterator or a lambda operation (requires variables to be declared as final, making retrieval of data troublesome)

  • Retrieving by values (eg. date of record) is difficult as it requires traversing through the HashMap and checking the individual records' dates

  • Adding of records is susceptible to errors as duplicate persons can be added

  • Creating our own data structure results in overheads in testing and creating our own helper methods

  • Retrieving an athlete’s individual records in O(1) time requires the athlete’s index in the list, which is not always known

Reason for choice of Alternative 1:

  • Retrieving from a HashMap is fast, which fulfils one of our non-functional requirements of being able to support a database of 1000 athletes

  • Using an athlete-records relationship is similar to the key-value relationship in HashMap so the existing methods that are in the HashMap API are relevant

Aspect: Method of displaying events and records to users.

Viewing events and records are separate commands in Athletick.

To view events, the command is view performance. Users will be shown a list of all the events they have in Athletick. To view records under a certain event, the command is view records EVENT_NAME. Users will be shown a graph on each athlete’s records under this event.

Alternative 1 (Current Choice): Display events and records separately.

Alternative 2: Display all records under all events.

Pros

  • Viewing events, followed by "zooming" into a particular event’s records gives users a more immersive experience

  • Navigating is simple as viewing events and its records require only one command

Cons

  • Getting an overview of all events and its respective records is not possible

  • Supporting 2 commands results in overhead in parsing the command and creating the relevant Ui in the feature box

  • Displaying of information will require a lot of scrolling (since the feature box is limited in size) and can be difficult when the event of interest is located at the end

Reason for choice of Alternative 1:

  • Allowing users to look at the records under their event of interest gives them more control over what they want to see

  • Navigating from event overview to a particular event mimics how people navigate in apps - tapping on a chat title (in this case, viewing records for a particular event), to see the whole conversation (record details for a particular event)

4.3. Calendar feature

To allow users to retrieve training and performance records using the date they were recorded on, Athletick has a calendar feature which provides 2 main functions:

  1. Displays an overview of training and performance records in a selected month

  2. Displays training and performance records entered on a specific date

4.3.1. Implementation

The implementation of the above functions will be described separately in this section.

Function 1: Displays an overview of training and performance records in a selected month

There are 2 commands that users can issue to perform function 1:

  1. view calendar: Displays calendar for the current month.

  2. calendar MMYYYY: Displays calendar for the month specified by the user.

The following sequence diagram shows you how the calendar MMYYYY (e.g. calendar 012019 where 012019 corresponds to January 2019) command works.

CalendarCommandSequenceDiagram1
Figure 18. Interactions inside the UI and Logic components for the calendar 012019 Command

Upon completion of the above execution, the calendar for January 2019 will be displayed to the user.

The view calendar command is similar except that displayCalendar(CommandResult) is called instead of displayCalendarWithDate(CommandResult) and the CalendarPanel class is instantiated without an AthletickDate specified by the user. The calendar displayed to the user will reflect the current month and year since date is not specified by the user.

The following activity diagram summarises what happens when a user wants to perform function 1.

Function1ActivityDiagram
Figure 19. Activity diagram showing what happens when a user wants to perform function 1

Function 1 is facilitated by the CalendarPanel class. It extends UiPart<Region> and represents the calendar using a GridPane with dimensions of 7 by 6 (42 cells). Additionally, it implements the following operations:

  • CalendarPanel#retrieveCurrentDate() — Retrieves the details of today’s date to be used as the title of the calendar feature and for rendering the displayed month on the calendar when the user does not provide a specific month to view.

  • CalendarPanel#retrieveProvidedDate(AthletickDate) — Retrieves the details of the date provided by the user for rendering the displayed month on the calendar.

  • CalendarPanel#initialiseSelectedDate() — Fills up all the 42 cells of the GridPane with their respective days based on the selected month by the user. Days of the previous and next month used to fill up the remaining cells are marked in a lighter colour.

    In addition, days with training or performance records will be marked with a small green or purple dot indicator respectively.

These operations are performed when an instance of the CalendarPanel class is created in the MainWindow class. An instance of CalendarPanel is created when the CommandResult obtained in MainWindow after the execution of the user’s command contains a Feature corresponding to a calendar and an optional AthletickDate.

The sequence diagram below shows you what happens when the CalendarPanel class is instantiated.

CalendarConstructorSequenceDiagram
Figure 20. Interactions inside the UI and Model components when CalendarPanel is instantiated

With reference to the above diagram, if hasTrainingOn(AthletickDate) returns true, a green dot indicator will be added to the cell of the GridPane. Similarly, if hasPerformanceOn(AthletickDate) returns true, a purple dot indicator will be added.

Upon completion of the above execution, all 42 cells GridPane will be filled with a number corresponding to the day of the month. Days with training or performance records will be marked with a green or purple dot indicator respectively. The following diagram depicts how each individual cell will look like.

CellResult
Function 2: Displays training and performance records entered on a specific date

In order to perform function 2, the user issues the calendar DDMMYYYY command (e.g. calendar 01012019 where 01012019 corresponds to 1st January 2019).

The following sequence diagram shows you how the calendar DDMMYYYY (e.g. calendar 01012019) operation works.

CalendarCommandSequenceDiagram2
Figure 21. Interactions inside the UI and Logic components for the calendar 01012019 command

Upon completion of the above execution, the attendance and performance records for 1st January 2019 will be displayed to the user.

The following activity diagram summarises what happens when a user issues the calendar DDMMYYYY command.

Function2ActivityDiagram
Figure 22. Activity diagram showing what happens when a user issues the calendar DDMMYYYY command

Function 2 is facilitated by CalendarDetailPanel. It extends UiPart<Region> and displays the attendance and performance records for a date specified by the user. Additionally, it implements the following operations:

  • CalendarDetailPanel#initialiseAttendanceData() — Retrieves and displays attendance records recorded on the specified date.

  • CalendarDetailPanel#initialisePerformanceData() — Retrieves and displays the performance records recorded on the specified date.

These operations are performed when an instance of CalendarDetailPanel is created in the MainWindow class. An instance of CalendarDetailPanel is created when the CommandResult obtained after executing the user’s command contains a Feature corresponding to a calendar and an AthletickDate.

The sequence diagram below shows you what happens when the CalendarDetailPanel class is instantiated.

CalendarDetailConstructor
Figure 23. Interactions inside the UI and Model components when CalendarPanel is instantiated

Upon completion of the above execution, training and performance records recorded on the specified date will be displayed to the user.

4.3.2. Design considerations

This section contains some of our design considerations for the calendar feature.

Aspect: Whether to display information using a monthly calendar or a list only containing dates in a month with training or performance records

Alternative 1 (Current Choice): Use a monthly calendar

Alternative 2: Use a monthly list

Pros

Displays information more clearly especially when users have a large number of training and performance records in a month

Displays information more concisely if users have a small amount of training and performance records in a month

Cons

Increases difficulty of implementation

Displays information in rows and columns which is no better than using Excel

Reasons for choice of alternative 1:

  • Alternative 1 displays information more clearly when users have a large amount of training and performance information, which is a probable scenario in the case of sports teams. In contrast, alternative 2 uses a list similar to Excel which we are trying to improve upon.

  • Alternative 1 abides by our design principle to keep Athletick designer friendly since future developers can expand upon it and implement more date-related functionalities.

Aspect: How to display calendar for a month

Alternative 1 (Current Choice): Display using a fixed 7 by 6 GridPane, fill up left over days with days from previous and next month

Alternative 2: Display using a variable sized GridPane that is populated with days from selected month only

Pros

Emulates implementation by other calendar applications and easier to implement (e.g. Google Calendar)

Maximises usage of space in the application window

Cons

Displays information of previous and next month which users may not be interested in

Increases difficulty of implementation

Reasons for choice of alternative 1:

  • Alternative 1 is easier to implement since the dimensions of the calendar are fixed so we do not have to recalculate it constantly. The ease of implementation is important given the tight deadlines we have to contend with in our software engineering module.

  • Alternative 1 emulates the implementation of other successful calendar applications (e.g. Google Calendar) so we do not have to reinvent the wheel.

Aspect: How the user can display the attendance and performance data on a specific date

Alternative 1 (Current Choice): Use one calendar DDMMYYYY command to view both attendance and performance records on the specified date

Alternative 2: Use two separate commands to view attendance and performance records separately on the specified date

Pros

Makes access of data more efficient

Allows users to have more control over what data is displayed

Cons

Displays both attendance and performance records on the specified date all the time

Requires more flags to be added to the command syntax which makes it more complex

Reasons for choice of alternative 1:

  • Alternative 1 is more user-friendly as it reduces the number of commands users have to remember in order to access the information they want to see. In addition, attendance and performance records are displayed into separate sections in the window so the information will not be cluttered.

4.4. Select feature

The select feature allows user to view the profile of a selected athlete.

4.4.1. Implementation

The implementation of the select feature consists of two parts, mainly the implementation of the command and the implementation of the UI.

The implementation of the command is facilitated by SelectCommand class. It extends Command and parses the arguments using SelectCommandParser. It implements one operation:

  • CommandResult#execute() — Executes the selectCommand which returns the athlete selected to be displayed in the UI.

The implementation of the UI portion for the select feature is facilitated by InformationDisplay. It extends UiPart<Region> and displays the personal information of the selected athlete. Additionally, it implements the following operations:

  • InformationDisplay#displayPersonalInfo() — Displays the personal information of the selected athlete such as the name, email, address, phone number and other personal details.

  • InformationDisplay#performanceDisplay() — Displays the performance of the selected athlete, which includes the event, best performance and most recent performance.

An example usage scenario is given below which elaborates how the select feature behaves at each step.

Step 1. The user executes the select 3 command. The command is then parsed by SelectCommandParser which creates an instance of SelectCommand. SelectCommand retrieves the athlete based on the index of the list panel on the left. When the command is executed, the athlete selected at the specified index will be stored in ModelManager as selectedPerson using the operation Model#storePerson(Person).

Step 2. After the command has been executed, the selected athlete is retrieved in the MainWindow class. It checks whether an athlete has been selected and displays the selected athlete’s personal information.

The diagram below summarises the steps of the example scenario when a user executes the select command:

SelectActivityDiagram
Figure 24. Activity diagram of select command execution

The implementation was done this way because the Ui component interacts with both the Logic and Model component. Firstly, the Ui component takes in the input from the user and allows SelectCommandParser in Logic component to parse the argument. After the argument has been parsed, the athlete is stored in the Model component which houses most of the data in the app. The Ui listens for any changes made to the Model data, and updates the Ui to display the selected athlete.

The following sequence diagram shows how the select feature works:

SelectCommandSequenceDiagram
Figure 25. Sequence Diagram of select Command

4.4.2. Design considerations

There were some decisions that I had to make as I was designing the select feature and had to compare which methods would better suit the application. The following consists of the design considerations for the select feature.

Aspect: How the personal information of the selected athlete will be displayed

There were a few ways how the personal information of the selected athlete could be displayed and the following alternatives are some of the considerations I had when implementing.

Alternative 1 (current choice): Displaying it in a feature box.

Alternative 2: Displaying it in a tab form.

Alternative 3: Displaying via a pop-up.

Pros

  • Minimises the use of mouse and is in line with the other features that is utilizing the feature box.

  • Looks more organised compared to the other alternatives.

  • Looks neater and organised.

Cons

  • Aesthetic is not as good compared to the other alternatives.

  • Not as intuitive to use as mouse has to be used to switch around tabs.

  • Increase the use of mouse to close the window and may be distracting to user.

Reason: Alternative 1 was chosen because it utilises more of the command line interface and we wanted to steer away from the use of the mouse. Even those the aesthetic might not be as good as alternative 2 and 3, I felt that it was a better choice as it was in line with the other features that my group mates were going to implement.

Aspect: How to select an athlete

There were two ways on how an athlete could be selected and it was between choosing by index or by name which I had to consider.

Alternative 1 (current choice): Choosing by the index number.

Alternative 2: Choosing by name.

Pros

  • Pros: Intuitive to use and can be used with other commands such as FindCommand and FilterCommand to narrow down the list of people.

  • Pros: Can omit the filtering step and select the athlete directly.

Cons

  • Cons: Additional step of filtering the list to make it shorter before selecting an athlete.

  • Cons: There may be 2 people with the same name and thus result in an error.

Reason: In the end, I went with alternative 1 because it was more intuitive to use and was in line with some of the other functions such as DeleteCommand or FindCommand which also uses index. It also reduces the need to type out the full name of the selected athlete.

4.5. Undo / Redo feature

The undo command enables users to undo their previous commands while the redo command enables users to redo their undone commands.

4.5.1. Undo Implementation

The undo command is facilitated by the HistoryManager. HistoryManager holds the states of Athletick, Attendance and Performance, which are kept in their respective stacks governed by HistoryManager. Furthermore, HistoryManager also holds the Command stack that keeps track of the commands executed by the user.

Each time after the user executes a command, the command will be pushed to the Command stack. Also, following the execution of the command, changes to either Athletick,Attendance or Performance will result in the new state being pushed into their respective stacks.

Given below is an example usage scenario on how the undo mechanism behaves at each step.

Step 1. The user launches the application for the first time. The HistoryManager will be initialised with the initial Athletick, Attendance and Performance state pushed to the respective stacks.

initialStack
Figure 26. Initial stacks of states

Step 2. The user executes the delete -p 3 command to delete the 3rd person in the Athletick list. The delete command will be pushed into the Command stack. After that, since the delete -p 3 command only alters the Athletick state, the new Athletick state will then be pushed to the Athletick stack while the Attendance and Performance stacks are left untouched as their states remain the same.

afterUndoStack
Figure 27. Stacks of states after delete -p 3 command

Step 3. The user now decides that deleting the 3rd person in the list was a mistake, and decides to undo the action by executing the undo command. The undo command then executes the undo method in the ModelManager. This pops the latest command from the Command stack and the latest Athletick state from the Athletick stack. It then peeks at the Athletick stack to retrieve the Athletick state before delete -p 3 command was executed.

initialStack
Figure 28. Stacks of states after undo command

Step 4. After retrieving the Athletick state before delete -p 3 command was executed, we then reset the Athletick state to this retrieved Athletick state. As such, the previous command will then be undone.

The following sequence diagram shows how the undo operation works:

undoSQ
Figure 29. Sequence diagram for undo implementation

4.5.2. Redo Implementation

The redo command is similarly facilitated by the HistoryManager. HistoryManager also holds the undone states of Athletick, Attendance and Performance, which are kept in their respective undone stacks governed by HistoryManager. Furthermore, HistoryManager also holds the undone Command stack that keeps track of the commands undone by the user.

Each time an undo command is executed succesfully, the undone Command will be pushed to the undone Command stack and the respective undone states of Athletick, Attendance or Performance, if affected, will be pushed to their respective undone states.

Following that, how the redo command works is very similar to how the undo command works. As such, you can also refer to the diagrams in the Undo Implementation.

The activity diagram for redo command is as follows:

redoactivity
Figure 30. Activity diagram for redo command

4.5.3. Design Considerations

This section describes the pros and cons of the current and other alternative implementations of the undo and redo features.

Aspect: How undo & redo executes

Alternative 1 (Current Choice): Keep states of Athletick, Attendance and Performance.

Alternative 2: Individual command knows how to undo/redo by itself

Pros

  • Easy to implement, and easy for developers to understand.

  • Will use less memory (e.g. for delete -p 1, just save the person being deleted).

Cons

  • May have performance issues in terms of memory usage.

  • We must ensure that the implementation of each individual command is correct.

Reason why we chose alternative 1:

Even though the memory usage of Alternative 2 is lesser, we do not feel that this benefit of lesser memory usage outweighs the tedious cost of implementing the alternative.

Furthermore, as we realise that each time the application starts, the memories of the states are cleared. This means that the cost of having alternative 1 is significantly lesser, as the memories of the states do not accumulate. As such, we decided to go with the first alternative.

4.6. Adding/editing photo feature

The sub feature of AddCommand and EditCommand allows the inclusion of photo for an athlete.

4.6.1. Implementation

The sub feature is facilitated by Photo. It is similar to the other features such as Name and Phone which uses a prefix i/ followed by the file name (e.g. i/default.png). Prior to adding the photo of an athlete, the image file that is going to be used has to be in the images folder which will be generated when the jar file is executed. Photo takes in the file name as a String and retrieves the photo to be added or edited from the images folder.

The file name of the images is restricted to alphanumerics only and the file format that will be used is .png. This is done to keep the file name simple.

4.6.2. Design Consideration

The following consists of some of the design consideration when I was designing this sub-feature.

Aspect: Regular expression for the file name

Alternative 1 (current choice): To use alphanumerics only.

Pros

Pros: Keeps it simple without the confusion of special characters.

Reason: Alternative 1 was chosen because it simplifies the parsing of the filename and reduces the error it might have if special characters were included.

4.7. Filter feature

The filter command enables filtering of athletes based on their tags. Users are able to filter by multiple tags, and any athlete that has any of the given tags will be in the results.

4.7.1. Implementation

Filter makes use of a TagMatchesPredicate class to determine if the athlete has tags matching the user input. Given below is the Sequence Diagram to show how Logic and Model are involved when an example input of filter captain freestyle is called.

filter sequencediagram
Figure 31. Sequence diagram for execution of FilterCommand.

4.7.2. Design considerations

This section explains the factors that we took into consideration when making decision on how FilterCommand should be implemented.

Aspect: Method of determining an athlete match when multiple tags are given.

Given an example search of filter captain freestyle, athletes will be shown in the results if they contain either the captain or freestyle tag. They need not have both captain and freestyle.

Alternative 1 (Current Choice): Match athletes who contain either tag.

Alternative 2: Match athletes who contain every tag.

Pros

  • Searching for athletes is flexible

  • Retrieving a specific type of athlete is possible

Cons

  • Filtering can yield results that the user is not interested in

  • Filtering will yield limited results and a separate filter operation is required if users want a more lenient filtering

Reason for choice of Alternative 1:

Our choice of "lenient" filtering may give users results that they may not be interested in especially if they are looking for very specific athletes. However, we find that it is a good compromise for users who want this "lenient" filtering as the athlete’s tags will be listed in the search as well, so specific athletes can be found from this filtered list.

4.8. Sort Command

The sort command sorts the displayed list of athletes in alphabetical order. As new athletes are added to the bottom of the list, the sort command is used after to reorder the athlete list.

4.8.1. Implementation

The sort command makes use of a PersonNameComparator that orders athletes in alphabetical order by comparing their names. The comparison is case-insensitive.

The following sequence diagram shows how the sort operation works:

SortCommandSequenceDiagram
Figure 32. Interactions Inside the Logic and Model Components for the sort Command

With reference to the diagram above, when the user issues the sort command, a SortCommand object s is created. s is then executed by LogicManager, which calls the sortByName() method in LogicManager. An instance of PersonNameComparator is then created and is used by the sortByName(PersonNameComparator) method in Athletick to sort the observable internalList in UniquePersonList. Upon completion of the above execution, the sorted list of athletes would be displayed immediately to the user.

To support sorting by more attributes (e.g. attendance rate/performance) in the future, you can simply create a new class that implements the Comparator interface which compares athletes by that attribute instead. After which, you have to edit the sort command syntax to allow users to indicate how they want their list to be sorted.

4.8.2. Design considerations

This section contains some of our design considerations for the sort command.

Aspect: When should the athlete list should be sorted

Alternative 1 (Current Choice): Sort address book after user issues the sort command

Alternative 2: Sort address book persistently in alphabetical order

Pros

  • Allows users to view their newly added athletes at the bottom of the list which is more user-friendly especially when the list of athletes is very long

  • Allows for future expansion of sorting by other attributes (e.g. performance scores) easily as we only have to create new comparators to order the athletes

  • Automates sorting so users do not have to issue any commands

Cons

  • Requires additional overhead in terms of having to create an additional command for users to issue

  • Restricts users from sorting their list by other methods

  • Limits feature’s further expansion by future developers

Reason for choice of alternative 1:

  • Alternative 1 allows users to view their newly added athletes to ensure their details are correct before they are sorted into their correct positions alphabetically. This is important especially when the athlete list is very long.

  • Alternative 1 abides by our design principle to keep Athletick designer friendly since future developers can expand upon it to allow sorting by other attributes. On the other hand, alternative 2 does not provide much room for future expansion.

4.9. Logging

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 4.10, “Configuration”)

  • The Logger for a class can be obtained using LogsCenter.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

4.10. Configuration

Certain properties of the application can be controlled (e.g user prefs file location, logging level) through the configuration file (default: config.json).

5. Documentation

Refer to the guide here.

6. Testing

Refer to the guide here.

7. Dev Ops

Refer to the guide here.

Appendix A: Product Scope

Target user profile:

  • Team coaches for time-based, competitive sports

  • Has a need to manage a significant number of team members

  • Prefer desktop apps over other types

  • Can type fast

  • Prefers typing over mouse input

  • Is reasonably comfortable using CLI apps

Value proposition: Manage team details faster and more accurately than a typical mouse/GUI driven app

Appendix B: User Stories

Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *

Priority As a …​ I want to …​ So that I can…​

* * *

Team coach who values commitment

Input attendance of my team

Keep track of their attendance rate and commitment level

* * *

Efficient team coach

Take attendance quickly

Focus on coaching my team

* * *

Team coach

Track performance of my team

Know how to help them improve

* * *

Motivational Team coach

Performance data analysis of the performance of my team

Provide detailed feedback to my athletes

* * *

Detailed team coach

Retrieve past training and performance records on a specific date

Know what happened on a specific date

* * *

Team coach

View profile of specific members

Monitor their individual progress

* * *

Careless user

Undo my previous commands

Redo any mistakes

* * *

New user

Know the available commands

Be able to use all the app functionalities

* *

Team coach

Assign tags to my team members

Differentiate roles of team members

* *

Team coach

Filter out my best performers for each event

Plan my team to send for competitions

*

Coach who is in-charge of multiple teams

Add multiple teams

Manage my teams separately

*

Forgetful coach

See past commands issued

Know what changes I have made

*

User who wants customisation

Change the app’s colour

Customise the app according to my preference

*

Coach who wants fit players

Filter players by overweight BMIs

Single them out and get them to lose weight

Appendix C: Use Cases

(For all use cases below, the System is Athletick and the Actor is the user, unless specified otherwise)

System: Athletick

UC1 - Marking attendance of players

Actor: User

MSS

  1. User requests to list persons

  2. Athletick shows a list of persons

  3. User keys in players who attended training

  4. Athletick saves the training session

    Use case ends.

Extensions

  • 2a. The list is empty.

    Use case ends.

  • 3a. The given index is invalid.

    • 3a1. Athletick shows an error message.

      Use case resumes at step 2.

UC2 - Delete person

Actor: User

MSS

  1. User requests to list persons

  2. Athletick shows a list of persons

  3. User requests to delete a specific person in the list

  4. Athletick deletes the person

    Use case ends.

Extensions

  • 2a. The list is empty.

    Use case ends.

  • 3a. The given index is invalid.

    • 3a1. Athletick shows an error message.

      Use case resumes at step 2.

UC3 - Key in Performance of a Player

Actor: User

MSS

  1. User requests to list persons

  2. Athletick shows a list of persons

  3. User requests to tag a performance to a specific person in the list

  4. Athletick updates the player’s performances

    Use case ends.

Extensions

  • 2a. The list is empty.

    Use case ends.

  • 3a. The given index is invalid.

    • 3a1. Athletick shows an error message.

  • 3b. Input event does not exist

    • 3b1. Athletick shows an error message

  • 3c. Timing is invalid

    • 3c1. Athletick shows an error message

    Use case resumes at step 2.

UC4 - View a player’s profile

Actor: User

MSS

  1. User requests to list persons

  2. Athletic shows a list of persons

  3. User request to select a specific person in the list

  4. Athletick shows the profile of the person

    Use case ends.

Extensions

  • 2a. The list is empty.

    Use case ends.

  • 3a. The given index is invalid.

    • 3a1. Athletick shows an error message.

      Use case resumes at step 2.

UC5 - Add a person

Actor: User

MSS

  1. User keys in details of person to be added

  2. Person is added to the list

    Use case ends.

Extensions

  • 1a. Details are invalid (eg. not all fields are filled up)

    • 1a1. Athletick shows an error message.

      Use case ends.

  • 1b. Person has already been added

    • 1b1. Athletick shows an error message.

      Use case ends.

UC6 - Undo a command

Actor: User

MSS

  1. User calls for undo

  2. Most recent command is undone

    Use case ends.

Extensions

  • 1a. There are no tasks to be undone.

    • 1a1. Athletick shows an error message.

      Use case ends

  • 1b. The most recent command cannot be undone.

    • 1b1. Athletick shows the most recent command that can be undone and undo

      Use case ends.

UC7 - Redo a command

Actor: User

MSS

  1. User calls for redo

  2. Undo command is redone

    Use case ends.

Extensions

  • 1a. No Redo Command to be redone

    • 1a1. Athletick shows an error message.

      Use case ends.

UC8 - View training and performance records on specific date

Actor: User

MSS

  1. User requests to view records on specific date

  2. Athletick displays training and performance records on specified date

    Use case ends.

Extensions

  • 1a. The specified date is invalid.

    • 1a1. Athletick shows an error message.

      Use case ends.

  • 1b. The specified date does not contain any records.

    • 1b1. Athletick informs the user that the specified date does not contain any records.

      Use case ends.

UC9 - Navigate to a different date on calendar

Actor: User

MSS

  1. User requests jump to a specific month and year.

  2. Athletick displays training and performance records on specified date.

    Use case ends.

Extensions

  • 1a. The specified date is invalid.

    • 1a1. Athletick shows an error message.

      Use case ends.

  • 1b. The specified date does not contain any records.

    • 1b1. Athletick informs the user that the specified date does not contain any records.

      Use case ends.

Appendix D: Non Functional Requirements

  1. Should work on any mainstream OS as long as it has Java 11 or above installed.

  2. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage.

  3. 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.

Appendix E: Glossary

Mainstream OS

Windows, Linux, Unix, OS-X

CLI

Command line interface (CLI) is a text-based interface that is used to operate software and operating systems while allowing the user to respond to visual prompts by typing single commands into the interface and receiving a reply in the same way.

Time-based Sports

Examples of time-based sports are swimming and track & field, where performance can be measured in terms of time or distance.

Appendix F: Product Survey

Author: Dominique Ng Wenyi

Pros:

  • Availability of team members for future trainings can be shown

  • Alerts given to user for upcoming trainings or a change in attendance

Cons:

  • Lacks analysis of data with visual aids like charts

  • Lacks an in-built calendar for an overview of schedule

Appendix G: 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

  1. Initial launch

    1. Download the jar file and copy into an empty folder

    2. Double-click the jar file
      Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.

  2. Saving window preferences

    1. Resize the window to an optimum size. Move the window to a different location. Close the window.

    2. Re-launch the app by double-clicking the jar file.
      Expected: The most recent window size and location is retained.

Deleting a person

  1. Deleting a person while all persons are listed

    1. Prerequisites: List all persons using the list command. Multiple persons in the list.

    2. Test case: delete -p 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.

    3. Test case: delete -p 0
      Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.

    4. Other incorrect delete commands to try: delete, delete x (where x is larger than the list size).
      Expected: Similar to previous.

Selecting an athlete

  1. Selecting an athlete while all athletes are listed

    1. Prerequisites: List all athletes using the list command. Multiple athletes in the list.

    2. Test case: select 1
      Expected: First athlete is selected from the list. Details of the selected athlete shown in the feature box.

    3. Test case: select 0
      Expected: No person is deleted. Error details shown in result box.

Adding/editing an image of an athlete

  1. Adding or editing an image of an athlete

    1. Prerequisites: Move the image files to be used into the images folder.

    2. Test case: add n/John Doe p/98765432 e/johnd@example.com g/male a/311, Clementi Ave 2, #02-25 t/backstroke i/john.png Expected: Athlete is added with the image john.png set as the profile picture.

    3. Test case: edit 2 i/john.png Expected: Athlete’s profile image is set as john.png.

    4. Test case: edit 1 i/bobby.png Expected: Error message : Image file does not exist. Make sure image file is in the images folder.

Adding a training using athletes present

  1. Add a training by indicating athletes present

    1. Prerequisites: There must be at least one person in the list. Use the list, filter or find commands.

    2. Test case: training d/11112019 #/1
      Expected: Result box indicates that training is successfully added. A green dot will appear on calendar at the date 11th of November 2019 indicating successful adding of training. Running the calendar 11112019 command will show that the first person attended training and everyone else will be displayed as absent.

    3. Test case: training #/1
      Expected: Result box indicates that training is successfully added. A green dot will appear on calendar at today’s date indicating successful adding of training. Running the calendar command with today’s date will show that the first person attended training and everyone else will be displayed as absent.

    4. Test case: training d/11112019 #/0
      Expected: No training added. Error details shown in the result box.

    5. Other incorrect commands: training d/1234567890 #/1, training
      Expected: Similar to previous.

Adding a training using athletes absent

  1. Add a training by indicating athletes absent

    1. Prerequisites: There must be at least one person in the list. Use the list, filter or find commands.

    2. Test case: training -a d/11112019 #/1
      Expected: Result box indicates that training is successfully added. A green dot will appear on calendar at the date 11th of November 2019 indicating successful adding of training. Running the calendar 11112019 command will show that the first person was absent from training and everyone else will be displayed as present.

    3. Test case: training -a #/1
      Expected: Result box indicates that training is successfully added. A green dot will appear on calendar at today’s date indicating successful adding of training. Running the calendar command with today’s date will show that the first person was absent from training and everyone else will be displayed as present.

    4. Test case: training -a d/11112019 #/0
      Expected: No training added. Error details shown in the result box.

    5. Other incorrect commands: training d/1234567890 #/1, training
      Expected: Similar to previous.

Editing a training

  1. Edit a training attendance

    1. Prerequisites: There must exist a training on the input date.

    2. Test case: training d/11112019 #/1
      Expected: Result box indicates that training was successfully replaced. Green dot that was previously on the calendar at 11th November 2019 remains there. Running the calendar 11112019 command shows the new attendance of training.

    3. Test case: training d/11112019 #/0
      Expected: Training is not replaced. Error details shown in the result box.

Deleting a training

  1. Delete a training at date

    1. Prerequisites: There must exist a training on the input date.

    2. Test case: delete -t d/11112019
      Expected: Result box indicates that training was successfully deleted. Green dot that was previously on the calendar at 11th November 2019 disappears. Running the calendar 11112019 command shows the new attendance of training.

    3. Test case: training d/11112019 #/0
      Expected: Training is not replaced. Error details shown in the result box.

Viewing attendance of one athlete

  1. View attendance of one athlete

    1. Prerequisites: There must be at least one person in the list. Use the list, filter or find commands.

    2. Test case: attendance 1
      Expected: Result box indicates the attendance of specified athlete.

    3. Test case: attendance 0
      Expected: Attendance is not shown. Error details shown in the result box.

    4. Other incorrect attendance commands to try: attendance, attendance x (where x is larger than the list size) {give more}
      Expected: Similar to previous.

Viewing overall attendance

  1. View attendance of all athletes

    1. Prerequisites: None.

    2. Test case: view attendance
      Expected: Result box indicates the team’s attendance is being displayed. Also, display in the application will show u a list of your athletes and their attendance beside their names.

    3. Other incorrect view attendance commands to try: view, view everyones attendance (where x is larger than the list size) {give more}
      Expected: Error details shown in result box.

Viewing the calendar

  1. Displaying the calendar for the current month

    1. Prerequisites: Currently viewing another feature (e.g. attendance, performance or records).

    2. Test case: view calendar
      Expected: Calendar for the current month is displayed in the feature box. The success message "Viewing your calendar" is displayed in the result box.

    3. Test case: view f (any String except attendance, performance and records)
      Expected: Calendar is not displayed. Error details shown in the result box.

    4. Other incorrect view commands to try: view, view x (where x is an integer). Expected: Similar to previous.

  1. Displaying the calendar for a specific month and year

    1. Test case: calendar 012019
      Expected: Calendar for January 2019 is displayed in the feature box. The success message "Viewing calendar for: January 2019" is displayed in the result box.

    2. Test case: calendar 132019
      Expected: Invalid date provided, calendar for specified month is not displayed. Error details shown in the result box.

    3. Test case: calendar 010000
      Expected: Similar to previous.

    4. Test case: calendar s (any String)
      Expected: Similar to previous.

    5. Other incorrect delete commands to try: calendar x (where x is any combination of numbers that is not length of 6 or 8) Expected: Similar to previous.

Viewing training and performance records

  1. Viewing training and performance records recorded on a specific date

    1. Test case: calendar 01012019
      Expected: Records for 1st January 2019 are displayed in the feature box. The success message "Viewing details for: 1st January 2019" is displayed in the result box.

    2. Test case: calendar 32012019
      Expected: Invalid date provided, records for specified date is not displayed. Error details shown in the result box.

    3. Test case: calendar 01010000
      Expected: Similar to previous.

    4. Test case: calendar s (any String)
      Expected: Similar to previous.

    5. Other incorrect delete commands to try: calendar x (where x is any combination of numbers that is not length of 6 or 8) Expected: Similar to previous.

Adding an event

  1. Adding an event while all events are listed

    1. Prerequisites: List all events using the view performance command. Multiple events in the list (freestyle 50m is inside, backstroke 100m is not).

    2. Test case: event backstroke 100m
      Expected: backstroke 100m event is added to the list. Details of the added event shown in the status message.

    3. Test case: event freestyle 50m
      Expected: No event is added. Error details shown in the status message.

    4. Other incorrect add commands to try: add event, new event.
      Expected: The former will result in an error message for adding a person. The latter will result in a general unknown command error message.

Deleting an event

  1. Deleting an event while all events are listed

    1. Prerequisites: List all events using the view performance command. Multiple events in the list (freestyle 50m is inside, backstroke 100m is not).

    2. Test case: delete -e freestyle 50m
      Expected: freestyle 50m event is deleted from the list. Details of the deleted event shown in the status message.

    3. Test case: delete -e backstroke 100m
      Expected: No event is deleted. Error details shown in the status message.

    4. Other incorrect delete commands to try: delete e, delete event.
      Expected: Similar to previous.

Undoing a previous command

  1. Undoing a previous command after user executes list command

    1. Prerequisites: Previous command is list.

    2. Test case: undo
      Expected: Error details shown in the status message. Status bar remains the same. List of people remains the same.

    3. Other incorrect undo commands to try: undo x (where x is any word)
      Expected: Similar to previous.

Redoing a previous command

  1. Redoing a previous command after user executes undo command

    1. Prerequisites: Previous command is undo.

    2. Test case: redo
      Expected: undo command reversed. Details of the redone command shown in the status message.

    3. Test case: redo undo
      Expected: Error details shown in status message. Status bar remains the same. List of people remains the same.