Overview
AlgoBase is a desktop algorithmic problem manager. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 20 kLoC.
About this portfolio
This project portfolio details my individual contributions to the AlgoBase project. It includes a summary of the enhancements and other contributions I made throughout the duration of the project. Additionally, portions of my contribution to the User Guide and Developer Guide have also been included.
Summary of contributions
-
Code contributed: Code contributed
-
Major enhancement: Implemented the problem searching and sorting feature.
-
What it does: allows the user to filter problems by combining search constraints on most fields (e.g. problem names, sources, descriptions, difficulty, etc.), allows user to save and reuse some typical search rules and allows user to sort the search result.
-
Justification: To organize algorithmic questions, the first step is to find a proper subset of AlgoBase to either add to a training plan or solve the problems directly. Searching and sorting feature should be one of the most frequently used features in AlgoBase. Plus, by enabling the user to save certain frequently used find rules (e.g. medium difficulty), we essentially made it possible to create a problem list that’s dynamically updated according to certain rules - the user no longer needs to manually add tags or create plans for problems with certain properties, they can just use the saved find rules to locate them.
-
Highlights:
-
This is a full-stack feature involving all the components of AlgoBase from
Logic
toModel
toStorage
toUI
, consisting of roughly 3000 lines of functional code and more than 2000 lines of testing code. -
findprob
can search on almost all fields of a problem whilesortprob
provides 10 combinations of sorting order. -
It requires an in-depth analysis of the overall architecture of AlgoBase because
-
The original implementation of
findprob
in AddressBook accepts only one search constraint (i.e. the name), but in AlgoBase we need to support combination of arbitrary (non-zero) number of search constraints. -
The design of AB3 only considers "filtering" problems, thus it used
FilteredList
to supportfindprob
command. However, AlgoBase needs to support bothfindprob
andsortprob
. We need to redesign the way AB3 exposes the processed observable list to the UI so that the list accepts both a predicate and a comparator.
-
-
-
-
Minor enhancement: Implemented the command history feature.
-
What it does: allows the user to navigate to previous commands using
Up
andDown
keyboard shortcut. -
Justification: This feature makes
addfindrule
more useful - the user can first check if their problem find rule is working as expected by executing it usingfindprob
command, then pressUp
to restore the command text, change the command word toaddfindrule
and assign a name to the added find rule. -
Relevant pull request #105 #137 (Adapted some code from AB4)
-
-
Other contributions:
-
Project management:
-
Managed releases
v1.3
,v1.3.4
,v1.4
(3 releases) on GitHub
-
-
Enhancements to existing features:
-
Re-implement the
help
command: #81
-
-
Documentation:
-
Explains how reserved words should work in AlgoBase (used as a reference in the development) #35
-
-
Community:
-
As shown below, I participated in the review of most (significant) PRs in AlgoBase and provided some in-depth comments to make sure that the code quality of this project is consistent.
-
PRs reviewed (with non-trivial review comments): #24 #37 #65 #66 #67 #70 #80 #85 #116 #145 #147 #201
-
Contributed to forum discussions
-
Reported bugs and suggestions for other teams in the class:
-
-
Contributions to the User Guide
Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users. |
Sorting problems: sortprob
Sorts the current list of problems by a specified method and order.
Format: sortprob m/METHOD [ord/ORDER]
-
METHOD
can bename
,author
,weblink
,difficulty
orsource
. -
ORDER
can beascend
ordescend
representing ascending and descending order. The default is in ascending order. -
String-based values (i.e.
name
,author
, etc.) are sorted alphabetically.
If sorted by ascending order (i.e. the default order), empty fields will have the highest priority, which means if you execute sortprob m/weblink , the first few results would be (if any) without web links.
|
Examples:
-
sortprob m/name
Sorts the current list of problems in ascending order of names. -
sortprob m/author ord/descend
Sorts the current list of problems in descending order of author names. -
sortprob m/difficulty ord/ascend
Sorts the current list of problems from lowest to highest difficulty.
Storing a problem-finding rule: addfindrule
Saves a problem-finding rule from provided constraints.
Format: addfindrule RULE_NAME [n/NAME] [a/AUTHOR] [d/DESCRIPTION] [src/SOURCE] [diff/LOWER_BOUND-UPPER_BOUND] [t/TAG_KEYWORDS]
Alias: afr
If you want to "keep a list of problems" that fulfills certain conditions, say "graph theory questions from Kattis", you may store these rules using addfindrule and apply them later.Unlike plans, as you add new questions to AlgoBase, so long as the new questions fulfill the search rule, they will show up if you apply that rule.
|
The rules for constraints are the same as those described in findprob command. Note that keywords in a find rule may be less restrictive than the fields (e.g. name, source, etc.).
|
Examples:
-
addfindrule MediumDiffAlgo t/algorithm diff/2.0-4.0
Adds a new find rule namedMediumDiffAlgo
that when applied, returns any problem withalgorithm
as one of its tags AND with a difficulty between 2.0 and 4.0 (inclusive). -
addfindrule Kattis src/Kattis
orafr Kattis src/Kattis
Adds a new find rule namedKattis
that when applied, returns any problem fromKattis
.
Applying a problem-finding rule: apply
Applies a problem-finding rule.
Format: apply INDEX
-
Applies the find rule at the specified
INDEX
. -
The index refers to the index number shown in the displayed find rule list.
-
The index must be a positive integer 1, 2, 3, …
You can find problem-finding rules that you can apply with in the "Find Rules" panel by clicking on the "Find Rules" tab.
|
apply a problem-finding rule is essentially the same as executing a pre-filled findprob command.
|
Examples:
-
apply 2
Applies the second find rule in the displayed list.
Deleting a problem-finding rule: deletefindrule
Deletes a problem-finding rule.
Format: deletefindrule INDEX
Alias: dfr
-
Deletes the find rule at the specified
INDEX
. -
The index refers to the index number shown in the displayed find rule list.
-
The index must be a positive integer 1, 2, 3, …
Examples:
-
deletefindrule 2
ordfr 2
Deletes the second find rule in the displayed list.
Viewing help : help
Lists all possible commands or shows the command usage of a command word.
Format: help [COMMAND_WORD]
help
command-
help
Shows all possible commands. -
help addprob
Shows command usage foraddprob
command.
help command only searches commands' full command word. (i.e. aliases is not supported by help )
|
Contributions to the Developer Guide
Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project. |
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
CommandCurrent 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
CommandDesign 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.
-
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.
Remaining part: Design - Model