Welcome to my project portfolio. I am Benjamin and I am a computing science student. This project portfolio will detail the contributions I have made to various Software Engineering projects.
PROJECT: MeetingBook
MeetingBook is a desktop scheduler application targeted at university students involved in multiple Co-Curricular Activities and Project-Based modules. The application is a modified contact book with features to group contacts and assign meetings to such groups. MeetingBook is written by a team of 5 students from National University of Singapore’s School of Computing. It is forked from AddressBook-Level4 written by SE-EDU.
Summary of contributions
-
Major enhancement: enhanced the
findcommand.-
What it does prior: the
findcommand filters the displayed list of persons based on the keywords given. Upon execution, the list displays persons whose name consists at least one of the keywords given. -
What it does after enhancement:
-
The user can add an additional parameter specifying whether to search for groups, meetings, or persons.
-
The user can put the keywords into 3 categories: a set of keywords where the results must match all given keywords, a set of keywords where the results must match at least one of the given keywords, and a set of keywords where the results must not match any of the given keywords.
-
-
Justification: The extension of the
findcommand allows the user to better manage their MeetingBook. When there is a large amount of data in the MeetingBook, the user will have an easier time searching for what they need.
-
-
Minor enhancement: added a
sortcommand that allows the user to sort the displayed list of persons by name, phone number, email address, or home address by lexicographical order. -
Code contributed:
-
Other contributions:
-
Project management:
-
Managed releases v1.1 - v1.3 (3 releases) on GitHub
-
Wrote tests to increase coverage from 93% to 94% (Pull request)
-
-
Enhancements to existing features:
-
Documentation:
-
Community:
-
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. |
Sorting the list of displayed persons: sort
The sort command sorts the list in the display of persons.
The user can specify whether to sort by name, phone number, email address, or home address,
in lexicographical order or numerical order.
Format:
sort <name|phone|email|address>
Examples:
-
sort name: Sorts the list of persons by name in lexicographical order. -
sort phone: Sorts the list of persons by phone number in numerical order. -
sort email: Sorts the list of persons by email address in lexicographical order. -
sort address: Sorts the list of persons by home address in lexicographical order.
Finding a group / person / meeting: find
The find command searches the MeetingBook for specified person, group, or meeting, and displays the results on
the panel.
Format:
Longhand: find <person|group|meeting> [a/KEYWORDS] [s/KEYWORDS] [n/KEYWORDS]
Shorthand: find <p|g|m> [KEYWORDS]
Examples:
-
find p Alex: finds all persons whose name containsAlex. (Refer to diagram above)
-
find p s/yu li: finds all persons whose name contains one ofyuorli. (Refer to diagram above)
-
find p n/Alex Bernice: finds all persons whose name does not containAlexorBernice(Refer to diagram above) -
find p Betty Charles: finds all persons whose name containsBettyandCharles. -
find p s/David Eric n/James: finds all persons whose name contains one ofDavidorEric, and whose name does not containJames. -
find group project: finds all groups whose title containsproject. -
find g a/team n/school: finds all groups whose title containsteamand whose title does not containschool. -
find meeting s/official important: finds all meetings whose title contains one ofofficialorimportant. -
find m a/urgent n/basketball: finds all meetings whose titles containsurgentand whose title does not containbasketball.
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. |
Sort and Find feature
The Sort and Find commands modifies the ObservableList<Person> in Model that the UI is bound to. This section will
detail how the sort and find commands are implemented.
Implementation of find command
Structure of find command
When the user executes a find command, the FindCommandParser returns either a FindPersonCommand, a FindMeetingCommand, or a FindGroupCommand,
depending on the user’s input. FindPersonCommand, FindMeetingCommand, and FindGroupCommand extends the
FindCommand<Person>, FindCommand<Meeting>, and FindCommand<Group> abstract classes respectively.
The FindCommand<E> abstract class extends the Command abstract class.
public abstract class FindCommand<E> extends Command {
public static final String COMMAND_WORD = "find";
public static final String MESSAGE_USAGE = ...
protected final Predicate<E> predicate;
FindCommand(Predicate<E> predicate) {...}
@Override
public boolean equals(Object other) {...}
}
ModelManager maintains 3 lists of type FilteredList. The lists are filteredPersons, filteredMeetings, and filteredGroups.
When the find command is executed, a predicate is passed into the respective FilteredList. The elements in the list that passes the predicate
test will be displayed in the UI.
Referring to the code snippet above, FindCommand<E> implements the equals() method and contains a predicate of type Predicate<E>.
This predicate will be applied to the filteredPersons list if FindPersonCommand is executed, filteredGroups list if FindGroupCommand is executed,
and filteredMeetings list if FindMeetingCommand is executed. Each of FindPersonCommand, FindGroupCommand, and FindMeetingCommand
implements the execute() method required by the Command abstract class.
Structure of Predicates
The predicates are created using the abstract class EntityContainsKeywordsPredicate<E>.
PersonNameContainsKeywordsPredicate extends EntityContainsKeywordsPredicate<Person>,
GroupTitleContainsKeywordsPredicate extends EntityContainsKeywordsPredicate<Group>, and
MeetingTitleContainsKeywordsPredicate extends EntityContainsKeywordsPredicate<Meeting>.
public abstract class EntityContainsKeywordsPredicate<E> implements Predicate<E> {
private final List<String> allKeywords;
private final List<String> someKeywords;
private final List<String> noneKeywords;
private final Function<E, Predicate<String>> testKeywordPredicateGetter;
public EntityContainsKeywordsPredicate(List<String> allKeywords, List<String> someKeywords, List<String> noneKeywords, Function<E, String> entityKeywordGetter) {...}
@Override
public boolean test(E element) {...}
@Override
public boolean equals(Object other) {...}
}
As seen in the code snippet above, EntityContainsKeywordsPredicate maintains 3 lists of String, the allKeywords list,
the someKeywords list, and the noneKeywords list. The lists of strings are generated by the FindCommandParser that
parses the find command entered. testKeywordPredicateGetter is used to generate the predicate that will be used to test
whether each keyword matches the element being tested.
Each of PersonNameContainsKeywordsPredicate, GroupTitleContainsKeywordsPredicate, and MeetingTitleContainsKeywordsPredicate
contains a predefined function used to retrieve the Person name, Group title, or Meeting title.
This predefined function will be used passed into the constructor of EntityContainsKeywordsPredicate to generate
testKeywordPredicateGetter.
When the predicate is passed into the FilteredList in ModelManager, the test() method in this predicate will be used
to test the elements in the list.
How the sort command works with the find command
In the current implementation, the sort command only applies on the list of persons.
ModelManager maintains a sortedPersons list of type SortedList<Person> and a filteredPersons list of type
FilteredList<Person>.
Illustrated in the figure above, sortedPersons list wraps the filteredPersons list and
filteredPersons list wraps the persons list of type ObservableList<Person> maintained by versionedMeetingBook.
persons list in versionedMeetingBook contains all the persons stored in the MeetingBook.
The list displayed in the UI is bound to the sortedPersons list. Hence, the persons list has two layers of
modification before being displayed in the GUI as sortedPersons.
Before the user executes any find or sort commands, no Comparator<Person> and no Predicate<Person> is applied to
the persons list. The UI will display the all the persons in the MeetingBook as expected.
When the user executes a find command, an appropriate Predicate<Person> will be created based on the user’s input,
and the Predicate<Person> will be applied to the persons list. This modification will be reflected in the
sortedPersons list and in the displayed list in the GUI.
Similarly, when a user executes a sort command, an appropriate Comparator<Person> will be applied to the
filteredPersons list. This modification will be reflected in the displayed list in the UI.
Design considerations
Due to this two-layered structure. The user can chain find and sort commands back-to-back to display the desired
list.
An example can be seen in the diagram above by executing the command find p s/yu li followed by sort name.
After applying the sort command, the find filter remains applied. The next example will demonstrate a different order.
The diagram above shows another example of back-to-back execution.
The diagram shows the execution of sort name followed by find p s/yeoh li.
As can be seen in the diagram, the sorting order remains even after executing the find command.