Merge branch 'feature/add-uuid-column-formulaelements'

This commit is contained in:
Álvaro González 2026-04-05 17:45:45 +02:00
commit f9c03d50e4
7 changed files with 160 additions and 134 deletions

View file

@ -80,6 +80,10 @@
- The "paste" button will copy the clipboard into the text editor. - The "paste" button will copy the clipboard into the text editor.
- A second button "import" will use the import preview screen - A second button "import" will use the import preview screen
-[R] Launch test app_test.dart. Iterate until the test pass. -[R] Launch test app_test.dart. Iterate until the test pass.
- [ ] 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. - [R] Unify UUID and id of FormulaElement
- [ ] 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. - UUID is in memory
- id is in database
- remove id from database, add UUID to database
- [ ] Solve exception in _CorpusLoaderState.build() when GetIt.instance.registerSingleton<Corpus>(corpus) after importing formula, since there is already registeted.
- [ ] When importing FormulaElements, save the FormulaElements in the database (currently, they are only added to the Corpus in memory). - [ ] When importing FormulaElements, save the FormulaElements in the database (currently, they are only added to the Corpus in memory).
- [ ] 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.

View file

@ -7,6 +7,8 @@ BUILDCACHE=./.build-container-cache
DOCKERFILE=./docker/Dockerfile DOCKERFILE=./docker/Dockerfile
IMAGE=d4rt-formulas-builder IMAGE=d4rt-formulas-builder
ALL_ARGS="$@"
detect_container_manager(){ detect_container_manager(){
if [ "$DOCKER" != "" ] if [ "$DOCKER" != "" ]
@ -18,6 +20,12 @@ detect_container_manager(){
elif command -v docker > /dev/null 2>&1 elif command -v docker > /dev/null 2>&1
then then
DOCKER=docker DOCKER=docker
elif [ -n "$DISTROBOX_HOST_HOME" ]
then
echo "Detected distrobox, as DISTROBOX_HOST_HOME is defined"
echo "Please try to run this script as: "
echo " distrobox-host-exec $0 $ALL_ARGS"
exit 3
else else
echo "Error: no container manager detected (like 'docker' or 'podman'), please define DOCKER variable" echo "Error: no container manager detected (like 'docker' or 'podman'), please define DOCKER variable"
exit 2 exit 2

View file

@ -4,6 +4,7 @@ import 'package:d4rt_formulas/formula_models.dart';
import 'package:d4rt_formulas/corpus.dart'; import 'package:d4rt_formulas/corpus.dart';
import 'package:d4rt_formulas/ai/formula_editor.dart'; import 'package:d4rt_formulas/ai/formula_editor.dart';
import 'package:d4rt_formulas/services/import_service.dart'; import 'package:d4rt_formulas/services/import_service.dart';
import 'package:d4rt_formulas/service_locator.dart';
import 'package:flutter_code_editor/flutter_code_editor.dart'; import 'package:flutter_code_editor/flutter_code_editor.dart';
import 'package:flutter_highlight/themes/monokai-sublime.dart'; import 'package:flutter_highlight/themes/monokai-sublime.dart';
@ -28,11 +29,7 @@ class _ImportPreviewScreenState extends State<ImportPreviewScreen> {
super.initState(); super.initState();
// Select all by default // Select all by default
for (final element in widget.elements) { for (final element in widget.elements) {
if (element is Formula) {
_selectedUuids.add(element.uuid); _selectedUuids.add(element.uuid);
} else if (element is UnitSpec) {
_selectedUuids.add(element.name);
}
} }
} }
@ -59,14 +56,9 @@ class _ImportPreviewScreenState extends State<ImportPreviewScreen> {
} }
} }
void _importSelected() { Future<void> _importSelected() async {
final selectedElements = widget.elements.where((element) { final selectedElements = widget.elements.where((element) {
if (element is Formula) {
return _selectedUuids.contains(element.uuid); return _selectedUuids.contains(element.uuid);
} else if (element is UnitSpec) {
return _selectedUuids.contains(element.name);
}
return false;
}).toList(); }).toList();
if (selectedElements.isEmpty) { if (selectedElements.isEmpty) {
@ -79,6 +71,17 @@ class _ImportPreviewScreenState extends State<ImportPreviewScreen> {
try { try {
widget.corpus.loadFormulaElements(selectedElements, true); widget.corpus.loadFormulaElements(selectedElements, true);
// Save imported elements to the database
final database = getDatabase();
for (final element in selectedElements) {
final existingElement = await database.getFormulaElementByUuid(element.uuid);
if (existingElement != null) {
await database.updateFormulaElement(element.uuid, element.toStringLiteral());
} else {
await database.insertFormulaElement(element.uuid, element.toStringLiteral());
}
}
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text('Imported ${selectedElements.length} element(s) successfully'), content: Text('Imported ${selectedElements.length} element(s) successfully'),
@ -186,7 +189,7 @@ class _ImportPreviewScreenState extends State<ImportPreviewScreen> {
} }
Widget _buildUnitTile(UnitSpec unit) { Widget _buildUnitTile(UnitSpec unit) {
final isSelected = _selectedUuids.contains(unit.name); final isSelected = _selectedUuids.contains(unit.uuid);
return Card( return Card(
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
@ -196,9 +199,9 @@ class _ImportPreviewScreenState extends State<ImportPreviewScreen> {
onChanged: (value) { onChanged: (value) {
setState(() { setState(() {
if (value == true) { if (value == true) {
_selectedUuids.add(unit.name); _selectedUuids.add(unit.uuid);
} else { } else {
_selectedUuids.remove(unit.name); _selectedUuids.remove(unit.uuid);
} }
}); });
}, },

View file

@ -31,64 +31,39 @@ extension CorpusDatabaseExtension on FormulasDatabase {
// Clear existing elements first // Clear existing elements first
await delete(formulaElements).go(); await delete(formulaElements).go();
// Insert new elements // Insert new elements with their UUIDs
for (final element in elements) { for (final element in elements) {
await insertFormulaElement(element.toStringLiteral()); await insertFormulaElement(element.uuid, element.toStringLiteral());
} }
} }
// Method to update a formula in the database by UUID // Method to update a formula in the database by UUID
Future<bool> updateFormula(models.Formula formula) async { Future<bool> updateFormula(models.Formula formula) async {
final elements = await getAllFormulaElements(); final existingElement = await getFormulaElementByUuid(formula.uuid);
if (existingElement != null) {
for (final element in elements) { await updateFormulaElement(formula.uuid, formula.toStringLiteral());
try {
final parsed = SetUtils.parseCorpusElements('[${element.elementText}]');
if (parsed.isNotEmpty && parsed.first is models.Formula) {
final existingFormula = parsed.first as models.Formula;
if (existingFormula.uuid == formula.uuid) {
// Update this element
await updateFormulaElement(
element.id,
formula.toStringLiteral()
);
return true; return true;
} }
} return false;
} catch (e) {
print('Error parsing database element during update: $e');
continue;
}
}
return false; // Formula not found
} }
// Method to add a new formula to the database // Method to add a new formula to the database
Future<void> addFormula(models.Formula formula) async { Future<void> addFormula(models.Formula formula) async {
await insertFormulaElement(formula.toStringLiteral()); await insertFormulaElement(formula.uuid, formula.toStringLiteral());
} }
// Method to delete a formula from the database by name // Method to add a new formula element (formula or unit) to the database
Future<bool> deleteFormula(String uuid) async { Future<void> addFormulaElement(models.FormulaElement element) async {
final elements = await getAllFormulaElements(); await insertFormulaElement(element.uuid, element.toStringLiteral());
}
for (final element in elements) { // Method to delete a formula from the database by UUID
try { Future<bool> deleteFormula(String uuid) async {
final parsed = SetUtils.parseCorpusElements('[${element.elementText}]'); final existingElement = await getFormulaElementByUuid(uuid);
if (parsed.isNotEmpty && parsed.first is models.Formula) { if (existingElement != null) {
final existingFormula = parsed.first as models.Formula; await deleteFormulaElement(uuid);
if (existingFormula.uuid == uuid) {
await deleteFormulaElement(element.id);
return true; return true;
} }
} return false;
} catch (e) {
print('Error parsing database element during delete: $e');
continue;
}
}
return false; // Formula not found
} }
} }

View file

@ -7,10 +7,13 @@ if (dart.library.ffi) 'formulas_database_native.dart';
part 'formulas_database.g.dart'; part 'formulas_database.g.dart';
// Define the FORMULAELEMENT table to store both formulas and units as text
class FormulaElements extends Table { class FormulaElements extends Table {
IntColumn get id => integer().autoIncrement()(); TextColumn get uuid => text()();
TextColumn get elementText => text()(); TextColumn get elementText => text()();
@override
Set<Column> get primaryKey => {uuid};
} }
@DriftDatabase(tables: [FormulaElements]) @DriftDatabase(tables: [FormulaElements])
@ -21,8 +24,10 @@ class FormulasDatabase extends _$FormulasDatabase {
int get schemaVersion => 1; int get schemaVersion => 1;
// Method to insert a new formula element (either formula or unit) // Method to insert a new formula element (either formula or unit)
Future<int> insertFormulaElement(String elementText) { Future<void> insertFormulaElement(String uuid, String elementText) {
return into(formulaElements).insert(FormulaElementsCompanion.insert(elementText: elementText)); return into(formulaElements).insert(
FormulaElementsCompanion.insert(uuid: uuid, elementText: elementText),
);
} }
// Method to get all formula elements // Method to get all formula elements
@ -30,20 +35,20 @@ class FormulasDatabase extends _$FormulasDatabase {
return select(formulaElements).get(); return select(formulaElements).get();
} }
// Method to get a formula element by ID // Method to get a formula element by UUID
Future<FormulaElement?> getFormulaElementById(int id) { Future<FormulaElement?> getFormulaElementByUuid(String uuid) {
return (select(formulaElements)..where((tbl) => tbl.id.equals(id))).getSingleOrNull(); return (select(formulaElements)..where((tbl) => tbl.uuid.equals(uuid))).getSingleOrNull();
} }
// Method to update a formula element // Method to update a formula element
Future<void> updateFormulaElement(int id, String newElementText) { Future<void> updateFormulaElement(String uuid, String newElementText) {
return (update(formulaElements)..where((tbl) => tbl.id.equals(id))) return (update(formulaElements)..where((tbl) => tbl.uuid.equals(uuid)))
.write(FormulaElementsCompanion.insert(elementText: newElementText)); .write(FormulaElementsCompanion(elementText: Value(newElementText)));
} }
// Method to delete a formula element // Method to delete a formula element
Future<void> deleteFormulaElement(int id) { Future<void> deleteFormulaElement(String uuid) {
return (delete(formulaElements)..where((tbl) => tbl.id.equals(id))).go(); return (delete(formulaElements)..where((tbl) => tbl.uuid.equals(uuid))).go();
} }
// Additional helper methods for direct access to the table // Additional helper methods for direct access to the table

View file

@ -9,18 +9,14 @@ class $FormulaElementsTable extends FormulaElements
final GeneratedDatabase attachedDatabase; final GeneratedDatabase attachedDatabase;
final String? _alias; final String? _alias;
$FormulaElementsTable(this.attachedDatabase, [this._alias]); $FormulaElementsTable(this.attachedDatabase, [this._alias]);
static const VerificationMeta _idMeta = const VerificationMeta('id'); static const VerificationMeta _uuidMeta = const VerificationMeta('uuid');
@override @override
late final GeneratedColumn<int> id = GeneratedColumn<int>( late final GeneratedColumn<String> uuid = GeneratedColumn<String>(
'id', 'uuid',
aliasedName, aliasedName,
false, false,
hasAutoIncrement: true, type: DriftSqlType.string,
type: DriftSqlType.int, requiredDuringInsert: true,
requiredDuringInsert: false,
defaultConstraints: GeneratedColumn.constraintIsAlways(
'PRIMARY KEY AUTOINCREMENT',
),
); );
static const VerificationMeta _elementTextMeta = const VerificationMeta( static const VerificationMeta _elementTextMeta = const VerificationMeta(
'elementText', 'elementText',
@ -34,7 +30,7 @@ class $FormulaElementsTable extends FormulaElements
requiredDuringInsert: true, requiredDuringInsert: true,
); );
@override @override
List<GeneratedColumn> get $columns => [id, elementText]; List<GeneratedColumn> get $columns => [uuid, elementText];
@override @override
String get aliasedName => _alias ?? actualTableName; String get aliasedName => _alias ?? actualTableName;
@override @override
@ -47,8 +43,13 @@ class $FormulaElementsTable extends FormulaElements
}) { }) {
final context = VerificationContext(); final context = VerificationContext();
final data = instance.toColumns(true); final data = instance.toColumns(true);
if (data.containsKey('id')) { if (data.containsKey('uuid')) {
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); context.handle(
_uuidMeta,
uuid.isAcceptableOrUnknown(data['uuid']!, _uuidMeta),
);
} else if (isInserting) {
context.missing(_uuidMeta);
} }
if (data.containsKey('element_text')) { if (data.containsKey('element_text')) {
context.handle( context.handle(
@ -65,14 +66,14 @@ class $FormulaElementsTable extends FormulaElements
} }
@override @override
Set<GeneratedColumn> get $primaryKey => {id}; Set<GeneratedColumn> get $primaryKey => {uuid};
@override @override
FormulaElement map(Map<String, dynamic> data, {String? tablePrefix}) { FormulaElement map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return FormulaElement( return FormulaElement(
id: attachedDatabase.typeMapping.read( uuid: attachedDatabase.typeMapping.read(
DriftSqlType.int, DriftSqlType.string,
data['${effectivePrefix}id'], data['${effectivePrefix}uuid'],
)!, )!,
elementText: attachedDatabase.typeMapping.read( elementText: attachedDatabase.typeMapping.read(
DriftSqlType.string, DriftSqlType.string,
@ -88,20 +89,20 @@ class $FormulaElementsTable extends FormulaElements
} }
class FormulaElement extends DataClass implements Insertable<FormulaElement> { class FormulaElement extends DataClass implements Insertable<FormulaElement> {
final int id; final String uuid;
final String elementText; final String elementText;
const FormulaElement({required this.id, required this.elementText}); const FormulaElement({required this.uuid, required this.elementText});
@override @override
Map<String, Expression> toColumns(bool nullToAbsent) { Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{}; final map = <String, Expression>{};
map['id'] = Variable<int>(id); map['uuid'] = Variable<String>(uuid);
map['element_text'] = Variable<String>(elementText); map['element_text'] = Variable<String>(elementText);
return map; return map;
} }
FormulaElementsCompanion toCompanion(bool nullToAbsent) { FormulaElementsCompanion toCompanion(bool nullToAbsent) {
return FormulaElementsCompanion( return FormulaElementsCompanion(
id: Value(id), uuid: Value(uuid),
elementText: Value(elementText), elementText: Value(elementText),
); );
} }
@ -112,7 +113,7 @@ class FormulaElement extends DataClass implements Insertable<FormulaElement> {
}) { }) {
serializer ??= driftRuntimeOptions.defaultSerializer; serializer ??= driftRuntimeOptions.defaultSerializer;
return FormulaElement( return FormulaElement(
id: serializer.fromJson<int>(json['id']), uuid: serializer.fromJson<String>(json['uuid']),
elementText: serializer.fromJson<String>(json['elementText']), elementText: serializer.fromJson<String>(json['elementText']),
); );
} }
@ -120,18 +121,19 @@ class FormulaElement extends DataClass implements Insertable<FormulaElement> {
Map<String, dynamic> toJson({ValueSerializer? serializer}) { Map<String, dynamic> toJson({ValueSerializer? serializer}) {
serializer ??= driftRuntimeOptions.defaultSerializer; serializer ??= driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{ return <String, dynamic>{
'id': serializer.toJson<int>(id), 'uuid': serializer.toJson<String>(uuid),
'elementText': serializer.toJson<String>(elementText), 'elementText': serializer.toJson<String>(elementText),
}; };
} }
FormulaElement copyWith({int? id, String? elementText}) => FormulaElement( FormulaElement copyWith({String? uuid, String? elementText}) =>
id: id ?? this.id, FormulaElement(
uuid: uuid ?? this.uuid,
elementText: elementText ?? this.elementText, elementText: elementText ?? this.elementText,
); );
FormulaElement copyWithCompanion(FormulaElementsCompanion data) { FormulaElement copyWithCompanion(FormulaElementsCompanion data) {
return FormulaElement( return FormulaElement(
id: data.id.present ? data.id.value : this.id, uuid: data.uuid.present ? data.uuid.value : this.uuid,
elementText: data.elementText.present elementText: data.elementText.present
? data.elementText.value ? data.elementText.value
: this.elementText, : this.elementText,
@ -141,70 +143,82 @@ class FormulaElement extends DataClass implements Insertable<FormulaElement> {
@override @override
String toString() { String toString() {
return (StringBuffer('FormulaElement(') return (StringBuffer('FormulaElement(')
..write('id: $id, ') ..write('uuid: $uuid, ')
..write('elementText: $elementText') ..write('elementText: $elementText')
..write(')')) ..write(')'))
.toString(); .toString();
} }
@override @override
int get hashCode => Object.hash(id, elementText); int get hashCode => Object.hash(uuid, elementText);
@override @override
bool operator ==(Object other) => bool operator ==(Object other) =>
identical(this, other) || identical(this, other) ||
(other is FormulaElement && (other is FormulaElement &&
other.id == this.id && other.uuid == this.uuid &&
other.elementText == this.elementText); other.elementText == this.elementText);
} }
class FormulaElementsCompanion extends UpdateCompanion<FormulaElement> { class FormulaElementsCompanion extends UpdateCompanion<FormulaElement> {
final Value<int> id; final Value<String> uuid;
final Value<String> elementText; final Value<String> elementText;
final Value<int> rowid;
const FormulaElementsCompanion({ const FormulaElementsCompanion({
this.id = const Value.absent(), this.uuid = const Value.absent(),
this.elementText = const Value.absent(), this.elementText = const Value.absent(),
this.rowid = const Value.absent(),
}); });
FormulaElementsCompanion.insert({ FormulaElementsCompanion.insert({
this.id = const Value.absent(), required String uuid,
required String elementText, required String elementText,
}) : elementText = Value(elementText); this.rowid = const Value.absent(),
}) : uuid = Value(uuid),
elementText = Value(elementText);
static Insertable<FormulaElement> custom({ static Insertable<FormulaElement> custom({
Expression<int>? id, Expression<String>? uuid,
Expression<String>? elementText, Expression<String>? elementText,
Expression<int>? rowid,
}) { }) {
return RawValuesInsertable({ return RawValuesInsertable({
if (id != null) 'id': id, if (uuid != null) 'uuid': uuid,
if (elementText != null) 'element_text': elementText, if (elementText != null) 'element_text': elementText,
if (rowid != null) 'rowid': rowid,
}); });
} }
FormulaElementsCompanion copyWith({ FormulaElementsCompanion copyWith({
Value<int>? id, Value<String>? uuid,
Value<String>? elementText, Value<String>? elementText,
Value<int>? rowid,
}) { }) {
return FormulaElementsCompanion( return FormulaElementsCompanion(
id: id ?? this.id, uuid: uuid ?? this.uuid,
elementText: elementText ?? this.elementText, elementText: elementText ?? this.elementText,
rowid: rowid ?? this.rowid,
); );
} }
@override @override
Map<String, Expression> toColumns(bool nullToAbsent) { Map<String, Expression> toColumns(bool nullToAbsent) {
final map = <String, Expression>{}; final map = <String, Expression>{};
if (id.present) { if (uuid.present) {
map['id'] = Variable<int>(id.value); map['uuid'] = Variable<String>(uuid.value);
} }
if (elementText.present) { if (elementText.present) {
map['element_text'] = Variable<String>(elementText.value); map['element_text'] = Variable<String>(elementText.value);
} }
if (rowid.present) {
map['rowid'] = Variable<int>(rowid.value);
}
return map; return map;
} }
@override @override
String toString() { String toString() {
return (StringBuffer('FormulaElementsCompanion(') return (StringBuffer('FormulaElementsCompanion(')
..write('id: $id, ') ..write('uuid: $uuid, ')
..write('elementText: $elementText') ..write('elementText: $elementText, ')
..write('rowid: $rowid')
..write(')')) ..write(')'))
.toString(); .toString();
} }
@ -225,13 +239,15 @@ abstract class _$FormulasDatabase extends GeneratedDatabase {
typedef $$FormulaElementsTableCreateCompanionBuilder = typedef $$FormulaElementsTableCreateCompanionBuilder =
FormulaElementsCompanion Function({ FormulaElementsCompanion Function({
Value<int> id, required String uuid,
required String elementText, required String elementText,
Value<int> rowid,
}); });
typedef $$FormulaElementsTableUpdateCompanionBuilder = typedef $$FormulaElementsTableUpdateCompanionBuilder =
FormulaElementsCompanion Function({ FormulaElementsCompanion Function({
Value<int> id, Value<String> uuid,
Value<String> elementText, Value<String> elementText,
Value<int> rowid,
}); });
class $$FormulaElementsTableFilterComposer class $$FormulaElementsTableFilterComposer
@ -243,8 +259,8 @@ class $$FormulaElementsTableFilterComposer
super.$addJoinBuilderToRootComposer, super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer, super.$removeJoinBuilderFromRootComposer,
}); });
ColumnFilters<int> get id => $composableBuilder( ColumnFilters<String> get uuid => $composableBuilder(
column: $table.id, column: $table.uuid,
builder: (column) => ColumnFilters(column), builder: (column) => ColumnFilters(column),
); );
@ -263,8 +279,8 @@ class $$FormulaElementsTableOrderingComposer
super.$addJoinBuilderToRootComposer, super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer, super.$removeJoinBuilderFromRootComposer,
}); });
ColumnOrderings<int> get id => $composableBuilder( ColumnOrderings<String> get uuid => $composableBuilder(
column: $table.id, column: $table.uuid,
builder: (column) => ColumnOrderings(column), builder: (column) => ColumnOrderings(column),
); );
@ -283,8 +299,8 @@ class $$FormulaElementsTableAnnotationComposer
super.$addJoinBuilderToRootComposer, super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer, super.$removeJoinBuilderFromRootComposer,
}); });
GeneratedColumn<int> get id => GeneratedColumn<String> get uuid =>
$composableBuilder(column: $table.id, builder: (column) => column); $composableBuilder(column: $table.uuid, builder: (column) => column);
GeneratedColumn<String> get elementText => $composableBuilder( GeneratedColumn<String> get elementText => $composableBuilder(
column: $table.elementText, column: $table.elementText,
@ -329,16 +345,23 @@ class $$FormulaElementsTableTableManager
$$FormulaElementsTableAnnotationComposer($db: db, $table: table), $$FormulaElementsTableAnnotationComposer($db: db, $table: table),
updateCompanionCallback: updateCompanionCallback:
({ ({
Value<int> id = const Value.absent(), Value<String> uuid = const Value.absent(),
Value<String> elementText = const Value.absent(), Value<String> elementText = const Value.absent(),
}) => FormulaElementsCompanion(id: id, elementText: elementText), Value<int> rowid = const Value.absent(),
}) => FormulaElementsCompanion(
uuid: uuid,
elementText: elementText,
rowid: rowid,
),
createCompanionCallback: createCompanionCallback:
({ ({
Value<int> id = const Value.absent(), required String uuid,
required String elementText, required String elementText,
Value<int> rowid = const Value.absent(),
}) => FormulaElementsCompanion.insert( }) => FormulaElementsCompanion.insert(
id: id, uuid: uuid,
elementText: elementText, elementText: elementText,
rowid: rowid,
), ),
withReferenceMapper: (p0) => p0 withReferenceMapper: (p0) => p0
.map((e) => (e.readTable(table), BaseReferences(db, table, e))) .map((e) => (e.readTable(table), BaseReferences(db, table, e)))

View file

@ -7,8 +7,12 @@ import 'package:uuid/uuid.dart';
typedef Number = double; typedef Number = double;
String _generateUuidV4() => Uuid().v4();
/// Abstract base class for formula elements /// Abstract base class for formula elements
abstract class FormulaElement { abstract class FormulaElement {
String get uuid;
Map<String, dynamic> toMap(); Map<String, dynamic> toMap();
String toStringLiteral() { String toStringLiteral() {
@ -18,6 +22,8 @@ abstract class FormulaElement {
} }
class UnitSpec extends FormulaElement { class UnitSpec extends FormulaElement {
@override
final String uuid;
final String name; final String name;
final String baseUnit; final String baseUnit;
final String symbol; final String symbol;
@ -28,6 +34,7 @@ class UnitSpec extends FormulaElement {
@override @override
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {
'uuid': uuid,
"name": name, "name": name,
"baseUnit": baseUnit, "baseUnit": baseUnit,
"symbol": symbol, "symbol": symbol,
@ -38,32 +45,35 @@ class UnitSpec extends FormulaElement {
} }
UnitSpec({ UnitSpec({
String? uuid,
required this.name, required this.name,
required this.baseUnit, required this.baseUnit,
required this.symbol, required this.symbol,
this.factorFromUnitToBase, this.factorFromUnitToBase,
this.codeFromBaseToUnit, this.codeFromBaseToUnit,
this.codeFromUnitToBase, this.codeFromUnitToBase,
}); }) : uuid = uuid ?? _generateUuidV4();
factory UnitSpec.fromSet(Map<Object?, Object?> theSet) { factory UnitSpec.fromSet(Map<Object?, Object?> theSet) {
String? uuid = theSet['uuid'] as String?;
String name = SetUtils.stringValue(theSet, "name"); String name = SetUtils.stringValue(theSet, "name");
String symbol = SetUtils.stringValue(theSet, "symbol"); String symbol = SetUtils.stringValue(theSet, "symbol");
if (theSet.containsKey("isBase")) { if (theSet.containsKey("isBase")) {
return UnitSpec(name: name, baseUnit: name, symbol: symbol, factorFromUnitToBase: 1); return UnitSpec(uuid: uuid, name: name, baseUnit: name, symbol: symbol, factorFromUnitToBase: 1);
} }
String baseUnit = SetUtils.stringValue(theSet, "baseUnit"); String baseUnit = SetUtils.stringValue(theSet, "baseUnit");
if (theSet.containsKey("factor")) { if (theSet.containsKey("factor")) {
Number factorFromUnitToBase = SetUtils.numberValue(theSet, "factor"); Number factorFromUnitToBase = SetUtils.numberValue(theSet, "factor");
return UnitSpec(name: name, baseUnit: baseUnit, symbol: symbol, factorFromUnitToBase: factorFromUnitToBase); return UnitSpec(uuid: uuid, name: name, baseUnit: baseUnit, symbol: symbol, factorFromUnitToBase: factorFromUnitToBase);
} else if (theSet.containsKey("toBase")) { } else if (theSet.containsKey("toBase")) {
String codeFromBaseToUnit = SetUtils.stringValue(theSet, "fromBase"); String codeFromBaseToUnit = SetUtils.stringValue(theSet, "fromBase");
String codeFromUnitToBase = SetUtils.stringValue(theSet, "toBase"); String codeFromUnitToBase = SetUtils.stringValue(theSet, "toBase");
return UnitSpec( return UnitSpec(
uuid: uuid,
name: name, name: name,
baseUnit: baseUnit, baseUnit: baseUnit,
symbol: symbol, symbol: symbol,
@ -84,7 +94,7 @@ class UnitSpec extends FormulaElement {
} }
} }
class VariableSpec extends FormulaElement { class VariableSpec{
final String name; final String name;
final String? unit; final String? unit;
final List<dynamic>? values; final List<dynamic>? values;
@ -128,8 +138,6 @@ class VariableSpec extends FormulaElement {
int get hashCode => Object.hash(unit, name, values != null ? const DeepCollectionEquality().hash(values!) : 0); int get hashCode => Object.hash(unit, name, values != null ? const DeepCollectionEquality().hash(values!) : 0);
} }
String _generateUuidV4() => Uuid().v4();
abstract class FormulaInterface { abstract class FormulaInterface {
String get uuid; String get uuid;