Better formula elements loading

This commit is contained in:
Your Name 2026-02-09 17:34:20 +01:00
parent 091dd9d4ec
commit 8df50f5e79
4 changed files with 74 additions and 20 deletions

11
TODO.md
View file

@ -2,12 +2,13 @@
[x] Means done
- [X] Unify error reporting. Create class ErrorHandler that get notified of every catched exception. This class prints the exception in stdout.
- [ ] Make formula description collapsable in FormulaScreen. Initialy, the description is visible, but the user can hide it.
- [X] Make formula description collapsable in FormulaScreen. Initialy, the description is visible, but the user can hide it.
- Refactor formula and unit loading:
- [ ] Create method `List<Object?> parseD4rtLiteral(String arrayStringLiteral). It parses a d4rt array literal (containing maps and arrays) to a List<Object?> using d4rt
- [ ] Remove `fromArrayStringLiteral` from UnitSpec and Formula.
- [ ] 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.
- [ ] 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] 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.
- [ ] Use a single table in database `FORMULAELEMENT` to store formulas and units. The table contains only two columns: autonumeric id and text.
- [ ] Create Formula.toStringLiteral. It is the reverse of Formula.fromSet( Formula.fromArrayStringLiteral(string)[0] )
- [ ] Create UnitSpec.toStringLiteral, like Formula.toStringLiteral

View file

@ -180,5 +180,28 @@ class Corpus{
Iterable<UnitSpec> allUnits() => _allUnits.values;
/// Loads formula elements, making sure to load units first, then formulas
/// to avoid dependency issues.
void loadFormulaElements(List<Object> elements) {
List<UnitSpec> units = [];
List<Formula> formulas = [];
// Separate units and formulas
for (final element in elements) {
if (element is UnitSpec) {
units.add(element);
} else if (element is Formula) {
formulas.add(element);
} else {
throw ArgumentError('Element must be either UnitSpec or Formula: $element');
}
}
// Load units first to satisfy dependencies
loadUnits(units);
// Then load formulas
loadFormulas(formulas);
}
}

View file

@ -39,7 +39,7 @@ Future<Corpus> createDefaultCorpus() async{
print( "Loading units from $unitRes");
final literal = await loadResourceAsString(unitRes);
final units = UnitSpec.fromArrayStringLiteral(literal);
corpus.loadUnits(units);
corpus.loadFormulaElements(units);
}
}
@ -49,7 +49,7 @@ Future<Corpus> createDefaultCorpus() async{
for (final formRes in formulaResources) {
final literal = await loadResourceAsString(formRes);
final formulas = Formula.fromArrayStringLiteral(literal);
corpus.loadFormulas(formulas);
corpus.loadFormulaElements(formulas);
}
}

View file

@ -23,6 +23,47 @@ abstract class SetUtils {
}
}
/// Parses a d4rt array literal (containing maps and arrays) to a List<Object?>
/// using d4rt
List<Object?> parseD4rtLiteral(String arrayStringLiteral) {
var d4rt = D4rt();
final buffer = StringBuffer();
buffer.write("main(){ return $arrayStringLiteral; }");
final code = buffer.toString();
final List<Object?> list = d4rt.execute(source: code);
return list;
}
/// Parses corpus elements from an array string literal.
/// Determines if each element is a formula or a unit and converts accordingly.
List<Object> parseCorpusElements(String arrayStringLiteral) {
final List<Object?> elements = parseD4rtLiteral(arrayStringLiteral);
final List<Object> result = [];
for (final element in elements) {
if (element is Map<Object?, Object?>) {
// Check if it's a formula by looking for required formula properties
// Formulas typically have 'd4rtCode' and 'input'/'output' properties
if (element.containsKey('d4rtCode')) {
result.add(Formula.fromSet(element));
}
// Units typically have 'name', 'symbol', and 'baseUnit' properties
else if (element.containsKey('name') && element.containsKey('symbol')) {
result.add(UnitSpec.fromSet(element));
}
else {
throw ArgumentError('Unknown element type: $element');
}
} else {
throw ArgumentError('Element must be a Map: $element');
}
}
return result;
}
typedef Number = double;
@ -86,12 +127,7 @@ class UnitSpec {
}
static List<UnitSpec> fromArrayStringLiteral(String arrayStringLiteral) {
var d4rt = D4rt();
final buffer = StringBuffer();
buffer.write("main(){ return $arrayStringLiteral; }");
final code = buffer.toString();
final List<Object?> list = d4rt.execute(source: code);
final List<Object?> list = parseD4rtLiteral(arrayStringLiteral);
final units = list.map((set) => UnitSpec.fromSet(set as Map));
@ -195,13 +231,7 @@ class Formula {
}
static List<Formula> fromArrayStringLiteral(String arrayStringLiteral) {
var d4rt = D4rt();
final buffer = StringBuffer();
buffer.write("main(){ return $arrayStringLiteral; }");
final code = buffer.toString();
//print("fromArrayStringLiteral:$code");
final List<Object?> list = d4rt.execute(source: code);
final List<Object?> list = parseD4rtLiteral(arrayStringLiteral);
final formulas = list.map((set) => Formula.fromSet(set as Map));