1. Introduction

This project portfolio details my key contributions to the team software engineering project, Athletick.

The team consists of five Year 2 Computer Science undergraduates in the National University of Singapore (NUS), including myself.

The project was completed as part of a CS2103T Software Engineering module offered by the NUS School of Computing. We were given six weeks to either morph or enhance an existing Java project, Address Book.

We chose to morph the project into Athletick, a tool for coaches and captains to use to keep track of their team’s attendance and performance. Athletick also features a calendar for coaches and captains to plan their schedules, and supports the sorting, filtering, and searching of athletes in their database.

Like Address Book, Athletick uses the command-line as its main method of input and a JavaFX Graphical User Interface for display. Some constraints of the project were that it should have a command-line input, and it should be used by a single user only. The full list of constraints can be found here.

My role was to build the Performance feature, which encompasses the adding, deleting and viewing of events and records.

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.

2. Summary of Contributions

This section shows a summary of my coding, documentation, and other helpful contributions to Athletick.

Major enhancement added: I added the ability to add, delete, and view events and records.

  • What it does: It allows coaches and captains to log records that an athlete completed for a certain event, on a certain day, into Athletick. An event can store multiple records over time for the same athlete to track their progress, which can be visualised with a line chart provided.

  • Justification: It is crucial for coaches and captains to track the progress of their team over time, hence the ability to add records. There are also different types of recordings to take in a sports team — 2.4km run, static jump, etc. —  hence the ability to add records under different events.

    The ability to delete records and events was also necessary, as teams may no longer participate in certain events, or records can be entered incorrectly.

    The presentation of record progress over a line chart was meant to give coaches and captains a quick overview of their athlete’s fitness status.

  • Highlights: This enhancement works well with future extensions to further analyse and present the records data as the required framework has been built.

    An in-depth analysis of design alternatives was necessary due to the complex structure of the records data which required efficient storage and retrieval. There was up to 4 levels of nesting - a list of events, each event with a list of athletes paired with their personal list of records, each record having a date and timing. This also made the implementation exceptionally challenging.

Minor enhancement added: I added the ability to filter athletes by their tags.

  • What it does: It allows captains and coaches to find athletes through their tags. Filtering by multiple tags is supported.

  • Justification: When there are many athletes in a team, tags are a useful way of remembering certain details about a particular athlete. This function enhances the existing tag feature by allowing users with certain tags to be filtered out of the general athlete list.

  • Highlights: This enhancement provides the necessary framework for further types of filtering, such as by gender or location.

Code contributed: The links provided are a compilation of my code contributed to the project: [GitHub repository] [RepoSense]

Other contributions

  • Project management

    • Acted as the Team Lead and assigned GitHub issues to team members

    • Managed the deliverables for all 4 milestones: v1.1, v1.2, v1.3, v1.4

    • Released v1.3.3 of the product, before the final v1.4 release

  • Enhancement to an existing feature

    • Extended the existing find by name feature to allow users to find by tags (Pull requests #64, #84)

  • Documentation

    • Modified the colour scheme of the documentation for consistency with Athletick's signature dark blue (Pull request #79)

    • Added Developer Guide documentation for FilterCommand, Performance and Storage (Pull requests #83, #226, #232, #238)

    • Added User Guide documentation for filter, find, delete -p and performance-related commands (Pull requests #79, #117, #206, #239, #241)

  • Community

    • Created helper methods for team members to integrate Performance into their respective features (Pull requests #98, #128)

    • Reviewed pull requests with non-trivial review comments (Pull requests #65, #91, #188)

    • Reported bugs and offered suggestions to other teams in the class (Issues #129, #131)

  • Tools

    • Integrated a new GitHub plugin (Coveralls) to the team repo

3. Contributions to the User Guide

Given below is an extract of what I contributed to the User Guide. They showcase my ability to write documentation targeting end-users. The full User Guide can be found here.

My key contributions include the documentation of Performance-related commands, as well as filter, find and delete -p commands.

[Start of extract from User Guide]

3.1. Adding an athlete’s record : performance

This command records your athlete’s performance for a certain event, on a certain day, to Athletick.

You will need the following details to add a record.

  • Athlete’s index

  • Event name

  • Date of record

  • Timing of record

The event has to be created first. Otherwise, Athletick will prompt you to create that event.

Let’s say that you took a timed trial for Tao Li on 2nd November 2019 under the freestyle 50m event, and she took 24.01 seconds to complete it. Now you want to store this record in Athletick.

What you should do

Type in the command in the following format and press Enter to execute it.

Format : performance INDEX e/EVENT_NAME d/DDMMYYYY t/TIMING

Example : performance 3 e/freestyle 50m d/02112019 t/24.01

addrecord wysd
Figure 1. As seen in the orange box, Tao Li has index 3 in the active list. Hence, 3 is used at the INDEX.

What you should see

If successfully added, the result box will display the details of the record you just added, as shown in the diagram below.

addrecord wyss
Figure 2. Details of Tao Li’s new record - event, date and timing - are displayed in the result box.

3.2. Viewing records : view records

This command shows you the records stored under a particular event in Athletick.

Let’s say that you want to see the records under the freestyle 50m event.

What you should do

Type in the command in the following format and press Enter to execute it.

Format : view records EVENT_NAME

Example : view records freestyle 50m

viewrecords wysd

What you should see

If successfully executed, the result box will display the message "Here are the records for" followed by the event name you requested, as shown in the red box in the diagram below.

Additionally, the feature box (orange box) will show the athletes who have records under this event, followed by a graph of their progress over time.

viewrecords wyss

[End of extract from User Guide]

4. Contributions to the Developer Guide

Given below is an extract of what I contributed to in the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project. The full Developer Guide can be found here.

My key contributions include the documentation of the Storage component, Performance implementation and FilterCommand implementation.

[Start of extract from Developer Guide]

4.1. 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.1.1. Implementation

This section explains how Performance is implemented in Athletick.

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

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 4. 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().

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 5. Activity diagram showing how a Record is added to an Event.

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 6. Sequence diagram showing how Records are viewed. Interactions in the RecordsPanel are omitted and shown in a separate sequence diagram below.
recordspanel sequencediagram
Figure 7. Reference frame for interactions in the RecordsPanel in the previous sequence diagram.

4.1.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)

[End of extract from Developer Guide]