From 560a3b5532e115e0ff01bdfbf0d319ba6d7bbcd4 Mon Sep 17 00:00:00 2001 From: Titus Chew <39845485+tituschewxj@users.noreply.github.com> Date: Sun, 14 Apr 2024 18:28:28 +0800 Subject: [PATCH 1/2] Update diagrams --- ...mpleteEmptyConstructorSequenceDiagram.puml | 13 +++++ ...CompletePrefixResolverSequenceDiagram.puml | 44 +++++++++++++++++ docs/diagrams/AutocompleteClassDiagram.puml | 47 +++++++++++++++++++ ...ompleteFindTrieMatchesSequenceDiagram.puml | 43 +++++++++++++++++ .../AutocompleteKeySequenceDiagram.puml | 34 ++++++++++++++ .../AutocompleteParseSequenceDiagram.puml | 46 ++++++++++++++++++ .../AutocompleteUpdateSequenceDiagram.puml | 36 ++++++++++++++ docs/diagrams/LogicClassDiagram.puml | 42 ++++++----------- 8 files changed, 277 insertions(+), 28 deletions(-) create mode 100644 docs/diagrams/AutoCompleteEmptyConstructorSequenceDiagram.puml create mode 100644 docs/diagrams/AutoCompletePrefixResolverSequenceDiagram.puml create mode 100644 docs/diagrams/AutocompleteClassDiagram.puml create mode 100644 docs/diagrams/AutocompleteFindTrieMatchesSequenceDiagram.puml create mode 100644 docs/diagrams/AutocompleteKeySequenceDiagram.puml create mode 100644 docs/diagrams/AutocompleteParseSequenceDiagram.puml create mode 100644 docs/diagrams/AutocompleteUpdateSequenceDiagram.puml diff --git a/docs/diagrams/AutoCompleteEmptyConstructorSequenceDiagram.puml b/docs/diagrams/AutoCompleteEmptyConstructorSequenceDiagram.puml new file mode 100644 index 00000000000..661f19e084f --- /dev/null +++ b/docs/diagrams/AutoCompleteEmptyConstructorSequenceDiagram.puml @@ -0,0 +1,13 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + +box Logic LOGIC_COLOR_T1 + participant ":AutoCompleteResult" as AutoCompleteResult LOGIC_COLOR +end box +mainframe **sd** create empty autocomplete + +[-> AutoCompleteResult: AutoCompleteResult() +activate AutoCompleteResult +return AutoCompleteResult +@enduml diff --git a/docs/diagrams/AutoCompletePrefixResolverSequenceDiagram.puml b/docs/diagrams/AutoCompletePrefixResolverSequenceDiagram.puml new file mode 100644 index 00000000000..7690b465ee4 --- /dev/null +++ b/docs/diagrams/AutoCompletePrefixResolverSequenceDiagram.puml @@ -0,0 +1,44 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + +box Logic LOGIC_COLOR_T1 + participant ":AutoCompletePrefixResolver" as ACPrefixResolver LOGIC_COLOR + participant ":AutoCompleteResult" as AutoCompleteResult LOGIC_COLOR +end box + +[-> ACPrefixResolver: getAutoComplete(input) +activate ACPrefixResolver + +alt input is blank + +ref over ACPrefixResolver +create empty autocomplete +end ref + +else else +ACPrefixResolver -> ACPrefixResolver: findTriePrefixContinuation(input) +activate ACPrefixResolver + +ref over ACPrefixResolver +find trie prefix continuation +end ref + +return trieMatchContinuations + +alt trieMatchContinuations is empty + +ref over ACPrefixResolver +create empty autocomplete +end ref + +else else + +create AutoCompleteResult +ACPrefixResolver -> AutoCompleteResult: AutoCompleteResult(trieMatchContinuations) +activate AutoCompleteResult +return AutoCompleteResult +end +end +return AutoCompleteResult +@enduml diff --git a/docs/diagrams/AutocompleteClassDiagram.puml b/docs/diagrams/AutocompleteClassDiagram.puml new file mode 100644 index 00000000000..039476df152 --- /dev/null +++ b/docs/diagrams/AutocompleteClassDiagram.puml @@ -0,0 +1,47 @@ +@startuml +!include style.puml +skinparam arrowThickness 1.1 +skinparam arrowColor LOGIC_COLOR_T4 +skinparam classBackgroundColor LOGIC_COLOR + +package Logic as LogicPackage { + class "<>\nLogic" as Logic + class LogicManager + + package "Attribute Classes" as AttributePackage { + class PrefixResolver + class "<>\nPrefixResolverSyntax" as PrefixResolverSyntax + class AttributeTrie + class "<>\nAttributeValueGeneratorManager" as AVGManager + PrefixResolverSyntax .right.> PrefixResolver + PrefixResolver *-->"1" AttributeTrie + PrefixResolverSyntax <..> AVGManager + + LogicManager ..up> AVGManager: updates > + } + + package "AutoComplete Classes" as AutoCompletePackage { + class "<>\nAutoComplete" as AutoComplete + class AutoCompleteCommand + class AutoCompletePrefixResolver + class AutoCompleteResult + AutoCompleteCommand .up.|> AutoComplete + AutoCompletePrefixResolver .up.|> AutoComplete + AutoCompleteCommand .down.> AutoCompleteResult: produces > + AutoCompletePrefixResolver .down.> AutoCompleteResult: produces > + + LogicManager ..up> AutoCompleteResult + } + + package "Parser Classes" as ParserPackage { + class Prefix + class AddressBookParser + } + + AddressBookParser .> AutoComplete: creates > + LogicManager -left-|> Logic + LogicManager *-->"1" AddressBookParser + PrefixResolver -up->"1" Prefix + AutoCompletePrefixResolver -down>"*" PrefixResolver +} +@enduml diff --git a/docs/diagrams/AutocompleteFindTrieMatchesSequenceDiagram.puml b/docs/diagrams/AutocompleteFindTrieMatchesSequenceDiagram.puml new file mode 100644 index 00000000000..fc7a90b4ca0 --- /dev/null +++ b/docs/diagrams/AutocompleteFindTrieMatchesSequenceDiagram.puml @@ -0,0 +1,43 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + +box Logic LOGIC_COLOR_T1 + participant ":AutoCompletePrefixResolver" as ACPrefixResolver LOGIC_COLOR + participant ":PrefixResolver" as PrefixResolver LOGIC_COLOR + participant ":AttributeTrie" as AttributeTrie LOGIC_COLOR +end box +mainframe **sd** find trie prefix continuation + +[-> ACPrefixResolver: findTriePrefixContinuation(input) +activate ACPrefixResolver + +ACPrefixResolver -> ACPrefixResolver: findLastPrefixIndex(input) +activate ACPrefixResolver +deactivate ACPrefixResolver + +ACPrefixResolver -> ACPrefixResolver: findLastPrefix(input, indexOfLastPrefix) +activate ACPrefixResolver +deactivate ACPrefixResolver + +note right of ACPrefixResolver: Iterates through a collection of PrefixResolvers and their AttributeTries +loop for all PrefixResolvers + +opt lastPrefix equals PrefixResolver's prefix + +ACPrefixResolver -> PrefixResolver: resolvePrefix(partialValue) +activate PrefixResolver +PrefixResolver -> AttributeTrie: findAllValuesWithPrefix(partialValue) +activate AttributeTrie +opt trieCache is absent +AttributeTrie -> AttributeTrie: generateTrie() +activate AttributeTrie +return trie +end +return list of values with prefix +return list of values with prefix +end +end loop + +return trieMatchContinuations +@enduml diff --git a/docs/diagrams/AutocompleteKeySequenceDiagram.puml b/docs/diagrams/AutocompleteKeySequenceDiagram.puml new file mode 100644 index 00000000000..bea51484c48 --- /dev/null +++ b/docs/diagrams/AutocompleteKeySequenceDiagram.puml @@ -0,0 +1,34 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + +box UI UI_COLOR_T1 + participant ":CommandBox" as CommandBox UI_COLOR + participant ":MainWindow" as MainWindow UI_COLOR +end box + +box Logic LOGIC_COLOR_T1 + participant ":LogicManager" as LogicManager LOGIC_COLOR + participant ":AutoCompleteResult" as AutoCompleteResult LOGIC_COLOR +end box + +[-> CommandBox: handleTabKeyPressEvent(...) +activate CommandBox +opt autoCompleteResultCache is null +CommandBox -> MainWindow: getAutoComplete(lastModifiedText) +activate MainWindow +ref over MainWindow, LogicManager +get AutoCompleteResult from commandText +end ref +return AutoCompleteResult +end + +CommandBox -> AutoCompleteResult: getNextResult() +activate AutoCompleteResult +return autocompletion + +CommandBox -> CommandBox: setText(lastModifiedText + autocompletion) +activate CommandBox +deactivate CommandBox +return +@enduml diff --git a/docs/diagrams/AutocompleteParseSequenceDiagram.puml b/docs/diagrams/AutocompleteParseSequenceDiagram.puml new file mode 100644 index 00000000000..92e47a159d1 --- /dev/null +++ b/docs/diagrams/AutocompleteParseSequenceDiagram.puml @@ -0,0 +1,46 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + +box Logic LOGIC_COLOR_T1 + participant ":LogicManager" as LogicManager LOGIC_COLOR + participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR + participant ":AutoCompleteResult" as AutoCompleteResult LOGIC_COLOR + participant ":AutoCompleteCommand" as AutoCompleteCommand LOGIC_COLOR + participant ":AutoCompletePrefixResolver" as ACPrefixResolver LOGIC_COLOR +end box + +mainframe **sd** get AutoCompleteResult from commandText + +[-> LogicManager: autoComplete(commandText) +activate LogicManager + +LogicManager -> AddressBookParser: parseAutoComplete(commandText) +activate AddressBookParser + +alt cannot parse commandText + +ref over AddressBookParser +create empty autocomplete +end ref + +else prefix absent in commandText + +create AutoCompleteCommand +AddressBookParser -> AutoCompleteCommand: AutoCompleteCommand() +activate AutoCompleteCommand +return + +else prefix present in commandText + +create ACPrefixResolver +AddressBookParser -> ACPrefixResolver: AutoCompletePrefixResolver(ALL_PREFIX_RESOLVERS) +activate ACPrefixResolver +return + +end + +return AutoComplete + +return AutoCompleteResult +@enduml diff --git a/docs/diagrams/AutocompleteUpdateSequenceDiagram.puml b/docs/diagrams/AutocompleteUpdateSequenceDiagram.puml new file mode 100644 index 00000000000..2af6060c286 --- /dev/null +++ b/docs/diagrams/AutocompleteUpdateSequenceDiagram.puml @@ -0,0 +1,36 @@ +@startuml +!include style.puml +skinparam ArrowFontStyle plain + +box Logic LOGIC_COLOR_T1 + participant ":LogicManager" as LogicManager LOGIC_COLOR + participant "<>\nAttributeValueGeneratorManager" as AVGManager LOGIC_COLOR + participant ":PrefixResolver" as PrefixResolver LOGIC_COLOR + participant ":AttributeTrie" as AttributeTrie LOGIC_COLOR +end box + +[-> LogicManager: execute(commandText) +activate LogicManager + +opt command modifies addressBook + +LogicManager -> LogicManager: getAddressBook() +activate LogicManager +return addressBook +LogicManager -> AVGManager : updateAddressBook(addressBook) +activate AVGManager + +'notify outdated data +note right of AVGManager: Iterates through a collection of PrefixResolvers and their AttributeTries +loop for each PrefixResolver + AVGManager -> PrefixResolver: notifyOutdatedData + activate PrefixResolver + PrefixResolver -> AttributeTrie: clearCache() + activate AttributeTrie + return + return +end +return +end +deactivate LogicManager +@enduml diff --git a/docs/diagrams/LogicClassDiagram.puml b/docs/diagrams/LogicClassDiagram.puml index 8b5f05215b9..3e92098b0fd 100644 --- a/docs/diagrams/LogicClassDiagram.puml +++ b/docs/diagrams/LogicClassDiagram.puml @@ -17,15 +17,18 @@ package Logic as LogicPackage { Class XYZCommand Class CommandResult Class "{abstract}\nCommand" as Command + note right of XYZCommand: XYZCommand = AddPersonCommand, \nFindPersonCommand, etc + XYZCommand -up-|> Command + XYZCommand .down.> CommandsUtil + Command .> CommandResult : creates > } - package "AutoComplete Classes" as AutoCompletePackage { - package "AutoComplete Utility Classes" as AutoCompleteUtil { - } - class "<>\nAutoComplete" as AutoComplete - class AutoCompleteXYZ - note bottom of AutoCompleteXYZ: AutoCompleteXYZ = AutoCompleteCommand, \nAutoCompleteNusNetId, etc - } + LogicManager .up|> Logic + LogicManager -up> ParserClasses + LogicManager ..> Command : calls > + LogicManager ..> CommandResult + ParserClasses .down> XYZCommand : creates > + Logic ..> CommandResult } package Model { @@ -33,31 +36,14 @@ package Model { } package Storage { + class HiddenModel #FFFFFF } Class HiddenOutside #FFFFFF -HiddenOutside ..> Logic - -LogicManager .right.|> Logic -LogicManager -right->"1" ParserClasses -ParserClasses ..> XYZCommand : <> -ParserClasses ...> AutoCompleteXYZ : <> -XYZCommand .down.> CommandsUtil -AutoCompleteXYZ .left.> AutoCompleteUtil - -XYZCommand -up-|> Command -AutoCompleteXYZ .up.|> AutoComplete -LogicManager .left.> Command : <> -LogicManager .down..> AutoComplete : <> - -LogicManager --> Model -LogicManager ----> Storage +HiddenOutside .down.> Logic -Command .[hidden]up.> Storage +LogicManager -down-> Model +LogicManager -right> Storage Command .right.> Model -note bottom of XYZCommand: XYZCommand = AddCommand, \nFindCommand, etc -Logic ..> CommandResult -LogicManager .down.> CommandResult -Command .up.> CommandResult : <> @enduml From 2faa71a901551f2085810a1e9a152432481e7567 Mon Sep 17 00:00:00 2001 From: Titus Chew <39845485+tituschewxj@users.noreply.github.com> Date: Sun, 14 Apr 2024 21:52:18 +0800 Subject: [PATCH 2/2] Update autocomplete dg --- docs/DeveloperGuide.md | 156 ++++++++++++++++-- ...ompleteFindTrieMatchesSequenceDiagram.puml | 4 +- .../AutocompleteParseSequenceDiagram.puml | 1 - 3 files changed, 147 insertions(+), 14 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index db10f99b78b..dd51381b36e 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -116,7 +116,7 @@ The `UI` component uses the JavaFx UI framework. The layout of these UI parts ar Here's a (partial) class diagram of the `Logic` component: - + The sequence diagram below illustrates the interactions within the `Logic` component, taking `execute("delstu nn/E1234567")` API call as an example. @@ -136,15 +136,6 @@ call as an example. Note that although this is shown as a single step in the diagram above (for simplicity), in the code it can take several interactions (between the command object and the `Model`) to achieve. 1. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `Logic`. -
- -**How autocomplete execution works in `Logic` component:** - -1. When `Logic` is called upon to autocomplete an input string, it is passed to an `AddressBookParser` object which in turn matches the input and return the corresponding autocomplete object (e.g. `AutoCompleteCommand`). -1. This results in a `AutoComplete` object (more precisely, an object of one of its subclasses e.g., `AutoCompleteCommand`) which is executed by the `LogicManager`. -1. The autocomplete object is solely responsible for generating the autocomplete suggestions based on the input string (e.g. the additional characters that can be appended to the input string). -1. The result of the autocompletion is simply a string that autocompletes the input string. Autocomplete classes uses [Trie](#trie) under the hood to efficiently generate the autocomplete suggestions. - Here are the other classes in `Logic` (omitted from the class diagram above) that are used for parsing a user command:

@@ -215,7 +206,148 @@ This section describes some noteworthy details on how certain features are imple ### Autocomplete Feature -**TODO** +Here is a (partial) class diagram of the autocomplete feature. + +

+ +There are 3 subcomponents in the [Logic component](#logic-component) that are involved the autocomplete feature, which are: +* Attribute Classes, that handle the resolution of dynamic attribute values. +* Parser Classes, that handle the parsing of the user input. +* AutoComplete Classes, that handle the generation of the autocompletion. + + + +Omitted from the (partial) class diagram is the functional interface `AttributeValueGenerator`, which produces a `List`, representing all possible values for an attribute of a student in TAPro's current data. + +`AttributeValueGeneratorManager` has static methods that match the method signature of `AttributeValueGenerator`, which is pass in as an argument when creating a `PrefixResolver`. + +`PrefixResolverSyntax` stores preset `PrefixResolvers` for all the `Prefix`s that can be autocompleted. + + +{{ newPageBetween }} + +There are two variants of autocomplete feature. One variant is the autocompletion of static data using `AutoCompleteCommand`. Another variant is the autocompletion of dynamic data using `AutoCompletePrefixResolver`. + +**How autocompletion of static data works using `AutoCompleteCommand` in the `Logic` component:** + +1. When `Logic` is called upon to autocomplete an input string, it is passed to an `AddressBookParser` object which in turn matches the input and return the corresponding `AutoComplete` object, `AutoCompleteCommand` in this case. +1. `AutoCompleteCommand` then produces an `AutoCompleteResult` which is executed by the `LogicManager`. +1. `AutoCompleteCommand` classes uses [`Trie`](#trie) under the hood to efficiently generate the autocomplete suggestions. The `Trie` is preloaded with static data of our command names (e.g. `addstu`), which is used to generate the suggestions. +1. The `AutoCompleteResult` object is solely responsible for generating the autocomplete suggestions based on the input string (e.g. the additional characters that can be appended to the input string). +1. The result of the autocompletion is simply a list of string suggestions that autocompletes the input string. + +**How autocompletion of dynamic data works using `AutoCompletePrefixResolver` in the `Logic` component:** + +In the autocompletion of dynamic data there are 5 main processes: +1. Notifying that the data is outdated +2. Using the autocomplete hotkey to return the autocompletion +3. Parsing the input to call the corresponding kind of autocompletion +4. Updating the new attribute data into the `AttributeTrie` +5. Generating the autocomplete result + +{{ newPageBetween }} + +**How the `AttributeTrie` is notified of new data:** + +1. When a command is executed, a check is performed in `LogicManager` to determine if the command could potentially modify the data. +1. If the data could be modified, then we would get the latest `addressBook` using `getAddressBook()`. +1. Then using the latest `addressBook`, we would update the `AttributeValueGeneratorManager` with `updateAddressBook(addressBook)`. +1. We iterate through all prefix resolvers to notify that the `PrefixResolver` needs to be updated using `notifyOutdatedData`. +1. Then `PrefixResolver` calls its corresponding `AttributeTrie` to `clearCache()`, which removes the `Trie` that is used internally. The absence of a `Trie` would cause `AttributeTrie` to lazily generate a new `Trie` using new data. Meaning that a new `Trie` is only generated when necessary. + +

+ +{{ newPageBetween }} + +**How the autocomplete hotkey works:** + +1. After the autocomplete hotkey {{ macros.keyFormat('Tab') }} is pressed, the method `handleTabKeyPressEvent(...)` is called. +1. Whenever `lastModifiedText` has changed, it means that the text in the `CommandBox`'s command input box has changed (e.g. the user types into the command input box), so the `autoCompleteResultCache` is set to `null` to indicate that the `AutoCompleteResult` is outdated. +1. If the `autoCompleteResultCache` is `null`, then we know that the `lastModifiedText` has changed, so we need to generate a new autocomplete result. We do this by calling `MainWindow#getAutoComplete(lastModifiedText)`, which calls the `LogicManager` to generate a new autocomplete result. +1. Otherwise, it means the `autoCompleteResultCache` still contains the latest `AutoCompleteResult` that works for the current `lastModifiedText`. +1. Once we have the latest `autoCompleteResultCache`, we call `autoCompleteResultCache.getNextResult()` to generate the next autocompletion. +1. Lastly, the text in the `CommandBox`'s command input box is updated to the suggested autocompletion using `setText(...)`. + +

+ + + +The reference frame below, `create empty autocomplete`, is used in the next few sequence diagrams. It represents that an `AutoCompleteResult` with no autocomplete suggestion is returned, meaning that pressing the autocomplete hotkey would cause no change in `CommandBox`'s command input box when it is used. + + + + +{{ newPageBetween }} + +**How `LogicManager` parses the input to generate a new `AutoCompleteResult`:** + +1. When `LogicManager#autoComplete(commandText)` is called with the text `commandText` to autocomplete, it calls the `AddressBookParser#parseAutoComplete(commandText)` method. +1. Depending on the `commandText` passed into `parseAutoComplete`, there are 3 possible paths: +1. The first path is that the `commandText` cannot be parsed as it doesn't meet format specifications. +1. The second path is that the `commandText` can be parsed, but is missing prefixes inside the text, so it is treated as an autocompletion for a command name. `AutoCompleteCommand` is then constructed and used like how autocompletion of static data works. +1. The final path is that the `commandText` can be parsed, and contains at least one prefix in the text, so it is treated as an autocompletion for a prefix. `AutoCompletePrefixResolver` is then constructed using `ALL_PREFIX_RESOLVERS` and used later on in `getAutoComplete`, given an `input`, to generate an autocompletion. +1. In all cases, a `AutoComplete` is returned, which `AutoCompleteCommand` and `AutoCompletePrefixResolver` are subclasses of. +1. The `AutoComplete` produces a `AutoCompleteResult`, which is passed back to the `MainWindow`. + +

+ +{{ newPageBetween }} + +**How `AutoCompletePrefixResolver` is generates an `AutoCompleteResult`:** + +1. When `AutoCompletePrefixResolver#getAutoComplete(input)` is called, if the `input` is blank, an empty `AutoCompleteResult` is returned. +1. Otherwise, it calls `findTriePrefixContinuation(input)` which would find the text, that continues from a given input, in the `AttributeTrie`. This may update the `AttributeTrie` with new attribute data if necessary, due to the lazy evaluation. +1. Then with the `trieMatchContinuations` returned from `findTriePrefixContinuation`, we use it to create the `AutoCompleteResult`. +1. If `trieMatchContinations` is empty, it means there are no autocomplete results for the current `input`, so an empty `AutoCompleteResult` is returned. +1. Otherwise, an `AutoCompleteResult` with the associated `trieMatchContinuations` is returned. + +

+ +{{ newPageBetween }} + +**How `AttributeTrie` is updated with new attribute data and returns the matches:** + +1. When `AutoCompletePrefixResolver#findTriePrefixContinuation(input)` is called, `findLastPrefixIndex(input)` is called which returns `indexOfLastPrefix`. +1. Then, with the `indexOfLastPrefix`, it calls `findLastPrefix` to find the last prefix in the `input`. +1. We iterate through all the `PrefixResolver`s to find one where `lastPrefix` matches the `PrefixResolver`'s `Prefix`. +1. If there is a match, we call `PrefixResolver#resolvePrefix(partialValue)` on the matching `PrefixResolver`, which calls `AttributeTrie#findAllValuesWithPrefix(partialValue)`. +1. When the `trieCache` is absent, it means that the `AttributeTrie#clearCache()` has been called before without a new `Trie` being generated. So `generateTrie()` is called, which generates values in the `Trie` using a `AttributeValueGenerator` which generates a list of attribute values to populate the `Trie` with. +1. The `AttributeTrie` then computes the list of values with the prefix and returns it back. +1. Finally, `AutoCompletePrefixResolver` formats the list of values and returns it as `trieMatchContinuations`, which are text continuations from the given `input`. + +

+ +{{ newPageBetween }} + +#### Design considerations + +**Separation of concerns:** + +As the autocomplete feature involves many classes all over the codebase, it is important to handle the separation of concerns carefully, to lead to higher cohesion and lower coupling. + +This was done through the following: +* Separating the notifying and updating of data from the storage, by using the methods `PrefixResolver#notifyOutdatedData` and `AttributeValueGeneratorManager#updateAddressBook`. + * How it worked was using the functional interface, `AttributeValueGenerator`, that is used by `AttributeValueGenerateManager` to generate an attribute values given the `addressBook`. The `AttributeValueGenerator` is then passed into the `AttributeTrie` to generate values to insert into the `Trie`. +* Separating the dynamic autocompletion from the static autocompletion, as their internal implementations were different. +* Having each of the subcomponents, Attribute Classes, Parser Classes and AutoComplete Classes, as packages, which encapsulates them, limiting functional overlaps. + +**Caching of intermediate results for improved performance:** + +There are two layers in the current implementation used for caching, which are: +* When the current `lastModifiedText` doesn't change, caching the `AutoCompleteResult` in `autoCompleteResultCache`. +* When the current data in the `addressBook` doesn't change, caching the `Trie` stored in the `AttributeTrie`. + +By having caching of intermediate results, it reduces the need to recompute certain results, thus improving performance of TAPro on users' systems. + +**Lazy evaluation to reduce redundant computations:** + +Lazy evaluation is carried out in `AttributeTrie`, where the new `Trie` was lazily evaluated. It means that the `Trie` was only generated when the autocompletion of a parameter value doesn't have an `AttributeTrie` already present. + +#### Future improvements to the autocomplete feature + +**Improve detection on whether attributes are actually modified before updating their `AttributeTrie`s:** +* Currently, our implementation causes all tries to be lazily reevaluated when a command potentially modifies the data. However, not all commands would actually modify the all data attribute values, but may only update a subset of those attribute values, or even none of the attribute values at all. +* Hence, we plan to check if the data for an attribute is actually modified before updating their respective `AttributeTrie`s, which would improve the performance of our autocompletion feature. {{ newPage }} @@ -317,6 +449,8 @@ The following activity diagram summarizes what happens when a user executes a ne

+{{ newPageBetween }} + #### Design considerations: **Aspect: How undo & redo executes:** diff --git a/docs/diagrams/AutocompleteFindTrieMatchesSequenceDiagram.puml b/docs/diagrams/AutocompleteFindTrieMatchesSequenceDiagram.puml index fc7a90b4ca0..5be6339eaa4 100644 --- a/docs/diagrams/AutocompleteFindTrieMatchesSequenceDiagram.puml +++ b/docs/diagrams/AutocompleteFindTrieMatchesSequenceDiagram.puml @@ -14,11 +14,11 @@ activate ACPrefixResolver ACPrefixResolver -> ACPrefixResolver: findLastPrefixIndex(input) activate ACPrefixResolver -deactivate ACPrefixResolver +return indexOfLastPrefix ACPrefixResolver -> ACPrefixResolver: findLastPrefix(input, indexOfLastPrefix) activate ACPrefixResolver -deactivate ACPrefixResolver +return lastPrefix note right of ACPrefixResolver: Iterates through a collection of PrefixResolvers and their AttributeTries loop for all PrefixResolvers diff --git a/docs/diagrams/AutocompleteParseSequenceDiagram.puml b/docs/diagrams/AutocompleteParseSequenceDiagram.puml index 92e47a159d1..40b5f743245 100644 --- a/docs/diagrams/AutocompleteParseSequenceDiagram.puml +++ b/docs/diagrams/AutocompleteParseSequenceDiagram.puml @@ -5,7 +5,6 @@ skinparam ArrowFontStyle plain box Logic LOGIC_COLOR_T1 participant ":LogicManager" as LogicManager LOGIC_COLOR participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR - participant ":AutoCompleteResult" as AutoCompleteResult LOGIC_COLOR participant ":AutoCompleteCommand" as AutoCompleteCommand LOGIC_COLOR participant ":AutoCompletePrefixResolver" as ACPrefixResolver LOGIC_COLOR end box