By: Team W15-B3
Since: February 2018
Licence: MIT
- 1. Introduction
- 2. Setting up
- 3. Design
- 4. Implementation
- 4.1. Undo/Redo feature
- 4.2. Module database feature
- 4.3. Calendar feature
- 4.4. Timetable feature
- 4.5. Showing the timetable
- 4.6. Schedule meetings feature
- 4.7. List Tag Members feature
- 4.8. Add Group feature
- 4.9. Add Member To Group feature
- 4.10. Delete Member From Group feature
- 4.11. List Group Members Feature
- 4.12. Delete Group feature
- 4.13. Tag Color feature
- 4.14. Add ToDo feature
- 4.15. Check/UnCheck ToDo feature
- 4.16. Edit ToDo feature
- 4.17. Delete ToDo feature
- 4.18. Logging
- 4.19. Configuration
- 5. Documentation
- 6. Testing
- 7. Dev Ops
- Appendix A: Product Scope
- Appendix B: User Stories
- Appendix C: Use Cases
- Appendix D: Non Functional Requirements
- Appendix E: Glossary
- Appendix F: Product Survey
- Appendix G: Instructions for Manual Testing
- G.1. Launch and Shutdown
- G.2. Deleting a person
- G.3. Adding a person
- G.4. Adding a to-do
- G.5. Deleting a to-do
- G.6. Checking a to-do
- G.7. Unchecking a to-do
- G.8. Editing a to-do
- G.9. Adding a group
- G.10. Adding a member to group
- G.11. Deleting a member from group
- G.12. Listing group members from a group
- G.13. Deleting a group
- G.14. Adding an event
- G.15. Listing persons with specified tags
- G.16. Changing a tag’s color
- G.17. Saving data
Fastis is a desktop application which functions as an address book that aims to help students who are studying at National University of Singapore (NUS) manage their group projects effectively. The application enables students to keep track of group members’ timetables, information, meetups agendas, to-dos, and schedule suitable meetup time.
This Developer Guide is meant to provides the necessary information for developers who are interested in contributing to this application. New developers should begin with Section 2, “Setting up”. Experienced developers might want begin instead with the Section 3, “Design” section to learn more about how Fastis is structured.
Understanding the implementation of the features in Fastis will be crucial to be able to modify any feature for further improvements.
This section provides information on setting up the project in order to work on Fastis.
The following programs have to be installed on the computer system before setting up.
-
JDK
1.8.0_60
or laterℹ️Having any Java 8 version is not enough.
This app will not work with earlier versions of Java 8. -
IntelliJ IDE
ℹ️IntelliJ by default has Gradle and JavaFx plugins installed.
Do not disable them. If you have disabled them, go toFile
>Settings
>Plugins
to re-enable them.
-
Fork this repo, and clone the fork to your computer
-
Open IntelliJ (if you are not in the welcome screen, click
File
>Close Project
to close the existing project dialog first) -
Set up the correct JDK version for Gradle
-
Click
Configure
>Project Defaults
>Project Structure
-
Click
New…
and find the directory of the JDK
-
-
Click
Import Project
-
Locate the
build.gradle
file and select it. ClickOK
-
Click
Open as Project
-
Click
OK
to accept the default settings -
Open a console and run the command
gradlew processResources
(Mac/Linux:./gradlew processResources
). It should finish with theBUILD SUCCESSFUL
message.
This will generate all resources required by the application and tests.
The following steps should be done to verify that the setup of Fastis is correct:
-
Run the
seedu.address.MainApp
and try a few commands -
Run the tests to ensure they all pass.
The following configurations should be done to ensure that Fastis future development follows good coding standards and practices.
This project follows oss-generic coding standards. IntelliJ’s default style is mostly compliant with ours but it uses a different import order from ours. To rectify,
-
Go to
File
>Settings…
(Windows/Linux), orIntelliJ IDEA
>Preferences…
(macOS) -
Select
Editor
>Code Style
>Java
-
Click on the
Imports
tab to set the order-
For
Class count to use import with '*'
andNames count to use static import with '*'
: Set to999
to prevent IntelliJ from contracting the import statements -
For
Import Layout
: Ensure that the import order isimport static all other imports
,import java.*
,import javax.*
,import org.*
,import com.*
,import all other imports
. Add a<blank line>
between eachimport
-
Optionally, you can follow the UsingCheckstyle.adoc document to configure Intellij to check style-compliance as you write code.
After forking the repo, links in the documentation will still point to the CS2103JAN2018-W15-B3/main
repo. If you plan to develop this as a separate product (i.e. instead of contributing to the CS2103JAN2018-W15-B3/main
) , you should replace the URL in the variable repoURL
in DeveloperGuide.adoc
and UserGuide.adoc
with the URL of your fork.
You should set up Travis to perform Continuous Integration (CI) for your fork. See UsingTravis.adoc to learn how to set it up.
After setting up Travis, you can optionally set up coverage reporting for your team fork (see UsingCoveralls.adoc).
ℹ️
|
Coverage reporting could be useful for a team repository that hosts the final version but it is not that useful for your personal fork. |
Optionally, you can set up AppVeyor as a second CI (see UsingAppVeyor.adoc).
ℹ️
|
Having both Travis and AppVeyor ensures your App works on both Unix-based platforms and Windows-based platforms (Travis is Unix-based and AppVeyor is Windows-based) |
When you are ready to start coding, get some sense of the overall design by reading Section 3.1, “Architecture”.
This section describes how Fastis is built and how its different components interact and work with each other.
The Architecture Diagram given below (Figure 1, “Architecture Diagram.”) explains the high-level design of Fastis. Given below is a quick overview of each component.
💡
|
The .pptx files used to create diagrams in this document can be found in the diagrams folder. To update a diagram, modify the diagram in the pptx file, select the objects of the diagram, and choose Save as picture .
|
The Main
component has only one class called MainApp
. It is responsible for:
-
Initializing the components in the correct sequence, and connects them up with each other during application launch.
-
Shutting down the components and invokes cleanup method where necessary during shut down.
The Commons
component represents a collection of classes used by multiple other components. Two of those classes play important roles at the architecture level.
-
EventsCenter
: This class (written using Google’s Event Bus library) is used by components to communicate with other components using events (i.e. a form of Event Driven design) -
LogsCenter
: This class is used by many classes to write log messages to the App’s log file.
The Database
component handles the downloading of module information via the NUSmods API, as well as holding and retrieving the information. Because it is only accessed and never changed, the database component resides on its own outside of the Model
component.
The rest of the App consists of these components:
UI
: The UI of the App.
Logic
: The command executor.
Model
: The holder of the data of the App in-memory.
Storage
: The location on the hard disk where date is read from and written to.
Each of the above 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 Figure 2, “Class Diagram of the Logic Component.”) defines it’s API in the Logic.java
interface and exposes its functionality using the LogicManager.java
class.
Figure 3, “Component interactions for delete 1
command (part 1).” shows how the components interact for the scenario where the user issues the command delete 1
.
ℹ️
|
Note how the Model simply raises a AddressBookChangedEvent when the Address Book data are changed, instead of asking the Storage to save the updates to the hard disk.
|
Figure 4, “Component interactions for delete 1
command (part 2).” shows how the EventsCenter
reacts to that event, which eventually results in the updates being saved to the hard disk and the status bar of the UI being updated to reflect the 'Last Updated' time.
ℹ️
|
Note how the event is propagated through the EventsCenter to the Storage and UI without Model having to be coupled to either of them. This is an example of how this Event Driven approach helps us reduce direct coupling between components.
|
The sections below give more details of each component.
The UI component handles the inputs from and the outputs to the User Interface. It consists of a MainWindow that is made up of parts e.g. CommandBox
, ResultDisplay
, PersonListPanel
, StatusBarFooter
, BrowserPanel
etc. All these, including the MainWindow
, inherit from the abstract UiPart
class. Refer to Figure 5, “Structure of the UI Component.”.
API : Ui.java
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. -
Binds itself to some data in the
Model
so that the UI can auto-update when data in theModel
change. -
Responds to events raised from various parts of the App and updates the UI accordingly.
The Logic component handles the commands from user and passes the command results to the User Interface.
Refer to Figure 6 and Figure 7 for class diagrams on how the Logic
component is structured.
XYZCommand
and Command
in Figure 6, “Structure of the Logic Component.”.API :
Logic.java
Given below is the workflow of the Logic Component when the user inputs a command:
-
The
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) and/or raise events. -
The result of the command execution is encapsulated as a
CommandResult
object which is passed back to theUi
.
Figure 8 shows the Sequence Diagram for interactions within the Logic
component for the execute("delete 1")
API call.
The model component stores and operates on the data held by Fastis as shown in Figure9.
API : Model.java
The Model
component:
-
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.
The model component does not depend on any of the other three components, meaning that it does not rely on any functions outside of itself to operate.
The storage component saves processed data from Fastis on to the running machine’s hard-disk and reads from the stored data as shown in Figure 10.
API : Storage.java
The Storage
component:
-
saves
UserPref
objects in json format and reading it back on next startup. -
saves the Address Book data in xml format and read it back on next startup.
The Database component is in charge of connections to the web.
The Database
component:
-
downloads module information from the
NUSmods API
. -
retrieves modules given a NUSmods timetable link.
ℹ️
|
NUSmods timetable links are the sharable short URL from a NUSmods page. E.g. http://modsn.us/MYwiD |
The sturucture of the Database component is shown in Figure 11
This section describes some noteworthy details on how certain features are implemented.
The Undo feature allows users to restore the state before the latest command while the Redo feature reverses the Undo command.
The undo/redo mechanism is facilitated by an UndoRedoStack
, which resides inside LogicManager
. It supports undoing and redoing of commands that modifies the state of the address book (e.g. add
, edit
). Such commands will inherit from UndoableCommand
.
UndoRedoStack
only deals with UndoableCommands
. Commands that cannot be undone will inherit from Command
instead. Figure 12 shows the inheritance of commands:
As you can see from Figure 12, UndoableCommand
adds an extra layer between the abstract Command
class and concrete commands that can be undone, such as the DeleteCommand
. Note that extra tasks need to be done when executing a command in an undoable way, such as saving the state of the address book before execution. UndoableCommand
contains the high-level algorithm for those extra tasks while the child classes implements the details of how to execute the specific command. Note that this technique of putting the high-level algorithm in the parent class and lower-level steps of the algorithm in child classes is also known as the template pattern.
Commands that are not undoable are implemented this way:
public class ListCommand extends Command {
@Override
public CommandResult execute() {
// ... list logic ...
}
}
With the extra layer, the commands that are undoable are implemented this way:
public abstract class UndoableCommand extends Command {
@Override
public CommandResult execute() {
// ... undo logic ...
executeUndoableCommand();
}
}
public class DeleteCommand extends UndoableCommand {
@Override
public CommandResult executeUndoableCommand() {
// ... delete logic ...
}
}
Suppose that the user has just launched the application. The UndoRedoStack
will be empty at the beginning.
The user executes a new UndoableCommand
, delete 5
, to delete the 5th person in the address book. The current state of the address book is saved before the delete 5
command executes. The delete 5
command will then be pushed onto the undoStack
(the current state is saved together with the command). Refer to Figure 13 for an illustration.
As the user continues to use the program, more commands are added into the undoStack
(Figure 14). For example, the user may execute add n/David …
to add a new person.
ℹ️
|
If a command fails its execution, it will not be pushed to the UndoRedoStack at all.
|
The user now decides that adding the person was a mistake, and decides to undo that action using undo
.
We will pop the most recent command out of the undoStack
and push it back to the redoStack
. We will restore the address book to the state before the add
command executed (Figure 15).
ℹ️
|
If the undoStack is empty, then there are no other commands left to be undone, and an Exception will be thrown when popping the undoStack .
|
Figure 16, “Sequence diagram for Undo/Redo.” shows how the undo operation works:
The redo does the exact opposite (pops from redoStack
, pushes to undoStack
, and restores the address book to the state after the command is executed).
ℹ️
|
If the redoStack is empty, then there are no other commands left to be redone, and an Exception will be thrown when popping the redoStack .
|
The user now decides to execute a new command, clear
. As before, clear
will be pushed into the undoStack
(Figure 17). This time the redoStack
is no longer empty. It will be purged as it no longer make sense to redo the add n/David
command (this is the behavior that most modern desktop applications follow).
Commands that are not undoable are not added into the undoStack
. For example, list
, which inherits from Command
rather than UndoableCommand
, will not be added after execution (as shown in Figure 18):
Figure 19, “Activity diagram of undo/redo.” summarize what happens inside the UndoRedoStack
when a user executes a new command:
The following considerations were taken into account during the design of this feature.
-
Alternative 1 (current choice): Add a new abstract method
executeUndoableCommand()
-
Pros: This implementation preserves undo/redo functionality as it is now part of the default behaviour. Classes that deal with
Command
do not have to know thatexecuteUndoableCommand()
exist. -
Cons: This implementation makes it hard for new developers to understand the template pattern.
-
-
Alternative 2: Just override
execute()
-
Pros: This implementation does not involve the template pattern, and is easier for new developers to understand.
-
Cons: This implementation makes it so that classes that inherit from
UndoableCommand
must remember to callsuper.execute()
, or lose the ability to undo/redo.
-
-
Alternative 1 (current choice): Saves the entire address book.
-
Pros: This implementation is easy to implement.
-
Cons: This implementation may have performance issues in terms of memory usage.
-
-
Alternative 2: Individual command knows how to undo/redo by itself.
-
Pros: This implementation uses less memory (e.g. for
delete
, just save the person being deleted). -
Cons: This implementation reduces leeway for error and forces developers to ensure that the implementation of each individual command are correct.
-
-
Alternative 1 (current choice): Only include commands that modifies the
AddressBook
.-
Pros: This implementation only reverts changes that are hard to change back (the view can easily be re-modified as no data are * lost).
-
Cons: This implementation might confuse users as to whether the command also works when the list is modified (undoing filtering for example).
-
-
Alternative 2: Include all commands.
-
Pros: This implementation might be more intuitive for the user.
-
Cons: This implementation makes it harder for users who only want to revert changes to
AddressBook
. Additional Info: See our discussion here.
-
-
Alternative 1 (current choice): Use separate stack for undo and redo
-
Pros: This implementation is easy to understand for new Computer Science undergraduates to understand, who are likely new developers.
-
Cons: This implementation duplicates
Logic
. For example, when a new command is executed, bothHistoryManager
and `UndoRedoStack`must be update.
-
-
Alternative 2: Use
HistoryManager
for undo/redo-
Pros: This implementation just reuses what is already in the codebase.
-
Cons: This implementation violates Single Responsibility Principle and Separation of Concerns as
HistoryManager
now needs to undo commands on top of keeping track of them.
-
The database feature enables Fastis to store and quickly find lesson schedules.
Fastis uses the available NUSmods API
to retrieve module information from the API server.
The sequence diagram (Figure 20) for the instantiation of DatabaseManager is shown below.
On startup, the network component makes a connection to the API server and checks the lastmodified
field of the JSON
file on the server. If the lastmodified
date is more recent that the JSON
file held in storage, the network component will download and overwrite the existing file on disk.
The Storage
component then converts the JSON file into a hashMap of modules to be held in the Database
component.
-
Alternative 1 (current choice): Store a complete dataset of all modules
-
Pros: This implementation allows Fastis to access information even when used offline.
-
Cons: This implementation requires more memory space.
-
-
Alternative 2: Store nothing, retrieve only module information of single module each time.
-
Pros: This implementation does not require any storage space.
-
Cons: This implementation requires Fastis to constantly download information from the web, making the app reliant on good internet connection.
-
Fastis uses a stand-alone Calendar
class, adapted from javafx-calendar by SirGoose3432.
It is used to view the user’s upcoming events, e.g. interviews, meetings, etc.
The calendar feature is facilitated by Calendar
and CalendarDate
classes,
both of which reside inside Ui
component. Their sole purpose is to draw out the calendar
in the application when given a list of Event
objects.
The calendar is drawn/redrawn whenever a CalendarChangedEvent
is raised.
The flow of operation thereafter is shown is Figure 21 below.
Calendar
utilizes the Event
class to determine which slots in the schedule are occupied.
Hence, a list of events is passed to every calendar upon construction and saved as a private variable.
The details of these event, e.g. time, location, are saved locally in .xml
file format.
It is also retrieved upon start up by the Storage
component and saved within the Model
for the whole process.
The implementation of Calendar
is as follows:
public Calendar(ObservableList<Event> eventList) {
super(FXML);
// ... Assigning class fields ...
initCalendar();
registerAsAnEventHandler(this);
}
private void initCalendar() {
// ... Create the calendar 7x6 GridPane ...
// ... Construct 42 CalendarDate objects ...
fillCalendar(currentYearMonth);
showEvents();
// ... show CalendarView ...
}
private void fillCalendar(YearMonth yearMonth) {
// ... Fill the calendar with the correct dates according to yearMonth ...
}
private void showEvents() {
// ... Show all events that are in the current yearMonth in the eventList ...
}
The current time is retrieved upon startup, and the calendar base on that point in time to display the appropriate time frame.
-
Alternative 1 (current choice): Implement a stand-alone
Calendar
class-
Pros: This implementation makes data manipulation and appearance customizing easy.
-
Cons: This implementation might lack functionalities available in external libraries.
-
-
Alternative 2: Import external libraries/API
-
Choices:
-
Pros: This implementation would be likely be optimized and have more functionalities.
-
Cons: This implementation restricts developers to what the libraries offer, and require a firm understanding of these external APIs.
-
-
Alternative 1 (current choice): Stores the
eventList
within theCalendar
object.-
Pros: This implementation makes it easy to show events and their details, even after the constructor returns.
-
Cons: This implementation takes up some memory even if there are no commands for showing these events.
-
-
Alternative 2: Only passes the
eventList
as a parameter to the constructor and not storing it as a field within theCalendar
object.-
Pros: This implementation uses less memory and makes code less cluttered.
-
Cons: This implementation makes it hard to show events and their details outside of the constructor.
-
Fastis uses a stand-alone Timetable
class, based largely on the Calendar
class. It is used to view the user’s own NUSMods timetable as well as that of other people in his address book.
The timetable is the weekly equivalent to the monthly Calendar.
This feature is similarly facilitated by the analogous Timetable
and TimetableSlot
classes,
both of which reside inside Ui
component. Their sole purpose is to draw out the timetable
in the application when given a list of WeeklyEvent
objects.
The calendar is drawn/redrawn whenever a TimetableChangedEvent
is raised.
This is done either by a precedent PersonPanelSelectionChangedEvent
or a ScheduleGroupCommand
.
The flow of operation thereafter is shown Figure 22 below.
The implementation of Timetable
is as follows:
public Timetable(ObservableList<WeeklyEvent> eventList) {
super(FXML);
// ... Assigning class fields ...
initTimetable();
registerAsAnEventHandler(this);
}
private void initTimetable() {
// ... Create the calendar 6x11 GridPane ...
// ... Construct 66 TimetableSlot objects ...
clearTimetable();
showSlots();
// ... show TimetableView ...
}
private void clearTimetable() {
// ... Draw all slots as blank ...
// ... Draw the timeline on the left ...
}
private void showSlots() {
// ... Show all slots that are in the in the eventList ...
// ... Make sure no 2 modules with different name would have the same color ...
}
As the weekly equivalent of Calendar
, Timetable
has the same aspect to consider. See Implementation of the Calendar.
-
Alternative 1 (current choice): Don’t support showing those modules
-
Pros: This implementation makes the GUI less cluttered and more readable
-
Cons: This implementation cannot cater to users with modules outside these times. Users cannot schedule events on weekends.
-
-
Alternative 2: Support showing those modules
-
Pros: This implementation caters to users with those modules, and support scheduling for the weekends.
-
Cons: This implementation makes the GUI look cluttered, as the GUI already has other main components.
-
This feature allows users to see a person’s timetable by selecting him/her.
When a person is selected, either by the select
command or by mouse click via the GUI, a PersonPanelSelectionChangedEvent
is raised. The flow of operation thereafter is shown Figure 23 below.
Upon receiving the event, the UI
component takes the Person
within the PersonPanelSelectionChangedEvent
and calls the parseEvents()
method of DataBaseManager
, passing the TimetableLink
of the Person
as an argument.
The result of the parseEvents()
is an ArrayList
of WeeklyEvents
. This result is used to form a TimeTableChangedEvent
, which ultimately tells the UI
component to display the result.
The implementation of parseEvents()
is as follows:
public static ArrayList<WeeklyEvent> parseEvents(TimeTableLink link) {
ArrayList<WeeklyEvent> eventList = new ArrayList<>();
if (!isCurrentSem(link)) {
// ... display and log warning messages ...
}
String query = getQuery(link);
// ... parse query into WeeklyEvents ...
return eventList;
}
The parseEvents()
method firsts checks if the TimetableLink
points to a schedule that is in the same semester as Fatis' database. It then calls the getQuery
helper method, which a URLconnection
to the shortened URL in TimetableLink
and returns the query
part of the full-length URL.
The method then takes the query
and parses them into modules and lessons, which are used to form WeeklyEvents
.
-
Alternative 1 (current choice): Store only the link to a NUSmods page for each person
-
Pros: This implementation requires very little space. The schedule of a person can easily be changed by editing the
TimetableLink
. -
Cons: This implementation requires Fastis to make a connection to the web each time a person is selected.
-
-
Alternative 2: Store the schedule of each person in the
AddressBook
-
Pros: This implementation will require much more space, and there will be a dilemma between whether to store it as
WeeklyEvent
, orModule
andschedule
-
Cons: This implementation requires Fastis to make a connection to the web only when a person is added or edited.
-
Fastis supports showing all the common free time slots for all members in based on their timetable.
Fastis utilizes a few components to schedule the meetings, namely the Group
class and WeeklyEvent
class in Model
, Timetable
in UI
, and parseEvents()
in Database
.
The command to show the scheduled meetings is ScheduleGroupCommand
, which resides in Logic
component.
When a ScheduleGroupCommand
is executed, it first gets all group members from Model
.
For each member, it parses the TimetableLink
to get all of his/her modules, and add them to an occupied
list.
From that list, the command generates all free time slots in another list called free
, and post that event to be handled by the UI
component later.
The flow of operation is shown in Figure 24 below.
The implementation of ScheduleGroupCommand
is as follows:
public ScheduleGroupCommand(Group group) {
requireNonNull(group);
// ... Assigning class fields ...
EventsCenter.getInstance().registerHandler(this);
}
public CommandResult execute() throws CommandException {
// ... Get the group's member from Model ...
fillTimeSlots(group);
generateFreeTimeSlots();
// ... Post new TimetableChangedEvent ...
// ... Return new CommandResult ...
}
private void fillTimeSlots(Group group) {
for (Person member : group.getPersonList()) {
// ... Parse the TimetableLink into moduleList
// ... Add all modules in moduleList to occupied list
}
}
private void generateFreeTimeSlots() {
// ... Generate free time slots logic
}
-
Alternative 1 (current choice): Show all free time slots
-
Pros: This implementation is intuitive for users, and easy to read.
-
Cons: This implementation slow, as there are a few extra steps to process.
-
-
Alternative 2: Show all occupied time slots
-
Pros: This implementation is very fast.
-
Cons: This implementation could make GUI cluttered as there are normally more occupied slots than free slots. Also, it might not be intuitive for users.
-
Fastis lists all persons in Fastis that have tags similar to input.
Fastis uses ListTagMembersCommand
, which resides under Logic
to facilitate the listing of members under the same
tag. Figure 25 shows the sequence diagram of the listTagMembers
command
When user types in command line listTagMembers
or lTM
, Fastis will use the keyword provided to search for the
tag and list out all members with the same tag.
-
Alternative 1 (current choice): Add a new command
listTagMembersCommand()
to list out the members with same tag.-
Pros: This implementation makes it is easy to change the methods called by command.
-
Cons: This implementation requires users and developers to remember more commands.
-
-
Alternative 2: Change existing find command to include finding person with same tags.
-
Pros: This implementation can reduce number of commands required to be remembered.
-
Cons: This implementation can affect the functionality of existing commands.
-
Fastis has a group feature that can:
-
add a group with information that was stated by user input.
-
delete a group with information that was stated by user input.
-
add a person into the group with information that was stated by user input.
-
delete a person from the group with information that was stated by user input.
-
list all the members in the group with information that was stated by user input.
The group mechanism is facilitated by UniqueGroupList
, which resides inside Model
component. Address book stores all groups in UniqueGroupList
.
The groups in the group list are facilitated by Group
class. Each Group
object have a Information
object, representing the information of the group.
Group
,Information
and UniqueGroupList
class reside inside Model
component. Figure 26 is the class diagram showing the relationship between Group
, Information
and UniqueGroupList
:
Figure 27 is a object diagram of Group Class.
Suppose that the user has just launched the application . The UniqueGroupList
in the address book will include few groups that are declared in SampleDataUtil.
A Group consists of the following:
-
Information: Represents the information of the group.
-
PersonList: Represents the list of persons in a group.
The add group feature adds a group with information named by user in input into Fastis.
The add group mechanism is facilitated by AddGroupCommand
, which resides inside Logic
component. It supports adding Group
object to the address book. AddGroupCommand
inherits from UndoableCommand
.
Hence, AddGroupCommand
can be undone using UndoRedoStack
.
With the extra layer, the AddGroupCommand
that is undoable is implemented this way:
public abstract class UndoableCommand extends Command {
@Override
public CommandResult execute() {
// ... undo logic ...
executeUndoableCommand();
}
}
public class AddGroupCommand extends UndoableCommand {
@Override
public CommandResult executeUndoableCommand() {
// ... AddGroup logic ...
}
}
Figure 28 shows the interaction of AddGroup
Command class.
The user executes a new AddGroupCommand
with Information
, to add a new group to the address book.
The new group is added to the UniqueGroupList
and the current state of the address book is saved.
The AddGroupCommand
is facilitated by AddGroupCommandParser
to parse AddGroupCommand
.
Figure 29 shows the flow of parsing of AddGroupCommand
object.
Figure 30 diagram shows how the add group operation works:
-
Alternative 1 (current choice): Add a new command method
AddGroupCommand()
-
Pros: This implementation makes it easy for developers to modify method to suit what they want
-
Cons: This implementation requires users and developers to remember more commands.
-
-
Alternative 2: Add a new abstract method
executeAddGroupCommand()
-
Pros: This implementation preserves
addGroup
functionality as it is now part of the default behaviour. Classes that deal withAddGroupCommand
do not have to know thatexecuteAddGroupCommand()
exist. -
Cons: This implementation makes it hard for new developers to understand the template pattern.
-
Fastis adds a person from the existing contact list to an existing group.
The add member to group mechanism is facilitated by AddMemberToGroupCommand
, which resides inside Logic
component.
It supports adding a member to Group
objects to the address book. AddMemberToGroupCommand
inherits from UndoableCommand
.
Hence, AddMemberToGroupCommand can be undone using UndoRedoStack
.
With the extra layer, the AddGroupCommand that is undoable is implemented this way:
public abstract class UndoableCommand extends Command {
@Override
public CommandResult execute() {
// ... undo logic ...
executeUndoableCommand();
}
}
public class AddMemberToGroupCommand extends UndoableCommand {
@Override
public CommandResult executeUndoableCommand() {
// ... AddMemberToGroup logic ...
}
}
The list of members in the group list are facilitated by Group
class. Each Group
object have a UniquePersonList
object, representing the list of persons in the group.
Address book stores all members added to the group using XmlAdaptedPersons as person object storage as shown in the following sequence diagram where the storage saves to file in XmlAdaptedGroups.
Fastis will then handle addressBookChangedEvent
and update command result.
Figure 31 shows the interaction of AddMemberToGroup
Command class.
The AddMemberToGroupCommand
is facilitated by AddMemberToGroupCommandParser
to parse AddMemberToGroupCommand
.
Figure 32 shows the flow of parsing of AddMemberToGroupCommand
object.
Figure 33 diagram shows how the addMembersToGroup operates.
-
Alternative 1 (current choice): Add a new command method
AddMemberToGroupCommand()
.-
Pros: This implementation makes it easy for developers to modify method to suit what they want.
-
Cons: This implementation requires users and developers to remember more commands.
-
-
Alternative 2 : Add a new interface
EditGroupMemberCommand()
to handle adding members to group.-
Pros: This implementation does not require a new command to be created.
-
Cons: This implementation is less flexible.
-
Fastis deletes a person from the existing contact list to an existing group.
The delete member from groups mechanism is facilitated by DeleteMemberFromGroupCommand
, which resides inside Logic
component.
It supports deleting a member to Group objects to the address book. DeleteMemberFromGroupCommand
from UndoableCommand
.
Hence, DeleteMemberFromGroupCommand can be undone using UndoRedoStack
.
With the extra layer, the AddGroupCommand that is undoable is implemented this way:
public abstract class UndoableCommand extends Command {
@Override
public CommandResult execute() {
// ... undo logic ...
executeUndoableCommand();
}
}
public class DeleteMemberFromGroupCommand extends UndoableCommand {
@Override
public CommandResult executeUndoableCommand() {
// ... DeleteMemberFromGroup logic ...
}
}
The list of members in the group list are facilitated by Group
class. Each Group
object have a UniquePersonList
object, representing the list of persons in the group.
Address book stores all members added to the group using XmlAdaptedPersons as person object storage.
The DeleteMemberFromGroupCommand
will retrieve the input, which is the index of the person of the last updated person list, and deletes that person from the list if the person exists in the UniquePersonList
in the specified group.
Fastis will then handle addressBookChangedEvent
and update command result.
Figure 34 shows the interaction of DeleteMemberFromGroup
Command class.
The DeleteMemberFromGroupCommand
is facilitated by DeleteMemberFromGroupCommandParser
to parse DeleteMemberFromGroupCommand
.
Figure 35 shows the flow of parsing of DeleteMemberFromGroupCommand
object.
Figure 36 diagram shows how the deleteMembersFromGroup operates.
-
Alternative 1 (current choice): Add a new command method
DeleteMemberFromGroupCommand()
-
Pros: This implementation is easy for developers to modify method to suit what they want.
-
Cons: This implementation requires users and developers to remember more commands.
-
-
Alternative 2 : Add a new interface
EditGroupMemberCommand()
.-
Pros: This implementation does not require a new command to be created.
-
Cons: This implementation is less flexible.
-
Fastis lists all persons under the group keyed by user.
Fastis uses ListGroupMembersCommand
,which resides under Logic
to facilitate the listing of members under the same
group.
When user types in command line listGroupMembers
or lGM
, Fastis will use the keyword provided to search for the
group and list out all members under the specified group in the PersonListPanel
.
The ListGroupMembersCommand
is facilitated by ListGroupMembersCommandParser
to parse ListGroupMembersCommand
.
Figure 37 shows the flow of parsing of ListGroupMembersCommand
object.
Figure 38 diagram shows how ListGroupMembersCommand
operates.
-
Alternative 1 (current choice): Use a command to list out the members with same group.
-
Pros: This implementation makes the methods called by command easily modifiable.
-
Cons: This implementation requires users and developers to remember more commands.
-
-
Alternative 2: Add a new abstract method
ListGroupMembersCommand()
-
Pros: This implementation makes it easy to edit
ListGroupMembersCommand()
easily to suit our needs -
Cons: This implementation makes it hard for new developers to understand the template pattern.
-
Fastis deletes a group named by the user from input.
The delete groups mechanism is facilitated by DeleteGroupCommand
, which resides inside Logic
component. It supports deleting Group objects to the address book. DeleteGroupCommand inherits from UndoableCommand
.
Hence, DeleteGroupCommand can be undone using UndoRedoStack
.
With the extra layer, the DeleteGroupCommand that is undoable is implemented this way:
public abstract class UndoableCommand extends Command {
@Override
public CommandResult execute() {
// ... undo logic ...
executeUndoableCommand();
}
}
public class DeleteGroupCommand extends UndoableCommand {
@Override
public CommandResult executeUndoableCommand() {
// ... DeleteGroup logic ...
}
}
The user executes a new DeleteGroupCommand
with Information
, to delete a existing group with the same information to the address book.
The group is deleted from the UniqueGroupList
and the current state of the address book is saved.
Fastis will then handle addressBookChangedEvent
and update command result.
Figure 39 shows the interaction of DeleteGroup
Command class.
The DeleteGroupCommand
is facilitated by DeleteGroupCommandParser
to parse DeleteGroupCommand
.
Figure 40 shows the flow of parsing of DeleteGroupCommand
object.
Figure 41 shows how the deleteGroup operation works:
-
Alternative 1 (current choice): Add a new command method
deleteGroupCommand()
-
Pros: This implementation makes it easy for developers to modify method to suit what they want
-
Cons: This implementation requires users and developers to remember more commands.
-
-
Alternative 2: Add a new abstract method
executeDeleteGroupCommand()
-
Pros: This implementation preserves
deleteGroup
functionality as it is now part of the default behaviour. Classes that deal withDeleteGroupCommand
do not have to know thatexecuteDeleteGroupCommand()
exist. -
Cons: This implemetation makes it hard for new developers to understand the template pattern.
-
Fastis supports changing the color of the tags given to people in the address book. There are up to 17 colors to choose from.
Changing a tag’s color is facilitated by ChangeTagColorCommand
, which resides inside Logic
component.
It supports modifying the color
field within Tag
objects.
The flow of operation is shown the Figure 42 below.
ChangeTagColorCommand
inherit from UndoableCommand
, therefore it can be undone and redone using UndoRedoStack
.
The implementation of ScheduleGroupCommand
is as follows:
public abstract class UndoableCommand extends Command {
@Override
public CommandResult execute() {
// ... undo logic ...
executeUndoableCommand();
}
}
public class ChangeTagColorCommand extends UndoableCommand {
@Override
protected void preprocessUndoableCommand() throws CommandException {
// .. Get the tag's name and color from Model
}
@Override
public CommandResult executeUndoableCommand() {
// ... Update tag in Model ...
// ... Update Person list in Model ...
// ... Return new CommandResult ...
}
}
-
Alternative 1 (current choice): Allow different tags with the same color
-
Pros: This implementation allows users to have more freedom.
-
Cons: This implementation might result in aesthetically unpleasing GUI.
-
-
Alternative 2: Disallow different tags with the same color
-
Pros: This implementation is more intuitive.
-
Cons: This implementation makes the code longer.
-
Adds a to-do.
The add to-dos mechanism is facilitated by AddToDoCommand
, which resides inside Logic
component. It supports adding ToDo objects to the address book. AddToDoCommand inherits from UndoableCommand
.
Hence, AddToDoCommand can be undone using UndoRedoStack
.
With the extra layer, the AddToDoCommand that is undoable is implemented this way:
public abstract class UndoableCommand extends Command {
@Override
public CommandResult execute() {
// ... undo logic ...
executeUndoableCommand();
}
}
public class AddToDoCommand extends UndoableCommand {
@Override
public CommandResult executeUndoableCommand() {
// ... add to-do logic ...
}
}
The to-dos in the to-do list are facilitated by ToDo
class. Each ToDo
object have a Content
object and a Status
object, representing the content and status of the to-do.
Address book stores all to-dos in UniqueToDoList
.
ToDo
,Content
and UniqueToDoList
class reside inside AddressBook
. Figure 43 is the class diagram showing the relationship between ToDo
,Content
, Status
, UniqueToDoList
and AddressBook
:
On a smaller scale, Figure 44 is a class diagram showing the relationship between ToDo
,Content
and Status
:
Suppose that the user has just launched the application. The UniqueToDoList
in the address book will be empty if no to-dos have been added previously.
The user executes a new AddToDoCommand
with Content
, to add a new to-do to the address book.
The Status
of the to-do is "undone" by default.
The new to-do with content and status is added to the UniqueToDoList
and the current state of the address book is saved.
Figure 45 shows how the addToDo operation works:
-
Alternative 1 (current choice): Restrict the constructor of ToDo to be ToDo(Content content, Status status)`
-
Pros: This implementation allows ToDo class to be easier to maintain and debug.
-
Cons: This implementation requires extensive refactor of existing tests.
-
Checks or unchecks a To-do
The check/uncheck to-dos mechanism is facilitated by CheckToDoCommand
and UnCheckToDoCommand
, which resides inside Logic
component. It supports modifying Status objects within ToDo objects. CheckToDoCommand and UnCheckToDoCommand inherit from UndoableCommand
.
Hence, CheckToDoCommand and UnCheckToDoCommand can be undone using UndoRedoStack
.
Similar to Content
object, each ToDo
object have a Status
object, representing the status of the to-do.
The status of a to-do can be either done
or undone
.
When user check/uncheck an existing to-do of specific Index
, a new ToDo
is created, with the existing ToDo’s `Content
and appropriate new Status
.
The existing to-do is replaced by the new to-do in the UniqueToDoList
and the current state of the address book is saved.
Figure 46 shows how the checkToDo operation works:
Figure 47 shows how the unCheckToDo operation works:
-
Alternative 1 (current choice): Add a new method
setStatus(Status newStatus)
inToDo
-
Pros: This implementation do not require a new
ToDo
object to be created to replace the existing to-do. -
Cons: This implementation does not follow the Single Responsibility Principle.
-
Edits a To-do.
The edit to-dos mechanism is facilitated by EditToDoCommand
, which resides inside Logic
component. It supports modifying Content objects within ToDo objects. EditToDoCommand inherit from UndoableCommand
.
Hence, EditToDoCommand can be undone using UndoRedoStack
.
When user edit an existing to-do of specific Index
, a new ToDo
is created, with the new Content
and a new Status
of "undone" value.
The existing to-do is replaced by the new to-do in the UniqueToDoList
and the current state of the address book is saved.
Figure 48 shows how the editToDo operation works:
-
Alternative 1 (current choice): Add a new method
setContentAndStatus(Content content, Status newStatus)
inToDo
-
Pros: This implementation do not require a new
ToDo
object to be created to replace the existing to-do. -
Cons: This implementation does not follow the Single Responsibility Principle.
-
Deletes a To-Do.
The delete to-dos mechanism is facilitated by DeleteToDoCommand
, which resides inside Logic
component. It supports deleting ToDo objects. DeleteToDoCommand inherit from UndoableCommand
.
Hence, DeleteToDoCommand can be undone using UndoRedoStack
.
When user delete an existing to-do of specific Index
, the UniqueToDoList
within AddressBook
is updated and stored in the StorageManager
.
Figure 49 shows how the deleteToDo operation works:
Fastis uses the 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 4.19, “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.
Listed below are the different logging levels:
-
SEVERE
: Critical problems detected which may possibly cause the termination of the application -
WARNING
: Non-Critical problems that allows the application to 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
This section provides necessary information for developers to edit and publish related documentations, such as User Guide and Developer Guide, for Fastis.
Fastis uses asciidoc for documentation.
ℹ️
|
Asciidoc is chosen over Markdown because asciidoc, although a bit more complex than Markdown, provides more flexibility in formatting. |
See UsingGradle.adoc to learn how to render .adoc
files locally to preview the end result of your edits.
Alternatively, you can download the AsciiDoc plugin for IntelliJ, which allows you to preview the changes you have made to your .adoc
files in real-time.
See UsingTravis.adoc to learn how to deploy GitHub Pages using Travis.
The project uses Google Chrome for converting documentation to PDF format, as Chrome’s PDF engine preserves hyperlinks used in webpages.
Here are the steps to convert the project documentation files to PDF format.
-
Follow the instructions in UsingGradle.adoc to convert the AsciiDoc files in the
docs/
directory to HTML format. -
Go to your generated HTML files in the
build/docs
folder, right click on them and selectOpen with
→Google Chrome
. -
Within Chrome, click on the
Print
option in Chrome’s menu. -
Set the destination to
Save as PDF
, then clickSave
to save a copy of the file in PDF format. For best results, use the settings indicated in the screenshot below.
This section documents how to run the tests on Fastis.
There are three ways to run tests.
Method 1: Using Gradle in headless mode (recommended)
Thanks to the TestFX library we use, our GUI tests can be run in the headless mode. In the headless mode, GUI tests do not show up on the screen. That means the developer can do other things on the Computer while the tests are running.
To run tests in headless mode, open a console and run the command gradlew clean headless allTests
(Mac/Linux: ./gradlew clean headless allTests
)
💡
|
The above-mentioned method is the most reliable. The other two listed below might fail some GUI tests due to platform/resolution-specific idiosyncrasies. |
Method 2: Using Gradle
Using Gradle without the headless mode will cause GUI tests to show up on screen. The test functions will simulate mouse movement and keyboard keystrokes, and tests might fail if you move your mouse or type anything on the keyboard. Thus during the GUI tests it is recommended that you leave your machine alone.
To run the tests, open a console and run the command gradlew clean allTests
(Mac/Linux: ./gradlew clean allTests
)
ℹ️
|
See UsingGradle.adoc for more info on how to run tests using Gradle. |
Method 3: Using IntelliJ JUnit test runner
Using this method, GUI tests will also show up on screen, and will require you to stop mouse and keyboard activity in order to run successfully.
This method requires you to have the project open on IntelliJ:
-
To run all tests, right-click on the
src/test/java
folder and chooseRun 'All Tests'
-
To run a subset of tests, you can right-click on a test package, test class, or a test and choose
Run 'ABC'
Fastis has two types of tests:
-
GUI Tests - These are tests involving the GUI. They include,
-
System Tests that test the entire App by simulating user actions on the GUI. These are in the
systemtests
package. -
Unit tests that test the individual components. These are in
seedu.address.ui
package.
-
-
Non-GUI Tests - These are tests not involving the GUI. They include,
-
Unit tests targeting the lowest level methods/classes.
e.g.seedu.address.commons.StringUtilTest
-
Integration tests that are checking the integration of multiple code units (those code units are assumed to be working).
e.g.seedu.address.storage.StorageManagerTest
-
Hybrids of unit and integration tests. These test are checking multiple code units as well as how the are connected together.
e.g.seedu.address.logic.LogicManagerTest
-
See UsingGradle.adoc to learn how to use Gradle for build automation.
We use Travis CI and AppVeyor to perform Continuous Integration on our projects. See UsingTravis.adoc and UsingAppVeyor.adoc for more details.
We use Coveralls to track the code coverage of our projects. See UsingCoveralls.adoc for more details.
When a pull request has changes to asciidoc files, you can use Netlify to see a preview of how the HTML version of those asciidoc files will look like when the pull request is merged. See UsingNetlify.adoc for more details.
Here are the steps to create a new release.
-
Update the version number in
MainApp.java
. -
Generate a JAR file using Gradle.
-
Tag the repo with the version number. e.g.
v0.1
-
Create a new release using GitHub and upload the JAR file you created.
A project often depends on third-party libraries. For example, Address Book depends on the Jackson library for XML parsing. Managing these dependencies can be automated using Gradle. For example, Gradle can download the dependencies automatically, which is better than these alternatives.
a. Include those libraries in the repo (this bloats the repo size)
b. Require developers to download those libraries manually (this creates extra work for developers)
Target user profile: NUS students with group projects that:
-
Have a number of events to keep track of. For example:
-
Group meetings,
-
Career Fair,
-
Interviews,
-
Consultations,
etc.
-
-
Prefer desktop apps over other types.
-
Can type fast.
-
Prefer typing over mouse input.
-
Are reasonably comfortable using CLI apps.
Value proposition: Help students manage the humongous amount of events that they might have.
Feature contribution:
-
Personal To-do list (MAJOR):
-
User can add to-dos, notes, upcoming tasks and organize them in a to-do list.
-
To-do list serves to remind the user of important tasks, events in group projects.
-
-
Meetup Time Generator (MAJOR):
-
Generator parses information from persons' NUSMods timetables and generate a suitable project meetup time.
-
Meetup Time Generator allows user to quickly decide meetup time without manually checking timetables.
-
-
Meetup Calendar (MAJOR):
-
User can add meetups with specific start, end time and display meetups on the calendar.
-
Meetup Calendar allows user to visualise and remember upcoming group events/meetups.
-
-
Organize persons in groups (MAJOR):
-
User can store specific persons in project groups.
-
User can have a group list and display persons in each group.
-
Groups allows user to manage persons based on the project groups they belongs to.
-
-
Detail field for a person (Minor):
-
Details for a person are additional information such as remark, hobbies, comments, etc.
-
Detail allows user to add information that does not fall under categories such as phone, email, etc.
-
Detail allows storing person information to become more flexible.
-
-
Timetable link field for a person (Minor):
-
Timetable link for person is an NUSMods website link.
-
Timetable link displays the actual link of NUSMods website shown when a person is selected.
-
Timetable link allows the user to manage NUSMods link of a person.
-
-
Customizable tags' color (Minor):
-
User can set color of specific tags.
-
Customizable tags' color allows user to better personalise the application.
-
-
Dark color theme for application bar and background (Minor):
-
Application bar and background are changed to dark grey color.
-
Dark color theme makes the application comfortable to use in different light conditions.
-
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
|
Student with group project |
Add person with project group tag |
I know which person belongs to which project groups |
|
Student that is finished with a group project |
Delete the group tag of a finished group project |
I will not see the group in the application anymore |
|
Student who forget teammates’ information |
Find a person by name |
I can find out more details of the person such as location, contact number |
|
Student who made a mistake in recording a group tag |
Edit a person’s group tag |
I can change the group tag accordingly |
|
Student who recorded the wrong personal information |
Edit a person |
I can correct the details of the person |
|
Student who wants to know which teammates are in the project group |
Print out the list of teammates under the same group tag |
I know which teammates I am meeting |
|
Student with arranged meet-ups |
Add meet-ups with title, time, venue to the calendar |
Have the summary of upcoming meet-ups in a quick glance |
|
Student using CLI |
Press up button to copy the previous command |
I do not need to retype duplicate commands |
|
Student that is involved with multiple groups |
search events by its title |
I can get details of a particular meet-up |
|
Student who wants to arrange meet-ups |
Search meet-ups by its title |
I can get details such as time and place of a particular meet-up |
|
Student adding teammates’ information |
Add the link to teammates’ timetable |
I can see teammates’ timetables to arrange meet-ups |
|
Student working with new teammates |
Add their contact information |
I can contact them if the need arises |
|
user |
add info of the members involved in events |
So that I know who I would need to talk to |
|
Student first time using the application |
See the usage instructions |
Learn how to use the application |
|
Student who have unused contacts |
Delete a teammate from the application |
I can free up storage for my application |
|
Busy student with busy schedule |
Have a reminder of the upcoming project meeting |
I can be reminded of impending project with the details of group members printed on it |
|
Student who created a group |
Show teammates from a group |
I can see the information of the teammates from the group |
|
Student who has multiple group projects |
Retrieve a list of all my groups |
I can see all my groups at once |
|
Student who is finished with a project |
Delete everyone in a group in one go |
I do not have to delete contacts one by one |
|
Student who is too lazy to type |
Use a shorter version of a command |
Use the app faster |
|
Student who wants to know the location of teammates |
Find the location of teammates’ address via google maps |
Decide on a appropriate meeting location for all teammates considering their home address |
|
Student that does not leave applications open |
See an overview of the week’s meetup right away when the application opens |
Do not have to type in any commands when I first open the application |
|
Student who would like different colours tag for different projects |
Have customizable coloured tags for different groups |
Easily differentiate the groups via colour tags |
|
User with accessibility problems |
Increase the font size of the application |
I can read and see more easily |
|
Student who is too lazy to eyeball through the timetables |
Have an appropriate meet-up time generated for a group |
I do not have to manually come up with time for meetup |
|
Student who uses NUSMods |
Use my NUSMods link to add my schedule into Fastis |
I don’t have to manually input my timetable |
|
Students who likes other colours on the interface |
Change color scheme |
Personalise the app |
|
Student who wants to call an absent teammate |
Open teammates’ Whatsapp page within the application e |
I can alert teammates of the meeting |
|
Student who do not how to reach the destination of the meet-up |
Have the venue of the meet-up shown on google map |
I can know the direction to the meetup |
|
user |
find the road that travels the shortest distance to the location of event |
So that I can rely on the, map while driving |
|
user |
link an event with another |
So that events that are related can be linked together so that i know which events are related |
|
user |
play music from address book |
So that I can listen to music i want |
|
user |
play videos from youtube |
So that I can watch videos i want |
(For all use cases below, the System is the Fastis
and the Actor is the user
, unless specified otherwise)
MSS
-
User requests to add an event by entering information.
-
Fastis adds the event to the calendar.
Use case ends.
Extensions
-
2a. Meet up clashes with an existing event.
-
2a1. Fastis still adds the event, but it’s not shown in the calendar.
Use case ends.
-
MSS
-
User requests to list all persons.
-
Fastis shows all persons, listed with an index.
-
User requests to add a person, specified by an index, to a group, specified by name.
-
Fastis adds the specified person to the specified group.
Use case ends.
Extensions
-
2a. Index given is invalid.
-
2a1. Fastis notifies user that the index given was invalid.
Use case ends.
-
-
3a. There is no such group in Fastis.
-
3a1. Fastis notifies the user that no group was found.
Use case ends.
-
MSS
-
User requests to list all persons in Fastis.
-
Fastis lists all persons.
Use case ends.
Extensions
-
2a. The persons list is empty.
-
2a1. Fastis shows an empty list.
Use case ends.
-
MSS
-
User requests to list all persons.
-
Fastis shows all persons, listed with an index.
-
User requests to delete a person, specified by an index, from a group, specified by name.
-
Fastis deletes the specified person from the specified group, and notifies the user.
Use case ends.
Extensions
-
2a. There is no such group in Fastis.
-
2a1. Fastis notifies the user that no group was found.
Use case ends.
-
-
3a. The specified person is not in that group.
-
3a1. Fastis notifies the user that there is no such person in the group specified.
Use case ends.
-
MSS
-
User selects a person, either by
select
command or by clicking on the person in the person list panel. -
Fastis shows the timetable for the person.
Use case ends.
Extensions
-
2a. The specified person has no timetable
-
2a1. Fastis shows an empty timetable
Use case ends.
-
MSS
-
User requests to list the groupmates for a group, specified by name.
-
Fastis lists all members in that group in the person list panel.
Use case ends.
Extensions
-
2a. There is no such group in Fastis.
-
2a1. Fastis notifies the user that no group was found.
Use case ends.
-
-
3a. There are no people in that group.
-
3a1. Fastis shows an empty list.
Use case ends.
-
MSS
-
User requests to see the help panel.
-
Fastis shows the help panel in a separate window.
Use case ends.
MSS
-
User enters keystroke to navigate to previously entered command.
-
Fastis copies the previous command into the input field.
Use case ends.
MSS
-
User enters a command to change a specific tag color.
-
Fastis changes the color accordingly and displays it.
Use case ends.
Extensions
-
2a. The tag specified doesn’t exist within the address book.
-
2a1. Fastis notifies the user.
Use case ends.
-
-
3a. The color specified is not supported by Fastis.
-
3a1. Fastis notifies the user.
Use case ends.
-
-
Fastis should work on any mainstream OS as long as it has Java
1.8.0_60
or higher installed. -
Fastis should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage.
-
A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
-
Fastis should be usable without the need of a mouse.
-
Fastis should be usable solely via a command line interface.
-
Fastis should respond within 2 seconds.
-
Fastis should have an easy to follow user guide.
-
Fastis should open the help page when user enters an invalid entry.
-
Fastis should be possible to fixed and debugged in the event of malfunction.
{More to be added}
- Abstraction
-
In Object-oriented Programming, abstraction is the mechanism by which users are provided with only the functionality, and not the implementation details. So, abstraction provides users with information on what an object does, rather than how it does it.
- GUI
-
Acronym for Graphical User Interface. It is an interface (through which humans to interact with computers) that uses windows, icons and menus and which can be manipulated by a mouse and a keyboard.
GUI is used predominantly in Windows and iOS applications, including Fastis. - CLI
-
Acronym for Command Line Interface. It is a purely text-based interface for software. User respond to visual prompts by typing single commands into the interface and receive results as text as well. An example of CLI would be MS-DOS.
- To-do
-
An objective that must be met by the user. May or may not have deadlines.
- Event
-
A set of scheduled activity that user needs to attend at a specific time
E.g. Interviews, parties, CCAs, talks, coding challenges, assignments, etc. - Mainstream OS
-
Windows, Linux, Unix, OS-X
- Member
-
A person in the address book.
- Private contact detail
-
A contact detail that is not meant to be shared with others
- User Interface
-
The means by which the user and a computer system interact, in particular the use of input devices and software.
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. |
-
Initial launch
-
Download the .jar file and copy into an empty folder
-
Double-click the .jar file
Expected: Fastis 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, preferably to maximum 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 are retained.
-
Deleting a person while all persons are listed
-
Prerequisites: All persons are listed using the
list
command. Multiple persons exist in the list. -
Test case:
delete 1
Expected: First contact is deleted from the list. Details of the deleted contact are shown in the result display box. Timestamp of the last update in the status bar is updated. -
Test case:
delete 0
Expected: No person is deleted. Error details are shown in the result display box. Status bar remains the same. -
Other incorrect delete commands to try:
delete John
,delete x
(wherex
is larger than the list size) {give more}
Expected: Similar to previous.
Adding a person specified by the command line input with required person prefixes.
-
Test case:
add n/John Doe p/98765432 e/[email protected] a/311, Clementi Ave 2, #02-25 l/http://modsn.us/MYwiD d/Likes tennis t/friends t/owesMoney
Expected: A new person named John Doe is added to Fastis. Details of person added are shown in the result display box. -
Test case:
add p/98765432 e/[email protected] a/311, Clementi Ave 2, #02-25 l/http://modsn.us/MYwiD d/Likes tennis t/friends t/owesMoney
Expected: No person is added. EssentialNAME
field is missing. Error details are displayed in result display box. -
Other incorrect add commands to try:
add
,add x
(where x is any input)
Expected: Similar to previous.
Adding a to-do with content specified by the command line input.
-
Prerequisites: To-do with the content specified by user must not already be in Fastis.
-
Test case:
addToDo Do homework
Expected: New to-do with contentDo homework
will be added to Fastis. Successful adding of to-doDo homework
will be reflected in the result display box. -
Test case:
addToDo Submit assignment - + -
Expected: No to-do is added. To-do content must be alphanumeric. Error details are displayed in the result display box. -
Other incorrect commands:
addToDo Submit assignment!
Expected: Similar to previous. -
To-do
Do homework
already existed.
Test case:addToDo Do homework
Expected: Error details are displayed in status bar that to-do already exists.
Deleting a to-do while all to-dos are listed
-
Prerequisites: All to-dos are listed. Multiple to-dos exist in the list.
-
Test case:
deleteToDo 1
Expected: First to-do is deleted from the list. Details of the deleted to-do are shown in the result display box. Timestamp of the last update in the status bar is updated. -
Test case:
deleteToDo 0
Expected: No to-do is deleted. Error details are shown in the result display box. Status bar remains the same. -
Other incorrect deleteToDo commands to try:
deleteToDo Swim
,deleteToDo x
(wherex
is larger than the list size)
Expected: Similar to previous.
Checking a to-do while all to-dos are listed
-
Prerequisites: All to-dos are listed. Multiple to-dos exist in the list.
-
Test case:
check 1
Expected: First to-do status is changed to "done". Details of the checked to-do are shown in the result display box. Timestamp of the last update in the status bar is updated. -
Test case:
check 0
Expected: No to-do is checked. Error details are shown in the result display box. Status bar remains the same. -
Other incorrect check commands to try:
check Swim
,check x
(wherex
is larger than the list size)
Expected: Similar to previous.
Unchecking a to-do while all to-dos are listed
-
Prerequisites: All to-dos are listed. Multiple to-dos exist in the list.
-
Test case:
uncheck 1
Expected: First to-do status is changed to "undone". Details of the unchecked to-do are shown in the result display box. Timestamp of the last update in the status bar is updated. -
Test case:
uncheck 0
Expected: No to-do is unchecked. Error details are shown in the result display box. Status bar remains the same. -
Other incorrect uncheck commands to try:
uncheck Swim
,uncheck x
(wherex
is larger than the list size)
Expected: Similar to previous.
Editing a to-do while all to-dos are listed
-
Prerequisites: All to-dos are listed. Multiple to-dos exist in the list.
-
Test case:
editToDo 1 c/Do homework
Expected: First to-do content is changed to "Do homework". Details of the edited to-do are shown in the result display box. Timestamp of the last update in the status bar is updated. -
Test case:
editToDo 0 c/Do homework
Expected: No to-do is edited. Error details are shown in the result display box. Status bar remains the same. -
Other incorrect editToDo commands to try:
editToDo c/Swim
,editToDo x c/Swim
(wherex
is larger than the list size)
Expected: Similar to previous.
Adding a group with information specified by the command line input.
-
Prerequisites: Group with the information specified by user must not already be in Fastis.
-
Test case:
addGroup CS1010
Expected: New group with informationCS1010
will be added to Fastis. Successful adding of groupCS1010
will be reflected in the result display box. -
Test case:
addGroup CS1-1-
Expected: No group is added. Group information must be alphanumeric. Error details are displayed in the result display box. -
Other incorrect commands:
addGroup CS!
Expected: Similar to previous. -
Group
CS1010
already existed.
Test case:addGroup CS1010
Expected: Error details are displayed in status bar that group already exists.
Adding a member identified by INDEX
to the group identified by INFORMATION
.
-
Prerequisites: Group and Person both exist in Fastis. Person must exist on the current Person List.
-
Test case:
addGroupMember 1 g/CS1010
Expected: Member that is first on Person List will be added to the group with informationCS1010
. Successful adding of the person will be displayed on the result display box. -
Test case:
addGroupMember 1 CS1010
Expected: No member is added as command input is invalid since group fieldg/
is missing. Error details are displayed in the result display box. -
Other incorrect commands to try:
addGroupMember
,addGroupMember 1 t/
Expected: Same as previous.
Deleting a person from a group specified by the user. Often used after listGroupMembers
command to see which members are in the group.
-
Prerequisites: Group and Person both exist in Fastis. Person must exist on the current Person List.
-
Test case:
deleteGroupMember 1 g/CS1010
Expected: Member is successfully deleted from the groupCS1010
. Successful deletion is displayed in the result display box. -
Test case:
deleteGroupMember 1 CS1010
Expected: No member is deleted due to missing fieldg/
in command. Error details are displayed in the result display box. -
Other incorrect commands to try:
deleteGroupMember
,deleteGroupMember 1 t/
Expected: Same as previous.
Listing all persons from a group specified by the user.
-
Prerequisites: Group must exist in Fastis.
-
Test case:
listGroupMembers CS1010
Expected: All members in group with informationCS1010
are listed on Person List. Successful listing is displayed in the result display box. -
Test case:
listGroupMembers !
Expected: No person is listed. Error details are displayed in the result display box.
Deleting a group with information specified by the user from Fastis.
-
Prerequisites: Group must exist in Fastis.
-
Test case:
deleteGroup CS1010
Expected: Group with informationCS1010
is deleted. Successful deletion is displayed in the result display box. -
Test case:
deleteGroup @
Expected: No group is deleted. Error details are displayed in the the result display box.
Adding an event specified by command line input with required event prefixes.
-
Test case:
addEvent n/CS2101 meeting v/COM1 Hackerspace d/15/04/2018 st/1600 et/1800
Expected: New event "CS2101 meeting" is added to Fastis. Details of the event added are shown in the result display box. -
Test case:
addEvent v/COM1 Hackerspace d/15/04/2018 st/1600 et/1800
Expected: No event is added. EssentialNAME
field is missing. Error details are displayed in the result display box. -
Other incorrect addEvent commands to try:
addEvent d/18/04/15
,addEvent d/30/02/2018
,addEvent st/1900 et/1700
, etc.
Expected: Similar to previous.
Listing all persons that have any of the specified tag(s).
-
Prerequisites: Tag(s) must exist in Fastis.
-
Test case:
listTagMembers friends
Expected: All members with tagfriends
will be listed on Person List. Number of person listed will be shown in status bar. -
Test case:
listTagMembers 2131
(Tag 2131 does not exist in Fastis)
Expected: 0 persons listed.
Changing a tag identified by `TAG` to have the color identified by `COLOR`.
-
Prerequisites:
TAG
already exists in Fastis.COLOR
must be supported by Fastis. -
Test case:
changeTagColor friends pink
Expected: Color of all tags named "friends" changes to "pink". Successful message of the change will be displayed in the result display box. -
Test case:
changeTagColor friends rainbow
Expected: No tag is changed as an unsupported color "rainbow" was input. Error details are displayed in the result display box. -
Other incorrect commands to try:
changeTagColor
,changeTagColor pink friends
Expected: Same as previous.