UUID for formulas
This commit is contained in:
parent
a9fd3bfc99
commit
0b0fccd4a3
5 changed files with 37 additions and 22 deletions
4
TODO.md
4
TODO.md
|
|
@ -53,5 +53,9 @@
|
||||||
- _prettyPrintSet(Set s, int indent)
|
- _prettyPrintSet(Set s, int indent)
|
||||||
- _prettyPrintArray(dynamic[] a, int indent)
|
- _prettyPrintArray(dynamic[] a, int indent)
|
||||||
- _prettyPrintRawString(String s, int indent): Use _prettyPrintRawString when the string contains newlines, $, backlash...
|
- _prettyPrintRawString(String s, int indent): Use _prettyPrintRawString when the string contains newlines, $, backlash...
|
||||||
|
- [X] Add a field to Formula: UUID.
|
||||||
|
- 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.
|
||||||
- [ ] 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.
|
- [ ] 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.
|
||||||
- [ ] Investigate https://pub.dev/packages/quantity
|
- [ ] Investigate https://pub.dev/packages/quantity
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,13 @@ class Multimap<K, V> extends DelegatingMap<K, List<V>> {
|
||||||
|
|
||||||
class Corpus{
|
class Corpus{
|
||||||
final Multimap<String, Formula> _tags = Multimap.create();
|
final Multimap<String, Formula> _tags = Multimap.create();
|
||||||
|
// Map formulas by uuid
|
||||||
final Map<String, Formula> _allFormulas = {};
|
final Map<String, Formula> _allFormulas = {};
|
||||||
|
|
||||||
void loadFormulas(List<Formula> formulas, {bool replaceOnDuplicates = true, bool checkUnits = true}) {
|
void loadFormulas(List<Formula> formulas, {bool replaceOnDuplicates = true, bool checkUnits = true}) {
|
||||||
for (final formula in formulas) {
|
for (final formula in formulas) {
|
||||||
if (!replaceOnDuplicates && _allFormulas.containsKey(formula.name)) {
|
if (!replaceOnDuplicates && _allFormulas.containsKey(formula.uuid)) {
|
||||||
throw ArgumentError("Duplicate formula:$formula");
|
throw ArgumentError("Duplicate formula:${formula}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if( checkUnits ){
|
if( checkUnits ){
|
||||||
|
|
@ -41,7 +42,7 @@ class Corpus{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_allFormulas[formula.name] = formula;
|
_allFormulas[formula.uuid] = formula;
|
||||||
for( final tag in formula.tags ){
|
for( final tag in formula.tags ){
|
||||||
_tags[tag]?.add(formula);
|
_tags[tag]?.add(formula);
|
||||||
}
|
}
|
||||||
|
|
@ -59,8 +60,18 @@ class Corpus{
|
||||||
return _allFormulas.values.toList(growable:false);
|
return _allFormulas.values.toList(growable:false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns first formula with the given name (preserves old API semantics).
|
||||||
Formula? getFormula(String name) {
|
Formula? getFormula(String name) {
|
||||||
return _allFormulas.get(name);
|
try {
|
||||||
|
return _allFormulas.values.firstWhere((f) => f.name == name);
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns formula by uuid
|
||||||
|
Formula? getFormulaByUuid(String uuid) {
|
||||||
|
return _allFormulas[uuid];
|
||||||
}
|
}
|
||||||
|
|
||||||
final Multimap<String, String> _baseToUnits = Multimap.create();
|
final Multimap<String, String> _baseToUnits = Multimap.create();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import 'package:d4rt/d4rt.dart';
|
import 'package:d4rt/d4rt.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:d4rt_formulas/d4rt_formulas.dart';
|
import 'package:d4rt_formulas/d4rt_formulas.dart';
|
||||||
|
import 'dart:math';
|
||||||
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
typedef Number = double;
|
typedef Number = double;
|
||||||
|
|
||||||
|
|
@ -45,7 +47,7 @@ abstract class SetUtils {
|
||||||
.replaceAll('\n', r'\\n')
|
.replaceAll('\n', r'\\n')
|
||||||
.replaceAll('\r', r'\\r')
|
.replaceAll('\r', r'\\r')
|
||||||
.replaceAll('\t', r'\\t')
|
.replaceAll('\t', r'\\t')
|
||||||
.replaceAll('"', r'\\"');
|
.replaceAll('"', r'\"');
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses corpus elements from an array string literal.
|
/// Parses corpus elements from an array string literal.
|
||||||
|
|
@ -95,7 +97,7 @@ abstract class SetUtils {
|
||||||
// Check if the string needs raw string formatting (newlines, $, backslashes, quotes)
|
// Check if the string needs raw string formatting (newlines, $, backslashes, quotes)
|
||||||
final needsRawString = s.contains('\n') ||
|
final needsRawString = s.contains('\n') ||
|
||||||
s.contains(r'$') ||
|
s.contains(r'$') ||
|
||||||
s.contains(r'\') ||
|
s.contains(r'\\') ||
|
||||||
s.contains('"');
|
s.contains('"');
|
||||||
|
|
||||||
if (needsRawString) {
|
if (needsRawString) {
|
||||||
|
|
@ -160,7 +162,7 @@ abstract class SetUtils {
|
||||||
/// Uses Dart's raw string syntax r"""..."""
|
/// Uses Dart's raw string syntax r"""..."""
|
||||||
static String _prettyPrintRawString(String s, int indent) {
|
static String _prettyPrintRawString(String s, int indent) {
|
||||||
// Escape triple quotes by replacing """ with ""\"
|
// Escape triple quotes by replacing """ with ""\"
|
||||||
final escaped = s.replaceAll('"""', r'""\"');
|
final escaped = s.replaceAll('"""', r'""\\"');
|
||||||
return 'r"""$escaped"""';
|
return 'r"""$escaped"""';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -296,7 +298,10 @@ class VariableSpec extends FormulaElement{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _generateUuidV4() => Uuid().v4();
|
||||||
|
|
||||||
class Formula extends FormulaElement {
|
class Formula extends FormulaElement {
|
||||||
|
final String uuid;
|
||||||
final String name;
|
final String name;
|
||||||
final String? description;
|
final String? description;
|
||||||
final List<VariableSpec> input;
|
final List<VariableSpec> input;
|
||||||
|
|
@ -306,6 +311,7 @@ class Formula extends FormulaElement {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
|
// UUID NOT INCLUDED ON PURPOSE
|
||||||
return {
|
return {
|
||||||
'name': name,
|
'name': name,
|
||||||
if (description != null) 'description': description,
|
if (description != null) 'description': description,
|
||||||
|
|
@ -317,13 +323,14 @@ class Formula extends FormulaElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
Formula({
|
Formula({
|
||||||
|
String? uuid = null,
|
||||||
required this.name,
|
required this.name,
|
||||||
this.description,
|
this.description,
|
||||||
required this.input,
|
required this.input,
|
||||||
required this.output,
|
required this.output,
|
||||||
required this.d4rtCode,
|
required this.d4rtCode,
|
||||||
this.tags = const [],
|
this.tags = const [],
|
||||||
}) {
|
}) : uuid = uuid ?? _generateUuidV4() {
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -337,25 +344,17 @@ class Formula extends FormulaElement {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() =>
|
String toString() =>
|
||||||
'Formula(name: $name, description: $description, input: $input, output: $output, d4rtCode: $d4rtCode, tags: $tags)';
|
'Formula(uuid: $uuid, name: $name, description: $description, input: $input, output: $output, d4rtCode: $d4rtCode, tags: $tags)';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
other is Formula &&
|
other is Formula &&
|
||||||
runtimeType == other.runtimeType &&
|
runtimeType == other.runtimeType &&
|
||||||
name == other.name &&
|
uuid == other.uuid;
|
||||||
description == other.description &&
|
|
||||||
output == other.output &&
|
|
||||||
ListEquality().equals(input, other.input) &&
|
|
||||||
d4rtCode == other.d4rtCode &&
|
|
||||||
ListEquality().equals(tags, other.tags);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode =>
|
int get hashCode => uuid.hashCode;
|
||||||
Object.hash(
|
|
||||||
name, description, ListEquality().hash(input), output, d4rtCode,
|
|
||||||
ListEquality().hash(tags));
|
|
||||||
|
|
||||||
List<String> inputVarNames() =>
|
List<String> inputVarNames() =>
|
||||||
input.map((v) => v.name).toList(growable: false);
|
input.map((v) => v.name).toList(growable: false);
|
||||||
|
|
@ -405,6 +404,7 @@ class Formula extends FormulaElement {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String? uuid = theSet['uuid'] as String?;
|
||||||
String name = SetUtils.stringValue(theSet, "name");
|
String name = SetUtils.stringValue(theSet, "name");
|
||||||
String? description = theSet["description"] as String?;
|
String? description = theSet["description"] as String?;
|
||||||
List<String> tags = (theSet["tags"] as List<Object?>? ?? []).map((t) =>
|
List<String> tags = (theSet["tags"] as List<Object?>? ?? []).map((t) =>
|
||||||
|
|
@ -417,6 +417,7 @@ class Formula extends FormulaElement {
|
||||||
String d4rtCode = SetUtils.stringValue(theSet, "d4rtCode");
|
String d4rtCode = SetUtils.stringValue(theSet, "d4rtCode");
|
||||||
|
|
||||||
return Formula(
|
return Formula(
|
||||||
|
uuid: uuid,
|
||||||
name: name,
|
name: name,
|
||||||
description: description,
|
description: description,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
|
|
|
||||||
|
|
@ -990,7 +990,7 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.5"
|
version: "3.1.5"
|
||||||
uuid:
|
uuid:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: uuid
|
name: uuid
|
||||||
sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489"
|
sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489"
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,7 @@ dependencies:
|
||||||
flutter_markdown_plus:
|
flutter_markdown_plus:
|
||||||
flutter_markdown_plus_latex:
|
flutter_markdown_plus_latex:
|
||||||
flutter_code_editor:
|
flutter_code_editor:
|
||||||
|
uuid:
|
||||||
# Drift dependencies for database support
|
|
||||||
drift:
|
drift:
|
||||||
sqlite3_flutter_libs:
|
sqlite3_flutter_libs:
|
||||||
path_provider:
|
path_provider:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue