By: Team AY1920S1-CS2103T-F14-1
Since: Sept 2019
Licence: MIT
1. Setting up
Refer to the guide here.
2. Design
2.1. Architecture
The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.
-
At app launch: Initializes the components in the correct sequence, and connects them up with each other.
-
At shut down: Shuts down the components and invokes cleanup method where necessary.
Commons
represents a collection of classes used by multiple other components.
Observable
is responsible for updates on User Interface if internal data changes.
`LogsCenter`is used by many classes to write log messages to the App’s log file.
The following five components plays an important role at the architecture level:
-
UI
: The User Interface of the App. -
Logic
: Includes 3 types of executors: the Command Executor, the Program Submission Executor, and the Question Builder Executor,. -
Model
: Holds the data of the App in-memory. -
Storage
: Reads data from, and writes data to, the hard disk. -
TextExecutor
: Compile the user program and run it against test cases. Output result.
Each of the six components:
-
Defines its API in an
interface
with the same name as the Component. -
Exposes its functionality using a
{Component Name}Manager
class.
For example, the QuestionLogic
component (see the class diagram given below) defines it’s API in the QuestionLogic.java
interface and exposes its functionality using the QuestionLogicManager.java
class.
How the architecture components interact with each other
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command submit
.
submit
commandThe sections below give more details of each component.
2.2. UI component
API : Ui.java
The UI consists of a MainWindow
that is made up of 7 parts e.g.CommandBox
, ResultDisplay
, Workspace
, NotesPage
, HelpPage
, Dashboard
and QuestionsPage
. All these parts, including the MainWindow
, inherit from the abstract UiPart
class.
Some of the 7 UI parts are also made up of other UI parts. For example, listed on the UML diagram, QuestionsPage
is made up of QuestionsListPanel
.
The UI
component uses the JavaFX UI framework. The layout of these UI parts are defined in matching .fxml
files that are in the src/main/resources/view
folder. For example, the layout of the MainWindow
is specified in MainWindow.fxml
The UI
component,
-
Executes user commands using the
Logic
component. -
Listens for changes through the Observer pattern. The UI updates as the
ObservableList
changes.
2.3. Logic components
2.3.1. Overview
There are 4 main logic components in the architecture of Duke Academy. They are CommandLogic
, QuestionsLogic
, ProgramSubmissionLogic
and NotesLogic
.
Each logic component serves as a facade for basic operations with regards to Commands, Questions, ProgramSubmission and Notes.
They orchestrate the execution of these operations internally and expose a simple interface for other components, such as the UI
to utilize.
The logic components are interfaces so their implementation can be changed easily.
Class diagrams for various logic classes
CommandLogic:
-
Only has one method which is used by the application to execute commands.
QuestionsLogic:
-
Deals with all CRUD operations pertaining to the questions found in the application.
-
Keeps track a selected question which represents the
Question
that is currently being viewed by the user.
ProgramSubmissionLogic:
-
Performs the evaluation of the user’s program submissions.
-
Keeps track of a currently attempting question which is used to test user program submissions.
-
Uses the
UserProgramChannel
interface to enable other components such as theUI
to serve as a source forUserProgram
without introducing them as dependencies.
NotesLogic:
-
Deals with all CRUD operations pertaining to the notes found in the application.
-
Uses the
NoteSubmissionChannel
interface to enable other components such as theUI
to serve as a source for notes without introducing them as dependencies.
2.3.2. CommandLogic implementation
The standard implementation of the CommandLogic is the CommandLogicManager
class.
Overview:
-
For commands to be parsed by
CommandLogic
, they have to be registered withregisterCommand()
. -
A
CommandSupplier
and a command word is required to register aCommand
-
A
Command
can also be registered with aCommandFactory
. -
When
executeCommand(commandText)
is invoke,CommandLogicManager
searches all previously registered commands for the right one to execute. -
Storage of these keys and the parsing of the
commandText
argument is performed byCommandParser
.
-
CommandSupplier
is a functional interface that returns aCommand
. -
Each
CommandSupplier
is mapped to a command word -
This command word is used to search for the appropriate
Command
-
CommandParser
splits the text input of the user into the command word and arguments. -
Each
Command
is responsible for parsing its own arguments. -
InvalidCommandArgumentException
is thrown if the arguments do not match the specification of the command.
The basic sequence of command execution is as follows:
-
Command
is registered upon startup by the application driver -
Command
and matching command word is stored inCommandParser
byCommandLogicManager
-
User enters command text
-
Application driver passes the command text as String to
CommandLogicManager
-
CommandLogicManager
passes command text toCommandParser
for parsing andCommand
retrieval -
CommandLogicManager
receives and executesCommand
2.3.3. QuestionsLogic implementation
The standard implementation of the QuestionsLogic
interface is the QuestionsLogicManager
. It stores questions
in the form of a QuestionBank
(View Section 2.5, “Storage component” for more details).
Overview:
-
Allows other components of the application to make changes to existing questions using its inteface.
-
Other components of the application can observe the current state of questions by getting an
ObservableList
throughgetAllQuestionsList()
andgetFilteredQuestionsList()
. -
ObservableList
fromgetFilteredQuestionsList()
is a filtered list. The filter can be changed bysetFilter(predicate)
.
-
QuestionsLogicManager
constructor takes in aQuestionBankStorage
instance which is used to load the initialQuestionBank
and to save subsequent changes to it. -
The main bulk of the CRUD operations are handled by
QuestionBank
. -
QuestionLogicManager
saves theQuestionBank
after each change.
2.3.4. ProgramSubmissionLogic implementation
The standard implementation of the ProgramSubmissionLogic
is the ProgramSubmissionLogicManager
. It
relies on TestExecutor
to execute users' program submissions
(View Section 3.1, “Evaluation of user program submissions” for more details).
Overview:
-
Keeps track of a currently attempting
Question
. -
Currently attempting
Question
can be set throughsetCurrentQuestion(question)
. -submitUserProgram(userProgram)
orsubmitUserProgramFromSubmissionChannel()
evaluates the program against test cases found in the currently attemptingQuestion
. -
Other components can observe the latest
TestResult
through an observable provided bygetTestResultObservable()
without havingProgramSubmissionLogicManager
depending on them.
-
ProgramSubmissionLogicManager
instantiates theTestExecutor
using theStandardCompilerEnvironment
,StandardCompiler
andStandardProgramExecutor
. -
ProgramSubmissionLogicManager
holds a reference toStandardCompilerEnvironment
so that it can be closed bycloseSubmissionLogicManager()
. -
It is important that the application invokes
closeSubmissionLogicManager()
method exiting to remove any temporary files that were created.
The basic sequence of submitting a program from a UI
component is as follows:
-
Register the
UI
component as the newUserProgramChannel
. -
Set the currently attempting question using
setCurrentQuestion(question)
. -
Invoke the
submitUserProgramFromSubmissionChannel()
. -
User program is retrieved from the
UI
component and evaluated against the currently attempting question.
2.3.5. NotesLogic implementation
The standard implementation of the NotesLogic
interface is the NotesLogicManager
. It relies on SketchManager
to handle loadiand saving of the Sketches.
It also stores the notes in the application in the form of a NoteBank
. (View Section 2.5, “Storage component” for more details.)
Overview:
-
Allows other components of the application to make changes to the current state of notes using its interface.
-
Other components of the application can also observe the current state of notes by getting an
ObservableList
throughgetAllNotesList()
-
NotesLogicManager
constructor takes in aNoteBankStorage
instance which is used to load the initialQuestionBank
and to save subsequent revisions to it. -
The main bulk of the CRUD operations are handled by the
NoteBank
class. -
NotesLogicManager
saves theNoteBank
methods along after each change -
NoteSubmissionChannel
is required to provide a pair of values — aNote
and aWritableImage
instance to represent the user’s sketch.
SketchManager:
-
Handles the saving, loading and deleting of sketches.
-
Deals with sketches in two formats,
WritableImage
class used by the JavaFXUI
components for rendering the image, and png form in storage. -
Converts sketches between the two formats upon loading/before saving.
The basic sequence of saving a user’s note from a UI
component is as follows:
-
Register the
UI
component as theNoteSubmissionChannel
-
Invoke the
saveNoteFromSubmissionChannel()
method -
Note
and sketch is retrieved from theNoteSubmissionChannel
-
Note
is saved by theNoteBankStorage
while the sketch is saved by theSketchManager
2.4. Model component
We created models for Question
, Program
, Note
and Profile
.
Note model:
-
The note model class represents a user’s note in the application.
-
It contains a title which provides an easy way for the user to identify and organize his or her notes
-
It contains a content string to represent all the text-based notes that the user has entered.
-
Each note also contains a sketch which the user can draw and edit within the
NoteCanvas
component. The sketch is stored as a png whose file name corresponds to the sketchId of the note.
2.5. Storage component
2.5.1. Overview
There are 2 main storage components found in the architecture of Duke Academy. They are QuestionBankStorage
and NoteBankStorage
. Each storage component serves as a facade for the basic operations by the application with regards to Commands and Notes.
The Storage
component,
-
can save
UserPref
objects in json format and read it back. -
can save the Duke Academy question bank in json format and read it back.
-
can save the notes and read it back.
2.5.2. Implementation
The storage components are interfaces so their implementation can be changed easily.
JsonAdaptedQuestion
serves as a good starting point to understand the implementation.
JsonAdaptedQuestion:
-
It contains all the necessary attributes for a question, including title, completion status, difficulty level, isBookmarked, topics belonged to, testCases, userProgram attempted and question description.
-
Compared with a standard
question
object, thisJsonAdaptedQuestion
object has processed its attributes to be compatible with json format. That is, this object can be directly serialized to and de-serialized from json files. -
The constructor is used to serialize the
Question
object using the@JsonProperty
notation. -
The
@JsonProperty
is also able to deserialize strings obtained from json files. ThetoModel()
function is then used to construct and return a newQuestion
object using attributes it obtained using the getter methods.
2.5.3. Structure
We would hereby use QuestionBankStorage
to illustrate the implementation.
The standard implementation of the QuestionBankStorage
is the JsonSerializableStandardQuestionBank
class.
Overview:
2.6. Common classes
Classes used by multiple components are in the com.dukeacademy.commons
package.
Core:
Exceptions:
DataConversionException
: occurs when loading files with incorrect data format.
IllegalValueException
: occurs when user inputs a invalid command.
Util:
FileUtil
: for loading and saving of files.
JsonUtil
: for serializing and deserializing json files.
3. Implementation
This section describes some noteworthy details on how certain features are implemented.
3.1. Evaluation of user program submissions
The evaluation of the user’s programs is facilitated by the testexecutor
package.
3.1.1. Entry point
-
TestExecutor
contains a single methodrunTestCases(testCases, program)
which evaluates aUserProgram
against a list ofTestCase
.
TestCase - stores an input and an expected value.
UserProgram - stores the name of the class which contains the main method along with the source code (note that the class name must match the source code for it to be evaluated successfully).
Class Diagrams for UserProgram and TestCase
-
The result of the program evaluation is returned as a
TestResult
object.
TestResult - encapsulates all possible outcomes of evaluating the user’s program. It is contains TestCaseResult
and CompileError
.
3.1.2. Implementation overview
The evaluation of a user’s program is done in 5 main steps, each handled by a specialized interface. The 5 steps include:
-
Create a Java file inside a temporary directory and write the source code into the file.
-
Compile the Java file. Catch and store any compile errors.
-
Execute the generated Class file and provide the inputs of the test cases.
-
Collect and store any output from the program.
-
Package the output, errors and results as a
TestResult
instance.
The 3 specialized interfaces used are CompilerEnvironment
, Compiler
and ProgramExecutor
. They provided through dependency injection in the TestExecutor
constructor.
TestExecutor
acts as an orchestrator for the 3 interfaces.
CompilerEnvironment - in charge of creating a temporary folder in the user’s file system to create Java files.
This temporary folder is deleted in closed()
. Uses JavaFile
.
Compiler - in charge of compiling the Java files into Class files at a given file path. Uses ClassFile
.
ProgramExecutor - in charge of executing the compiled Class files. Uses ProgramOutput
.
Models classes:
-
JavaFile - contains the canonical name and class path of a Java file with various convenience methods. Note that the file must actually exist or an
FileNotFoundException
is thrown during instantiation. -
ClassFile - contains the canonical name and class path of a Java file with various convenience methods. Note that the file must actually exist or an
FileNotFoundException
is thrown during instantiation. -
ProgramInput - contains the String input to be fed into the user’s program.
-
ProgramOutput - contains the String output produced by the user’s program. It also contains convenience methods for producing different outputs.
The basic flow of a program evaluation is as follows:
-
TestExecutor
callsclearEnvironment()
ofCompilerEnvironment
to remove any leftover files from previous program evaluations. -
TestExecutor
callscreateJavaFile()
ofCompilerEnvironment
to create the Java file with the correct class name and source code. -
TestExecutor
callscompileJavaFile()
ofCompiler
to compile the newly created Java file. -
For each test case,
TestExecutor
callsexecuteProgram
ofStandardProgramExecutor
with the corresponding input to retrieve aCompletableFuture
of the results. -
TestExecutor
sets a timeout on theCompletableFuture
and maps the result into aTestCaseResult
. -
TestExecutor
packages all the errors and results into a singleTestResult
instance.
-
Note that if the evaluation
CompletableFuture
async task timesout before it is completed, an erroredTestCaseResult
with a "Time limit exceeded!" error message is returned instead. -
Compile errors and runtime errors will also be reflected in the
TestResult
andTestCaseResult
models respectively.
3.1.3. User interaction
In the application, the user’s interactions when submitting a program is as follows:
-
User submits program after typing it into the
Editor
UI component. -
ProgramSubmissionLogic
retrieves the program fromEditor
and evaluates it against the currently attemptingQuestion
inQuestionLogic
. -
ProgramEvaluationPanel
observes the latestTestResult
and reflects new result in the UI.
-
Editor
must have been set as theUserProgramChannel
inProgramSubmissionLogic
. -
ProgramEvaluationPanel
must be observing the test resultObservable
provided byProgramSubmissionLogic
. -
View Section 2.3.4, “ProgramSubmissionLogic implementation” for details about the sequence of events
3.1.4. Implementation details
The implementations of CompilerEnvironment
, Compiler
and ProgramExecutor
are as follows:
-
StandardCompilerEnvironment - utilizes Java11’s native Files package:
-
Creates a temporary folder when instantiated at the file path specified during instantiation.
-
All files are created in this temporary folder.
-
The temporary folder is deleted in
close()
. -
When tasked to create a new file, it first creates an empty file in the temporary folder before writing the contents of the source code to the file
-
-
StandardCompiler - utilizes Java11’s native JavaCompiler package to programmatically compile Java files:
-
Compile errors recorded by the
DiagnosticsListener
class from the compilation task is parsed and thrown asCompileContentException
.
-
-
StandardProgramExecutor - utilizes Java11’s native Runtime class to execute programs programmatically:
-
exec(String command)
of theRuntime
class is used to execute programs on a separate process. -
Each process has its own input and output streams.
-
Test inputs are fed into the input stream.
-
Results and errors are collected from the output stream.
-
The process is destroyed upon completion.
-
3.1.5. Design considerations
Aspect : How the programs are run
Alternative 1 : Use native Java packages and run the program locally (current choice) | Alternative 2 : Host an online server which receives user programs via HTTP requests |
---|---|
Pro : No additional installation requirements is needed from the user |
Pro : Can support multiple languages |
Pro : No internet connection is required |
Pro : Scale of tests can be increased |
Pro : Easy to implement |
Pro : Reduce strain on user’s machine |
Con : Creates files in the user’s machine (dependent on memory/permissions) |
Con : Difficult to implement |
Con : Can only support the execution of Java programs |
Con : Dependent on internet |
3.2. Logging
java.util.logging
package is used for logging. The LogsCenter
class is used to manage the logging levels and logging destinations.
-
The logging level can be controlled using the
logLevel
setting in the configuration file (See Section 3.3, “Configuration”) -
The
Logger
for a class can be obtained usingLogsCenter.getLogger(Class)
which will log messages according to the specified logging level -
Currently log messages are output through:
Console
and to a.log
file.
Logging Levels
-
SEVERE
: Critical problem detected which may possibly cause the termination of the application -
WARNING
: Can continue, but with caution -
INFO
: Information showing the noteworthy actions by the App -
FINE
: Details that is not usually noteworthy but may be useful in debugging e.g. print the actual list instead of just its size
3.3. Configuration
Certain properties of the application can be controlled (e.g test output path, logging level) through the configuration file (default: config.json
).
3.4. Dashboard
The home page of Duke Academy is the main page that the user sees upon app initialization. Not only does it provide an introduction and greeting to the user, it also functions as a personal dashboard.
As a personal dashboard, it presents the user with essential information about his personal progress and learning journey.
Here are three main pieces of information presented to the user: 1. Number of questions completed` 2. Questions that user is still working on 3. Questions that user chose to bookmark for personal reference
To obtain these three pieces of information, we first obtain the ObservableList
that represents all questions in the
storage. We can obtain this ObservableList
, from QuestionLogic
, through a method named getFilteredQuestionsList()
.
The controller class for Home Page, HomePage.java
has a constructor that takes in this ObservableList
. Through
helper methods within the controller class, we can do some processing to the ObservableList
and easily generate the
three pieces of data.
These pieces of information will then be displayed on the Home Page through standard JavaFX controls.
3.5. Problem Statement Panel
Since the problem description cannot be viewed fully from the question list, we introduced a new problem description panel. As shown on Figure 20, when type view [id]
, the panel updates to
display all the additional information a question has to provide.
3.5.1. General Procedure of Command execution:
-
User types
view [id]
in the command box. TheMainApp
class receives the input, calls thecommandLogic
class to executes the command and returns anCommandResult
object.
3.5.2. Implementation Details
The implementation details are narrated following user cases as follows:
-
When the
view
command is executed, it switches the pane to "Question" by calling theapplicationState
object’ssetCurrentActivity(Activity pane)
method. -
It then updates the
questionLogic
object of the current question being viewed by calling itsselectQuestion(int id)
method. -
The
ProblemStatementPanel
UI utilizes a JavaFx@FXML
property calledTextArea
to display information. -
Every time when the
QuestionPage
pane or theWorkspace
pane is displayed, their respective UI controller checks whetherquestionLogic
refers to a question that is currently of interest by the user. If positive, they will call theProblemStatementPanel
controller’ssetProblemStatement(String problemStatement)
to display data.
As such, the functionality required by problem display panel is well covered.
3.5.3. Future Improvement
In version 2.0, we aim to achieve rich text display of problem description. It can be in MarkDown format, containing LaTeX formulas, images, URL links, coloured text, formatted code snippet, etc.
3.5.4. Design Considerations
This is my design consideration on how to update the problem statement panel when a view
command is entered.
-
Alternative 1 (current choice): Use
questionLogic
to track the currentQuestion
being viewed by the user.UI
components can access attributes inLogic
components and display them.-
Pros: More OOP. It is clear that
UI
does not interfere with the tasks responsible by theLogic
component. There is less coupling, making the code easier to understand and undertake testing. -
Cons: Complicates the code base by abstracting another attribute onto the
QuestionLogic
class.
-
-
Alternative 2 : Stores the
Problem Description
content as a String temporarily. UseMainWindow
controller to check whether the command generated is aview
command. If yes, force theProblemStatementPanel
to update.-
Pros: Easy to implement based on the existing code base.
-
Cons: It breaks OOP’s open and close principle. It mixed up
UI
class withLogic
class.
-
3.6. Bookmark Command
The sequence is as follows:
-
User calls execute() on a BookmarkCommand object.
-
The BookmarkCommand object calls getUserSelectedQuestion(), activating an instance of QuestionsLogic.
-
The QuestionsLogic object returns userSelectedQuestion, which is the question the user chose to bookmark.
-
If userSelectedQuestion is already bookmarked, the BookmarkCommand object calls notifyUserNoActionTaken() as a response to the user. Else, the BookmarkCommand object calls bookmarkUserSelectedQuestion(), and then calls notifyUserBookmarkSuccess() as a response to the user.
3.6.1. Design considerations
Aspect : How to bookmark a question
Alternative 1 : Add an instance boolean attribute, isBookmarked, to the Question class | Alternative 2 : Create a global list of bookmarked questions, named bookmarkedQuestions |
---|---|
Pro : Better Object Oriented Design |
Pro : Easy to implement |
Con : All unit tests pertaining to Question objects have to be modified |
Con : Repeated reference to the global list, coupling is higher |
Decision: Alternative 1
Alternative 1 was chosen because good software engineering practices were prioritised over ease of implementation. Firstly, Object Oriented Design from AB3 was maintained. Next, we prevented an increase in coupling, which would reduce the testability of the project.
3.7. Editor Panel
The editor panel is the panel right next to the Problem Display Panel and the Program Evaluation Panel. The editor panel consists of two parts: The main text editor and the line counter component.
The main text editor is where the user codes and is responsible for feeding the text input to the Program Submission
Logic Manager
for compilation of the user-written code. It is capable of performing auto-indentations for the user and
this is achieved by overwriting the function of the Enter key. Through helper methods available in Editor.java
, the
number of unclosed braces can easily be counted so as to perform the appropriate indentations.
There are other modifications to key inputs to make the text editor imitate the behaviour of an actual IDE editor. These
include overwriting the tab
key to input 4 spaces instead of 8, and also performing auto de-indentation when a right brace
(i.e. "}") is typed. Refer to the activity diagram below for the possible outcomes.
The line counter component of the editor keeps track of the number of lines written by the user in the editor. It takes
in a SimpleIntegerProperty
and is updated automatically whenever there are changes to the text observed in the editor.
This is achieved through adding a InvalidationListener
to the text property of the editor, along with using the
necessary helper functions to count the number of newline characters in the text. The Sequence Diagram below shows how
the UI
interacts with the Editor
class to generate the line counter in the text editor.
4. Documentation
Refer to the guide here.
5. Testing
Refer to the guide here.
6. Dev Ops
Refer to the guide here.
Appendix A: Product Scope
Target user profile:
-
has a need to practice a lot of algorithm / data structure problems with the following conditions satisfied:
-
instant assessment of answers submitted
-
practices under timed conditions
-
automatic progress checker
-
personal tutor to recommend problems with suitable difficulties and topics
-
fun in learning with achievement badges to unlock
-
no WiFi needed,
-
-
or has a need to distribute problem sets:
-
can set the coding problems easily
-
share problems via link
-
view-only answers protected by passwords
-
-
prefer desktop apps over other types
-
can type fast
-
prefers typing over mouse input
-
is reasonably comfortable using CLI apps
Value proposition:
-
everyone can learn data structures - anytime, anywhere
-
make coding threshold-less
-
manage contacts faster than a typical mouse/GUI driven app
Appendix B: User Stories
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
|
student from university courses |
search problems by partially matching keywords |
identify the problem I am required to do asap |
|
developer |
introduce new problems to the software easily |
the repository of code challenges can be updated without much hassle |
|
coding student |
look back on the coding challenges I have completed |
revise the concepts used in those problems |
|
job seeker |
view past interview problems by a company |
increase my chances of getting hired |
|
user |
see the difficulties of each problem |
choose to do problems that are more aligned to my standard |
|
developer |
receive detailed auto-generated error reports if any bug occurs |
correct them |
|
forgetful user |
set reminders |
be reminded of the problems that I need to solve before a deadline |
|
unorganized coder |
view my progress on different categories |
know which area I am weak in |
|
programming course student |
attempt problems under timed condition |
I feel more prepared in timed assessments such as labs, practical exam and final exam. |
|
tutor |
choose to reveal the answers to the solutions through a password |
|
|
coder |
identify the concepts required to solve a problem before attempting them |
move on to another quickly |
|
a coding student |
attempt the same problem in different coding languages |
test my proficiency at those languages |
|
coding amateur |
look at hints/tutorials for the problem |
learn something new while attempting a coding challenge |
|
coding student |
share coding challenges with my friends easily |
discuss possible solutions with them |
|
achievement hunter |
view the badges that I have earned (and those that I have not) |
feel a sense of accomplishment |
|
conscientious coding student |
easily identify problems that I have given up on previously |
tackle them again |
|
professor teaching this course |
assign a unique hash code for each problem I input |
students can look for the problems quickly |
|
picky coder |
select different themes for the software |
the user interface looks more appealing to me |
|
programming language polyglot |
specifically choose problems designed in a specific language |
practice that language in focus |
|
coding student |
view similar/related problems to the one I have just completed |
further deepen my understanding of the concepts used |
|
easily distracted coder |
switch off all external distractions |
focus better on the problem I am working on |
|
busy coder |
save my progress on a problem |
come back to it and continue at a later time |
|
competitive programming enthusiast |
set my own questions and pose them to my fellow enthusiast friends to solve |
|
|
student |
see statistics about my attempts/success rates to track my learning progress |
|
|
tutor |
print a pdf version of the coding problem |
give them as practices to my students |
|
competitive coder |
see my areas for improvement after completing a coding challenge |
become a better competitive coder |
|
international student |
view translation of the problem statement |
aids my understanding of the problem |
Appendix C: Use Cases
(For all use cases below, the System is the Duke Academy
and the Actor is the user
, unless specified otherwise)
Use case: UC01 Set questions
MSS
-
User requests to input problem sets.
-
Duke Academy requires a file path.
-
User select file path.
-
Duke Academy imports the problem sets and prompts success message.
Use case ends.
Extensions
-
4a. The input format is incorrect.
Duke Academy reports wrong format error. Duke Academy resumes at step 3.
C.1. Use case: UC02 View Questions
MSS
-
User finds a question by question ID, title or category.
-
Duke Academy shows a list of problems that matches the keyword.
-
User views the question identified by ID.
-
Duke Academy displays the problem statement of the question.
Use case ends.
Extensions
-
1a. User inputs wrong keywords.
Duke Academy reports error and prompts link to help page.
Use case resumes at step 1.
C.2. Use case: UC03 Attempt Questions
MSS
-
User chooses a problem to attempt.
-
Duke Academy shows up the problem statement and an editor.
-
User inputs the code in editor.
-
User submit the answer.
-
Duke Academy compiles the problem and display whether it has passed the test cases.
Use case ends.
Extensions
-
2a. User requests to reset the previous input in the editor for this question.
-
2a1. Duke Academy clears the cached code.
-
Use case resumes from step 3.
-
-
2b. User requests to set a timer.
-
2b1. Duke Academy requests for a time duration.
-
2b2. User inputs a time duration.
-
2b3. Duke Academy displays a timer.
-
2b4. User starts the timer.
Use case resumes from step 4.
-
-
2c. User requests to quit the program.
-
2c1. Duke Academy requests to save the draft.
-
2c2. User confirms or denies.
-
2c3. Duke Academy follows user’s preference to save or discard the draft.
-
2d4. Duke Academy exists.
Use case ends.
-
-
*a. At any time, user chooses to attempt an question imported from external resources.
-
*a1. load the questions from file.
*a2. Duke Academy stores the problem in local machine.
*a3. User search for the problem imported.
*a4. Duke Academy displays the question.
-
Appendix D: 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 problem sets 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.
-
Time taken to assess the submitted programmes should not exceed 3 minutes.
-
Data not intended for disclosure should be encrypted with minimum needs so that it’s protected from direct access.
-
Should not take more than 5 seconds to load the initial screen.
-
If interrupted, the program should provide an auto-saved version and prompt for restore when the app opens next time.
7. Instructions for Manual Testing
Given below are instructions to test the app manually.
These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing. |
7.1. Launch
-
Initial launch
-
Download the jar file and copy into an empty folder
-
Double-click the jar file
Expected: Shows the GUI with the Home tab in focus. The questions tab should contain a list of sample questions
-
7.2. Navigate in the app
7.2.1. Navigate between panes
-
Type
tab
in command box. -
Or use mouse to click the tabs.
7.2.2. Navigate in the Question Pane
-
showall
: list all questions -
browse [keyword]
: find question by topic, difficulty, title, description… etc. It can find multiple keywords at one time. It finds by matching words, not by matching characters. -
find [keyword]
: find by question title. -
view [id]
: views the problem statement of the question with such id. If id is out of range, prompts error.
7.2.3. Navigate to the workspace
-
attempt [id]
7.3. Attempting question
-
Attempting questions
-
Attempt a question
-
Exit the application and reopen it.
Expected: The previous attempt should have been saved automatically
-
-
Submitting solutions
-
Attempt a question
-
Submit the solution
Expected: The application should run the solution against sample test cases and display the results -
Submit a solution with a compile error
Expected: The application should display the compile error in the Workspace tab -
Submit a solution with an infinite loop
Expected: The evaluation should terminate in 5 seconds and a "Time limit exceeded" error is shown -
Submit a solution with a runtime error
Expected: The application should display the runtime error
-
7.4. Bookmarking a question / Removing bookmark for a question
-
Bookmark a question
-
Bookmark any question in the question library. For example, bookmark question 3 through
bookmark 3
. -
Navigate to the Dashboard tab, either through clicking or typing
dashboard
.
Expected: The question you chose to bookmark should be in the list of bookmarked questions.
-
-
Removing a bookmark
-
On the Dashboard, refer to the list of bookmarked questions and pick one question to remove the bookmark.
-
Remove the bookmark for that question. For example,
deletebookmark 3
Expected: The question is no longer in the list of bookmarked questions.
-
7.5. Creating notes
-
Creating notes
-
Create a new note
Expected:
The new note should be loaded into the Notes tab
The sketchpad should be available for drawing
The note text input should also be available for editing
-
-
Deleting notes
-
Delete a note
Expected: The new note should no longer be reflected in the GUI
-
-
Saving notes
-
Create a new note
-
Edit the note however you like
-
Save the note
-
Restart the app
Expected: The changes to the note should be saved and reflected in the app
-
7.6. Loading Custom Questions
-
Load question files prepared by developers
-
type
loadquestions NewProblems.txt
in the command box.
Expected: The Question List is updated with newly loaded questions namedApple
andBanana
.
-
-
Question file in wrong format
-
Navigate to to the
DukeAcademy/newQuestions/NewProblems.txt
file. TheDukeAcademy
folder is in the same directory as where you put the jar file. -
Change
Difficulty: EASY
toDifficulty: easy
.
Expected: Prompts an error. -
Other ways include changing Topics to invalid values or uncapitalized words.
-
-
Question file not saved in specified location
-
Drag the file to Desktop and re-enter
loadquestions NewProblems.txt
.
Expected: Prompts an error.
-
-
Entered commands with wrong file name
-
Type in command box
loadquestions newproblem
or any unexistant file.
Expected: Prompts an error.
-
-
Load your own set of questions
-
You can directly edit from the
NewProblems.txt
file. Description can be multi-lined, as long as the identifiers (e.g.Difficulty:
) occupy a single line.
Expected: New questions are loaded. -
Alternatively, you can create questions from scratch. The instructions below are copied from user guide.
-
Create a .txt file.
-
The format of a question goes like follows:
-
-
Question:: Title:: Description:: Difficulty:: Topics:: TestCase:: Input:: Output::
Some notes:
-
All inputs must be in the order stated above.
-
Title, Description can be any non-empty string.
-
Difficulty can only be EASY, MEDIUM or HARD. (Must be capitalized)
-
Topics can only be ARRAY, LINKED_LIST, HASHTABLE, TREE, GRAPH, RECURSION, DIVIDE_AND_CONQUER, DYNAMIC_PROGRAMMING, SORTING, or OTHERS. (Must be capitalized)
-
One question can only have one title, description and difficulty. It can have multiple topics separated by
,
. It can have multiple test cases, each begin with aTestCase::
identifier.