Developer Guide
Table of contents
- 1. Introduction
- 2. Setting up the Project
- 3. Design
- 4. Implementation
- 5. Logging
- 6. Documentation
- 7. Testing
- Appendix A: Product Scope
- Appendix B: User Stories
- Appendix C: Non functional Requirements
- Appendix D: Glossary
- Appendix E: Instructions for Manual Testing
1. Introduction
revisED is a CLI application that helps students to revise by allowing them to create flashcards, take quizzes, and keep track of their deadlines, tasks and any other important dates. The users can create different subjects, add different topics under a subject, and create different flashcards in the form of questions and answers under a topic. They can also take quizzes for the flashcards they have added and view the results.
This developer guide is for developers who wish to understand and/or develop reviseED further. This guide includes design, implementation, logging, testing, product scope, and other sections to help developers better understand the application.
Note the following symbols and formatting used in this document:
Symbols / Formatting | Meaning |
---|---|
📝️️ NOTE: | Important or additional information |
⚠️ WARNING: | Things to avoid or pay extra attention to |
✔️ TODO: | Things that should be but have not been done |
Grey highlight |
Code or terms related to the code/application |
2. Setting up the Project
This section guides you through the steps to setup the project on your computer.
📝️️ NOTE: This guide assumes you already have Java 11 or above installed on your computer. If you do not have it yet, follow the link to download and install it.
- Fork this repo and clone the fork to your computer. Alternatively, download the source code from here.
- Open a console in the folder where
build.gradle
resides, and run the commandgradlew.bat run
if you are using Windows or./gradlew run
if you are using Mac/Linux. - If the setup is successful, you should see the greeting screen:
> Task :run
Hello from
___________
| __ | _ \
____ ______ _____ ________ | |__| | | |
| __|/ __ \ \ / /| | / _____/ | __| | | |
| | | __/ \ \__/ / | | /_____ / | |__| |_| |
| | \___| \____/ |_|/_______/ |_____|_____/
____________________________________________________________
Hello! I'm revisED
____________________________________________________________
____________________________________________________________
Alright, What can I do for you?
____________________________________________________________
____________________________________________________________
Type help for all available commands
____________________________________________________________
Alternatively, if you are using IntelliJ, follow the first step above, then:
- Configure the Intellij for JDK 11, as described here.
- Import the project as a Gradle project, as described here.
- Locate and click the
run
task underTasks > application > run
in the Gradle tool window.
3. Design
This section describes how revisED has been designed so that developers can better understand the designing of the code, with the help of visual aids.
The application has been broken down into different levels so that users would find it easy to navigate from one level to the next one. There are three levels within the application, and their hierarchy is ranked as shown below:
- Main: This level edits the list of all the subjects present within the application and takes care of relevant commands
such as add subject, delete subject or find subject. The parser for this level is invoked in the
Revised
class. - Subject: This level is accessed through the
subject [NAMEOFSUBJECT]
command. The user would then look at the individual subjects and then would be able to add, delete, list or find either tasks or topics. The parser for this level is invoked in theAccessSubjectCommand
class. - Topic: This level is accessed through the
topic [NAMEOFTOPIC]
command. The user can add, delete or list flashcards in this level. The parser for this level is invoked in theAccessTopicCommand
class.
Exiting from the Topic level will result in the program running at the Subject level, while exiting from the Subject level allows the program to run at the Main level. The program can also access the Subject level from the main level, or the Topic level from the Subject level via user input.
Architecture
Figure 3 Architecture diagram for revisED.
The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.
Revised
is the Main class and is responsible for:
- Containing the
SubjectList
- Invoking
Parser
on the main level on loop until the user exits - Invoking
Storage
to save data when user exits
The rest of the App consists of six packages:
- card - main data structures that holds the most of the information of the application.
- command - handles the commands
- list - contains lists of classes in
card
- parser - parses instances of
Command
- ui - handles input and output
- storage - handles loading, saving, and exporting
More details for each package can be accessed in the sections below, or by clicking the links above.
3.1 Card Package
Figure 3.1 UML class diagram for card package. The quizcard package is omitted.
The card
package contains the main data structures that holds the most of the information of the application.
It contains:
Flashcard
class - contains aquestion
andanswer
Subject
class - contains aTopicList
,TaskList
, andResultList
Topic
class - contains a list ofFlashCards
quizcard
package - contains classes related to the quiz functionstaskcard
package - contains classes related to the task functions
Each of the classes in the card package contains getters and setters for its own attributes.
3.1.1 Quizcard Package
Figure 3.1.1 UML class diagram for the quizcard package
The quizcard
package stores the information relating to all quiz functionality in the application.
It also starts the quizes and handles the updating of results. It consists of 4 classes:
Quiz
class - abstract class in thequizcard
package. It contains:result
- theResult
of the quiz.
TopicQuiz
class - inherits from theQuiz
class and initiates the quiz for a topic. It contains:topic
- theTopic
that the quiz is on
SubjectQuiz
class - inherits from theQuiz
class and initiates the quiz for a subject. It contains:subject
- theSubject
that the quiz is on
Result
class - holds information regarding the results of a quiz. It has three class variables:score
is the user's current score for the quizmaxScore
is the maximum score for the quizdesciption
is the grade given to the user depending on their performance.
3.1.2 Taskcard Package
Figure 3.1.2 UML class diagram for taskcard package
The taskcard
package stores the information relating to all the tasks in the application. It consists of 4 classes:
Task
class - class that the other classes in this package inherits from. It contains:- description - name of the the task
- isDone - whether the task is done or not
Todo
class - inherits fromTask
Deadline
class - inherits fromTask
. Additionally, it contains:dateTime
- deadline of the task
Event
class - inherits fromTask
. Additionally, it contains:dateTime
- time of the event
3.2 command Package
The Command package consists of different classes that executes the various commands of the application due to user input,
and is split into 4 packages, flashcard, subject, task and topic, as well as an abstract command class, that is a superclass of the various classes in the different packages.
As mentioned in the introduction of the design segment of the developer guide, the program is split into 3 levels, namely the main level, the subject level, as well as the topic level.
The subjectcommand
package holds the information to allow the program to execute a user command at the main level, the topiccommand
package holds the information
to allow the program to execute a user command at the subject level, while the taskcommand
and flashcardcommand
packages holds the information to allow the program to execute a user command
- Command: In charge of reading the command and calling the relevant methods. The package itself holds
the following packages. The commands also have a method isExit to exit the current level the program is at.
Exiting from a level of the program will either up the program to run at a level of a higher level or end the program.
The levels in the program are mentioned in the introduction of the design segment of the developer guide.
- flashcardcommand
- subjectcommand
- topiccommand
- taskcommand
Each of the sub-packages hold multiple classes that are a subclass of the Command class, and contains:
- An execute command to execute the respective commands in their respective levels of the program
- An isExit method that checks if the command exits the level the program is currently running in AccessSubjectCommand and AccessTopicCommand both have an extra method goToSubject and goToTopic methods that allows the program to enter Subject level from the Main level, and to the Topic level from the Subject level respectively.
subjectcommand package
The subjectcommand
package holds all the necessary classes for executing methods at the main level. The Class that will be created and executed depends
on user input. A Class diagram of how the classes interact with each other in the subjectcommand package is shown below.
Figure 3.2.1 UML class diagram for subjectcommand package
The subjectcommand
package holds the following classes.
- AccessSubjectCommand
- AddSubjectCommand
- DeleteSubjectCommand
- ExitSubjectCommand
- ExportSubjectCommand
- FindSubjectCommand
- HelpSubjectCommand
- ListAllSubjectCommand
- ListSubjectCommand
- QuizSubjectCommand
- ResultSubjectCommand
- SorrySubjectCommand
- SubjectCommand
AccessSubjectCommand
The AccessSubjectCommand
class has 3 methods:
- execute()
- goToSubject()
- isExit()
and is mainly used for entering the Subject level from the Main Level. This occurs when
the execute() method of the AccessSubjectCommand
is first run. It first decodes the full command of the user input, then
accesses the subject level of the program. Different Subject class instances have different information contained in them, thus
there exists multiple subject levels of the program, each subject class having their own subject level in the program.
For example, if there are 2 subjects, like Maths and Science, then accessing the Subject level of the Maths instance is different from
accessing the Subject level of the Science Subject, since both subjects contain different information. Accessing the different subjects depend on user input, which
will be decoded in the execute() method in AccessSubjectCommand
. The execute() method will then run the goToSubject() command, that will access the information
available in the subject that is selected via user input.
The isExit() method determines whether the program exits. The AccessSubjectCommand
isExit() method is hard coded to return false since the command does not exit the code.
For more information of the implementation of the AccessCommand Class, refer to 4.8 Accessing subjects/topics implementation.
AddSubjectCommand
The execute() method of the AddSubjectCommand
decodes the user input, then adds a subject into the SubjectList, which title depends on the user input. For example, if the
user input is add Maths
, then the title of the Subject created in the SubjectList will be Maths. It also prints the title of the subject that
is added to the SubjectList.
The isExit() method determines whether the program exits. The AddSubjectCommand
isExit() method is hard coded to return false since the command does not exit the code.
For more information of the implementation of the AddCommand Class, refer to 4.7 Adding objects implementation .
DeleteSubjectCommand
The execute() method of the DeleteSubjectCommand
decodes the user input, then deletes a subject based on the index the Subject currently in the SubjectList.
For example, when the user input is delete 1
, the program decodes the input, and deletes the first Subject in the SubjectList, which is at index 0 of the SubjectList.
The isExit() method determines whether the program exits. The DeleteSubjectCommand
isExit() method is hard coded to return false since the command does not exit the code.
ExitSubjectCommand
The execute() method of the ExitSubjectCommand
does nothing, but needed since this method was implemented from an abstract class.
The isExit() method determines whether the program exits. The ExitSubjectCommand
isExit() method is hard coded to return true, so that when the isExit() command is run, the program
will exit.
ExportSubjectCommand
The execute() method of the ExportSubjectCommand
calls the export() method of the storage instance to export all
data to the disk storage.
The isExit() method determines whether the program exits. The ExportSubjectCommand
isExit() method is hard coded to return false, so that when the isExit() command is run, the program does not exit.
FindSubjectCommand
The execute() method of the FindSubjectCommand
decodes the user input, then find subjects whose title contains the keywords the user input into the program.
It then prints the title of the Subjects in the SubjectList whose title contains the keyword.
The isExit() method determines whether the program exits. The FindSubjectCommand
isExit() method is hard coded to return false since the command does not exit the code.
HelpSubjectCommand
The execute() method of the HelpSubjectCommand
prints a list of available commands at the main level of the program,
for the user to understand the format of inputs, as well as types of input needed for execution.
The isExit() method determines whether the program exits. The HelpSubjectCommand
isExit() method is hard coded to return false since the command does not exit the code.
ListAllSubjectCommand
The execute() method of the ListAllSubjectCommand
groups different tasks and flashcards under each topic, and different topics under each subject, then prints an organized list
of all the subjects, topics, tasks and flashcards.
The isExit() method determines whether the program exits. The ListAllSubjectCommand
isExit() method is hard coded to return false since the command does not exit the code.
ListSubjectCommand
The execute() method of the ListAllSubjectCommand
prints a list of all subjects in the SubjectList instance.
The isExit() method determines whether the program exits. The ListSubjectCommand
isExit() method is hard coded to return false since the command does not exit the code.
QuizSubjectCommand
The execute() method of the QuizSubjectCommand
decodes the user input, and initiates a quiz for the subject that the user requested for.
For example, if the user enters quiz Maths
, then the application starts a quiz for the Maths subject.
The isExit() method determines whether the program exits. The QuizSubjectCommand
isExit() method is hard coded to return false since the command does not exit the code.
ResultSubjectCommand
The execute() method of the ResultSubjectCommand
decodes the user input, and prints out the results of previous SubjectQuizzes for the subject.
For example, if the user enters results Maths
, then the application prints out the results of the previous SubjectQuizzes attempted by the user for the Maths subject.
The isExit() method determines whether the program exits. The ResultSubjectCommand
isExit() method is hard coded to return false since the command does not exit the code.
SorrySubjectCommand
The execute() method of the SorrySubjectCommand
throws a FailedParseException
, meaning the parser has failed to decode the user input. Then, the exception will result in the Ui printing the error back
to the user.
The isExit() method determines whether the program exits. The SorrySubjectCommand
isExit() method is hard coded to return false since the command does not exit the code.
SubjectCommand
The SubjectCommand
class is an abstract class that contains a abstract execute() method as well as a isExit() method, and is a super class for all the commands in the subjectcommand
package. This is to ensure that all other commands in the subjectcommand package can have the same method calls, and that execute() can be called on a SubjectCommand class,
even if they are a subclass of the SubjectCommand class.
topiccommand package
The topiccommand
package holds all the necessary classes for executing methods at the subject level. The Class that will be created and executed depends
on user input. A Class diagram of how the classes interact with each other in the topiccommand package is shown below.
Figure 3.2.2 UML class diagram for topiccommand package
The topiccommand
package holds the following classes.
- AccessTopicCommand
- AddTopicCommand
- DeleteTopicCommand
- ExitTopicCommand
- FindTopicCommand
- HelpTopicCommand
- ListAllTopicCommand
- ListTopicCommand
- QuizTopicCommand
- ResultTopicCommand
- SorryTopicCommand
- TopicCommand
All classes in the topiccommand
package works the same way as the ones found in the subjectcommand
package, but it deals with the Topic
class instead of the Subject
class. Notably,
there is a change in parameters, as the TopicCommand
classes is missing the Storage parameter. This is due to the absence of ExportCommand
in the TopicCommands, since we did not implement
the export command for the subject level. The rest of the TopicCommands do not need the Storage parameter since none of the execute() methods of the Commands require it.
For more information of the subjectcommand
package, please refer to SubjectCommand .
taskcommand package
The taskcommand
package holds all the necessary classes for executing methods at the subject level. The Class that will be created and executed depends
on user input. A Class diagram of how the classes interact with each other in the taskcommand package is shown below.
Figure 3.2.3 UML class diagram for taskcommand package
The taskcommand
package holds the following classes.
- AddDeadlineCommand
- AddEventCommand
- AddTodoCommand
- DeleteTaskCommand
- DoneTaskCommand
- FindTaskCommand
- TaskCommand
The Classes in the taskcommand
package is different from the ones found in the other command packages. This is because all the taskcommand
Classes are parsed by the TopicParser
, since they work at the
Subject level, similar to the Topic Commands. Thus, they do not have their own Exit Commands, List Commands and Help Commands, since all those are handled by the Topic Commands.
There are 3 different Add Task Commands, due to the 3 different formats of the Tasks that the user can save, namely Event
, Deadline
and Todo
. The rest of the Task Commands have similar functionality to
the ones found in the subjectcommand
package. For more information of the subjectcommand
package, please refer to SubjectCommand .
flashcardcommand package
The flashcardcommand
package holds all the necessary classes for executing methods at the topic level. The Class that will be created and executed depends
on user input. A Class diagram of how the classes interact with each other in the flashcardcommand package is shown below.
Figure 3.2.4 UML class diagram for flashcardcommand package
The flashcardcommand
package holds the following classes.
- AddFlashcardCommand
- DeleteFlashcardCommand
- ExitFlashcardCommand
- HelpFlashcardCommand
- ListAllFlashcardCommand
- ListFlashcardCommand
- SorryFlashcardCommand
- FlashcardCommand
All classes in the Flashcardcommand
package works the same way as the ones found in the subjectcommand
package, but it deals with the Flashcard
class instead of the Subject
class. Notably,
there is a change in parameters, as the FlashcardCommand
classes is missing the Storage parameter. This is due to the absence of ExportCommand
in the FlashcardCommands, since we did not implement
the export command for the subject level. The rest of the FlashcardCommands do not need the Storage parameter since none of the execute() methods of the Commands require it. Additionally, the flashcardcommand
package is also missing a few classes such as the QuizCommand
, ResultCommand
and FindCommand
classes. This is due to the fact that at the topic level, there are only flashcards in each topic, and it would not
make sense to quiz one flashcard at a time, thus the absence of the implementation. For more information of the subjectcommand
package, please refer to SubjectCommand .
3.3 List Package
This package contains different list classes used for managing a list of different card package objects. They are used to abstract the extra processing needed (if any) before or after interacting with the underlying list. The relationship between the classes is shown below.
Figure 3.3.1 UML class diagram for list package
✔️ TODO: Delete method should also be implemented here (just like the add method) and be called to do the delete operations instead of doing it directly through the underlying list for better cohesion.
✔️ TODO: FlashcardList should also be created to manage the list of flashcards instead of directly operate on the ArrayList for better cohesion.
3.4 Parser Package
The parser package consists of all the classes that are necessary to parse the user inputs. These classes are responsible to understand what the useer has input, and take the necessary action.
This package consists of three classes:
-SubjectParser: This class parses all the user inputs at the main level. It deals with all the commands that relate to working with subjects, such as add and delete subjects.
-TopicParser: This class parses all the user inputs at the subject level. It deals with all the commands that relate to working with topics and tasks, such as adding and deleting topics or tasks.
-FlashcardParser: This class parses all the user inputs at the topic level. It deals with all the commands that relate to working with flashcards, such as adding and deleting flashcards.
The classes in this package directly communicate with the command package in order to execute the relevant commands.
3.5 Ui Package
The ui package deals with handling user input and printing all the system outputs on the command line. It consists of one class, Ui. This class is responsible to print all messages to the command line. The command classes call the methods in this class in order to print anything on the command line. This class also deals with printing any messages when exceptions are encountered.
3.6 Storage Package
There are two classes inside this package, both of which are inside Storage.java
. The following diagram shows the
relationship between the two classes.
Figure 3.6.1 UML class diagram for storage package
StorageBuilder
StorageBuilder
class is a static inner class of the Storage
class. It follows the builder pattern and its sole purpose
is to create Storage
instances. The builder pattern is used to deal
with the decrease in clarity due to the increase of the number parameters. Every instance of the Storage
class should
be created through StorageBuilder
, and this is enforced by disabling the public constructor of the Storage
class.
Storage
Storage
class handles every operation that involves data storage, including storing, loading, and exporting of
application data. Storing of data only happens when the application exits while loading of data only happens
when the application launches. On the other hand, exporting of data happens when the user runs export
command.
4. Implementation
This section describes some noteworthy details on how certain features are implemented.
4.1 Storing data
Storage
class stores the data following the same logical structure (subject -> topic) of the application to
make the stored data more presentable to the user. Subject
and Topic
data are stored as nested directories, while
Flashcard
and Result
data are stored in JSON format so that they are readable
to the users and allows them to change the saved data manually.
Gson library is used to create the json files.
Task
data are stored differently as text files due to
legacy reason, but they are also readable and can be changed manually as well.
📝️️ NOTE: If the users modify the file contents with wrong syntax, the data in the affected files will not be loaded and empty data will be returned instead so that the application can still run.
An example of the structure mentioned is shown in the figure below.
data --> Data main folder └── CS2113T --> CS2113T subject folder ├── Java --> Java topic folder under CS2113T subject │ ├── topicResults.json │ └── flashcards.json ├── subjectResults.json └── tasks.txt
Figure 4.1.1 Sample directory structure
File formats
One tasks.txt
file is created under each subject folder, storing the tasks (Todo, Event, Deadline) data under
that subject. An example of the file content is shown below.
T | 1 | someTodoTask --> Todo task D | 0 | someDeadlineTask | 11:59 PM 20 Dec 2020 --> Deadline task E | 0 | someEventTask | 1:00 PM 10 Nov 2020 --> Event task
Figure 4.1.2 Sample tasks.txt content
The first column of data shows the type of task, where T corresponds to Todo
task, D corresponds to Deadline
task, and E corresponds to Event
task. The second column shows if a task is completed, where 0 means not completed
while 1 means completed. The third column shows the name of a task. Lastly, the fourth column shows the time and date of
a deadline or event task.
Moving on, one subjectResults.json
is created under each subject folder, and one topicResults.json
is created
under each topic folder. subjectResults.json
stores the quiz results the users have obtained from doing quizzes under
a subject, while topicResults.json
stores the quiz results the users have obtained from doing quizzes under a topic.
Both of the files have the same content format, and an example of
the file content is shown below.
[ { --> Result record 1 "score": 1.0, --> Score obtained "maxScore": 1.0, --> Maximum score that can be obtained "description": "Excellent" --> Result description }, { --> Result record 2 ... }, ... ]
Figure 4.1.3 Sample subjectResults.json content
This content format is a result of converting a list of Result
data into json form.
Lastly, one flashcards.json
file is created under each topic folder, storing all the flashcard data the users
have added under a specific subject and topic. An example of the file content is shown below.
[ { --> Flashcard 1 "question": "x + y = 4. y = ? ", "answer": "4 - x" }, { --> Flashcard 2 ... }, ... ]
Figure 4.1.4 Sample flashcard.json content
Similarly, this content format is a result of converting a list of Flashcard
data into json form.
Behavior
The implementation stores the data in a cascading manner, meaning that when a call to save topics is made, all the data under the topics will be saved. Similarly, when a call to save subjects is made, all the data under the subjects including topics will be saved. The behavior mentioned is shown in the diagram below.
Figure 4.1.5 UML sequence diagram for storing subjects
Figure 4.1.6 UML sequence diagram for storing topics
As can be seen in figure 4.1.5, all the data is deleted from the disk before saving of data takes place. It is implemented this way to make sure the deletion of a subject or topic by the user is also saved. Otherwise, the subject or topic will not be deleted since the rest of the method calls only replace or create data.
✔️ TODO: As the amount of data grows larger, this saving algorithm can get very slow since it only saves the data when the application exits, not to mention the (most of the time) needless deletion of all data before each save. To speed up the process, the implementation can be changed such that data is saved right after each user command that involves data manipulation.
4.2 Loading data
For the data stored in json format, they are loaded using the same Gson
library, whereas for the data tasks.txt
, they are parsed line by line and converted into corresponding Task
objects.
The loading of data follows a similar cascading manner as saving, as can be seen in the diagram below.
Figure 4.2.1 UML sequence diagram for loading subjects
Figure 4.2.2 UML sequence diagram for loading topics
Note that only Subject
and Topic
data are sorted; Result
, Flashcard
, and Task
data still follow the added
order. This is because subjects and topics are stored as directories, and the order of the directories loaded is not
guaranteed by the Java, so the sorting is just to fix the inconsistency of the order. The rest of the data, on the
other hand, is guarenteed to have the same order every time they are loaded, so they are not sorted.
4.3 Exporting data
The user can export all data of the application to the pre-defined export/data.json
in the same directory where
the application runs. An example of the file content is shown below.
[ { --> Subject 1 "title": "CS2113T", "topics": { "topics": [ --> Topics under CS2113T subject { --> Topic 1 "title": "Java", "flashcards": [same as the content of flashcards.json], --> Flashcards under Java topic "results": { "resultList": [same as the content of topicResults.json] --> Results under Java topic } }, ... ] }, "tasks": { --> Tasks under CS2113T subject "taskList": [ { --> Task 1 "description": "someTodoTask", "isDone": false }, { --> Task 2 "dateTime": { "date": { "year": 2020, "month": 12, "day": 20 }, "time": { "hour": 23, "minute": 59, "second": 0, "nano": 0 } }, "description": "someDeadlineTask", "isDone": false }, ... ] }, "results": { "resultList": [same as the content of subjectResults.json] --> Results under CS2113T subject } }, ... --> More subjects ]
Figure 4.3.1 Sample data.json content
This content format is a result of converting a list of Subject
objects with populated data into json form.
✔️ TODO: Importing of the exported data is not yet supported, and it would make sense to implement it in the future versions. However, it may not be straightforward as type conversion is needed to convert the data into the right types (refer to Gson documentation for more details).
4.4 Parsing Commands
The parser package contains the following three classes which are responsible for making sense of the user input.
SubjectParser
The SubjectParser class parses the user inputs at the main level. The diagram below shows how the SubjectParser class is implemented.
Figure 4.4.1 UML sequence diagram for subject parser
FlashcardParser
The FlashcardParser class parses the user inputs at the topic level. The diagram below shows how the FlashcardParser class is implemented.
Figure 4.4.2 UML sequence diagram for flashcard parser
TopicParser
The TopicParser class parses the user inputs at the topic level. This class is implemented in a similar manner as the FlashcardParser and SubjectParser classes.
4.5 Quiz
The abstract quiz class contains a checkAnswer() method that checks the answer that the user had given with the correct answer of the quiz.
If the user enters the correct answer, the existing score is incremented by one. Else, the contents of the flashcards and the incorrect answer provided by
the user are transferred to the incorrectAnswers
list. Once the user finished the quiz, the application would print the
questions that the users did not answer correctly, along the the answer that was provided by the user.
Initiating a subject quiz
You can start a subject quiz by entering quiz NAMEOFSUBJECT
. Subsequently, the application retrieves the QuizSubjectCommand
after parsing the command and calls for the startQuiz
method.
The startQuiz
method calls for the setupQuiz
method checks for the presence of topics or flashcards. Else, the application throws the NoTopicException
for the former, and the
NoFlashcardException
for the latter. If the topics have flashcards, then these are transferred to the
SubjectQuiz
class, while the maximum score of the quiz is set to be the total number of flashcards in the list of flashcards
present in the SubjectQuiz
class .
The application now returns to the startQuiz
method and the current score of the quiz is set to zero. Subsequently, the
application begins printing the questions from the flashcards and checks the answer that you provide. If you want to stop the
quiz, use the stop
command. The application will then print out the score that you obtain. If you complete the quiz
then the application not only prints the score, but it also prints the incorrect answers from the quiz.
The following diagram shows how you can initiate the quiz for the Maths Subject.
Figure 4.5.1 UML sequence diagram for subject quiz
Initiating a topic quiz
Provided that you have used the subject NAMEOFSUBJECT
command to access a subject,you can start a subject quiz by entering quiz NAMEOFTOPIC
. Subsequently, the application retrieves the QuizTopicCommand
after parsing the command and calls for the startQuiz
method. This method class for the setupQuiz
method, which throws the NoFlashcardException
for when the topic does not
have any flashcards. The application then returns back to the startQuiz
method. The implementation of the startQuiz
method is similar
to that of the SubjectQuiz class.
The following diagram shows how you can initiate the quiz for a topic speed under the Maths subject.
Figure 4.5.2 UML sequence diagram for topic quiz
📝️ NOTE: For both the subject quiz and the topic quiz, the application only prints out the incorrectAnswer if the user has completed the quiz. If the user stops the quiz without completing it, then the application will only show the score obtained by the user.
4.6 Sorting tasks
The application sorts the tasks according to their dates and times. Tasks which are due soon are placed at the front
while tasks which are due later are placed at the end of the task list. Todo
tasks are placed at the end of the tasklist.
Their LocalDateTime
variables are assigned the LocalDateTimeMax
value. This is to ensure that the sorting can be done
for all tasks.
4.7 Results feature
Updating results
The updateResult
method in the Result
class updates the result for a given quiz by setting the score and the description.
There are three categories of descriptions: Fail
for getting a score which is lesser than half of the maximum score, Pass
for obtaining a score above half of the maximum score and Excellent
for getting the maximum score in a quiz.
4.7.1 Printing out the results for a subject
For the results of a subject , the printSubjectResults
method in the Ui class checks if there are any results of previous subject quizzes for that particular subject.
Figure 4.7.1 UML sequence diagram for requesting results of the Maths subject
4.7.2 Printing out the results for a topic
For the results of a topic, the printTopicResults
method checks if the topic has any any results from previous topic quizzes.
The user has to access the particular subject level to use this command.
Figure 4.7.2 UML sequence diagram for requesting results of the Speed topic of the Maths subject
4.8 Adding objects
Each of the add commands have an execute() method. The execute() method for AddSubjectCommand add subjects into the subject list, the execute() method for AddTopicCommand add topics in a subject, while the execute() method for AddTodoCommand, AddDeadlineCommand and AddEventCommand adds tasks in a subject. subject.
Adding a subject
You can add a subject by entering add [SUBJECT_NAME]
. The subject will be added to a SubjectList
created when the program initialises.
After the program initialises, the program will ask for user input. The Ui
will read the user input using the readCommand() method, then the
the SubjectParser
will parse the command. Since the user input is add [TOPIC_NAME]
, the program will register it as a command to add a Subject
,
and will create a new AddSubjectCommand
. This AddSubjectCommand
is then passed back to the main function, where its execute() method will run.
The execute method decodes the user input. If the [SUBJECT_NAME]
is not a title of another Subject
already on the list, it will create a new Subject
,
and add that new Subject
created into the SubjectList
that was created during initialisation of the program. The Ui
will then print the adding of the
Subject
into the list. The program then returns to the main function, where it waits for next user input.
A Sequence diagram of adding a Subject
Maths is shown below.
Figure 4.8.1 UML sequence diagram for adding a subject
Adding a topic/task
you can add a Topic
by entering add [TOPIC_NAME]
. Additionally, you can add a Todo
task by entering todo [DESCRIPTION]
, add a Deadline
task by entering deadline [DESCRIPTION] /by [TIME]
, and add an Event
task by entering event [DESCRIPTION] /at [TIME]
. This command can only
be entered in the subject level of the program, which can be accessed using the command subject [SUBJECT_NAME]
. The documentation of the
implementation and how to access a subject can be found in 4.8 Accessing subjects/topics implementation.
Otherwise, adding topics and tasks follows the same implementation as adding a subject.
4.9 Accessing levels
Each of the access commands have an execute() method and a goToSubject()/goToTopic() method. The AccessSubjectCommand class allows users to access the subject level of a subject specified in the user input from the main level, while the AccessTopicCommand class allows users to access the topic level of a topic specified in the user input from a subject level.
Accessing a subject
You can access a subject by entering subject [SUBJECT_NAME]
. The subject needs to be a subject that already exists in the list, and you can
add the Subject
into the SubjectList
by using the add [SUBJECT_NAME]
feature, elaborated further in 4.7 Adding objects implementation.
For example, after adding a Subject
CS2101, the CS2101 Subject
can be accessed by entering access CS2101
. The application first reads the command using
the Ui class, then parses the user input using the SubjectParser
class, similar to adding a subject. The program will register the user input as a command to
access a subject. The SubjectParser will create a new AccessSubjectCommand
class, and this class will be returned to the main function.
The main program will run the execute() method of AccessSubjectCommand
. The execute() method checks for subjects in the SubjectList
whose title
matches the [SUBJECT_NAME]
, and if a subject matches, the subject will be passed as a parameter to the goToSubject() method. The goToSubject() method will then
have a loop that reads user inputs and parse these inputs to create new TopicCommand
or TaskCommand
classes to execute.
The sequence diagram of accessing a Subject
Maths is shown below.
Figure 4.9.1 UML sequence diagram for accessing a subject
Accessing a Topic
You can access a topic by entering topic [TOPIC_NAME]
. The topic needs to be a topic that already exists in the list, and you can
add the Topic
into the TopicList
of a Subject
by using the adding a topic feature, elaborated further in 4.7 Adding objects implementation.
4.10 list all
command
While the syntax of the list all
command is the same on the main, subject and topic levels,
there are 3 separate ListAllXYZCommands for each level. Although all 3 commands classes call Ui.printAll(subjects,activeSubject,activeTopic)
,
the 3 classes are kept separate so that printAll()
can recognise what object the user is accessing.
The following sequence diagram shows how you can proccess the list all
command from the subject level.
Figure 4.9.1 UML sequence diagram for list all at topic level
If the list all
command is given at the topic level, printTreeTopic()
will check if each topic is the active topic each loop,
instead of Ui.printAll
checking each subject.
📝️ NOTE: This command uses unicode characters such as "├" and "└". You may consider changing the characters to ASCII characters only for the sake of compatibility.
5. Logging
We use java.util.logging package for logging. Whenever you need to use logging in a class, add this line
java
private static final Logger logger = Logger.getLogger(CurrentClass.class.getName());
to the start of the class to get a logger instance,
where CurrentClass
is replaced by the class name you are adding the logger to.
Subsequently, you can use the logger instance created to start logging. To learn more about
how logging works, read the official logging documentation.
The current configuration logs all the messages with log levels above FINE
into a file (revisED.log
) in the same
directory where the application is run. You can find more details about the logging configurations (and change them or add more)
in src/main/resources/logging.properties
.
For consistency, you should only change the behavior of logging via this file.
6. Documentation
All project documentations are put under the /docs
folder. The following tools are used to write the documentations:
To learn how set the documentation website up and maintain it, follow the guide Using Jekyll for project documentation.
To convert the documents to PDF files for distribution, follow the guide Saving web documents as PDF files.
7. Testing
This section describes different types of tests used in the application and the ways to carry them out.
7.1 JUnit Tests
We use JUnit to write all unit tests and integration tests for the project. If you are new to JUnit, refer to the JUnit Tutorial.
All the JUnit Tests are located under src/test
folder. To run all the tests available in the project,
open a console in the project root directory and run gradlew.bat test
if you are using Windows or ./gradlew test
if
you are using Mac/Linux.
Alternatively, you can run the test
task under Tasks > verification > test
in the Gradle tool window if
you are using IntelliJ.
7.2 I/O Redirection Tests
We use I/O redirection to test the actual output of the application against the expected output using a set of different inputs.
To run the test, open a console in the text-ui-test
folder under the project root and run runtest.bat
if you
are using Windows or ./runtest.sh
if you are using Mac/Linux. If the test is successful,
you will see the following message in the last line of the output.
Test passed!
If the test fails, you will instead see the following message in the last line of the output.
Test failed!
To see what goes wrong, you can compare the content of ACTUAL.txt
and the content of EXPECTED.txt
inside the same folder,
where ACTUAL.txt
contains the actual output of the application and EXPECTED.txt
shows the expected output of the
application given the inputs.
📝️️ NOTE: You can change the inputs in
input.txt
and the expected output inEXPECTED.txt
if you would like to test more aspects of the application or if the input/expected output changes due to code modification.
7.3 Checkstyle
We use Checkstyle
to check if all the developers comply to the coding standards. The rules and configurations can be found
in checkstyle.xml
under config/checkstyle
folder in the project root. Refer to the official documentation
to learn more about how to configure the rules.
To run the checks, open a console in the project root directory and run gradlew.bat checkstyleMain
if you are using Windows
or ./gradlew checkstyleMain
if you are using Mac/Linux.
Alternatively, you can run the checkstyleMain
task under Tasks > other > checkstyleMain
in the Gradle tool window if
you are using IntelliJ.
Appendix A: Product scope
This section describes the scope of the application. To be specific, the target audience and the uses and benefits of this application.
Target user profile
The targeted audience are university students , aged 18 - 25 who have access to a computer. The students must be familiar with applications that run on the command-line interface. Currently, this application is created for students who study in Singaporean universities.
Value proposition
This application aims to help students to keep track of their revision. Students should be able to revise their subjects effectively through this application by adding various questions and answers in the form of flashcards. After that, students can refer to the flashcards to revise the subjects. Furthermore, they can take quizzes and see if they grasp the topics or subjects well enough to attend their school based exams.
Students who find it hard to keep track of their assignments would also find this application useful since it lets the students add their tasks. The application then reminds the students regarding the upcoming tasks, which would prompt the students to prepare them.
Students who find it difficult to organise would find this app useful since it offers a one stop solution to manage both their revision and their upcoming tasks .
Appendix B: User Stories
This section summarises various user stories of this application in the table below.
Version | As a ... | I want to ... | So that I ... |
---|---|---|---|
v1.0 | new user | add a flash card intuitively | don't get put off by learning a new program |
v1.0 | long time user | categorize the flashcards to different categories | know where to look for which flashcard |
v1.0 | organised person | see neat UI and flashcard organization | will want to use the program |
v1.0 | student | revise all my notes for different subjects | do not have to use multiple applications/websites to revise |
v1.0 | long time user | add flashcards efficiently | can save time when need to add multiple flashcards |
v1.0 | long time user | find a to-do item by name | can locate a to-do without having to go through the entire list |
v1.0 | student | do quizzes on the flashcards added | can know how much I remember the content |
v2.0 | forgetful student | be notified of assignments which are due in a week | do not forget them |
v2.0 | new user | see usage instructions | can refer to them when I forget how to use the application |
v2.0 | CS student | export all data into a readable format | can import the data into another application I made |
v2.0 | normal user | be able to view my data saved on the disk easily | can do modify the data without launching the app |
v2.0 | long time user | see all the subjects, topics, and number of flashcards I have added | know what I have added |
Appendix C: Non-Functional Requirements
The following are the requirements that the application should satisfy:
- The application should be easily maintainable when bugs and errors occur.
- The application should be scalable for possible future expansion of the project.
- The application should run on any mainstream OS as long as it has Java 11 or above installed.
- Application data should be portable so that it can be transferred between devices.
- The application should be easy to use or come with a detailed user guide/help for better user experience.
- The application should not crash when invalid or malicious user input is received.
- Users should be allowed to modify the saved data manually without causing disruption to the application operations.
Appendix D: Glossary
A
AccessSubjectCommand
- A command in the subjectcommand package which returns the subject that the user wants to access.AccessTopicCommand
- A command in the topiccommand package which returns the topic that the user wants to access.AddDeadlineCommand
- A command in the taskcommand package which adds a deadline task in the application.AddEventCommand
- A command in the taskcommand package which adds an event task to the application.AddFlashcardCommand
- A command in the flashcardcommand package which adds a flashcard in the application.AddSubjectCommand
- A command in the subjectcommand package which adds a subject to the application.AddTodoCommand
- A command in the taskcommand package which adds a todo task in the application.AddTopicCommand
- A command in the topiccommand package which adds a topic to the application.- Application - Refers to the revisED application which the user is using.
- attributes - variables in a class
B
BaseList
- An abstract class in the list package which all others lists inherit from.- Builder Pattern - A methodology used in the Storage class to ensure that the clarity does not decrease even if the number of parameters increase.
C
card
- Package which contains the quizcard package, task package and the Flashcard,Topic and Subject classes.- Checkstyle - Tool that checks the coding standards in the application.
- CLI - Command Line Interface
Command
- An abstract class in the command package which is inherited by all the command classes.command
- A package which holds the 4 command packages: subjectcommand,topiccommand,taskcommand,flashcardcommand. This package is in charge of returning the relevant subject,task,topic or flashcard .
D
DataLoadingException
- An exception thrown if the application is not able to load data.DateTime
- A variable in Event and Deadline classes which tracks the time and date at which the task has to be completed.Deadline
- A class in the taskcard package which refers to a task with a deadline. Inherits from the Task class.DeleteFlashcardCommand
- A command in the flashcardcommand package which deletes a flashcard from the application.DeleteSubjectCommand
- A command in the subjectcommand package which deletes a subject from the application.DeleteTaskCommand
- A command in the taskcommand package which deletes a task from the application.DeleteTopicCommand
- A command in the topiccommand package which deletes a topic from the application.description
- A variable in the Result class which describes the grade obtained during a quiz.description
- A variable in the Task class which describes the task to be completed.
E
Event
- A class in the taskcard package which refers to an event. Inherits from the Task class.Excellent
- A description for a quiz present in the Result class which states that the user obtained full marks for the quiz.Exception
- A class which holds conditions that the application would throw in the event that the input entered is incorrect.exception
- A package which holds all the exceptions used in the application. These exceptions are delcared as individual classes, all extending the Exception class.execute
- A command in Command classes which executes the required action by the command.ExitFlashcardCommand
- A command in the flashcardcommand package which allows the user to exit the topic level to return to the subject level.ExitSubjectCommand
- A command in the subjectcommand package which allows the user to exit the application.ExitTaskCommand
- A command in the taskcommand package which allows the user to exit the subject level to return to the main level.ExitTopicCommand
- A command in the topiccommand package which allows the user to exit the subject level to return to the main level.export
- A User Command to export the data to external file.
F
Fail
- A description for a quiz which states that the user failed the quiz.FailedParseException
- An exception thrown in the SorrySubjectCommand if the application is not able to read the commands.FINE
- A log level, which indicates the severity of the message.Flashcard
- A class in the card package which instantiates the flashcard object.Contains the question and answer feature of the flashcard.FlashcardCommand
- An abstract class that is inherited by all the other FlashcardCommand classes in the FlashCardCommand package.flashcardcommand
- A package which holds the different FlashcardCommand classes.flashcardexception
- A package which holds all the exceptions for methods related to flashcard operations.FlashcardParser
- A class in the parser package which reads the user commands to call the relevant Flashcard command.FindSubjectCommand
- A command in the subjectcommand package which finds the subject which the user requested for.FindTaskCommand
- A command in the taskcommand package which finds the task which the user requested for.FindTopicCommand
- A command in the topiccommand package which finds the topic which the user requested for.
G
- GSON - Used to create the Json files in the external data file.
goToSubject
- A method in the AccessSubjectCommand class which allows the application to transition to the Subject Level from the main level.goToTopic
- A method in the AccessTopicCommand class which allows the application to transfer from the Subject Level to the Topic Level.- GRADLE - An automated tool to build and compile the application.
H
HelpSubjectCommand
- A command in the subjectcommand package which lists all the commands in the Main level.HelpTopicCommand
- A command in the topiccommand package which lists all the commands in the Subject level.
I
isExit
- A method which checks if the user wants to change levels/exit application. This method is implemented in all the command classes.incorrectAnswers
- List present in the Quiz class which stores the questions that the user answered incorrectly, along with the answer provided by the user and the correct answer.InvalidFlashcardException
- An exception thrown if a flashcard is not created using the question ; answer format.InvalidSubjectException
- An exception that is thrown if the user does not add a title of a subject for the commands in the main level.InvalidTopicException
- An exception thrown if the TopicCommands are used solely without a topic.- I/O - Input/Output
J
- Jekyll - A software used by Github to create websites.
- JSON - Javascript Object Notation. A form of data representation used in the external data files.
- JUnit - A testing framework in Java that runs automated tests.
L
list
- A package which holds all the lists used in the application.ListAllFlashcardCommand
- A command in the flashcardcommand package which lists all the items in the application in the topic level.ListAllSubjectCommand
- A command in the subjectcommand package which all the items in the application.ListAllTopicCommand
- A command in the topiccommand package which prints all the topics in the Subject level.ListFlashcardCommand
- A command in the flashcardcommand package which lists all the flashcards in the application.ListSubjectCommand
- A command in the subjectcommand package which lists all the subjects in the application.ListTaskCommand
- A command in the taskcommand packagewhich lists all the tasks in the application.ListTopicCommand
- A command in the topiccommand package which lists all the topics and tasks in the application.LocalDateTime
- A class in Java which contains both the time and date of a given task.Used in Event and Deadline classes.LocalDateTimeMax
- Maximum time available in the LocalDateTime library.loadFlashcards
- Method in Storage class which loads the flashcards into the application.loadResults
- Method in Storage class which loads the results into the application.loadTasks
- Method in Storage class which loads the tasks into the applicationloadTopics
- Method in Storage class which loads the topics into the application.Logging
- Procedure of writing information to an external file, to track the flow of the program.
M
maxScore
- Maximum score obtainable from a quiz.Present in the Result class.- Markdown - Syntax used in Github.
N
NoFlashcardException
- An exception thrown if a quiz is initiated for a subject or topic without flashcards.NoSubjectException
- An exception thrown if the user requests for a subject that is not present in the application.NoTopicException
- An exception thrown if the user requests for a topic that has not been added to the application.
P
parser
- A package which parses the user commands and initialises the necessary topics,subjects or tasks.Pass
- A description for a quiz which states that the user passed the quiz.Present in the Result class.- PlantUML - Software used to create UML diagrams.
printScore
- Method in SubjectQuiz and TopicQuiz classes which prints out the score and the incorrect answers from a quiz.
Q
Quiz
- An abstract class that holds the result, list of flashcards and a list of incorrectAnswers for the SubjectQuiz class and the TopicQuiz class to inherit from.quizcard
- Package which contains the Quiz,Result,SubjectQuiz,TopicQuiz classes.QuizSubjectCommand
- A command in the subjectcommand package which initiates a quiz for a subject.QuizTopicCommand
- A command in the topiccommand package which initiates a quiz for a topic.
R
RepeatedFlashcardException
- An exception thrown if the user tries to add a flashcard which already exists.RepeatedSubjectException
- An exception thrown if the user adds a subect which is already present in the application.RepeatedTopicException
- An exception thrown if the users adds a topic that is already present in the application.- repo - The repository in Github which holds the revisED project.
Result
- A class in the quizcard package which stores the marks from a quiz and a description which indicates the performance of the user for that quiz.result
- An object of the Result class.ResultList
- A class in the list package which holds an ArrayList of Results.ResultSubjectCommand
- A command in the subjectcommand package which shows all the results of subjectQuizzes obtained for the subject.Revised
- The main class which initiates the whole application.It is also the name of the application.
S
saveTasks
- Method in the Storage class which saves the tasks.saveToJson
- Method in the Storage class which saves information in JSON format.saveTopics
- Method in Storage class which saves the topics in the application.score
- A variable in the Result class which tracks the score during the quiz.setupQuiz
- Method in SubjectQuiz and TopicQuiz class which sets up the quiz by transfering the flashcards.Subject
- A class which instantiates the subject object. Holds the title of the subject and lists of flashcards, results and topics.SubjectCommand
- An abstract class that is inherited by all the other SubjectCommand classes in the subjectcommand package.subjectcommand
- A package which holds the different Subjectcommand classes.subjectexception
- A package which holds the exceptions thrown in the main level.SubjectList
- A class in the list package which holds an ArrayList of Subjects.SubjectParser
- A class in the parser package which reads the user commands to call the relevant Subject command.SubjectQuiz
- A class in quizcard package which initiates a quiz for the subject.SorryFlashcardCommand
- A command in the flashcardcommand package which highlights invalid commands in the topic level.SorrySubjectCommand
- A command in the subjectcommand package which highlights invalid commands in the main level.SorryTaskCommand
- A command in the taskcommand package which highlights invalid commands in the subject level.SorryTopicCommand
- A command in the topiccommand package which highlights invalid commands in the subject level.Storage
- A class which is saves the data when the user exits the application and loads the data once the user starts the application.storage
- A package which holds the Storage class, which is in charge of storing and loading data into the application.StorageBuilder
- Inner class of storage class and creates storage instances.storageexception
- A package which holds the DataLoadingException.
T
Task
- An abstract class in the taskcard package which Todo, Deadline and Event classes inherit from.task
- A package which contains the TaskList class.taskcard
- Package which contains the task classes.TaskCommand
- A class in the taskcommand package that is inherited by all the other TaskCommand classes in the taskCommand package.taskcommand
- A package which holds the different taskcommand classes.TaskDeadlineException
- An exception thrown if an invalid deadline task is added to the applcation.TaskEventException
- An exception thrown if an invalid event task is added to the application.taskexception
- A package which holds the exceptions related to task operations.TaskList
- A class in the list package which holds the list of classes.TaskList
- A class in the list package which holds an ArrayList of Tasks.TaskParser
- A class in the parser package which reads the user commands to call the relevant task command.TaskTodoException
- An exception thrown if an invalid todo task is added to the application.Todo
- A class in the taskcard package which refers to a task without deadline.Inherits from the Task class.Topic
- A class in the card package which is instantiated when the user creates the topic. Holds the title of the topic, an arraylist of flashcards and an arraylist of results.TopicCommand
- An abstract class in the topiccommand package that is inherited by all the other TopicCommand classes in the topiccommand package.topiccommand
- A package which holds the different topiccommand classes.topicexception
- A package which holds the exceptions that are related to topic operations.TopicList
- A class in the list package which holds an ArrayList of Topics.TopicParser
- A class in the parser package which reads the user commands to call the relevant topic command.TopicQuiz
- A class in the quizcard package which initiates the quiz for a topic.toString
- A method provided by Java to convert the current object into a String. This method has been overriden in classes such as Event,Deadline to provide the accurate output .
U
Ui
- A class which takes care of interaction with the users. Prints the correct output to the console.ui
- Package which contains the Ui class, in charge of user interactions.updateResult
- Method in Result class which updates the score of a quiz.
Appendix E: Instructions for Manual Testing
Given below are the instructions to test the app manually.
📝️️ NOTE: These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.
Launching
- Refer to the Quick Start to download and launch the application.
- Expected: The application should show the greeting screen as illustrated in the quick start section.
Testing features
- Run each command as demonstrated in the example of usage in the Features section of the user guide.
- Expected: The output should match the sample output given.
Shutdown
- Run
exit
command until you reach the main level of the application (or until an error message saying the command is not recognized is displayed). - Run
bye
command. - Expected: A bye message should be displayed and the application should exit.
Saving data
When shutdown normally
- Create a new folder and copy the jar file used in the above steps to the new folder.
- Navigate to the new folder and launch the application.
- Run
add CS2113T
thensubject CS2113T
. - Run
add Java
. - Run
exit
thenbye
. - Expected: A
data/
folder containing the same structure as mentioned here should be created in the new folder.
When shutdown abruptly
- Follow steps 1 to 4 above to add data.
- Close the console running the application, then navigate to the new folder via file explorer.
- Expected: No folder is found created in the new folder.
Loading data
When data is not modified externally
- Follow all the steps above to create saved data.
- Launch the application again.
- Expected: CS2113T subject and Java topic persist in the application.
When data is modified externally
- Follow all the steps above to create saved data.
- Go into the
data/
folder in the new folder. - Rename the
CS2113T/
folder toCS2040/
. - Go back to the new folder and launch the application.
- Expected: CS2113T subject is changed to CS2040, and Java topic remains the same in the application.