This project is based on the AddressBook-Level3 project created by the SE-EDU initiative.
Libraries used in this project:
Refer to the guide Setting up and getting started.
The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of main components and how they interact with each other.
Main components of the architecture
Main
(consisting of classes Main
and MainApp
) is in charge of the app launch and shut down.
The bulk of the app's work is done by the following 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.Commons
represents a collection of classes used by multiple other components.
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
.
Each of the four main components (also shown in the diagram above),
interface
with the same name as the Component.{Component Name}Manager
class (which follows the corresponding API interface
mentioned in the previous point.For example, the Logic
component defines its API in the Logic.java
interface and implements its functionality using the LogicManager.java
class which follows the Logic
interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component's being coupled to the implementation of a component), as illustrated in the (partial) class diagram below.
The sections below give more details of each component.
The API of this component is specified in Ui.java
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 which captures the commonalities between classes that represent parts of the visible GUI.
The UI
component uses the 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,
Logic
component.Model
data so that the UI can be updated with the modified data.Logic
component, because the UI
relies on the Logic
to execute commands.Model
component, as it displays Person
object residing in the Model
.API : Logic.java
Here's a (partial) class diagram of the Logic
component:
The sequence diagram below illustrates the interactions within the Logic
component, taking execute("delete 1 2 3")
API call as an example.
Note: The lifeline for DeleteCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram.
How the Logic
component works:
Logic
is called upon to execute a command, it is passed to an AddressBookParser
object which in turn creates a parser that matches the command (e.g., DeleteCommandParser
) and uses it to parse the command.Command
object (more precisely, an object of one of its subclasses e.g., DeleteCommand
) which is executed by the LogicManager
.Model
when it is executed (e.g. to delete a person).Model
) to achieve.CommandResult
object which is returned back from Logic
.Here are the other classes in Logic
(omitted from the class diagram above) that are used for parsing a user command:
How the parsing works:
AddressBookParser
class creates an XYZCommandParser
(XYZ
is a placeholder for the specific command name e.g., AddCommandParser
) which uses the other classes shown above to parse the user command and create a XYZCommand
object (e.g., AddCommand
) which the AddressBookParser
returns back as a Command
object.XYZCommandParser
classes (e.g., AddCommandParser
, DeleteCommandParser
, ...) inherit from the Parser
interface so that they can be treated similarly where possible e.g, during testing.API : Model.java
The Model
component,
Person
objects (which are contained in a UniquePersonList
object).Person
objects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as 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.UserPref
object that represents the user’s preferences. This is exposed to the outside as a ReadOnlyUserPref
objects.Model
represents data entities of the domain, they should make sense on their own without depending on other components)API : Storage.java
The Storage
component,
AddressBookStorage
and UserPrefStorage
, which means it can be treated as either one (if only the functionality of only one is needed).Model
component (because the Storage
component's job is to save/retrieve objects that belong to the Model
)Classes used by multiple components are in the seedu.address.commons
package.
This section describes some noteworthy details on how certain features and commands are implemented.
The addstudent
command is used to add a student to the address book with the information fields Name
, Phone
,
Email
, Address
, LessonTime
and Education
.
The format for the addstudent
command can be found here
addstudent
command.Student
is then searched in the model
to see if it is an existing person that the address book contains. If the person does
exist, an error message will be displayed.Student
will be added to the AddressBook
The activity diagram for adding a Student
into the address book
The sequence of the addstudent
command is as follows:
addstudent
command.addstudent n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01 lt/mon:12:00 edu/Primary t/focused
LogicManager
calls the AddressBookParser#parseCommand
to parse the command.AddressBookParser
then creates a new AddStudentCommandParser
to parse the fields provided by the user and
a new Student
and AddStudentCommand
is created.AddStudentCommand
checks if the Student
is valid by calling Model#hasPerson
and retrieves
the module if the person exists in Address Book.AddStudentCommand
then attempts to add the module into the Model via Model#addPerson
.Student
, the user inputs are valid, and the Address Book does not contain the module, AddStudentCommand
will
successfully add the new Student
into Address Book.The following two Sequence Diagrams shows how the addstudent
command works:
Here is the Sequence Diagram showing how the parser works:
And here is the Sequence Diagram showing the command being executed:
The addparent
command is used to add a student to the address book with the information fields Name
, Phone
,
Email
, Address
.
The format for the addparent
command can be found here
addparent
command.Parent
is then searched in the model
to see if it is an existing person that the address book contains. If the person does
exist, an error message will be displayed.Parent
will be added to the AddressBook
The activity diagram for adding a Parent
into the address book
The sequence of the addparent
command is as follows:
addparent
command.addparent n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01
LogicManager
calls the AddressBookParser#parseCommand
to parse the command.AddressBookParser
then creates a new AddParentCommandParser
to parse the fields provided by the user and
a new Parent
and AddParentCommand
is created.AddParentCommand
checks if the Parent
is valid by calling Model#hasPerson
and retrieves
the module if the person exists in Address Book.AddParentCommand
then attempts to add the module into the Model via Model#addPerson
.Parent
, the user inputs are valid, and the Address Book does not contain the module, AddParentCommand
will
successfully add the new Parent
into Address Book.The following two Sequence Diagrams shows how the addparent
command works:
Here is the Sequence Diagram showing how the parser works:
And here is the Sequence Diagram showing the command being executed:
The edit
command is used to change the information fields (e.g. name, email and address) for person in the address book.
The format for the edit
command can be found here.
The edit mechanism uses EditPersonDescriptor
to abstract out the fields to edit. It can be found as a publicly accessible class within EditCommand
. Currently, it contains fields for name
, phone
, email
, address
, tags
, lessonTime
, education
, which are the only attributes of Parent
or Student
that can be edited for now. Besides this, it largely follows the parser and command structure as described in Logic.
Below illustrates how EditPersonDescriptor
is used.
Here is a Sequence Diagram showing the parser in action:
And here is a Sequence Diagram showing the command being executed:
The delete
command is used to delete a person from the address book. The person can only be deleted if it is already present in the address book.
The format of the delete
command can be found here.
delete
command. Person
will be successfully deleted from the address book.The sequence of the delete
command is as follows:
delete
command.delete 1
LogicManager
calls the AddressBookParser#parseCommand
to parse the command.AddressBookParser
then creates a new DeleteCommandParser
to parse the fields provided by the user and a new DeleteCommand
is created.DeleteCommand
checks if the index
is validindex
is valid and Model
contains the persons, the DeleteCommand
calls Model#deletePerson
to delete the person from the address book.The following sequence diagram shows how the delete
command works:
The link
command is used to delete a person from the address book. The person can only be deleted if it is already present in the address book.
The format of the link
command can be found here.
link
command.index
field is not provided, an error message with the correct command usage will be shown.index
field is provided, an error message with the correct command usage will be shown.Person
will be successfully deleted from the address book.The sequence of the link
command is as follows:
link
command.link ch/Alex Yeoh pa/Bernice Yu
LogicManager
calls the AddressBookParser#parseCommand
to parse the command.AddressBookParser
then creates a new LinkCommandParser
to parse the fields provided by the user and a new LinkCommand
is created.LinkCommand
checks if the Student and Parent name
is in the address book by calling Model#personFromName
name
is valid and Model
contains the person, the LinkCommand
creates a new Student by calling LinkCommand#createLinkedChild
.name
is valid and Model
contains the person, the LinkCommand
creates a new Parent by calling LinkCommand#createLinkedParent
.LinkCommand
updates the Student and Parent in the address book by calling Model:setPerson
.The following sequence diagram shows how the link
command works:
The find
command is used to find a person from the address book. The person can only be found if it is already present in the address book.
The format of the find
command can be found here.
find
command.keyword
field is not provided, an error message with the correct command usage will be shown.Person
matching at least one keyword will be successfully returned from the address book.The sequence of the find
command is as follows:
find
command.find Alex Bernice
LogicManager
calls the AddressBookParser#parseCommand
to parse the command.AddressBookParser
then creates a new FindCommandParser
to parse the fields provided by the user and a new FindCommand
and NameContainsKeywordsPredicate
is created.FindCommand
updates the filter of the filtered person list in the address book by calling Model#updateFilteredPersonList
.FindCommand
sorts the filtered person list in the address book by calling Model#sortByPin
.The following sequence diagram shows how the find
command works:
The pin
command is used to pin a person from the address book. The person pinned will be shifted to the top of the filtered list.
The format of the find
command can be found here.
pin
command.index
field is not provided, an error message with the correct command usage will be shown.Person
pinned will be successfully shifted to the top of the filtered list in the address book.The sequence of the pin
command is as follows:
pin
command.pin 1 2
LogicManager
calls the AddressBookParser#parseCommand
to parse the command.AddressBookParser
then creates a new PinCommandParser
to parse the fields provided by the user and a new PinCommand
is created.PinCommand
pins all Person
in the filtered person list in the address book by calling Model#pinPerson
.PinCommand
sorts the filtered person list in the address book by calling Model#sortByPin
.The following sequence diagram shows how the pin
command works:
The proposed undo/redo mechanism is facilitated by VersionedAddressBook
. It extends AddressBook
with an undo/redo history, stored internally as an addressBookStateList
and currentStatePointer
. Additionally, it implements the following operations:
VersionedAddressBook#commit()
— Saves the current address book state in its history.VersionedAddressBook#undo()
— Restores the previous address book state from its history.VersionedAddressBook#redo()
— Restores a previously undone address book state from its history.These operations are exposed in the Model
interface as Model#commitAddressBook()
, Model#undoAddressBook()
and Model#redoAddressBook()
respectively.
Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
Step 1. The user launches the application for the first time. The VersionedAddressBook
will be initialized with the initial address book state, and the currentStatePointer
pointing to that single address book state.
Step 2. The user executes delete 5
command to delete the 5th person in the address book. The delete
command calls Model#commitAddressBook()
, causing the modified state of the address book after the delete 5
command executes to be saved in the addressBookStateList
, and the currentStatePointer
is shifted to the newly inserted address book state.
Step 3. The user executes add n/David …
to add a new person. The add
command also calls Model#commitAddressBook()
, causing another modified address book state to be saved into the addressBookStateList
.
Note: If a command fails its execution, it will not call Model#commitAddressBook()
, so the address book state will not be saved into the addressBookStateList
.
Step 4. The user now decides that adding the person was a mistake, and decides to undo that action by executing the undo
command. The undo
command will call Model#undoAddressBook()
, which will shift the currentStatePointer
once to the left, pointing it to the previous address book state, and restores the address book to that state.
Note: If the currentStatePointer
is at index 0, pointing to the initial AddressBook state, then there are no previous AddressBook states to restore. The undo
command uses Model#canUndoAddressBook()
to check if this is the case. If so, it will return an error to the user rather
than attempting to perform the undo.
The following sequence diagram shows how an undo operation goes through the Logic
component:
Note: The lifeline for UndoCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Similarly, how an undo operation goes through the Model
component is shown below:
The redo
command does the opposite — it calls Model#redoAddressBook()
, which shifts the currentStatePointer
once to the right, pointing to the previously undone state, and restores the address book to that state.
Note: If the currentStatePointer
is at index addressBookStateList.size() - 1
, pointing to the latest address book state, then there are no undone AddressBook states to restore. The redo
command uses Model#canRedoAddressBook()
to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.
Step 5. The user then decides to execute the command list
. Commands that do not modify the address book, such as list
, will usually not call Model#commitAddressBook()
, Model#undoAddressBook()
or Model#redoAddressBook()
. Thus, the addressBookStateList
remains unchanged.
Step 6. The user executes clear
, which calls Model#commitAddressBook()
. Since the currentStatePointer
is not pointing at the end of the addressBookStateList
, all address book states after the currentStatePointer
will be purged. Reason: It no longer makes sense to redo the add n/David …
command. This is the behavior that most modern desktop applications follow.
The following activity diagram summarizes what happens when a user executes a new command:
Aspect: How undo & redo executes:
Alternative 1 (current choice): Saves the entire address book.
Alternative 2: Individual command knows how to undo/redo by itself.
delete
, just save the person being deleted).{more aspects and alternatives to be added}
Target user profile:
Value proposition: Tutors find it challenging to keep track of student information if they are teaching multiple students. They could be juggling additional administrative duties with their teaching duties. GOATS can enhance their efficiency by managing student and parent data, freeing up their time and allowing them to focus on other tasks.
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
* * * | detail-oriented private tutor | add my students' contact details, educational levels and subjects taught to the address book | I can keep track of all these details effectively |
* * * | tutor | view all my students | I know who are my students |
* * * | long-time private tutor | delete contacts | I can keep my address book concise and remove all unneeded contacts |
* * | concerned private tutor | add my students' parents' contact details to the address book | I am able to contact them regarding their child’s academic progress |
* * | organised private tutor | link each student to their parents in the address book | I can contact related users at once |
* * | private tutor with multiple students | tag students based on characteristics | I can keep track of additional information on students if required |
* * | non-tech savvy private tutor | have a help sheet with the provided commands | I do not have to spend too much time memorising commands in order to use the app |
* * | private tutor | filter the contact details in the address book by name and tag | I can find the relevant contact details more quickly |
* * | organised private tutor | view all related users (e.g. students and parents) in one page | I do not have to manually search or filter for them |
* * | user | find my students by name | I will be able to quickly find their contact information |
* | busy private tutor with too many students | have a prompt for non-clients to be deleted automatically | I do not have to manually keep track and delete them |
* | user concerned with aesthetics | edit the look of the GUI and select from several themes | I can customise the look of the address book to suit my aesthetic preferences |
* | user who prefers CLI | customise the format of inputting contact data in the command line | I can use the app in a way that suits my workflow |
* | potential user exploring the address book | try out the app's features with sample data | I can easily see how the app will look when it is in use |
* | user ready to start using the app | delete all existing data | I can get rid of sample/experimental data I used for exploring the app |
* | private tutor who is juggling multiple subjects | filter students and parents by subject | I can contact all parties easily and at once when I need to make an announcement that concerns all students of a particular subject |
* | private tutor who has to schedule lessons manually by myself | filter students by availability | I can keep track of when students are available when planning make-up or additional lessons |
* | impatient user | execute tasks at low latency | I do not spend unnecessary time waiting for the address book to load and handle my commands and can thus work more efficiently |
* | user who prefers pictures over words | attach a picture with the contact | I can have a more enjoyable GUI experience |
* | tutor who teaches students across different time zones | have a tag that tracks the difference in timezones | I do not have to manually keep track of time zones and potentially make mistakes |
* | private tutor who may expand my business | download all my data into a .csv file | I can transfer data across different digital platforms |
* | private tutor who is starting to use the app | upload data of a collection of clients into the app | It seamlessly stores all the previous clients data with minimal setup steps |
* | private tutor that specializes in special needs education | search, filter and categorize students by their needs | I can better tailor my teaching to each individual needs |
* | private tutor who contacts certain students or parents more frequently | pin certain students to the top of the contact list | I can access frequently contacted students or parents immediately |
* | private tutor performing a task on my contact list (e.g. deleting contacts) | select multiple users and perform a single task on them | I do not have to perform each task individually |
* | private tutor who wishes to organise my students more effectively | add multiple users to a list and save it | I can keep track of them better and I do not need to perform tasks on them individually |
* | tutor with compromised eyesight | zoom in to the address book GUI | I do not have to strain my eyes to read what is on the screen |
* | colorblind tutor | use a colorblind mode | I would not confuse colors of the tags |
* | private tutor offering both online and in-person sessions | mark the preferred mode of learning for each student | I can plan my schedule and resources accordingly |
* | tutor who receives payments from parents | add payment statuses to each student | I can manage my finance-related tasks efficiently |
* | private tutor involved in long-term academic planning | keep a history of each student's progress and achievements | I can monitor their growth over time and adjust my teaching strategies accordingly |
* | expert user of the addressbook | set macros for filters/sort | I would be able to quickly organise without typing long commands |
(For all use cases below, the System is the GOATS
application and the Actor is the user
, unless specified otherwise)
Guarantees: The new contact will be added to the GOATS Address Book, provided the command format is valid, all required information is present and valid, and the contact does not already exist in the GOATS Address Book.
MSS
User enters the new contact's details.
GOATS adds the contact.
GOATS displays the list of all unarchived contacts.
GOATS shows success message.
Use case ends.
Extensions
1a. User enters an invalid command or invalid/missing details.
1a1. GOATS shows an error message.
Use case ends.
1b. User enters a contact with a name that already exists in the GOATS Address Book.
1b1. GOATS shows an error message.
Use case ends.
Preconditions: The contact(s) to delete exist in the displayed list of contacts. Guarantees: The specified contact(s) will be removed from the GOATS Address Book, provided the command format is valid.
MSS
User requests to delete specific contact(s) in the displayed list of contacts by passing in the displayed indices of the contacts to be deleted.
GOATS deletes the specified contact(s).
GOATS removes the deleted contact(s) from the displayed list of contacts.
GOATS shows success message.
Use case ends.
Extensions
1a. User enters an invalid command or invalid indices.
1a1. GOATS shows an error message.
Use case ends.
Guarantees: The displayed list be updated to show all unarchived contacts.
MSS
User requests to list contacts.
GOATS displays the list of all unarchived contacts.
Use case ends.
Extensions
1a. User enters an invalid command.
1a1. GOATS shows an error message.
Use case ends.
Guarantees: The displayed list will be sorted in alphabetical order.
MSS
User requests to sort the displayed list of contacts.
GOATS sorts the list and displays the sorted list.
Use case ends.
Extensions
1a. User enters an invalid command.
1a1. GOATS shows an error message.
Use case ends.
Preconditions: The contact to edit exists in the displayed list of contacts. Guarantees: The specified contact will be updated with the new information, provided the command format and all information provided is valid.
MSS
User requests to edit a specific contact in the displayed list of contacts by entering the displayed index of the contact to be edited and the updated details.
GOATS edits the person.
GOATS displays the list of all unarchived contacts.
GOATS shows success message.
Use case ends.
Extensions
1a. User enters an invalid command or invalid index/details.
1a1. GOATS shows an error message.
Use case ends.
1b. User attempts to update the contact with a name that already exists in the GOATS Address Book.
1b1. GOATS shows an error message.
Use case ends.
Guarantees: The displayed list will be updated to show all contacts whose names contain any of the specified keywords.
MSS
User requests to find contacts by entering one or more keywords.
GOATS displays the list of all contacts whose names contain one or more of the specified keywords.
Use case ends.
Extensions
1a. User enters an invalid command or does not provide any keywords.
1a1. GOATS shows an error message.
Use case ends.
Guarantees: The displayed list will be updated to show all contacts who has one or more of the specified keywords as tags.
MSS
User requests to find contacts by entering one or more keywords.
GOATS displays the list of all contacts who have a tag that matches any of the specified keywords.
Use case ends.
Extensions
1a. User enters an invalid command or does not provide any keywords.
1a1. GOATS shows an error message.
Use case ends.
Guarantees: The displayed list will be updated to show all students who have a lesson on the specified day of the week.
MSS
User requests to find contacts by entering one or more keywords.
GOATS displays the list of all students whose lesson day matches any of the specified keywords.
Use case ends.
Extensions
1a. User enters an invalid command or does not provide any keywords.
1a1. GOATS shows an error message.
Use case ends.
MSS
User requests to show user guide.
GOATS displays a link to the user guide.
Use case ends.
Extensions
1a. User enters an invalid command.
1a1. GOATS shows an error message.
Use case ends.
Guarantees: All contacts in the list of contacts will be deleted from the GOATS Address Book.
MSS
User requests to clear all contacts.
GOATS deletes all contacts.
GOATS displays an empty list of contacts.
GOATS shows success message.
Use case ends.
Extensions
1a. User enters an invalid command.
1a1. GOATS shows an error message.
Use case ends.
Preconditions: The contact(s) to archive exist in the displayed list of contacts. Guarantees: The specified contact(s) will be archived, provided the command format is valid.
MSS
User requests to archive specific contact(s) in the displayed list of contacts by passing in the displayed indices of the contacts to be archived.
GOATS archives the specified contact(s).
GOATS shows success message.
Use case ends.
Extensions
1a. User enters an invalid command or invalid indices.
1a1. GOATS shows an error message.
Use case ends.
Preconditions: The contact(s) to unarchive exist in the displayed list of contacts. Guarantees: The specified contact(s) will be unarchived, provided the command format is valid.
MSS
User requests to unarchive specific contact(s) in the displayed list of contacts by passing in the displayed indices of the contacts to be unarchived.
GOATS unarchives the specified contact(s).
GOATS shows success message.
Use case ends.
Extensions
1a. User enters an invalid command or invalid indices.
1a1. GOATS shows an error message.
Use case ends.
Guarantees: The displayed list will be updated to show all archived contacts.
MSS
User requests to list archived contacts.
GOATS displays the list of all archived contacts.
Use case ends.
Extensions
1a. User enters an invalid command.
1a1. GOATS shows an error message.
Use case ends.
Preconditions: The contact(s) to pin exist in the displayed list of contacts. Guarantees: The specified contact(s) will be pinned, and the displayed list will be updated to show all pinned contacts at the top of the list, provided the command format is valid.
MSS
User requests to pin specific contact(s) in the displayed list of contacts by passing in the displayed indices of the contacts to be pinned.
GOATS pins the specified contact(s).
GOATS updates the displayed list of contacts to show all pinned contacts at the top of the list.
GOATS shows success message.
Use case ends.
Extensions
1a. User enters an invalid command or invalid indices.
1a1. GOATS shows an error message.
Use case ends.
Preconditions: The contact(s) to unpin exist in the displayed list of contacts. Guarantees: The specified contact(s) will be unpinned, and the displayed list will be updated to show all pinned contacts at the top of the list, provided the command format is valid.
MSS
User requests to unpin specific contact(s) in the displayed list of contacts by passing in the displayed indices of the contacts to be unpinned.
GOATS unpins the specified contact(s).
GOATS updates the displayed list of contacts to show all pinned contacts at the top of the list.
GOATS shows success message.
Use case ends.
Extensions
1a. User enters an invalid command or invalid indices.
1a1. GOATS shows an error message.
Use case ends.
Preconditions: The student whose grade is to be updated exists in the displayed list of contacts. Guarantees: The grade of the specified contact will be updated, provided the command format is valid and the specified contact is a student.
MSS
User requests to update the grade of a specific contact in the displayed list of contacts by entering the displayed index of the contact to be edited and the updated grade.
GOATS edits the contact.
GOATS displays the list of all unarchived contacts.
GOATS shows success message.
Use case ends.
Extensions
1a. User enters an invalid command, an invalid index or an invalid grade value.
1a1. GOATS shows an error message.
Use case ends.
1b. GOATS detects that the specified contact is not a student.
1b1. GOATS shows an error message.
Use case ends.
Preconditions: The student and parent to be linked both exist in the GOATS Address Book. Guarantees: The student and the parent will be linked in a parent-child relationship, provided the command format and all information provided is valid.
MSS
Extensions
1a. User enters an invalid command.
1a1. GOATS shows an error message.
Use case ends.
1b. GOATS detects that the specified contacts do not consist of a student and a parent.
1b1. GOATS shows an error message.
Use case ends.
1c. User enters a name that does not exist in the GOATS Address Book.
1c1. GOATS shows an error message.
Use case ends.
Preconditions: The student to be unlinked exists in the GOATS Address Book, and has a link to a parent. Guarantees: The student and the parent will be linked in a parent-child relationship, provided the command format and all information provided is valid.
MSS
Extensions
1a. User enters an invalid command.
1a1. GOATS shows an error message.
Use case ends.
1b. GOATS detects that the specified contact is not a student.
1b1. GOATS shows an error message.
Use case ends.
1c. User enters a name that does not exist in the GOATS Address Book.
1c1. GOATS shows an error message.
Use case ends.
1d. GOATS detects that the specified student has no links to any parent.
1d1. GOATS shows an error message.
Use case ends.
MSS
User requests to exit application.
GOATS exits and closes.
Use case ends.
Extensions
1a. User enters an invalid command.
1a1. GOATS shows an error message.
Use case ends.
17
or above installed.GOATS
in order to perform a certain action, like adding a new contact to the GOATS Address Book. Commands will be the primary way of interacting with GOATS
.GOATS
which actions to perform. For example, the delete command requires one or more integers as a parameters, which will specify the contacts to be deleted from the GOATS Address Book.GOATS
understands what kind of values they are. For example, the prefix "n/" lets GOATS
know that a name is expected to follow behind it, while the prefix "d/" lets GOATS
know that a date is expected.user
.Given below are instructions to test the app manually.
Note: These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.
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.
Deleting a person while all persons are being shown
Prerequisites: List all persons using the list
command. Multiple persons should be displayed in the list.
Test case: delete 1
Expected: The first contact is deleted from the list. Details of the deleted contact are shown in the status message.
Test case with multiple indices: delete 1 2 3
Expected: The first, second, and third contacts are deleted from the list. Status message reflects successful deletion of multiple contacts.
Test case: delete 0
Expected: No contact is deleted. Error details are shown in the status message.
Other incorrect delete commands to try: delete
, delete x
, ...
(where x is larger than the list size)
Expected: Similar to previous; no contact is deleted, and an error message is displayed in the status message.
Finding contacts by name while all persons are being shown
Prerequisites: List all persons using the list
command. Multiple persons in the list with diverse names.
Test case: find John
Expected: All contacts with names containing "John" are displayed in the list. Number of matching contacts are shown in the status message.
Test case with multiple keywords: find Alex David
Expected: All contacts with names containing "Alex" or "David" appear in the list. Number of matching contacts are shown in the status message.
Test case: find {NON-EXISTENT NAME]
Expected: No contacts are shown. Status message indicates 0 matches found.
Finding contacts by tag while all persons are being shown
Prerequisites: List all persons using the list
command. Some contacts should have tags such as "friend" or "tutor".
Test case: findtag friend
Expected: All contacts tagged with "friend" are displayed in the list. Status message reflects the number of matching contacts.
Test case with multiple tags: findtag friend colleague
Expected: All contacts tagged with either "friend" or "colleague" appear in the list. Status message reflects the number of matching contacts.
Test case: findtag [NON-EXISTENT TAG]
Expected: No contacts are shown. Status message indicates 0 matches found.
Finding students by lesson day while all persons are being shown
Prerequisites: List all persons using the list
command. Some students should have lesson days like "Tuesday" or "Wednesday".
Test case: findday tuesday
Expected: All students with lessons on Tuesday are displayed in the list. Status message reflects the number of matching contacts.
Test case with multiple days: findday tuesday wednesday
Expected: All students with lessons on either Tuesday or Wednesday are displayed. Status message reflects the number of matching contacts.
Test case: findday [NON-EXISTENT DAY]
Expected: No contacts are shown. Status message indicates no matches found.
Archiving contacts while all persons are being shown
Prerequisites: List all persons using the list
command. All contacts should be displayed in the list.
Test case: archive 1
Expected: The first contact is archived and removed from the main contact list. A status message confirms the archiving.
Test case with multiple indices: archive 1 2 3
Expected: The first, second, and third contacts are archived and removed from the main contact list. Status message reflects successful archiving of multiple contacts.
Test case: archive 0
Expected: No contact is archived. Error details are shown in the status message.
Other incorrect archive commands to try: archive
, archive x
, ...
(where x is larger than the list size)
Expected: Similar to previous; no contact is archived, and an error message is displayed in the status message.
Unarchiving contacts while viewing archived contacts
Prerequisites: Archive at least one contact as above. List all archived contacts using the listarchive
command. Archived contacts should be displayed.
Test case: unarchive 1
Expected: The first archived contact is unarchived and moved back to the main contact list. A status message confirms the unarchiving.
Test case with multiple indices: unarchive 1 2 3
Expected: The first, second, and third archived contacts are unarchived and returned to the main contact list. Status message reflects successful unarchiving of multiple contacts.
Test case: unarchive 0
Expected: No contact is unarchived. Error details are shown in the status message.
Other incorrect unarchive commands to try: unarchive
, unarchive x
, ...
(where x is larger than the archived list size)
Expected: Similar to previous; no contact is unarchived, and an error message is displayed
Pinning contacts while all persons are being shown
Prerequisites: List all persons using the list
command. Multiple persons should be displayed in the list.
Test case: pin 1
Expected: The first contact is pinned and moved to the top of the contact list. A status message confirms the pinning.
Test case with multiple indices: pin 1 2 3
Expected: The first, second, and third contacts are pinned and appear at the top of the list. Status message reflects successful pinning of multiple contacts.
Test case: pin 0
Expected: No contact is pinned. Error details are shown in the status message.
Other incorrect pin commands to try: pin
, pin x
, ...
(where x is larger than the list size)
Expected: Similar to previous; no contact is pinned, and an error message is displayed in the status message.
Unpinning contacts while pinned contacts are at the top of the list
Prerequisites: Pin at least one contact using the pin
command, then use list
to verify the contact is pinned and at the top.
Test case: unpin 1
Expected: The first pinned contact is unpinned and placed back in the sorted order. A status message confirms the unpinning.
Test case with multiple indices: unpin 1 2 3
Expected: The first, second, and third pinned contacts are unpinned and returned to their original sorted order. Status message reflects successful unpinning of multiple contacts.
Test case: unpin 0
Expected: No contact is unpinned. Error details are shown in the status message.
Other incorrect unpin commands to try: unpin
, unpin x
, ...
(where x is larger than the list size)
Expected: Similar to previous; no contact is unpinned, and an error message is displayed in the status message.
Linking a parent to a student
Prerequisites: Ensure that both a student (e.g., "John Doe") and a parent (e.g., "Jane Doe") contact exist in the contact list. Use find
to verify both contacts are present.
Test case: link ch/John Doe pa/Jane Doe
Expected: The specified student "John Doe" and parent "Jane Doe" are linked, establishing a parent-child relationship. A status message confirms the successful linking.
Test case: link ch/[NON-EXISTENT STUDENT NAME] pa/Jane Doe
Expected: No link is created. Error details are shown in the status message, indicating that the student contact does not exist.
Test case: link ch/John Doe pa/[NON-EXISTENT PARENT NAME]
Expected: No link is created. Error details are shown in the status message, indicating that the parent contact does not exist.
Test case: link ch/[NON-EXISTENT STUDENT NAME] pa/[NON-EXISTENT PARENT NAME]
Expected: No link is created. Error details are shown in the status message.
Unlinking a parent from a student
Prerequisites: Ensure a parent (e.g., "Jane Doe") is already linked to a student (e.g., "John Doe"). Use list
to verify the linked relationship.
Test case: unlink ch/John Doe
Expected: The parent-child relationship between "John Doe" and "Jane Doe" is removed, and "John Doe" is no longer linked to "Jane Doe". A status message confirms the successful unlinking.
Test case: unlink ch/[NON-EXISTENT STUDENT NAME]
Expected: No unlinking occurs. Error details are shown in the status message, indicating that the student contact does not exist.
Test case: unlink ch/John Doe ch/Alice Smith pa/Jane Doe
Expected: No unlinking occurs. Error details are shown in the status message.
Test case: unlink ch/John Doe
when no parent is linked
Expected: No change occurs. An error message indicates that "John Doe" does not have a linked parent.
Dealing with corrupted data files
Corrupted data files can be simulated by editing data/addressbook.json file
Test case: Start GOATS app Expected: GOATS should clear all data from the corrupted file and user is presented with an empty addressbook
Dealing with missing data files
Missing data files can be simulated by deleting data/addressbook.json file
Test case: Start GOATS app Expected: GOATS should initialise a new data/addressbok.json file with sample data and user is presented an addressbook with that data
The project was a step-up in difficulty as compared to AddressBook Level3 (AB3), due to the number of commands added, and the need to support multiple entity types. Contacts in AB3 only constituted one single entity type, but in GOATS, they are split it into two different entities: Student and Parent, both with differing functionalities and representation in the UI. In addition, a large number of commands were added, with a high level of interaction between them, which made it difficult to keep track of and fix all the unintended behaviours and interactions that inevitably arose.
The project required significant effort due to the implementation of the following features on top of AB3:
Each member of the group wrote an average of 1,400 lines of code.
Over the course of the project, the group achieved the following:
Team Size: 5. Hence, maximum number of planned enhancements is 10.
findday
command to only take in days of the week.DAY
parameter of the findday
command.DAY
inputs (i.e. the days of the week), and display an error message to the user if the value input to the DAY
parameter does not match any of the valid inputs.