PROJECT: Naggy Joel


Overview

Naggy Joel is a desktop application for University students who wish to manage their social life as well as their school assignments. While Naggy Joel understands the importance of maintaining a social life, Naggy Joel also understands that school assignments should come first! The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java.

Summary of contributions

  • Major enhancement: added the ability to add/delete/edit Events

    • What it does: allows the user to add/delete/edit their events (eg. social events).

    • Justification: This feature improves the product significantly because a user can log their events, delete events if there have been cancellations, or edit events if they have made mistakes in commands and the app should provide a convenient way to rectify them using the edit function.

    • Highlights: The implementation was challenging because I had to integrate this with the existing features (like the Schoolwork Tracker). For instance, I added a warning to be thrown when the user adds an Event on the same day as which an assignment is due, to warn the user that they ought to prioritize the assignment if it isn’t completed yet, and to prompt the user to reconsider if going to such an event is necessary if they do not have time to complete their schoolwork.

    • Credits: -

  • Major enhancement: added the ability to find Restaurants and Persons

    • What it does: allows the user to find specific people in the address book and specific restaurants in the restaurant tracker.

    • Justification: This feature improves the product significantly because it allows people to find specific restaurants or people in the app (if the user have many contacts and many restaurants logged down, it makes it easier to the user to pick out the specific contact/restaurant that they want).

    • Highlights: This enhancement required in-depth knowledge of the Java Predicate because the existing code base had been using Predicates. Furthermore, since one Person could have multiple tags and our find command allows for searching via tags, the implementation was challenging as it required me to come up with a way to manipulate using one Predicate’s keywords to search against multiple fields (unlike other Predicates, which usually check their keywords against one field like a Person’s Name).

    • Credits: -

  • Minor enhancement: Added in the GUI display for the Event Schedule (so a person can see what events they have upcoming).

  • Code contributed: [Summary of code contributions]

  • Other contributions:

    • Enhancements to existing features:

      • Added in the Organization field of a person, allowing them to be tagged to a specific Organization.

    • Documentation:

      • Contributed to both the Developer Guide and User Guide for this project.

      • Did cosmetic tweaks to existing contents of the User Guide: #154

    • Community:

      • PRs reviewed (with non-trivial review comments): #152

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

    • Tools:

      • Integrated Travis with the team repo

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.

Event Schedule commands

Create a new social event : (ev)add

Creates a social event.
Format: (ev)add t/EVENT_TITLE d/EVENT_DATE h/DURATION p/PLACE

  • EVENT DATE must be in a YYYY-MM-dd HH:mm format

Examples:

  • (ev)add t/Facebook job interview d/2020-10-18 10:00 h/3 p/Facebook APAC HQ
    Adds a new social event with title "Facebook job interview", event date 2020-10-18, duration of 3 hours and place of event at "Facebook APAC HQ".

Edit a social event : (ev)edit

Allows editing of a social event.
Format: (ev)edit INDEX [t/EVENT_TITLE] [d/EVENT_DATE] [h/DURATION] [p/LOCATION]

  • INDEX must be a positive integer. It corresponds to the INDEX of the event as shown when you list all events in the Event Schedule using the default event list function (see above).

  • At least one field must be non-empty.

  • All the non-empty fields will replace their respective previous data fields.

Examples:

  • (ev)edit 2 d/2020-10-09 22:00 h/2
    Edits the 2nd event in the Event Schedule by changing the timing to 10PM on the 9th of October and the estimated duration to be 2 hours.

Deletes a social event : (ev)delete

Deletes a social event.
Format: (ev)delete INDEX

  • INDEX must be a positive integer. It corresponds to the INDEX of the event as shown when you list all events in the Event Schedule using the default event list function (see above).

Examples:

  • (ev)delete 1
    Deletes the 1st Event in the Event Schedule.

Listing all events : (ev)list

Lists all social events in your Event Schedule.
Format: (ev)list

Finding contacts : (ab)find

Lists out all your contacts in the address book which match a certain criteria. Each contact will have a displayed index. Only the contact’s name, phone number and tags (if present) will be listed
Format: (ab)find [o/ORGANIZATION] [n/NAME] [t/TAG]

  • If more than 1 switch is indicated, it will be treated as a conjunction of filters

  • [o] [t] List all contacts from a particular organization with the particular tag

Examples:

  • (ab)find o/NUS n/Lim
    Finds and lists all contacts that is in organization “NUS” and have the word “Lim” in his name

Find restaurants : (rt)find

Finds restaurants based on a number of criteria.
Format: (rt)find [n/RESTAURANT_NAME] [l/LOCATION]

  • At least one search criteria must be filled in.

  • All are case insensitive.

  • If more than 1 optional parameters are filled, they are viewed as a conjunction of filters

Examples:

  • (rt)find n/no signboard
    Finds restaurants with the keyword no signboard.

  • (rt)find l/bedok
    Finds restaurants in the Bedok area.

  • [COMING SOON] Ability to search by price point and operating hours.

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.

(Chua Xinhui Sarah: 3.6)

Finding Contacts

Implementation

The finding of a Person is facilitated by the Address Book. This feature allows for users to find a specific contact in their Address Book.

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

Step 1: The user launches the application for the first time. The Address Book will be initialized with the initial state, which is an empty list.

Step 2: The user executes the (ab)add n/Joel …​ command multiple times with different details of different people to add multiple people as contacts into the Address Book.

Step 3: The user executes the (ab)find …​ command to find their desired contacts in the AddressBook list. For instance, the user may do: * (ab)find o/NUS searches by organization. * (ab)find n/Joel Lim searches by name. * (ab)find t/friends searches by tags.

The following sequence diagram shows how the find operation works within the Logic component.

findPersonMain
findPersonRef

Design Considerations

Aspect: How to execute the command for finding a contact using Java Predicates, given that a Person has multiple tags.

Current implementation of Predicates uses the stream and anyMatch commands to check each keyword against one single word, but since a person may have multiple tags, the implementation needs to be able to check each keyword against multiple tags instead of a single tag.

  • Alternative 1 (chosen): Concatenate all the tags of a person together into a String, and check the provided tag keywords against that one String.

    • Pros: Easier to implement.

    • Cons: -

  • Alternative 2: For each person’s unique tags, create one Tag Predicate per tag.

  • Pros: Conceptually easier to understand, as well as to draw the UML diagram.

  • Cons: Many Tag Predicate objects would have to be created. This could be messy and cause debugging to be difficult.

Aspect: How to sort the provided keywords into different Predicates given that there are multiple fields we can search against (eg. Organization, Name, etc)
  • Alternative 1 (chosen): Have a loop to parse the keywords and sort them into different Predicate keyword lists depending on where the prefixes are located. For instance, if the user types (ab)find t/friends colleagues o/NUS, then the keywords friends and colleagues would to go to the Tag Predicate while the keyword NUS would be allocated to the Organization Predicate.

  • Pros: Easier for the user because they just have to demarcate which keywords are used for which using a single prefix.

  • Cons: More difficult to implement.

  • Alternative 2: Have the user include the prefix before every different keyword they want to search. For instance, if they want to search using 2 different tag keywords like "friends" and "colleagues", they would have to type (ab)find t/friends t/colleagues. Then we can use the Argument Multimap to tokenize the arguments.

  • Pros: Easier to implement.

  • Cons: More troublesome for the user because if they want to search for multiple tags, they would have to keep typing the /t prefix for each keyword.