By: Team CS2103T-W11-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.
The .puml files used to create diagrams in this document can be found in the diagrams folder.
Refer to the Using PlantUML guide to learn how to create and edit diagrams.
|
-
At app launch: Initializes the components in the correct sequence, and connects them up with each other.
-
At shut down: Shuts down the components and invokes cleanup method where necessary.
Commons
represents a collection of classes used by multiple other components.
The following class plays an important role at the architecture level:
-
LogsCenter
: Used by many classes to write log messages to the App’s log file.
The rest of the App consists of five components.
Each of the five components
-
Defines its API in an
interface
with the same name as the Component. -
Exposes its functionality using a
{Component Name}Manager
class.
For example, the Logic
component (see the class diagram given below) defines it’s API in the Logic.java
interface and exposes its functionality using the LogicManager.java
class.
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 deleteprob 1
.
deleteprob 1
commandThe Sequence Diagram below shows how the components interact with each other for the scenario where the user switches tabs in the GUI.
The sections below give more details of each component.
2.2. UI component
API :
Ui.java
The UI
component consists of a MainWindow
that is made up of parts
e.g.CommandBox
, ResultDisplay
, DetailsTabPane
, DisplayTabPane
, TaskManagementPane
, StatusBarFooter
etc.
All these components, including the MainWindow
, inherit from the abstract UiPart
class.
The DetailsTabPane
consists of FindRuleListPanel
, PlanListPanel
, ProblemListPanel
and TagListPanel
,
which are used for displaying entries of FindRule
, Plan
, Problem
and Tag
stored in AlgoBase respectively.
The UI
component uses JavaFx UI framework.
The layout of these UI parts are defined in matching .fxml
files that are in the src/main/resources/view
folder.
For example, the layout of the MainWindow
is specified in MainWindow.fxml
The UI
component,
-
Executes user commands using the
Logic
component. -
Listens for changes to
Model
data so that the UI can be updated with the modified data.
2.3. Logic component
API :
Logic.java
-
Logic
uses theAlgoBaseParser
class to parse the user command. -
This results in a
Command
object which is executed by theLogicManager
. -
The command execution can affect the
Model
(e.g. adding a problem). -
The result of the command execution is encapsulated as a
CommandResult
object which is passed back to theUi
. -
In addition, the
CommandResult
object can also instruct theUi
to perform certain actions, such as displaying help to the user.
Given below is the Sequence Diagram for interactions within the Logic
component for the execute("deleteprob 1")
API call.
deleteprob 1
Command
The lifeline for DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
|
2.4. UiLogic Component
API :
UiLogic.java
-
Performing an action (e.g. switching tabs) triggers the creation of a
UiActionDetails
object. -
UiLogic
uses theAlgoBaseUiActionParser
class to parse theUiActionDetails
object. -
This results in a
UiAction
object which is executed by theUiLogicManager
. -
The command execution can affect the
Model
(e.g. deleting a problem). -
The result of the command execution is encapsulated as a
UiActionResult
object which is passed back to theUi
. -
In addition, the
UiActionResult
object can also instruct theUi
to perform certain actions, such as displaying the results as feedback to the user.
UiActionDetails
with a UiActionType
of editPlanUiAction
. This UiActionDetails
also contains the ID of the problem to be deleted, in this case 11b
.
The lifeline for EditProblemUiActionParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
|
2.5. Model component
API :
Model.java
The Model
,
-
stores a
UserPrefs
object that represents the user’s preferences. -
stores the AlgoBase data.
-
exposes unmodifiable
ObservableList<Problem>
,ObservableList<Tag>
,ObservableList<Plan>
,ObservableList<Task>
,ObservableList<ProblemSearchRule>
that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. -
does not depend on any of the other three components.
We organize different data classes into packages (e.g. Problem
), inside which we provide a collection class of that data object (e.g. UniqueProblemList
) so that AlgoBase
can manage these data objects without knowing the details of each data class.
Note that we don’t require plans to be unique, thus unlike problems' collection class is named UniqueProblemList
, plan’s collection is simply named PlanList
.
Both problemsearchrule
and plansearchrule
are packaged under searchrule
and they share similar internal structure - note that saving find rule feature only supports saving problem search rule, thus there’s no subclass for FindPlanDescriptor
.
As we support preserving the GUI state, we included GuiState
as a part of AlgoBase's model.
2.6. Storage component
API :
Storage.java
The Storage
component,
-
can store
UserPrefs
objects inJSON
format. -
can retrieve
UserPrefs
objects fromJSON
format. -
can store the AlgoBase app data including
GuiState
,Plan
,Problem
,ProblemSearchRule
,Tag
,Task
objects in relational manner inJSON
format. -
can retrieve
GuiState
,Plan
,Problem
,ProblemSearchRule
,Tag
,Task
objects from data stored inJSON
format.
2.7. Common classes
Classes used by multiple components are in the seedu.algobase.commons
package.
It contains utility files for configuration ConfigUtil
, file handling FileUtil
,
JSON storage JsonUtil
, string manipulation StringUtil
and others including AppUtil
and CollectionUtil
.
3. Implementation
This section describes some noteworthy details on how certain features are implemented.
3.1. Task Management Feature
As an algorithmic problem management tool, one of the most important features will be managing tasks that have been done or are to be done.
This section will describe in details the current implementation and design considerations of the task management feature.
3.1.1. Current Implementation
The task management feature supports eight main operations:
-
AddTask
- creates a new task for a problem and add it to a specified plan. -
CopyTask
- copies a task from one plan to another. -
DeleteTask
- deletes an existing task from a specified plan. -
DoneTask
- marks a task as done in a specified plan. -
EditTask
- edits the due date of a task in a specified plan. -
MoveTask
- moves a task from one plan to another. -
SetPlan
- sets a plan as the current plan in main display. -
UndoneTask
- marks a task as undone in a specified plan.
This feature is mainly supported by the Task
class.
Given below is the class diagram of the Task
class.
Given below is an example usage scenario and how the mechanism for adding tasks behaves at each step.
The following activity diagram summarizes what happens when a user executes the AddTaskCommand
:
AddTaskCommand
Step 1. The user launches the application.
Step 2. AlgoBase displays a list of existing problems and plans in the UI.
Step 3. The user executes addtask plan/1 prob/1
to add the problem with index 1 in the list to the plan with index 1.
The AddTaskCommand
calls Model#updateTasks
to create a new plan from the original plan with this additional task,
and replace the original plan with this updated plan in the PlanList
stored in AlgoBase
.
The sequence diagram below shows the high-level abstraction of how AlgoBase processes user request
to execute addtask plan/1 prob/1
:
addtask plan/1 prob/1
The following sequence diagram illustrates the interaction between the Logic
and Model
components
while executing AddTaskCommand
:
AddTaskCommand
3.1.2. Design Considerations
Aspect: Data structure to support the task commands.
-
Alternative 1 (current choice): Use a
HashSet
to store tasks in a plan.-
Pros: Duplicate tasks can be checked easily.
-
Cons: Harder to identify tasks by index.
-
-
Alternative 2: Use an
ArrayList
to store tasks in a plan.-
Pros: Tasks can be identified by index easily.
-
Cons: Harder to check for duplicate tasks.
-
Aspect: How to store problem details within tasks to support the task commands.
-
Alternative 1 (current choice): Store a problem object in each task.
-
Pros: Changes in problem details will be reflected in the relevant tasks as well.
-
Cons: Relational storage is required to keep track of this relationship.
-
-
Alternative 2: Copy all problem details and store as separate fields in each task.
-
Pros: No need to implement relational storage. There will be less coupling between problems and tasks as well.
-
Cons: Changes in problem details cannot be reflected in the relevant tasks easily.
-
Aspect: Relational storage to support the task commands.
-
Alternative 1 (current choice): Use an additional
id
field to identify problems and tasks.-
Pros: The id field is kept immutable over time, thus ensuring integrity.
-
Cons: An additional field is needed for the models.
-
-
Alternative 2: Use object hash to identify problems and tasks.
-
Pros: No need to store another additional field in the models.
-
Cons: Object hash can change over time.
-
3.2. Tag feature
3.2.1. Implementation
The tag mechanism is facilitated by UniqueTagList. It creates a list of Tag, stored internally as an uniqueTagList. Additionally, it implements the following operations:
-
AddTag
- creates a new tag in AlgoBase’s uniqueTagList in the algobase history. -
DeleteTag
- deletes a current tag which have already in the uniqueTagList. -
EditTag
- edits the current tag name which have already been in theuniqueTagList
. -
ListTag
- shows the tags in the uniqueTagList in the algobase GUI for users.
These operations are exposed in the Model interface as Model#addTag()
, Model#deleteTag()
, Model#listTag()
and Model#editTag()
respectively.
Given below is an example usage scenario and how the tag mechanism behaves at each step.
Step 1. The user launches the application for the first time. The UniqueTagList will be initialized with the initial algobase state
Step 2. The user executes addtag t/easy
to add a tag named [easy] with default color which have not applied in any problems. The addtag command calls Model#addtag()
, causing the taglist added a tag after the ‘addtag t/easy’ command executes to be saved in the uniqueTagList.
The following sequence diagram shows how the addtag
operation works:
AddTagCommand
Step 3. The user decides to execute the command listtag
to show a tag list in the GUI of algobase. The listtag
command calls Model#listtag()
, causing the taglist shows the current components of uniqueTagList. Commands that do not modify the data, such as listtag
, will not call Model#addTag()
, Model#deleteTag()
or Model#editTag()
. Thus the uniqueTagList
remains unchanged.
Step 4.The user executes edittag 1 t/hard c/BLUE
to edit the current tag [easy] to [hard] in the uniqueTagList
. The edittag 1 t/hard c/BLUE
Command executes edittag
, causing the taglist find the tag with index 1 in the tag list and change tag [easy] into [hard] and change tag color from default color to blue, and change all [easy] tag into [hard] in blue color in all problems.
Step 5. The user executes deletetag t/hard
to delete the current tag [easy] in the uniqueTagList. The deletetag t/hard
command executes deletetag
, causing the taglist delete the [hard] tag in uniqueTagList and [hard] tag in all problems.
(diagram)
The following activity diagram summarizes what happens when a user executes a new tag modifying command
3.2.2. Design considerations
Aspect: Data structure to support the tag commands.
-
Alternative 1 (current choice): Use a list in current AlgoBase to save the content of different tags which used in tagging different problems. While problems create new tags for problems, it will also add into tag-list in AlgoBase. While the tag in problems changes, the tag in tag-list will not change and add a new tag into the tag-list in AlgoBase. While modifying tag in tag-list will change the tag for all related problem.
-
Pros: Users can manage the tags conveniently.
-
Cons: May lead to many tags do not combine with problems.
-
-
Alternative 2: Simply keep tags as a part of problems. While execute the tag command will search for all tags in problems for every times it execute.
-
Pros: No need to save the tag separately in the storage, all tags are under problems.
-
Cons: Difficult to manage tags in different problems. Waste time for computer to execute.
-
3.3. Find Problem Feature
Since AlgoBase is a management tool for algorithmic questions, the search functionality is crucial to the user’s experience with AlgoBase. For instance, the planning feature heavily relies on findprob
command to determine the exact set of problems the user wants to include in a training plan.
This section will describe in detail the current implementation and design considerations of the find problem feature (i.e. search feature) of AlgoBase.
The following activity diagram summarizes what happens when a user executes the findprob
command:
findprob
Command3.3.1. Current Implementation
The find problem feature mainly involves three parts:
-
validating and parsing user input
-
creating a filtering predicate from user’s search constraints
-
update the displayed problem list with the filtering predicate.
The find problem feature is facilitated by the following classes:
-
FindProblemDescriptor
It stores predicates that are needed to describe a
FindCommand
Additionally, it implements the following operation(s):
-
FindProblemDescriptor#isAnyFieldProvided()
- Determines if there is at least one search restriction included in this instance ofFindProblemDescriptor
. -
FindProblemDescriptor#equals(…)
- Two instances ofFindProblemDescriptor
are equal if and only if all of their predicates are equal.
-
-
FindCommandParser
It validates and parses user input to an instance ofFindCommand
.
If the user provides difficulty range as one of the search restrictions, FindCommandParser expects the format LOWER_BOUND <= difficulty <= UPPER_BOUND while LOWER_BOUND and UPPER_BOUND are valid strings for doubles (i.e. parsable by Double.parseDouble(…) ).
|
-
FindCommand
It creates and stores the
predicate
from an instance ofFindProblemDescriptor
.predicate
is used to perform the filtering of the displayed problem list when the command is executed.predicate
returns true only when the provided problem fulfills all restrictions described by the provided instance ofFindProblemDescriptor
.Additionally, it implements the following operation(s):
-
FindCommand#execute(…)
- This method overridesCommand#execute(…)
. It filters problems infilteredProblemList
inmodel
withpredicate
. -
FindCommand#equals(…)
- Two instances ofFindCommand
are equal if and only if theirpredicate
are equal.
-
-
Predicates that implements interface
Predicate<Problem>
These are classes that describes whether an instance of
Problem
is considered a match under a certain field with provided keyword(s).-
NameContainsKeywordsPredicate
-
It ignores case.
-
It returns true as long as one of the keywords appear in the name as a word. (“As a word” means the matching is done word by word. For instance,
hello
doesn’t matchhelloworld
.)
-
-
AuthorMatchesKeywordPredicate
-
It is case sensitive and matches the entire author string (i.e. requires an exact match).
-
-
DescriptionContainsKeywordsPredicate
-
It ignores case.
-
It returns true only when all of the keywords appear in the description as a word.
-
-
SourceMatchesKeywordPredicate
-
It requires an exact match.
-
-
DifficultyIsInRangePredicate
-
It matches problems with LOWER_BOUND <= difficulty <= UPPER_BOUND
-
-
TagIncludesKeywordsPredicate
-
Each keyword will be considered as a tag, and two tags are considered equal only when their names are exactly the same (i.e. an exact match).
-
It returns true when the provided tags are a subset of the tags of the provided problem.
-
-
Given below is an example usage scenario and how the find problem mechanism behaves at each step.
Step 1. The user executes findprob t/recursion diff/2.0-4.0
to find a problem with a tag “recursion” and difficulty between 2.0 and 4.0.
Step 2. FindCommandParser
processes the user input and returns a FindCommand
instance with the information of user’s search restrictions.
If no valid search restriction is provided by the user, FindCommandParser will throw a parsing exception, which is handled and displayed to the user.
|
Step 3. LogicManager
invokes execute()
method of the returned FindCommand
. FindCommand
updates the problem list with user’s search constraints.
findprob
Command3.3.2. Design Considerations
Aspect: How to update the displayed problem list in the UI
-
Alternative 1 (current choice): Let UI display problems in a
FilteredList<Problem>
and update the displayed problem by callingsetPredicate
on theFilteredList
.-
Pros: Provides good protection over unexpected changes on the displayed problem list.
-
Cons: Need to write a complex logic to generate one predicate out of multiple search constraints.
-
-
Alternative 2: Let UI displays problems in an
ObservableList<Problem>
and update the list directly.-
Pros: The implementation would be more straightforward as the logic can update the displayed list directly.
-
Cons: Leaves room for potential unexpected changes on the displayed problem list as the observable list is open to any kind of operation.
-
Aspect: How to deal with the case where no search restriction is provided (i.e. user types in findprob
with no arguments given)
-
Alternative 1 (current choice): Treat it as an exception and notify the user to provide at least one constraint.
-
Pros: Makes the meaning of
findprob
command clear - you can’t search for problems without giving any conditions. -
Cons: Has to check there is at least one predicate provided, making the implementation a bit more complicated.
-
-
Alternative 2: Treat it as no restriction (i.e.
findprob
is equivalent tolist
in this case)-
Pros: Easier implementation (if all predicates are always-true predicates, using
.and
method to chain them together would naturally result in an always-true predicate). -
Cons: Confusing definition of the search feature.
-
Aspect: How to make predicates optional (i.e. user doesn’t have to provide restrictions for all searchable fields)
-
Alternative 1 (current choice): Use
FindProblemDescriptor
in which the getter for the predicate returnsOptional<Predicate>
.-
Pros: If the parser doesn’t receive keyword(s) for a specific field, it simply doesn’t call the descriptor’s setter for that field. It doesn’t need to deal with
null
, andnull
is dealt gracefully usingOptional.ofNullable(…)
-
Cons: Rather troublesome implementation of the descriptor.
-
-
Altermative 2: Store predicates in
FindProblemCommand
and check for not-provided predicates by comparing it withnull
.-
Pros: More straightforward implementation.
-
Cons: If we are to add more predicates, it’s more likely that we forget to check
null
value of the new predicate.
-
3.4. Save Find Rules Feature
AlgoBase provides many ways to organizing your problems including tags and plans. However, both organizing features require persistent user involvement - if the user added a new problem belonging to a category, the user needs to manually assign a tag to the problem or add the problem to a plan. Since AlgoBase’s findprob
command enables the user to filter problems with great flexibility, we allow them to save certain find rules so that they can re-apply these rules to quickly locate problems of their need.
This section will describe in detail the current implementation and design considerations of the save find rules (or problem search rules) feature of AlgoBase.
The following activity diagram summarizes what happens when a user executes addfindrule
command:
addfindrule
Command3.4.1. Current Implementation
The save find rules feature is facilitated by the following classes:
-
ProblemSearchRule
It stores both theName
of the find rule and all predicates included in this find rule. AProblemSearchRule
doesn’t have to include all possible predicates as the user may not provide all of them. Missing predicates will be stored asnull
in this class. -
UniqueFindRuleList
It stores the find rules and makes sure that every find rule in this list has a unique name.-
UniqueFindRuleList
stores aObservableList<ProblemSearchRule>
for UI purposes.
-
Except for ProblemSearchRule , we refer to these rules as FindRule in all other places. This is to prevent possible naming conflicts if AlgoBase is to support saving find rules on other items (e.g. Plans, etc.). FindRule corresponds to FindCommand . Thus, if you are to implement saving find plan rules, name them as PlanSearchRule , AddFindPlanRuleCommand , UniqueFindPlanRuleList , etc.
|
Under the category of save find rules feature, we have the following Command
classes and their corresponding Parser
classes:
-
AddFindRuleCommand
-
DeleteFindRuleCommand
-
ApplyCommand
It applies a problem-finding rule by specifying the index of the displayed find rule.
Since these commands share similar implementations, we will only take AddFindRuleCommand
as an example since it’s the most complicated one among the three.
Implementation of addfindrule
feature
The addfindrule
feature is facilitated by AddFindRuleCommand
and AddFindRuleCommandParser
class.
The sequence diagram below shows the high-level abstraction of how AlgoBase processes the request when user types in addfindrule rule1 n/Sequences
:
addfindrule rule1 n/Sequences
The sequence diagram below illustrates the interaction between the Logic
and Model
component when executing AddFindRuleCommand
. Notice that the constructor for ProblemSearchRule
requires Name
to be non-null and accepts null values for other predicates. Thus if the predicate is not present in the arguments, AddFindRuleCommandParser
will pass null to the constructor of ProblemSearchRule
.
addfindrule
Command3.4.2. Design Considerations
Aspect: To implement ProblemSearchRule
as a subclass of FindProblemDescriptor
or implement it as an immutable concrete class.
Since AlgoBase is forked from AddressBook 3, it also inherits AB3’s design choice on all data classes - they are all immutable classes with all fields being final
. However, ProblemSearchRule
is essentially saving the information of a command input, where the user may provide any number of predicates as the argument. We implement mutable FindProblemDescriptor
to accommodate variable user inputs, now we have to consider whether to keep ProblemSearchRule
immutable or not.
-
Alternative 1 (current choice):
ProblemSearchRule
extendsFindProblemDescriptor
with an additional fieldname
-
Pros: Greatly reduces the amount of duplicate code as
ProblemSearchRule
shares most fields withFindProblemDescriptor
-
Cons:
ProblemSearchRule
as a data class is no longer immutable. We have to be careful not to call any setters it inherits fromFindProblemDescriptor
.
-
-
Alternative 2:
ProblemSearchRule
as an individual class with immutable fields.-
Pros: Provides good protection over unexpected changes to the data fields.
-
Cons: Lots of duplicated code.
-
3.5. Graphical User Interface Features
An intuitive GUI facilitates the overall user friendliness of the application. The user should be able to navigate around the application easily to facilitate a smooth experience using AlgoBase. While the command line is fast for typing short commands, it us not ideal if the user is editing large amounts of text (e.g. when the user is adding description for a new problem). In this case, having a GUI will be more beneficial to the user and facilitates a smoother user experience.
Additionally, multitasking is important as a user may be tackling multiple algorithmic questions at a single time. This, we introduced tabbing, which facilitates multitasking in AlgoBase, which is an important requirement for competitive programmers.
3.5.1. Graphical User Interface Enhancements
Current Implementation
The following classes facilitate the handling of GUI actions:
-
UiActionType
- An Enum of the types of UI actions that exist in AlgoBase. -
UiActionDetails
- An object containing details of a UI action. -
UiAction
- Interface with instructions for executing a UI action. -
UiLogicManager
- ImplementsUilogic
and manages the overall UI Logic. -
AlgoBaseUiActionParser
- Parses aUiActionDetails
object into an implementation ofUiAction
. -
UiActionResult
- The result of executing the UI action.
When the user makes a change in the GUI, the change is propagated from Ui
to UiLogic
to Model
and to Storage
, as represented in the diagram below:
This process of how the application handles UI Actions is captured by the example in the Sequence Diagrams below:
UI
and UiLogic
Step 1: The user edits the ProblemDetails
controller class through his/her actions in the GUI.
Step 2: The ProblemDetails
class constructs a new UiActionDetails
object of type UiActionType.EditProblem
.
Step 3: The executeUiAction
of the MainWindow
class is called with the UiActionDetails
object,
which in turn calls the execute
method of UiLogicManager
.
Step 4: The method call returns a UiActionResult
object, which may optionally contain feedback for the user.
The following diagram goes into more details on how the UiLogic
handles the UiActionDetails
:
UiLogic
component.Step 1: The UiLogicManager
passes the UiActionDetails
object to the AlgoBaseUiActionParser
,
which in turn passes it to the EditProblemUiActionParser
based on its Action type.
Step 2: The EditProblemUiActionParser
converts the UiActionDetails
object into a EditProblemUiAction
object,
and passes it back to the UiLogicManager
.
Step 3: The UiLogicManager
executes the EditProblemUiAction
together with the Model
, and returns the UiActionResult
.
3.5.2. Graphical User Interface State
Current Implementation
The state of the GUI is stored in a GuiState
object, which is in turn stored in the Model
. The GuiState
object contains a TabManager
object, which manages tab information such as the tabs that are open and the tabs that are currently selected.
The following class diagram illustrates how the classes in the GuiState
interact with one another:
GuiState
classThe following Activity diagram illustrates the series of actions that occur when the user opens a new tab:
In AlgoBase, the state of the GUI is also saved to Storage after every action. This is so that when the user closes the application and opens it again later, the state is stored. The Sequence diagram below also shows how the GuiState is saved to Storage:
The StorageManager
saves the modified GuiState
as a new JSON
file.
This is done with the help of the JsonSerializableGui
, JsonSerializableTabManager
and JsonSerializableTab
classes that are wrappers for the GuiState
, TabManager
and TabData
classes.
These wrapper classes can be converted into JSON
format for storage without any data loss.
Design Considerations
Aspect | Alternative 1 (Current Choice) | Alternative 2 |
---|---|---|
How to implement Commands and UI Actions in the same application |
Handle Commands and UI Actions separately. Pros: Higher modularity. Allows separation the different architectures as well (Synchronous for Commands & Event-Driven for UI Actions) Cons: Multiple Logic managers (LogicManager and UiLogicManager) |
Handle Commands and UI Actions together. Pros: Less code and higher reusability. Cons: Higher coupling and less cohesion. |
How to handle different kinds of UI Actions |
Using a command structure with a central parser and many smaller parsers. Pros: Higher extensibility, easier to add new UI Actions Cons: Have to write more code to achieve the same functionality. |
Handling each UI action individually. Pros: Can write less code to achieve the same functionality. Cons: Lower extensibility, harder to add new UI Actions |
3.6. Command Line Tab Management
3.6.1. Current Implementation
The following commands facilitate the management of tabs:
-
switchTab
- Switch between tabs within a specified Tab pane. -
openTab
- Opens a new tab containing details of a model. -
closeTab
- Closes an existing tab.
These operations are exposed in the TabManager
class respectively as:
-
SwitchTab
:TabManager#switchTab
-
OpenTab
:TabManager#openTab
-
CloseTab
:TabManager#closeTab
The following Activity Diagrams illustrate what happens when the user executes a SwitchTabCommand
or OpenTabCommand
switchtab
Commandopentab
CommandGiven below is an example usage scenario and how the tag mechanism behaves at each step.
SwitchCommand
objectStep 1: The user executes switchtab tt/display i/1
to switch to the first tab in the display
tabpane.
Step 2: SwitchTabCommandParser
processes the user input, retrieving the tab type (display
) and the index (1
).
Step 3: These two attributes are passed into the constructor of a SwitchTabCommand
and a corresponding SwitchTabCommand
object is returned to the LogicManager
Step 4: LogicManager
invokes execute()
method of the returned SwitchTabCommand
, which retrieves the TabManager from the Model
object. The setDisplayTabPaneIndex(1)
method is invoked with the index 1 that the SwitchTabCommand
was instantiated with.
Step 5: Invoking this method updates the integer value in the displayTabIndex
field (type ObservableIntegerValue
) of the TabManager
.
Step 6: A listener was added to the displayTabIndex
field when the application was initialized. When a change in the value is detected, it triggers the selectTab(1)
method with the value of the new index passed as an argument. This updates the selected tab in the UI.
Step 7: After the command is executed, the state of the GUI changes. This causes the StorageManager
to save the modified GUI state as a new JSON
file.
This is done with the help of the JsonSerializableGui
, JsonSerializableTabManager
and JsonSerializableTab
classes that are wrappers for the GuiState
, TabManager
and TabData
classes.
These wrapper classes can be converted into JSON
format for storage without any data loss.
3.6.2. Design Considerations
Aspect | Alternative 1 (Current Choice) | Alternative 2 |
---|---|---|
Implementation of Tab Logic |
Implement Tab Logic separately within model and UI. Pros: Modularizes the logic and reduces the need for tighter coupling between model and UI Cons: Multiple sources of truth and more modules to be implemented |
Implement Tab Logic as a singular module Pros: Single source of truth for state of tabs Cons: Increasing coupling between Model and UI, which in turn reduces testability |
How to update the tab in the UI |
Using a listener to detect changes to state of tab Pros: Reduces coupling between the Cons: As callback functions are utilized, it is not immediately obvious how changes in state of TabManager leads to a change in the UI |
Updating the UI synchronously Pros: Execution is sequential and it is easier to keep track of the flow of the program. Cons: Increases coupling between the |
3.7. Training Plan Feature
Training plan feature allows users to create customized training plans with specific starting date and end date and that consist of selected problems in AlgoBase. Each problem is wrapped up as a task in the plan. Users can record their progress by marking problems in plans as done or undone, and they can edit, delete or search for plans.
3.7.1. Current Implementation
The training plan mechanism is faciliated by AlgoBase
, which keeps a list of training plans. It supports the following operations:
-
Algobase#addPlan()
— Adds a new training plan. -
AlgoBase#setPlan()
— Replaces an existing plan by an edited version. -
AlgoBase#removePlan()
— Deletes a training plan. -
AlgoBase#getPlanList()
— Returns a list of training plans.
Plan
Given below is an example usage scenario and how the AlgoBase behaves at each step.
Step 1. The user launches the application for the first time. The AlgoBase
will be initialized with the initial empty state.
Step 2. The user switches to the plan tab and executes addplan n/CS2040 d/past year questions start/2019-01-01 end/2019-05-04
command to add a new plan to AlgoBase. The addplan
command checks if Model#hasPlan()
and calls Model#addPlan()
, causing the modified state of plans after the addplan
command executes to be saved in the PlanList
.
AddPlanCommand
Step 3. The user executes listplan
to list all plans. The listplan
command calls Model#updateFilteredPlanList()
. The plan CS2040
is numbered 1
in the displayed list.
Step 4. The user finds out that the exam date of CS2040 has changed, and decides to change the end date of the training plan by executing the editplan 1 end/2019-05-05
command. The editplan
command will check if Model#hasPlan()
, and then call Model#setPlan()
and Model#updateFilteredPlanList()
, which will replace the original plan with the modified plan in the PlanList
.
EditPlanCommand
The user can also add value for an empty field by executing editplan command if the field has not been specified when adding the plan.
|
Step 5. The user then decides to execute the command findplan start/2019-03-01 end/2019-03-31
to find out what plans he has in March. The findplan
command constructs a FindPlanDescriptor
, and then executes Model#getFilteredPlanList()
and Model#updateFilteredPlanList(FindPlanDescriptor)
. A list of plans in AlgoBase that has overlapping time range with the specified starting date and end date will be displayed on the plan list panel.
FindPlanDescriptor
If the user wants to find plans with overlapping time range, both the starting date and the end date should be specified, and the starting date should be before or at least equal to the end date, or an error message will be displayed to inform the user the correct form of input. |
Step 6. The user executes deleteplan 1
, which calls Model#getFilteredPlanList()
and Model#deletePlan
. The Model#getFilteredPlanList()
returns the last shown plan list, which is list of plans returns by the findplan
command in step 4. Therefore, the first plan with overlapping time range is deleted.
3.7.2. Design Considerations
Aspect: Data Structure of TimeRange class
-
Alternative 1 (current choice): Abstract out a
TimeRange
class in packageplansearchrule
.-
Pros: Easy to implement.
-
Cons: Generating a
TimeRange
object infindplan
command adds coupling, and is not very intuitive.
-
-
Alternative 2: Abstract out
startDate
andendDate
fields in plans to a single fieldTimeRange
.-
Pros: More OOP (
startDate
andendDate
are currentlyLocalDate
objects). -
Cons: We must ensure that the implementation complies with other date-related commands and storage of plans, such as adding or editing due dates of tasks in plans and the json file.
-
Aspect: How to find plans with certain tasks
-
Alternative 1 (current choice): By exactly-matching names.
-
Pros: Easy to implement.
-
Cons: Users need to figure out the exact name of the task they would like to find, which is more time-consuming.
-
-
Alternative 2: By indicating index of the original problem.
-
Pros: Complies with other usages of prefix
task/
. -
Cons: Adds coupling due to access to
filteredProblemList
in the model.
-
-
Alternative 3: By exactly-matching tags of the original problem.
-
Pros: User-friendly.
-
Cons: Adds coupling due to access to
filteredProblemList
in the model as the wrapped-up task does not have a tag list field.
-
Appendix A: Product Scope
Target user profile:
-
has a need to manage a significant number of contacts
-
prefer desktop apps over other types
-
can type fast
-
prefers typing over mouse input
-
is reasonably comfortable using CLI apps
Value proposition:
-
To manage algorithmic problems and training plans faster than using Excel sheets
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… |
---|---|---|---|
|
new user |
see usage instructions |
refer to instructions when I forget how to use the App |
|
user |
add a new problem |
keep track of the problems for future usage |
|
user |
delete a problem |
remove entries that I no longer need |
|
user |
find a problem by keyword |
locate details of problems without having to go through the entire list |
|
user |
do advanced search on problems |
locate details of problems without having to go through the entire list |
|
user |
do fuzzy search on problems |
locate details of problems without having to go through the entire list |
|
user |
create custom tags |
categorize problems via tags |
|
user |
add tags to problems |
categorize problems via tags |
|
user |
sort problems according to difficulty |
locate problems easily |
|
user |
add remarks to problems |
have reference in the future |
|
user |
create plans containing problems |
better prepare for interview |
|
user |
add tasks to a plan |
better prepare for interview |
|
user |
mark tasks as done/undone within plans |
keep track of progress within each plan |
|
user |
edit due dates of tasks |
better manage progress for each plan |
|
user |
move tasks among plans |
better manage progress for each plan |
|
user |
import database from JSON files |
easily transfer data from one computer to another |
|
user |
export data into JSON format |
easily transfer data from one computer to another |
|
advanced user |
export data into CSV format |
do some manipulation/processing on the data |
Appendix C: Use Cases
(For all use cases below, the System is the AlgoBase
and the Actor is the user
, unless specified otherwise)
Use Case 1: Add Problems
MSS
-
User requests to add a new problem by entering the name of the problem, optionally specifying the description, author, weblink, source as well as any remarks or tags.
-
AlgoBase adds a new problem with the provided details.
-
AlgoBase indicates successful addition of new problem.
-
AlgoBase displays details of problem added.
Use case ends.
Extensions
-
2a. AlgoBase detects that an existing name already exists.
-
2a1. AlgoBase informs user that problem was not successfully added because the name already exists.
Use case ends.
-
-
2b. AlgoBase detects that name is missing or format for some field(s) is invalid.
-
2b1. AlgoBase informs user that problem was not successfully added because the format is invalid.
Use case ends.
-
Use Case 2: Edit Problems
MSS
-
User requests to edit an existing problem by entering the index, followed by fields that the user intends to edit (including name, description, weblink, author, source, remark, tag, etc.).
-
AlgoBase edits the problem using the provided details.
-
AlgoBase indicates successful edition of the existing problem.
-
AlgoBase updates the UI with the updated problem.
Use case ends.
Extensions
-
2a. AlgoBase detects that the index is out of bounds.
-
2a1. AlgoBase informs user that the edition is unsuccessful because the index is out of bounds.
Use case ends.
-
-
2b. AlgoBase detects that no fields are provided.
-
2b1. AlgoBase informs user that nothing is updated.
Use case ends.
-
Use Case 3: Delete Problems
MSS
-
User requests to delete an existing problem by entering index.
-
AlgoBase deletes the problem from storage.
-
AlgoBase indicates successful deletion of the existing problem.
-
AlgoBase updates the UI with the remaining problems.
Use case ends.
Extensions
-
2a. AlgoBase detects that the index is out of bounds.
-
2a1. AlgoBase informs user that the deletion is unsuccessful because the index is out of bounds.
Use case ends.
-
Use Case 4: List Problems
Guarantees
A list of existing problems will be displayed.
MSS
-
User requests for a list of all existing problems.
-
AlgoBase retrieves all problems in storage.
-
AlgoBase displays in the UI the list of problems stored in AlgoBase.
Use case ends.
Extensions
-
2a. AlgoBase detects no existing problems stored.
-
2a1. AlgoBase informs user that there is no existing problems.
Use case ends.
-
Use Case 5: Find Problems
Guarantees
A list of existing problems with matching keywords in specified fields will be displayed.
MSS
-
User requests to find problems by specifying keywords in certain fields.
-
AlgoBase retrieves all problems with matching keywords in specified fields from storage.
-
AlgoBase displays in the UI the list of problems with matching keywords in specified fields.
Use case ends.
Extensions
-
2a. AlgoBase detects that no keywords in any fields are specified.
-
2a1. AlgoBase informs user that at least one constraint should be provided.
Use case ends.
-
Use Case 6: Sort Problems
Guarantees
A list of problems will be displayed in a specific order provided by user.
MSS
-
User requests to sort a set of problems by specifying rules of ordering.
-
AlgoBase sorts the problem list using the provided order.
-
AlgoBase displays the set of questions in sorted order.
Use case ends.
Extensions
-
2a. AlgoBase detects that no sorting method is specified.
-
2a1. AlgoBase informs user that no sorting method is given.
Use case ends.
-
Use Case 7: Add Tag
MSS
-
User requests to add a tag.
-
AlgoBase creates the tag with taq name and tag color.
-
AlgoBase displays the tag list.
Use case ends.
Extensions
-
2a. AlgoBase detects that tag name or tag color has an invalid format.
-
2a1. AlgoBase informs user that the form of new tag is invalid.
Use case ends.
-
Use Case 8: Delete Tag
MSS
-
User requests to delete a tag.
-
AlgoBase deletes the tag in tag list.
-
AlgoBase deletes the tag in every problems.
-
AlgoBase displays the tag list.
Use case ends.
Extensions
-
2a. AlgoBase detects that the index of tag in not valid.
-
2a1. AlgoBase informs user that the index of tag is invalid.
Use case ends.
-
Use Case 9: Edit Tag
MSS
-
User requests to edit a tag.
-
AlgoBase edits the tag with taq name and tag color.
-
AlgoBase displays the tag list.
Use case ends.
Extensions
-
2a. AlgoBase detects that tag name or tag color has an invalid format.
-
2a1. AlgoBase informs user that the form of new tag is invalid.
Use case ends.
-
Use Case 10: List Tag
MSS
-
User requests to list the tags.
-
AlgoBase displays the tag list.
Use case ends.
Extensions
-
2a. AlgoBase detects that tag name or tag color has an invalid format.
-
2a1. AlgoBase informs user that the form of new tag is invalid.
Use case ends.
-
Use Case 11: Add Tasks to Plan
MSS
-
User requests to add a new task by entering the index of the problem, index of the plan and optionally a due date.
-
AlgoBase creates a new task with the specified problem (and due date).
-
AlgoBase adds the newly created task to the specified plan.
-
AlgoBase indicates successful addition of new task to plan.
-
AlgoBase displays details of task added.
Use case ends.
Extensions
-
2a. AlgoBase detects that the index of problem is out of bounds.
-
2a1. AlgoBase informs user that the addition is unsuccessful because the index of problem is out of bounds.
Use case ends.
-
Use Case 12: Copy Tasks between Plans
MSS
-
User requests to copy an existing task from one plan to another by entering the index of the task and the indices of the plans involved.
-
AlgoBase copies the specified task from the specified "from" plan to the "to" plan.
-
AlgoBase indicates that the existing task is copied successfully.
-
AlgoBase displays list of tasks of the updated "to" plan.
Use case ends.
Extensions
-
2a. Similar to 3a in Use Case 11.
-
2d. Similar to 3b in Use Case 11.
Use Case 13: Delete Tasks from Plan
MSS
-
User requests to delete an existing task by entering the index of the plan and index of the task.
-
AlgoBase deletes the specified task from the specified plan.
-
AlgoBase indicates successful deletion of the existing task.
-
AlgoBase updates the UI with the remaining tasks in the plan.
Use case ends.
Extensions
-
2a. Similar to 3a in Use Case 11.
-
2b. Similar to 2b in Use Case 12.
Use Case 14: Edit Due Dates of Tasks
MSS
-
User requests to edit due date of an existing task by entering the index of the plan, index of the task and new due date.
-
AlgoBase edits the due date of the specified task in the specified plan.
-
AlgoBase indicates that the existing task is edited successfully.
-
AlgoBase displays details of the task updated.
Use case ends.
Extensions
-
2a. Similar to 3a in Use Case 11.
-
2b. Similar to 2b in Use Case 12.
-
2c. Similar to 3b in Use Case 11.
Use Case 15: Mark Tasks as Done in Plan
MSS
-
User requests to mark an existing task as done by entering the index of the plan and index of the task.
-
AlgoBase marks the specified task as done in the specified plan.
-
AlgoBase indicates that the existing task is marked as done successfully.
-
AlgoBase displays details of the task updated.
Use case ends.
Extensions
-
2a. Similar to 3a in Use Case 11.
-
2b. Similar to 2b in Use Case 12.
Use Case 16: Mark Tasks as Undone in Plan
MSS
-
User requests to mark an existing task as undone by entering the index of the plan and index of the task.
-
AlgoBase marks the specified task as undone in the specified plan.
-
AlgoBase indicates that the existing task is marked as done successfully.
-
AlgoBase displays details of the task updated.
Use case ends.
Extensions
-
2a. Similar to 3a in Use Case 11.
-
2b. Similar 2b in Use Case 12.
-
2c. Similar 2c in Use Case 15.
Use Case 17: Move Tasks between Plans
MSS
-
User requests to move an existing task from one plan to another by entering the index of the task and the indices of the plans involved.
-
AlgoBase moves the specified task from the specified "from" plan to the "to" plan.
-
AlgoBase indicates that the existing task is moved successfully.
-
AlgoBase displays list of tasks of the updated "to" plan.
Use case ends.
Extensions
-
2a. Similar to 3a in Use Case 11.
-
2b. Similar to 2b in Use Case 12.
-
2c. Similar to 2c in Use Case 12.
-
2d. Similar to 3b in Use Case 11.
Use Case 18: Set Current Plan in Main Display
MSS
-
User requests to set a plan as the current plan in main display.
-
AlgoBase sets the specified plan as the current plan.
-
AlgoBase indicates that the specified plan is successfully set as the current plan.
-
AlgoBase displays updated current plan in main display.
Use case ends.
Extensions
-
2a. Similar to 3a in Use Case 11.
Use Case 19: Switch between View of Items
MSS
-
User requests to switch the current view of items to a different view of items.
-
AlgoBase displays the list of items corresponding to that view.
Use case ends.
Extensions
-
2a. AlgoBase detects that the specified view of items does not exist.
-
2a1. AlgoBase informs user that the specified view of items does not exist.
Use case ends.
-
Use Case 20: See details of an item
MSS
-
User requests to see the details of a specified item from the list of items.
-
AlgoBase displays the details of that item.
Use case ends.
Use Case 21: Export AlgoBase data
MSS
-
User requests to export AlgoBase data to a specified path.
-
AlgoBase exports AlgoBase data to a file name
algobase.json
in the specified location. -
AlgoBase indicates that AlgoBase data are exported successfully.
Use case ends.
Extensions
-
2a. AlgoBase detects that the specified path is invalid.
-
2a1. AlgoBase informs user that the export is unsuccessful because the path is invalid.
Use case ends.
-
Use Case 22: Import AlgoBase data
MSS
-
User requests to import data from a specified file into AlgoBase.
-
AlgoBase imports data from the specified file into AlgoBase.
-
AlgoBase indicates that the data are imported into AlgoBase successfully.
Use case ends.
Extensions
-
2a. AlgoBase detects that the specified file does not exist.
-
2a1. AlgoBase informs user that the import is unsuccessful because the file path is invalid.
Use case ends.
-
Appendix D: Non Functional Requirements
-
Every change is saved immediately and no manual saving is needed.
-
A user with above average typing speed for regular Unix commands should be able to accomplish most of the tasks faster using commands than using the mouse.
-
Should work on any mainstream OS as long as it has Java
11
or above installed. -
Should work on both
32-bit
and64-bit
environments. -
Should be able to hold up to 1000 problems with response time less than 1 second for typical usage.
-
Should work without installation (i.e. portable).
-
Should be for a single user i.e. (not a multi-user product).
-
Storage file should be human interpretable and editable for someone who’s familiar with JSON.
-
Not required to store solutions to problems.
Appendix E: Glossary
- JSON
-
JavaScript Object Notation
- Mainstream OS
-
Windows, Linux, Unix, OS-X
- Environment
-
An execution environment offered by mainstream OSes as defined above
- Response Time
-
An execution environment offered by mainstream OSes as defined above
- Solutions to Problems
-
Source code or executable that aims to solve the corresponding problem
Appendix F: Instructions for Manual Testing
Given below are instructions to test the app manually.
These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing. |
F.1. Launch and Shutdown
-
Initial launch
-
Download the jar file and copy into an empty folder
-
Double-click the jar file
Expected: Shows the GUI with a set of sample problems. The window size may not be optimum.
-
-
Saving window preferences
-
Resize the window to an optimum size. Move the window to a different location. Close the window.
-
Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-
F.2. Problem
F.2.1. Adding a problem
-
Test case:
addprob n/Sequences d/find number of inversions t/algorithm
Expected: A problem named 'Sequences' and tagged 'algorithm' is added to AlgoBase. -
Test case:
addprob n/ d/unnamed problem
Expected: No problem is added. The problem’s name shouldn’t be blank. Error details shown in the status message.
F.2.2. Deleting a problem
-
Prerequisites: List all problems using the
listprob
orfindprob
orsortprob
command. Multiple problems in the list. -
Test case:
deleteprob 1
Expected: First problem is deleted from the list, details shown in the status message, timestamp in the status bar is updated. Otherwise show message will ask to force delete all related tasks in plans. -
Test case:
deleteprob 0
Expected: No problem is deleted. Error details shown in the status message. Status bar remains the same. -
Other incorrect delete commands to try:
delete
,deleteprob x
(where x is larger than the list size)
Expected: Similar to previous.
F.2.3. Editing a problem
-
Prerequisites: List all problems using the
listprob
orfindprob
orsortprob
command. Multiple problems in the list. -
Test case:
editprob 1 n/Two Sequences
Expected: Change the name of the first problem to 'Two Sequences'. -
Test case:
editprob 2 t/
Expected: Removes all tags from the second problem. -
Test case:
editprob x
Expected: No problem is edited. Index of problem should be a valid integer. Error details shown in the status message.
F.2.4. Listing problems
-
Test case:
listprob
Expected: All problems in AlgoBase are listed in the problem panel.
F.2.5. Sorting problems
-
Test case:
sortprob m/name
Expected: The current problem list is sorted with respect to names in ascending order. -
Test case:
sortprob m/difficulty ord/descend
Expected: The current problem list is sorted with respect to difficulty in descending order. -
Test case:
sortprob m/diff
Expected: The current problem list remains unchanged and an error is thrown to inform the user that the method name is incorrect. -
Test case:
sortprob m/diff m/name
Expected: The current problem list is sorted with respect to name in ascending order. -
Test case:
sortprob m/name m/diff
Expected: The current problem list remains unchanged and an error is thrown to inform the user that the method name is incorrect.
F.2.6. Finding a problem
-
Test case:
findprob n/sort
Expected: All problems whose name includes “sort” (case-insensitive) is listed in the “Problems” panel. -
Test case:
findprob
Expected: An error is thrown and the user is informed that at least one constraint should be provided.
F.3. Tag
F.3.1. Adding a tag
-
Test case:
addtag t/test c/BLUE
Expected: New Tag [test] added to AlgoBase. -
Test case: type in
addtag t/test c/BLUE
for twice
Expected: Tag [test] already exists in AlgoBase.
F.3.2. Deleting a tag
-
Test case:
deletetag 1
Expected: Tag [test] deleted. -
Test case:
deletetag 9999
Expected: The Tag index provided is invalid
F.3.3. Editing a tag
-
Test case:
edittag 1 t/edited c/RED
Expected: Tag [edited] edited. -
Test case:
edittag t/edited c/RED
Expected: An error is thrown and the user is informed that the format of command is invalid.
F.3.4. Listing a tag
-
Test case:
listtag
Expected: All tags listed.
F.4. Find Rule
F.4.1. Adding a problem-finding rule
-
Prerequisites: there is no find rules named “rule1” or “rule2” or “rule3” in the existing AlgoBase, and find rules with a certain name is never added more than once.
-
Test case:
addfindrule rule1 n/Sequences
Expected: A new find rule named “rule1” is added and the new rule appears in the “Find Rules” panel. -
Test case:
afr rule2 n/sequences
Expected: A new find rule named “rule2” is added and the new rule appears in the “Find Rules” panel. -
Test case:
afr rule3
Expected: An error is thrown and the user is informed that at least one constraint should be provided.
F.4.2. Applying a problem-finding rule
-
Prerequisites: there are four find rules in the existing AlgoBase.
-
Test case:
apply 1
Expected: The first find rule is applied, the problems in the “Problems” panel are updated accordingly. -
Test case:
apply 0
Expected: An error is thrown and the user is informed that the command format is invalid. -
Test case:
apply 100
Expected: An error is thrown and the user is informed that the provided find rule index is invalid.
F.4.3. Deleting a problem-finding rule
-
Prerequisites: there are four find rules in the existing AlgoBase.
-
Test case:
deletefindrule 1
Expected: The first find rule is deleted and the find rules list is updated. -
Test case:
dfr 1
Expected: The first find rule is deleted and the find rules list is updated.
F.5. Plan
F.5.1. Adding a plan
-
Test case:
addplan n/ByteDance d/coding test for Software engineering
Expected: A new plan with respective information is added and displayed on plan tab. Start date is now and end date is one month from now. -
Test case:
addplan n/ByteDance d/coding test for Software engineering
Expected: No plan is added. No plans with duplicate names can be added. Error details shown in the status message. -
Test case:
addplan n/Graph start/2019-1-1 end/2019-3-3
Expected: No plan is added. The date should be inyyyy-MM-dd
format. Error details shown in the status message. -
Test case:
addplan n/Graph end/1912-06-23
Expected: No plan is added. If no starting time is specified, the starting time will beLocalDate#now()
, and the starting time should not be after end time. Error details shown in the status message.
F.5.2. Editing a plan
-
Prerequisites: List all plans using the
listplan
orfindplan
command. Multiple plans in the list. -
Test case:
editplan 1 d/give up start/2019-01-01 end/2020-02-02
Expected: The description and the dates of the first displayed plan is changed. -
Test case:
editplan 1 end/2018-02-02
Expected: Edit command is invalid. Error details shown in the status message. Starting date should be before or equal to end date. -
Test case:
editplan 1 end/2019-02-02 f/
Expected: The end date of the first displayed plan is changed to2019-02-02
. Any task’s due date after2019-02-02
will be changed to2019-02-02
. ..Test case:editplan 1 start/2019-01-30 f/
Expected: The starting date of the first displayed plan is changed to2019-01-30
. Any task’s due date before2019-01-30
will be changed to the plan’s end date.
F.5.3. Finding plans
-
Test case:
findplan n/bytedance
Expected: The plan named 'ByteDance' is listed. -
Test case:
findplan start/2019-01-01 end/2019-12-12
Expected: Plans whose time range overlaps with the given time range are listed in the plan panel. -
Test case:
findplan start/2019-01-01
Expected: Invalid command. Both range start and range end should be specified. Error details shown in the status message. -
Test case:
findplan start/2019-01-01 end/2018-01-02
Expected: Invalid command. Range start should not be after range end. Error details shown in the status message.
F.5.4. Deleting a plan
-
Prerequisites: List all plans using the
listplan
orfindplan
command. Multiple plans in the list. -
Test case:
findplan n/bytedance
deleteplan 1
Expected: The plan with name 'ByteDance' is deleted. -
Test case:
listplan
deleteplan 1
Expected: The first plan among all plans is deleted.
F.5.5. Listing plans
-
Test case:
listplan
Expected: All plans in Algobase are listed in the plan display tab.
F.5.6. Setting a plan as current plan
-
Prerequisites
-
There are exactly 2 training plans in AlgoBase.
-
-
Test case:
setplan 2
Expected: Plan 2 is set as the current plan. The task management pane is updated. Current plan in the task management is updated to plan 1. -
Test case:
setplan 20
Expected: No task is added. Error details shown in the status message, indicating that the given plan index is invalid.
F.6. Task
F.6.1. Adding a task to an existing plan
-
Prerequisites
-
There is at least 1 training plan and 10 problems in AlgoBase.
-
Plan 1 is empty.
-
Start and end dates of plan 1 are
2019-11-15
and2019-12-15
respectively.
-
-
Test case:
addtask plan/1 prob/1
Expected: A new task is created from problem 1 with due date on2019-12-15
, and added to task list in plan 1. Current plan in the task management is updated to plan 1. -
Test case:
addtask plan/1 prob/2 due/3030-01-01
Expected: No task is added. Error details shown in the status message, indicating that the due date is not within the range of plan.
F.6.2. Editing due date of a task
-
Prerequisites
-
There is at least 1 training plan in AlgoBase.
-
Plan 1 has at least 1 task.
-
Start and end dates of plan 1 are
2019-11-15
and2019-12-15
respectively.
-
-
Test case:
edittask plan/1 task/1 due/2019-11-20
Expected: The due date of the first task in plan 1 is updated to2019-11-20
. -
Test case:
edittask plan/1 task/1 due/3030-01-01
Expected: Error details shown in the status message, indicating that the due date is not within the range of plan.
F.6.3. Deleting a task
-
Prerequisites
-
There is exactly 1 training plan in AlgoBase.
-
Plan 1 has at least 1 task.
-
-
Test case:
deletetask plan/1 task/1
Expected: The first task in plan 1 is deleted. -
Test case:
deletetask plan/100 task/1
Expected: Error details shown in the status message, indicating that the plan index is invalid.
F.6.4. Marking a task as done
-
Prerequisites
-
There is at least 1 training plan in AlgoBase.
-
Plan 1 has at least 2 tasks.
-
The first task in plan 1 is not yet done.
-
The second task in plan 1 is already done.
-
-
Test case:
donetask plan/1 task/1
Expected: The first task in plan 1 is marked as done. -
Test case:
donetask plan/1 task/2
Expected: Error details shown in the status message, indicating that the specified task is already done.
F.6.5. Marking a task as undone
-
Prerequisites
-
There is at least 1 training plan in AlgoBase.
-
Plan 1 has at least 2 tasks.
-
The first task in plan 1 is already done.
-
The second task in plan 1 is not yet done.
-
-
Test case:
undonetask plan/1 task/1
Expected: The first task in plan 1 is marked as undone. -
Test case:
undonetask plan/1 task/2
Expected: Error details shown in the status message, indicating that the specified task is not yet done.
F.6.6. Copying a task between plans
-
Prerequisites
-
There are at least 2 training plans in AlgoBase.
-
Plan 1 has at least 2 tasks.
-
Plan 2 has exactly 1 task, which is the same the the first task in plan 1.
-
-
Test case:
copytask task/2 from/1 to/2
Expected: The second task in plan 1 is copied to plan 2. -
Test case:
copytask task/1 from/1 to/2
Expected: Error details shown in the status message, indicating that the specified task is already in plan 2.
F.6.7. Moving a task between plans
-
Prerequisites
-
There are at least 2 training plans in AlgoBase.
-
Plan 1 has at least 2 tasks.
-
Plan 2 has exactly 1 task, which is the same the the first task in plan 1.
-
-
Test case:
movetask task/2 from/1 to/2
Expected: The second task in plan 1 is copied to plan 2. -
Test case:
movetask task/1 from/1 to/2
Expected: Error details shown in the status message, indicating that the specified task is already in plan 2.
F.7. GUI
F.7.1. Switching tabs
-
Switching between Tabs
-
Prerequisites: Currently at the first display tab (Problem).
-
Test case:
switchtab tt/display i/2
Expected: The display tab is now at theTags
tab. -
Test case:
st tt/1 i/2
Expected: The display tab is now at theTags
tab. -
Test case:
switchtab tt/details i/2
Expected: The details tab is now at the second tab. -
Test case:
st tt/2 i/2
Expected: The details tab is now at the second tab. -
Test case:
st tt/2 i/5
(Assuming only 4 details tab exist)
Expected: The details tab is not changed. Error message is shown.
-
-
Switching to non-existent Tab Type index
-
Test case:
switchtab tt/3 i/1
Expected: No tabs are changed. Error message is shown.
-
F.7.2. Opening a new tab
-
Opening a new Details Tab for a Problem or Plan
-
Prerequisites: At least 1 problem or plan exists in the current problem display tab.
-
Test case:
opentab m/problem i/1
Expected: A new details tab containing the problem at index 1 of the currently displayed problem list is opened. The tab is selected as well. -
Test case:
opentab m/plan i/1
Expected: A new details tab containing the plan at index 1 of the currently displayed plan list is opened. The tab is selected as well. The plan tab also updates to display the selected plan. -
Test case:
ot m/3 i/1
Expected: A new details tab containing the plan at index 1 of the currently displayed plan list is opened. The tab is selected as well. The plan tab also updates to display the selected plan. -
Test case:
opentab m/problem i/0
Expected: No details tab are opened. Error message is shown. -
Test case:
ot m/3 i/4
(Assuming only 3 plans exist)
Expected: No details tab are opened. Error message is shown.
-
-
Opening an existing Details Tabs for a Problem or Plan
-
Prerequisites: At least 1 problem or plan exists and it is already in a details tab.
-
Test case:
opentab m/problem i/1
(Assuming the first problem is in a Details Tab)
Expected: The existing details tab containing the problem is selected. -
Test case:
ot m/3 i/1
(Assuming the first plan is in a Details Tab)
Expected: The existing details tab containing the plan is selected. The plan tab also updates to display the selected plan.
-
-
Opening a non-existent Model Type index
-
Test case:
ot m/5 i/1
Expected: No tabs are opened. Error message is shown.
-
F.7.3. Closing an existing tab
-
Prerequisites: At least one Details Tab exist.
-
Test case:
closetab i/1
while first tab is selected (Assuming there are 3 details tabs)
Expected: The first tab is closed and the new first tab (previously second tab) is selected. -
Test case:
ct i/1
while first tab is selected (Assuming there are 3 details tabs)
Expected: The first tab is closed and the new first tab (previously second tab) is selected. -
Test case:
closetab i/3
while first tab is selected (Assuming there are 3 details tabs)
Expected: The last tab is closed and the new first tab (previously second tab) is selected. -
Test case:
ct i/3
while first tab is selected (Assuming there are 3 details tabs)
Expected: The last tab is closed and the new first tab (previously second tab) is selected. -
Test case:
ct i/0
while current tab is selected (Assuming there are 3 details tabs)
Expected: No details tab are closed. Error message is shown. -
Test case:
ct i/4
while current tab is selected (Assuming there are 3 details tabs)
Expected: No details tab are closed. Error message is shown.
F.7.4. Editing a problem from GUI
-
Prerequisites: At least one problem exists and it is opened in a Details Tab.
-
Test case: No changes are made to the Problem.
Expected: The Edit Problem button should be disabled and not clickable. -
Test case: Some valid changes are made and the user clicks on Edit Problem button.
Expected: Name of the edited problem shown in the status message. Field updates are reflected in the Display, Details and Plan tabs. Edit Problem button is disabled. -
Test case: Some invalid changes are made and the user clicks on Edit Problem button.
Expected: Error details shown in the status message. Field updates are not reflected in the Display and Plan tabs, and Details Tab remains in edit mode. Edit Problem button is not disabled.
F.7.5. Deleting a problem from GUI
-
Prerequisites: At least one problem exists and it is opened in a Details Tab.
-
Test case: User clicks on the Delete button.
Expected: A warning dialog shows up with a Confirm and Cancel button. -
Test case: User clicks on the Delete button then clicks Confirm on the warning dialog.
Expected: The Warning dialog and Details tab is closed, and the problem is removed from the plan as well as Display and Plan tabs. -
Test case: User clicks on the Delete button then clicks Cancel on the warning dialog.
Expected: The Warning dialog is closed and no other changes are made.
F.7.6. Editing a plan from GUI
-
Prerequisites: At least one plan exists and it is opened in a Details Tab.
-
Test case: No changes are made to the Plan.
Expected: The Edit Plan button should be disabled and not clickable. -
Test case: Some valid changes are made and the user clicks on Edit Plan button.
Expected: Name of the edited plan shown in the status message. Field updates are reflected in the Display, Details and Plan tabs. Edit Plan button is disabled. -
Test case: Some invalid changes are made and the user clicks on Edit Problem button.
Expected: Error details shown in the status message. Field updates are not reflected in the Display and Plan tabs, and Details Tab remains in edit mode. Edit Plan button is not disabled.
F.7.7. Deleting a plan from GUI
-
Prerequisites: At least one plan exists and it is opened in a Details Tab.
-
Test case: User clicks on the Delete button.
Expected: A warning dialog shows up with a Confirm and Cancel button. -
Test case: User clicks on the Delete button then clicks Confirm on the warning dialog.
Expected: The Warning dialog and Details tab is closed, and the plan is removed from the Display and Plan tabs. -
Test case: User clicks on the Delete button then clicks Cancel on the warning dialog.
Expected: The Warning dialog is closed and no other changes are made.
F.7.8. Switching tabs from GUI
-
Switching between Display Tabs
-
Prerequisites: Currently at the first display tab (Problem).
-
Test case: Click on
Training Plans
Tab
Expected: The display tab is now at theTraining Plans
tab.
-
-
Switching between Details Tabs
-
Prerequisites: At least 2 Details Tabs are opened. Currently at the first details tab.
-
Test case: Click on a different tab
Expected: The display tab is now at the tab that is clicked on.
-
F.7.9. Opening a new tab from GUI
-
Opening a new Details Tabs for a Problem or Plan
-
Prerequisites: There is at least 1 problem or plan in the Display Tab currently.
-
Test case: The user double clicks on a problem or plan in the display tab.
Expected: The problem or plan is added as the last tab of the Details Tabs and is selected.
-
-
Opening an existing Details Tabs for a Problem or Plan
-
Prerequisites: At least 1 problem or plan exists and it is already in a details tab.
-
Test case: The user double clicks on a problem or plan in the display tab that is already in a details tab. Expected: The tab is switched to details tab containing the problem or plan.
-
F.7.10. Closing an existing tab from GUI
-
Prerequisites: At least one Details Tab exist.
-
Test case: User clicks on the
x
button next to the tab.
Expected: The Details tab corresponding to that tab is closed.
F.8. Data
-
Test case: Delete the
data
folder in project root folder and launch AlgoBase.
Expected: No errors shown. A new data file is created silently. -
Test case: Delete some mandatory fields in the data file located at
data/algobase.json
and launch AlgoBase.
Expected: Error details shown in the status message, indicating corrupted data file.