PROJECT: CoderLifeInsights

CoderLifeInsights (CLI) is a desktop application that provides you insights and suggestions to your social life as a programmer using a CLI (Command Line Interface)


My Role

I am responsible to complete the features related to group and overall system design. Furthermore, I’ve worked extensively on the storage package and developed the JSON implementations for group and event classes. I have also made notable contributions to the User Guide and Developer Guide.

Summary of contributions

Major enhancements:

  • Major enhancement #1: Implemented group features - add_group, delete_group, edit_group and list_groups

    • What they do: They allow the user of CoderLifeInsights to add a social group, delete a social group or edit the group for adding/removing members or changing the name of the group. The list_group command lists all the groups in the app. It was planned and implemented in anticipation of a find_group command in the future that could change the group list view in the app.

    • Justification: A social group is a crucial aspect of the CoderLifeInsights app as it allows the users to distinguish between time spent in group interactions and individual, one-to-one interactions. The group features are essential to record and track data regarding social groups. The commands are implemented similar to add_person, delete_person and edit_person features of the addressbook3 due to the clear design and defensive programming style.

    • Highlights: This enhancement functions well with existing commands and adds a crucial ability to add social groups. It required an in-depth analysis of design alternatives.

    • Credits: As highlighted above, the group features take inspiration from the person features of addressbook3. Thus, credits go to the previous developers of addressbook3 for the system design and class structures.

  • Major enhancement #2: Implemented storage features - JSON Implementations for Event and Group

    • What it does: JSON implementations allow the app to store and retrieve data from file. This is crucial as the app is not expected to always run and needs to store data in the hard disk.

    • Justification: Using the JSON implementations, the app can go back to its last state when a user re-launches the app.

    • Highlights: This enhancement required an in-depth understanding of JSON and Java Data structures in order to convert between Java Classes such as Group and Event and JSON implementations which stored strings.

Minor enhancements:

  • Minor enhancement #1: Implemented Unique Event List

    • What it does: Stores unique Event instances

    • Justification: Since events are crucial to social interactions, storing events is important for the purpose of tracking.

    • Highlights: This enhancement required an in-depth understanding of the JavaFX Observable class.

  • Minor enhancement #2: Implemented Time Class

    • What is does: Allows the user to store a specific time spent in terms of number of hours and minutes.

    • Justification: The constraints the in the class allow for efficient management of time format, which suites the customised need of the app.

    • Highlights: This enhancement functions well with all the classes that depend upon it and use it. This required a thorough understanding of the different use cases.

  • Code contributed:[tP Dashboard]

  • Functional Code Contributed:

  • Test Code Contributed:

  • Other contributions:

    • Project management:

      • Initiated group meetings and set policies for Pull Requests

      • Opened issues on Github repo to account for bugs and enhancements. Some relevant/important issues: #162, #161, #129, #130.

    • Enhancements to existing features:

      • Updated command words for existing features in order distinguish between person and group commands.

    • Documentation:

      • Added contents of the User Guide (Pull requests: #96, #54, #175)

      • Added contents of the Developer Guide (Pull requests: #26, #76, #167, #174)

    • Community:

    • Tools:

      • Integrated Codacy to automate code quality checks

      • Used Creately to create initial class diagrams to visualise the relationship between Objects (Person, Group, Event) and their UniqueLists. The diagram can be viewed here.

    • Rough UI:

      • To visualise the app UI before actually creating it, I used Sketch App to create a rough UI of the app. The team used the rough UI as a guide. The UI can be viewed here.

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.

Adding a Group: add_group

[written by: Raivat Bhupesh Shah]

Creates an empty social group with given name.
Format: add_group n/GROUP_NAME m/MEMBER_IDs …​

A group can have any number of member_ids (including 0)
  • 1 required parameter (group_name)

  • CoderLifeInsights will create a new group and show a uniquely generated Group ID for the same.

  • Member_IDs will be added to the group and displayed if supplied while creating the group.

Examples:

Example Command Result

Create a group

add_group n/SoC Friends

Creates a group named SoC Friends and assigns a group ID, which is shown to the user.

Create a group and add members into that group

add_group n/RC Friends m/1 m/2 m/3

Creates a group named RC Friends and assigns a group ID and the given memberIDs to the group. Both are displayed to the user after creation.

Editing a Group: edit_group

[written by: Raivat Bhupesh Shah]

Edit a group with a given group index
Format: edit_group GROUP_INDEX n/GROUP_NAME m/MEMBER_IDs

  • CoderLifeInsights will edit the group with given index to change the name to supplied name and change the list of members to the ones supplied. Either a new name or new member(s) is required to edit the group.

Examples:

Example Command Result

Change name of 1st group

edit_group 1 n/FOS

Changes the name of the group with index 1 in CoderLifeInsights to FOS from whatever it was before. Name overwritten, memberIDs remain the same as before.

Edit the members in the 1st group

edit_group 1 m/1 m/5

Changes the members of the group with index 1 in CoderLifeInsights to 1 and 2 from whatever it was before. Member list overwritten, Name stays the same.

Change the name and members of the first group

edit_group 1 n/new_name m/1

Changes both the name and members of the group with index 1 in Coder Life Insights. Both values overwritten.

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.

Add Group Feature

[written by: Raivat Bhupesh Shah]

Implementation

The Add Group feature is implemented to allow users to track social activities with a group of people (instead of just one person). A Group represents a social group containing 1 or more Person. To avoid dependencies, a Group class stores the index of a Person instead of the Person object itself. A Group can be created with or without Person as member(s), but must have a Name.

This feature creates a new Group instance, which is then stored in an instance of UniqueGroupList, which in turn is stored in the AddressBook. These classes are part of the model component.

The feature is supported by the AddGroupCommand class, which extends the abstract class Command and AddGroupCommandParser, which implements the Parser interface. These classes are part of the logic component.

The following class diagram showcases the relationship between the main classes that support this command and key attributes and methods:

][pdfwidth="50%"

Here below is an example usage scenario and how the add_group feature works at each step:

  1. User enters add_group n/group_name or add_group n/group_name m/index …​ into the app.

  2. The request is handled by the LogicManager#execute(String), which then calls and passes the input to the AddressBookParser#parseCommand(String) method.

  3. AddressBookParser detects the command word add_group in the input string and creates an AddGroupCommandParser to parse inputs according to the format specified for AddGroupCommand.

  4. AddGroupCommandParser parses the input and also performs input validation to check for correct types (eg alphanumeric characters for Name and Integer for memberIDs) using the AddGroupCommandParser#parse(String) method.

  5. AddressBookParser#parse(String) calls the constructor of Group and creates a new Group instance with the inputs from the user. It creates a new AddGroupCommand and passes the newly created Group to it.

  6. AddressBookParser returns the new Command object to the AddressBookParser, which in turn returns it to LogicManager.

  7. LogicManager calls the AddGroupCommand#execute(model) method

  8. The AddGroupCommand#execute(model) method obtains a copy of the FilteredPersonList from Model using the Model#getFilteredList() method. Using the list, the method verifies if the member indexes in the Group instance exist in the Person list.

  9. the AddGroupCommand adds the group to the app by calling the Model#addGroup(Group) method.

  10. As a last step, the AddGroupCommand creates a CommandResult with SuccessMessage and ViewType and returns it to LogicManager.

The process is shown in the following sequence diagram:

AddGroupSequenceDiagram

Delete Group Feature

[written by: Raivat Bhupesh Shah]

Implementation

The Delete Group feature allows the user to delete a previously Group. This feature is implemented using the DeleteGroupCommand, which extends the abstract class Command and the DeleteGroupCommandParser, which implements the Parser interface.The feature is also supported by UniqueGroupList, which stores the Group instances. The relationship between classes is similar to the one seen in diagram x.x and hence is omitted for conciseness.

Here below is an example workflow, which is shown using an activity diagram:

[pdfwidth="50%"

The above workflow is achieved due to the interlinked classes. Their behaviour during an execution of the DeleteGroup feature is shown using the following Sequence Diagram.

DeleteGroupSequenceDiagram

Design Considerations

Aspect: how the delete group feature executes

  • Alternative 1 (current choice) : Separate DeleteGroupCommand and DeleteGroup classes to support the feature.
    Pros: clear class responsibility, easier to trace bugs. Since this follows the design of most other commands, intuitive to understand for new developers
    Cons: increases the amount of code, which might introduce more errors.

  • Alternative 2: The DeleteGroupCommand class parses the inputted index
    Pros: Since only one argument to parse, this eliminates the need for another class. Less code. Cons: Can cause confusion among developers regarding the class responsibility. === List Group Feature [written by: Raivat Bhupesh Shah]

The list group feature allows users to view all the Group instances currently stored in CoderLifeInsights.

Implementation

This feature is mainly supported by the ListGroupCommand, which extends the abstract class Command.

Here below is a sequence diagram showcasing how the command works.

ListGroupSequenceDiagram

The following is an example usage scenario and how the list group mechanism behaves at each step.

  1. User enters list_groups into the command prompt

  2. The LogicManager calls AddressBookParser#parseCommand() with the arguments supplied by the user

  3. The method AddressBookParser#parseCommand() checks if the input is valid and if yes, creates a ListGroupCommand.

  4. The ListGroupCommand calls the updateFilteredGroupList method of Model to update the GUI.

  5. The ListGroupCommand returns the CommandResult to AddressBookParser

  6. The AddressBookParser returns the CommandResult to LogicManager.

The following activity diagram summarises the workflow for the list group feature.

ListGroupCommandActivity

Edit Group Feature

[written by: Raivat Bhupesh Shah]

The Edit Group Feature allows the user to edit an existing Group in the app.

Implementation

The Edit Group Feature is facilitated by the EditGroupCommand, which extends the abstract class Command, and the EditGroupCommandParser, which implements the Parser interface. Both of these classes are part of the Logic component. Additionally, a private and static EditGroupDescriptor class is present in EditGroupCommand as a container class to encapsulate attributes to be edited for a Group.

he following operations are implemented and used for accomplishing this feature:

  • EditGroupCommandParser#parser(String args) - Parses the input to obtain the arguments and returns an EditGroupCommand instance with the arguments.

  • EditGroupCommandParser#arePrefixesPresent(ArgumentMultimap argumentMultiMap, Prefix…​ prefixes) - checks if the member indexes are supplied by the user.

  • EditGroupCommand#EditGroupCommand(Index index, EditGroupDescriptor editGroupDescriptor) - Creates a new EditGroupCommand instance with the supplied index and editGroupDescriptor.

  • EditGroupCommand#createEditedGroup(Group groupToEdit, EditGroupDescriptor editGroupDescriptor) - Modifies the given groupToEdit with the details given in editGroupDescriptor.

The following is an example usage scenario and how the edit group mechanism behaves at each step:

  1. User types edit_group index n/new_name or edit_group index m/index …​ into the app.

  2. The request is handled by LogicManager#execute(String), which then calls and passes the input to the AddressBookParser#parseCommand(String) method.

  3. AddressBookParser detects the command word edit_group in the input string and creates a new EditGroupCommandParser to parse inputs according to the format specified for EditGroupCommand.

  4. Input is parsed using the EditGroupCommandParser#parse(String) method, which also performs input validation. The method creates a EditGroupDescriptor using the parsed inputs by calling the static constructor inside EditGroupCommand.

  5. The EditGroupCommandParser creates a new EditGroupCommand instance with the given index and newly created EditGroupDescriptor object and returns it to AddressBookParser, which in turn returns it to LogicManager.

  6. LogicManager calls the EditGroupCommand#execute(model) method.

  7. EditGroupCommand obtains a copy of the FilteredPersonList by calling the Model#getFilteredPersonList() method. This is used to check if the member indexes supplied by the user exist in the app and that there are no duplicate person indexes in the command.

  8. EditGroupCommand edits the group at given index by calling its own private static method EditGroupCommand#createEditGroup(Group, EditGroupDescriptor).

  9. EditGroupCommand obtains a copy of the FilteredGroupList by calling the Model#getFilteredGroupList() method. This is used to check if the edited group already exits in the app.

  10. As a last step, EditGroupCommand creates a CommandResult with SuccessMessage and ViewType and returns it to LogicManager.

The above process is shown in the following sequence diagram:

EditGroupSequenceDiagram

The following activity diagram summarises the general workflow for the Edit Group Feature

][pdfwidth="60%"

Design Considerations

Aspect: What and how to edit

  • Alternative 1 (current choice): Only edit parameters that are supplied. For the parameters that are supplied, overwrite the existing entry.

    • Pros: The single edit group feature can achieve both addition and deletion of members as well as renaming of the group. Better maintainability of code.

    • Cons: Overwriting all existing entries might affect usability as the user will have to re-enter the current member indexes if they want to add to member indexes rather than delete.

  • Alternative 2: Only edit parameters that are supplied. For the parameters that are supplied, add to the existing entries instead of overwriting.

    • Pros: The user will not have to re-enter member indexes if they choose to retain members inside a group.

    • Cons: Will require implementing a separate command to then delete member indexes from a group. This can also confuse the user if there are too many commands.

  • Alternative 3: Edit all parameters. Overwrite all existing entries.

    • Pros: Simplest to implement in terms of code. Will require less code than alternative 1 and 2.

    • Cons: Cumbersome for the user as they have to enter an attribute value even if they don’t want to change it.