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
andtag 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
.
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
Planned Sub-commands (2.0)
-
index <indexes>
— groups students by index, separated by space, e.g.group index 1 3 4 5
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.
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 subcommandsgroup 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
andwith
-
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.