Project: UniCity
UniCity is a desktop address book application used to help university students manage their ever-growing network. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 16 kLoC (16 000 Lines of Code).
Code contributed: [https://github.com/CS2103AUG2017-W13-B1/main/blob/master/collated/main/jacoblipech.md [Functional code]] [https://github.com/CS2103AUG2017-W13-B1/main/blob/master/collated/test/jacoblipech.md [Test code]]
Enhancement Added: sort
command
Sorting a contact : sort
Sorts the list of contacts in UniCity by name.
Format:
sort
st
Example:
-
sort
Sort the list of contacts in UniCity by ascending order.
End of Extract
Justification
The purpose of sorting the contacts is so that users could view their contacts in alphabetical order.
This allows the user to find the necessary contact easier by simply glancing through UniCity in order.
Given a large number of contacts by university students, the user can always view their contacts in sorted order to scroll through their contacts list,
Sorting mechanism (Since v1.2)
The sorting mechanism is achieved by the SortCommand
. In order to sort the list of contacts, the default constructor of SortCommand
creates an empty editable array list of contacts as shown below:
private ArrayList<ReadOnlyPerson> contactList;
public SortCommand() {
contactList = new ArrayList<>();
}
The new list will take in a list of contacts from address book, sort the contacts and overwrite the existing list of contacts in address book sorted by alphabetical order.
The SortCommand
inherits from Command
instead of UndoableCommands
so there is no mechanism for sorting to be undone.
The SortCommand
is implemented in the following way:
public class SortCommand extends Command {
@Override
public CommandResult execute() {
// ... sort logic ....
}
}
When the command word sort
or st
is entered in UniCity, AddressBookParser
will call SortCommandParser
.
Upon calling the function, an editable contactList containing ReadOnlyPerson will be empty at the beginning.
When the user executes SortCommand
, sort
or st
, to sort the list of contacts in address book. The current empty ArrayList of contactList will be sent to the model ……..
The following sequence diagram shows how the sort operation works:

public Boolean sortPersonByName(ArrayList<ReadOnlyPerson> contactList) {
//check the condition of the list of contacts in addressbook currently
//different Boolean value will be returned depending on the order of the contacts
if (filteredPersons.size() == 0) {
return null;
}
contactList.addAll(filteredPersons);
Collections.sort(contactList, Comparator.comparing(p -> p.toString().toLowerCase()));
if (contactList.equals(filteredPersons)) {
return false;
}
try {
addressBook.setPersons(contactList);
indicateAddressBookChanged();
}
//...exceptions caught...
return true;
}
Upon successful sorting, the SortCommand
will correctly sort the contacts in alphabetical order and display the contacts under the PersonListPanel
.
If there is an empty list, the address book will show a message saying No contact to be sorted.
If the list is in correct order, the address book will show a message saying Already sorted.
The sorting process is case insensitive. |
Design considerations
Aspect: Implementation of SortCommand
Alternative 1 (current choice): The SortCommand
will inherit directly from Command
without the undo/redo mechanism.
Pros: After the user has finished sorting his list of contacts, it will remain sorted without reverting back to the original list.
Cons: The user can no longer obtain the list of contacts with the original order.
Alternative 2: The SortCommand
will implement undo/redo mechanism.
Pros: All contacts will be able to return to the original order when undo is applied.
Cons: It may be troublesome for the user as he may want to undo a delete/add function but the list of contacts becomes unsorted and he must sort again.
Aspect: How sorting is executed
Alternative 1 (current choice): Sorting is accomplished using the in-built function in Collections
to sort the arrays according to alphabetical order.
Pros: This method is straightforward and easy to implement.
Cons: The algorithm is in-built so it is harder to debug if something goes wrong.
Alternative 2: Writing my own sorting algorithm.
Pros: This method can cater to case sensitivity and other exceptions of the list when sorting is involved.
Cons: The algorithm may be more prone to error and may not be straightforward enough.
Aspect: Data structure to support the sort command
Alternative 1 (current choice): Create an empty array list to obtain the data from the contact list and sort the contacts. It will overwrite the existing array list of unsorted contacts when sorted.
Pros: This method is easier to understand and the original list of contacts is not changed to prevent any unexpected mistakes from occurring.
Cons: This method may have performance issues due to additional memory usage and longer time taken to overwrite the given list of contacts.
Alternative 2: Edit the current list of contacts directly by adding a function to the AddressBook
class.
Pros: This method is less time and storage consuming as sorting is achieved in a single array.
Cons: There is no way to obtain the original list of contacts for other functions. If a mistake is made, the original list of contacts will be compromised. There is a need to update all classes that inherits from AddressBook
class which may be confusing.
End of Extract
Enhancement Added: birthday
command
Adding a birthday to selected contacts : birthday
Adds the given birthday to the specified contacts .
Format:
birthday INDEX [b/BIRTHDAY]
bd INDEX [b/BIRTHDAY]
Examples:
-
list
birthday 1 b/21/10/95
Adds the birthday "21 Oct 95" to the 1st contact in UniCity’s contact list. -
bd 3 b/21/10/1995
Adds the birthday "21 Oct 1995" to the 3rd contact in UniCity’s contact list.

Figure 5: UI shown for birthday command
End of Extract
Justification
The purpose of implementing birthday was so that users can record down their friends' birthday details so that they can celebrate other friend’s birthday.
In university, birthday celebration has always been an occasion for everyone to meet up and wish the well being of the person.
Hence you would not want to miss out any of these days. This birthday command allows you to keep track of birthdays of your close friends.
Birthday mechanism (Since v1.3)
The birthday mechanism is achieved by the AddBirthdayCommand
. In order to add a birthday value to a contact, the default constructor of AddBirthdayCommand
takes in the index of the contact and the birthday value to be added to the contact.
AddBirthdayCommand
will use the arguments and parse to AddressBookParser
. This instance is then sent to AddBirthdayCommandParser
which parse the index and birthday entered.
Invalid indexes and command format will be handled by throwing an exception as shown below:
public class AddBirthdayCommandParser implements Parser<BirthdayCommand> {
public BirthdayCommand parse(String args) throws ParseException {
try {
// ... parse index and pass it to `BirthdayCommand`...
} catch (IllegalValueException ive) {
// ... throw an exception ...
}
}
}
The following sequence diagram shows how AddBirthdayCommand
is processed:

Upon successfully adding of the birthday value to the contact with the given index shown in the list, it will change the value of the Birthday
field of a Person
.
At the same time, the Birthday
class checks for the valid date entered by the user to ensure that it is in the format of DD/MM/YY or DD/MM/YYY.
As Birthday
is an optional field, the default constructor of Birthday
takes no arguments and set the default birthday to the Birthday
field for Person
. The default value to be used will be "No Birthday Added`.
In some cases, BirthdayCommand
needs to be initialized with a certain birthday for testing. Hence, another constructor is used to add a certain birthday to the Birthday
field.
public Birthday () {
this.birthdayNumber = DEFAULT_BIRTHDAY;
}
public Birthday(String birthday) throws IllegalValueException {
String trimmedBirthday = birthday.trim();
if (!isValidBirthdayFormat(trimmedBirthday)) {
throw new
IllegalValueException(MESSAGE_BIRTHDAY_CONSTRAINTS);
}
this.birthdayNumber = trimmedBirthday;
}
The AddBirthdayCommand
inherits from the UndoableCommand
so that users can undo the command of adding a birthday by accident.
The birthday value added will be displayed in the ExtendedPersonListPanel
instead of PersonCard
as it is additional information for each contact.
Design Considerations
Aspect: Changing of the Birthday
value of the selected Person
Alternative 1 (current choice): Copy values from all fields including the newly added birthday value to a newly created Person
. Then replace this Person
with the old Person
in the AddressBook
class.
Pros: This is easy to implement and it ensures that the original value will be intact in case any other information is changed.
Cons: Additional space is used to store the new Person
instance.
Alternative 2: Edit the Birthday
field in the given list of contacts directly.
Pros: No additional space is needed to store the Person
instance and more straightforward.
Cons: The data can no longer be retrieved if there is any error in the process of adding birthday to the contact.
Aspect: Storing of the Birthday
value of the selected Person
Alternative 1 (current choice): Add a new Birthday
class.
Pros: Same coding format stored as Name
, Phone
and other information so the coding principle is standardized. It can also perform validation checks for the birthday value easily.
Cons: Add a new class affects many components of the code and much work needs to be done to make the changes.
Alternative 2: Use a String
value to keep track of birthday for each Person
.
Pros: This is easier and faster to implement.
Cons: It is prone to bugs as the String
value can be overwritten easily.
End of Extract
Other contributions
-
Made tags in UniCity to show different colors. (Pull request https://github.com/CS2103AUG2017-W13-B1/main/pull/59 [#59])
-
Made error message to show a different color in UniCity. (Pull request https://github.com/CS2103AUG2017-W13-B1/main/pull/60 [#60])
-
Added birthday field to add and edit command to make changes there as well (Pull request https://github.com/CS2103AUG2017-W13-B1/main/pull/61 [61])
-
Made address, email and birthday optional fields in UniCity. (Pull request https://github.com/CS2103AUG2017-W13-B1/main/pull/77 [#77])
-
Enhanced UI in UniCity by adding another panel to show more information about a contact. (Pull request https://github.com/CS2103AUG2017-W13-B1/main/pull/100 [#100])
-
Added a calendar view panel to show all the calendars and the box will display red color if someone’s birthday lies on it. The user can details of the person with birthday on that day by clicking on the box. (Pull request https://github.com/CS2103AUG2017-W13-B1/main/pull/132 [#132])