- [X] Create method `List<Object?> parseD4rtLiteral(String arrayStringLiteral). It parses a d4rt array literal (containing maps and arrays) to a List<Object?> using d4rt
- [X] Make `fromArrayStringLiteral` from UnitSpec and Formula to use parseD4rtLiteral
- [X] Create function `List<Object> parseCorpusElements(String arrayStringLiteral)`. It uses parseD4rtLiteral and determines if each element of the array is a formula or a unit. Then converts the objects with Formula.fromSet or UnitSpec.fromSet.
- [X] Create method loadFormulaElements( List<Object> elements). Tipically receives the list from parseCorpusElements(). It loads the units first, then the formulas, to avoid missing dependencies.
- [X] Change createDefaultCorpus to use loadFormulaElements instead of loadUnits and loadFormula. Make loadUnits and loadFormula private.
- [X] Use a single table in database `FORMULAELEMENT` to store formulas and units. The table contains only two columns: autonumeric id and text.
- Drift files have a lot of duplicate code. "web" version is the same as native version, only _openConnection is diferrent. Refactor to not duplicate code.
- [X] If the database is empty, sugest to use a default corpus
- [X] If the user choose to use the default corpus, populate de database with the default corpus (load defaultcorpus, and then use toStringLiteral). If not, start with an empty list of formulas.
- [X] From now on, the corpus will be loaded from database instead of assets
- [X] Create method List<FormulaElement> Corpus.withDependencies(Formula formula). It will return the formula, the units of the formula, and all the units from the corpus with the same base unit.
- [X] Replace flutter-markdown with flutter-markdown-plus
- [X] Heron's formula: investigate why a=3, b=40, c=5 yields NaN. Root cause: input values don't form a valid triangle (violate triangle inequality: 3+5=8 is not > 40). Added documentation note to the formula description.
- [X] Pretty print files as dart literals (like JSON, but allow raw strings r"""like this""")
- [X] Ensure there is no formula duplicates. If necesary, move or delete the formula in file formulas.d4rt
- [X] defaultCorpus must load all formula files
- [X] Create a formula in ./assets/formulas/networking.d4art: input is a string with ip address and mask, output is ip subnet of this address and broadcast address.
- [R] Develop a new screen that edits a formula in ./lib/ai directory:
- [R] FormulaEditor initializes with a Formula
- [R] A textfield allows editing the "name" of the formula
- [R] A text area allows editing the "description". A button pops up a preview of the markdown.
- [R] There is one row per input variable. The "name" is a textfield. A first drop down allows to select the base unit, and a second dropdown is populated with all derived units of the selected base unit, and the base unit. The unit of the input variable is the derived unit.
- [R] Each input variable can be deleted with a button
- [R] A button after the inputs variables allows to insert a new input variable
- [R] There is one row for the ouput variable, similar to the row for the input variable
- [R] d4rtCode is a text area with dart syntax highligthing
- [R] At the botton, a button allows to test the edited Formula, launching a FormulaScreen
- [X] Create SetUtils.prettyPrint(): receives a dynamic Set, Array, string or number. Convert to a dart representation of than value (a set/array literal), json-like, but for dart language. Do it recursivelly on local functions to that method:
- _prettyPrintString(String s, int indent): Only for simple strings
- _prettyPrintNumber(Number n, int indent)
- _prettyPrintSet(Set s, int indent)
- _prettyPrintArray(dynamic[] a, int indent)
- _prettyPrintRawString(String s, int indent): Use _prettyPrintRawString when the string contains newlines, $, backlash...
- A constructor without UUID will generate a new random UUID. A constructor with UUID will use the provided UUID.
- The field should be used in database and everywhere instead of the name. The name is not unique anymore, but the UUID is.
- This will be used to identify formulas, instead of the name. This way, we can have formulas with the same name but different UUIDs. The name is not unique anymore. Corpus will be a list of UUIDs, instead of a list of formulas. The corpus.getFormula() method will return the first formula with that name.
- [R] When _FormulaScreenState._evaluateFormula() detect an error, instead of show an SnackBar, show a ExpansionTile with "⚠️ There were an error. Show details..." with the details of the exception. The ExpansionTile will be invisible if there is no error.
- [R] In FormulaEditor, add a button to "Save as copy", additional to the existing button "Save". It doesnt matter if the copy has the same name as the original formula, since they are identified by a internal UUID.
- The screen will receive a list of FormulaElements to import
- The formulas will have a "edit" button to show a FormulaEditor with the formula
- The screen will have an "import all" button to import all the FormulaElements in the list. This will call Corpus.addFormulaElement() for each element, and then pop the screen.
- [ ] Add a uuid column to the table or FormulaElements, so it is not necessary to load all the formulas to find a formula by uuid. This will improve performance when updating and deleting.
- [ ] Make formulaSolver() asyncronous, and show a CircularProgressIndicator while the formula is being solved. Honor a new optinal parameter "timeout" in formulaSolver, that will throw a TimeoutException.
- [ ] When importing FormulaElements, save the FormulaElements in the database (currently, they are only added to the Corpus in memory).