Developer Guide
- Setting up, getting started
- Design
-
Implementation
- Add contact command
- Edit contact command
- Modelling Meetings
- Add meeting command
- Edit meeting command
- Delete contact command
- Delete meeting command
- Find contact command
- Remind meeting command
- Edit userpref command
- Find meeting command
- List meeting & contact command
- Clear meeting & contact command
- Undo command
- System Timer
- Documentation, logging, testing, configuration, dev-ops
-
Appendix: Requirements
- Product scope
- User stories
-
Use cases
- Use case: UC01 - Add a contact
- Use case: UC02 - Add a meeting and its participants
- Use case: UC03 - List all contacts or all meetings
- Use case: UC04 - Edit a contact
- Use case: UC05 - Edit a meeting
- Use case: UC06 - Delete participant from the meeting
- Use case: UC07 - Find a contact or a meeting
- Use case: UC08 - Delete a contact or a meeting
- Use case: UC09 - Clear all contacts or meetings
- Use case: UC10 - Export all meetings
- Use case: UC11 - Undo commands
- Non-Functional Requirements
- Glossary
- Appendix: Effort
- Appendix: Instructions for manual testing
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
interface
with the same name as the Component. - exposes its functionality using a concrete
{Component Name}Manager
class (which implements the corresponding APIinterface
mentioned 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 deletemeeting 1
.
The sections below give more details of each component.
UI component
API :
Ui.java
The UI Diagram given above explains the UI of the app. The UI consists of a MainWindow
that is made up of parts e.g.CommandBox
, ResultDisplay
, PersonListPanel
, 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
Logic
component. - Listens for changes to
Model
data so that the UI can be updated with the modified data. - Sometimes, Scheduler has a reference to UI to force an update to the UI based on current time. This is helpful for changing the location of the green bar and popup reminders.
Logic component
API :
Logic.java
The Logic Diagram given above explains the logic of the app.
-
Logic
uses theAddressBookParser
class to parse the user command. - This results in a
Command
object which is executed by theLogicManager
. - The command execution can affect the
Model
(e.g. adding a person). - The result of the command execution is encapsulated as a
CommandResult
object which is passed back to theUi
. - In addition, the
CommandResult
object can also instruct theUi
to 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("deletemeeting 1")
API call.
DeleteMeetingCommandParser
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 Diagram given above explains the Models of the app that are used to store most app data.
The Model
,
- stores a
UserPref
object that represents the user’s preferences. - stores the data of contacts and meetings.
- exposes unmodifiable
ObservableList<Person>
andObservableList<Meeting>
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 Person
references. This allows AddressBook
to only require one Tag
object per unique Tag
, instead of each Person
needing their own Tag
object.Storage component
API : Storage.java
The Storage Diagram given above explains the Storage of the app, how data is stored in files outside of the app.
The Storage
component,
- can save
UserPref
objects 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.
Add contact command
Implementation
The add meeting mechanism is facilitated by AddContactCommandParser
and AddContactCommand
which extend Parser
and
Command
respectively. AddContactCommandParser
is responsible for parsing the user’s inputs to generate a new
AddMeetingCommand
with meeting, which then adds the meeting into the AddressBook.
Here are some of the most important operations implemented:
-
AddContactCommandParser#parse()
— Parse the user inputs to create a new person -
AddContactCommand#execute()
— Add a new person in the model if it is valid and not a duplicate.
The AddContactCommand#execute()
is exposed in the Model
interface as Model#addPerson()
and Model#hasPerson(meeting)
.
The following sequence diagram shows how the add contact operation works:
AddContactCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The following activity diagram summarizes the flow of events when a contact is being added:
Edit contact command
Implementation
The edit meeting mechanism is facilitated by EditContactCommandParser
and EditContactCommand
which extend Parser
and
Command
respectively. EditContactCommandParser
is responsible for parsing the user’s inputs to generate a new
EditContactCommand
which then modifies a meeting at a specific index.
Here are some of the most important operations implemented:
-
EditContactCommandParser#parse()
— Parse the user inputs to create an edited meeting -
EditContactCommand#execute()
— Add the edited meeting if it is not a duplicate and if its time does not clash with other meetings
The EditContactCommand#execute()
is exposed in the Model
interface as Model#setPerson()
and Model#hasPerson(meeting)
.
The following sequence diagram shows how the edit contact operation works:
EditContactCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The following activity diagram summarizes the flow of events when a contact is being added (Note that less important details are omitted for better clarity):
Modelling Meetings
Implementation
The Meetings class and meeting details classes are adapted from the code for Persons and person details.
The following is the Class Diagram for the meetings feature.
The Meetings class and meeting details classes are adapted from the code for Persons and person details. The Meeting class contains two methods that are not present in the Person class:
-
addParticipant(Person person)
— Adds person as a participant of the meeting. -
delParticipant(Index index)
— Deletes the participant at index from the meeting’s list of participants.
The following sequence diagram shows how the delete participant operation works:
DeleteParticipantCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The addParticipant
command does the opposite with a similar sequence — it calls Meeting#addParticipant(person)
.
The following activity diagram summarizes what happens when a user executes a delete participant command:
Design consideration:
Aspect: Why not make participants an attribute?
- Adding participants through index is not effectively when the contact base is large. On the other hand, using separate commands provides the possibility of combinatorial commands to improve efficiency. For instance,
FindContactCommand
can be applied betweenAddMeetingCommand
andAddParticipantCommand
, making it easier to locate the intended contact.
Add meeting command
Implementation
The add meeting mechanism is facilitated by AddMeetingCommandParser
and AddMeetingCommand
which extend Parser
and
Command
respectively. AddMeetingCommandParser
is responsible for parsing the user’s inputs to generate a new
AddMeetingCommand
with meeting, which then adds the meeting into the AddressBook.
Here are some of the most important operations implemented:
-
AddMeetingCommandParser#parse()
— Parse the user inputs to create a new meeting -
AddMeetingCommand#execute()
— Add a new meeting in the model if it is valid and not a duplicate.
The AddMeetingCommand#execute()
is exposed in the Model
interface as Model#addMeeting()
, Model#hasConflict(meeting)
and Model#sortMeeting()
.
Given below is a description on the flow of the add meeting mechanism behaves:
- The user enters a new input for the addmeeting command
- The
AddMeetingCommand#parse()
is called to parse the user inputs and create a new meeting object based on the inputs if all required prefixes are present. Else, aParseException
will be thrown and the user will be prompted to fill in all required fields. - Upon successful parsing,
AddMeetingCommand#execute()
will be called. It will first check if the added meeting is unique and if not, it will throw aCommandException
and not add the meeting. - Then,
AddMeetingCommand#execute()
will also check if the meeting has any clashingdate
with any other meeting and throw aCommandException
and not add the meeting if so. - If a meeting is unique and has no clashing
date
, thenModel#addMeeting()
is called to add the meeting. - Lastly,
Model#sortMeeting()
is called to sort theUniqueMeetingList
to make sure that all meetings are arranged according to time.
The following activity diagram summarizes the flow of events when a meeting is being added:
The following sequence diagram shows how the add meeting operation works:
AddMeetingCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Design consideration:
Aspect: Algorithm for conflict checking
- checks for conflict by comparing the meeting toAdd and its nearest past and future meetings in this list by taking advantage of meeting list being sorted at all time
- this ensures that new interval value will not cause planned meetings to conflict with each other
Edit meeting command
Implementation
The edit meeting mechanism is facilitated by EditMeetingCommandParser
and EditMeetingCommand
which extend Parser
and
Command
respectively. EditMeetingCommandParser
is responsible for parsing the user’s inputs to generate a new
EditMeetingCommand
which then modifies a meeting at a specific index.
Here are some of the most important operations implemented:
-
EditMeetingCommandParser#parse()
— Parse the user inputs to create an edited meeting -
EditMeetingCommand#execute()
— Add the edited meeting if it is not a duplicate and if its time does not clash with other meetings
The EditMeetingCommand#execute()
is exposed in the Model
interface as Model#setMeeting()
, Model#hasConflict(meeting)
and Model#sortMeeting()
.
Given below is a description on the flow of the edit meeting mechanism behaves:
- The user enters a new input for the editmeeting command
- The
EditMeetingCommandParser#parse()
is called to parse the user inputs and create aEditMeetingDescriptor
object based on the inputs if a valid index (in this step, a positive integer suffices) is provided. Else, aParseException
will be thrown and the user will be prompted to fill in all required fields. - Upon successful parsing,
EditMeetingCommand#execute()
will be called to check if there is an existing meeting at the specified index. If not, aCommandException
will be thrown and no meeting will be edited. - If there is an existing meeting,
EditMeetingCommand#execute()
then creates a new edited meeting and checks if the edited meeting is the same as the current meeting or a duplicate of other meetings. If so, it will throw aCommandException
. - Then,
EditMeetingCommand#execute()
also deletes the existing meeting and checks if the meeting has any clashingdate
with any other meeting before adding the existing meeting back. If there is a clash, it throws aCommandException
and not add the meeting. - If a meeting is unique and has no clashes, then
Model#setMeeting()
is called to set the existing meeting to the edited meeting. - Lastly,
Model#sortMeeting()
is called to sort theUniqueMeetingList
to make sure that all meetings are arranged according to time.
The following activity diagram summarizes the flow of events when a meeting is being added (Note that less important details are omitted for better clarity):
The following sequence diagram shows how the edit meeting operation works (Note that less important details are omitted for better clarity):
EditMeetingCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Design consideration:
Aspect: Parameters taken for edit command
- Alternative 1 (current choice): Take in arguments for the same prefix more than once
- Pros: Allow the user to enter different arguments for the same prefix multiple times so they do not have to backtrack and change the argument. Only the last argument corresponding to the prefix will be used.
- Cons: User might unintentionally enter 2 arguments for the same prefix and find unexpected details in the edited meeting
- Alternative 2:
- Pros: Easy to uncover mistakes if the user has accidentally entered the same prefix more than once, and no ambiguity on which argument to use to create the edited meeting.
- Cons: User has to re-enter the arguments again
Delete contact command
Implementation
The delete contact mechanism is facilitated by DeleteContactCommand
. It extends Command
.
-
DeleteContactCommand#execute()
— Deletes the contact specified by an index, and removes it from all participant lists of meetings, if any.
The following sequence diagram shows how the delete contact operation works (Note that less important details are omitted for better clarity):
Delete meeting command
Implementation
The delete meeting mechanism is facilitated by DeleteMeetingCommand
. It extends Command
.
-
DeleteMeetingCommand#execute()
— Deletes the meeting (and possibly its recurrences) specified by an index.
The flow of a usual delete meeting execution cycle has been illustrated above as an example in logic component:
Design consideration:
Aspect: which list to delete from?
-
DeleteMeetingCommand
is implemented in a way so that it deletes the meeting specified by an index from the last shown list. This enables combinatorial commands which seem more intuitive. For instance,deletemeeting 1
following aFindMeetingCommand
deletes the first meeting from the search results, whereas the same command following aListMeetingCommand
deletes the first meeting from the whole meeting list.
Find contact command
Implementation
The find contact mechanism is facilitated by FindContactCommand
. It extends Command
.
-
FindContactCommand#execute()
— Finds contacts where the name of contact matches given keywords.
Given below is the high-level class diagram based on FindContactCommand
and its direct dependencies.
The given sequence diagram illustrates the flow of a usual find meeting execution cycle:
FindContactCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Remind meeting command
Implementation
The remind meeting mechanism is facilitated by RemindMeetingCommand
. It extends Command
.
-
RemindMeetingCommand#execute()
— Search and display all meetings that will occur within the hours specify by the user.
Given below is the high-level class diagram based on FindMeetingCommand
and its direct dependencies.
The given sequence diagram illustrates the flow of a usual find meeting execution cycle:
RemindMeetingCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Edit userpref command
Implementation
The edit userpref mechanism is facilitated by EditUserPrefCommand
. It extends Command
.
-
RemindMeetingCommand#execute()
— Edit the value of interval between meetings. The interval value is stored and remain valid when user open the app next time.
Given below is the high-level class diagram based on EditUserPrefCommand
and its direct dependencies.
The given sequence diagram illustrates the flow of a usual find meeting execution cycle:
RemindMeetingCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Design consideration:
Aspect: Extention
- Although we only allow user to edit interval value in preferences.json for now, I implement it with
ArgumentMultimap
when parsing user input. Therefore, it is quite easy to extend this feature to allow users to edit and even add new field in preferences.json
Find meeting command
Implementation
The find meeting mechanism is facilitated by FindMeetingCommand
. It extends Command
.
-
FindMeetingCommand#execute()
— Finds meeting where the data of meeting matches given keywords.
Given below is the high-level class diagram based on FindMeetingCommand
and its direct dependencies.
The given sequence diagram illustrates the flow of a usual find meeting execution cycle:
FindMeetingCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Design consideration:
Aspect: Keyword matching Title or Data?
- Initially, mimicing the functionality of
FindContactCommand
, the find meeting only matched the keywords to the title. However, it made more sense to match other attributes like participant names, location and time since it would be easy to pinpoint which meetings take place where through a single find command. - Hence, the predicate matching logic was tweaked in order to accomodate other attributes to make the feature more robust.
DateTime matching using different formats
- The DateTime is converted into various different formats before comparing with the keyword. This ensures that natural searching like “Nov” and “November” are correctly matched.
List meeting & contact command
Implementation
The list meeting / contact mechanism is facilitated by ListMeetingCommand
and ListContactCommand
respectively. They both extend Command
.
-
ListMeetingCommand#execute()
— Lists out all the meetings stored in the address book. -
ListContactCommand#execute()
— Lists out all the contacts stored in the address book.
Design consideration:
Aspect: Why not use find?
- Adding a syntax like
findmeeting
/findcontact
with empty keyword makes the list operation less intuitive. Aslistmeeting
/listcontact
is a frequently used functionality, we decide to have a separate command.
Clear meeting & contact command
Implementation
The clear meeting / contact mechanism is facilitated by ClearMeetingCommand
/ ClearContactCommand
respectively. They both extend Command
.
-
ClearMeetingCommand#execute()
— Deletes all the meetings stored in the address book. -
ClearContactCommand#execute()
— Deletes all the contacts stored in the address book.
Design consideration:
Aspect: Why not use delete?
- Adding a syntax like
deletemeeting all
command makes it hard to parseDeleteMeetingCommand
, andclearmeeting
itself is not very often used. The same applies for contacts.
Undo command
Implementation
The undo mechanism is facilitated by History
and RecretaryState
. History
stores the previous commands and RecretaryState
stores a particular addressbook state and its command. UndoCommand
which extends Command
, acts as an entrypoint into accessing these classes.
-
FindMeetingCommand#execute()
— Finds meeting where the data of meeting matches given keywords.
Given below is the high-level class diagram based on FindMeetingCommand
and its direct dependencies.
Design consideration:
Aspect: Memento Pattern vs Command Pattern
- The undo feature had two different design implementations that we were considering. Due to a growing list of features we had in our app, we decided to choose memento instead of command as coding out an undo for each individual command is an arduous and time-consuming process.
- Moreover, since the pre-existing architecture already has a
Model
that stores the state, it blends in well with the current architecture.
System Timer
Implementation
A system timer is implemented to automatically update Ui and send reminders as time passes by if the app is running in the background (with no user interaction). The timer is handled by Scheduler
and ScheduledTask
. The Scheduler
keeps track of the next upcoming meeting, if any, and uses a Timer
to start ScheduledTask
. When the time comes, the Timer
executes ScheduledTask
where the application gets updated. Different types of tasks extend ScheduledTask
to achieve various functionalities. The dependencies are shown in the diagram below.
Design consideration:
Aspect: How to ensure the timer is valid?
- The
Scheduler
is updated at the start of application and after every user input. If theScheduledTask
is not replaced, which happens most of the time, the overhead is relatively low.
Documentation, logging, testing, configuration, dev-ops
Appendix: Requirements
Product scope
-
Target user profile:
- Potential Users (who prefer CLI/typing):
- Coders
- Authors/Bloggers/Journalists
- Personal Secretaries
- Potential Users (who need address book):
- Business managers
- Personal Secretaries
- HR admins
- Salespersons
- Common in both:
- Executive Personal Secretary
- Job Focus:
- Arrange conference calls and meetings
- Manage clients
- Send email correspondence
- Make travel arrangements
- Potential Users (who prefer CLI/typing):
-
Value proposition:
- Minimise the workload
- Easier to manage
- Automate monotonous and repetitive tasks
- Decrease human errors
- Reduce typos and spelling mistakes
- Optimise meeting timings and location
- Reminders for important tasks/events
User stories
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
* |
meeting planner | create new meeting in my meeting list. | |
* |
meeting planner | update existing meetings | make sure the details are up to date. |
* |
meeting planner | delete specified meetings if they are cancelled. | |
* |
meeting planner | view all upcoming meetings in chronic order. | |
* |
meeting planner | search for meetings with some keywords. | |
* |
frequent user | create new contact in my contact list. | |
* |
frequent user | update existing contact in my contact list. | |
* |
frequent user | search for a certain contact I am looking for. | |
* |
frequent user | view a list of all my contacts at any time. | |
* |
frequent meeting planner | attach a location and time of the meeting as additional information. | |
* |
frequent meeting planner | attach a location and time of the meeting as additional information. | |
* |
frequent meeting planner | create recurring meetings conveniently | avoid repetitive input. |
* * |
frequent meeting planner | receive reminders for upcoming meetings | prepare for the meeting. |
* * |
first time user | get a help page of the app | actually use the app to solve the tasks that I have. |
* * |
long-time user | automatically archive expired meetings | I am not distracted by old meetings. |
* * |
frequent meeting planner | export the meeting calendar | easily sync on other applications. |
* * |
relatively new user | be prompted to change my invalid input | get it correctly from then on. |
* * * |
first time user | find the list of all features that the app has | know what specific task can I complete by using this app. |
* * * |
potential user exploring the app | see the app populated with sample data, | easily see how the app will look like when it is in use. |
* * * |
user ready to start using the app | clear all current data | get rid of data I added when experimenting with the app. |
Use cases
(For all use cases below, the System is the Recretary
and the Actor is the user
, unless specified otherwise)
Use case: UC01 - Add a contact
MSS
- User requests to add a new contact with the relevant details.
- System indicates that the addition is successful.
Use case ends.
Extensions:
- 1a. System detects an error in the data.
- 1a1. System requests for the correct data.
- 1a2. User enters new data.
Steps 1a1-1a2 are repeated until the data entered are correct.
Use case resumes from step 2.
Use case: UC02 - Add a meeting and its participants
MSS
- User requests to add a new meeting with the location, title, datetime, duration and recurrences.
- System indicates that meeting addition is successful and prompts user to add participants to the meeting.
- User enters the participant’s index on the displayed list (must be one of the contacts).
- System indicates that the addition is successful.
- User repeats step 3 until all participants are added.
Use case ends.
Extensions:
- 1a. System detects an error in the data.
- 1a1. System requests for the correct data.
- 1a2. User enters new data.
Steps 1a1-1a2 are repeated until the data entered are correct.
Use case resumes from step 2.
- 3a. Contact is not in System.
- 3a1. System requests for the correct contact.
- 3a2. User enters new contact name.
Steps 3a1-3a2 are repeated until the data entered are correct.
Use case resumes from step 4.
Use case: UC03 - List all contacts or all meetings
MSS
- User requests to list all contacts/ meetings
- System shows the full list of contacts/ meetings
Use case ends.
Extensions:
-
2a. The requested list is empty.
Use case ends.
Use case: UC04 - Edit a contact
MSS
- User requests to list all contacts (UC03).
- User requests to edit a contact with its index and new details.
- System indicates that the update is successful.
Use case ends.
Extensions:
-
2a. The list is empty.
Use case ends.
- 2b. User enters a negative integer as index.
- 2b1. System indicates the error and requests for a non-negative index as index.
- 2b2. User enters the correct index and new details.
Steps 2b1-2b2 are repeated until the data entered are correct.
Use case resumes from step 3. - 2c. User did not enter new details.
- 2c1. System indicates the error and requests for the correct details.
- 2c2. User enters the specific index and correct details.
Steps 2c1-2c2 are repeated until the data entered are correct.
Use case resumes from step 3.
Use case: UC05 - Edit a meeting
MSS
- User requests to list all meetings (UC03).
- User requests to edit a meeting with its index and new details.
- System indicates that the update is successful.
Use case ends.
Extensions:
-
2a. The list is empty.
Use case ends.
- 2b. User enters a negative integer as index.
- 2b1. System indicates the error and requests for a non-negative index as index.
- 2b2. User enters the correct index and new details.
Steps 2b1-2b2 are repeated until the data entered are correct.
Use case resumes from step 3. - 2c. User did not enter new details.
- 2c1. System indicates the error and requests for the correct details.
- 2c2. User enters the specific index and correct details.
Steps 2c1-2c2 are repeated until the data entered are correct.
Use case resumes from step 3. - 2d. User requests to edit participant list.
- 2d1. System shows current list of participants.
- 2d2. User enters the index of the participant he/she wants to remove.
- 2d3. System shows the updated list of participants.
Steps 2d1-2d2 are repeated until the user finishes editing.
Use case resumes from step 3.
Use case: UC06 - Delete participant from the meeting
MSS
- User requests to remove a particular participant from a specific meeting.
- System shows a success message.
Use case ends.
Extensions:
- 1a. User enters a negative integer as index.
- 1a1. System indicates the error and requests for a non-negative index as index.
- 1a2. User enters the correct index.
Steps 1a1-1a2 are repeated until the data entered are correct.
Use case resumes from step 2. - 1b. The contact and/ or meeting does not exist at the specified index.
- 1b1. System indicates the error and requests for a valid index.
- 1b2. User enters the correct index.
Steps 1b1-1b2 are repeated until the data entered are correct.
Use case resumes from step 2.
Use case: UC07 - Find a contact or a meeting
MSS
- User requests to search for a contact/meeting with keywords.
- System shows the list of contacts/ meetings with matching keywords.
Use case ends.
Extensions:
- 1a. No contact/ meeting matched the keyword method.
- 1a1. System shows a message indicating no matching records were found. Use case ends.
Use case: UC08 - Delete a contact or a meeting
MSS
- User requests to list all contacts/ meetings (UC03).
- User requests to remove a contact/ meeting from the list with its index.
- System shows a success message
Use case ends.
Extensions:
-
2a. The list is empty.
Use case ends.
- 2b. User enters a negative integer as index.
- 2a1. System indicates the error and requests for a non-negative index as index.
- 2a2. User enters the correct index.
Steps 2b1-2b2 are repeated until the data entered are correct.
Use case resumes from step 3. - 2c. The contact deleted is a participant of some meeting.
- 2c1. The contact is removed from the list of participants for all meetings. Use case ends.
- 2d. User requires to remove all recurrences of a meeting.
- 2d1. System finds all recurrences of the meeting.
- 2d2. System removes all recurrences one after another. Use case ends.
Use case: UC09 - Clear all contacts or meetings
MSS
- User requests to clear contacts/ meetings.
-
System indicates that the deletion is successful.
Use case ends.
Extensions:
-
1a. No contact/ meeting has been added.
Use case ends.
Use case: UC10 - Export all meetings
MSS
- User requests to export meetings.
- System indicates that the export is successful.
-
User finds the exported file in the
data
folder.Use case ends.
Extensions:
-
1a. No contact/ meeting has been added.
Use case ends.
Use case: UC11 - Undo commands
MSS
- User executes a command that he wishes to undo.
- User executes an undo command with a given index.
-
System revokes the commands and displays the commands that were undone.
Use case ends.
Extensions:
-
2a. Undo INDEX is more than the history of commands.
Use case ends.
-
3a. Export command cannot be undone.
- 3a1. User notified that exported ics isn’t deleted.
Use case ends.
Non-Functional Requirements
- Should work on any mainstream OS as long as it has Java
11
or above installed. - Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage.
- 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.
- Should be portable. The executable must be one-click run.
- The data must be saved onto the hard disk and must be transferrable. In case of unexpected shutdown, the data must be preserved. The data should be human readable.
- Each new update should be backwords-compatable with the data from the previous versions so that it will be easy for users to port over.
- The app must speeden the workflow of the secretary and not be of hinderance.
Glossary
- API: Application Programming Interface
- UML: Unified Modeling Language
- CLI: Command Line Interface
- GUI: Graphic User Interface
- MSS: Main Success Scenario (aka Main Flow of Events)
- Java FX: Standard GUI library for Java SE
- Mainstream OS: Windows, Linux, Unix, OS-X
Appendix: Effort
Overall, we believe that compared to the difficulty level of AB3 at 10, the effort required for our project would be 15.
Difficulty Level
Compared to AB3, our project is much more challenging. We added a new entity, Meeting, with its own function and command classes, by adapting code from AB3. In addition to that, we overhauled the entire UI, and added many new functionalities. For instance, command history, undo function, and meeting reminders. We also had to add elements to the pre-existing AB3 Person code to complement our new features. The new additions were much harder to implement as we had no basis to follow and had to hammer out the details and choose the most efficient implementation ourselves.
Challenges Faced
Since the project began, we have overcome many challenges in implementation.
- We realised our initial implementation of meeting participants would cause participants to be unlinked from the Contact class after restarting the app. After a long discussion, we decided to add unique identifiers to each contact and use that to refer to meeting participants, so that the information would be updated promptly even after restarting.
- We implemented a completely new UI for our app that shows both contacts and meetings at the same time. However, the new implementation required the app to be fullscreen at all times. We realised the difficulty of implementing this as different implementations would not work on both Windows and Mac. Hence we realised the importance of cross-platform testing at every stage of implementation and were able to solve the problem eventually.
- We realised that the meetings class required a different way to add participants as the participants needed to be searched for as contacts. Hence we decided to use adding and deleting participants commands that are independent of the add meeting command.
- We implemented our meeting schedule on a separate thread. However, the arguments accepted by that thread could not be modified after passing them, and it was thus unsuitable for using in the UI to display the meeting schedule. Hence, we decided to use the JavaFX default UI thread to solve the problem.
Effort Required
We estimate that the effort required to code our new features is much higher than that of AB3. We were required to come up with new ways to implement associations between the many new classes that we added. We also had to overcome many obstacles during implementation that would hinder future functions, and had to come up with creative solutions for those problems. Hence our effort was above and beyond that needed for AB3.
Achievements
- Implemented a new UI that is completely upgraded from the AB3 UI.
- Implemented new features to sort meetings by date and time and display the meeting schedule.
- Implemented a new type of instruction with two indexes (addpart and deletepart).
- Implemented new features that improve user experience (command history, undo).
- Implement a function to increase compatibility between our app and other apps (exportmeeting).
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 data. The window size should be maximized to full screen. Users are expected to use the app at this window size for it to have the correct performance.
-
-
Shutdown
- Simply enter the
exit
command to shutdown the app
- Simply enter the
Add a contact
-
Add a new contact to the addressbook
-
Prerequisites: The new contact does not already exist in the addressbook. In case that a duplicate contact was added, Recretary will prompt the user about this exception.
-
Test case:
addcontact n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01 c/ABC Holdings Pte. Ltd
Expected: The contact is successfully added to the addressbook. -
Test case:
addcontact n/John Doe p/ e/johnd@example.com a/John street, block 123, #01-01 c/ABC Holdings Pte. Ltd
Expected: The contact is not added becausep/
. User should see the error message in the feedback box. -
Test case:
addcontact p/98765432 e/johnd@example.com a/John street, block 123, #01-01 c/ABC Holdings Pte. Ltd
Expected: The contact is not added to the addressbook because of the missing name field, eg:n/John Doe
. -
Test case:
addcontact abcd n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01 c/ABC Holdings Pte. Ltd
Expected: The contact is not added to the addressbook because of the random Stringabcd
.
-
Edit a contact
-
Edit an existing contact in the addressbook
-
Prerequisites: The new contact does not already exist in the addressbook. In case that a duplicate contact was added, Recretary will prompt the user about this exception.
-
Test case:
editcontact 1 t/
Expected: The tag for the first contact after thelist
command has been cleared. -
Test case:
editcontact 1
Expected: An exception was shown the prompt user to enter at least one field to be edited.
-
Deleting a contact
-
Deleting a person while all persons are being shown
-
Prerequisites: List all persons using the
list
command. Multiple persons in the list. -
Test case:
deletecontact 1
Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated. -
Test case:
deletecontact 0
Expected: No person is deleted. Error details shown in the status message. Status bar remains the same. -
Other incorrect delete commands to try:
delete
,delete x
,...
(where x is larger than the list size)
Expected: Similar to previous.
-
Add a meeting
-
Add a new meeting to the addressbook
-
Prerequisites: The meeting does not already exist in the addressbook or conflict with any other meetings in the addressbook.
-
Test cases:
addmeeting title/roundtable discussion d/31/12/20 1200 dur/00 30 l/NUS SoC
addmeeting title/roundtable discussion two d/31/12/20 1201 dur/00 30 l/NUS SoC
Expected: An error being shown telling the user that the second meeting conflicts with the first meeting -
Test cases:
addmeeting d/31/12/20 1200 dur/00 30 l/NUS SoC
Expected: An error being shown because the command is missing the compulsory title field, eg:title/roundtable discussion
-
Test cases:
addmeeting title/roundtable discussion d/31/12/20 1200 dur/00 30 l/NUS SoC rec/yearly/30
Expected: An error being shown indicating wrong recurrence format because there is no option foryearly
and/30
is greather than the maximum value allowed which is 20 -
Other incorrect commands that have extra random String or invalid value for a specific prefix
Expected: An error being shown indicating wrong command format and suggest a correct usage.
-
Adding a participant into a meeting
-
Add participant to an existing meeting in the addressbook
-
Prerequisite: The meeting should already exist in the addressbook (the index should be valid).
-
Test cases:
findcontact alice
followed byaddpart ci/1 mi/2
Expected: Succesfully adds the first contact of thefindcontact
command’s result into the 2nd meeting. -
Test cases:
addpart ci/-1 mi/-1
Expected: An error being shown because the index for existing contact and meeting is invalid -
Test cases:
addpart ci/-1
Expected: An error being shown because the compulsory meeting index filed is missing, eg:mi/1
-
Editing a meeting
-
Edits an existing meeting in the meeting schedule
-
Prerequisite: The meeting should already exist in the addressbook (the index should be valid).
-
Test cases:
editmeeting -1 d/10/11/20 1400 l/clementi
Expected: An error being shown because the index is invalid or empty -
Test cases:
editmeeting 1
Expected: An error being shown because at least one filed needs to be specify -
Other test cases that doesn’t follow the prefix convention Expected: An error being shown because it does not follow the correct format
-
Other test cases that make an existing meeting identical to another meeting in the list Expected: An error being shown because the edited meeting should be unique in the list
-
Other test cases that make an existing meeting conflict with another meeting in the list Expected: An error indicate this conflict issue being shown
-
Locating a meeting
-
Find meetings whose data (matches title, date in all natural formats, location) contain any of the given keywords.
-
Test cases:
findmeeting
Expected: An error indicates invalid command format being shown because the arguments cannot be empty -
Test cases:
findmeeting abc def
Expected: A list of meetings such asabc meeting
,def meeting
or 0 meeting being displayed.
-
Deleting a meeting
-
Deletes the specified item (and its recurrences) from the address book.
-
Prerequisites: The index should be a valid index (<= the largest meeting index).
-
Test cases:
deletemeeting 1
Expected: The 1st meeting in the displayed meeting list being deleted or shows an error if the displayed meeting list is empty. -
Test cases:
deletemeeting 2 rec/true
Expected: The 2nd meeting being displayed in meeting list and all its recurrences being deleted; or show an error if there is only one meeting being displayed in list. -
Test cases:
deletemeeting
Expected: An invalid command format error being shown because meeting index can’t be empty.
-
Remind a meeting
-
Search and display all meetings that will occur within the hours specify by the user.
-
Test cases:
remindmeeting 1440
Expected: All meeting within 1440 hours being displayed, empty display if 0 meeting is found -
Test cases:
remindmeeting 0
Expected: An error being shown because the input value is not in the valid range -
Other test cases that contain random text Expected: An error indicates Unknown command or Invalid command format being shown.
-
Update user preference
-
Edit the value of interval between meetings.
-
Test cases:
edituserpref 10
Expected: The value forintervalBetweenMeetings
stored insidepreferences.json
is changed to 10. -
Test cases:
edituserpref 0
Expected: An error being shown because the input value is not in the valid range. -
Other test cases that contain random text Expected: An error indicates Unknown command or Invalid command format being shown.
-
Saving data
-
Dealing with missing/corrupted data files
-
Run Recretary without a
addressbook.json
inside the data folder.
Expected: Recreatary will perform as per normal with sample data loaded. -
Run Recretary with a corrupted
addressbook.json
(data are stored in wrong format, random text somewhere,etc).
Expected: Recreatry will perform as per normal with an empty addressbook. -
Run Recretary without a
preferences.json
inside the root directory.
Expected: Recretary will perform as per normal with the default data loaded. -
Run Recretary with a corrupted
preferences.json
inside the root directory (data are stored in wrong format, random text somewhere,etc).
Expected: Recretary will perform as per normal with the default data loaded.
-