2025-09-22 11:35:18 +00:00
|
|
|
import 'dart:math' as Math;
|
2025-08-21 16:35:50 +00:00
|
|
|
|
|
|
|
|
import 'package:d4rt/d4rt.dart';
|
|
|
|
|
import 'formula_models.dart';
|
|
|
|
|
|
2025-09-22 11:35:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-08-21 16:35:50 +00:00
|
|
|
/// Exception thrown when formula evaluation fails
|
|
|
|
|
class FormulaEvaluationException implements Exception {
|
|
|
|
|
final String message;
|
|
|
|
|
final Object? cause;
|
|
|
|
|
|
|
|
|
|
const FormulaEvaluationException(this.message, [this.cause]);
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
String toString() => 'FormulaEvaluationException: $message'
|
|
|
|
|
'${cause != null ? ' (caused by: $cause)' : ''}';
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-22 11:35:18 +00:00
|
|
|
class MyMath{
|
2025-10-05 15:25:49 +00:00
|
|
|
static Number myLog(Number x) => Math.log(x);
|
|
|
|
|
static Number myPow(Number b, Number e) => Math.pow(b,e) as Number;
|
2025-09-22 11:35:18 +00:00
|
|
|
}
|
|
|
|
|
|
2025-08-21 16:35:50 +00:00
|
|
|
class FormulaEvaluator {
|
|
|
|
|
final D4rt _interpreter;
|
|
|
|
|
|
2025-10-05 15:25:49 +00:00
|
|
|
static D4rt createDefaultInterpreter() => D4rt();
|
|
|
|
|
|
|
|
|
|
FormulaEvaluator([D4rt? interpreter]) : _interpreter = interpreter ?? createDefaultInterpreter(){
|
2025-09-22 11:35:18 +00:00
|
|
|
prepareInterpreter(_interpreter);
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-05 15:25:49 +00:00
|
|
|
static Number getNumberValueOf(String s){
|
2025-09-22 11:35:18 +00:00
|
|
|
return double.parse(s);
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-05 15:25:49 +00:00
|
|
|
static void prepareInterpreter(D4rt interpreter){
|
2025-09-22 11:35:18 +00:00
|
|
|
final myMathDefinition = BridgedClass(
|
|
|
|
|
nativeType: MyMath,
|
2025-10-05 15:25:49 +00:00
|
|
|
name: 'MyMath',
|
2025-09-22 11:35:18 +00:00
|
|
|
staticMethods: {
|
2025-10-05 15:25:49 +00:00
|
|
|
'myPow': (visitor, positionalArgs, namedArgs) {
|
2025-09-22 11:35:18 +00:00
|
|
|
final Number base = getNumberValueOf( positionalArgs[0].toString() );
|
|
|
|
|
final Number exp = getNumberValueOf( positionalArgs[1].toString() );
|
2025-10-05 15:25:49 +00:00
|
|
|
return MyMath.myPow(base,exp);
|
2025-09-22 11:35:18 +00:00
|
|
|
},
|
2025-10-05 15:25:49 +00:00
|
|
|
'myLog': (visitor, positionalArgs, namedArgs) {
|
2025-09-22 15:00:34 +00:00
|
|
|
final Number x = getNumberValueOf( positionalArgs[0].toString() );
|
2025-10-05 15:25:49 +00:00
|
|
|
return MyMath.myLog(x);
|
2025-09-22 15:00:34 +00:00
|
|
|
},
|
2025-09-22 11:35:18 +00:00
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
2025-09-22 15:00:34 +00:00
|
|
|
interpreter.registerBridgedClass(myMathDefinition, "package:d4rt_formulas.dart");
|
2025-09-22 11:35:18 +00:00
|
|
|
}
|
|
|
|
|
|
2025-10-15 08:10:29 +00:00
|
|
|
static dynamic evaluateExpression(String code, [D4rt? interpreter]) {
|
|
|
|
|
final d4rtInterpreter = interpreter ?? createDefaultInterpreter();
|
|
|
|
|
prepareInterpreter(d4rtInterpreter);
|
2025-10-05 15:25:49 +00:00
|
|
|
final d4rtCode = """
|
|
|
|
|
import 'dart:math';
|
|
|
|
|
import "package:d4rt_formulas.dart";
|
|
|
|
|
main()
|
|
|
|
|
{
|
2025-10-13 14:31:26 +00:00
|
|
|
late var result;
|
|
|
|
|
result = $code;
|
|
|
|
|
return result;
|
2025-10-05 15:25:49 +00:00
|
|
|
}""";
|
2025-10-13 14:31:26 +00:00
|
|
|
//print("evaluateExpression:\n$d4rtCode");
|
2025-10-15 08:10:29 +00:00
|
|
|
final result = d4rtInterpreter.execute(source: d4rtCode);
|
2025-10-05 15:25:49 +00:00
|
|
|
return result.toDouble();
|
|
|
|
|
}
|
2025-09-22 11:35:18 +00:00
|
|
|
|
2025-08-21 16:35:50 +00:00
|
|
|
dynamic evaluate(Formula formula, Map<String, dynamic> inputValues) {
|
|
|
|
|
_validateInputValues(formula, inputValues);
|
2025-09-22 15:00:34 +00:00
|
|
|
final completeSource = _buildCompleteSource(formula, inputValues);
|
|
|
|
|
final result = _interpreter.execute(source: completeSource);
|
|
|
|
|
return result;
|
2025-08-21 16:35:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _validateInputValues(Formula formula, Map<String, dynamic> inputValues) {
|
|
|
|
|
final missingVars = <String>[];
|
|
|
|
|
|
2025-08-24 09:52:34 +00:00
|
|
|
for (final inputVar in formula.inputVarNames()) {
|
2025-08-21 16:35:50 +00:00
|
|
|
if (!inputValues.containsKey(inputVar)) {
|
|
|
|
|
missingVars.add(inputVar);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (missingVars.isNotEmpty) {
|
|
|
|
|
throw FormulaEvaluationException(
|
|
|
|
|
'Missing required input variables for formula "${formula.name}": '
|
|
|
|
|
'${missingVars.join(', ')}',
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String getOutputVariableName(Formula formula) {
|
2025-08-24 09:52:34 +00:00
|
|
|
return formula.output.name;
|
2025-08-21 16:35:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String getOutputVariableMagnitude(Formula formula) {
|
2025-09-15 19:42:15 +00:00
|
|
|
return formula.output.unit;
|
2025-08-21 16:35:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List<String> getInputVariableOrder(Formula formula) {
|
2025-08-24 09:52:34 +00:00
|
|
|
return formula.inputVarNames()..sort();
|
2025-08-21 16:35:50 +00:00
|
|
|
}
|
|
|
|
|
|
2025-10-15 08:10:29 +00:00
|
|
|
static final String d4rtImports = """
|
|
|
|
|
import 'dart:math';
|
|
|
|
|
import "package:d4rt_formulas.dart";
|
|
|
|
|
""";
|
|
|
|
|
|
2025-08-21 16:35:50 +00:00
|
|
|
String _buildCompleteSource(Formula formula, Map<String, dynamic> inputValues) {
|
|
|
|
|
final buffer = StringBuffer();
|
2025-08-24 10:08:10 +00:00
|
|
|
|
2025-09-22 15:00:34 +00:00
|
|
|
buffer.writeln("""
|
2025-10-15 08:10:29 +00:00
|
|
|
$d4rtImports
|
2025-09-22 15:00:34 +00:00
|
|
|
|
|
|
|
|
main()
|
|
|
|
|
{
|
|
|
|
|
"""
|
|
|
|
|
);
|
2025-10-15 08:10:29 +00:00
|
|
|
|
2025-08-24 10:08:10 +00:00
|
|
|
|
2025-08-21 16:35:50 +00:00
|
|
|
for (final entry in inputValues.entries) {
|
|
|
|
|
final varName = entry.key;
|
|
|
|
|
final value = entry.value;
|
|
|
|
|
|
|
|
|
|
if (value is String) {
|
|
|
|
|
final escapedValue = value.replaceAll('"', '\\"');
|
2025-09-22 15:00:34 +00:00
|
|
|
buffer.writeln("""
|
|
|
|
|
final $varName = "$escapedValue";
|
|
|
|
|
""");
|
2025-08-21 16:35:50 +00:00
|
|
|
} else {
|
2025-09-22 15:00:34 +00:00
|
|
|
buffer.writeln("""
|
|
|
|
|
final $varName = $value;
|
|
|
|
|
""");
|
2025-08-21 16:35:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
2025-09-22 15:00:34 +00:00
|
|
|
buffer.writeln("""
|
|
|
|
|
late var ${getOutputVariableName(formula)};
|
|
|
|
|
${formula.d4rtCode}
|
|
|
|
|
return ${getOutputVariableName(formula)};
|
|
|
|
|
}
|
|
|
|
|
"""
|
|
|
|
|
);
|
2025-08-21 16:35:50 +00:00
|
|
|
|
|
|
|
|
return buffer.toString();
|
|
|
|
|
}
|
|
|
|
|
}
|