Developer Guide
- Setting up, getting started
- Design
- Implementation
- Documentation, logging, testing, configuration, dev-ops
- Appendix: Requirements
- Appendix: Instructions for manual testing
- Appendix: Effort
Setting up, getting started
Refer to the guide Setting up and getting started.
Design
Architecture

The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.
.puml files used to create diagrams in this document can be found in the diagrams folder. Refer to the PlantUML Tutorial at se-edu/guides to learn how to create and edit diagrams.
Main has two classes called Main and MainApp. It is responsible for,
- At app launch: Initializes the components in the correct sequence, and connects them up with each other.
- At shut down: Shuts down the components and invokes cleanup methods where necessary.
Commons represents a collection of classes used by multiple other components.
The rest of the App consists of four components.
-
UI: The UI of the App. -
Logic: The command executor. -
Model: Holds the data of the App in memory. -
Storage: Reads data from, and writes data to, the hard disk.
Each of the four components,
- defines its API in an
interfacewith the same name as the Component. - exposes its functionality using a concrete
{Component Name}Managerclass (which implements the corresponding APIinterfacementioned in the previous point.
For example, the Logic component (see the class diagram given below) defines its API in the Logic.java interface and exposes its functionality using the LogicManager.java class which implements the Logic interface.

How the architecture components interact with each other
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delete 1.

The sections below give more details of each component.
UI component

API :
Ui.java
The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, PassengerListPanel, StatusBarFooter etc. All these, including the MainWindow, inherit from the abstract UiPart class.
The UI component uses JavaFx UI framework. The layout of these UI parts are defined in matching .fxml files that are in the src/main/resources/view folder. For example, the layout of the MainWindow is specified in MainWindow.fxml
The UI component,
- Executes user commands using the
Logiccomponent. - Listens for changes to
Modeldata so that the UI can be updated with the modified data.
Logic component

API :
Logic.java
-
Logicuses theAddressBookParserclass to parse the user command. - This results in a
Commandobject which is executed by theLogicManager. - The command execution can affect the
Model(e.g. adding a passenger). - The result of the command execution is encapsulated as a
CommandResultobject which is passed back to theUi. - In addition, the
CommandResultobject can also instruct theUito perform certain actions, such as displaying help to the user.
Given below is the Sequence Diagram for interactions within the Logic component for the execute("delete 1 2") API call. This is also explained below.

DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Model component

API : Model.java
The Model,
- stores a
UserPrefobject that represents the user’s preferences. - stores the GME terminal data.
- exposes an unmodifiable
ObservableList<Passenger>andObservableList<Pool>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.
Tag list in the AddressBook, which Passenger references. This allows AddressBook to only require one Tag object per unique Tag, instead of each Passenger needing their own Tag object.
Storage component

API : Storage.java
The Storage component,
- can save
UserPrefobjects in json format and read it back. - can save the address book data in json format and read it back.
Common classes
Classes used by multiple components are in the seedu.addressbook.commons package.
Implementation
This section describes some noteworthy details on how certain features are implemented.
Model
The class diagram for the Model can be seen above in the Design section. Such a design was chosen after a few iterations on other designs. One such design is briefly documented as below:
v1.2

In v1.2, Passenger has-an optional Driver, which was initially chosen for its ease of implementation and storage. However, it was spotted that this would lead to issues in future when implementing trips on multiple days, since each Driver would have their own times, leading to a lot of duplication of Drivers. Further, this was not an easy format to display to the user intuitively, and would require a traverse of the whole Passenger list just to group Passengers by Drivers.
Implementation
Therefore, the decision was made to encapsulate the details of each trip (which is a trip by 1 driver with multiple passengers), into a Pool class. This Pool class would have it’s own CRUD, and would contain a Driver, Passengers, TripDay and TripTime.
This is done to facilitate Storage and UI, and also from a Users perspective, to allow for Pools with timings that may be slightly different from the Passengers preferred time.
A package Pool containing class Pool and UniquePoolList was created. This package performs a function that is similar to the Passenger package, exposing CRUD operations through ModelManager.
The decision was also made to make Passenger and Driver extend Person, so that for future iterations, we can support a Driver who is also a Passenger with minimal changes to the code.
Storage
As above, with regards to Model, the initial implementation of Storage was simply to store a Driver as a String field inside Passenger.
However, this involved extra parsing to ensure that the Driver String was still a valid Driver on load. Therefore, Driver was also made into a Jackson JsonProperty.
The class diagram for Storage can be found above.
Implementation
As of v1.3, the relation between Driver and Passenger is encapsulated in a Pool. All of Driver, Passenger, Pool and Tag are stored as JSON Objects. The choice was also made to store all data in 1 file, for ease of portability, such that the user only needs to manage 1 file.
At a high level, the JSON file is structured as such:

The Passengers are duplicated between the Passenger list and each of the Pools that reference the Passenger simply so we can reuse the JsonSerializablePassenger structure. This association would be much better represented in a RDBMS, which would be an easy change for a potential future iteration.
JsonSerializableAddressBook implements checks to ensure the following from the read JSON file:
- There are no duplicate Passengers
- There are no duplicate Pools
- No more than one Pool can reference a single Passenger
- There are no Pools that reference a Passenger that does not exist
This is to ensure the sanitization of data that is read from JSON, if the user decides to edit the JSON file directly.
Pool feature
This feature allows users to create and add a pool to the list of pools, through the use of a pool command.
Design considerations include the pool command being able to be used in conjunction with the find command. For instance, the user would
first use find tag/female and then followed by pool n/Alice p/91234567 d/MONDAY t/1930 c/2 c/3.
The find tag/female command first filters the list of displayed passengers, such that only passengers with the female tag would be displayed. Calling the pool command
would then assign Alice with number 91234567 to be the driver of the passengers specified by the indices for the currently displayed list.
The activity diagram below encapsulates the user workflow of adding passengers, finding passengers and then pooling the passengers:

The rationale behind this implementation was because once the GME terminal is populated with a large number of passengers, it would be rather difficult for the user to find a specific passenger. By allowing the user to first filter the passengers then subsequently pooling from the filtered list would greatly enhance the feature, thereby making the product much more cohesive as features work well together.
Given below is the Sequence Diagram for interactions within the Logic component for the execute("pool n/Alice p/91234567 d/monday t/1930 c/2 c/3") command.

command argument that is passed into
execute(), represents the string "pool n/Alice p/91234567 d/monday t/1930 c/2 c/3", and has been abstracted for readability.
The lifeline for
PoolCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
From the diagram illustrated above:
-
LogicManagerhas itsexecute()method called when a user enters the"pool n/Alice p/91234567 d/monday t/1930 c/2 c/3"command. -
AddressBookParserclass is then accessed, which subsequently instantiatesPoolCommandParserclass to help parse the user’s command. -
AddressBookParserwould then have itsparse()method invoked to parse the arguments of"n/Alice p/91234567 d/monday t/1930 c/2 c/3"toPoolCommandParserwhich creates and returns aPoolCommand. -
LogicManagerwould subsequently invoke theexecute()method of thePoolCommand, which in turn calls its own method ofgetPassengersFromIndexes()that gets a list of passengers fromModelby callinggetFilteredPassengerList(). - A
Poolobject is then instantiated with the list of passengers returned bygetPassengersFromIndexes(), and then added to the model by theaddPool()method. - The model filtered pool list is then updated with
updateFilteredPoolList()with a predicate to show all pools in the listPREDICATE_SHOW_ALL_POOLS. - Finally, a
CommandResultwould be instantiated to indicate the completion status of the command and returned back toLogicManager.
It is worth noting that in the case of adding a passenger, a Passenger object is created by AddCommandParser and used in the constructor of AddCommand.
However, in the case of adding a pool, a PoolCommand is constructed using the details specified and parsed from PoolCommandParser, instead of creating and passing a Pool object.
The rationale is due the fact that a list of passengers have to be obtained from the indexes specified, which requires interactions with the model.
The current implementation thus encapsulates all the interactions with model, within the methods of PoolCommand.
ListPool feature
This feature allows users to list all the pools from the pool list without any filter.
Given below is the Sequence Diagram for interactions within the Logic component for the execute("listPool").

From the diagram illustrated above:
-
LogicManagerhas itsexecute()method called when a user enters the"listPool"command. -
AddressBookParserclass is then accessed, which subsequently instantiates anListPoolCommandobject to be returned toLogicManager. -
LogicManagerwould subsequently invoke theexecute()method of theListPoolCommand. - The model filtered pool list is then updated with
updateFilteredPoolList()with a predicate to show all pools in the listPREDICATE_SHOW_ALL_POOLS. - Finally, a
CommandResultwould be instantiated to indicate the completion status of the command and returned back toLogicManager.
Unpool feature
This feature allows users to remove a pool from the pool list through the specification of an index.
Given below is the Sequence Diagram for interactions within the Logic component for the execute("unpool 1").

UnpoolCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
From the diagram illustrated above:
-
LogicManagerhas itsexecute()method called when a user enters the"unpool 1"command. -
AddressBookParserclass is then accessed, which subsequently instantiatesUnpoolCommandParserclass to help parse the user’s command. -
AddressBookParserwould then have itsparse()method invoked, passing the argument"1"toUnpoolCommandParser. - Given that the index
"1"is a valid index, anUnpoolCommandobject would be instantiated and returned toLogicManager. -
LogicManagerwould subsequently invoke theexecute()method of theUnpoolCommandwhich in turn invokesdeletePool()method with an argument of1. - This would update the model by deleting the specified pool at the first index, then a
CommandResultwould be instantiated to indicate the completion status of the command and returned back toLogicManager.
FindPool feature
This feature allows users to find a pool that contains a passenger with a provided keyword in their name.
Design considerations include the findPool command being able to be used in conjunction with the pool or unpool command. Due to the limitations of the current iteration of GME, each passenger can only belong to one pool. As the number of passengers and pools increases, it may be hard to keep track of the passengers that exist in pools and those that do not, thus, the user might attempt to create a new pool with a passenger and be informed that the passenger already exists in a pool. The findPool feature thus allows the user to find the pool that the passenger already exists in to either confirm if they are in the correctly assigned pool, or unpool them if they are not. The findPool command works similarly to the find command, except that it currently only supports the use of the name prefix: “n/”
The activity diagram below encapsulates the user workflow of attempting to pool a passenger, finding out that the passenger already exists in a pool, and using the findPool command to rectify the issue:

The rationale behind this implementation was because once the GME terminal is populated with a large number of pools, it would be rather difficult for the user to find a specific pool that includes a specific passenger. This could make it difficult to pool a passenger if they already exist in another pool. By allowing the user to filter the pools by the passengers they include, the user will be able to quickly find the pools that include the passenger they are attempting to pool, allowing them to confirm if they have been assigned to the right pool or to rectify the issue if they have not.
Given below is the Sequence Diagram for interactions within the Logic component for the execute("findPool n/Alice") command.

command argument that is passed into
execute(), represents the string "findPool n/Alice", and has been abstracted for readability.
The lifeline for
FindPoolCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
From the diagram illustrated above:
-
LogicManagerhas itsexecute()method called when a user enters the"findPool n/Alice"command. -
AddressBookParserclass is then accessed, which subsequently createsFindPoolCommandParserclass to help parse the user’s command. -
AddressBookParserwould then have itsparse()method invoked to parse the argument"n/Alice"and passes it toFindPoolCommandParser. -
FindPoolCommandParserparses the argument"n/Alice"and creates aPooledPassengerContainsKeywordPredicatewhich is returned to theFindPoolCommandParser. -
FindPoolCommandParserthen creates aFindPoolCommand, and provides the newly createdPooledPassengerContainsKeywordPredicateto it. TheFindPoolCommandobject is then returned toLogicManager. -
LogicManagerwould subsequently invoke theexecute()method of theFindPoolCommand, which in turn calls theupdateFilteredPoolList()method inModel, causing the shown pool list to be updated according to the predicate in theFindPoolCommandobject. - A
Poolobject is then created with the list of passengers returned bygetPassengersFromIndexes(), and then added to the model by theaddPool()method. - Finally, a
CommandResultwould be returned toLogicManagerto indicate the completion status of the command.
Find feature
The rationale behind expanding on the find feature is to allow for the user to find passengers by more attributes to improve usability. Instead of being restricted to searching for names only, the user can now find other passengers with the same day or of a certain area. This is vital as it is necessary to improve the usability for the user when attempting to find passengers to carpool with drivers.

command argument that is passed into
execute(), represents the string "find n/Lucy n/Adam", and has been abstracted for readability.
The lifeline for
FindCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
From the diagram illustrated above:
-
LogicManagerhas itsexecute()method called when a user enters the"find n/Lucy n/Adam"command. - Object of
AddressBookParserclass is then accessed, which then subsequently createsFindCommandParserclass object to help parse the user’s command. -
AddressBookParserwould then invoke theparse()method ofFindCommandParser, with parametersn/Lucy n/Adam, to parse the argumentsn/Lucy n/Adam. -
FindCommandParserparses the argumentsn/Lucy n/Adamand creates aNameContainsKeywordPredicateobject namedpredicatewhich is returned to theFindCommandParserobject. -
FindCommandParserthen instantiates aFindCommandobject withpredicateas a parameter. TheFindCommandobject is then returned toLogicManager. -
LogicManagerwould subsequently invoke theexecute()method ofFindCommand, which in turn calls theupdateFilteredPoolList()method inModel, causing the shown pool list to be updated according topredicatein theFindCommandobject. - A
CommandResultobject is then created with a message which includes the number of passengers found on the list updated byupdateFilteredPoolList(). - Finally, the
CommandResultobject is returned toLogicManager.
Delete feature
This feature was adapted from AB-3. It allows users to delete Passengers.
Design considerations include being able to delete multiplePassengers with one command, and prevent the deletion of any Passengers that are currently in a Pool. This is done to prevent any accidental deletions of Passengers without either party being informed.
Given below is the Sequence Diagram for interactions within the Logic component for the delete 1 2 command

DeleteCommandParser and DeleteCommand should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
From the diagram illustrated above:
-
LogicManagerhas itsexecute()method called when a user enters the"delete 1 2"command. - Object of
AddressBookParserclass is then accessed, which then subsequently createsDeleteCommandParserclass object to help parse the user’s command. -
AddressBookParserwould then invoke theparse()method ofDeleteCommandParser, with parameters1 2. -
DeleteCommandParserinvokes theparseDeleteIndex()method ofParserUtil, with the arguments"1 2", which splits the arguments into tokens via whitespace. -
ParserUtilself invokesparseIndex()on each token, which is used for parsing single indexes, and returns all theIndexobjects created toDeleteCommandParserasindexes. -
DeleteCommandParserthen instantiates aDeleteCommandobject withindexesas a parameter. TheDeleteCommandobject is then returned toLogicManager. -
LogicManagerwould subsequently invoke theexecute()method ofDeleteCommand, which in turn calls thegetFilteredPassengerList()method inModel, to get the current passenger list being shown to the user aslastShownList. -
lastShownListis then iterated through to and each passenger is passed toModelviahasPoolWithPassenger(), to check if that passenger is indeed currently beingPooled.- If any
Passengeris found to be contained in aPool, a newCommandExceptionis thrown, informing the user as such.
- If any
- After checking that it is indeed safe to delete all the
PassengersinlastShownList, eachPassengeris then deleted inModelvia passing it to thedeletePassenger()method. - A
CommandResultobject is then created with a message which includes the names of thePassengersdeleted, inlastShownList - Finally, the
CommandResultobject is returned toLogicManager.
Documentation, logging, testing, configuration, dev-ops
Appendix: Requirements
Product scope
Target user profile:
- a HR executive who is required to find and pool passengers with drivers from an already existing database.
- prefer desktop apps over other types
- is able to type fast
- prefers typing to mouse interactions
- is reasonably comfortable using CLI apps
Value proposition: Greater ease of use in managing driver and passenger profiles as compared to an Excel sheet.
User Stories
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a … | I want to … | So that |
|---|---|---|---|
| * * * | HR Executive | allocate drivers to passengers to be picked up | I can arrange carpooling trips for my colleagues |
| * * * | HR Executive | search for specific type of passengers | I can see if any passengers fulfil a criteria and view their carpool details |
| * * * | HR Executive | list all passengers | I can see all the passengers available |
| * * * | HR Executive | create a profile | I can easily manage and track drivers and passengers |
| * * * | HR Executive | delete employee profile | passenger’s data will not be stored when they are no longer looking to carpool |
| * * | HR Executive | filter passengers’ based on their preference for female drivers | their concerns for their personal safety are taken into account |
| * * | HR Executive | filter passengers’ destination based on location | drivers are not heavily inconvenienced to pick up passengers |
| * * | HR Executive | edit drop off location | passengers and drivers who have negotiated a new drop off location can be easily updated |
| * | HR Executive | indicate the price willing to pay | drivers are more likely to choose these passengers |
Use Cases
System: HR executive’s terminal
Use case: UC01 - Allocate drivers to passengers to be picked up
Actor: User
MSS:
- User lists out passengers available to be picked up.
- GME shows a list of passengers.
- User chooses and view the details of the specific passenger.
-
User allocates drivers to specific passenger to the driver’s carpooling group.
Use case ends.
Extensions
-
1a. User searches for a passenger (UC02).
Use case ends.
System: HR executive’s terminal
Use case: UC02 - Search for specific type of passengers
Actor: User
MSS:
- HR executive chooses the criteria that the passengers need to fulfil in order to be picked up.
- HR exective initiates the search.
-
GME shows a list of passengers that fulfils the criteria.
Use case ends.
Extensions
- 3a. No passenger fulfils the criteria.
- 3a1. GME shows empty list.
Use case ends.
System: HR executive’s terminal
Use case: UC03 - Create a passenger profile
Actor: User
MSS:
- HR exeuctive fills out the passenger’s name, contact number and pickup address.
- GME verifies that all the required fields are not empty.
-
GME adds passenger’s details to GME.
Use case ends.
Extensions
- 2a. Any required field is missing.
-
2a1. GME warns the user to input the data missing.
Use case ends.
-
System: HR executive’s terminal
Use case: UC04 - Delete a passenger profile
Actor: User
MSS:
- HR exeuctive indicates they would like to delete a passenger profile.
- GME verifies that passenger exists.
-
GME deletes the specific passenger’s profile.
Use case ends.
Extensions
- 2a. Index number of passenger does not exist.
-
2a1. GME warns that no such passenger exists.
Use case ends.
-
Non-Functional Requirements
-
Usability:
- GME shall work on any mainstream OS as long as it has Java
11or above installed. - GME’s interface shall be user-friendly and easy to use by using mouse when not using commands, meaning all buttons and interaction should be self-explanatory and intuitive which can be used by people without training.
- A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
- GME shall work on any mainstream OS as long as it has Java
-
Reliability:
- GME shall allow drivers to pick passengers throughout the week ant any time during the day, up to 6 passengers depending on car size.
- GME Should be able to hold up to 1000 persons (drivers and passengers included) without a noticeable sluggishness in performance for typical usage.
-
Security:
- Only users that creates their own profile can view their private information and change the privacy settings
-
Integrity
- All monetary amounts (including passenger’s tips) must be accurate to two decimal places and in SGD.
- All geolocation coordinates must be accurate to six decimal places.
- All email and phone numbers provided by users must pass through format check.
- All time-related data that is presented to user must be accurate to minutes, and use
DD-MM-YYYYformat - All timestamps for any events occurred recorded by the GME shall be in UTC (Universal Time Coordinated) when placed into permanent storage.
-
Flexibility
- GME shall be able to process different date formats input by user and converts to
DD-MM-YYYY
- GME shall be able to process different date formats input by user and converts to
Glossary
| Term used | Meaning | |
|---|---|---|
| Pool | A group of employees carpooling together. Consists of one driver and at least one passenger. The pools generated for a specifc day and time are the same every week unless reorganised by the user. Passenger | An employee carpooling with at least one driver. |
| TripDay | Day of the intended carpooling trip. | |
| TripTime | Time of the intended carpooling trip. | |
| Tag | A miscellaneous piece of information about the pool, passenger, or driver that isn’t captured by the other fields but is good to have. | |
| Price | The amount of money a passenger is willing to pay for the carpooling trip. | |
| Alphanumeric | A combination of letters and numbers only. | |
| Home Folder | The folder where the app’s data will be stored | |
| GME | GreenMileageEfforts, this software that is used to arrange carpooling. | |
| Passenger | An employee carpooling with at least one driver. | |
| Driver | An employee that is in-charge of driving passengers within the pool to their location. | |
| Mainstream OS | Windows, Linux, Unix, MacOS. | |
| Command Line Interface (CLI) | An interface that relies primarily on text input and little to no point and click UI elements exist. |
Appendix: Instructions for manual testing
Given below are instructions to test the app manually.
Launch and shutdown
-
Initial launch.
-
Download the jar file and copy into an empty folder.
-
Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
-
-
Saving window preferences.
-
Resize the window to an optimum size. Move the window to a different location. Close the window.
-
Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-
Creating a pool
-
Creating a pool from using the list of all passengers being shown.
-
Prerequisites: List all passengers using the
listcommand. Multiple passengers in the list, with the first four passengers having the same the trip day ofMONDAYand trip time of1930. This can be achieved through the editing the details of the passengers with theeditcommand and thed/andt/prefixes. The remaining passengers must have a different trip day and trip time fromMONDAYand1930respectively. -
Test case:
pool n/Paul p/90101231 d/MONDAY t/1930 c/1 c/2Expected: A pool is created and added to the pool list, with a trip by the driver named
Paul, phone number90101231, atMONDAY 1930. Names of the passengers from the passenger list at index 1 and 2 are also displayed in the pool. Status message shows the details of the pool created. -
Test case:
pool n/Sarah p/96663777 d/MONDAY t/1400 c/3 c/4Expected: A pool is created and added to the pool list, with a trip by the driver named
Sarah, phone number96663777, atMONDAY 1400. Names of the passengers from the passenger list at index 3 and 4 are also displayed in the pool. Status message shows a message to warn the user that there are passengers with a time difference of more than 15 minutes of the pool time. -
Test case:
pool n/Patricia p/90102020 d/WEDNESDAY t/1930 c/1 c/5Expected: No pool is added. Error details shown in the status message, prompting user to check for a trip day mismatch. Text in command bar turns red.
-
Test case:
pool n/Jose p/85553777 d/MONDAY t/1930 c/0Expected: No pool is added. Error details shown in the status message. Text in command bar turns red.
-
Deleting a pool
-
Deleting a pool while all pools are being shown.
-
Prerequisites: List all pools using the
listPoolcommand. Multiple pools in the list. -
Test case:
unpool 1Expected: First pool is deleted from the list. Details of the deleted pool shown in the status message.
-
Test case:
unpool 0Expected: No pool is deleted. Error details shown in the status message. Status bar remains the same.
-
Other incorrect unpool commands to try:
unpool,unpool x,...(where x is larger than the list size)Expected: Similar to previous.
-
Deleting a passenger
-
Deleting a passenger while all passengers are being shown.
-
Prerequisites: List all passengers using the
listcommand. Multiple passengers in the list. Passengers to be deleted are not in a pool. -
Test case:
delete 1.
Expected: First contact is deleted from the list. Name of the deleted contact shown in the status message. -
Test case:
delete 0.
Expected: No passenger is deleted. Error details shown in the status message. Text in command bar turns red. -
Other incorrect delete commands to try:
delete,delete x,...(where x is larger than the list size).
Expected: Similar to previous.
-
-
Deleting multiple passengers while all passengers are being shown.
-
Prerequisites: List all passengers using the
listcommand. Multiple passengers in the list. Passengers to be deleted are not in a pool. -
Test case:
delete 1 2.
Expected: First and second contact is deleted from the list. Names of deleted contacts are shown in the status message.
-
Finding a passenger
-
Finding passengers by name while all passengers shown.
-
Prerequisites: Newly generated sample data is used. This can be done by deleting
data/GMEdata.json. All passengers listed usinglist. -
Test case:
find n/bernice.
Expected: Details of passenger namedBernice Yuis shown. Status message shows 1 passenger listed. -
Test case:
find n/bob.
Expected: No passengers are shown. Status message shows 0 passenger listed. -
Test case:
find n/ROY n/lEnny.
Expected: Details of passengers namedRoy BalakrishnanandLenny Hoonshown. Status message shows 2 passengers listed. -
Test case:
find n/ David lI.
Expected: Details of passenger namedDavid Liis shown. Status message shows 1 passenger listed.
-
-
Finding passengers by tag while all passengers are shown.
-
Prerequisites: Newly generated sample data is used. This can be done by deleting
data/GMEdata.json. All passengers listed usinglist. -
Test case:
find tag/finance.
Expected: Details ofBernice YuandRoy Balakrishnanare shown. Status message shows 2 passengers listed. -
Test case:
find tag/marketing tag/sales.
Expected: Details ofAlex Yeoh,Bernice Yu,Irfan IbrahimandTurner Peckare shown. Status message shows 4 passengers listed. -
Test case:
find tag/marketing sales.
Expected: Passengers are shown are same as previous. Status message shows tag provided is invalid.
-
Finding a pool
-
Finding a pool while all pools are being shown.
-
Prerequisites: Newly generated sample data is used. This can be done by deleting
data/GMEdata.json. All pools listed usinglistPool. -
Test case:
findPool n/lenny.
Expected: Details of only the pool withAlan Poh,Lenny Hoon, andTurner Peckis shown. Status message shows 1 pool listed. -
Test case:
findPool n/michael.
Expected: No pools are listed. Status message shows 0 pool listed. -
Test case:
findPool n/....
Expected: Pool list on right pane shows no change. Error details shown in the status message. -
Other variations to use after the prefix n/:
///,?#$%,..., any other non alphanumeric characters.
Expected: Similar to previous.
-
Editing a passenger
-
Editing passengers with 1 parameter while all passengers shown.
-
Prerequisites: Newly generated sample data is used. This can be done by deleting
data/GMEdata.json. All passengers listed usinglist. -
Test case:
edit 1 n/Alice.
Expected: Name of passenger previously namedAlex Yeohis changed toAlice. Status message shows all the details ofAlice. -
Test Case:
edit 0 n/Alice.
Expected: No passenger is edited. Result box shows error:One of the passenger indexes provided is invalid. Command box text turns red. -
Other incorrect edit commands to try:
edit n/Alice,edit x n/Alice, … (where x is larger than the list size). Expected: Similar to previous.
-
- Editing passengers with multiple parameters while all passengers shown.
-
Prerequisites: Newly generated sample data is used. This can be done by deleting
data/GMEdata.json. All passengers listed usinglist. -
Test case:
edit 1 p/12345678 a/Floor Street tag/abcd.
Expected: Phone number, address, and tag of passenger namedAliceis changed to12345678,Floor Street, andabcdrespectively. Status message shows all the new details ofAlice
-
- Editing passenger to match an existing passenger’s identity.
-
Prerequisites: Using sample passengers, list all passengers using the
listcommand. Multiple passengers in the list. -
Test case:
edit 1 n/Bernice Yu p/99272758.
Expected: No passenger is edited. Result box shows error:This passenger already exists in the GME Terminal.. Command box text turns red.
-
- Editing passenger that is in a Pool.
-
Prerequisites: Newly generated sample data is used. This can be done by deleting
data/GMEdata.json. All passengers listed usinglist. All pools listed usinglistPool. -
Test case:
edit 7 n/Kelly.
Expected: Name of passenger previously namedKristen Woois changed toKelly. Status message shows all the details ofKelly.Trip by Irfan Ibrahimin Pool list updates toRoy Balakrishnan, Kelly. -
Test case:
edit 7 d/TUESDAY.
Expected: No passenger is edited. Result box shows error:TThe Passenger to be edited exists in a pool. Day cannot be edited.. Command box text turns red. -
Test case:
edit 7 t/1400.
Expected: Time of passenger namedKellyis changed to1400. Status message shows all the details ofKelly, andNOTE: The passenger edited exists in a pool and has had their preferred trip time edited. This might result in a time difference of more than 15 minutes with the pool time.
-
Appendix: Effort
The creation of GreenMileageEfforts came with a great deal of effort from each of the team members. Since the start of the project we have made the effort to consistently conduct team meetings every week, most of these meetings were held in physical settings such that we could communicate our ideas effectively. Upon completion of the project, we have achieved a product that is a direct reflection of our hard work and determination. GreenMileageEfforts is a product that has been adapted and morphed from AB3, where there have been significant enhancements made since AB3.
Challenges faced, Effort and Achievement
The following section describes the challenges our team faced in this project, the efforts we took to overcome it, as well as what we have achieved as a result of the efforts we have taken.
Extension of Model
As our group had initially decided on morphing the existing AB3, changes to the model consisted mainly of refactoring existing classes. Although a rather trivial task, this process was rather time-consuming and tedious. Due to the scale of the existing AB3 code, some difficulty was encountered during this refactoring stage as some making seemingly minute changes in method signatures or names would result in a need to edit other segments of affected code. Although the use of IntelliJ’s toolbox greatly sped up the process, the nature of some of the refactoring changes we intended to make meant that some of said changes were not as easily detected by IntelliJ, resulting in some uncaught bugs following our refactoring stage. The brownfield nature of the project also led to some difficulty in understanding the model and how the different modules interact with each other.
Towards the end of the first milestone, every team member had a better understanding of the existing code allowing for a better segmentation of work. As this was also the period where new additions were made to the existing AB3 model instead of simple refactoring, there was also less confusion surrounding what components of the model needed to be modified. This was also helped by the fact that in the case of adding features, we had a clearer idea of what needed to be done for the new feature instead of following the trails of an existing one. However, some difficulty was still present as the original AB3 dealt only with a list of one entity(person) while our intended final product would have to handle a list of two entities that interact with each other (Passenger and Pool). These interactions between the two entities led to some difficulty in the implementation of CRUD commands and in coding to avoid too much cyclic dependency.
However, by the end of the second milestone, many of us have a firm grasp of the model and its components. This allowed us to make improvements to not just to the code of the features we had added, but also to the code that was existed in the original AB3.
Reworking of drive command to pool command
The initial concept for this product included two commands drive and undrive which was later reworked to pool and unpool after much discussion with the team to better suit the needs of our users.
These changes were made after the addition of a pool list to the model. Prior to the change, the passengers in the model consisted of a driver with a phone number attached to it,
where drive was intended to be implemented in a way which merely edits the driver field in each passenger. Likewise, undrive was intended to be implemented to edit the driver field within the
specified passengers to be empty. Upon extension of the model to include a list of pools, pool was implemented to add a pool to the list, while unpool was implemented to delete a pool from the list.
This change involved a significant amount of effort from all of our team members, as the change involved almost all components of the project.
Each team member tested their own component as extensively as possible before integration of the parts together, eventually coming together to fix the bugs that came from integration.
As a result, we have achieved a product that is relatively bug-free and extensible as each component has already be properly tested.
Extension and rework of UI
While the user interface of AB3 consists of one panel to illustrate a list of persons, GreenMileageEfforts was required to illustrate a list of passengers as well as a list of pools. This was not a trivial task, as each of the panels had their own set of commands such as adding, deleting and filtering. On top of that, enhancements were made to ensure a cleaner looking user interface that is the current GreenMileageEfforts product today.
Extension of find command
The initial implementation of find inherited from AB3 only allowed users to search by names.
To improve usability for users, we introduced searching of other fields of a passenger.
While implementing the first iteration in v1.2, it took some additional time as it took some time to understand which classes interacted with each other when find was executed.
This was harder to understand as there was no sequence diagram included for the find command as well.
To implement the command, a predicate was needed for each of the attributes as well as the parsing of the arguments in FindCommandParser to allow for different type of searches to be possible.
Extension of delete command
The initial implementation of delete inherited from AB3 only allowed users to delete 1 passenger at a time.
To improve usability for users, we introduced multi-passenger deletion using indexes.
The first iteration of this allowed for passengers to be deleted despite some other passengers being already in a pool.
This was later revised to prevent users from executing delete all together when there are passengers still in a pool.
This was chosen as better code quality could be achieved through such a decision.
Workflow
At the start of the project, work delegation and flow was not ideal, where one team member had to wait for the changes that another had to make.
For instance, while one team member added new fields such as (TripTime and TripDay), another team member was tasked to update the logic of Add and Edit command for the new fields.
Upon a post-mortem to reflect and evaluate our workflow, we managed to refine our workflow to make it much more efficient by the second milestone, this included the proper
segmentation and delegation of work into its features. Finally, by doing so we have achieved a far better workflow by the end of the project that enabled us to create the GreenMileageEfforts product as it is today.