PROJECT: ConTAct


Overview

ConTAct is an application designed to help teaching assistants manage the details of their students. 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: Ability to add students to a temporary group and perform batch operations on the group

    • What it does: allows the user to create temporary groups of students and manipulate these groups using set operations (union, intersection) and run commands on groups of students instead of one by one

    • Justification: This enhancement saves time and improves productivity as the user only has to run one command for each batch, instead of one command for every student

    • Highlights: Greatly improves usability. Enhances other commands/features.

  • Code contributed: Link

  • Other contributions:

    • Minor enhancement: added a tag command to update tags of a group of students

    • Project management:

      • Maintain issue tracker

      • Populate SampleData

      • Assist GUI redesign

      • Review team pull requests

      • Assist team in debugging other features

    • Enhancements to existing features:

      • added ability to find by tag

    • Documentation:

      • Review other members' documentation and suggest improvements

    • Community:

    • Tools:

      • Tweaked Travis CI build settings to forgive trivial errors (e.g. incorrect alphabetical order of imports will now only give a warning)

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.

Group: group

A Group represents a group of Students in the app. Some commands accept Groups as an alternative to INDEX as a parameter to perform batch operations instead of individual operations.

Group Creation

Format: group [g/grpName] find t/TAGNAME or group [g/grpName] find KEYWORD

This creates a Group containing the Students returned by the find command with the supplied arguments.

group find t/friends will find all students in the Address Book tagged with "friends" and add them to a group.

  • [v2.0] group index INDEX…​ will take a series of indices as arguments and group the students represented by the indices

// assume that the current display shows {Adam, Bob, Charles, Dylan}
group g/grp1 index 1 4
// g/grp1 will then contain {Adam, Dylan} since Adam is index 1 and Dylan is index 4 on the currently displayed list

Named Groups

Groups can be named by using the prefix g/GROUPNAME. If not specified, the name of the created Group will default to "g/default", i.e. group find t/friends is equivalent to group g/default find t/friends

E.g. group g/myGroupName find t/friends will add the Students tagged with "friends" to a Group called "myGroupName"

Note: Group names must be alphanumeric and not contain spaces.

Manipulating Groups

Groups are able to be manipulated to expand or contract the selection to fit the users needs

  • join will take two groups as arguments and create a new group that contains students from either of the groups

// assume that g/grp1 contains {Adam, Bob}
// g/grp2 contains {Bob, Charles}
group g/grp3 join g/grp1 g/grp2
// g/grp3 will contain {Adam, Bob, Charles}
  • and will take two groups as arguments and create a new group that contains only students that are in both of the groups

// assume that g/grp1 contains {Adam, Bob}
// g/grp2 contains {Bob, Charles}
group g/grp3 and g/grp1 g/grp2
// g/grp3 will contain {Bob} since Bob is the only student in g/grp1 and g/grp2
  • [v2.0] complement will take one groups as an argument and create a new group that contains every student except those in the supplied group

// assume that there are a total of 3 entries, {Adam, Bob, Charles}
// and g/grp1 contains {Bob}
group g/grp2 complement g/grp1
// g/grp2 will then contain {Adam, Charles} since Bob is in g/grp1 and will thus be excluded

General format: group [g/DEST_GROUP] <operation> g/OPERANDGROUP1 [g/OPERANDGROUP2]

Note: The first operand is compulsory while the second operand is optional and will default to "g/default"

Displaying Groups

The Students in a Group can be shown in the GUI with the following command:

group [g/GROUPTOBESHOWN] show

Interactions with undo and redo

Due to the way undo and redo are implemented, Groups that are changed as a result of these commands will not behave as expected, the students that are changed will be removed from the Group.

For example,

// g/grp1 contains {Adam, Bob}
delete 1 // delete Adam
// g/grp1 will now only contain {Bob}
undo // restores Adam to the addressbook
// g/grp1 will not be restored to the previous state and will still only contain {Bob}

Reference

(Implemented as of 1.4)

  • group [g/grp1] find <KEYWORD|t/TAG…​> — finds persons matching KEYWORD in their name or matching specified tags and group under grp1

  • group [g/grp1] join g/grp2 g/grp3 — groups the union of grp2 and grp3 under grp1

  • group [g/grp1] and g/grp2 g/grp3 — groups the intersection of grp2 and grp3 under grp1

  • group [g/grp1] show — displays students from grp1 in the GUI

Notes:

  • g/grp1 defaults to default if omitted

Examples:

  • group find t/friends — adds all students with tag t/friends under g/default

  • group g/abc find t/colleagues — groups all students with tag t/colleagues under g/abc

  • group join g/a g/b — groups students in either g/a or g/b under g/default (union of a and b)

  • group and g/a g/b — groups students in both g/a and g/b under g/default (intersection of a and b)

  • group g/test show — shows students grouped under g/test in the GUI

Tag Students: tag

Adds, sets or deletes tags from students (by index or by name).

Format: tag add|set|del index|g/group [t/tags…​]

Examples:

tag add 1 t/tut1 // Adds the tag "tut1" to first person in list
tag set 1 t/tut1 // Removes all tags from first person in list and adds tag "tut1"
tag del 1 t/tut1 // Removes the tag "tut1" to first person in list (does not do anything if supplied tag is not found)

tag add g/students t/cs2103 // Adds the tag "cs2103" to all students in the group named "students"

Note:

  • The command accepts any number of tags (including 0), using tag set with no tags supplied will clear all tags

  • The command will not fail even if the supplied tag is already present in the case of tag add and tag set

  • The command will not fail even if the supplied tag is absent in the case of tag delete

  • The command will still display a success message if the above cases occur

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.

Group feature

A Group allows tutors to manage students easily without typing a command for each student. It is designed to work with the existing Tag system, and designed with commands such as attendance and email in mind. It is session based, meaning that groups are not stored in the data files after the app has closed, and is not intended as a replacement for Tag.

Note: was previously called Mark

Implementation

Each Group represents a collection of unique students, stored with a Set<Student> and exposes getter and setter methods, as well as methods for the manipulation of Groups.

GroupClassDiagram

Groups are maintained by ModelManager, which is responsible for updating, storing and providing the correct Group for commands.

Commands relating to the creation and manipulations of Groups are parsed by GroupCommandParser, which then returns the appropriate GroupSubCommand to be executed. It is designed in this way to be easily extensible in the future as more sub-commands are added.

The commands adhere to the following pattern:

group [g/m1] <subcommand> <arguments>`

The arguments g/m1 may be optional in some cases and default to Group.DEFAULT_NAME

Sub-commands

  • find name — groups Students matched by name

  • find t/tag…​ — groups Students matched by tags

  • join g/m2 [g/m3] — returns union of m2 and m3

  • and g/m2 [g/m3] — returns intersection of m2 and m3

  • show — shows grouped Students in GUI

Note: The base command by itself does not do anything, i.e. group will not do anything but display an error

GroupCommandClassDiagram

Planned Sub-commands (2.0)

  • index <indexes> — groups students by index, separated by space, e.g. group index 1 3 4 5

Execution

The following sequence diagram illustrates how GroupCommands are processed and executed

GroupCommandSeqDiagram

Use Cases:

Suppose a tutor wants to mark the attendance of all students from tutorial groups W13 and W14.

Instead of:

find t/W13
attendance 1 at/Present
attendance 2 at/Present
attendance 3 at/Present
...
find t/W14
attendance 1 at/Present
attendance 2 at/Present
attendance 3 at/Present
...

The tutor can type in:

group g/a find t/W13` // adds students tagged with "W13" to group g/a
group g/b find t/W14` // adds students tagged with "W14" to group g/b
group g/res join g/a g/b` // merges students in g/a and g/b to group g/res
attendance g/res at/Present` // updates the grouped students' attendance

Suppose the tutor then wants to send an email to the aforementioned group of students. They can do that with a simple command:

email g/res s/subject b/body (group email command coming in V2.0)

Tracking students

The application is implemented with immutable Student objects. As a result, when a student is edited, a new Student instance is created with the updated fields and stored in the AddressBook. This causes the stored Student objects in existing Groups to be outdated, and attempts to use those objects will lead to a crash.

To solve this issue, after every command where student(s) are changed, the stored Groups will be updated as depicted in the activity diagram below.

UpdateStudentsActivityDiagram

Design considerations

Aspect: Data structure for storing Students
  • HashSet (Current)

    • Pros: Built in duplicates prevention, easier implementation of methods, faster

  • ArrayList

    • Pros: Order is preserved, able to convert to ObservableList easily

Ordering was not as important as duplicates prevention and the fact that many of the methods are designed for a Set. Efficiency is a nice bonus but not significant as the expected number of Student entries is well below the magnitude where the difference in speed is significant.

Aspect: Command format
  • Separate commands for subcommands

    • separate commands into group-find, group-show etc.

    • Pros: Easy parsing, easy to understand, beginner friendly

  • Single command (Current)

    • single root command group with subcommands group find, group show

    • Pros: More usable, intuitive, minimize code duplication, better extensiblity

  • Natural language

    • single "root" command but parsed intelligently using keywords such as to and with

    • e.g. group students with tags t/tut1 to g/destination, group g/group1 and g/group2 to g/group3

    • Pros: Highly intuitive, beginner friendly

    • Cons: Difficult to implement and exhaustively test

Initially, the single command approach was thought to be better as I had expected users with CLI experience to be familiar with this style of commands, and will provide greater degree of customization of commands (due to the different combinations of arguments available). Furthermore, as the subcommands have very similar argument patterns, I believed that it would make more sense to consolidate the parsing code in one place.

However, feedback from trials suggest that some users prefer self-explanatory command names e.g. group-by-tag-to t/tagName g/destinationGroup over group g/destinationGroup find t/tagName. Despite this, as a developer I prefer the latter.

I briefly considered a natural language parser but decided that it was not worth the effort.