preparando apgar

This commit is contained in:
Álvaro González 2025-11-09 20:29:58 +01:00
parent e04276cb2a
commit 13612e7601
10 changed files with 74 additions and 40 deletions

View file

@ -37,8 +37,8 @@ void main() {
print(' Mass: 10.0 kg');
print(' Acceleration: 9.8 m/s²');
print(' Calculated Force: $force N');
print(' Output variable: ${evaluator.getOutputVariableName(newtonFormula)}');
print(' Output magnitude: ${evaluator.getOutputVariableMagnitude(newtonFormula)}');
print(' Output variable: ${newtonFormula.output.name}');
print(' Output magnitude: ${newtonFormula.output.unit}');
} catch (e) {
print(' Error: $e');
}

View file

@ -105,11 +105,11 @@ class _FormulaScreenState extends State<FormulaScreen> {
// Convert input to base unit if needed
// Always convert from dropdown unit to variable's base unit
late final convertedValue;
if( value is Number ) {
if( value is Number && input.unit != null ) {
convertedValue = widget.corpus.convert(
value,
_selectedUnits[input.name]!,
input.unit,
input.unit as String,
);
}
else{
@ -124,11 +124,17 @@ class _FormulaScreenState extends State<FormulaScreen> {
final result = evaluator.evaluate(widget.formula, inputValues);
// Convert output to selected unit if needed
String? unit = widget.formula.output.unit;
if( unit != null ) {
_result = widget.corpus.convert(
result,
widget.formula.output.unit,
unit,
_selectedOutputUnit!,
).toStringAsFixed(2);
}
else{
_result = result;
}
//print( "_evaluateFormula: result:${result} _result:${_result}");

View file

@ -34,7 +34,7 @@ class Corpus{
if( checkUnits ){
for( final inputVar in formula.input + [formula.output] ){
if( !_allUnits.containsKey(inputVar.unit) ){
if( inputVar.unit != null && !_allUnits.containsKey(inputVar.unit) ){
throw ArgumentError( "Unit not found: ${inputVar.unit}");
}
}
@ -71,7 +71,10 @@ class Corpus{
}
}
List<String> unitsOfSameMagnitude(String unit){
List<String> unitsOfSameMagnitude(String? unit){
if( unit == null ){
return ["unitless"];
}
final base = getUnit(unit).baseUnit;
return _baseToUnits[base] as List<String>;
}
@ -113,7 +116,7 @@ class Corpus{
}
final ret = _convertUsingCode(x, unit.codeFromUnitToBase as String);
return ret as Number;
return ret;
}
Number _convertFromBase(Number x, String toUnit) {
@ -128,7 +131,7 @@ class Corpus{
}
final ret = _convertUsingCode(x, unit.codeFromBaseToUnit as String);
return ret as Number;
return ret;
}
@ -140,17 +143,19 @@ class Corpus{
final ret = _evaluate(completeSourceExpression);
return ret;
}
catch(e1,stack){
catch(e1, stack1){
try{
completeSourceStatement = _converterFromCodeStringAsStatement(x, code);
final ret = _evaluate(completeSourceStatement);
return ret;
}
catch( e2, stack ){
catch( e2, stack2 ){
print(completeSourceExpression);
print(e1);
print(stack1);
print(completeSourceStatement);
print(e2);
print(stack2);
throw FormulaEvaluationException( "Evaluation as statement and expression failed" );
}
}

View file

@ -17,6 +17,7 @@ Future<Corpus> createDefaultCorpus() async{
"lib/defaults/units/force.d4rt.units",
"lib/defaults/units/mass.d4rt.units",
"lib/defaults/units/pressure.d4rt.units",
"lib/defaults/units/scalar.d4rt.units",
"lib/defaults/units/temperature.d4rt.units",
"lib/defaults/units/time.d4rt.units",
"lib/defaults/units/velocity.d4rt.units",

View file

@ -126,13 +126,13 @@ Where:
"name": "Apgar Score",
"description": "Newborn health assessment scoring system\n\nScores 0-2 for:\n1. Heart rate\n2. Breathing\n3. Muscle tone\n4. Reflexes\n5. Skin color\nTotal score 0-10",
"input": [
{"name": "HeartRate", "unit": "integer"},
{"name": "Breathing", "unit": "integer"},
{"name": "MuscleTone", "unit": "integer"},
{"name": "Reflexes", "unit": "integer"},
{"name": "SkinColor", "unit": "integer"}
{"name": "HeartRate", "values": ["hr1", "hr2", "hr3"] },
{"name": "Breathing", "values": ["hr1", "hr2", "hr3"] },
{"name": "MuscleTone", "values": ["hr1", "hr2", "hr3"] },
{"name": "Reflexes", "values": ["hr1", "hr2", "hr3"] },
{"name": "SkinColor", "values": ["hr1", "hr2", "hr3"] }
],
"output": {"name": "Result", "unit": "Apgar score"},
"output": {"name": "Result", "unit": "scalar"},
"d4rtCode": """
var total = HeartRate + Breathing + MuscleTone + Reflexes + SkinColor;
var interpretation = switch (total) {

View file

@ -0,0 +1,3 @@
[
{"name": "scalar", "symbol": "", "isBase": true}
]

View file

@ -121,13 +121,7 @@ class FormulaEvaluator {
}
}
String getOutputVariableName(Formula formula) {
return formula.output.name;
}
String getOutputVariableMagnitude(Formula formula) {
return formula.output.unit;
}
List<String> getInputVariableOrder(Formula formula) {
return formula.inputVarNames()..sort();
@ -166,9 +160,9 @@ class FormulaEvaluator {
}
}
buffer.writeln("""
late var ${getOutputVariableName(formula)};
late var ${formula.output.name};
${formula.d4rtCode}
return ${getOutputVariableName(formula)};
return ${formula.output.name};
}
"""
);

View file

@ -101,12 +101,18 @@ class UnitSpec {
class VariableSpec {
final String name;
final String unit;
final String? unit;
final List<dynamic>? allowedValues;
VariableSpec({required this.name, required this.unit});
VariableSpec({required this.name, this.unit, this.allowedValues}){
final valuesValid = allowedValues != null && allowedValues?.isNotEmpty == true;
if( unit == null && !valuesValid ){
throw new ArgumentError("$name: at least unit or allowedValues should be valid");
}
}
@override
String toString() => 'var($name: $unit)';
String toString() => 'var($name: $unit${allowedValues != null ? ' allowed: $allowedValues' : ''})';
@override
bool operator ==(Object other) =>
@ -114,10 +120,11 @@ class VariableSpec {
other is VariableSpec &&
runtimeType == other.runtimeType &&
unit == other.unit &&
name == other.name;
name == other.name &&
const DeepCollectionEquality().equals(allowedValues, other.allowedValues);
@override
int get hashCode => Object.hash(unit, name);
int get hashCode => Object.hash(unit, name, allowedValues != null ? const DeepCollectionEquality().hash(allowedValues!) : 0);
}
class Formula {
@ -196,8 +203,25 @@ class Formula {
factory Formula.fromSet(Map<Object?, Object?> theSet) {
VariableSpec parseVar(Map<Object?, Object?> varSpec) {
String name = SetUtils.stringValue(varSpec, "name");
String unit = SetUtils.stringValue(varSpec, "unit");
return VariableSpec(name: name, unit: unit);
String? unit;
if (varSpec.containsKey("unit")) {
unit = SetUtils.stringValue(varSpec, "unit");
}
final allowed = varSpec['values'] as List<dynamic>?;
if (allowed != null) {
final types = allowed.map((v) => v.runtimeType).toSet();
if (types.length > 1) {
throw ArgumentError('Allowed values must be all Strings or all Numbers');
}
if (!types.contains(String) && !types.contains(double) && !types.contains(int)) {
throw ArgumentError('Allowed values must be Strings or Numbers');
}
}
return VariableSpec(
name: name,
unit: unit,
allowedValues: allowed?.toList(growable: false),
);
}
String name = SetUtils.stringValue(theSet, "name");

View file

@ -29,6 +29,7 @@ main(){
}
""";
final interpreter = D4rt();
interpreter.grant(FilesystemPermission.readPath("/etc/passwd"));
final result = interpreter.execute(source: completeSource);
expect(result, contains("root"));

View file

@ -152,7 +152,7 @@ void main() {
d4rtCode: 'force = x;',
);
expect(evaluator.getOutputVariableName(formula), 'force');
expect(formula.output.name, 'force');
});
test(
@ -165,7 +165,7 @@ void main() {
d4rtCode: 'force = x;',
);
expect(evaluator.getOutputVariableMagnitude(formula), 'Newton');
expect(formula.output.unit, 'Newton');
},
);
@ -177,8 +177,8 @@ void main() {
d4rtCode: 'result = x;',
);
expect(evaluator.getOutputVariableName(validFormula), 'result');
expect(evaluator.getOutputVariableMagnitude(validFormula), 'Newton');
expect(validFormula.output.name, 'result');
expect(validFormula.output.unit, 'Newton');
});
});