Overview
The Real App is an enhanced desktop address book designed primarily for real estate agents. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC.
Summary of contributions
-
Major enhancement: Transform the model to allow for client contact and property information to be stored, modified and accessed.
-
What it does: allows The Real App to treat each entry as a customer to process and store the relevant information.
-
Justification: This feature forms the underlying model of The Real App and allows the user to use The Real App to store customer and real estate information.
-
Highlights: This enhancement affects existing commands and commands to be added in future. It required an in-depth analysis of design alternatives. The implementation too was challenging as it required extensive changes to many existing components, such as
logic
,model
,storage
andui
.
-
-
Minor enhancement:
-
Modify
add
command to allow user to add entries into the revamped contact book. -
Modify
edit
command to allow user to edit entries in the revamped contact book. -
Transform existing
find
command intosearch
command to allow user to search and retrieve information. -
Integrate new
search
command with thearchive
feature. -
Modify UI to display all the information of customers and properties.
-
-
Code contributed: [Project Code Dashboard]
-
Other contributions:
-
Project management:
-
Set up the organisation Github and the team repo.
-
Set up Travis-CI and Coverall.
-
Set up auto-publishing of documentation.
-
-
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. |
Starting the app
-
Double-click the file to start the app. The GUI should appear in a few seconds.
-
Type the command in the command box and press Enter to execute it.
E.g. typinghelp
and pressing Enter will open the help window. -
The outcome of the command will be displayed in the result display box.
E.g. after successfully executing thehelp
command, the following message will appear:
Opened help window.
Displaying main person list! -
The pin list shows the contacts who has been pinned. It can be resized by clicking and dragging the borders of the box.
-
The main contact list shows the active list of contacts. It can also be resized by clicking and dragging the borders of the box. You can toggle between the contact list view and the archive list view using commands
list
andarchivelist
. -
The browser window will display the property’s location on Google Maps™ when an appropriate contact is selected. You can go to [GoogleMaps] for more details of the Google Maps™ display.
Adding a contact : add
Adds a contact to the contact book, with 4 variants of customer types. Adds the associated property information for sellers and landlords.
|
Accepted customer types: |
A property can have any number of TAG (including 0).
|
-
Seller:
Format:add c/seller n/NAME p/PHONE_NUMBER e/EMAIL r/REMARKS a/ADDRESS sp/SELLING_PRICE_OF_PROPERTY [t/TAG]…
Example:add c/seller n/James Tan p/97652456 e/jamestan@example.com r/need to sell by April 2018 a/Blk 345 Clementi Ave 5, #04-04, S120345 sp/500000 t/MRT t/newlyRenovated
-
Buyer:
Format:add c/buyer n/NAME p/PHONE_NUMBER e/EMAIL r/REMARKS
Example:add c/buyer n/James Ho p/87657252 e/jamesho@example.com r/looking for 3-room apartment
-
Landlord:
Format:add c/landlord n/NAME p/PHONE_NUMBER e/EMAIL r/REMARKS a/ADDRESS rp/RENTAL_PRICE_OF_PROPERTY [t/TAG]…
Example:add c/landlord n/Hans Tan p/90826522 e/hanstan@example.com r/family friend a/Blk 345 Woodlands Street 32, #04-04, S730345 rp/1500 t/MRT t/newlyRenovated
-
Tenant:
Format:add c/tenant n/NAME p/PHONE_NUMBER e/EMAIL r/REMARKS
Example:add c/tenant n/Bo Yang p/86541526 e/boyang@example.com r/looking for 4-room apartment
When multiple parameters of the same type are entered, only the last one will be added. e.g. |
Screenshots for 1st example:
-
Enter
add c/seller n/James Tan p/97652456 e/jamestan@example.com r/need to sell by April 2018 a/Blk 345 Clementi Ave 5, #04-04, S120345 sp/500000 t/MRT t/newlyRenovated
:
-
Client James Tan is successfully added, the contact list is updated and the newly added contact is selected:
Displaying a sorted list of contacts by specified category : sort
[coming in v2.0]
Shows a list of all contacts in the contact book, sorted according to a specified category.
Format: sort CATEGORY [CATEGORY_RESTRICTOR] ORDER
|
Example: sort sp <540000 ascending
Displays the contact list sorted by price less than $540,000 in ascending order.
Example: sort n ascending
Displays the contact list sorted by name in ascending alphabetical order.
Searching for contact(s) by keyword(s) : search
Search for contact(s) whose information contains any of the keyword(s).
e.g. search by name, search by address, search by tags etc.
Format: search KEYWORD [KEYWORD]…
|
Examples:
-
search James
ReturnsJames Tan
andJames Ho
-
search James Tan Yang
Returns any contact with information matchingJames
,Tan
, orYang
-
search Woodlands Landlord
Returns any contact with information matchingWoodlands
orLandlord
Screenshots for 1st example:
-
Enter
search James
:
-
The search is executed successfully and the contact list is updated to show
James Tan
andJames Ho
.
Editing a contact : edit
Edits an existing contact and/or associated property (if any) in the contact book, with 4 variants of customer types.
-
Seller:
Format:edit INDEX_SELLER [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [r/REMARKS] [a/ADDRESS] [sp/SELLING_PRICE_OF_PROPERTY] [t/TAG]…
Example:edit 2 n/James Li e/jamesli@example.com sp/450000 t/
-
Edits the name and email address of the 2nd contact to be
James Li
andjamesli@example.com
respectively. Edits selling price of the associated property to be450000
and clears all existing tags.
-
-
Buyer:
Format:edit INDEX_BUYER [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [r/REMARKS]
Example:edit 2 n/James Han e/jameshan@example.com r/looking for houses in Woodlands
-
Edits the name, email address and remarks of the 2nd contact to be
James Tan
,jamestan@example.com
andlooking for houses in Woodlands
respectively.
-
-
Landlord:
Format:edit INDEX_LANDLORD [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [r/REMARKS] [a/ADDRESS] [rp/RENTAL_PRICE_OF_PROPERTY] [t/TAG]…
Example:edit 2 n/Jim Lee p/87654321 rp/1700 t/MRT t/Park
-
Edits the name and phone number of the 2nd contact to be
Jim Lee
and87654321
respectively. Edits rental price of the associated property to be1700
, clears all existing tags and adds new tagsMRT
andPark
.
-
-
Tenant:
Format:edit INDEX_TENANT [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [r/REMARKS]
Example:edit 2 n/James p/87654322
-
Edits the name and phone number of the 2nd contact to be
James
and87654322
respectively.
-
The customer type of the contact cannot be changed and only information type relevant to the customer type can be modified. |
When multiple parameters of the same type are entered, only the last one will be edited. e.g. |
Screenshots for 1st example:
-
Enter
list
:
-
Main contact list is displayed:
-
Make sure that the contact at index 2 is a seller, otherwise choose the correct index corresponding to a seller.
Enteredit 2 n/James Li e/jamesli@example.com sp/450000 t/
:
-
Contact at index 2 is now edited to
James Li
and the information are updated accordingly. The contact is also selected upon successful execution of theedit
command:
Searching for archived contact(s) : archivesearch
Searches the archive and finds contact(s) whose information contains any of the keyword(s).
Format: archivesearch KEYWORD [KEYWORD]…
|
Example:
-
archivesearch James Seller
Returns any contact with information fields matching keywordsJames
and/orSeller
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. |
Model component
API : Model.java
The Model
,
-
stores a
UserPref
object that represents the user’s preferences. -
stores the Address Book, Archive Book and Pin Book data as 3 separate instances of the AddressBook class.
-
exposes an unmodifiable
ObservableList<Person>
that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. -
does not depend on any of the other three components.
As a more OOP model, we can store a Tag list in Address Book , which Property can reference. This would allow Address Book to only require one Tag object per unique Tag , instead of each Property needing their own Tag object. An example of how such a model may look like is given below. |
Transformation of AddressBook4 to The Real App
Current Implementation
To allow The Real App to store client contact and property information, the model of AB4 must be modified.
The Person
class has been modified to only contain the following 4 information:
-
Name
— Encapsulates the name of a client in the model. -
Phone
— Encapsulates the phone of a client in the model. -
Email
— Encapsulates the email of a client in the model. -
Remark
— Encapsulates the remark associated with a client in the model.
The Person
class has also been extended to the following 4 sub-classes to encapsulate the customer type and related information:
-
Buyer
— Represents a client who is a buyer in the model. -
Seller
— Represents a client who is a seller in the model, contains additional property information. -
Tenant
— Represents a client who is a tenant in the model. -
Landlord
— Represents a client who is a landlord in the model, contains additional property information.
The abstraction of the property information is done through a Property
class. The Property
class encapsulates property information through the following 3 classes:
-
Address
— Encapsulates the address of a property in the model. -
Price
— Encapsulates the price of a property in the model. -
Tag
— Encapsulates short keywords associated with a property in the model.
There are 2 ways through which client information can be added into the model. One is through user input in the add
command, the other is through reading the storage json files at launch.
Given below is an example scenario of how client information can be added into the model via the 2 ways described above.
From storage
Step 1. The user launches the application.
Step 2. MainApp
will find the addressbook
, archivebook
and pinbook
json files in the data folder and get them as JsonAddressBookStorage
objects.
Step 3. The JsonAddressBookStorage
objects are used to initialise StorageManager
.
Step 4. The MainApp
calls initModelManager
method which will eventually return a ModelManager
object.
Step 5. To build the model, the StorageManager
will build three AddressBook
objects which are collections of all the Person
objects stored in the addressbook
, archivebook
and pinbook
json files.
Step 6. The three AddressBook
objects are used to initialise the ModelManager
, which creates the model.
The following sequence diagram summarizes how the model is created from json files when a user launches The Real App:
Through add command
Step 1. The user launches the application.
Step 2. The user enters the add
command with the correct parameters into the Command Box.
e.g. add c/seller n/James Tan p/97652456 e/jamestan@example.com r/need to sell by April 2018 a/Blk 345 Clementi Ave 5, #04-04, S120345 sp/500000 t/MRT t/newlyRenovated
Step 3. The LogicManager
handles the user input and creates an AddCommand
object.
Step 4. The AddCommand
object is executed by the LogicManager
.
Step 5. The ModelManager
updates the model to add the contact into the AddressBook
.
The following sequence diagram summarizes how a contact is added to the AddressBook
using the add
command:
Other Improvements
To allow for modification and retrieval of information, the edit
and search
commands have been expanded to fit the new model.
Edit command
Edit command has been improved to handle the different types of contacts safely. Object type checking is done during the execution of the command to ensure that only the correct information associated with the customer type is edited. This also ensures that the returned object is the same class as the original object being edited.
Search command
The original find
command in AB4 has been renamed to search
command to better reflect its new functionality. search
command can now search through multiple information fields to look for matches to the input keywords.
This allows users to quickly retrieve contacts using whatever limited information they may have at hand.
Design Considerations
Aspect: Abstraction of different customer types
-
Alternative 1 (current choice): The four customer types are abstracted as sub-classes which extends the
Person
class-
Pros: Allows for subclass polymorphism.
-
Cons: Legacy code from AB4 is not optimised for runtime polymorphism.
-
-
Alternative 2: Encapsulate customer type information in
Person
class using aCustomerType
class.-
Pros: Easy to implement.
-
Cons: Requires rigorous checking of customer type to ensure each contact is handled appropriately.
-
-
Alternative 3: Refactor
Person
class into an abstract class and extend the 4 subclasses from it-
Pros: Prevents the initialisation of a
Person
object, which is not required in our application. -
Cons: Much of the legacy code of AB4 has strong dependence on the instantiation of the
Person
objects.
-
Adding a client
-
Adding a client to the app.
-
Prerequisite: The app must be launched and the client does not already exist in the database.
-
Test case:
add c/seller n/James Tan p/97652456 e/jamestan@example.com r/need to sell by April 2018 a/Blk 345 Clementi Ave 5, #04-04, S120345 sp/500000 t/MRT t/newlyRenovated
Expected: A new contact appears at the end of the contact list with all the relevant information added. Address location of the added contact is displayed on the Google Maps™ window panel(if applicable). -
Test case:
add c/buyer n/James Ho e/jamesho@example.com r/looking for 3-room apartment
Expected: Contact cannot be added as there are missing parameters. Error details shown in the status message. Status bar remains the same. -
Other incorrect add commands to try:
add c/seller p/86567123
,add c/buyer n/James Ho
. Expected: Similar to previous.
-
Edit a contact
-
Editing an existing contact in the app.
-
Prerequisite: The app must be launched and there are contacts currently in the database.
-
Test case:
edit x n/James Han e/jameshan@example.com r/looking for houses in Woodlands
(where x is the index of a buyer contact)
Expected: The buyer contact as index x will be edited with new nameJames Han
, new emailjameshan@example.com
and new remarklooking for houses in Woodlands
. Other information remains the same. -
Test case:
edit x n/James Li e/jamesli@example.com sp/450000 t/
(where x is the index of a contact who is not a seller)
Expected: Contact cannot be edited as there are parameters that are not applicable to this customer type. Error details shown in the status message. Status bar remains the same. -
Other incorrect edit commands to try:
edit n/James
,edit 1
. Expected: Invalid command format.
-
Edit a contact
-
Searching for a contact in the app.
-
Prerequisite: The app must be launched and there are contacts currently in the database.
-
Test case:
search James
Expected: The contact list will be updated to display all contacts with information matching the keywordjames
. -
Test case:
search &$%$
Expected: No contacts listed as&$%$
does not match any of the valid information field in a contact. -
Other incorrect search commands to try: `search `. Expected: Invalid command format.
-
Archiving a person
-
Archiving a person while all persons are listed
-
Prerequisites: List all persons using the
list
command. Multiple persons in the list. -
Test case:
archive 2
Expected: 2nd contact in the list is selected. Details of the archived contact shown in the status message. Timestamp in the status bar is updated. -
Test case:
archive 0
Expected: No person is archived. Error details shown in the status message. Status bar remains the same. -
Other incorrect archive commands to try:
archive
,archive one
,archive x
(where x is larger than the list size),archive n
(where n is a name of an existing contact),archive .
Expected: Similar to previous.
-
-
Archiving a person from a search command result
-
Prerequisites: Enter
list
. Search for persons using thesearch
command. Persons that match the search are displayed in the list. -
Test case:
archive 1
Expected: 1st contact in the list is archived. Details of the archived contact shown in the status message. Timestamp in the status bar is updated. -
Test case:
archive 0
Expected: No person is archived. Error details shown in the status message. Status bar remains the same. -
Other incorrect archive commands to try:
archive
,archive one
,archive x
(where x is larger than the list size),archive n
(where n is a name of an existing contact),archive .
Expected: Similar to previous.
-
Selecting an archived person
-
Selecting a person while all archived persons are listed
-
Prerequisites: List all archived persons using the
archivelist
command. Multiple persons in the list. -
Test case:
archiveselect 2
Expected: 2nd contact in the list is selected. Address location of the selected contact is displayed on the Google Maps™ browser window panel (if applicable). -
Test case:
archiveselect 0
Expected: No person is selected. Error details shown in the status message. -
Other incorrect archiveselect commands to try:
archiveselect
,archiveselect one
,archiveselect x
(where x is larger than the list size),archiveselect n
(where n is a name of an existing archived contact),archiveselect .
Expected: Similar to previous.
-
-
Selecting a person from an archivesearch command result
-
Prerequisites: Enter
archivelist
. Search for archived persons using thearchivesearch
command. Persons that match the search are displayed in the list. -
Test case:
archiveselect 1
Expected: 1st contact in the list is selected. Address location of the selected contact is displayed on the Google Maps™ browser window panel (if applicable). -
Test case:
archiveselect 0
Expected: No person is selected. Error details shown in the status message. -
Other incorrect archiveselect commands to try:
archiveselect
,archiveselect one
,archiveselect x
(where x is larger than the list size),archiveselect n
(where n is a name of an existing archived contact),archiveselect .
Expected: Similar to previous.
-
Unarchiving a person
-
Unrchiving a person while all archived persons are listed
-
Prerequisites: List all archived persons using the
archivelist
command. Multiple persons in the list. -
Test case:
unarchive 2
Expected: 2nd contact in the list is unarchived. Details of the unarchived contact shown in the status message. Timestamp in the status bar is updated. -
Test case:
unarchive 0
Expected: No person is unarchived. Error details shown in the status message. Status bar remains the same. -
Other incorrect unarchive commands to try:
unarchive
,unarchive x
(where x is larger than the list size),unarchive n
(where n is a name of an existing contact),unarchive .
Expected: Similar to previous.
-
-
Unarchiving a person from an archivesearch command result
-
Prerequisites: Enter
archivelist
. Search for archived persons using thearchivesearch
command. Persons that match the search are displayed in the list. -
Test case:
unarchive 1
Expected: 1st contact in the list is unarchived. Details of the unarchived contact shown in the status message. Timestamp in the status bar is updated. -
Test case:
unarchive 0
Expected: No person is unarchived. Error details shown in the status message. Status bar remains the same. -
Other incorrect unarchive commands to try:
unarchive
,unarchive x
(where x is larger than the list size),unarchive n
(where n is a name of an existing contact),unarchive .
Expected: Similar to previous.
-
PROJECT: PowerPointLabs
{Optionally, you may include other projects in your portfolio.}