By: SC09-F14-3      Since: Aug 2019      Licence: MIT

1. Setting up

Refer to the guide here.

2. Design

2.1. Architecture

Typee UML Architecture
Figure 1. Architecture Diagram

The Architecture Diagram given above explains the high-level design of the App.

Main has two classes called Main and MainApp. It is responsible for,

  • At app launch: Initializes the components in the correct sequence, and connects them up with each other.

  • At shut down: Shuts down the components and invokes cleanup 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

  • UI: The UI of the App.

  • Logic: The command executor.

  • Model: Holds the data of the App in-memory.

  • Storage: Reads data from, and writes data to, the hard disk.

The first 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.

LogicClassDiagram
Figure 2. Class Diagram of the Logic Component

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 i/1.

ArchitectureSequenceDiagram
Figure 3. Component interactions for delete i/1 command

The sections below give more details of each component.

2.2. UI component

UiClassDiagram
Figure 4. Structure of the UI Component

API : Ui.java

The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, EngagementListPanel, StatusBarFooter, HelpWindow , Tab, TabListPanel, 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.

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

LogicClassDiagram
Figure 5. Structure of the Logic Component


The package state contains additional packages that represent state machines for each Command. These packages have been omitted for brevity.
XYZ refers to any arbitrary command. For example:
XYZEndState can be AddEndState and XYZCommand can be AddCommand.

API : Logic.java

  1. Logic uses the InteractiveParser class to parse the user command.

  2. This results in a Command object which is executed by the LogicManager.

  3. The command execution can affect the Model (e.g. adding a person).

  4. The result of the command execution is encapsulated as a CommandResult object which is passed back to the Ui.

  5. In addition, the CommandResult object can also instruct the Ui to perform certain actions, such as displaying help to the user.

2.4. Model component

ModelClassDiagram
Figure 6. Structure of the Model Component

API : Model.java

The Model,

  • stores a UserPref object that represents the user’s preferences.

  • stores the engagement list data.

  • exposes an unmodifiable ObservableList<Engagement> 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.

2.5. Storage component

StorageClassDiagram
Figure 7. Structure of the Storage Component

API : Storage.java

The Storage component,

  • can save UserPref objects in json format and read it back.

  • can save the engagement list data in json format and read it back.

2.6. Common classes

Classes used by multiple components are in the com.typee.commons package.

3. Implementation

This section describes some noteworthy details on how certain features are implemented.

3.1. Tab Switch Feature

Tab switch feature is a type of Command that allows users to switch to respective windows for using different features in the system.
Tab switch function is implemented in using both CLI and GUI approach; user can execute tab-switch by typing command in the input text-area or by interaction with the UI component (Button).

3.1.1. Implementation Structure


tabcmd and tabFetch activity
Figure 8. TabCommand Class Diagram and fetchTabInfo Activity Diagram

  1. User is required to use a Command; TabCommand in order to switch the window to another window.

    • Upon first startup of the system, system will display the EngagementList window by default.

  2. New Ui Model class Tab is implemented to contain the respective fxml controller classes in a OOP manner.

MainWindow will have an additional method fetchTabInformation(tabName). After the parser executes the TabCommand, it will return a CommandResult with Tab property.
System will then check whether the input name matches with one of the tab names in the system. If there is a match, system will fetch the tab information and return the Tab object. If no match is found, system will return with an empty tab with only name attached.

3.2. Undo/Redo feature

3.2.1. Implementation

The undo/redo mechanism is facilitated by HistoryManager. It extends EngagementList with an undo/redo history, stored internally as an historyList and versionPointer. Additionally, it implements the following operations:

  • HistoryManager#saveState() — Saves the current engagement list state in its history.

  • HistoryManager#undo() — Restores the previous engagement list state from its history.

  • HistoryManager#redo() — Restores a previously undone engagement list state from its history.

These operations are exposed in the Model interface as Model#saveEngagementList(), Model#undoEngagementList() and Model#redoEngagementList() respectively.

Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.

Step 1. The user launches the application for the first time. The HistoryManager will be initialized with the initial engagement list state, and the versionPointer pointing to that single engagement list state.

UndoRedoState0

Step 2. The user executes delete i/5 command to delete the 5th person in the engagement list. The delete command calls Model#saveEngagementList(), causing the modified state of the engagement list after the delete 5 command executes to be saved in the historyList, and the versionPointer is shifted to the newly inserted engagement list state.

UndoRedoState1

Step 3. The user executes add t/meeting …​ to add a new engagement. The add command also calls Model#saveEngagementList(), causing another modified engagement list state to be saved into the historyList.

UndoRedoState2
If a command fails its execution, it will not call Model#saveEngagementList(), so the engagement list state will not be saved into the historyList.

Step 4. The user now decides that adding the person was a mistake, and decides to undo that action by executing the undo command. The undo command will call Model#undoEngagementList(), which will shift the versionPointer once to the left, pointing it to the previous engagement list state, and restores the engagement list to that state.

UndoRedoState3
If the versionPointer is at index 0, pointing to the initial engagement list state, then there are no previous engagement list states to restore. The undo command uses Model#hasNoUndoableCommand() to check if this is the case. If so, it will return an error to the user rather than attempting to perform the undo.

The following sequence diagram shows how the undo operation works:

UndoSequenceDiagram
The lifeline for UndoCommand and UndoState should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.

The redo command does the opposite — it calls Model#redoEngagementList(), which shifts the versionPointer once to the right, pointing to the previously undone state, and restores the engagement list to that state.

If the versionPointer is at index historyList.size() - 1, pointing to the latest engagement list state, then there are no undone engagement list states to restore. The redo command uses Model#hasNoRedoableCommand() to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.

Step 5. The user then decides to execute the command sort p/start o/ascending. Commands that do not modify the engagement list, such as sort, will usually not call Model#saveEngagementList(), Model#undoEngagementList() or Model#redoEngagementList(). Thus, the historyList remains unchanged.

UndoRedoState4

Step 6. The user executes clear, which calls Model#saveEngagementList(). Since the versionPointer is not pointing at the end of the historyList, all engagement list states after the versionPointer will be purged. We designed it this way because it no longer makes sense to redo the add d/meeting …​ command. This is the behavior that most modern desktop applications follow.

UndoRedoState5

The following activity diagram summarizes what happens when a user executes a new command:

CommitActivityDiagram

3.2.2. Design Considerations

Aspect: How undo & redo executes
  • Alternative 1 (current choice): Saves the entire engagement list.

    • Pros: Easy to implement.

    • Cons: May have performance issues in terms of memory usage.

  • Alternative 2: Individual command knows how to undo/redo by itself.

    • Pros: Will use less memory (e.g. for delete, just save the person being deleted).

    • Cons: We must ensure that the implementation of each individual command are correct.

Aspect: Data structure to support the undo/redo commands
  • Alternative 1 (current choice): Use a list to store the history of engagement list states.

    • Pros: Easy to implement.

    • Cons: Logic is duplicated twice. For example, when a new command is executed, we must remember to update both historyList and engagementList.

  • Alternative 2: Use jdeveloper.history.HistoryManager for undo/redo

    • Pros: We do not need to maintain a separate list, and just reuse what is already in the codebase.

    • Cons: Requires dealing with commands that have already been undone: We must remember to skip these commands. Violates Single Responsibility Principle and Separation of Concerns as HistoryManager now needs to do two different things.

3.3. Sort feature

3.3.1. Implementation

The sort mechanism is facilitated by EngagementComparator. The EngagementComparator is an enum class that implements Java Comparator<Engagement> and specifies the comparing logic of 8 different orders, namely START_TIME, START_TIME_REVERSE, END_TIME, END_TIME_REVERSE, ALPHABETICAL, ALPHABETICAL_REVERSE, PRIORITY, and PRIORITY_REVERSE. Each positive sequence comparator compares two Engagements with the field specified within its name in ascending order, and _REVERSE comparators compare in descending order.

Additionally, the Model interface is modified to support the following methods:

  • Model#setComparator(Comparator<Engagement>) — Sets the designated comparator in model.

  • Model#updateSortedEngagementList() — Executes the sorting method with the currentComparator in model to sort the internal list.

  • Model#getSortedEngagementList() — Returns the current internal engagement list as an unmodifiable ObservableList.

These operations are implemented in the ModelManager class as ModelManager#setComparator(Comparator<Engagement>), ModelManager#updateSortedEngagementList() and ModelManager#getSortedEngagementList() respectively.

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 currentComparator will be initialized as null.

SortListState0

Step 2. The user executes sort p/priority o/ascending command to sort the engagement list in ascending order of priority. The sort command calls Model#setComparator(), causing the currentComparator in ModelManager to assume the value EngagementComparator#PRIORITY. The command then calls Model#updateSortedEngagementList to execute the sorting.

SortListState1
The parsing of sort follows the interactive parsing structure Typee adopts, where various stages are created while parsing. See Sequence Diagram below.

The following sequence diagram shows how the sort operation works:

SortSequenceDiagram
The lifeline for SortCommand and the 3 Stages should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.

Step 3. The user executes add t/meeting …​ p/high to add a new engagement. The add command also calls Model#updateSortedEngagementList() with currentComparator, causing the execution of sorting after the new engagement is added to the list, to preserve the current ordering.

SortListState2
If the currentComparator assumes the initial value null when Model#updateSortedEngagementList is called, the method will simply catch the NullPointerException thrown by java.object.requireNonNull which will essentially abort the attempt to sort with an empty catch block. The initial chronological order is preserved in this case.

Step 5. The user then decides to execute the command list. Commands that do not modify the engagement list or alter the order of the list, such as list, will usually not call Model#setComparator(Comparator<Engagement>), or Model#updateSortedEngagementList(). Thus, the internal ObservableList remains unchanged.

SortListState3

The following activity diagram summarizes what happens when a user executes a new command:

SortUpdateActivityDiagram

3.3.2. Design Considerations

Aspect: How sort executes
  • Alternative 1 (current choice): Use the List.sort(Comparator<T>) function to sort the list.

    • Pros: Has trivial support for features that updates the predicate of FilteredList, like Find.

    • Cons: There is a need to sort the list each time a command that modifies the elements of the list is executed, which may result in performance issues in case the list size is large.

  • Alternative 2: Replace the FilteredList in ModelManager with a SortedList.

    • Pros: Sorting the list is more intuitive, and the ordering of the engagements is automatically preserved whenever a command that modifies the list elements is executed.

    • Cons: Features like find command may lose functionality and needs extra modification.

3.4. Engagement Report Generation

This feature allows user to generate a pre-selected engagement in to a report and save it as a document file. The document file will be created in a .pdf format.

3.4.1. Implementation Structure

PdfCommandClassDiagram
Figure 9. PdfCommand Implementation Class Diagram

The feature will be implemented as an additional type of Command; PdfCommand

  • Proposed syntax of the PdfCommand is as follow: pdf i/ENGAGEMENT_LIST_INDEX t/RECEIVER f/SENDER.

Util class PdfUtil will be implemented for handling all pdf document creation related methods. It will be implemented under util package and it will be able to deliver few essential features that are necessary for document creation.

  • Able to generate a full report document based on the Engagement as input.

  • Use different templates for each other types of Engagement such as Appointment, Interview and Meeting. Document template will follow general email format: Receiver, Engagement Information written in a table, Sender and signature with address and company logo.

    To fulfill the document format, Report class needs to be implemented in order to model all necessary properties that has to be in the document. It 3 following properties;

    • engagement: specific engagement information to include in the document

    • to: A Person who is receiving the document

    • from: A Person who is either a receptionist or a secretary who is sending the document.

Below is the sequence diagram for document generation which displays the concept of how this feature will be implemented by multiple interaction between different architecture components.

GenerateReportSequenceDiagram
Figure 10. Sequence diagram for document generation.

3.4.2. UI Design

ReportWindow will be the UI container which helps the user to interact using PdfCommand. The window will include dynamic tree-view that is directly linked to the external directory in the file-system; reports/

UI Components & Features

Table below explains the components that are included in the ReportWindow with its purpose and features.

Table 1. Report Window UI Components
UI Component Feature Purpose

Refresh Button

Button

Refreshes the tree-view file directory.

To help user refresh the directory when there is a system glitch or when document (.pdf) is manually added in the reports/ directory.

Delete Button

Button

Deletes the selected document item in the tree-view file directory.

To assist users who prefer using mouse instead of typing command in keyboard can delete documents easily.

File_Explorer

Scrollable Tree View

1. Displays the list of document generated previously and stored under the directory reports/.

2. Each list item is clickable with a mouse click action of opening the document.

To allow user to manage documents more time efficiently.

3.5. Calendar Window

The CalendarWindow provides a visual representation of stored engagements over a monthly period. Users can choose to change the month being displayed and also open scrolling text windows which show more detailed descriptions of the stored engagements for a particular day.

3.5.1. Implementation Structure

CalendarWindowClassDiagram
Figure 11. Structure of the Calendar Window


The CalendarWindow is part of the MainWindow. Specifically, it is one possible Tab which can be displayed. The CalendarWindow class and any of its associated UI components can be found under the com.typee.ui.calendar package.

The following sequence diagram shows the creation of a CalendarWindow instance when the user switches to the calendar window tab.

CalendarWindowSequenceDiagram
Figure 12. CalendarWindow Initialization Sequence Diagram


3.5.2. UI Design

The CalendarWindow class was designed with the observer pattern in mind. The calendar’s display and any open engagements list windows are automatically updated as engagements are added to or deleted from the application. CalendarDateCell and EngagementListViewCell both have a reference to an ObervableList of engagements in order to conform to the observer pattern. The following table shows all UI components which are used and their respective purposes.

Table 2. Calendar Window UI Components
UI Component Type Feature Purpose

DateDisplayGrid

GridPane

Displays a grid which represents 35 calendar dates.

Shows the user the days of the month which is currently being displayed.

CalendarDateStackPane

StackPane

Displays the date of a single CalendarDateCell and the number of engagements for that date.

Provides the user with some general engagement information for a particular date.

PreviousMonthButton

Button

Switches the calendar’s display to the previous month.

Allows the user to navigate to the previous month.

CalendarTitle

Text

Indicates the month and year currently being displayed by the calendar window.

Informs the month and year currently being displayed by the calendar window.

NextMonthButton

Button

Switches the calendar’s display to the next month.

Allows the user to navigate to the next month.

EngagementListView

ListView

Displays a list of engagements for a particular date.

Lets the user see more detailed information about all of his/her engagements for a particular date

EngagementListViewCell

ListCell

Displays information for a single engagement.

Allows the user to see detailed information about a single engagement. This is used as the cell factory for ListView.

3.5.3. Command Execution Workflows

The following are the four commands which interact with CalendarWindow. They are accompanied by their respective activity diagrams which are used to model their workflows:

  • CalendarOpenDisplayCommand — Opens the engagements list window for the specified date.

CalendarOpenDisplayActivityDiagram
Figure 13. Open Display Activity Diagram


  • CalendarCloseDisplayCommand — Closes the engagements list window for the specified date.

CalendarCloseDisplayActivityDiagram
Figure 14. Close Display Activity Diagram


  • CalendarNextMonthCommand — Changes the calendar window’s display to the month after the currently displayed month.

CalendarNextMonthActivityDiagram
Figure 15. Next Month Activity Diagram


  • CalendarOpenDisplayCommand — Changes the calendar window’s display to the month prior to the currently displayed month.

CalendarPreviousMonthActivityDiagram
Figure 16. Previous Month Activity Diagram


3.5.4. Design Considerations

Aspect: Deciding whether to let engagements list windows from other months remain open when changing the displayed month
  • Alternative 1 (current choice): Only engagements list windows from the current month can be opened. Switching to other months causes all opened engagements list windows to be closed.

    • Pros: Easier to implement and does not take up much memory.

    • Cons: Does not let users view engagement lists from different months simultaneously.

  • Alternative 2: Letting engagements list windows remain open, regardless of the month, until they are closed by users.

    • Pros: Users are able to view side-by-side comparisons of their engagement lists across different months.

    • Cons: Introduces additional dependencies because many references to ObervableList instances must be maintained.

Aspect: Information being displayed in each calendar cell
  • Alternative 1 (current choice): Only display the number of engagements for each date.

    • Pros: Does not take up a lot of on-screen space. More detailed information about each day’s engagements can be viewed by opening the engagements list window for that particular date.

    • Cons: The information shown in the calendar window is very generalized.

  • Alternative 2: Display the descriptions (and maybe more detailed information) of each date’s engagements.

    • Pros: Shows more detailed information in the calendar window.

    • Cons: Might end up distorting the shape of the calendar window’s cells since some engagements have more information than others. The alternative would be to add fixed constraints to the size of each cell but then information would get cut off.

3.6. Game Feature

3.6.1. Implementation

The game feature is implemented using the singleton pattern using the singleton class GameWindow which is created by button-click in StartWindow. This means that there can only be one gameInstance at any given time with the exception of the game being over. The two diagrams below show the UML sequence diagram and activity diagram of the game window, which gives a high level overview of the game.

GameSequenceDiagram
Figure 17. Summary Sequence Diagram of Game Window
GameActivityDiagram
Activity Diagram of the Game Window

GameWindow has three main components PlayerInformation, GameBody and Player.

GameWindowClassDiagram
Figure 18. Structure of the Game Window

The component GameBody makes use of javafx.animation.AnimationTimer API to continuously loop MovingWords objects moving from top to bottom of the window using GameBody#loopWords(). MovingWords are created using HighlighterUtil#convertToTextFlowUsing(String word) , which appears as a TextFlow object of javafx.scene.text API.

Player input is represented as a javafx.beans.property.StringProperty in Player. Based on player input, MovingWords are updated using HighlighterUtil#convertToTextFlowUsing(String playerInput, String word) , which appears as a highlighted TextFlow object. In order to update the MovingWords object, the API javafx.animation.AnimationTimer is used by calling MovingWords#continuouslyUpdate().

The component PlayerInformation is bound to Player using javafx.beans.property API and is also updated when MovingWords#continuouslyUpdate() is called.

The table below summarises the various purposes of the 3 main Game Window UI components.

Table 3. Game Window UI Components
UI Component Type Feature Purpose

PlayerInformation

Scrollable Stack Pane

Displays the user’s score and health points.

To inform user about the in-game progress.

GameBody

AnchorPane

Displays the animation of the game.

To allow the user to view the animation of the moving words in a continuous manner.

MovingWords

Scrollable Stack Pane

Displays the individual word.

To allow user to know the next word to type.

3.6.2. Design Considerations

Aspect: Singleton pattern design of Game Window
  • Alternative 1 (current choice): Game Window with Singleton pattern design

    • Pros:

      • Prevent users from instantiating multiple Game Windows which may cause performance issues or even cause the application to crash.

    • Cons:

      • Reduced testability as it is difficult to replace Singleton objects with stubs, and increased coupling across code base.

  • Alternative 2: Game Window without Singleton pattern design

    • Pros: Increased testability and reduced coupling.

    • Cons: There could be the risk of users being able to instantiate hundreds or thousands of GameWindows which would cause performance issues or application crash issues.

3.7. Interactive Parsing

3.7.1. Overview

Interactive parsing allows users to build a command sequentially, as opposed to doing it entirely in one shot. A user that wishes to add an interview can simply type add t/interview to receive prompts on what to enter next.

This feature was conceived to make the application easy to use for amateur users.

3.7.2. Design & Implementation

Important Classes:

  • InteractiveParser - The interface exposed to LogicManager. The parser implements this interface.

  • Parser - A concrete implementation of InteractiveParser that enables interactive parsing.

  • State - An abstract class that represents the individual states the application can be in while parsing and building a Command.

  • EndState - An abstract class that extends from State. Represents the final State of a parsed command, from which a Command object can be built.

The interface InteractiveParser is the connecting interface between the LogicManager and the main Parser. This interface is designed by contract (DbC - proposed by Bertrand Meyer). The interface exposes four methods to the LogicManager, namely:

  • parseInput() - Parses the entered input.

  • fetchResult() - Returns the response to be showed to the user in a CommandResult object.

  • hasParsedCommand() - Returns true if the Parser has finished parsing a Command fully.

  • makeCommand() - Makes and returns the Command the user intends to execute.

To achieve interaction, the Parser keeps track of the State of the current Command being built. State is an abstract class that represents the individual states the application can be at in the midst of building a Command. EndState is an abstract class that extends from State, from which Command objects can be built. As and when valid inputs are entered, the Parser updates the current State to the subsequent States of the corresponding Command.

The Parser starts at an idle, inactive State Upon entering add t/meeting, the State being tracked is changed twice - first to the State corresponding to the type of the Engagement and then to the State responsible for the start date-time.

Such State changes happen sequentially until all the arguments necessary for the Command have been supplied. When all necessary arguments are present, the State being tracked transitions into an EndState. Once the tracked State transitions into an EndState, the Parser builds the Command which is executed by the LogicManager.

The structure of the interactive parser is detailed in the UML diagram below.

InteractiveParserDiagram
Figure 19. Class diagram of the interactive parser. This figures shows an example of a state machine inside the package State.


The above diagram only shows the component of the package State that handles the PdfCommand. The other packages have been omitted for brevity.

Parsing of user entered inputs can be viewed as parsing a small, finite context-free language. The command built by a sequence of inputs is uniquely determined by the sequence of inputs entered by the user and happens to be deterministic.

This observation allows the Parser to be modeled by a finite state machine. A finite state machine is an abstract computational model which consists of a machine comprising several states. At a particular point in time, only one state of the state machine is active. The machine transitions from one state to another state if certain conditions are met.

In the context of Typee’s Parser, the parser of each individual Command is a distinct finite state machine. The condition to be satisfied to transition to another state is the validation of user-entered inputs.

The incorporation of state machines into the Parser is done by implementing a slightly modified version of the state pattern documented by the Gang of Four (GoF).

Upon initiating the parsing (building) of a Command, the state machine that corresponds to the required Command is instantiated and set to its initial state. This state becomes the State tracked by the Parser Subsequent inputs are tokenized by the ArgumentTokenizer class, processed by the InputProcessor class and forwarded to the current State. If the input is deemed valid, the Parser invokes the transition() method of the current State to proceed to the next State. This process is repeated until an EndState is reached. Throughout this process, the user receives feedback from the Parser in the form of an encapsulated CommandResult object.

Below is a sequence diagram illustrating the processes that occur when the user enters add t/meeting s/15/11/2019/1500 e/15/11/2019/1600.

InteractiveParserSequenceDiagram
Figure 20. Sequence diagram illustrating how the Parser parses the entered input and returns the result to the GUI in the form of a CommandResult object.


The sequence diagram incorrectly extends the life-line of the three destroyed State classes. This is due to a limitation of PlantUML.

The high-level working of the Parser can be summarized by the activity diagram shown below.

InteractiveParsingActivityDiagram
Figure 21. Activity diagram illustrating the high level functionality.


"parameter present" refers to the parameter required by a particular state.

3.7.3. Design Considerations

Aspect : Abstract model
  • Alternative 1 (current design) : Finite state machine

    • Pros:

      • Highly flexible - Entire command, one argument at a time and multiple arguments at a time - all are supported.

      • Easily extensible - Adding a new command will require almost no changes in any of the existing classes.

      • Supports optional arguments with the help of the OptionalState interface.

    • Cons:

      • Tedious to implement a state machine for each individual command.

  • Alternative 2 : Use a list based implementation to keep track of arguments entered.

    • Pros:

      • Easy to implement and keep track of arguments

    • Cons:

      • Very hard to implement optional states.

      • Cannot execute commands like Help at any point in time without hard-coding it in the Parser.

3.8. 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.9, “Configuration”)

  • The Logger for a class can be obtained using LogsCenter.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.9. 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:

  • receptionists / secretaries in corporations.

  • can type fast

  • prefers typing over mouse input

  • is reasonably comfortable using CLI apps

  • requires submitting large amount of structured reports or documents

Value proposition: increase productivity by managing appointments faster than a typical mouse/ GUI driven app and by increasing typing speed.

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…​

* * *

secretary

add an appointment

organise and schedule meetings/appointments

* * *

secretary

request ro edit a specific appointment

fix any misinformation that I typed wrongly

* * *

secretary under a busy manager

find specific appointments fast

schedule appointments efficiently

* * *

secretary

have the option to clear the appointment list

restart from scratch

* * *

secretary

undo my previous commands

recall commands made by mistake

* * *

secretary

redo recalled commands

retrieve the commands undone by mistake

* * *

secretary

select and delete a specific appointment from the list

manage inactive or cancelled appointments

* * *

busy secretary

able to see the appointments in calendar view

enjoy better convenience

* * *

user

save and load data from a local file

keep the appointment list locally

* *

secretary under a busy manager

sort all appointments

see them in the order I want

* *

user

have a command to terminate the application

* *

advanced user

be able to execute compound statements

improve efficiency

*

highly motivated secretary

have a typing warm-up

prepare myself for an important events like important meetings.

*

highly driven secretary

have a way to practice typing

improve my efficiency during work by increasing my typing speed

*

fast-typer

have a way to amend trivial spelling errors

improve typing efficiency

*

secretary

generate a PDF file of a selected appointment

make a distributable copy of the appointment

Appendix C: Use Cases

(For all use cases below, the System is the Typee and the Actor is the user, unless specified otherwise)

Use case: (UC01) Add appointment

MSS

  1. User requests to add an appointment.

  2. System adds the corresponding appointment to the existing appointment list.

  3. System displays the updated appointment list and notifies the user.

    Use case ends

Extensions

  • 1a. User supplies the necessary information.

    Use case ends

  • 1b. User supplies invalid information.

    • 1b1. System notifies user about the invalid information.

      Use case ends

  • 1c. Appointment clashes with an existing appointment.

    • 1c1. System notifies user about the conflict.

      Use case ends

Use case: (UC02) List appointments

MSS

  1. User requests to list appointments

  2. System displays the list of appointments

    Use case ends.

Extensions

  • 1a. The list of appointments is empty

    Use case ends.

  • 2a. The list is empty

    Use case ends.

Use case: (UC03) Find appointment

MSS

  1. User requests to find appointments

  2. User provides fields that the user wants to use to find appointments

  3. System finds and displays the list of relevant appointments

    Use case ends.

Extensions

  • 2a. The list is empty.

    Use case ends.

Use case: (UC04) Delete appointment

MSS

  1. User requests to list appointments

  2. System displays the list of appointments

  3. User requests to delete a specific appointment in the list

  4. System deletes the appointment

    Use case ends.

Extensions

  • 2a. The list is empty.

    Use case ends.

  • 3a. The given index is invalid.

    • 3a1. System shows an error message.

      Use case resumes at step 2.

Use case: (UC05) Exit application

MSS

  1. User requests to exit the application

  2. System displays exit message

  3. System exits

    Use case ends

Use case: (UC06) Request help information

Use case: (UC07) Save updated Appointment data

MSS

  1. User make changes in the appointment list, or a specific appointment via CRUD.

  2. System saves the updated data

  3. System displays the updated appointment data

    Use case ends

Use case: (UC08) Edit selected appointment

MSS

  1. User requests to list appointments

  2. System displays the list of appointments

  3. User keys in index and provide fields that the user wants to edit

  4. System edits the selected appointment accordingly

    Use case ends.

Extensions

  • 2a. The list is empty

    Use case ends.

  • 3a. User keys in invalid index

    • 3a1. System shows error message.

      Use case resumes at step 2.

  • 3b. User does not provide any field to edit.

    • 3b1. System shows error message.

      Use case resumes at step 2.

Use case: (UC09) Undo previous command

MSS

  1. User requests to undo command

  2. System reverts the appointment list to its previous state

    Use case ends.

Extensions

  • 2a. There is no previous command

    Use case ends.

Use case: (UC10) Redo previous command

MSS

  1. User requests to redo command

  2. System reverts the appointment list to its previous undone state

    Use case ends.

Extensions

  • 2a. There is no previous undone command

    Use case ends.

Use case: (UC11) Switch tabs

MSS

  1. User requests to switch to a specified tab.

  2. System switches to the appropriate tab.

    Use case ends.

Extensions

  • 1a. Requested tab is invalid.

    • 1a1. System shows error message.

      Use case resumes at step 1.

Use case: (UC12) Calendar mode

MSS

  1. User specifies a date to view engagements for.

  2. System shows the engagements for the specified date.

Extensions

  • 1a. User specifies an invalid date.

    • 1a1. System shows error message.

      Use case resumes at step 1.

Use case: (UC13) Calendar mode month switching

MSS

  1. User specifies a month to switch the display to.

  2. System updates the calendar view to display appointments for the specified month.

Extensions

  • 1a. User specifies an invalid month.

    • 1a1. System shows error message.

      Use case resumes at step 1.

Use case: (UC14) Typing game

MSS

  1. User requests to start the typing game

  2. System shows typing game window which displays the specific word(s) to type.

  3. User plays the game by typing the word(s).

  4. Typing game updates the User’s score and health points accordingly. Steps 2-4 are repeated for as many rounds as required until User runs out of health points.

  5. Typing game shows the final score of the User when the game ends.

    Use case ends.

Extensions

  • 2a. User exits game

    Use case ends.

Use case: (UC15) Generate appointment document in PDF format

MSS

  1. User enters information for generating PDF of an engagement for a selected engagement.

  2. System generates a PDF file in a specific external directory

  3. System shows successful message

  4. System opens the generated document.

    Use case ends.

Extensions

  • 2a. System receives invalid input.

    • 2a1. System shows error message.

      Use case resumes at step 1.

  • 2b. User inputs duplicate information that already exists in the directory.

    • 2b1. System shows error message.

      Use case resumes at step 1.

Use case: (UC16) Sort appointments

MSS

  1. User requests to sort appointments

  2. User specifies the property to sort regarding to

  3. User specifies the order of ascending or descending

  4. System sorts the list of appointments by the specified order

    Use case ends.

Extensions

  • 2a. User does not specify property

    • 2a1. System shows error message

      Use case ends.

  • 2b. User specifies an invalid property

    • 2b1. System shows error message

      Use case ends.

  • 3a. User does not specify order

    • 3a1. System shows error message

      Use case ends.

  • 3b. User specifies an invalid order

    • 3b1. System shows error message

      Use case ends.

Appendix D: Non Functional Requirements

  1. Should work on any mainstream OS as long as it has Java 11 or above installed.

  2. Should come with automated unit tests and open source code.

  3. Should work on both 32-bit and 64-bit environments.

  4. Application should not exceed 100MB in size.

  5. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage.

  6. 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.

Appendix E: Glossary

Mainstream OS

Windows, Linux, Unix, OS-X

Secretary

A person employed by an individual or in an office to assist with correspondence, make appointments, and carry out administrative tasks.

Manager

The person that the secretary is assigned to work for.

Engagement

An arrangement, meeting or interview managed and maintained by a secretary, for the manager to meet someone at a particular time and place.

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

  1. Initial launch

    1. Download the jar file and copy into an empty folder

    2. Double-click the jar file
      Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.

  2. Saving window preferences

    1. Resize the window to an optimum size. Move the window to a different location. Close the window.

    2. Re-launch the app by double-clicking the jar file.
      Expected: The most recent window size and location is retained.

F.2. Adding an engagement

(i) Test case: add t/meeting s/16/11/2019/1500 e/16/11/2019/1600 l/Meeting Room 2 d/Team Meeting a/John | Smith p/High

Expected: Status bar shows the successful addition of engagement with its details. The engagement list is updated accordingly.

(ii) Test case: add t/ s/16/11/2019/1500 e/16/11/2019/1600 l/Meeting Room 2 d/Team Meeting a/John | Smith p/High

Expected: The engagement is not added. Status bar shows prompt for a valid engagement type due to invalid engagement type.

(iii) Test case: add t/meeting s/ e/16/11/2019/1600 l/Meeting Room 2 d/Team Meeting a/John | Smith p/High

Expected: The engagement is not added. Status bar shows prompt for a valid start time due to invalid start time.

(iv) Test case: add t/meeting s/16/11/2019/1500 e/ l/Meeting Room 2 d/Team Meeting a/John | Smith p/High

Expected: The engagement is not added. Status bar shows prompt for a valid end time due to invalid end time.

(v) Test case: add t/meeting s/16/11/2019/1500 e/16/11/2019/1600 l/ d/Team Meeting a/John | Smith p/High

Expected: The engagement is not added. Status bar shows prompt for a valid location due to invalid location.

(vi) Test case: add t/meeting s/16/11/2019/1500 e/16/11/2019/1600 l/Meeting Room 2 d/ a/John | Smith p/High

Expected: The engagement is not added. Status bar shows prompt for due to invalid description.

(vii) Test case: add t/meeting s/16/11/2019/1500 e/16/11/2019/1600 l/Meeting Room 2 d/Team Meeting a/ p/High

Expected: The engagement is not added. Status bar shows prompt for a valid attendees due to invalid attendees.

(vii) Test case: add t/meeting s/16/11/2019/1500 e/16/11/2019/1600 l/Meeting Room 2 d/Team Meeting a/John | Smith p/高

Expected: The engagement is not added. Status bar shows prompt for a valid priority due to invalid priority.

(viii) Test case:
The sequence of commands is as follows:

add
t/meeting
s/16/11/2019/1500
e/16/11/2019/1600
l/Meeting Room 2
d/Team Meeting
a/John | Smith
p/High

Expected: Status bar shows the successful addition of engagement with its details. The engagement list is updated accordingly.

(ix) Test case:
The sequence of commands is as follows:

add
t/appointment
s/01/01/2019/0900
e/01/01/2019/1000
l/Meeting Room 3
d/Team Discussion
a/John Smith
p/None

Expected: Status bar shows the successful addition of engagement with its details. The engagement list is updated accordingly.

(x) Test case:
The sequence of commands is as follows:

add
t/meeting
s/16/11/2019/1500
e/16/11/2019/1600
l/Meeting Room 2
d/Team Meeting
a/John | Smith
p/😄

Expected: The engagement is not added. Status bar shows prompt for a valid priority due to invalid priority.

F.3. Listing an engagement

(i) Test case: list

Expected: Status bar shows the successful listing of engagement. The full engagement list is shown.

(ii) Test case: 123 list

Expected: Status bar shows the successful listing of engagement. The full engagement list is shown.

(iii) Test case: list 123

Expected: Status bar shows the successful listing of engagement. The full engagement list is shown.

F.4. Deleting an engagement

(i) Test case: delete i/3

Expected: If there are 3 or more engagements in the engagement list, the 3rd engagement is deleted. Status bar shows the successful deletion of engagement with its details. The engagement list is updated accordingly. Otherwise, the engagement is not deleted due to invalid index.

(ii) Test case:
The sequence of commands is as follows:

delete
i/3

Expected: If there are 3 or more engagements in the engagement list, the 3rd engagement is deleted. Status bar shows the successful deletion of engagement with its details. The engagement list is updated accordingly. Otherwise, the engagement is not deleted due to invalid index.

(ii) Test case: delete i/-1

Expected: The engagement is not deleted due to invalid index.

(iii) Test case:
The sequence of commands is as follows:

delete
i/-1

Expected: The engagement is not deleted due to invalid index.

F.5. Finding an engagement

(i) Test case: find d/Singapore based

Expected: Engagements containing description keyword will be shown. e.g. will show all engagements containing the description Singapore based.
e.g. singapore based internship appointment, Singapore based project meeting

(ii) Test case:
The sequence of commands is as follows:

find
d/Singapore based

Expected: Engagements containing description keyword will be shown. e.g. will show all engagements containing the description Singapore based.
e.g. singapore based internship appointment, Singapore based project meeting

(iii) Test case: find l/Com Basement

Expected: Engagements matching the full exact keyword will be shown. e.g. will show all engagements containing the location Com Basement. Note that engagement with location Basement Room 6 will not be shown.

(iv) Test case:
The sequence of commands is as follows:

find
l/Com Basement

Expected: Engagements matching the full exact keyword will be shown. e.g. will show all engagements containing the location Com Basement. Note that engagement with location Basement Room 6 will not be shown.

(v) Test case: find a/Hans

Expected: Engagements containing attendee keyword will be shown. e.g. find a/Hans will show all engagements containing the attendee Hans.
e.g. Hansen Gruber, hans christian

(vi) Test case: find a/Hans
The sequence of commands is as follows:

find
a/Hans

Expected: Engagements containing attendee keyword will be shown. e.g. find a/Hans will show all engagements containing the attendee Hans.
e.g. Hansen Gruber, hans christian

(vii) Test case: find p/High

Expected: Engagements containing high priority will be shown.

(viii) Test case:
The sequence of commands is as follows:

find
p/High

Expected: Engagements containing high priority will be shown.

(ix) Test case: find a/Hans p/high

Expected: Engagements containing the attendee Hans and with high priority will be shown.

(ix) Test case:
The sequence of commands is as follows:

find
a/Hans p/high`

Expected: Engagements containing the attendee Hans and with high priority will be shown.

F.6. Sorting the engagement list

(i) Test case:
The sequence of commands is as follows:

sort
p/start
o/ascending

Expected: The list should be sorted in ascending order of start time.

(ii) Test case: Executing the sort command by giving all attributes at once

sort p/start o/ascending

Expected: This should give the exact same result as the previous stepwise command.

F.7. Undo and Redo

(i) Test case: Executing the undo command The sequence of commands is as follows:

delete i/1 (provided there is at least 1 engagement in the list)
undo

Expected: The previously deleted engagement should reappear in the list.

(ii) Test case: Executing the redo command The sequence of commands is as follows:

delete i/1 (provided there is at least 1 engagement in the list)
undo
redo

Expected: The recovered engagement should disappear in the list.

F.8. Calendar commands

All listed commands assume that the application is in the calendar tab.

(i) Test case:
The sequence of commands is as follows:

calendar c/opendisplay d/11/11/2019

Expected: The engagements display window for 11/11/2019 opens up.

(ii) Test case:
The sequence of commands is as follows:

calendar c/closedisplay d/11/11/2019

Expected: When executed immediately after executing the command in (i), the engagements display window for 11/11/2019 closes.

(iii) Test case:
The sequence of commands is as follows:

calendar c/opendisplay d/10/10/2019

Expected: The calendar window switches from the currently displayed month (assuming that it is not displaying October 2019) to October 2019. The engagements display window for 10/10/2019 opens up.

(iii) Test case:
The sequence of commands is as follows:

calendar c/nextmonth

Expected: All open engagements list windows are closed and the calendar displays the month after the currently displayed month.

(iv) Test case:
The sequence of commands is as follows:

calendar c/previousmonth

Expected: All open engagements list windows are closed and the calendar displays the month prior to the currently displayed month.

F.9. Tab

(i) Test case: tab b/engagement
Expected: The current tab switches to engagement tab

(ii) Test case: tab b/calendar
Expected: The current tab switches to calendar tab

(iii) Test case: tab b/game
Expected: The current tab switches to game tab

(iv) Test case: tab b/report
Expected: The current tab switches to report tab

F.10. Game

(i) Test case: Click on Start button of the starting window of the game tab. Expected: New game window opens.

(ii) Test case: Click on Close button of the game window. Expected: Game window closes.

F.11. Generating PDF

(i) Test case:

pdf
i/1 (provided at least 1 engagement in the list)
f/Jason
t/Gi Hun

Expected: A PDF file is generated with the content of the first engagement in list, with sender set to Gi Hun and reciver set to Jason. The file can be seen in the documents explorer tree view.

(ii) Test case:

Click the refresh button

Expected: Documents explorer tree view refreshes.

(iii) Test case:

Single click on an existing document in documents explorer tree view
Click the delete button
Select OK in pop-up dialog

Expected: Selected document is deleted from directory.

(iv) Test case:

Double click on an existing document in documents explorer tree view

Expected: Selected document opens in the default .pdf file viewer