Overview
UniLA is a desktop utilities application designed for university students who are typing oriented to easily manage their contact and event lists. The application is primarily concerned with CLI (Command Line Interface) Interaction, with a simple and intuitive GUI provided.
Summary of contributions
-
Major enhancement: upgrade the find command and implement findE command
-
What it does: These two commands support different search patterns. The
find
allows users to search for people in contact list easily. Users can search a person through exact keyword match, fuzzy keyword match and wildcard keyword match. ThefindE
command allows users to search for events in event list. Users can search for an event through exact keyword match, search for events before, on or after a certain date, and search for the event with a certain duration. -
Justification: This feature is important and efficient for users to manage a large list of contacts and events.
-
Highlights: The enhancement and implementation involves reorganizing different classes, adding new predicates classes and command classes. The implementation is challenging because different search patterns are used and the optimal algorithm is chosen after a detailed analysis of the alternatives.
-
Credits: Levenshtein Distance is used to calculate the similarity between keywords. [Original Blogger]
-
-
Minor enhancement:
-
Implement photo command which allows user to add photo to the person in the contact list.
-
Implement personInfo fxml to display personal information on contact list.
-
-
Code contributed: [RepoSense Project Code Dashboard]
-
Other contributions:
-
Project Management:
-
Setup netlify test.
-
Added issues to issue tracker.
-
Updated User Guide, Developer Guide, About Us pages.
-
Helped teammates with their problems regarding github and the project.
-
-
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. |
Locating persons by any field: find
Finds people whose fields contain any of the input keywords. Searching can be done with or without prefix. When searched without prefix, people whose fields that contain any matching keywords will be returned. When searched with prefix, people whose corresponding fields that contain any matching keywords will be returned.
Format1: find KEYWORD [MORE_KEYWORDS]
Format2: find prefix/KEYWORD, [MORE KEYWORDS]
These are 3 search patterns that are utilized be the find
command:
-
Exact keyword match - Matches the input keyword with exact keywords found in people’s fields.
-
Fuzzy keyword match - Matches the input keyword to people’s fields that have higher than 0.7 similarity. The similarity is calculated based on Levenshtein Distance. Further explanation is provided in the developer guide.
-
Wildcard keyword match - Matches the input keyword with wildcard character *. * represents any number of alphanumeric characters consisting of 0-9, a-z and A-Z.
Searching results are displayed in the following format:
n persons listed:
Exact Search:
[NAME]…
Fuzzy Search:
[NAME]…
Wildcard Search:
[NAME]…
There are three parts of executing find command. The input keywords are first searched with exact string match, then fuzzy search, and finally wildcard search.
Any results displayed in the previous searching stage will not be shown in the next searching stage.For example, if person Alice is found in exact string match, she will not be displayed in fuzzy search result. This is to avoid message duplication. |
Examples:
-
find victoria
In exact search: Returns any person whose fields that contain keywordvictoria
in exact search. For example, person whose name isVictoria
or person who lives inVictoria Street
.
In fuzzy search: Returns any person whose fields that have keywords similar tovictoria
. For example, person whose tags containing the keywordVictory
. -
find Serangon doctor
In exact search: Returns any person whose fields that contain keywordsSerangon
ordoctor
In fuzzy search: Returns any person whose fields that have keywords similar toSerangon
ordoctor
-
find t/owemoney friends
In exact search: Returns any person whose tags that contain keywordsowemoney
orfriends
In fuzzy search: Returns any person whose tags that have keywords similar to toowemoney
orfriends
-
find *@gmail.com
In exact search: Returns any person whose fields that contain keywords*@gmail.com
In fuzzy search: Returns any person whose fields that have keywords similar to*@gmail.com
In wildcard search: Returns any person whose fields that have keywords match regex*@gmail.com
Locating events by any field: findE
Finds events whose fields contain any of the input keywords. Searching can be done with or without prefix. When searched without prefix, events whose fields that contain any matching keywords will be returned. When searched with prefix, events whose corresponding fields that contain any matching keywords will be returned.
Format1: find KEYWORD [MORE_KEYWORDS]
Format2: find prefix/KEYWORD, [MORE KEYWORDS]
Examples:
-
findE google
Returns any events having fields that contain keywordsgoogle
. For example, event whose name is 'Google talk' or event whose venue is 'Google building'. -
findE pgp library
Returns any events having fields that contain keywordspgp
orlibrary
. For example, events with venue 'pgp' or 'central library'. -
findE l/important
Returns any event having label that contains keywordimportant
.
There are two sub command of findE
command which are findE time/
and findE duration/
:
1. findE time/
finds events whose starting date are before, equal to or after the searching date. Alternatively alias (ytd, today or tmr) can be used to search for events whose starting date is yesterday, today or tomorrow.
Format3: findE time/operatorDATE
Format4: findE time/alias(ytd, today or tmr)
Examples:
-
findE time/>2019-12-01
Returns all the events whose starting dates are after 2019,12,1. -
findE time/tmr
Returns all the events that starting tomorrow.
2. findE duration/
finds events whose duration is smaller, equal to or larger than the searching period.
Format5: findE duration/operatorHOURS
Examples:
-
findE duration/<2
Returns all the events which are shorter than 2 hours. -
findE duration/>4
Returns all the events which are longer than 4 hours.
Adding photo to a person : photo
Adds photo to a person in the contact list (identified by the index number used in the last listing).
Format1: photo INDEX IMAGE_PATH
Removes photo from a person in the contact list by the sub-command clear
. Photo of the person will reset to the default photo.
Format2: photo INDEX clear
Examples:
-
list
photo 3 /users/alice/desktop/photo.png
(in mac)
photo 3 C:\Users\william\Desktop\photo.jpg
(in windows)
Adds photo to the 3rd person in the UniLA.
photo 3 clear
Removes the photo from the 3rd person in the UniLA. Photo is reset to the default photo.
The added photo will be copied to the program. Thus, if the photo in the original path is moved, renamed or deleted, UniLA will not be affected. |
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. |
Find feature
Current Implementation
The mechanism is facilitated by findCommand
, findCommandParser
and different Predicate classes. It allows users to search with 3 different search patterns. During the execution of find command, 3 search patterns will be executed one by one.
Given below is the process of executing find command:
Step 1. The exact search: This is a base method of matching string. It’s implemented by String.equals().
Step 2. The fuzzy search: This is based on similarity comparison. First edit distance between input keywords and the string in people’s fields is calculated based on Levenshtein Distance algorithm. Subsequently, similarity is calculated by s = 1 - Levenshtein_Distance/Max_Length_Of_Two_Strings. The similarity threshold is set to 0.7. If a person’s fields contain keyword which have more than 0.7 similarity to the input keywords, he or she will be returned in fuzzy search result.
Step 3. The wildcard search: This is based on regular expression. It recognizes character *. The character * matches any number of alphanumeric characters consisting of 0-9, a-z and A-Z.
-
The following code snippet is from
TagsContainsKeywordPredicate
class. It shows an example of how predicate class works:
@Override
public boolean test(Person person) {
return keywords.stream()
.anyMatch(keyword -> {
String name = person.getName().fullName;
String tags = person.getTagsAsStringNoBracket();
if (StringUtil.containsWordIgnoreCase(tags, keyword)) {
if (!exactSearchList.contains(name)) {
exactSearchList.add(name);
}
return true;
}
if (StringUtil.matchFuzzySearch(tags, keyword)) {
if (!fuzzySearchList.contains(name)) {
fuzzySearchList.add(name);
}
return true;
}
if (StringUtil.matchWildcardSearch(tags, keyword)) {
if (!wildcardSearchList.contains(name)) {
wildcardSearchList.add(name);
}
return true;
}
return false;
});
}
Design Considerations
Aspect: How fuzzy search is executed
-
Alternative 1 (current choice): Use similarity to compare the keywords
-
Pros: The accuracy is higher because the differences and the total length of the strings are proportional.
-
Cons: Less easy to implement.
-
-
Alternative 2: Use edit distance to compare the keywords
-
Pros: Easy to implement.
-
Cons: Lower accuracy especially when the string is short.
-
Different search patterns optimize the 'find' command for different kinds of users. They help with users when they cannot remember the exact spelling or users who are prone to typos. |
Photo feature
Current Implementation
The mechanism is facilitated by Photo
, PhotoCommand
class. A Photo
class is added to Model
. It allows users to add a photo to the person in the contact list.
Given below is the process of executing photo command:
Step 1. The command will be checked whether it contains sub command clear
. If it is a photo clear command, the photo of the contact list will reset to default photo. The photo command execution is finished. Else, following steps will be executed.
Step 2. The input file path will be checked for whether the file exists.
Step 3. The input file path will be checked for whether it can be opened as an image.
Step 4. The size the of photo will be checked for whether it is within the range (smaller than 20MB).
Step 5. The photo will be copied to the program and it is saved to the target person.
-
The following code snippet is from PhotoCommand class. It shows an example of how photo command executes:
if (photo.getPath().equals(COMMAND_SUB)) {
photo.setPath(DEFAULT_PHOTOPATH);
Person personToEdit = lastShownList.get(targetIndex.getZeroBased());
String path = personToEdit.getPhoto().getPath();
File file = new File(path);
file.delete();
} else {
if (!isValidPhotoPath(photo.getPath())) {
return new CommandResult(MESSAGE_INVALID_PHOTOPATH);
}
if (!isImage(photo.getPath())) {
return new CommandResult(MESSAGE_FILE_NOT_IMAGE);
}
if (!isPhotoSizeWithinRange(photo.getPath())) {
return new CommandResult(MESSAGE_SIZE_EXCEED);
}
String user = System.getProperty("user.name");
String dir = "data/";
String copyPath = FileUtil.copyFile(photo.getPath(), String.format(dir, user));
photo.setPath(copyPath);
}
Design Considerations
Aspect: How photo is stored in UniLA
-
Alternative 1 (current choice): Copy the photo to the program.
-
Pros: The address book will not be affected if the photo in the original path is moved, renamed or deleted. Stability of the program is ensured.
-
Cons: Consumes more memory because the photo is copied to the program.
-
-
Alternative 2: Save the path and load the photo from the path every time when user opens the app.
-
Pros: Use less memory. Easy to implement.
-
Cons: The photo will be not be displayed if the photo in the original path is moved, renamed or deleted.
-