PROJECT: TheTracker (v1.4)


Summary of contributions

  • Major enhancement: Improved delete function to properly delete any type of entry

    • Description: Allows the user to delete a person, module or occasion by index. It also removes this entry from all other linked entries.

    • Design Decisions: In implementing the feature, I decided to incorporate the following:

      • Inferred Deletion: The deletion will be applied to the currently active list.

      • Deep Deletion: The deletion will automatically all references to this entry (i.e. from other entries' lists)

    • Highlights: Inferred deletion required amendments in the model and UI. This was also useful in implementing the select command.
      Deep Deletion required the writing of methods that selectively mutates entries in a list. The methods were used in the edit, insertperson and removeperson commands.

  • Minor enhancement: Implemented the select feature

    • Description: Allows the user to select an entry from the active list, and view their list info.

  • Code Contributed: Link to Code Contributions

  • Project management:

    • Involved in distributing roles and consolidating tasks

    • Manage Issue Tracker for v1.3, v1.4

  • Community:

    • PRs reviewed (with non-trivial review comments): #81, #87

    • Set up test utils for modules and occasions: #97, #109

  • Documentation:

    • Wrote user stories, use cases for v1.0

    • Updated description of user guide to match application design

  • Key Code Components

    • Set up Module class and its associated fields/exceptions

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.

GUI Components

This section explains the components of the GUI, along with some ways you can interact with it.

Layout

TheTracker’s GUI is divided into 5 main regions that you will interact with:

GUIComponents
Figure 1. TheTracker’s GUI
  1. Menu Bar: contains simple commands to switch between windows

  2. Command Box: text box (equipped with auto-suggestions) to receive input commands

  3. Result Display: panel that displays the result of inputted commands

  4. List Panel: panel displaying all saved persons/modules/occasions

  5. Info Panel: panel displaying additional information for selected entry

Using the GUI

  • Switching between person, module and occasion lists can be done from the Menu Bar by clicking on the desired type, followed by "Show Persons/Modules/Occasions". You can also view these using the listperson, listmodule and listoccasion commands in the Command Box.

  • Clicking on an entry in the List Panel selects the entry. This allows you to see its additional info in the Info Panel. Selecting an entry can also be done by using the select command in the Command Box.

Types of Entries

This section explains the three types of entries - person, module and occasion.
Each of them contains a compulsory field, optional fields, optional tags and relevant lists as explained below.

Shared: Tags

All three types of entries contain the following fields:

  • Tags - One or more alphanumeric strings (A-Z, 0-9), with no limit on length.
    Note: An entry can have 0 or any positive number of tags.
    Valid: Friend, CS2103, Must RSVP
    Invalid: Buddy!, CS2103:(, 25/12/2018

Person

A Person has the following fields:

  • Name (compulsory) - One or more alphanumeric strings, with no limit on length.
    Valid: Ashwin Raj, Damith Rajapakse, Bob12345
    Invalid: Ashwin Raj S/O Yadav, Damith C. Rajapakse, Bob12345!!!

  • Phone Number - 3 or more digits (0-9), with no limit on length.
    Valid: 999, 1800123456, 659192939495
    Invalid: 9, 1800 123456, +659192939495

  • Email - A single string with an @ character in between the username and domain name.
    Username can contain the following special characters: !#$%&'*+/=?{|}~^.-
    Domain name should be at least 3 letters long.
    Valid: alex@abc, bob123@xyz.com, example!123@nus.edu.sg
    Invalid: alex, bob@co, example@123@nus.edu.sg

  • Address - Any non-blank input, with no limit on length.
    Valid: NIL, Singapore, 123 Clementi Ave 999 S(654123)

A person will also have a module list and occasion list. These are comprised of modules and occasions that are currently in the address book.
These lists will be initialized as empty until modules or occasions are added.

Warning: Persons with the same name are permitted as long as they have a different phone number or email address.
Use with caution, as they may be difficult to distinguish (e.g. in a module’s registration list).

Module

A Module has the following fields:

  • Module Code (compulsory) - 2 or 3 letters, followed by 4 digits and an optional letter behind.
    Note: Does not check whether the module is an actual NUS module.
    Valid: CS2103, CS2103T, GER1001
    Invalid: CS210, CS2103AB, GER10000

  • Module Title - One or more alphanumeric strings, with no limit on length.
    Note: Does not check whether the module title matches the module code.
    Valid: Software Engineering, Programming Methodology, A very annoying module
    Invalid: Software Engineering!, Object-Oriented Design, ARGH:o

  • Academic Year - 4 digit number, with the first and last 2 numbers representing consecutive years.
    Valid: 1819, 9900, 0001, 0304
    Invalid: 123, AY1819, 18/19, 2018

  • Semester - 1 digit number between 1 and 4.
    Remark: Semesters 3 and 4 are used to refer to Special Term I and II.
    Valid: 1, 2, 3, 4
    Invalid: Sem 1, 01, 1819/1

A module will also have a person list. This will be consistent with the persons in the list (i.e. the module will appear in their module lists).

Warning: Modules with the same code are permitted as long as they have a different academic year or semester.
Use with caution, as they may be difficult to distinguish (e.g. in a person’s module list).

Occasion

An Occasion has the following features:

  • Occasion Name (compulsory) - One or more alphanumeric strings, with no limit on length.
    Valid: Project Discussion, CS2103 Exam, Recess Week
    Invalid: Ad-hoc Work, Meeting**, Friend’s Birthday

  • Occasion Date - Date in YYYY-MM-DD format.
    Remark: Checks whether date is valid.
    Valid: 2018-11-13, 2000-02-29, 2010-10-31
    Invalid: 2018/11/13, 2001-02-29, 2010-09-31

  • Occasion Location - One or more alphanumeric strings, with no limit on length.
    Valid: Home, NUS COM1, 123 Clementi Rd
    Invalid: John’s Home, NUS COM1 02-18, 123 Clementi Rd S(654123)

An occasion will also have a person list. This will be consistent with the persons in the list (i.e. the occasion will appear in their occasion lists).

Warning: Occasions with the same name are permitted as long as they have a different date.
Use with caution, as they may be difficult to distinguish (e.g. in a person’s occasion list).

Deleting an entry: delete

A command to allow the user to delete the specified entry from the active list in TheTracker.
Format: delete INDEX

  • Deletes the entry at the specified INDEX shown. The index refers to the index number shown in the List Panel.

  • The index must be a positive integer: 1, 2, 3, …​

  • The specified entry will be removed from all linked entries. For example, a deleted person will be removed from the student list of all modules.

Examples:

  • listperson
    delete 1
    Deletes the 1st person in TheTracker.

  • listmodule
    findmodule sem/1
    delete 2
    Deletes the 2nd module of the find command.

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.

Design Considerations

Aspect: Implementation of Dependencies
  • Alternative 1 (current choice): Have 3 separate classes for Person, Module and Occasion

    • Pros: Each class can be designed specifically to accommodate suitable fields

    • Cons: Some code duplication in similar methods

  • Alternative 2: Have a parent Entity class, with all three classes inheriting from it

    • Pros: Polymorphism can be implemented for similar methods

    • Cons: Difficulty in implementation, (e.g. UniqueEntityList must be implemented in the model and EntityCard, EntityListPanel in the UI).

  • Decision: Alternative 1 was adopted, as the 3 classes do not have the exact same features. For example, a Person has 2 separate lists of Modules and Occasions respectively, but a Module or Occasion only contains a Person list.

Updating of Lists

When executing commands for a particular type of entry, another type of entry can modified.

Naturally, insertperson and removeperson will affect a person and a module/occasion.
However, both edit and delete also can affect multiple types of entries.

  • If an entry is edited, all linked entries should reflect the changes accordingly.

  • If an entry is deleted, all linked entries should remove this entry from their list.

Current Implementation

To facilitate the execution of undo and redo, a new replacement person, module or occasion is created to replace the original entry. By avoiding modification of these entries, previous versions of the ReadOnlyAddressBook will not be incorrectly modified.

Currently, a list only stores a copy of the desired entries, instead of the actual entries.

Suppose that a person needs to be edited/deleted. Then correctly implementing any of these commands requires 3 stages:

  1. Locate all linked modules and occasions

  2. Replace each module and occasion with an updated version

  3. Edit/Delete the person

Methods for the implementation of 1 and 2 are contained in the AttendanceListUtil class.
The code snippets below are extracted with slight modifications, and are used to perform 1 and 2 by updating the person lists in modules after deleting a Person.

while (moduleListIterator.hasNext()) {
    Module module = moduleListIterator.next();
    module.getStudents()
            .asNormalList()
            .stream()
            .filter(person -> person.isSamePerson(personToRemove))
            .findFirst()
            .ifPresent(removePersonFromModule(model, module));
}
  • The above loop iterates through all modules.

  • For each module, it filters through its studentList to determine whether it should be edited.

  • If so, the person is removed from the module.

private static Consumer<Person> removePersonFromModule(Model model, Module module) {
    return person -> {
        List<Person> updatedPersons = module.getStudents().makeShallowDuplicate().asNormalList();
        updatedPersons.remove(person);
        UniquePersonList updatedPersonList = new UniquePersonList(updatedPersons);
        ModuleDescriptor updatedModuleDescriptor = new ModuleDescriptor();
        updatedModuleDescriptor.setStudents(updatedPersonList);
        Module updatedModule = Module.createEditedModule(module, updatedModuleDescriptor);
        model.updateModule(module, updatedModule);
    };
}
  • In turn, removing a person from a module is done by creating a new list of persons, excluding the one pending deletion.

  • A new module is then created based on the original module and this new list.

  • Finally, the new module replaces the original module in the model.

Similar implementations are used for both delete and edit in the various combinations of entries and lists.

Delete

Current Implementation

The delete command will delete a Person, Module or Occasion. Similar to other commands, a new ReadOnlyAddressBook is created upon the execution of this command.
It can then be accessed within the VersionedAddressBook when executing undo or redo.

The sequence diagram below (reproduced from [Design-Logic]) shows that the high-level implementation is similar to the earlier commands.

DeletePersonSdForLogic

However, the current implementation also allows for 2 useful functionalities in this feature:

  • Inferred Deletion: As we maintain the active type, the deletion will be applied to the currently active list.

  • Deep Deletion: By updating the associated lists, all references to this entry can be removed (i.e. from other entries' lists).

The following activity diagram gives a broad overview of the deletion process:

DeleteActivityDiagram

In performing deep deletion, almost all "related" objects are copied.

DeleteDeleteCommandStateListDiagram

For example, suppose TheTracker is initialised in the following manner:

  • 2 Persons p1, p2 and 2 Modules m1, m2 are created

  • p1 is inserted into m1, m2

  • p2 is inserted into m1

DeleteSequenceDiagram

The current object diagram can be drawn as follows (unnecessary fields omitted):

DeepDeletionObjectDiagramBefore

After deleting p1, the new object diagram will be:

DeepDeletionObjectDiagramAfter

Notice that:

  • p1 and its UniqueModuleList is deleted

  • p2 is not affected

  • A new version of m1 is created. It has a new UniquePersonList, which contains a new copy of p2 (copied from p2Copy1)

  • A new version of m2 is created. It has a new UniquePersonList which is empty.

Design Considerations

Aspect: Explicit/Implicit Deletion
  • Alternative 1 (Current Implementation): Check the active type from the model, and delete from the list.

    • Pros:

      • User can use delete instead of typing deleteperson, deletemodule or deleteoccasion in full.

      • User is explicitly prevented from deleting entries from an inactive list

    • Cons:

      • Harder to implement.

  • Alternative 2 : 3 commands deleteperson, deletemodule and deleteoccasion to delete from the respective list.

    • Pros:

      • Easier to implement

    • Cons:

      • User may delete from the wrong list without realising

      • Inconvenient for user to type out full command

Aspect: Deletion by Index/Fields
  • Alternative 1 (Current Implementation): Delete entries by index

    • Pros:

      • User can easily identify the index from the List Panel

      • User can use the same command for all 3 lists

    • Cons:

      • User needs to user a find command first if he cannot find the entry

  • Alternative 2: Delete entries by field (e.g. delete n/john)

    • Pros:

      • User can find an entry and delete them currently

    • Cons:

      • Have to decide what to do if multiple entries satisfying the condition are found

      • User has to remember prefixes in order to delete an entry

Aspect: Shallow/Deep Deletion
  • Alternative 1 (Current Implementation): Deleted entry is removed from all linked entries

    • Pros:

      • User can completely remove an entry from all mentions in TheTracker

      • removeperson implementation does not need to check whether an entry still exists in the address book

    • Cons:

      • Difficult to implement

  • Alternative 2: Only allow entries that are not referenced to be deleted

    • Pros:

      • User will not accidentally delete an entry that is used

    • Cons:

      • User must manually use the removePerson command to eliminate all references

      • Difficult to implement

  • Alternative 3: Deleted entries can remain in all linked entries

    • Pros:

      • Easy to implement

      • User can keep archival information for an entry

    • Cons:

      • Very tedious to remove all mentions of an entry after it has been deleted

      • User may be misled that an entry still exists