algún avance con copilot en apgar

This commit is contained in:
Álvaro González 2026-01-25 19:20:28 +01:00
parent b053fc3900
commit 57becb5577

View file

@ -1,3 +1,4 @@
// dart
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:flutter_markdown/flutter_markdown.dart';
import '../formula_models.dart'; import '../formula_models.dart';
@ -15,9 +16,6 @@ class FormulaScreen extends StatefulWidget {
State<FormulaScreen> createState() => _FormulaScreenState(); State<FormulaScreen> createState() => _FormulaScreenState();
} }
// TODO: Create VariableWidget. Depending on VariableSpec.values, it can be a ValueDropdown or a D4rtEditingController
// The d4rtValue will be FormulaResult?
//// Start of D4rtEditingController class //// //// Start of D4rtEditingController class ////
class D4rtEditingController extends TextEditingController { class D4rtEditingController extends TextEditingController {
String? _lastError; String? _lastError;
@ -59,19 +57,25 @@ class _FormulaScreenState extends State<FormulaScreen> {
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
final Map<String, D4rtEditingController> _inputControllers = {}; final Map<String, D4rtEditingController> _inputControllers = {};
final Map<String, String?> _selectedUnits = {}; final Map<String, String?> _selectedUnits = {};
final Map<String, String?> _selectedValues = {}; // for string dropdowns
String? _result; String? _result;
String? _selectedOutputUnit; String? _selectedOutputUnit;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// Initialize controllers and units with listeners // Initialize controllers and units with listeners
for (final input in widget.formula.input) { for (final input in widget.formula.input) {
_inputControllers[input.name] = D4rtEditingController();
_selectedUnits[input.name] = input.unit; _selectedUnits[input.name] = input.unit;
if (input.values != null && input.values!.isNotEmpty) {
// string/categorical variable -> use dropdown
_selectedValues[input.name] = input.values!.first;
} else {
// numeric variable -> use D4rtEditingController
_inputControllers[input.name] = D4rtEditingController();
_inputControllers[input.name]!.addListener(_evaluateFormula); _inputControllers[input.name]!.addListener(_evaluateFormula);
} }
}
_selectedOutputUnit = widget.formula.output.unit; _selectedOutputUnit = widget.formula.output.unit;
} }
@ -91,34 +95,41 @@ class _FormulaScreenState extends State<FormulaScreen> {
try { try {
final inputValues = <String, dynamic>{}; final inputValues = <String, dynamic>{};
for (final input in widget.formula.input) { for (final input in widget.formula.input) {
// string/categorical variable
if (input.values != null && input.values!.isNotEmpty) {
final selected = _selectedValues[input.name];
if (selected == null) {
_result = "";
return;
}
inputValues[input.name] = selected;
continue;
}
// numeric variable - must have controller
final controller = _inputControllers[input.name]!; final controller = _inputControllers[input.name]!;
if (controller.d4rtValue == null) { final val = controller.d4rtValue;
//throw FormulaEvaluationException("Field ${input.name} is invalid"); if (val == null) {
_result = ""; _result = "";
return; return;
} }
late final dynamic convertedValue; dynamic convertedValue;
if (val is NumberResult) {
switch (controller.d4rtValue) {
case NumberResult nr:
// Convert input to base unit if needed
// Always convert from dropdown unit to variable's base unit
if (input.unit != null) { if (input.unit != null) {
convertedValue = widget.corpus.convert( convertedValue = widget.corpus.convert(
nr.value, val.value,
_selectedUnits[input.name]!, _selectedUnits[input.name]!,
input.unit as String, input.unit as String,
); );
} else { } else {
convertedValue = nr.value; convertedValue = val.value;
} }
} else if (val is StringResult) {
case StringResult sr: convertedValue = val.value;
convertedValue = sr.value; } else {
default:
throw FormulaEvaluationException( throw FormulaEvaluationException(
"Field ${input.name} has unsupported type ${controller.d4rtValue!.runtimeType}", "Field ${input.name} has unsupported type ${val.runtimeType}",
); );
} }
@ -131,14 +142,15 @@ class _FormulaScreenState extends State<FormulaScreen> {
// Convert output to selected unit if needed // Convert output to selected unit if needed
String? unit = widget.formula.output.unit; String? unit = widget.formula.output.unit;
if (unit != null) { if (unit != null) {
_result = widget.corpus final converted = widget.corpus.convert(result, unit, _selectedOutputUnit!);
.convert(result, unit, _selectedOutputUnit!) if (converted is num) {
.toStringAsFixed(2); _result = converted.toStringAsFixed(2);
} else { } else {
_result = result; _result = converted.toString();
}
} else {
_result = result?.toString();
} }
//print( "_evaluateFormula: result:${result} _result:${_result}");
setState(() {}); setState(() {});
} catch (e, stack) { } catch (e, stack) {
@ -269,12 +281,51 @@ class _FormulaScreenState extends State<FormulaScreen> {
} }
Widget _buildVariableRow(VariableSpec variable) { Widget _buildVariableRow(VariableSpec variable) {
final isCategorical = variable.values != null && variable.values!.isNotEmpty;
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0), padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Row( child: Row(
children: [ children: [
Text(variable.name), Text(variable.name),
const Spacer(), const Spacer(),
if (isCategorical) ...[
SizedBox(
width: 150,
child: DropdownButtonFormField<String>(
value: _selectedValues[variable.name],
items: variable.values!
.map((v) => DropdownMenuItem<String>(value: v, child: Text(v)))
.toList(),
onChanged: (v) {
setState(() {
_selectedValues[variable.name] = v;
});
_evaluateFormula();
},
decoration: const InputDecoration(
border: UnderlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) return 'Required';
return null;
},
),
),
const SizedBox(width: 8),
if (variable.unit != null)
UnitDropdown(
corpus: widget.corpus,
variable: variable,
selectedUnit: _selectedUnits[variable.name],
onUnitChanged: (unit) {
setState(() {
_selectedUnits[variable.name] = unit;
});
_evaluateFormula();
},
),
] else ...[
SizedBox( SizedBox(
width: 100, width: 100,
child: TextFormField( child: TextFormField(
@ -296,6 +347,7 @@ class _FormulaScreenState extends State<FormulaScreen> {
), ),
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
if (variable.unit != null)
UnitDropdown( UnitDropdown(
corpus: widget.corpus, corpus: widget.corpus,
variable: variable, variable: variable,
@ -308,6 +360,7 @@ class _FormulaScreenState extends State<FormulaScreen> {
}, },
), ),
], ],
],
), ),
); );
} }