ProjectPro is a contacts organisation application designed for university students.
University students often spend a lot of time coordinating project meetup sessions and finding project information, resulting in large amounts of time wasted.
This app can help to save time by:
Refer to the guide Setting up and getting started.
ProjectPro is a brownfield Java Project based on the AB3 project template created by the SE-EDU initiative.
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.
2.1.1. Main components of the architecture
Main
has two main classes called Main
and MainApp
. It is responsible for app launch and shut down.
The rest of the App consists of these main 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.On the other hand, Commons
represents a collection of classes used by multiple other components.
2.1.2. 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 n/Alex
.
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.
GroupTimeContainer
is a helper class that process the data from the model
in Calendar
and passes the processed data to DayCard
which will be then displayed in the UI
.
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 n/Alex")
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 reaches the end of diagram.
How the Logic
component works:
Logic
is called upon to execute a command, it calls the 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
), being executed by the LogicManager
.Model
to execute the action (e.g. to delete a person).CommandResult
object which is returned back to 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
).With the inclusion of Group
and TimeIntervals
in our application, more components had to be saved by our storage.
To address this requirement, we updated our storage to save both classes in JSON format.
Classes used by multiple components are in the seedu.addressbook.commons
package.
This section describes some noteworthy details on how certain features are implemented.
The add
feature is facilitated by a number of classes such as Person
and Model
Step 1. The user launches the application for the first time.
Step 2. The user executes “add n/John Doe p/98765432 e/johnd@example.com g/CS2103T”
command to add a new person.
Step 3, The AddCommandParser
is called to read the user input. AddCommandParser
parses the input and calls AddCommand
.
Step.4 AddCommand
then calls Model#addPerson()
which then calls AddressBook#addPerson()
. The latter method will add person inside the uniquePersonList
in addressBook
. AddCommand
also calls Model#addGroup
which then calls AddressBook#addGroup
to add the group inside grouplist
if the group does not exist. Lastly, AddCommand
adds the person inside the group
Note No duplication is allowed in addressbook for name, email and phone number field.
The following sequence diagram describes the process of add
command:
Note: The lifeline for AddCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Aspect: Handling group attribute in user input
Alternative 1 (Current Choice): Only allow user to add one group for each add
Command
Alternative 2: Allow user to add as many groups as required for each add
Command
The Add Group mechanism is facilitated by Group
class. This operation is exposed in the Model
interface as Model#addGroup()
.
Given below is an example usage scenario and how the group creation mechanism behaves at each step.
Step 1: User launches the application.
Step 2: The user executes new g/GROUPNAME
to create a new group with the name GROUPNAME. CreateGroupCommandParser
parses the GROUPNAME, ensuring the input is valid, and creates a CreateGroupCommand
, which calls Model#addGroup()
. The model retrieves the existing groupList from the addressBook and adds this new group to the groupList.
Note: ProjectPRO does not allow 2 groups of the same name to be added. The group name must also be alphanumerical and non empty.
The following activity diagram summarizes what happens when a user executes a new command:
Below is a sequence diagram that summarizes how a user creates a new group:
Note: The lifeline for CreateGroupCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Aspect: Groups with the same name
Alternative 1 (current choice): Group names are Unique
Alternative 2: Group names are not unique but tagged with an id
The Delete person/group mechanisms are facilitated by Model
class, which accesses the AddressBook
class. It implements the following operations:
AddressBook#removePerson(Person p)
— Removes Person p from the address book.AddressBook#removeGroup(Group g)
— Removes Group g from the address book.These operations are exposed in the Model
interface as Model#deletePerson()
, Model#deleteGroup()
respectively.
Both DeletePersonCommand
and DeleteGroupCommand
implement an abstract class DeleteCommand
, which helps to encapsulate the similarities between these two commands.
Since both Delete Person and Delete Group commands utilise the same command word, the DeleteCommandParser
will create either a DeletePersonCommand
or DeleteGroupCommand
and return it as a DeleteCommand
after parsing the user input.
The following activity diagram summarizes what happens when a user executes a delete command:
Given below is an example usage scenario and how the Delete Person mechanism behaves at each step.
Step 1. The user executes delete n/Alex Yeoh
command to delete a person named 'Alex Yeoh' in the contact list. After parsing, a new DeletePersonCommand
object will be returned.
Step 2. DeletePersonCommand
is executed, in which Model#deletePerson("Alex Yeoh")
is called.
Note: If no such person named 'Alex Yeoh' exists, a CommandException
will be thrown.
Step 3. Model#deletePerson()
will also call AddressBook#removePerson(Alex Yeoh)
which will remove the target contact from the contact list while removing it from all the groups it was part of by calling Group#removePerson(Alex Yeoh)
.
The following sequence diagram shows how the Delete Person operation works:
Note: The lifeline for DeleteCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The Delete Group command mechanism behaves the same as the Delete Person command above, except it deletes the target Group
object instead of the Person
object.
Additionally, AddressBook#removeGroup(Group g)
will remove the target group 'g' from the group lists of all the members that were a part of it by calling Person#removeGroup(Group g)
.
Aspect: How to handle two similar but different commands (delete group and delete person)
Alternative 1 (current choice): Use the same command word
Alternative 2: Use different command words for both commands
The List mechanism is facilitated by the Model
class.
The operation it utilises is exposed in the Model
interface as Model#updateFilteredPersonList(Predicate<Person> predicate)
.
Given below is an example usage scenario and how the list mechanism behaves at each step.
Step 1: User executes list
command to view all contacts. After parsing, a new ListCommand
object will be returned.
Step 2: ListCommand
is executed, in which Model#updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS)
is called with the Predicate
The following activity diagram summarizes what happens when a user executes a list command:
Note: The lifeline for ListCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The List Group mechanism is facilitated by the Model
class.
The operation it utilises is exposed in the Model
interface as Model#getFilteredGroupList()
.
Given below is an example usage scenario and how the listgroup mechanism behaves at each step.
Step 1: User executes listgroup
command to view all groups in their contact list. After parsing, a new ListGroupCommand
object will be returned.
Step 2: ListGroupCommand
is executed, in which Model#getFilteredGroupList()
is called, returning all the groups the user has in the contact list.
Step 3: The group names of all the groups in the contact list are appended to a String
which will be displayed to the user as a message in the output box.
The following activity diagram summarizes what happens when a user executes a listgroup command:
Note: The lifeline for ListGroupCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The Find person/group mechanisms are facilitated by the Model
class.
The operation they utilise is exposed in the Model
interface as Model#updateFilteredPersonList(Predicate<Person> predicate)
.
Both FindPersonCommand
and FindGroupCommand
implement an abstract class FindCommand
, which helps to encapsulate the similarities between these two commands.
Since both Find Person and Find Group commands utilise the same command word, the FindCommandParser
will create either a FindPersonCommand
or FindGroupCommand
and return it as a FindCommand
after parsing the user input.
The following activity diagram summarizes what happens when a user executes a find command:
Given below is an example usage scenario and how the Find Person mechanism behaves at each step.
Step 1. The user executes find n/Alex John
command to find all contacts whose names contain either 'Alex' or 'John' in the address book. After parsing, a new FindPersonCommand
object will be returned along with the corresponding Predicate<Person>
.
Step 2. FindPersonCommand
is executed, in which Model#updateFilteredPersonList()
is called with the Predicate
Note: If there are no contacts whose name contains 'Alex, or 'John', no contacts will be shown.
The following sequence diagram shows how the Find Person operation works:
Note: 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.
The Find Group mechanism works like the Find Person mechanism, expect it filters contacts by a different Predicate<Person>
which will filter for contacts who are a part of the target group.
Additionally, it calls on an extra method Group#getGroupRemark()
. Group#getGroupRemarks()
will be called to display the previously saved group remarks to the user.
Aspect: How to handle two similar but different commands (find by group and find by name)
Alternative 1 (current choice): Use the same command word
Alternative 2: Use different command words for both commands
Aspect: Case-sensitivity for find by name
Alternative 1 (current choice): Not case-sensitive
Alternative 2: Case sensitive
The group mechanism is facilitated by Group
. It is stored internally as a Group
. This operation is exposed in the Model
interface as Model#groupPerson(personName, groupName)
.
Given below is an example usage scenario and how the group mechanism behaves at each step.
Step 1: User launches the application.
Step 2: The user executes group n/personName g/groupName
to group a person personName
into group groupName
. `
Step 3. GroupPersonCommandParserparses the personName and groupName ensuring the input is valid and creates a
GroupPersonCommand`
Step 4. GroupPersonCommand calls Model#groupPerson(personName, groupName)
. The model retrieves the existing person and group from the addressBook.
Step 5. Model calls Model#assignGroup(Person person, Group group)
which adds a group to a person's groupList and person to the personList in group.
Note: Should a person or group not exist, an error is thrown, displaying the missing entity to the User.
Ungroup works in the same way as group except the use of Command word ungroup
The following activity diagram summarizes what happens when a user executes a new command:
Aspect: Whether to store references in both person and group
Alternative 1 (current choice): Store references in both person and group
Alternative 2: Store reference to the other entity, e.g. store a list of groups in person.
The Group Remark mechanism is facilitated by the Group Remark
class, involving other classes like Group
. It implements the following operation:
Group#setGroupRemark()
— Sets the group's remark.This operation is exposed in the Model
interface as Model#addGroupRemark()
.
Here's an example usage scenario and how the group remark mechanism behaves at each step:
Step 1. The user creates a group called "CS2103T". The group is initialized with an empty groupRemark
.
Step 2. The user executes the remark g/CS2103T r/Quiz tomorrow
command to add the remark "Quiz tomorrow" to the "CS2103T" group. The GroupRemarkCommandParser
extracts the group and remark from the input and creates a GroupRemarkCommand
, which calls Model#addGroupRemark(groupName, groupRemark)
. The model retrieves the existing "CS2103T" group from the database and calls the group's Group#setGroupRemark(groupRemark)
, setting the "Quiz tomorrow" as the groupRemark
of the group.
Note: If the user wants to modify the group remark, they can execute the same command with the new remark. The existing remark will be overwritten, and the new remark is stored in the group.
The following activity diagram summarizes what happens when a user executes a new command:
Note: The lifeline for GroupRemarkCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Aspects: How to change the group remark
Alternative 1 (current choice): Override the original remark
Alternative 2: Edit the original remark
The Add Time to person/group mechanisms are facilitated by the TimeInterval
class, involving other classes like Person
and Group
. It implements the following operations:
Person#addFreeTime()
— Adds the inputted time intervals to the person.Group#addTime()
— Adds the inputted time intervals to the group.These operations are exposed in the Model
interface as Model#addTimeToPerson()
, Model#addTimeToGroup()
respectively.
The following activity diagram summarizes what happens when a user executes an add time command:
Given below is an example usage scenario and how the Add Time to Person mechanism behaves at each step.
Step 1. The user executes addtime n/Alex Yeoh t/mon 1300 - mon 1400 t/tue 1300 - tue 1400
command to add the free time intervals of Monday 1 pm to 2 pm and Tuesday 1 pm to 2 pm to a person named "Alex Yeoh" in the contact list. The AddTimeCommandParser
will be called to parse the inputs and check if any of the inputted times clash with each other. It will then call the AddTimeCommand
.
Note: Since multiple inputs are allowed, an array list of time intervals is passed around, each of which is to be added.
Step 2. AddTimeCommand
is executed, in which Model#addTimeToPerson()
is called.
Note: If no such person named "Alex Yeoh" exists, a CommandException
will be thrown.
Step 3. Model#addTimeToPerson()
will also call Person#addFreeTime()
which will add all times stored in the array list to the person's list of free times, given that none of the times clash with the person's existing free time intervals. If clashes do occur, the user will be notified of the problematic time intervals while the problem-free intervals will be added.
The following sequence diagram shows how the Add Time to Person operation works:
Note: The lifeline for AddTimeCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The Add Time to Group command mechanism behaves the same as the Add Time to Person command above, except it uses the Group
class instead of the Person
class.
Aspect: How to handle two similar but different commands (add meeting time to group and add free time to person)
Alternative 1 (current choice): Use different command words for both commands
Alternative 2: Use the same command word
Aspect: How to handle time clashes
Alternative 1 (current choice): Add all non-clashing time intervals
Alternative 2: Reject all time intervals
The Delete Time from person/group mechanisms are facilitated by the TimeInterval
class, involving other classes like Person
and Group
. It implements the following operations:
Person#deleteFreeTime()
— Deletes the inputted time intervals from the person.Group#deleteTime()
— Deletes the inputted time intervals from the group.These operations are exposed in the Model
interface as Model#deleteTimeFromPerson()
, Model#deleteTimeFromGroup()
respectively.
Below is an activity diagram that illustrates the control flow for Delete Person Time feature.
The proposed delete time feature is facilitated by the timeIntervalList
and Person
class. It accesses the timeIntervalList
from the Person
class and deletes a time interval with Person#deleteFreeTime()
. The operation is exposed in the Model
interface as Model#deleteTimeFromPerson
.
Step 1. The user launches the application. The AddressBook
will be initialized with the free time of its contacts.
Step 2. The user executes the command deleteTime n/Alex Yeoh t/mon 1200 - mon 1400 t/tue 1000 - wed 1600
. The deleteTimeCommandParser
will be called to parse the inputs and call the deletePersonTimeCommand
. The deletePersonTime
command calls Model#deleteTimeFromPerson()
, which will call Person#deleteFreeTime()
.
Note: Since multiple inputs are allowed, an array list of time intervals are passed around, each of which is to be deleted.
Step 3. The function will be called in the person's timeInterval
list. The application will loop through each time interval that is to be deleted and in the person's timeInterval
list. Each time interval will be compared to see whether the timeIntervalList
contains the time interval to be deleted. Afterwards, the new timeInterval
list will be saved.
Note: If a time interval is not in the person's list, that interval will be collated and printed to specifically notify the user which time intervals are not in the list. The other time intervals that are in the list will still be deleted.
The following sequence diagram summarizes what happens when a user executes a new command:
Note: The lifeline for DeleteTimeCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The Delete Time from Group command mechanism behaves the same as the Delete Time from Person command above, except it uses the Group
class instead of the Person
class.
Aspect: Error Messages
Alternative 1 (current choice): Print specific error messages.
StringBuilder
to craft the message and did extra checks to see whether there had been any errors appended to the error message.Alternative 2: Generalized error message.
Aspect: How to Handle Multiple Time Inputs
Alternative 1 (current choice): Parse each time input one by one and execute the commands.
Alternative 2: Allow only single input.
Aspect: How to Handle Errors in Time Intervals
Alternative 1 (current choice): Delete the time intervals that are correct and return the intervals that are wrong. Pros: Better user experience as users need not rewrite intervals that were right. Cons: Increased memory usage to store the errors.
Alternative 2: Do not carry out the delete at all. Pros: More time and memory efficient. Cons: Not as user-friendly since users will have to re-input the time intervals that were originally correct.
The List Time for person/group mechanisms are facilitated by the TimeInterval
class, involving other classes like Person
and Group
. It implements the following operations:
Person#getTime()
— Shows the person's time intervals.Group#getTime()
— Shows the group's time intervals.These operations are exposed in the Model
interface as Model#getTimeFromPerson()
, Model#getTimeFromGroup()
respectively.
Both ListTimePersonCommand
and ListTimeGroupCommand
implement an abstract class ListTimeCommand
, which helps to encapsulate the similarities between these two commands.
Since both List Time Person and List Time Group commands utilise the same command word listtime
, the ListTimeCommandParser
will create either a ListTimePersonCommand
or ListTimeGroupCommand
and return it as a ListTimeCommand
after parsing the user input.
The following activity diagram summarizes what happens when a user executes an add time command:
Given below is an example usage scenario and how the List Time from Person mechanism behaves at each step.
Step 1. The user executes listtime n/Alex Yeoh
command to list the free time intervals of a person named "Alex Yeoh" in the contact list. The ListTimeCommandParser
will be called to parse the inputs. It will then call the ListTimePersonCommand
.
Step 2. ListTimePersonCommand
is executed, in which Model#getTimeFromPerson()
is called.
Note: If no such person named "Alex Yeoh" exists, a CommandException
will be thrown.
Step 3. Model#getTimeFromPerson()
will also call Person#getTime()
which will parse all times stored in the array list into an easy-to-read chunk using a StringBuilder, and show it in the output box.
The following sequence diagram shows how the List Time from Person operation works:
Note: The lifeline for ListTimeCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The List Time from Group command mechanism behaves the same as the List Time from Person command above, except it uses the Group
class instead of the Person
class.
Aspect: How to handle two similar but different commands (add meeting time to group and add free time to person)
Alternative 1 (current choice): Use different command words for both commands
Alternative 2: Use the same command word
Aspect: Display format
Alternative 1 (current choice): Print raw list of times
Alternative 2: Organise time intervals by day.
The FindFreeTime mechanism is facilitated by the Model
, Group
and Person
class. It retrieves Group
from Model
to find a free time between group members in listOfGroupMates
in Group
with a duration specified, Duration
. The operation is exposed to Model
interface as Model#findGroup
.
Given below is an example usage scenario and how the list mechanism behaves at each step.
Step 1: User launches the application.
Step 2: User executes findfreetime g/CS2103 d/60
command to find a common meeting time with duration 60 minutes for group CS2103.
Step 3: FindFreeTimeCommandParser parses the group name CS2103 and duration 60, ensuring that duration is a valid integer in terms of minutes, and returns a FindFreeTimeCommand.
Step 4: FindFreeTimeCommand calls Model#findGroup(groupName)
to retrieve the group with matching name. If group does not exist, then an error is thrown.
Step 4: FindFreeTimeCommand calls Group#findFreeTime(duration)
, to retrieve the all common timeslots between listOfGroupMates
in Group
and return them in a list should they accommodate the duration stated.
Note:
If group is empty, having no group mates in listOfGroupMates
an error is thrown. If any group mate has not key in their free time slots using addtime
, an error is thrown.
The following activity diagram summarizes what happens when a user executes a FindFreeTime command:
Currently, we do not have undo and redo feature which open rooms for users to accidentally have typos in their command messages, causing certain unwanted commands to be executed. This can cause an array of problems, from deleting important data along with the contact, to inconvenience for the users themselves. As such, we plan to implement undo and redo feature in the future to provide a better user experience for our users.
addtime
/deletetime
featureCurrently, our add and delete time features allow users to input multiple time slots in the command box. Should a certain input encounter an error (clashing time intervals), ProjectPRO adds / deletes the other time intervals that are valid and clears the command box. We recognise that users might encounter accidental typos while typing time intervals. Hence, we plan to disallow the clearing command box when the user typed an invalid input.
Currently, ProjectPRO's output box height is relative short which could lead to user frustration and hindered efficiency. Users may find it challenging to quickly interpret and comprehend the output, especially when certain commands generate outputs with numerous lines. This limitation might result in a suboptimal user experience, making it difficult for users to extract the desired information promptly.Addressing this problem is crucial to ensuring a more user-friendly interface and improving the overall effectiveness of ProjectPRO for its users. Our future implementation involves optimizing the output display by increasing the height of the output box. This enhancement aims to provide users with a more comprehensive and visually accessible view, allowing them to easily grasp the content at a glance.
As ProjectPro is a CLI text-based application, it requires extensive typing which might prove troublesome at times. As a result, our users would naturally have their personal preferences regarding the command word inputs. Enabling users to customize input requirements for functions within ProjectPRO would significantly enhance the flexibility and adaptability of the system. This future implementation empowers users by allowing them to tailor input parameters based on their specific needs and preferences. By accommodating a range of input variations, users can streamline their workflows and optimize the tool to align with diverse use cases.
addmeeting
feature.In the addmeeting
feature, user can add free time intervals to a group. Currently, user can add same free time intervals for 2 separate groups or overlapping time intervals between 2 or more groups, causing a clash in their schedule. (Eg. Group A: Mon 1200 - Mon 1400
; Group B: Mon 1300 - Mon 1500
). These clashes are not detected and will allow this state to exist. We plan to not allow this, so user cannot insert time intervals that are overlapping with other groups. Eg. Group A: Mon 1200 - Mon 1400
; Group B: Mon 1300 - Mon 1500
will not be allowed.
Target user profile:
Value proposition: Text-friendly project management tool that helps students schedule meetings with different groups while also keeping track of tasks and responsibilities of each member. Our app will track the schedule of each contact and tasks individuals have to do for their project.
Priority | As a ... | I want to ... | So that I can ... |
---|---|---|---|
*** | student | add a new contact | keep track of any new contacts |
*** | student with many contacts | organize contacts into groups | easily keep track and manage my contacts |
*** | student with many team members | record team members' info | keep track of my team members' contact information |
*** | student with many projects | delete a group | avoid clutter and unnecessary attention to completed projects |
*** | student with many contacts | search for group members | quickly access contact details using name, contact number |
*** | user | save entered information | avoid repetitive data entry |
** | team leader | add tasks to contacts | remember who is responsible for which task |
** | student | filter contacts by project | easily view tasks for a specific project group |
** | user | prioritize tasks | work on important tasks first |
** | student | add time slots of group mates | find a suitable meeting time when everyone is available |
** | new user | access a help command | quickly learn about application functions without reading a long guide |
* | impatient user | access the user guide | quickly learn how to use the application |
* | technology-challenged student | read the user guide | gain a better understanding of how to use the application |
* | fast but inaccurate typer | undo a previous command | correct typing mistakes |
* | forgetful student | add a reminder | ensure attendance at upcoming project meetings |
* | student with many projects | color code projects | differentiate between various project groups |
* | lazy user | minimize typing/clicking | achieve tasks with minimal effort |
* | student with an irregular schedule | edit contact information | easily manage changes in contact details |
* | user | filter contacts by courses | view contacts based on shared courses or projects |
* | user | upload attachments/files | improve collaboration and reference for tasks and projects |
* | user | view contact profiles | access course schedules, contact details, and profile pictures |
(For all use cases below, the System is ProjectPRO
and the Actor is the user
, unless specified otherwise)
6.3.1. Use case 1: Creating contact
MSS
User requests to add contact.
ProjectPRO adds new contact.
ProjectPRO informs user contact has been successfully added.
Use Case ends.
Extensions:
1a. ProjectPRO detects error in input
1b. ProjectPRO detects duplicate contact requested by user.
6.3.2. Use case 2: Delete contact
MSS
User requests to delete contact
ProjectPRO deletes contact.
ProjectPRO informs user contact has been successfully deleted.
Use Case ends
Extensions
6.3.3. Use case 3: Finding a contact
MSS
Use Case ends.
Extensions
6.3.4. Use case 4: Listing all contacts
MSS
Use Case ends.
6.3.5. Use case 5: Creating a group
MSS
Use Case ends.
Extensions
6.3.6. Use case 6: Deleting a group
MSS
Use Case ends.
Extensions
6.3.7. Use case 7: Adding a group remark
MSS
Extensions
Use Case ends.
6.3.8. Use case 8: Finding a group
MSS
Use Case ends.
Extensions
6.3.9. Use case 9: Listing all groups
MSS
Use Case ends.
6.3.10. Use case 10: Add contact to group
MSS
Use Case ends.
Extensions
1a. If the group does not exist.
1b. If the contact does not exist.
6.3.11. Use case 11: Removing contact from group
MSS
Extensions
1a. If the group does not exist.
1b. If the contact does not exist.
6.3.12. Use case 12: Adding free time to contact
MSS
Use Case ends.
Extensions
1a. If the contact does not exist.
1b. If the time input does not follow the format.
6.3.13. Use case 13: Removing free time from contact
MSS
Extensions
1a. If the contact does not exist.
1b. If the time input does not follow the format.
6.3.14. Use case 14: Listing free time of contact
MSS
Extensions
6.3.15. Use case 15: Adding meeting time to group
MSS
Extensions
6.3.16. Use case 16: Remove meeting time from group
MSS
Extensions
6.3.17. Use case 17: Listing meeting time of group
MSS
6.3.18. Use case 18: Find free time of group
MSS
Extensions
Parameter | Description | Constraints | Valid Examples | Invalid Examples |
---|---|---|---|---|
n/ | Contact name of the student | Alphanumeric characters (a to z, A to Z, 0 to 9) | John Doe, David Li 2 | Kishen s/o Kasinathan, ナルト, அசிங்கமான |
p/ | Phone number of the student | Positive integer with 3 or more digits | 999, 98765432, 18003569377 | 1-800-356-9377, 0, -1, 98431234.5 |
e/ | Email of the student | Email prefix: Alphanumeric characters (a to z, A to Z, 0 to 9), @, Email Domain | example@gmail.com, example@moe.edu.sg | example@!.com, example@moed.edu.s |
g/ | Name of the group | Alphanumeric characters (a to z, A to Z, 0 to 9) | CS2103T, Group 3 | Group 3!, 1 |
r/ | Group remark | N/A | Zoom link: CS2101.zoom, 123!@#$#@ | N/A |
t/ | Time interval of student / group | timings are written with the first 3 letters of the day and time in 24 hour format, with a - between the timings. Start time cannot be after end time | mon 1300 - mon 1400, sat 1000 - sun 1300 | monday 1300 - tuesday 1200, wed 1300 - wed 1000 |
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 in the list.
Test case: delete n/Alex Yeoh
Expected: Alex is deleted from the list. Details of the deleted person shown in the status message. Timestamp in the status bar is updated.
Test case: delete n/Alex Yeoh
, after Alex has been deleted
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 n/x
, ...
(where x is not in the list)
Expected: Similar to previous.
Find a particular contact in your address book
Prerequisites: List all persons using the list
command. Multiple persons in the list.
Test case: find n/Alex Yeoh
Expected: Only contacts with Alex is shown in the list. Number of perosns with that name is shown.
Test case: find n/Alex Yeoh
, after Alex has been searched
Expected: No change to the status message.
Other incorrect find commands to try: find n/
, find n/x
, ...
(where x is not in the list)
Expected: Similar to previous.
Listing all contacts in your address book
Prerequisites: Find a limited number of persons using the find n/
command. No persons will be listed.
Test case: list
Expected: All contacts will be shown.
Other incorrect find commands to try: list n/
, list n/x
, ...
Expected: Error message shown.
Creating a group that does not exist
Test case: new g/CS2103
Expected: New group called CS2103 is added to ProjectPRO.
Test case: new g/CS2103
, after CS2103 has been created
Expected: No group is created. Error details shown in the status message. Status bar remains the same.
Other incorrect delete commands to try: new g/
, new g/x
, ...
(where x is a group in the ProjectPRO)
Expected: Similar to previous.
Deleting a Group
Prerequisites: List all persons using the list
command. Multiple persons in the list.
Test case: delete g/CS2103
Expected: CS2103 is deleted from the list. Details of the deleted group shown in the status message. Group tag under contacts in that group is removed.
Test case: delete g/CS2103
, after CS2103 has been deleted
Expected: No group is deleted. Error details shown in the status message. Status bar remains the same.
Other incorrect delete commands to try: delete
, delete n/x
, ...
(where x is not in the list)
Expected: Similar to previous.
Adding a group remark
Test case: remark g/CS2103 r/Lecture on friday
Expected: New remark with "Lecture on friday" is added to CS2103.
Test case: remark g/CS2103 r/Lecture on thursday
, after CS2103 has a remark added
Expected: Old remark is replaced with new remark.
Incorrect remark commands to try: remark g/
, remark g/x r/Lecture on wednesday
, ...
(where x is a group in the ProjectPRO)
Expected: Error message displayed.
Find a particular group in your address book
Prerequisites: List all persons using the list
command. Multiple persons in the list.
Test case: find g/CS2103
Expected: Only contacts in the group is shown in the list. Group remark of the group is displayed.
Test case: find g/CS2103
, after CS2103 has been searched
Expected: No change to the status message.
Other incorrect find commands to try: find g/
, ...
Expected: Error message displayed.
Listing all groups in your address book
Test case: listgroup
Expected: All groups will be shown in the contact box.
Other incorrect find commands to try: listgroup g/
, listgroup cs2103
, ...
Expected: Error message shown.
Adding a contact to a group
Prerequisite: list
Expected: All contacts will be shown in address book.
Test case: group n/Alex Yeoh g/CS2103
Expected: Alex is added to the group. A CS2103 group tag is added below his name.
Incorrect group commands to try: group n/ g/
, group n/Alex Yeoh g/x
, group n/x g/CS2103
(where x is an unadded contact / group)
Expected: Error message shown.
Ungrouping a contact
Prerequisite: list
Expected: All contacts will be shown in address book.
Test case: ungroup n/Alex Yeoh g/CS2103
Expected: Alex Yeoh's group tag is removed.
Test case: ungroup n/Alex Yeoh g/CS2103
, after Alex has been ungrouped
Expected: No change to the address book, error message shown in output box.
Other incorrect find commands to try: ungroup n/Alex Yeoh g/
, ungroup n/ g/CS2103
, ...
Expected: Error message displayed.
Add free time to contact
Prerequisite: list
Expected: All contacts will be shown in address book.
Test case: addtime n/Alex Yeoh t/mon 1300 - mon 1400
Expected: Free time added to contact, contact has a time interval tag underneath his name.
Test case: addtime n/Alex Yeoh t/mon 1300 - mon 1400
, after previous command
Expected: No change to the address book, error message shown in output box stating there is a clash in timing.
Other incorrect find commands to try: addtime n/Alex Yeoh t/mon 1300 - mon 1200
, addtime n/Alex Yeoh t/monday 1300 - monday 1400
, ...
Expected: Command format error.
Delete free time to contact
list
addtime n/Alex Yeoh t/mon 1300 - mon 1400
Test case: deletetime n/Alex Yeoh t/mon 1300 - mon 1400
Expected: Free time deleted from contact, contact's time interval tag underneath his name is removed.
Test case: deletetime n/Alex Yeoh t/mon 1300 - mon 1400
, after previous command
Expected: No change to the address book, error message shown in output box stating time is not in his list.
Other incorrect find commands to try: deletetime n/Alex Yeoh t/mon 1300 - mon 1200
, deletetime n/Alex Yeoh t/monday 1300 - monday 1400
, ...
Expected: Command format error.
Add free time to contact
list
addtime n/Alex Yeoh t/mon 1300 - mon 1400
Test case: listtime n/Alex Yeoh
Expected: All time intervals under contact is listed in output box.
Test case: listtime n/Alex Yeoh
, after previous command
Expected: No change to the address book.
Other incorrect find commands to try: listtime n/Alex Yeoh t/mon 1300 - mon 1200
, ...
Expected: Error message.
Add free time to contact
Prerequisite: list
Expected: All contacts will be shown in address book.
Test case: addmeeting g/CS2103 t/mon 1300 - mon 1400
Expected: Meeting time added to group, day card on the right has a time interval tag under monday.
Test case: addmeeting g/CS2103 t/mon 1300 - mon 1400
, after previous command
Expected: No change to the address book, error message shown in output box stating there is a clash in timing.
Other incorrect find commands to try: addmeeting g/CS2103 t/mon 1300 - mon 1200
, addmeeting g/CS2103 t/monday 1300 - monday 1400
, addmeeting g/x t/mon 1300 - mon 1400
, ...
(where x is not an existing group)
Expected: Command format error.
Delete meeting time from group
Prerequisite: list
Expected: All contacts will be shown in address book.
Prerequisite: addmeeting g/CS2103 t/mon 1300 - mon 1400
Expected: Meeting time added to group, day card on the right has a time interval tag under monday.
Test case: deletetime g/CS2103 t/mon 1300 - mon 1400
Expected: Meeting time deleted from contact, time interval tag under the day card on the right is removed.
Test case: deletetime g/CS2103 t/mon 1300 - mon 1400
, after previous command
Expected: No change to the address book, error message shown in output box stating time is not in the list.
Other incorrect find commands to try: deletetime g/CS2103 t/mon 1300 - mon 1200
, deletetime g/CS2103 t/monday 1300 - monday 1400
, deletetime g/x t/mon 1300 - mon 1400
, ...
(where x is not an existing group)
Expected: Command format error.
Add free time to contact
list
addtime g/CS2103 t/mon 1300 - mon 1400
Test case: listtime g/CS2103
Expected: All time intervals under group is listed in output box.
Test case: listtime g/CS2103
, after previous command
Expected: No change to the address book.
Other incorrect find commands to try: listtime g/CS2103 t/mon 1300 - mon 1200
, ...
Expected: Error message.
Add free time to contact
list
group n/Alex Yeoh g/CS2103
, group n/Bernice Yu g/CS2103
addtime n/Alex Yeoh t/mon 1200 - mon 1300
, addtime n/Bernice Yu t/mon 1200 - mon 1300
Test case: findfreetime g/CS2103 d/60
Expected: mon 1200 - mon 1300 is listed in output box
Test case: findfreetime g/CS2103 d/1
, after previous command
Expected: No change to the address book.
Test case: findfreetime g/CS2103 d/70
, after previous command
Expected: No available timeslots will be shown in output box.
Other incorrect find commands to try: findfreetime g/CS2103 d/
, findfreetime g/ d/70
, findfreetime g/CS2103 d/0
, ...
Expected: Error message.
Dealing with missing/corrupted data files
ProjectPRO is a project built upon AB3, which was built out of the SE-EDU initiative. Our group has been actively working on ProjectPRO this semester, meeting regularly to discuss about our application to meet deadlines punctually.
In this section, we will detail some challenges we faced throughout the process of creating ProjectPRO.
As ProjectPRO is a brownfield project built from AB3, it was necessary to identify the pros and cons of AB3, and use them to come up with a better application more suited for university students. Some challenges include: