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
LogictoModeltoStoragetoUI, consisting of roughly 3000 lines of functional code and more than 2000 lines of testing code. -
findprobcan search on almost all fields of a problem whilesortprobprovides 10 combinations of sorting order. -
It requires an in-depth analysis of the overall architecture of AlgoBase because
-
The original implementation of
findprobin 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
FilteredListto supportfindprobcommand. However, AlgoBase needs to support bothfindprobandsortprob. 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
UpandDownkeyboard shortcut. -
Justification: This feature makes
addfindrulemore useful - the user can first check if their problem find rule is working as expected by executing it usingfindprobcommand, then pressUpto restore the command text, change the command word toaddfindruleand 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
helpcommand: #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]
-
METHODcan bename,author,weblink,difficultyorsource. -
ORDERcan beascendordescendrepresenting 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/nameSorts the current list of problems in ascending order of names. -
sortprob m/author ord/descendSorts the current list of problems in descending order of author names. -
sortprob m/difficulty ord/ascendSorts 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 namedMediumDiffAlgothat when applied, returns any problem withalgorithmas one of its tags AND with a difficulty between 2.0 and 4.0 (inclusive). -
addfindrule Kattis src/Kattisorafr Kattis src/Kattis
Adds a new find rule namedKattisthat 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 2ordfr 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-
helpShows all possible commands. -
help addprobShows command usage foraddprobcommand.
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 theNameof the find rule and all predicates included in this find rule. AProblemSearchRuledoesn’t have to include all possible predicates as the user may not provide all of them. Missing predicates will be stored asnullin this class. -
UniqueFindRuleList
It stores the find rules and makes sure that every find rule in this list has a unique name.-
UniqueFindRuleListstores 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/SequencesThe 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):
ProblemSearchRuleextendsFindProblemDescriptorwith an additional fieldname-
Pros: Greatly reduces the amount of duplicate code as
ProblemSearchRuleshares most fields withFindProblemDescriptor -
Cons:
ProblemSearchRuleas a data class is no longer immutable. We have to be careful not to call any setters it inherits fromFindProblemDescriptor.
-
-
Alternative 2:
ProblemSearchRuleas 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
UserPrefsobject 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