iGraduate Developer Guide
Project by: W09-2
Latest update: 12 April 2021
Table of Contents
- Introduction
- Developer Guide Usage
- Setting up, Getting Started
- Design
- Implementation
- Logging
- Documentation
- Appendix A: Product Scope
- Appendix B: User Stories
- Appendix C: Non-Functional Requires
- Appendix D: Glossary
- Appendix E: Instructions for Manual Testing
Introduction
iGraduate is a Command Line Interface (CLI) application that helps NUS Information Security students track and plan their graduation by allowing them to add, delete, update modules to the module list. The users are allowed to add Core, General Education (GE), Math and Elective modules for tracking. There is also a built-in CAP calculator and Progress Command to check their graduation progress. Users can also list down modules on the list. When listing the modules, the module type will be shown accordingly.
Developer Guide Usage
This developer guide is made for developers who wish to further understand and/or develop iGraduate. This guide includes the setup instructions, design, implementation, logging, testing, product scope, and other sections to give developers a better understanding of the application.
The following symbols and formatting are used in this guide:
Symbols/Formatting | Description |
---|---|
ℹ️ Note: | Information to take note of. |
📝 Tip: | Optional information that may be useful. |
⚠️ Warning! | Important information that may resolve problems. |
Grey highlight |
Code or terms related to the application. |
Setting Up, Getting Started
This section guides you through the process of setting up the project on your computer.
ℹ️ Note: This application is developed for users with
Java 11
installed on their computer. If you do not have it installed on your computer or if you have other versions of Java, follow this link to download and install it before continuing with this section.
📝 Tip: To check if you have
Java 11
installed, typejava --version
into a command prompt
Fork the iGraduate repository to your GitHub account and clone it to your local computer. Alternatively, you could also download the source code of the application directly from our latest release.
Terminal
- Open a new terminal in the folder/directory where the
build.gradle
resides, and rungradlew.bat run
on Windows platform or run./gradlew run
on macOS/Linux platform. - You will see the following output in the console when the setup is successful:
Starting without existing module data...
Initializing new module list...
--------------------------------------------------------------------------------------
_ ____ _ _
(_)/ ___|_ __ __ _ __| |_ _ __ _| |_ ___
| | | _| '__/ _` |/ _` | | | |/ _` | __/ _ \
| | |_| | | | (_| | (_| | |_| | (_| | || __/
|_|\____|_| \__,_|\__,_|\__,_|\__,_|\__\___|
iGraduate starting up...
Welcome to iGraduate, your one stop study planning service!
What would you like to do today?
--------------------------------------------------------------------------------------
IntelliJ IDEA
- Configure IntelliJ IDEA to use
JDK 11
by referring to the IDEA set up guide.ℹ️ Note: This developer guide uses IntelliJ IDEA as the default IDE. It is recommended to install IntelliJ to follow the guide.
- Import the project as a
Gradle
project⚠️ Warning! Importing a
Gradle
project is slightly different from importing a normal Java project.📝 Tip: IntelliJ IDEA has the
Gradle
plugin installed by default. If you have disabled it, go toFile
→Settings
→Plugins
to re-enable them. If there is abuild.gradle
file in the project root, IntelliJ treats it as aGradle
project by default.- Open IntelliJ (if you are not in the welcome screen, click
File
→Close Project
to close the existing project first) - Open the project into IntelliJ
- Click
Open
. - Select the project directory, and click
OK
. - If there are any further prompts, accept the defaults.
- Click
- Click
OK
to accept the default settings but do ensure that the selected version of Gradle JVM matches the JDK being used for the project. - Wait for the importing process to finish (could take a few minutes).
- Open IntelliJ (if you are not in the welcome screen, click
- Verify the setup by running
seedu.igraduate.IGraduate
. If successful, the console would output the following:Starting without existing module data... Initializing new module list... -------------------------------------------------------------------------------------- _ ____ _ _ (_)/ ___|_ __ __ _ __| |_ _ __ _| |_ ___ | | | _| '__/ _` |/ _` | | | |/ _` | __/ _ \ | | |_| | | | (_| | (_| | |_| | (_| | || __/ |_|\____|_| \__,_|\__,_|\__,_|\__,_|\__\___| iGraduate starting up... Welcome to iGraduate, your one stop study planning service! What would you like to do today? --------------------------------------------------------------------------------------
Design
The following section is an overview of the design architecture. Each Sub-section provides a more detailed explanation for the design of each individual components.
Architecture Diagram
Figure 1.1.1 Architecture diagram showing an overview of the main components in iGraduate
Architecture
iGraduate has one class called iGraduate
which contains a main
and run
method and iGraduate
constructor.
It is responsible for:
- At app launch: Initialising the components in the correct sequence, and connects them up with each other.
- At shut down: Shuts down the components and invokes clean up 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.Parser
-> Understands and interprets the commands input by user, passes command to run to Command.Command
-> Executes command based on what is parsed.
Model
-> The user data held by the programModule
-> Holds the information of individual modules.ModuleList
-> Holds data of all modules 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 interface with the same name as the Component.
- Exposes its functionality using a concrete
{Component Name}Manager
class (which implements the corresponding API interface mentioned in the previous point.)
Given below is the sequence diagram of the startup sequence of iGraduate before any user input.
Figure 1.1.2 Sequence diagram of iGraduate from startup until before first user input.
The startup sequence sets up all objects required for running commands, such as the Ui
and fetching of stored data from Storage
.
Given below is the sequence diagram of how the architecture handles the flow of execution of commands and how the program exits.
Figure 1.1.3 Sequence diagram of iGraduate from receiving the first user input until exit.
UI Component
The UI is a public class that consists of three components: Scanner
, Constants
and Print Methods
. The UI component mainly manages the retrieval of user command and display of user feedback, ranging from successful execution, execution results and exceptions.
Behaviour
- Listens for calls from the logic component and model component, which will call the specific print method to print an output.
- Print method references
Constants
and prints them for user to see.
Figure 1.2 UML class diagram for Ui class
Logic Component
The logic component consists of the class Parser
and the package Command
. The classes work together to interpret user input, identify the right command to execute and the execution of the input command.
Behaviour
Parser
identifies the command to run and extracts the parameters and flags required for the command from user inputParser
passes these values tocommand
, creating an instance of the object from the type of command detected.Command
then runs the command with the processed parameters and flags.
Parser Class
The Parser
class is part of the logic component.
The Parser
interprets user input and subsequently passes the properly processed user input to Command
to execute the command.
Given below is the Parser
class diagram showing the important methods that returns a Command
object. As shown, Parser
contains one class, Parser.java
and the main function is the parseCommand()
method.
Figure 1.3 UML class diagram for Parser class
Behaviour
parseCommand()
extracts the command phrase entered by the user by extracting the first word of the user input.- Based on the type of command from the user,
parseCommand()
then calls different methods to extract parameters and flags from the user command that are relevant to the command. - The parser then creates the relevant
Command
object and dispatches the control of the program to the created object.
ℹ️ Note:
- Interpretation and checking of parameter validity occurs in the parser.
- The Parser also contains checks that ensures the parameters passed are appropriate.
The methods that extract the various parameters and flags, which would be invoked based on the command word detected in the user input:
Method | Description | Invoked with |
---|---|---|
extractModuleCode() |
Extracts the module code by checking for the -c flag. |
createAddCommand() |
extractModuleType() |
Extracts the module type by checking for the -t flag. |
createAddCommand() |
extractModuleCredits() |
Extracts the module credits by checking for the -mc flag. |
createAddCommand() , createUpdateCommand() |
extractModuleGrade() |
Extracts the module grade obtained by checking for the -g flag. |
createDoneCommand() , createUpdateCommand() |
extractModuleName() |
Extracts the module name by checking for the -n flag. |
createUpdateCommand() |
extractPreRequisites() |
Extracts the module prerequisites by checking for the -p flag. |
createAddCommand() , createUpdateCommand() |
extractListScope() |
Extracts the list type. Accepts all, complete, incomplete or available as acceptable scopes. | createListCommand() |
Table 1.4 Methods invoked to extract various flags in various commands
The method that check various parameters:
Method | Description |
---|---|
isModuleCodeValid() |
Checks that the module code is a valid module code according to the standard for NUS modules. The method uses regex to check for the valid code. There are 2 overloading methods - one for checking a single instance and another for an array list to check through a list of module codes. |
Table 1.5 Method invoked to check the validity of the module code
inputted
Command Package
The command
component executes the correct command based on what the parser interprets.
The command
component consists of an abstract class Command
and 10 subclasses that inherit from it. The subclasses are:
- AddCommand
- CapCommand
- DeleteCommand
- DoneCommand
- ExitCommand
- HelpCommand
- InfoCommand
- ListCommand
- ProgressCommand
- UpdateCommand
Behaviour
The correct command is executed once the Command
object is created by the parser by executing the execute()
method in the correct subclass.
The command execution can affect the Model
(e.g. adding a module).
At the end of each command execution, different methods in the Ui
will be called to perform certain actions, such as displaying the list of modules to the user.
Below are the Command class diagrams, split into 3 diagrams for better readability.
Figure 1.6.1 UML class diagram for Command class part 1
Figure 1.6.2 UML class diagram for Command class part 2
Figure 1.6.3 UML class diagram for Command class part 3
Model Component
The model
component consists of two main packages, module
and list
, which define and deal with data storing issues based on the information provided by the user input.
Behaviour
The data storing issues are split into two main categories - what data should be included in a module and a container managing the module objects.
module
holds the information which acts as a blueprint for creating and manipulating module objectslist
consists of a class that defines the way the module objects should be managed and stored.
Module Package
The module
package consists of classes that are used to define the type of data to be stored in a module object and establish a framework to show how other components can make use of the features in module classes.
Behaviour
The module
package consists of classes related to module objects.
- An abstract class
Module
is created to hold attributes and methods applicable to all class objects. Module
is then inherited by all other child module classes.
A class diagram illustrating the relationship between the interaction of classes under the module package is shown below.
Figure 1.7 UML class diagram for the Module package
The following child classes handle different types of modules based on the generic module type available in the university:
CoreModule
GeModule
ElectiveModule
MathModule
Each of the module classes consists of:
- Attributes related to the module type it is representing
- Getter and setter methods for setting and retrieval of its attributes
- Methods that alter an instance of its own class
Module Class
Module
class is an abstract class in the module package. It holds the attributes and methods for manipulating the
attributes applicable to all modules. The attributes found in the Module
class are relevant to NUS module information.
Behaviour
The Module
class also consists of methods that set and get the value of attributes shown in the table above. There are
four additional methods in the class, namely removeUntakenPreRequisite
, removeRequiredByModule
, getStatusIcon
and toString
. The removeUntakenPreRequisite
and removeRequiredByModule
methods are used to remove a singleuntakenPreRequisites
module
and requiredByModules
module respectively, whereas getStatusIcon
returns the status icon based on the module
status. For customized formatting of module printing messages, toString
method is overridden.
Child Class | Behaviour |
---|---|
CoreModule |
Initializes the core module object with the information needed and contains a toString method that overrides the format of core module printing. |
GeModule |
Initializes the general education module object with the information needed and contains a toString method that overrides the format of general education module printing. |
ElectiveModule |
Initializes the elective module object with the information needed and contains a toString method that overrides the format of elective module printing. |
MathModule |
Initializes the math module object with the information needed and contains a toString method that overrides the format of math module printing. |
Table 1.8 Child classes that inherited from the Module
class
List Package
The list
package contains an ArrayList
of type Module
, representing
the entire list of Module
objects added by the user. It also defines the methods used to modify the data of existing Module
objects,
such as adding, deleting or marking a Module
as done.
Behaviour
The package consists of 1 class, ModuleList.java
. ModuleList
contains 2 constructor signatures; 1 for constructing a
new, empty list for when the user uses iGraduate for the first time, and the other to contain the modules already stored
in Storage
.
ModuleList Class
The ModuleList
class acts as an abstraction for the ArrayList that is used to store module objects created from any of the classes under the module
package.
Given below is the class diagram of ModuleList
showing its 3 main functions.
Figure 1.9 UML class diagram for ModuleList class
Behaviour
The ModuleList
class:
- Provides a
ModuleList
structure with features built on top of ArrayList to enhance and customize its usage for the application. - Added data-related methods
addModuleRequiredBy
andremoveTakenPreRequisiteModule
to aid data processing when adding a module to theModuleList
. - The
ModuleList
class is also used by theStorage
component to generate JSON data of all modules and store it to disk. - Within the class
ModuleList
, different methods are defined to perform different operations on the list ofModules
. These operations are: - Apart from these 3 operations, the
ModuleList
class also defines getter and setter methods to retrieve individual modules from the list according to different parameters such as module code or index.
Add a Module
The methods add
, addModuleRequiredBy
and removeTakenByPrerequisites
are invoked to add a module.
The following shows the process of adding a module named newModule
:
addModuleRequiredBy
is called to populate the list of modules that requirenewModule
as a prerequisite.removeTakenByPrerequisites
checks the list of prerequisites ofnewModule
and removes the ones that have been marked as taken.add
callsArrayList.add()
to addnewModule
to the list.
Delete a Module
The methods delete
and removeFromPreRequisiteModuleRequiredBy
are invoked to delete a module.
The following shows the process of deleting a module named existingModule
:
delete
callsArrayList.remove()
to deleteexistingModule
from the list.removeFromPreRequisiteModuleRequiredBy
is called to removeexistingModule
from its pre-requisite modules’ requiredBy list.
Mark Module as Taken
The methods markAsTaken
and removeFromModuleUntakenPrerequisites
are invoked to mark a module as taken.
The following shows the process of marking a module named existingModule
as done:
markAsTaken
callsModule.setStatus
and sets the status ofexistingModule
to “taken”.removeFromModuleUntakenPrerequisites
is called to removeexistingModule
from the prerequisitesUntaken table from the list of modules that requireexistingModule
as a prerequisite.
Storage Component
The storage component consists of the class Storage
. The storage component is closely associated with the ModuleList
component to store latest module information (including completion, code, name, prerequisites, etc.) in a JSON format after every manipulation of ModuleList
. This includes adding, deleting and updating of modules, as well as marking a module as done.
Class Diagram:
Figure 1.10 UML class diagram for Storage package
Behaviour
The Storage
Component,
- Can save
module
objects in themoduleList
in a JSON format and read them back
Figure 1.11 UML object diagram for an instance of storage object
Common Classes
The common class used by multiple components in this app are in the exception
package. The exceptions
are thrown when an error occurs. The method catches the exceptions and prints out the respective error message.
ℹ️ Note: Each exception
is specified by the name and description.
Behaviour
This section elaborates on some details about how certain features are implemented.
Implementation
This section describes some noteworthy details on how certain feature are implemented.
UI
The Ui feature has 3 primary responsibilities:
- Executes user command using
Logic Component
- Prints resulting message
- Listens to calls from Model data
Parser
The parser feature has 4 primary responsibilities:
- Identify the command the user wants to run
- Extract the relevant parameters and flags required to run the command
- Check the validity of the parameters and flags
- Create a new
Command
object and hand it over toiGraduate
to execute
Figure 1.12 Sequence diagram of Parser
in execution with done CS1010 -g A
as user input
Details
There are 3 classifications of user input: command, parameter and flags.
User input | Description | Usage/Example |
---|---|---|
command |
the type of command the user intends to run and is first word from the user input | dictates how Parser extracts the parameter and flags. Refer to Command for the list of available commands |
parameter |
the argument that comes after the command word and can vary depending on the command | specifies the identifier (module name or code or list type) for the modules. For example, the parameter for add command would be the module name, but the parameter for delete would be the module code. For list, the parameters would specify the type of list (complete, incomplete or available) |
flag |
comes after parameters and are available only for a few commands | specify the additional information required for the command to run. For add , flags would be for module code, module type, MCs and prerequisites. |
Table 1.13 Terms used in differentiating the different parts of a user command
Considerations : How to implement parsing of user input
From the start, it was known that Parser
would be one of the more challenging components to implement due to the
large number of commands and the variance in parameter and flag types. Another difficult problem to navigate around was the
validation of the format and values of the parameters and flags. Initially, no validation checks were implemented in Parser
,
with the respective Command
subclasses doing the input validation for their specific parameters and flags. However,
the Storage
component also requires the same checks as the Command
component. As such, there was a dependency
between Storage
and Command
, which does not make sense as the responsibilities of the two are completely unlinked.
Hence, the validation of parameters and flags were moved to Parser
. In this implementation of Parser
, the Storage
and Command
components are unaware of each other, instead relying on Parser
for extracting and validating inputs.
This helps to eliminate the dependency between Storage
and Command
.
Alternatives
- Custom (current choice): Designing and implementing a custom parser for iGraduate
- Pros:
- Better suited for target users (fast typists)
- Cons:
- Less sophisticated error and exception handling
- Higher risk of bugs
- More complicated to implement
- Pros:
- Outsource: Adopt third-party libraries to perform parsing
- Pros:
- More resilient to error and exceptions
- Less design considerations
- Cons:
- Less suitable for iGraduate behaviour
- Pros:
Considerations were made for the adoption of third-party parser libraries. However, the third-party libraries obtained did not achieve the behaviour that was envisioned. Instead of keeping the application running when executing any commands, the command, parameters and flags would have to be directly piped in the command terminal, together with the application. This would create an instance of the iGraduate application before terminating after one command. Though this may provide a far superior parsing and error and exception handling, the behaviour does not support the target audience. Therefore, the decision was made against using a third-party library. Instead, attempts were made to mimic the behaviours and error handling of the libraries, but within the context of the running application.
Considerations : Format to store module information
An arrayList
is used to store the parsed data from the user input instead of an array
. This is to make use of the built-in class functions (especially indexOf()
and size()
). The array
class also lacks certain features that are of good use to the parser
class. This includes the use of regex for checking against the values stored in each index without making the process too manual. For instance, matches()
of arrayList
automatically takes in a regex instead of having to manually create a regex object, then parsing into the find()
function, which loops through the entire array to obtain the matches. This significantly simplifies the code in the parser
function, and makes handling exceptions easier.
Alternatives
- ArrayList (current choice)
- Pros:
- Equipped with useful built-in class functions
- Significantly simplifies logic needed to parse flags and parameters
- Cons:
- Less Memory efficient
- Pros:
- Array
- Pros:
- Efficient memory allocation
- Fixed size, which uses less memory
- Cons:
- Inefficient in extracting input flags
- Limited functionalities
- Pros:
Initially, it was decided that the parameters would be split into an array
to utilise the efficient memory allocation and standard size because arrays are more memory efficient. The parsing does not modify any values in the array after the initial split to the arrays (i.e. no additions of removal of data needed). However, the process needed to extract the flags from the array is inefficient, and requires another method to locate. Furthermore, the array in limited in its capabilities, making the coding of some behaviour complicated (such as filtering with a regex value). Therefore, the array ultimately got changed into an arrayList
type, since arrayList
has more features that can be utilised to make the code more efficient.
Command
The command
package is responsible for executing the command from the user. The package contains the abstract class
Command
and 10 subclasses that inherit Command
, one for each valid iGraduate command .
Details
The abstract class Command
contains only 1 method: execute()
, which takes in 3 parameters: moduleList
, ui
and
storage
. These 3 parameters aid with printing information to the user, making modifications to the data and saving the
data. Each subclass of Command
overrides execute()
and implements their own methods to execute the command. Each
subclass also has a unique constructor signature as each subclass requires different parameters to execute.
Implementation
The implementation for executing every command differs, and the implementation details of each of them will be further
elaborated below.
Add Command
The add command allows a user to add a new module to the list of existing modules. The module name is part of the parameters and is extracted directly from user input while the various information required to add a new module are included in the flags of the user input.
There are 3 compulsory flags and 1 optional flag for adding a module:
- module code
-c <String>
- module credits
-mc <double>
- module type
-t <String>
- (Optional) prerequisite modules
-p [<String>, ...]
ℹ️ Note: The order of flags in user input does not matter.
The sequence diagram below shows the execution of add command in action:
Figure 1.14 Sequence diagram of AddCommand
in execution with add Programming Methodology -c CS1010 -mc 4 -t core
as user input.
Delete Command
The delete command allows for deletion of module from the module list, identified by the module code, which is extracted from user input as a parameter. There are no flags involved for deleting a module.
ℹ️ Note: Users cannot delete modules which are prerequisites for other modules.
Figure 1.15 Sequence diagram of DeleteCommand
in execution with delete CS1010
as user input
Update Command
The update commands allows users to modify existing modules, identified by the module code. The information that can be updated include module name, credits, prerequisites and grades (if the module is marked as done).
The module code is extracted from user input as a parameter while the various information requested to update would be identified with their flags:
- name ->
-n <String>
- module credits ->
-mc <int>
- prerequisites ->
-p [<String>, ...]
- grade ->
-g <String>
ℹ️ Note:
- The code and type of modules cannot be modified as they are identifiers of the modules.
- Multiple module information can be updated in a single command.
- The command will not update grades if the module requested has not been completed. The rest of the information parsed in the command (if any) will be updated.
Figure 1.17 Sequence diagram of UpdateCommand
in execution with update CS1010 -mc 2
as user input
Considerations : Command behaviour
The main considerations regarding the behaviour of the update command would be if multiple flags should be permitted in a single update command.
Alternatives
- Restrict to single update flag
- Pros:
- Simple to implement
- Easier error and exception handling
- Cons:
- Inconvenient and unsuitable for target audience
- Pros:
- Allow multiple flags (current choice)
- Pros:
- Suitable for target audience who are fast typists
- Update Command makes it more convenient for users to change module information as compared to deleting a module and adding it again.
- Cons:
- Complicated process when extracting flags
- More considerations needed for error and exception handling
- Pros:
Having a single input would significantly simplify the code, as a simple switch statement will suffice. There is also less error and exception handling as only two parameters are given. In the event of an exception, simply retrace the command and throw exception. However, having only one flag at a time is inconvenient for fast typists, and is less optimized for their quick typing.
Another alternative was to allow multiple flags, each with their own input and error handling. Extraction would be significantly more complex, as each flag has to be accounted for, extracted together with its trailing new value. Should one of the flag cause an exception, another consideration would be to determine if the command should be completely aborted or just the failed flag. The greatest advantage of parsing multiple updating instances would be to allow fast typists to quickly make multiple changes in a single command line. This caters much more to the target audience, and makes using iGraduate more convenient. Ultimately, decision was made to allow multiple flags, individually parsed with their own checks and extraction methods, reused from the other commands.
Considerations : Command error and exception handling management
On the event of a failed flag, considerations have to made to determine how the update command would manage the rest of the flags.
Alternatives
- Abort entire command
- Pros:
- Simple to implement
- Cons:
- Major inconvenience to users
- Pros:
- Ignore failed flag
- Pros:
- More usable and convenient for users
- Cons:
- Extremely complex in error and exception handling
- Pros:
- Ignore failed grade flag (current choice)
- Pros:
- Compromise between convenience and code difficulty
- If grade flag generates an error, the other flags would still be updated
- Cons:
- Failure in other flags still results in aborting the entire command
- Pros:
The first way is to completely abort the entire command, which lowers the usability aspect of the application, creating inconvenience when a small error is encountered. However, this makes coding straightforward and simple.
Another alternative is to simply ignore the failed flag and attempt to change the rest. This would make the update command more usable and convenient. However, the primary issue is the difficulty in designing and programming such behaviour, individual try and catch statements needs to be used. Each statement must be able to differentiate between having an invalid flag input or having a flag that does not exist (i.e. the user did not use the flag). This behaviour makes the application significantly more complex to code and catch.
Finally, decisions were made to compromise between the two alternatives. After some discussions, it was determined that grade (the -g flag) is the most likely to fail since it depends on not just the user input but if the module has been completed. Therefore, a dedicated try statement is used to ensure that, even in the event of errors associated with providing a grade to an incomplete module, the rest of the command would still be updated (the rest of the extracts and checking is in the final clause). Unfortunately, if the other flags fail, the program will abort entirely. This alternative balances the complexity between error and exception handling and usability, allowing some flexibility in managing error while providing some convenience.
Info Command
The info command provides a feature for the user to view any module they added to the list regardless of the module type and status by specifying its module code. The module code is extracted from user input as a parameter. The command will only be executed if valid module code is provided by the user. All information of the specified module will be shown to the user to aid the planning of module.
There are no flags required for this command.
An example of info command execution flow is shown in the sequence diagram below.
Figure 1.18 Sequence diagram of InfoCommand
in execution with info CS1010
as user input
Considerations
After receiving feedback from a user stating that there are no ways for the user to view the prerequisite
information for any modules, the team considered implementing a prerequisite column for the list command
as
suggested by the user. However, after much consideration and discussion, the team felt that it could become too
convoluted and cluttered for the list command
results as there are simply too much information to show in one
screen. Instead, the team decided to create a new info command
to list the information of the module based on the module
code as specified by the user.
List Command
The list command provides users with 8 options to list down the modules being tracked by iGraduate. The options come in the form of a parameter that is extracted from user input.
The table below is an overview of the list commands.
List Parameter | Scope |
---|---|
all |
List all modules being tracked |
complete |
List modules that have been marked as done |
incomplete |
List modules that have not been marked as done |
available |
List incomplete modules available to be marked as done based on prerequisites completed |
core |
List all core modules on the list |
math |
List all math modules on the list |
elec |
List all elective modules on the list |
ge |
List all GE modules on the list |
Table 1.19.1 Overview of the List function
Figure 1.19.2 Sequence diagram of ListCommand
in execution with list complete
as user input
CAP Command
The CAP command calculates the current CAP of the user based on the grades of modules that are marked as done. The command also displays the degree classification of the user. There are no flags or additional parameters required.
Figure 1.20 Sequence diagram of CapCommand
class.
Done Command
The done command is used to mark a module as completed. To execute this command, the module code is extracted as a parameter from user input, and there is 1 compulsory flag:
- Grade obtained for module
-g <String>
ℹ️ Note: Only the following letter grades (A+, A, A-, B+, B, B-, C+, C, D+, D, F, S, U, CS, CU) are valid.
ℹ️ Note: Module codes are case-insensitive. This means that module codes like
CS2102
andcs2102
are considered the same.
Figure 1.21 Sequence diagram of DoneCommand
in execution with done CS1010 -g A
as user input
Progress Command
The progress command prints a progress bar as well as the user’s graduation progress in the form of a percentage. No additional flags are required for this command.
Figure 1.22 Sequence diagram of ProgressCommand
in execution.
Help Command
The help command provides users with a quick reference guide to the list of available commands, their functions and the proper format for inputs. Users also have an optional parameter to find the reference guide for a specific command.
The optional parameters are:
add
delete
update
list
info
done
progress
cap
exit
ℹ️ Note: If no parameters are provided, a brief description of the program and the available commands will be printed instead.
The figure below demonstrates the behaviour of the help command.
Figure 1.23 Sequence diagram of HelpCommand
in execution with help add
as user input.
Considerations
A quick reference guide where users can see the summary of commands and the different formats for each command.
One implementation considered was the format used for Linux man
pages, where a single command line input displays all
information about the functionality of the command and the types of parameters accepted. This was
the most straightforward implementation due to the ease of parsing possible user inputs and there being only one kind of
message to be displayed. This proved to be unfeasible from a User Experience point of view as there was too much information
displayed at one go due to the number of commands the application has and their unique formats. Instead, the team opted to
go for a more segmented implementation of the help
command, with one command showing users how to use the reference guide
while the other commands provide a readable reference guide to the user that targets the command that users want to know
more about.
Module
The module
component contains the class module
, together with 4 child classes that inherit from module
. All modules
stored in iGraduate are instances of one of the 4 subclasses.
Details
For the implementation of modules in iGraduate, most of the information used to identify a module are contained in the
parent class module
. The class contains the setters and getters of all the data pertaining a module, such as the module code,
grade and MCs. It also contains the lists that track the prerequisites of the module.
The implementation details of the subclasses are hence quite sparse, containing only a constructor and a public method toString()
which identifies the type of module stored
in the module
object.
Considerations
To accommodate the wide range of operations available to the modules, the implementation of the module
component had to
be comprehensive in the data it stores. However, since every module shares the same categories of data to store, such as
module code and grade, the subclasses do not contain much information that is not already stored in their parent class. To
better accommodate our list by module type feature, the subclass each module belongs to is determined by the module type.
ModuleList
The moduleList
component acts as a temporary storage for storing module data while application is
running. All module data added to the application could be found under the moduleList
storage.
Details
Since the moduleList
is used for storing module data needed for running application, the module data
will be loaded from the disk when the application first started. After any data changing command is executed,
the latest module data in the moduleList
will be written to disk for permanent storage (unless the secondary
memory is faulty). It also consists of utility methods which allows retrieval, manipulation and deletion of
module data in a centralised and consistent manner.
Considerations
At the start of project, an array is considered to be used as the underlying data structure for the moduleList
component. However, after taking the scalability issue into consideration, the team decided to incorporate an
ArrayList
instead. Reason being ArrayList
is a dynamically sized array along with standard methods such as
whether the list contains a specific module, search and removal of specified module. The size of the ArrayList
is only limited by the user device’s available memory size.
Storage
The storage feature saves the state of the module list after every execution of commands that manipulates (i.e. update, add or delete) the modules in the list.
Details
The storage function is executed after every command that manipulates (i.e. adds, deletes or updates) the modules in the module list, saving the updated state into the storage file.
The module list is stored in a storage file named modules.json
in the data
folder (<program location>/data/modules.json
).
The figure below demonstrates the behaviour of the storage feature.
Figure 1.23 UML sequence diagram showing the life of Storage when the Add
command is invoked
Considerations
The main reason in using a JSON file instead of designing one is to allow a more robust error and exception handling and management with respect to modified storage files. The parsing of JSON format is also more sophisticated and reliable.
In addition, the JSON format can be read across multiple different types of applications, allowing flexibility in any future implementations regarding exporting of data.
Alternatives
The alternative storage format considered is the use of delimiters. However, there are concerns regarding such usage; the most important being potential parsing failure from a valid module. With the use of common delimiters such as commas ,
and dashes -
, the program is unable to differentiate between the various module information and legitimate module names containing delimiters and may parse the portion of the module to a wrong variable, resulting in a corrupted program. One example of such occurrence would be a module named Software Engineering and Object-Oriented Programming
, which contains dashes when the delimiters are used for separating various module information is also a dash.
Considerations were also given to use more unique delimiters (such as \
, |
, etc.) to avoid accidental parsing failures, but the problem still remained. Attempting to fuzz characters would lead to a corrupted storage file and render the application useless. Ultimately, the idea was scrapped in favour of the JSON format with a third-party library, since the exception handling and parsing management lies in the library functions.
Exception
Exception is an event that disrupts the normal flow of the diagram. It is an object that is thrown at runtime. In iGraduate, there are several exceptions that are thrown due to different conditions.
Exception | Description |
---|---|
AddSelfToPrereqException | This exception is thrown when user updates a module’s list of prerequisites to include the module itself. |
DataFileNotFoundException | The exception is thrown if module data file is not found. |
ExistingModuleException | The exception is thrown if the module code input already exists. |
IllegalParametersException | The exception is thrown if the parameter includes any parameters not allowed in the command. |
IncorrectParameterCountException | The exception is thrown if the parameters given is incorrect. |
InputNotNumberException | The exception is thrown if input is not an integer. |
InvalidCommandException | The exception is thrown if the command input was invalid. |
InvalidListTypeException | Exception is thrown if list command is not followed by: all, incomplete and complete. |
InvalidModularCreditException | Exception is thrown if modular credit input is negative. |
InvalidModuleGradeException | The exception is thrown if module grade input is invalid. |
InvalidModuleTypeException | The exception is thrown if the module type input is invalid. |
LoadModuleFailException | The exception is thrown if module cannot be loaded properly. |
MarkCompletedModuleException | The exception is thrown if module is already marked completed. |
ModifiedStoragefileException | The exception is thrown if the json file has been modified (when credits > 32 or credits < 0). |
ModuleNotCompleteException | The exception is thrown if the module being updated (on grade) has not been completed. |
ModuleNotFoundException | The exception is thrown if the module cannot be matched. |
PrerequisiteNotFoundException | The exception is thrown if the pre-requisite module cannot be matched. |
PrerequisiteNotMetException | Exception is thrown if prerequisite of the module has not been completed. |
SaveModuleFailException | This exception is thrown if the program fails to save data to file. |
UnableToDeletePrereqModuleException | This exception is thrown when user tries to delete a pre-requisite module. |
Table 1.24 The Summary list of all exceptions used in iGraduate
Logging
The logging feature is implemented using the java.util.logging
package. It is a default logging package included
in the Java package. To learn more about the package, you may refer to here.
To make use of logging feature, you will need to include the following line at the start of all the classes where logging
feature is to be used.
private static final Logger LOGGER = Logger.getLogger(ClassName.class.getName());
When including the line above, remember to replace ClassName
with the name of current class such as iGraduate
. Once
you have done instantiating the logger object with the code above, you can use the logger object to start logging. For
more information on how logging works, refer to the official documentation.
The logging configurations are specified in the logger.properties
file located in src/main/resources/logger.properties
.
To change the logging configurations, simply modify the logger.properties
file with the respective value. The current
configuration logs all messages with level of FINE
and above into a log file, iGraduate-0.log
, under the same folder
where the application resides.
Documentation
All the documentations related to the application are stored under the /docs
folder. There are currently three
documentations, AboutUs.md
, UserGuide.md
and DeveloperGuide.md
. The documentation tools used for developing these
guides are:
- GitHub Markdown syntax for formatting
- PlantUML for drawing diagrams
- Jekyll for documentation static site generation For more information on how to set up a documentation site using Jekyll, you may refer to Using Jekyll for project documentation guide.
Appendix A: Product Scope
Target User Profile
- is a NUS Information Security student
- has a need to manage and plan modules
- has a need to track graduation progress
- has a need to track his/her CAP
- prefer desktop apps over other types
- can type fast
- prefers typing to mouse interactions
- is reasonably comfortable using CLI apps
Value Proposition
Allows users to manage modules faster than a typical mouse/GUI driven app.iGraduate Includes higher level features such as ability to add modules while ensuring user has cleared all prerequisites and to list all modules taken, graduation progress and current CAP with degree classification.
This app will help NUS students majoring in Information Security check his/her graduation progress and modules taken in a coherent manner based on the program requirements. It also contains tools as mentioned above to help students make informed decisions about future modules to take.
Appendix B: User Stories
Version | As a … | I want to … | So that I can … |
---|---|---|---|
v1.0 | user | see the list of modules I can take now | decide on which modules to register |
v1.0 | user | clearly see which modules I have taken | to check my prerequisites |
v1.0 | user | delete mods that I have added | amend any typos |
v1.0 | user | add new modules that I have taken | track the modules I have taken |
v1.0 | user | utilise the CLI to input my information and execute functions | |
v1.0 | user | have my data be persistent | access it again next time when I run the program |
v1.0 | impatient user | access information quickly | |
v1.0 | lazy user | access information with as little effort as possible | |
v1.0 | user | know my academic progress | estimate my pace and plan for the future |
v2.0 | careless user | know if the module I entered is valid | |
v2.0 | user | calculate my current CAP | |
v2.0 | user | know if the module I entered is valid | monitor my performance throughout the course of study |
v2.0 | user | see what modules I have already taken | plan what modules to take next semester |
v2.0 | forgetful user | know if I meet the prerequisites for computing modules I want to take | |
v2.0 | user | edit the modules for the course | amend my mistakes or changes in module details |
v2.0 | user | be able to pick out any module as my UE | |
v2.0 | user | know the pre-requisites of a module | plan my semesters better |
v2.0 | user | see all core modules I have to take | |
v2.0 | user | be able to choose any electives of my course |
Table 1.25 All user stories considered in the designing of iGraduate
Appendix C: Non-Functional Requirements
- Should work on any mainstream OS as long as it has Java 11 or above installed.
- Should be able to hold up to 1000 modules without a noticeable sluggishness in performance for typical usage.
- A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
- A user without online connection should still be able to use the application.
- A user should be someone studying in National University of Singapore.
- A beginner user without prior knowledge should be able to pick up the application comfortably.
Appendix D: Glossary
Term | Definition | Usage/Example |
---|---|---|
command |
the type of command the user intends to run and is first word from the user input; dictates how Parser extracts the parameter and flags. |
Refer to Command for the list of available commands |
parameter |
specifies the identifier (module name or code or list type) for the modules. | For example, the parameter for add command would be the module name, but the parameter for delete would be the module code. For list, the parameters would specifies the type of list (complete, incomplete or available) |
flag |
comes after parameters and are available only for a few commands; specifies the additional information required for the command to run. | For add , flags would be for module code, module type, MCs and prerequisites. |
delimiters |
a sequence of one or more characters that specifies the boundary between different streams | The delimiters such as commas, and dashes are used to differentiate the parameters for parsing. |
parsing |
the process of converting code into a more readable data format | a command is parsed through the parser class to create different commands. |
Table 1.26 Definitions and context of terms used in the developer guide
Appendix E: Instructions for Manual Testing
Given below are instructions on how 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.
Launch and Shutdown
-
Initial launch
-
Download the jar file and copy into an empty folder
-
Run the jar file on your command prompt with the by typing “java -jar iGraduate.java” then enter.
-
-
Shutdown
- The program shutdowns automatically after entering the command
exit
in iGraduate.
- The program shutdowns automatically after entering the command
Adding a Module
Adding a module into the module list.
Prerequisites:
- Module does not exist in the module list.
Test cases:
-
add Programming Methodology -t core -mc 4 -c CS1010
Expected: Module added successfully.-------------------------------------------------------------------------------------- Added CS1010 Programming Methodology to the list. (4.0MCs) [C][✘] CS1010 Programming Methodology NIL 4 MC --------------------------------------------------------------------------------------
-
add Programming Methodology -t core -mc 4 -c CS1010
Expected: Error in adding module as module type is invalid.-------------------------------------------------------------------------------------- The module type you have entered is invalid. The supported module types for add are: ue, ge, core and math. --------------------------------------------------------------------------------------
-
add Programming Methodology -t core -mc -c CS1010
Expected: Error in adding module as there is incorrect number of parameters given, which in this case number of mc is not given.-------------------------------------------------------------------------------------- The number of parameters provided is incorrect. Please double check and try again. --------------------------------------------------------------------------------------
-
Other incorrect add commands to try:
add
,add nothing
Expected: Similar totest case 3
.-------------------------------------------------------------------------------------- The number of parameters provided is incorrect. Please double check and try again. --------------------------------------------------------------------------------------
Deleting a Module
Deleting modules from a given module list.
Prerequisites:
- Module list is not empty.
Assumption:
- Module list consists of module
CS1010
.
Test Cases:
-
delete CS1010
Expected: Module deleted successfully.-------------------------------------------------------------------------------------- "Core" module CS1010 has been deleted. --------------------------------------------------------------------------------------
-
delete CS1020
Expected: Error in deleting module as module is not in the list.-------------------------------------------------------------------------------------- The module code you have entered does not exists. Please double check and try again. --------------------------------------------------------------------------------------
-
delete CS1010
Expected: Error in deleting module asdelete
is an unknown command word.-------------------------------------------------------------------------------------- The command you have entered is incorrect. Please double check and try again. --------------------------------------------------------------------------------------
-
delete -g A CS1010
Expected: Error in deleting module as extra parameter, e.g. -g A, is found.-------------------------------------------------------------------------------------- The number of parameters provided is incorrect. Please double check and try again. --------------------------------------------------------------------------------------
Marking Modules as Done
Masking modules as done with grade obtained after the semester.
Prerequisites:
- Module list is not empty.
Assumption:
- Module list consists of module
CS1010
, which is incomplete.
Test Cases:
done CS1010 -g A+
Expected: Module marked as done with grade A+ successfully.-------------------------------------------------------------------------------------- Nice! I've marked this module as done: [C][✓] CS1010 Programming Methodology A+ 2 MC --------------------------------------------------------------------------------------
done CS1020
Expected: Error in marking module as done as module is not in the list.-------------------------------------------------------------------------------------- The module code you have entered does not exists. Please double check and try again. --------------------------------------------------------------------------------------
done CS1010 A+
Expected: Error in marking module as done as flag-g
is not found before the gradeA+
.-------------------------------------------------------------------------------------- The number of parameters provided is incorrect. Please double check and try again. --------------------------------------------------------------------------------------
done CS1010
Expected: Error in marking module as done as incorrect number of parameters are given, e.g. missing grade.-------------------------------------------------------------------------------------- The number of parameters provided is incorrect. Please double check and try again. --------------------------------------------------------------------------------------
- Other incorrect done commands to try:
done
,done -g A+
Expected: Similar to previous.-------------------------------------------------------------------------------------- The number of parameters provided is incorrect. Please double check and try again. --------------------------------------------------------------------------------------
Updating the Module List
Update the modules in module list with changes in module credits or module grade.
Prerequisites:
- Module list is not empty.
Assumption:
- Module list consists of module
CS1010
with 4mcs marked as done with grade A+.
Test Cases:
update CS1010 -g A- -mc 2
Expected: Module grade and module credits updated successfully.-------------------------------------------------------------------------------------- Nice! I've updated this module: [C][✓] CS1010 Programming Methodology A- 2 MC --------------------------------------------------------------------------------------
update CS1010 -g A-
Expected: Module grade updated successfully.-------------------------------------------------------------------------------------- Nice! I've updated this module: [C][✓] CS1010 Programming Methodology A 4 MC --------------------------------------------------------------------------------------
update CS1010 -mc 2
Expected: Module credits updated successfully.-------------------------------------------------------------------------------------- Nice! I've updated this module: [C][✓] CS1010 Programming Methodology A+ 2 MC --------------------------------------------------------------------------------------
update
Expected: Error in updating module as not parameters were given.-------------------------------------------------------------------------------------- The number of parameters provided is incorrect. Please double check and try again. --------------------------------------------------------------------------------------
update CS1234 -g A- -mc 2
Expected: Error in updating module as module is not found in the module list.-------------------------------------------------------------------------------------- The module code you have entered does not exists. Please double check and try again. --------------------------------------------------------------------------------------
update -g A- -mc 2
Expected: Error in updating module as no module name is given.-------------------------------------------------------------------------------------- The number of parameters provided is incorrect. Please double check and try again. --------------------------------------------------------------------------------------
- Other incorrect update commands to try:
update
,update CS1010
.
Expected: Similar to previous.-------------------------------------------------------------------------------------- The number of parameters provided is incorrect. Please double check and try again. --------------------------------------------------------------------------------------
CAP
Display current CAP and degree classification of user.
Assumptions:
- Module list consists of
CS1010
marked as done with 4mcs and grade A+.
Test Cases
cap
Expected: CAP and degree classification displayed successfully.-------------------------------------------------------------------------------------- Current CAP: 4.50 Current Degree Classification: Honours (Highest Distinction) --------------------------------------------------------------------------------------
cap gg
Expected: Error as there is extra parameters found.-------------------------------------------------------------------------------------- The number of parameters provided is incorrect. Please double check and try again. --------------------------------------------------------------------------------------
Progress
Display user’s progress towards graduation.
Assumptions:
- Module list consists of
CS1010
marked as done with 4mcs and grade A+.
Test Cases
progress
Expected: Progress displayed successfully.-------------------------------------------------------------------------------------- Progress: ░░░░░░░░░░░ 2.50% 4MCs/160MCs Completed --------------------------------------------------------------------------------------
-
progress gg
Expected: Error as there is extra parameters found.-------------------------------------------------------------------------------------- The number of parameters provided is incorrect. Please double check and try again. --------------------------------------------------------------------------------------
List Modules
List modules in the modules list.
Assumption:
- Module list consists of
CS1010
marked as completed andCS2040C
is incomplete.
Test Cases
list all
Expected: All modules listed successfully.Module List: 1: [C][O] CS1010 Programming Methodology A 4 MC 2: [C][X] CS2040C Data Structures and Algorithms NIL 4 MC
list complete
Expected: All completed modules listed successfully.Modules you have have completed: 1: [C][O] CS1010 Programming Methodology A 4 MC
list incomplete
Expected: All incomplete modules listed successfully.Modules you have yet to complete: 1: [C][X] CS2040C Data Structures and Algorithms NIL 4 MC
list
Expected: Error in listing modules as list type not given.The number of parameters provided is incorrect. Please double check and try again.
list all completed
Expected: Error in listing modules as list type invalid.The list type you have entered is invalid. The supported list types for list are: all, incomplete and complete.
Saving Data
Dealing with missing/corrupted data files.
- While not in iGraduate, delete json file under
/data
directory. Then start iGraduate.
Expected: iGraduate accepts current content of files as empty and functions as per normal.Starting without existing module data... Initializing new module list... -------------------------------------------------------------------------------------- _ ____ _ _ (_)/ ___|_ __ __ _ __| |_ _ __ _| |_ ___ | | | _| '__/ _` |/ _` | | | |/ _` | __/ _ \ | | |_| | | | (_| | (_| | |_| | (_| | || __/ |_|\____|_| \__,_|\__,_|\__,_|\__,_|\__\___| iGraduate starting up... Welcome to iGraduate, your one stop study planning service! What would you like to do today? --------------------------------------------------------------------------------------
- While not in iGraduate, corrupt the json file under
/data
directory. Then start iGraduate.
Expected: iGraduate senses the corrupted files, replace it with empty content and functions as per normal.Unsupported changes in storage file detected, using new storage file. Note: If you wish to attempt to fix the configuration, exit program immediately. Do not perform any commands or you will lose the original storage file. -------------------------------------------------------------------------------------- _ ____ _ _ (_)/ ___|_ __ __ _ __| |_ _ __ _| |_ ___ | | | _| '__/ _` |/ _` | | | |/ _` | __/ _ \ | | |_| | | | (_| | (_| | |_| | (_| | || __/ |_|\____|_| \__,_|\__,_|\__,_|\__,_|\__\___| iGraduate starting up... Welcome to iGraduate, your one stop study planning service! What would you like to do today? --------------------------------------------------------------------------------------