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
find
command.-
What it does prior: the
find
command 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
find
command 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
sort
command 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 ofyu
orli
. (Refer to diagram above)
-
find p n/Alex Bernice
: finds all persons whose name does not containAlex
orBernice
(Refer to diagram above) -
find p Betty Charles
: finds all persons whose name containsBetty
andCharles
. -
find p s/David Eric n/James
: finds all persons whose name contains one ofDavid
orEric
, 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 containsteam
and whose title does not containschool
. -
find meeting s/official important
: finds all meetings whose title contains one ofofficial
orimportant
. -
find m a/urgent n/basketball
: finds all meetings whose titles containsurgent
and 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.