PROJECT: SplitWiser


Overview

My team of 4 software engineering students and I were tasked with enhancing a basic command line interface desktop addressbook application for our Software Engineering project. We chose to morph it into an activity tracking bill-splitting system called SplitWiser. This enhanced application enables people who participate in group activities together with shared expenses to split the cost evenly without the hassle of manual calculation.

This is what our project looks like:

SplitWiserGUI
Figure 1. The graphical user interface for SplitWiser.

My role was to design and write codes for the invite, disinvite and delete features. The following sections illustrate these enhancements in more detail, as well as the relevant documentation I have added to the user and developer guides in relation to these enhancements.

Note the following formatting used in this document.

delete: A grey highlight indicates that this is a command that can be inputted into the command line and executed by the application

Summary of contributions

  • Major enhancement: added the ability to invite contacts to current viewed activity

    • What it does: allows the user to invite multiple contacts at once to the current viewed activity.

    • Justification: This feature improves the product significantly because the participants in an activity is not static as people can join midway during an activity and the app should provide a convenient way to invite them without creating a new activity.

    • Highlights: This enhancement affects existing commands and commands to be added in future. The implementation was challenging due to the fact that it depends on the user’s screen.

  • Major enhancement: added the ability to disinvite contacts from current viewed activity

    • What it does: allows the user to disinvite multiple contacts at once from the current viewed activity.

    • Justification: It is sort of an "undo" function if user mistakenly invited the wrong person to an activity. Since invite allows multiple invitees at once, an "undo" function will be inconvenient as it removes everyone that was invited previously, disinvite allows user to remove particular participants that was invited mistakenly to the activity conveniently.

    • Highlights: This enhancement affects existing commands and commands to be added in future. The implementation was challenging due to the fact that it depends on the user’s screen.

  • Major enhancement: added the ability to delete contact/activity/expense in an activity

    • What it does: allows the user to delete contact/activity or soft-delete expense one at a time.

    • Justification: This feature improves the product significantly especially for the deletion of expense. Since money is a sensitive issue, the soft deletion of expense allows the expense to still be visible but striked-off so it remains as a history for accountability.

    • Highlights: This enhancement affects existing commands and commands to be added in future. The implementation was challenging due to the fact that it depends on the user’s screen.

  • Code contributed: Functional and test codes

  • Other contributions:

    • Enhancements to existing features:

      • Enhanced delete command to delete contacts, activities, expenses based on displayed screen (Pull requests #196)

      • Implemented invite and disinvite command to invite or disinvite participants from current viewed activity (Pull requests #121, #108)

      • Wrote additional tests for delete, invite and disinvite (Pull requests #196, #121, #108, #136)

    • Community:

      • PRs reviewed (with non-trivial review comments): 190, 23

      • Reported bugs and suggestions for other teams in the class (examples: 4, 1, 5, 6, 3, 2)

Contributions to the User Guide

Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users.

Inviting contacts to an activity: invite

This command invites the contacts specified to the current viewed activity.

Format: invite p/PERSON …​

Example:
Suppose you have already created an activity with Alice, Bob and Carl in it.
activity t/Holiday Trip p/Alice p/Bob p/Carl

And you have friends that want to join an activity midway.

To invite:

Step 1: Type invite into the command box and specify the contacts you want to invite from the contact list with the p/ prefix e.g. invite p/Mary p/John p/Carl and press Enter to execute it.

InviteCommand

Step 2: Observe the output in result box and the activity details box.

InviteOutput
The invite command only invites to current viewed activity.
if there is no current viewed activity, there will be an error.

The invite command only invites contact that exists in the contact list.
If the specified contact does not exist in the contact list, then the contact cannot be added and a warning message will be shown.

Multiple contacts can be invited at once.

Contact that already exists in activity cannot be invited again.

Disinviting contacts from an activity: disinvite

This command disinvites the contacts specified from the current viewed activity.

Format: disinvite p/PERSON …​

Example:
Suppose you have an activity with the same participants but with an expense shared by Alice, Bob and Carl

DisinviteExample

And you feel that the activity has too many participants that do not participate in any event, thus having no shared expense and you decided to remove them.

To disinvite:

Step 1: Type disinvite into the command box and specify the contacts you want to disinvite from the activity with the p/ prefix e.g. disinvite p/Mary p/John p/Carl and press Enter to execute it.

DisinviteCommand

Step 2: Observe the output in result box and the activity details box.

DisinviteOutput
The disinvite command only disinvites from current viewed activity.
if there is no current viewed activity, there will be an error.

The disinvite command only disinvites contact that exists in the activity.
If the specified contact does not exist in the activity, then a warning message will be shown.

Multiple contacts can be disinvited at once.

Contact that involves in any expense cannot be disinvited.
If a contact is involved in any expense, he cannot be disinvited.

Deleting a contact, activity or expense: delete

Deletes the contact/activity/expense at the specified index from the current display.

Format: delete INDEX

If current display is listing contacts e.g. list c/, the contact at that specified INDEX will be deleted if he/she is not involved in any activity.

If current display is listing activities e.g. list a/, the activity at that specified INDEX will be deleted.

If viewing an activity instead e.g. view a/1, it will soft-delete the expense* at that INDEX.

If the current display is not any of the above displays mentioned, error will be thrown.

Examples:

  • delete 2
    If viewing the list of contacts, deletes the 2nd person by index if he/she is not involved in any activity.

  • delete 1
    If viewing the list of activities, deletes the 1st activity by index.

  • delete 1
    If viewing a particular activity, fades (soft-deletes) the 1st expense by index.

Deletes the entry at the specified INDEX.

The INDEX refers to the index number shown in the displayed list of contacts/activities/expenses.

The INDEX must be a positive integer 1, 2, 3, …​

Expenses cannot be completely deleted. It will instead be faded (but still visible) in the activity view.

Contributions to the Developer Guide

Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project.

Invite/Disinvite feature

Implementation

The invite/disinvite mechanism is facilitated by Activity. It extends AddressBook with an ActivityBook, stored internally as an activityList. Additionally, it implements the following operations:

  • Activity#invite() — Invites a person to the activity.

  • Activity#disinvite() — Disinvites a person from the activity.

These operations are exposed in the Activity class as Activity#invite() and Activity#disinvite() respectively.

Given below is an example usage scenario and how the invite/disinvite mechanism behaves at each step.

Step 1. The user launches the application for the first time. SplitWiser will be initialized with the initial address book and activity book state.

Step 2. The user executes activity t/breakfast p/David command to create an activity named breakfast with David as the sole participant which is stored in the activityList.

Step 3. The user executes invite p/Louis p/Mary…​ to invite more participants into the current viewed activity. The invite command calls Activity#invite() which then modifies the activityList with the new participants and is stored in the ActivityBook.

The following sequence diagram shows how the invite operation works:

InviteSequenceDiagram
The lifeline for InviteCommand should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.

Step 4. The user decides that inviting some contacts was a mistake or they has not been involved in any of the expenses in the activity. Hence the user decides to remove them from the activity by executing the disinvite command.

Step 5. The user executes disinvite p/Louis p/David …​ to remove participant(s) from the current activity. The disinvite command calls Activity#disinvite() which then modifies the activityList and is stored in the ActivityBook.

The sequence diagram for the disinvite operation is omitted as it is similar to the invite operation.

The following activity diagram summarizes what happens when a user executes an invite command:

InviteActivityDiagram
The activity diagram for the disinvite command is omitted as it is similar to the invite operation.

Design Considerations

Aspect: How invite & disinvite executes
  • Alternative 1 (current choice): Contextual based invite/disinvite based on current viewed activity.

    • Pros: More user-friendly. User does not have to keep specifying which activity to invite the participants to each time an invite command is made.

    • Cons: Harder to implement. Have to consider which activity to invite the participants to based on the current viewed activity.

  • Alternative 2: Invite/disinvite based on user specifying the activity number.

    • Pros: Easy to implement.

    • Cons: Have to keep retyping activity number if multiple invites/disinvites are needed.

Aspect: Data structure to support the invite/disinvite commands
  • Alternative 1 (current choice): Use a list to store the participant’s ID in the activity instead of participant’s name.

    • Pros: Easy for new Computer Science student undergraduates to understand, who are likely to be the new incoming developers of our project.

    • Cons: Have to map participant’s ID to participant’s name. Hard to search for participant’s specific ID when given name.

  • Alternative 2: Use list to store participants instead of ID

    • Pros: Easy to implement. Reuse what is already in the codebase and we do not need to create additional Unique ID key for each participant to identify them.

    • Cons: Might create duplicate person object when reading from multiple json files if not implemented properly.

Delete feature

Implementation

The delete mechanism is facilitated by AddressBook, ActivityBook, as well as Activity.
The items that will be deleted can be contact/activity/expense depending on your current display.

Given below is an example usage scenario and how the delete mechanism behaves at each step.

Step 1. The user launches the application for the first time. SplitWiser will be initialized with the initial address book and activity book state.

Step 2. The user executes list c/ command to display list contacts screen.

Step 3. The user executes delete 1 to delete the contact at the first index, he/she will be deleted if he/she is not involved in any activity.

Step 4. The user executes list a/ to display list activities screen.

Step 5. The user executes delete 1 again, but this time the activity at the first index will be deleted instead.

Step 6. The user views an activity at the second index using view a/2

Step 7. The user executes delete 1 again, but this time the expense at the first index will be soft deleted instead.

The following activity diagram summarizes what happens when a user executes a delete command for deletion of activity:

DeleteContactActivityDiagram
The activity diagram for deletion of expense and contact are omitted as they are similar to the deletion of activity.

Design Considerations

Aspect: How delete executes
  • Alternative 1 (current choice): Contextual based delete of contact/activity/expense based on current displayed screen.

    • Pros: More user-friendly. User does not have to keep specifying what field to delete.

    • Cons: Harder to implement.

  • Alternative 2: Delete based on user specifying which field to delete.

    • Pros: Easy to implement.

    • Cons: Have to keep retyping the field for deletion which is inconvenient.