Developer Guide
- Setting up, getting started
 - Design
 - Implementation
 - Documentation, logging, testing, configuration, dev-ops
 - Appendix: Requirements
 - Appendix: Instructions for manual testing
 - Appendix: Effort
 
Setting up, getting started
Refer to the guide Setting up and getting started.
Design
Architecture

The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.
.puml files used to create diagrams in this document can be found in the diagrams folder. Refer to the PlantUML Tutorial at se-edu/guides to learn how to create and edit diagrams.
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 methods where necessary.
 
Commons represents a collection of classes used by multiple other components.
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. 
Each of the four components,
- defines its API in an 
interfacewith the same name as the Component. - exposes its functionality using a concrete 
{Component Name}Managerclass (which implements the corresponding APIinterfacementioned in the previous point. 
For example, the Logic component (see the class diagram given below) defines its API in the Logic.java interface and exposes its functionality using the LogicManager.java class which implements the Logic interface.

How the architecture components interact with each other
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delete 1.

The sections below give more details of each component.
UI component

API :
Ui.java
The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, QAndAListPanel, StatusBarFooter etc. All these, including the MainWindow, inherit from the abstract UiPart class.
The UI component uses JavaFx UI framework. The layout of these UI parts are defined in matching .fxml files that are in the src/main/resources/view folder. For example, the layout of the MainWindow is specified in MainWindow.fxml
The UI component,
- Executes user commands using the 
Logiccomponent. - Listens for changes to 
Modeldata so that the UI can be updated with the modified data. 
Logic component

API :
Logic.java
- 
Logicuses theMedmoriserParserclass to parse the user command. - This results in a 
Commandobject which is executed by theLogicManager. - The command execution can affect the 
Model(e.g. adding a qAndA). - The result of the command execution is encapsulated as a 
CommandResultobject which is passed back to theUi. - In addition, the 
CommandResultobject can also instruct theUito perform certain actions, such as displaying help to the user. 
Given below is the Sequence Diagram for interactions within the Logic component for the execute("delete 1") API call.

DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Model component

API : Model.java
The Model,
- stores a 
UserPrefobject that represents the user’s preferences. - stores the answer book data.
 - exposes an unmodifiable 
ObservableList<Person>that can be ‘observed’ e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. - does not depend on any of the other three components.
 
Tag list in the Medmoriser, which QAndA references. This allows Medmoriser to only require one Tag object per unique Tag, instead of each QAndA needing their own Tag object.
Storage component

API : Storage.java
The Storage component,
- can save 
UserPrefobjects in json format and read it back. - can save the answer book data in json format and read it back.
 
Common classes
Classes used by multiple components are in the seedu.medmoriser.commons package.
Implementation
This section describes some noteworthy details on how certain features are implemented.
Add Feature (Cheng Jiyuqing)
Implementation
This portion describes the implementation of the add feature which allows the user to add new QAndAs with the question, answer and tags(optional).
Explanation of the diagrams:
- As the user parses the add command through the 
UI, theMedmoriserParseridentifies this as aAddCommandand passes the user input to theAddCommandParser. - The 
AddCommandParserensures the input is of correct format and identifies the input for question, answer and tag(s). - The 
AddCommandParserthen creates a new QAndA object, and passes it to a newAddCommandobject to handle the rest of the job. - The 
AddCommandobject will then add the new QAndA to model, and return aCommandResultcontaining a message to users indicating success in adding a new QAndA. - 
UIwill also be updated accordingly. 
The following sequence diagram (Fig 1.1) shows how the add operation works:
(Figure 1.1: Add Command Sequence Diagram)

Find feature (Ming Yang)
Implementation
This portion describes the implementation of the find feature which allows the user to find QAndA sets based on the question, answer or tags.
Explanation of the diagrams:
- As the user parses the find command through the 
UI, theMedmoriserParseridentifies this as aFindCommandand passes the user input to theFindCommandParser. - The 
FindCommandParseridentifies the type of find command, such as find tag/question/answer. - A 
FindCommandwith the respective predicate such asTagContainsKeywordPredicateis created and returned to theLogicManager. - The filtered list of question will be displayed on the 
UI. 
The following sequence diagram (Fig 1.2) shows how the find operation works:
(Figure 1.2: Find Command Sequence Diagram)

The activity diagram below (Fig 1.3) shows the activity flow of the find feature.
(Figure 1.3: Find Command Activity Diagram)

Quiz Feature (Joshua Tan)
Implementation
This feature allows the user to quiz himself/herself.
The flow of the execution is as follows:
- 
    
User enters the input for quiz (eg.
quiz t/Immune System) - 
    
The
LogicManagerexecutes the command, the command is then parsed byMedmoriserParserand the command is identified as aQuizCommand. The command is then parsed byQuizCommandParser. - 
    
QuizCommandParseridentifies the type of quiz command. (eg. quiz t/) - 
    
A
QuizCommandwith the respective predicate, in this caseTagContainsKeywordPredicateis created and returned toLogicManager - 
    
The
QuizCardwill be displayed on theUI. 
The sequence diagram below (Fig 1.4) shows the interactions between the Logic and model components for the quiz command.
(Figure 1.4: Quiz Command Sequence Diagram)

The diagram below (Fig 1.5) shows the activity diagram flow for the quiz command
(Figure 1.5: Quiz Command Activity Diagram)

Delete Feature (Jian Ling)
Implementation
This feature allows the user to delete a QAndA from the answer book. The flow of the execution of the delete command is shown below.
- 
    
User enters the input to delete a QAndA (eg.
delete 1) - 
    
The
LogicManagerexecutes this command, leading to the command being parsed byMedmoriserParserandDeleteCommandParser - 
    
After successful parsing,
DeleteCommand#execute(Model model)is called. This method checks for the following scenarios:- A quiz is currently in progress
 - The index entered by the user is out of bounds
 
If any of the scenarios above occur, a
CommandExceptionwill be thrown with their respective error messages. Othewise, a newCommandResultis returned, along with a success message that the specified QAndA has been successfully deleted 
The sequence diagram (Fig. 1.6) below shows the flow of the delete feature.
(Figure 1.6: Delete Command Sequence Diagram)

The activity diagram (Fig 1.7) below further shows the flow of the delete feature.
(Figure 1.7: Delete Command Activity Diagram)

List Feature (Jonathan Foo)
Implementation
This section elaborates on the implementation of the list feature.
- 
    
The user enters input to list all QAndAs.
 - 
    
The
Uicomponent calls theLogiccomponent to execute this.MedmoriserParserparses the command, resulting in aListCommandobject which is executed by theLogicManager. - 
    
This updates the
Modelto show all QAndAs in the answer book. - 
    
The result of this command execution is encapsulated as a
CommandResultobject which is passed back to theUi. - 
    
Uichecks theCommandResultobject and modifies the visibility of theAnswerlabel. In this case, the visibilty is set tohidden 
The sequence diagram below (Fig 1.8) shows the interactions between the Ui and Logic components for the list command.
(Figure 1.8: List Command Sequence Diagram)

The following activity diagram (Fig 1.9) summarises what happens when a user executes the list command.
(Figure 1.9: List Command Activity Diagram)

Design considerations:
- The 
Uicomponent was selected to perform the showing/hiding of answers as it already had access to the various components in the GUI, hence preventing further coupling between the different components. - We decided to use 
listrather thanlist allto show all questions and answers as we wanted to maintain the original functionality of thelistcommand. 
Documentation, logging, testing, configuration, dev-ops
Appendix: Requirements
Product scope
Target user profile:
- medical students with heavy content to memorise
 - has a need to manage and frequently revisit a significant number of questions and answers
 - has a need to refer to images and diagrams
 - prefer desktop apps over other types
 - finds typing with a keyboard faster than typing with smartphones or handwriting.
 - prefers typing to mouse interactions
 - is reasonably comfortable using CLI apps
 
Value proposition:
- Aggregate and organises contents and much faster than traditional methods.
 - Allows students to memorise contents more efficiently by continuously testing them. This way they can practice active recall.
 
User stories
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a … | I want to … | So that I can… | 
|---|---|---|---|
* * * | 
      new user | see usage instructions | refer to instructions when I forget how to use the App | 
* * * | 
      user | key in questions and answers | revise on the questions I keyed in | 
* * * | 
      user | delete a Q&A | remove entries that I no longer need | 
* * * | 
      user | edit existing questions and answers | make changes to the questions and answers | 
* * * | 
      user | see all the questions | have an overview of all the Q&As I have | 
* * | 
      user | find questions by keywords | locate the Q&A without having to go through the entire list of questions | 
* *  | 
      user | tag questions to its topics | organise the questions properly by topic | 
* | 
      organised user | archive questions I no longer need | keep my question book organised and updated | 
Use cases
(For all use cases below, the System is the Medmoriser and the Actor is the user, unless specified otherwise. Q&A stands for a question and answer pair)
Use case: UC01 - Add a Q&A
MSS
- 
    
User adds a new QAndA into the database
 - 
    
Medmoriser adds the new QAndA and displays a success message
Use case ends.
 
Extensions
- 
    
1a. The entered data is invalid
- 
        
1a1. Medmoriser displays an error message
Use case ends.
 
 - 
        
 
Use case: UC02 - View all QAndAs
MSS
- 
    
User requests to view all QAndAs
 - 
    
Medmoriser shows a list of QAndAs in the database
Use case ends.
 
Use case: UC03 - Delete a QAndA
MSS
- 
    
User requests to view all QAndAs
 - 
    
Medmoriser shows a list of QAndAs in the database
 - 
    
User requests to delete a QAndA at a specific index in the list
 - 
    
Medmoriser deletes the Q&A and displays success message
Use case ends
 
Extensions
- 
    
2a. The list is empty.
Use case ends.
 - 
    
3a. The given index is invalid.
- 
        
3a1. Medmoriser shows an error message.
Use case resumes at step 2.
 
 - 
        
 
Use case: UC04 - Add a tag to a QAndA
MSS
- 
    
User requests to view all QAndAs
 - 
    
Medmoriser shows a list of QAndAs in the database
 - 
    
User requests to add a tag to a QAndA at a specific index in the list
 - 
    
Medmoriser adds the specified tag to the QAndA and displays success message
Use case ends.
 
Extensions
- 
    
2a. The list is empty.
Use case ends.
 - 
    
3a. The given index is invalid.
- 
        
3a1. Medmoriser shows an error message.
Use case resumes at step 2.
 
 - 
        
 - 
    
3b. The given tag is invalid.
- 
        
3b1. Medmoriser shows an error message.
Use case resumes at step 2.
 
 - 
        
 
Use case: UC05 - Edit a QAndA
MSS
- 
    
User requests to view all QAndAs
 - 
    
Medmoriser shows a list of QAndAs in the database
 - 
    
User requests to edit a QAndA at a specific index in the list
 - 
    
Medmoriser edits the QAndA at the specified index according to the user’s new input and displays success message
Use case ends
 
Extensions
- 
    
2a. The list is empty.
Use case ends.
 - 
    
3a. The given index is invalid.
- 
        
3a1. Medmoriser shows an error message.
Use case resumes at step 2.
 
 - 
        
 - 
    
3b. The edit request is invalid
- 
        
3b1. Medmoriser shows an error message
Use case resumes at step 2.
 
 - 
        
 
Use case: UC06 - Find a QAndA
MSS
- 
    
User searches for a key word or phrase
 - 
    
Medmoriser shows a list of QAndAs with that specified word or phrase
Use case ends
 
Extensions
- 
    
2a. There are no QAndAs that contain the specified word or phrase
- 
        
2a1. Medmoriser displays message that no QAndAs found
Use case ends
 
 - 
        
 
{More to be added}
Non-Functional Requirements
- Data bank should be able to hold large number (500+) pairs of QAndAs without any sluggish performance for typical usage.
 - Users should be able to retrieve answers to a question with a single command
 - User should be able to add a QAndA easily and efficiently through a user-friendly GUI
 - Have a clean user interface when it comes to reviewing questions and answers
 
{More to be added}
Glossary
- QAndA: A set containing a question and answer
 - Question: A question belonging to a QAndA
 - Answer: An answer to a question, both of which belong to the same QAndA
 
Appendix: Instructions for manual testing
Given below are instructions to test the app manually.
Launch and shutdown
- 
    
Initial launch
- 
        
Download the jar file and copy into an empty folder
 - 
        
Double-click the jar file Expected: Shows the GUI with a set of sample QAndAs. The window size may not be optimum.
 
 - 
        
 - 
    
Saving window preferences
- 
        
Resize the window to an optimum size. Move the window to a different location. Close the window.
 - 
        
Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained. 
 - 
        
 
Finding a QAndA
- 
    
Find QAndAs based on keywords in the question
- 
        
Prerequisites: QAndA(s) with the word
heartin the question - 
        
Test case:
find q/heartExpected: QAndA(s) withheartin the question are shown. 
 - 
        
 - 
    
Find QAndAs based on keywords in the answer
- 
        
Prerequisites: 2 different QAndAs, 1 with the word
bloodin the answer and the other withrespiratory functionin the answer - 
        
Test case:
find a/blood, respiratory function
Expected: Both QAndAs with the corresponding keywords are shown. (i.e. the QAndA withbloodin the answer and the QAndA withrespiratory functionin the answer are both shown) 
 - 
        
 - 
    
Find QAndAs based on keywords in the tag
- 
        
Prerequisites: QAndA(s) with the tag
immune system - 
        
Test case:
find t/immune system
Expected: QAndA(s) with the tagimmune systemare shown. 
 - 
        
 
Quizzing
- 
    
Starting a quiz
- 
        
Prerequisites: QAndA(s) with the
hearttag. No QAndA with themissingtag. - 
        
Test case:
quiz t/heart
Expected: A card showing a QAndA with thehearttag appears. - 
        
Test case:
quiz t/missing
Expected: No QAndA is shown. Error message shown in the result box. 
 - 
        
 - 
    
Attempting a quiz
- 
        
Prerequisites: QAndA(s) with the
immune systemtag. Start the quiz by following step 2 in the previous test case (i.e.quiz t/immune system) - 
        
Test case:
answer white blood cell
Expected: The card displaying the quizzed QAndA now shows the correct answer to the question. The input answer is displayed in the result box. - 
        
End the quiz with
endquiz. Repeat step 1. Test case:white blood cell
Expected: The card displaying the quizzed QAndA remains unchanged. Error message shown in result box. 
 - 
        
 
endquiz and achieve the prerequisites when starting a new test case.
Deleting a QAndA
- 
    
Deleting a QAndA while all QAndAs are being shown
- 
        
Prerequisites: List all QAndAs using the
listcommand. Multiple QAndAs in the list. - 
        
Test case:
delete 1
Expected: First QAndA is deleted from the list. Details of the deleted QAndA shown in the result box. - 
        
Test case:
delete 0
Expected: No QAndA is deleted. Error details shown in the result box. - 
        
Other incorrect delete commands to try:
delete,delete x,...(where x is larger than the list size)
Expected: Similar to previous. 
 - 
        
 - 
    
Deleting QAndA while only certain QAndAs are being shown
- 
        
Prerequisites: Multiple QAndAs with the word
heartin the question. Find all QAndAs withheartin the question using thefind q/heartcommand. - 
        
Test case:
delete 2
Expected: Second QAndA is deleted from the list. Details of the deleted QAndA shown in the result box. The window continues to display the remaining QAndAs withheartin the question. 
 - 
        
 
Saving data
- 
    
Initial setup of data files
- 
        
Download the jar file and move it into an empty folder
 - 
        
Double-click the jar file.
Expected: Shows the GUI with a set of sample QAndAs. - 
        
Exit the app with the
exitcommand. 
 - 
        
 - 
    
Simulating a missing data file
- 
        
Locate the
datafolder and delete themedmoriser.jsonfile - 
        
Re-launch the app by double-clicking the jar file.
Expected: The app shows the GUI with the same set of sample QAndAs. A newmedmoriser.jsonfile is created in thedatafolder. 
 - 
        
 - 
    
Simulating a corrupted data file
- 
        
Locate the
datafolder and open themedmoriser.jsonfile with an editor of your choice. Delete all the data and replace it with random characters (e.g.abcdef123456), then save the file. - 
        
Re-launch the app by double-clicking the jar file.
Expected: Shows the GUI with no QAndAs. - 
        
Add a QAndA into the app. Exit the app with the
exitcommand. Expected: The random characters inmedmoriser.jsonare replaced with the json data of the new QAndA. 
 - 
        
 
Appendix: Effort
This section explains the difficulty level, challenges faced, effort required, and achievements of Medmoriser.
Making Medmoriser was particularly difficult as there were many challenges we faced along the way:
- There was a need to change a large portion of the AB3 code, as we had a completely different set of variables for Medmoriser. We had to do a lot of refactoring in the form of renaming class and attributes. The restrictions on fields in AB3 were also different from those in Medmoriser (eg. Person in AB3 cannot have special characters, but Question in Medmoriser can), and we had to edit those restrictions respectively.
 - Implementing a quizzing feature required a deep understanding of the design of AB3. Merely manipulating variables in existing code was not sufficient here, and we had to create many new classes such as 
QuizCommand,AnswerCommand,NextCommandandEndQuizCommand. We also had to come up with ways to keep track of the state of the application, such as whether the user is in an ongoing quiz, whether the user has entered an answer for a quiz question, and whether a quiz question has been asked before when choosing the next question to show the user in a quiz. There was not a need for this in AB3. - The numerous new classes created and enhancements to existing commands meant that a lot more effort was required to implement testing for Medmoriser. This is evident in our implementation of new test classes (eg. 
QuizCommandTest,QuizCommandParserTest,AnswerCommandTest,EndQuizTest, etc) and additional test cases in existing test classes (egFindCommandTest,ListCommandTest, etc). 
Despite the difficulties mentioned above, we managed to overcome them and come up with a fully functional product that we are proud of.