By: Team Naggy Joel
Since: Mar 2020
Licence: MIT
- 1. Setting up
- 2. Design
- 3. Implementation
- 4. Documentation
- 5. Testing
- 6. Dev Ops
- Appendix A: Product Scope
- Appendix B: User Stories
- Appendix C: Use Cases
- Appendix D: Non Functional Requirements
- Appendix E: Glossary
- Appendix F: Instructions for Manual Testing
- F.1. Launch and Shutdown
- F.2. Adding a person
- F.3. Deleting a person
- F.4. Editing a person
- F.5. Adding additional information to a person
- F.6. Editing additional information for a person
- F.7. Deleting additional information of a person
- F.8. Finding a specific contact/specific set of contacts
- F.9. Retrieving a specific contact and view in full details
- F.10. List contacts with upcoming birthdays
- F.11. Adding a restaurant
- F.12. List all restaurants saved
- F.13. Editing a restaurant
- F.14. Deleting a restaurant
- F.15. Adding food note(s) to a restaurant
- F.16. Editing food note(s) of a restaurant
- F.17. Deleting food note(s) of a restaurant
- F.18. Search for restaurants based on a number of criteria
- F.19. Adding an assignment
- F.20. List current assignments
- F.21. Deleting an assignment
- F.22. Editing an assignment
- F.23. Generating schedule
- F.24. Adding a social event
- F.25. Listing all events
- F.26. Editing a social event
- F.27. Deleting a social event
1. Setting up
Refer to the guide here.
2. Design
2.1. Architecture
The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.
The .puml files used to create diagrams in this document can be found in the diagrams folder.
Refer to the Using PlantUML guide to learn how to create and edit diagrams.
|
-
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 method where necessary.
Commons
represents a collection of classes used by multiple other components.
The following class plays an important role at the architecture level:
-
LogsCenter
: Used by many classes to write log messages to the App’s log file.
The rest of the App consists of four components.
Each of the four components
-
Defines its API in an
interface
with the same name as the Component. -
Exposes its functionality using a
{Component Name}Manager
class.
For example, the Logic
component (see the class diagram given below) defines it’s API in the Logic.java
interface and exposes its functionality using the LogicManager.java
class.
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
.
delete 1
commandThe sections below give more details of each component.
2.2. UI component
API : 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.
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.
2.3. Logic component
API :
Logic.java
-
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("delete 1")
API call.
delete 1
Command
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.
|
2.4. Model component
API : Model.java
The Model
,
-
stores a
UserPref
object that represents the user’s preferences. -
stores the Address Book data.
-
exposes an unmodifiable
ObservableList<Person>
that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. -
does not depend on any of the other three components.
As a more OOP model, we can store a Tag list in Address Book , which Person can reference. This would allow Address Book to only require one Tag object per unique Tag , instead of each Person needing their own Tag object. An example of how such a model may look like is given below. |
2.5. Storage component
API : Storage.java
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.
2.6. Common classes
Classes used by multiple components are in the seedu.addressbook.commons
package.
3. Implementation
This section describes some noteworthy details on how certain features are implemented.
tag::schedule[]
(Elysia Tan Ziyi: 3.1, 3.2)
3.1. Schoolwork Tracker
The SchoolworkTracker
helps users keep track of their assignments so that they do not accidentally overlook any of them. It consists of the AssignmentList
which contains all the added assignments.
From Fig 1 below, each Assignment
has four components: Title
, Deadline
, Status
and Workload
. Workload
refers to the expected amount of time required to finish the Assignment
. These components will be used for schedule generation when (st)schedule n/NUM_DAYS
is executed (explained below).
Fig 1. Class Diagram detailing the main components of the SchoolworkTracker
3.2. Schedule
3.2.1. Current Implementation
Schedule is facilitated by the SchoolworkTracker
. This feature enhances the basic form of the SchoolworkTracker
by allowing users to better visualise their current commitments so that they can better manage their time to pursue social events. This feature aims to distribute Workload
as evenly as possible while ensuring that the user is able to complete the Assignment
before the Deadline
, unless it is impossible (i.e. Workload
exceeds the amount of time the user has before the Deadline
after taking into account more urgent assignments). A sample result is shown in Fig 2 below.
Fig 2. Sample result of the generated schedule
It utilizes the existing Assignment
stored in the SchoolworkTracker
and implements ScheduleList
which represents the generated schedule.
As seen from Fig 3 below, ScheduleList
consists of Day
objects and each Day
has 3 components. totalAllocatedHours
represents the total number of hours allocated to the Day
.
dueAssignment
refers to an assignment that is due on the Day
and allocatedAssignment
represents an assignment that has been scheduled to be done on that Day
. The latter also has an additional field allocatedHours
which correspond to the suggested amount of time
that should be spent on the assignment on that Day
.
Fig 3. Class Diagram detailing the main components of ScheduleList
Given below is a detailed example of how the schedule command behaves at each stage.
Step 1: User launches Naggy Joel
for the first time. SchoolworkTracker
is initialized to an empty list.
Step 2: User executes the add assignment command [(st)add n/NAME d/DEADLINE e/ESTIMATED_COMPLETION_HOURS
] to add assignments to the SchoolworkTracker
.
Step 3: User wants to better understand his schedule for the next 5 days before deciding whether he has time to hang out with his friends and executes (st)schedule n/5
.
As seen from Fig 4 below, after the user enters the schedule command, the command will first be checked for validity. If it is not valid, the user will be informed and can then choose whether to re-enter the command or enter another command. On the other hand, if the input command is valid, the application will proceed to generate his schedule and after display it on the GUI.
Fig 4. Activity Diagram summarizing what happens when the schedule command is entered
The specific workings of the schedule command will be explained in the paragraphs below.
As seen from Fig 5 below, arguments from the input command is first parsed using the ScheduleCommandParser
which converts
the string variable into an integer and then passes it to ScheduleCommand
for use later on and represents the NUM_DAYS
queried. If the input argument is invalid, a ParseException
is thrown instead and the user will be notified of the proper command usage. If the command is valid, the ScheduleCommand
object will be created and returned to the LogicManager
who will then call the execute()
method in ScheduleCommand
.
Fig 5. Sequence Diagram depicting the creation of ScheduleCommand object
As seen from Fig 6 below, the necessary preparations will be made before the schedule is being generated:
-
The
ScheduleCommand
will retrieve thefilteredAssignments
from theModel
component. -
The
ScheduleList
will then be initialized to have a size equals to theNUM_DAYS
queried by the user, which in this example is5
since the user typed(st)schedule n/5
.
Fig 6. Sequence Diagram showing the execution of the ScheduleCommand
The schedule generation process will be explained next and begins with Fig 7 all the way to Fig 9.
In Fig 7 below, filteredAssignments
is iterated through in sorted order, starting with the Assignment
due the earliest and for all assignments:
-
The
Status
andDeadline
of theAssignment
will be retrieved. -
If
Status
is uncompleted andDeadline
is not over,Workload
will be distributed.
Fig 7. Sequence Diagram showing the process of generating the schedule
As shown in Fig 8 below, for each uncompleted Assignment
:
-
Workload
is retrieved and distributed across several days, from query date to deadline, incrementally so as to generate a balanced schedule. -
The final allocation of hours, including amount unscheduled, is recorded and the
Assignment
will be recorded as adueAssignment
if its deadline falls within the range of days queried.
Fig 8 Sequence Diagram showing how an uncompleted Assignment is handled
Fig 9. Sequence Diagram showing how the workload of an assignment is distributed
From Fig 9 above, assignments due on query date are handled differently from those that are not.
-
Assignment
due on query date: The amount of time that can be allocated to the assignment will be capped at the amount of time available before theDeadline
. -
Assignment
not due on query date: Incremental distribution ofWorkload
starting from days with no allocated hours, then days with least amount of allocated hours and lastly allocating evenly.-
Between query date and deadline (both exclusive): Available time is capped at 24 hours.
-
Query date: Available time is capped at the amount of time left in the day.
-
Deadline: Available time is capped at the amount of time before the assignment is due.
-
Actual caps are as above but after accounting for hours already allocated to other assignments.
Once the user’s schedule is generated, ScheduleList
is updated with the allocationResult
, a CommandResult
object will be created and returned to LogicManager
. LogicManager
returns it to MainWindow
who
will then retrieve the generated schedule and display it as shown in Fig 10 below.
Fig 10. Sequence Diagram showing how the generated schedule is retrieved
Step 4: Based on the results, the user can then decide on how to best schedule his outing.
3.2.2. Design Considerations
Aspect: Distribution of estimated work hours for each assignment
-
Current choice: Hours are allocated incrementally to achieve a balanced schedule while still ensuring that deadlines can be met (unless impossible due to the constraints of time left)
-
Pros: Better reflects the real-world scenario where students are more likely to spread out their work and encourages work life balance which is the main selling point of Naggy Joel.
-
Cons: Complicated algorithm is more prone to errors.
-
-
Alternative: For each day, cumulatively add
Workload divide by Number of days to deadline
for all assignments-
Pros: Easier to implement.
-
Cons: Some days may have impossibly high workload, deadlines are not handled properly.
-
Aspect: Variable type to be used for calculations during distribution of workload
-
Current choice: Use of BigDecimal for calculations
-
Pros: More accurate allocation of hours while minimizing lost hours due to rounding errors.
-
Cons: Harder to handle and new objects have to be created each time.
-
-
Alternative: Restrict calculations to the use of integer
-
Pros: Easier to handle and more accurate comparisons can be made as compared to when floats are used as floating point arithmetic is not exact.
-
Cons: A lot of unnecessary ‘loss’ in allocated and available time due to rounding errors.
-
end::schedule[]
tag::get[]
(Kwan Xin Jie: 3.3, 3.4, 3.5)
3.3. Detailed Contact Viewer
3.3.1. Implementation
The detailed contact viewer is facilitated by AddressBook
. This feature allows a user to view a particular contact details in entirety.
Given below is an example usage scenario and how the get mechanism behaves at each step.
Step 1. The user launches the application for the first time. The AddressBook
will be initialized with the initial state, which is an empty list.
Step 2. The user executes the (ab)add n/David p/12345 …
command to add a new person.
Step 3. The user executes the (ab)get 1
command to get the detailed contact of the first person in the AddressBook list.
The following sequence diagram shows how the get operation works within the Logic
component:
3.3.2. Design Considerations
Aspect: What information to display
-
Alternative 1 (current choice): Set a limit on details that has a potential long list (such as NoteTaker) and display them on the detailed contact viewer.
-
Pros: All information are displayed for easier viewing/access.
-
Cons: AddressBook list might be long and hard to view.
-
-
Alternative 2: Display selective information on the AddressBook list and the full information under get command.
-
Pros: AddressBook list is less cluttered.
-
Cons: Omits certain information.
-
end::get[]
tag::sortAssgn[]
3.4. Sorting of Assignments
3.4.1. Implementation
The sorting of assignments is facilitated by AssignmentList
. This feature allows a user to sort assignments by deadline or estimated completion time.
Given below is an example usage scenario and how the sort mechanism behaves at each step.
Step 1. The user launches the application for the first time. The 'AssignmentList' will be initialized with the initial state, which is an empty list.
Step 2. The user executes the following commands to add new assignments.
-
1.
(st)add t/CS2103 Project d/2020-04-18 23:59 e/180
-
2.
(st)add t/DBA3702 Project d/2020-04-19 19:00 e/150
-
3.
(st)add t/CS2106 Lab d/2020-04-11 20:00 e/20
Step 3. The user executes the (st)list -d
command to sort the assignments by deadline.
The following sequence diagram shows how the list assignment operation works within the Logic
component:
3.4.2. Design Considerations
Aspect: How to sort assignment by estimated completion time
-
Alternative 1 (Current choice): Descending order
-
Pros: User can prioritise by doing the assignment which takes the longer first.
-
Cons: User may spend too much time on assignments that take much longer.
-
-
Alternative 2: Ascending order
-
Pros: User can clear more assignments faster, by completing those that takes a shorter amount of time first.
-
Cons: User may delay starting on assignments that take longer and risk having uncompleted assignments at the deadline.
-
end::sortAssgn[]
tag::editRestNote[]
3.5. Editing of Restaurant Notes
3.5.1. Implementation
The editing of restaurant notes is facilitated by RestaurantBook
. This feature allows a user to edit existing notes of a restaurant in the list.
Given below is an example usage scenario and how the editing of note mechanism behaves at each step.
Step 1: The user launches the application for the first time. The RestaurantBook
will be initialized with the initial state, which is an empty list.
Step 2: The user executes the following commands to add notes to a restaurant.
-
1.
(rt)add n/Ameens l/Clementi v/No o/0900:2300 p/$ c/Indian
-
2.
(rt)addnote r/Cheese fries
Step 3: The user executes the (rt)editnote 1 rl/1 r/Butter chicken
command to edit the first recommended food of the restaurant at index 1, to Butter chicken.
The following sequence diagram shows how the edit restaurant note operation works within the Logic
component.
3.5.2. Design Considerations
Aspect: How to execute the command for edit note, given 3 editable notes for a restaurant.
-
Alternative 1 (chosen): Have one command that allows user to choose any note to edit.
-
Pros: Easy for user to use, without switching between different commands.
-
Cons: As line number of the relevant note needs to be indicated, many levels of checking of the user input is required, and is thus more prone to errors.
-
-
Alternative 2: Have 3 separate edit commands, one for each restaurant’s note.
-
Pros: Easier to implement.
-
Cons: Not user-friendly since different notes cannot be edited in a single command.
-
end::editRestNote[]
tag::findContacts[]
(Chua Xinhui Sarah: 3.6)
3.6. Finding Contacts
3.6.1. Implementation
The finding of a Person is facilitated by the Address Book
. This feature allows for users to find a specific contact in their Address Book
.
Given below is an example usage scenario and how the finding contact mechanism behaves at each step.
Step 1: The user launches the application for the first time. The Address Book
will be initialized with the initial state, which is an empty list.
Step 2: The user executes the (ab)add n/Joel …
command multiple times with different details of different people to add multiple people as contacts into the Address Book
.
Step 3: The user executes the (ab)find …
command to find their desired contacts in the AddressBook list. For instance, the user may do:
* (ab)find o/NUS
searches by organization.
* (ab)find n/Joel Lim
searches by name.
* (ab)find t/friends
searches by tags.
The following sequence diagram shows how the find operation works within the Logic
component.
3.6.2. Design Considerations
Aspect: How to execute the command for finding a contact using Java Predicates, given that a Person has multiple tags.
Current implementation of Predicates uses the stream
and anyMatch
commands to check each keyword against one single word, but since a person may have multiple tags, the implementation needs to be able to check each keyword against multiple tags instead of a single tag.
-
Alternative 1 (chosen): Concatenate all the tags of a person together into a String, and check the provided tag keywords against that one String.
-
Pros: Easier to implement.
-
Cons: -
-
-
Alternative 2: For each person’s unique tags, create one Tag Predicate per tag.
-
Pros: Conceptually easier to understand, as well as to draw the UML diagram.
-
Cons: Many Tag Predicate objects would have to be created. This could be messy and cause debugging to be difficult.
Aspect: How to sort the provided keywords into different Predicates given that there are multiple fields we can search against (eg. Organization, Name, etc)
-
Alternative 1 (chosen): Have a loop to parse the keywords and sort them into different Predicate keyword lists depending on where the prefixes are located. For instance, if the user types
(ab)find t/friends colleagues o/NUS
, then the keywordsfriends
andcolleagues
would to go to the Tag Predicate while the keywordNUS
would be allocated to the Organization Predicate. -
Pros: Easier for the user because they just have to demarcate which keywords are used for which using a single prefix.
-
Cons: More difficult to implement.
-
Alternative 2: Have the user include the prefix before every different keyword they want to search. For instance, if they want to search using 2 different tag keywords like "friends" and "colleagues", they would have to type
(ab)find t/friends t/colleagues
. Then we can use the Argument Multimap to tokenize the arguments. -
Pros: Easier to implement.
-
Cons: More troublesome for the user because if they want to search for multiple tags, they would have to keep typing the
/t
prefix for each keyword. end::findContacts[]
tag::rtundoredo[]
(Joel Lim Hee Heng: 3.7, 3.8)
3.7. Restaurant Book
3.7.1. Current Implementation
The RestaurantBook
helps users keep track of Restaurants
, so that users can quickly find an eating place given their constraints (e.g. odd hours, location, food cravings, etc). We will briefly introduce the implementation and logic behind this component as a stepping stone to understand the undo/redo
implementation in the next section.
The following depicts the class diagram for the Restaurant
component of the application.
Each Restaurant
has 9 components Name
, Location
, Visit
, Hours
, Price
, Cuisine
, and 3 lists of Note
to represent the recommended, good, and bad food that the user can input. visit
represents whether the user has visited the restaurant, and hours
represent the restaurant’s opening hours. The other fields are self-explanatory.
We will illustrate how commands to the RestaurantBook
works using the simple (rt)add
command, which adds a new Restaurant
to the RestaurantBook
.
The above shows a medium level abstraction of the activity diagram with swim lanes when the user enters a valid add restaurant command. Even though the command is valid, the parameters might not be, or the restaurant entered might be a duplicate (duplicate iff the name and phone matches). Hence, the corresponding units check for these executing the command.
Once these checks pass, before the ModelManager
adds the new restaurant in, the ModelManager
first does some housekeeping to support the undo/redo
operation as seem in the activity diagram. This is the key we want to illustrate here to better understand undo/redo
. This is very useful because all commands that change the state will go through a similar process. More details are given below.
3.8. Undo/Redo
3.8.1. Current Implementation
This is the Class Diagram for the ModelManager
and the ModelState
, the 2 integral classes to understand the undo/redo
operations. Note that we have omitted methods used to support other commands but are irrelevant to the undo/redo
operation and also omitted the getter methods of the ModelState
for better readability.
The undo/redo
mechanism is facilitated by modifying ModelManager
to include 3 additional attributes.
undoStack: which stores the lists of ModelState
from which the undo
operation will draw upon
redoStack: which stores the lists of ModelState
from which the redo
operation will draw upon
** currentModel: which is simply the ModelState
that the application is currently in
We will now go through a very simple example of how the undo/redo
operation is implemented. Assume the following is the initial state:
-
Step 1: When the user launches the application for the first time, the undo stack is initialised to only 1 state, which is the current state. The redo stack will always be empty initially.
-
Step 2: Suppose the user executes
(rt)add n/KFC l/East v/No
to add a new restaurant. This is a command that changes the state of the model. Hence, the application will execute a series of commands that is equivalent to duplicatingm0
, pushing the duplicate into the undo stack, and then making thecurrentModel
pointer point to the top of the stack. All changes will then be made to this new duplicate, with the previous statem0
intact at the bottom of the undo stack. The redo stack still remains empty.
-
Step 3: Now, suppose the user executes the
undo
command. TheModelManager
will simply push the current statem1
into the redo stack, and make the current state pointer point to the resultant top element in the undo stackm0
, which will be the state before the user entered the last command, effectively restoring the previous state. The redo stack simply stores all the undone states.
Note that if the user executes the undo
command when the undo stack has only 1 state, an error will be returned.
-
Step 3.1: Now, if the user then executes the
redo
command, the application will simply push the top statem1
in the redo stack into the undo stack, and make the current state pointer point to the resultant top state in the undo stack again.
Note that if the user executes the redo
command when the redo stack is empty, an error will be returned.
-
Step 3.2: However, suppose if instead of executing the
redo
command, the user executes another command that changes the state such as(rt)delete 1
, apart from modifying the undo stack as we mentioned earlier when the user executes a command, the redo stack will also be emptied, since there is nothing to redo anymore.
This is a brief summary of how the undo/redo
operation is implemented. In reality, the type of command that caused the change is also stored in the ModelState
. This is to ensure that we can display the appropriate visual confirmation in the UI when the user executes an undo
or redo
command. For example, when the user redoes a command that added a restaurant, we will want to display the lists of restaurants instead of whatever the user is looking at now.
For greater detail, below is the sequence flow diagram when the user executes an undo
command:
redo
is simply the opposite of undo
. Instead of popping from undo stack and pushing into redo stack, ModelManager
pops from the redo stack and pushes the popped state into the undo stack. The current state is still the top of the undo stack.
The update()
simply makes the other attributes of the ModelManager
point to the corresponding ones in the current state. That is, to update them to point to the current copy. This makes the code cleaner as we don’t have to always access them from the currentModel
pointer.
Lastly, do note that there are 2 types of commands:
Commands that alters the state (e.g. add, edit): the ModelManager
will do the housekeeping to duplicate the state before executing these commands
Commands that do not alter the state (e.g. list, get): these commands do not alter the state, and the ModelManager
will simply execute these commands without duplicating the state
3.8.2. Design Considerations
Aspect: How undo & redo executes
-
Alternative 1: Creates and saves the entire state of the application from scratch
-
Pros: Easy to implement
-
Cons: Requires huge amount of memory
-
-
Alternative 2: Stores only the individual command entered
-
Pros: Minimal memory usage
-
Cons: More difficult to ensure correctness as there will be many more alternate paths (scales as the number of commands go up)
-
-
Alternative 3 (current choice): Partially stores the entire application
-
Pros: Easy to implement
-
Cons: Require significant amount of memory, but less than alternative 1
-
For alternative 3, the current implementation seems to store the entire application, but in reality, the end objects that the pointers in each ModelState
are pointing to are largely the same. For example, suppose we have 1,000 persons in the AddressBook and we edit person 1000. The new ModelState
actually points to the same Person object for the 1st 999 objects and only differs in the 1000th object.
Aspect: Which commands will cause a state change
-
Alternative 1: Every command will generate a new state
-
Pros: Easy to implement (need not differentiate); can be more intuitive to some users (e.g. the user accidentally
(rt)list
and would like to go back to what the user was viewing previously) -
Cons: Requires more memory; can be less intuitive to some users as the
undo
for commands such as(rt)list
only changes what the user sees but does not perform any real changes to the state
-
-
Alternative 2 (current choice): Only commands that change the state will cause state transitions
-
Pros: Less memory usage, can be more intuitive to some users; in reality, difficult to tell which is more intuitive to users without more data
-
Cons: More difficult to ensure correctness as we need to ensure the exact set of commands that cause state transitions
-
Aspect: What to show when the user executes a undo
or redo
-
Alternative 1: Simply show the same screen
-
Pros: Easy to implement, need to only take care of the backend without worrying about the UI; user might not want to move away from his/her current screen
-
Cons: User has no confirmation that the undo did happen (e.g. if the user undoes adding a restaurant but we don’t show the updated restaurant list)
-
-
Alternative 2 (current choice): Displays what the user has undone/redone (e.g. if the user undoes adding a note to a contact, we should show the details of that contact upon the
undo
operation)-
Pros: Gives user confirmation of the new data and that the command is indeed undone
-
Cons: More difficult to implement and requires more memory as we will have to store more information to flash to the user the correct screen that corresponds to the command
-
end::rtundoredo[]
3.9. Logging
We are using java.util.logging
package for logging. The LogsCenter
class is used to manage the logging levels and logging destinations.
-
The logging level can be controlled using the
logLevel
setting in the configuration file (See Section 3.10, “Configuration”) -
The
Logger
for a class can be obtained usingLogsCenter.getLogger(Class)
which will log messages according to the specified logging level -
Currently log messages are output through:
Console
and to a.log
file.
Logging Levels
-
SEVERE
: Critical problem detected which may possibly cause the termination of the application -
WARNING
: Can continue, but with caution -
INFO
: Information showing the noteworthy actions by the App -
FINE
: Details that is not usually noteworthy but may be useful in debugging e.g. print the actual list instead of just its size
3.10. Configuration
Certain properties of the application can be controlled (e.g user prefs file location, logging level) through the configuration file (default: config.json
).
4. Documentation
Refer to the guide here.
5. Testing
Refer to the guide here.
6. Dev Ops
Refer to the guide here.
Appendix A: Product Scope
Target user profile: Busy university students who want to balance their hectic work schedule as well as their social life.
-
Has the need to manage a significant number of contacts and project/assignment deadlines
-
Has the need to manage a significant number of friends' birthdays and their miscellaneous information (such as their likes and dislikes)
-
Can type fast and prefers typing over mouse input
-
Is reasonably comfortable using CLI applications
-
Prefers desktop applications instead of other applications
Value proposition: A one-stop application for managing your social life, allowing you to manage contacts faster than a typical mouse/GUI driven app.
-
Afraid that you will forget your best friend’s birthday? Naggy Joel will remind you!
-
Not sure where you want to hang out? Naggy Joel can suggest places for you!
-
Want to hang out with your friends but not sure when you can because of your hectic university schedule and many deadlines? Naggy Joel will help you find the time!
Appendix B: User Stories
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
|
new user |
see usage instructions |
refer to instructions when I forget how to use the app |
|
user |
add new contact |
so that I can expand my address book |
|
user |
list all my contacts according to particular filters |
easily search and locate the people I want to find according to certain filters |
|
user |
edit my contacts |
update my contacts’ information to ensure accuracy of my data |
|
busy university student |
be reminded of my friends' birthdays as and when they are approaching |
have no need to memorize all my friends' birthdays |
|
busy university student with many groupmates and friends |
find and sort contacts by certain criteria (eg. find by name, find by tags, find by organization) |
locate my friends and groupmates easily |
|
user |
undo and redo commands |
reverse mistakes. |
|
user |
view a contact in its entirety |
see all the information pertinent to a particular contact |
|
user |
add notes to a particular contact |
store additional useful information pertaining to a particular contact |
|
busy university student with many assignments and project deadlines scattered throughout the semester |
be provided timely reminders of my work deadlines |
not have to remember the specific timing, date and deliverables of each assignment. |
|
busy university student with a hectic work schedule |
get a sense of how free I am to go out with my friends and pursue other social events given my upcoming deadlines |
pursue social events without missing my deadlines |
|
busy university student with a hectic work schedule |
be able to be suggested places to eat with my friends based on "KIV" notes for certain restaurants |
choose a gathering place without much hassle |
|
university student who wants to live life to the fullest |
be able to schedule social events whenever I have free time |
still hang out with my friends amidst all the school work. |
|
university student with many places to explore |
be able to keep track of the different must-try food places |
visit them when hanging out with friends. |
|
university student with many places to explore |
be able to keep track of the different food places that opens at odd times |
eat when I’m studying until the wee hours. |
|
university student with different groups of friends |
be able to categorise my contacts |
know how I met them. |
|
user |
be able to delete unwanted contacts/details |
keep the application free from clutter and ensure that it does not take up unnecessary space. |
|
user |
be able to keep track of the restaurants I have visited |
have a list of restaurants to go to when I have no preferences. |
|
university student who aims to have a good social life |
be able to remember miscellaneous information about my friends |
easily find places to hang out with my friends and identify gifts to buy for their birthdays. |
|
university student with many assignment to keep track of |
mark assignments as done |
have a better idea of my remaining assignments. |
|
busy university student with many assignments and projects |
add an assignment to the app |
not have to remember the details and deliverables of each assignment. |
|
busy university student with many events to attend and friends to catch up with |
keep track of all the events that I need to attend |
do not miss any meetings and anger anyone. |
|
user who has visited many different restaurants |
be able to keep track of terrible dishes at each restaurant |
I can avoid ordering them again. |
Appendix C: Use Cases
(For all use cases below, the System is the AddressBook
and the Actor is the user
, unless specified otherwise)
Use case: Adding an assignment
MSS
-
User adds an assignment by typing the "(st)add" command and includes description of the assignment, deadline, and number of estimated hours to complete the work.
-
Naggy Joel adds the assignment to the list of assignments.
Use case ends.
Extensions
-
1a. The given description, deadline, and number of estimated hours to complete work is invalid/empty.
-
1a1. Naggy Joel shows an error message.
-
1a2. User enters new data
Steps 1a1 and 1a2 are repeated until the data entered are correct
Use case resumes at step 2.
-
Use case: Finding restaurants to hang out
MSS
-
User requests to list out all upcoming social events.
-
Naggy Joel lists out all upcoming social events, displaying the dates and times of each event.
-
User chooses the event for which he wants to find a restaurant for and notes down the time and location.
-
User searches for restaurants based on the location of the event.
-
Naggy Joel lists out all restaurants that match the given location.
-
User selects a restaurant based on the opening hours and the attendees of the event.
Use case ends.
Extensions
-
4a. There are no restaurants that match the location that the user used to search.
-
4a1. Naggy Joel shows an error message.
-
4a2. User searches using a nearby location
Steps 4a1 and 4a2 are repeated until a restaurant is shown
Use case resumes at step 2.Use case ends.
-
Use case: Finding time for a social event
MSS
-
User requests to know his schedule for the upcoming period (can be the next day, week or month)
-
Naggy Joel generates and displays the user’s schedule for the upcoming period.
-
User chooses a period of free time as shown by Naggy Joel.
-
User creates social event and inputs just the description of social event.
-
Naggy Joel creates the social event and adds it to the list of upcoming social events.
Use case ends.
Extensions
-
4a. User cancels creating a social event.
-
4a1. Naggy Joel cancels the creation of the social event.
Use case ends.
-
Use case: Marking assignment as done
MSS
-
User requests to list out all assignments with upcoming deadlines.
-
Naggy Joel displays a list of all assignments with upcoming deadlines.
-
User chooses the assignment which has been completed.
-
Naggy Joel marks the indicated assignment as completed.
Use case ends.
Use case: Keeping track of birthdays
MSS
-
User requests to list out all upcoming birthdays.
-
Naggy Joel displays a list of birthdays within the next 5 days (including current day), with the name, date and remarks.
-
User views the remarks of the contact to decide on a suitable gift.
Use case ends.
Appendix D: Non Functional Requirements
-
The final product is a result of evolving/enhancing/morphing the given code base.
-
The final product targets users who can type fast and prefer typing over other means of input.
-
The final product should be for a single user.
-
The product is developed incrementally over the project duration.
-
The data should be stored locally and should be in a human editable text file.
-
The data cannot be stored in a DBMS
-
The software should follow the Object-Oriented paradigm primarily.
-
The software should work on any mainstream OS such as Windows, Linux, and OS-X platforms and should avoid having OS-dependent libraries and OS-specific features.
-
The software should work on a computer that has version 11 of Java installed.
-
The software should work without requiring an installer.
-
The software should not depend on a remote server.
-
The use of third-party frameworks is subject to approval by the module administrators
-
The file size of deliverables should not exceed 100MB for the JAR file and 15MB/file for the PDF files
-
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 able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage.
Appendix F: Instructions for Manual Testing
Given below are instructions to test the app manually.
These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing. |
F.1. Launch and Shutdown
-
Initial launch
-
Download the jar file and copy into an empty folder
-
Double-click the jar file
Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
-
-
Saving window preferences
-
Resize the window to an optimum size. Move the window to a different location. Close the window.
-
Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-
tag::manual[]
F.2. Adding a person
-
Test case:
(ab)add n/John p/12345 o/NUS n/05-20
Expected: A new contact with the name John, phone number 12345, and birthday 20 May is added to the list. Details of the added contact shown in the status message.
F.3. Deleting a person
-
Deleting a person while all persons are listed
-
Prerequisites: List all persons using the
(ab)list
command. Multiple persons in the list. -
Test case:
(ab)delete 1
Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. -
Test case:
(ab)delete 0
Expected: No person is deleted. Error details shown in the status message. -
Other incorrect delete commands to try:
(ab)delete
,(ab)delete x
(where x is larger than the list size)
Expected: Similar to previous.
-
-
Deleting a person while finding contacts that meet certain criteria
-
Prerequisites: List subset of contacts using the
(ab)find
command. Persons who meet the criteria are listed. -
Test case:
(ab)delete x
(where x is larger than the filtered list size but smaller than the size of the full contact list)
Expected: No person is deleted. Error details shown in the status message.
-
F.4. Editing a person
-
Editing a person while all persons listed
-
Prerequisites: List all persons using the
(ab)list
command. Multiple persons in the list. -
Test case:
(ab)edit 2 t/BFF -t/Friends
Expected: Second contact in the list is edited, with tag "Friends" deleted, and tag "BFF" added. Details of the edited contact shown in the status message.
-
-
Editing a person while finding contacts that meet certain criteria
-
Prerequisites: List subset of contacts using the
(ab)find
command. Persons who meet the criteria are listed. -
Test case:
(ab)edit x b/06-22
(where x is larger than the filtered list size but smaller than the size of the full contact list)
Expected: No person is edited. Error details shown in the status message.
-
F.5. Adding additional information to a person
-
Adds note(s) to a person while all persons listed
-
Prerequisites: List all persons using the
(ab)list
command. Multiple persons in the list. -
Test case:
(ab)addnote 2 i/Likes red i/Lives in Jurong i/Cycles
Expected: Second contact in the list has 3 new notes, "Likes red", "Lives in Jurong" and "Cycles", added. Details of the edited contact shown in the status message.
-
-
Add note(s) to a person while finding contacts that meet certain criteria
-
Prerequisites: List subset of contacts using the
(ab)find
command. Persons who meet the criteria are listed. -
Test case:
(ab)addnote x i/Can’t take spicy
(where x is larger than the filtered list size but smaller than the size of the full contact list)
Expected: No new note is added to a person. Error details shown in the status message.
-
F.6. Editing additional information for a person
-
Editing an existing note of person while all persons listed
-
Prerequisites: List all persons using the
(ab)list
command. Multiple persons in the list. -
Test case:
(ab)editnote 2 l/2 i/Likes matcha
Expected: Edits the second note of the second contact in the list to "Likes matcha". Details of the edited contact shown in the status message. -
Test case:
(ab)editnote x i/Likes red
(where x is larger than the number of existing notes of a person)
Expected: No note is edited for the person. Error details shown in the status message. -
Other incorrect commands to try:
(ab)editnote 2 l/aaa i/Likes cats
(where line number is not an integer)
Expected: Similar to previous
-
-
Editing an existing note of a person while finding contacts that meet certain criteria
-
Prerequisites: List subset of contacts using the
(ab)find
command. Persons who meet the criteria are listed. -
Test case:
(ab)editnote x l/3 i/Can’t take spicy
(where x is larger than the filtered list size but smaller than the size of the full contact list)
Expected: No note is edited for a person. Error details shown in the status message.
-
F.7. Deleting additional information of a person
-
Delete note(s) of a person while all persons listed
-
Prerequisites: List all persons using the
(ab)list
command. Multiple persons in the list. -
Test case:
(ab)deletenote 2 l/1 l/3
Expected: Deletes the first and third note of the second contact in the list. Details of the edited contact shown in the status message. -
Test case:
(ab)deletenote 2 l/x
(where x is larger than the number of existing notes of a person)
Expected: No note is deleted for the person. Error details shown in the status message. -
Other incorrect commands to try:
(ab)deletenote 2 l/2 l/aaa
(where line number is not an integer)
Expected: Similar to previous
-
-
Editing a person while finding contacts that meet certain criteria
-
Prerequisites: List subset of contacts using the
(ab)find
command. Persons who meet the criteria are listed. -
Test case:
(ab)deletenote x l/2
(where x is larger than the filtered list size but smaller than the size of the full contact list)
Expected: No note is deleted for a person. Error details shown in the status message.
-
F.8. Finding a specific contact/specific set of contacts
-
Finding person(s) by organization, name or tag.
-
Test case:
(ab)find o/NUS n/Lim
Expected: If person(s) with the organization "NUS" and have the word "Lim" in the name, person(s) will be listed. The number of person listed shown in the status message.
-
F.9. Retrieving a specific contact and view in full details
-
Retrieves a person contact while all persons listed
-
Prerequisites: List all persons using the
(ab)list
command. Multiple persons in the list. -
Test case:
(ab)get 2
Expected: Display the second person in the full contact list. The number of person listed shown in the status message. -
Test case:
(ab)get x
(where x is larger than the number of contacts in the list)
Expected: No detailed view of contact is displayed. Error details shown in the status message.
-
-
Retrieves a person contact while finding contacts that meet certain criteria
-
Prerequisites: List subset of contacts using the
(ab)find
command. Persons who meet the criteria are listed. -
Test case:
(ab)get x
(where x is larger than the filtered list size but smaller than the size of the full contact list)
Expected: No detailed view of contact is displayed. Error details shown in the status message.
-
F.10. List contacts with upcoming birthdays
-
All persons are listed
-
(ab)birthday
Expected: All contacts with birthdays in the next 5 days (current day included) should be listed.
-
F.11. Adding a restaurant
-
Test case:
(rt)add n/Ameens l/Clementi v/No o/0900:2300 p/$ c/Indian
Expected: Adds a new restaurant called Ameens at Clementi with 1 dollar sign price point, opens from 9am to 11pm, with cuisine Indian and has yet to be visited.
F.12. List all restaurants saved
-
(rt)list
Expected: All restaurants added should be displayed.
F.13. Editing a restaurant
-
Editing a restaurant while all restaurants are listed
-
Prerequisites: List all restaurants using the
(rt)list
command. Multiple restaurants in the list. -
Test case:
(rt)edit 1 v/Yes o/0900:2200
Expected: Edits the first restaurant visited status to "Yes" and operating hours to "0900:2200".
-
-
Editing a restaurant while finding restaurants that meet certain criteria
-
Prerequisites: List subset of restaurants using the
(rt)find
command. Restaurants that meet the criteria are listed. -
Test case:
(rt)edit x
(where x is larger than the filtered list size but smaller than the size of the full restaurant list)
Expected: No restaurant edited. Error details shown in the status message.
-
F.14. Deleting a restaurant
-
Deletes a restaurant while all restaurants are listed
-
Prerequisites: List all restaurants using the
(rt)list
command. Multiple restaurants in the list. -
Test case:
(rt)delete 2
Expected: Deletes the second restaurant in the restaurant list. Details of the deleted restaurant shown in the status message. -
Test case:
(rt)delete x
(where x is larger than the size of the restaurant list)
Expected: No restaurant is deleted. Error details shown in the status message.
-
-
Deleting a restaurant while finding restaurants that meet certain criteria
-
Prerequisites: List subset of restaurants using the
(rt)find
command. Restaurants that meet the criteria are listed. -
Test case:
(rt)delete x
(where x is larger than the filtered list size but smaller than the size of the full restaurant list)
Expected: No restaurant deleted. Error details shown in the status message.
-
F.15. Adding food note(s) to a restaurant
-
Add food note(s) to a restaurant while all restaurants are listed
-
Prerequisites: List all restaurants using the
(rt)list
command. Multiple restaurants in the list. -
Test case:
(rt)addnote 1 r/Chicken Chop g/Truffle Fries b/Risotto b/Lobster Pasta
Expected: Add notes to the restaurant at index 1 with recommended food Chicken Chop, good food Truffle Fries, and bad food Risotto and Lobster Pasta. Details of the edited restaurant shown in the status message.
-
F.16. Editing food note(s) of a restaurant
-
Edit food note(s) to a restaurant while all restaurants are listed
-
Prerequisites: List all restaurants using the
(rt)list
command. Multiple restaurants in the list. -
Test case:
(rt)editnote 1 rl/1 r/Fish and Chip gl/1 g/Mushroom soup bl/2 b/Salad
Expected: Edit notes to the restaurant at index 3 with recommend food Fish and Chip at line number 1, good food Mushroom soup at line number 1, and bad food Salad at line number 2. Details of the edited restaurant shown in the status message. -
Test case:
(rt)editnote 2 rl/aaa r/Fried Rice gl/1 g/Tomato soup
(Non-integer line number for recommended food notes)
Expected: No restaurant’s food notes is edited. Error details shown in the status message.
-
F.17. Deleting food note(s) of a restaurant
-
Delete food note(s) to a restaurant while all restaurants are listed
-
Prerequisites: List all restaurants using the
(rt)list
command. Multiple restaurants in the list. -
Test case:
(rt)deletenote 1 rl/1 gl/1 bl/2
Expected: Delete notes to the restaurant at index 1, at line number 1 of recommended food notes, at line number 1 of good food notes, at line number 2 of bad food notes. -
Test case
(rt)deletenote 1 rl/1 gl/x bl/aaa
(where x is larger than the size of good food notes, and non-integer line number for bad food notes)
Expected: No restaurant’s bad notes is edited. Error details shown in the status message.
-
F.18. Search for restaurants based on a number of criteria
-
(rt)find l/Clementi
Expected: Searches and display restaurants in the Clementi area. Number of restaurants displayed shown in the status message.
F.19. Adding an assignment
-
Test case:
(st)add t/CS2103 post lecture quiz d/2020-11-11 23:59 e/2
Expected: Adds an assignment titled CS2103 post lecture quiz to the Schoolwork Tracker, due 11 Nov 2020 23:59 PM and which takes an estimated two hours to complete. Details of the added assignment shown in the status message. -
Test case:
(st)add t/CS2105 lab d/DEADLINE e/5
(whereDEADLINE
is before the current date and time)
Expected: No assignment is added. Error details shown in the status message.
F.20. List current assignments
-
Test case:
(st)list -d
Expected: Assignments will be shown in chronological order, with respect to the deadline, with all completed assignments at the bottom of the list. -
Test case:
(st)list -e
Expected: Assignments will be shown according to the estimated completed time in descending order with all completed assignments at the bottom of the list. -
Test case:
(st)list -d -e
Expected: Assignments will not be sorted. Error details shown in the status message.
F.21. Deleting an assignment
-
Deletes an assignment while all assignments are listed
-
Prerequisites: List all assignments using the
(st)list
command. Multiple assignments in the list. -
Test case:
(st)delete 1
Expected: Deletes the first assignment in the Schoolwork Tracker. Details of the deleted assignment shown in the status message. -
Test case:
(st)delete x
(where x is larger than the size of Schoolwork Tracker)
Expected: No assignment is deleted. Error details shown in the status message.
-
F.22. Editing an assignment
-
Edits an assignment while all assignments are listed
-
Prerequisites: List all assignments using the
(st)list
command. Multiple assignments in the list. -
Test case:
(st)edit 1 t/CS2103 Quiz e/1
Expected: Changes the title of the first assignment to 'CS2103 Quiz' and estimated completion time to 1 hour. Details of the edited assignment shown in the status message. -
Test case:
(st)edit 1 s/Completed
Expected: Marks the first assignment in the Schoolwork Tracker as completed. Details of the edited assignment shown in the status message. -
Test case:
(st)edit 1 s/Uncompleted
Expected: Marks the first assignment in the Schoolwork Tracker as uncompleted. Details of the edited assignment shown in the status message. -
Test case:
(st)edit d/DEADLINE
(whereDEADLINE
is before the current date and time)
Expected: No assignment is edited. Error details shown in the status message. -
Other incorrect commands to try:
(st)edit x
(where x is larger than the size of Schoolwork Tracker)
Expected: Same as above
-
F.23. Generating schedule
-
Generates the user’s schedule
-
Prerequisites: There are assignments added to the SchoolworkTracker
-
Test case:
(st)schedule n/5
Expected: The user’s schedule for the next 5 days is displayed. For the query date, the total allocated hours should not exceed the amount of time remaining on query date. For each assignment, the amount of time allocated to the day it is due should not exceed the amount of time the user has on that day before the time of submission. For each assignment, the total amount of time scheduled and unscheduled should equals the estimated workload of that assignment. -
Test case:
(st)schedule n/-1
Expected: No schedule is displayed. Error details shown in the status message.
-
F.24. Adding a social event
-
Test case:
(ev)add t/Facebook job interview d/2020-05-18 10:00 h/3 p/Facebook APAC HQ
Expected: Adds a new social event with title "Facebook job interview", event date 2020-05-18, duration of 3 hours and location at "Facebook APAC HQ". -
Test case:
(ev)add t/Birthday party d/DATETIME h/3 p/Clementi
(where DATETIME is after the current date and time)
Expected: No social event is added. Error details shown in the status message.
F.25. Listing all events
-
(ev)list
Expected: List all added social events in the Event Schedule.
F.26. Editing a social event
-
Edits a social event while all social events are listed
-
Prerequisites: List all social events using the
(ev)list
command. Multiple social events in the list. -
Test case:
(ev)edit 1 d/2020-04-09 11:00 h/2
Expected: Edits the first event in the Event Schedule by changing the timing to 11AM on the 9th of April and the estimated duration to be 2 hours. -
Test case:
(ev)edit d/DATETIME
(where DATETIME is after the current date and time)
Expected: No social event is edited. Error details shown in the status message.
-
F.27. Deleting a social event
-
Deletes a social event while all social events are listed
-
Prerequisites: List all social events using the
(ev)list
command. Multiple social events in the list. -
Test case:
(ev)delete 1
Expected: Deletes the first social event in the Event Schedule. -
Test case:
(ev)delete x
(where x is larger than the size of Event Schedule)
Expected: No social event is deleted. Error details shown in the status message.
-
end::manual[]