PROJECT: AlgoBase

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 to Model to Storage to UI, 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 while sortprob 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 support findprob command. However, AlgoBase needs to support both findprob and sortprob. 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.

    • Relevant pull requests: #49 #61 #64 #90 #94 #107

  • Minor enhancement: Implemented the command history feature.

    • What it does: allows the user to navigate to previous commands using Up and Down 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 using findprob command, then press Up to restore the command text, change the command word to addfindrule 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

        • Fixed the forum issue template #126

        • Reported module website’s inaccurate information on PPP #149

      • 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 be name, author, weblink, difficulty or source.

  • ORDER can be ascend or descend 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

find rule 1
Figure 1. Information related to find rules is displayed in the "Find Rules" panel
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 named MediumDiffAlgo that when applied, returns any problem with algorithm as one of its tags AND with a difficulty between 2.0 and 4.0 (inclusive).

  • addfindrule Kattis src/Kattis or afr Kattis src/Kattis
    Adds a new find rule named Kattis that when applied, returns any problem from Kattis.

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 or dfr 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
Figure 2. All possible (full) command words will be listed using help command
  • help Shows all possible commands.

  • help addprob Shows command usage for addprob 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:

AddFindRuleActivityDiagram
Figure 3. Activity Diagram for the Execution of addfindrule Command

Current Implementation

The save find rules feature is facilitated by the following classes:

  • ProblemSearchRule
    It stores both the Name of the find rule and all predicates included in this find rule. A ProblemSearchRule doesn’t have to include all possible predicates as the user may not provide all of them. Missing predicates will be stored as null 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 a ObservableList<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.

AddFindRuleClassDiagram
Figure 4. Class Diagram for Add Find Rule Feature

The sequence diagram below shows the high-level abstraction of how AlgoBase processes the request when user types in addfindrule rule1 n/Sequences:

HighLevelAddFindRuleSequenceDiagram
Figure 5. High-level Sequence Diagram for the Execution of 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.

AddFindRuleSequenceDiagram
Figure 6. Sequence Diagram for the Execution of addfindrule Command

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 extends FindProblemDescriptor with an additional field name

    • Pros: Greatly reduces the amount of duplicate code as ProblemSearchRule shares most fields with FindProblemDescriptor

    • Cons: ProblemSearchRule as a data class is no longer immutable. We have to be careful not to call any setters it inherits from FindProblemDescriptor.

  • 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

ModelClassDiagram
Figure 7. Structure of the 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.

ProblemPackageDiagram
Figure 8. Structure of the Problem Package

Remaining part: Design - Model