From e08474a7ebb5108b563ba22ee2a22558bbab79dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Gonz=C3=A1lez?= Date: Mon, 15 Sep 2025 21:42:15 +0200 Subject: [PATCH] magnitude -> unit --- aider.sh | 2 +- example/formula_evaluation_example.dart | 28 +- lib/ai/FormulaWidget.dart | 333 ------------------------ lib/ai/unit_list.dart | 6 +- lib/formula_evaluator.dart | 2 +- lib/formula_models.dart | 12 +- lib/main.dart | 1 - test/formula_evaluator_test.dart | 70 ++--- 8 files changed, 60 insertions(+), 394 deletions(-) delete mode 100644 lib/ai/FormulaWidget.dart diff --git a/aider.sh b/aider.sh index 4cdb855..6a39ffb 100755 --- a/aider.sh +++ b/aider.sh @@ -1,2 +1,2 @@ -aider --git --watch-files --read CLAUDE.md --notifications +aider --git --watch-files --read CLAUDE.md --notifications --no-auto-commits diff --git a/example/formula_evaluation_example.dart b/example/formula_evaluation_example.dart index da1ca41..068c699 100644 --- a/example/formula_evaluation_example.dart +++ b/example/formula_evaluation_example.dart @@ -19,10 +19,10 @@ void main() { final newtonFormula = Formula( name: "Newton's Second Law", input: [ - VariableSpec(name: 'm', magnitude: 'mass'), - VariableSpec(name: 'a', magnitude: 'acceleration'), + VariableSpec(name: 'm', unit: 'mass'), + VariableSpec(name: 'a', unit: 'acceleration'), ], - output: VariableSpec(name: 'F', magnitude: 'force'), + output: VariableSpec(name: 'F', unit: 'force'), d4rtCode: ''' return m * a; ''', @@ -50,11 +50,11 @@ void main() { final discriminantFormula = Formula( name: 'Quadratic Discriminant', input: [ - VariableSpec(name: 'a', magnitude: 'coefficient'), - VariableSpec(name: 'b', magnitude: 'coefficient'), - VariableSpec(name: 'c', magnitude: 'coefficient'), + VariableSpec(name: 'a', unit: 'coefficient'), + VariableSpec(name: 'b', unit: 'coefficient'), + VariableSpec(name: 'c', unit: 'coefficient'), ], - output : VariableSpec(name: 'discriminant', magnitude: 'scalar'), + output : VariableSpec(name: 'discriminant', unit: 'scalar'), d4rtCode: ''' return b * b - 4 * a * c; ''', @@ -89,9 +89,9 @@ void main() { final circleAreaFormula = Formula( name: 'Circle Area', input: [ - VariableSpec(name: 'r', magnitude: 'length'), + VariableSpec(name: 'r', unit: 'length'), ], - output: VariableSpec(name: 'A', magnitude: 'area'), + output: VariableSpec(name: 'A', unit: 'area'), d4rtCode: ''' var pi = 3.14159265359; @@ -132,12 +132,12 @@ void main() { final compoundInterestFormula = Formula( name: 'Compound Interest', input: [ - VariableSpec(name: 'P', magnitude: 'currency'), // Principal - VariableSpec(name: 'r', magnitude: 'rate'), // Annual interest rate - VariableSpec(name: 'n', magnitude: 'count'), // Times compounded per year - VariableSpec(name: 't', magnitude: 'time'), // Time in years + VariableSpec(name: 'P', unit: 'currency'), // Principal + VariableSpec(name: 'r', unit: 'rate'), // Annual interest rate + VariableSpec(name: 'n', unit: 'count'), // Times compounded per year + VariableSpec(name: 't', unit: 'time'), // Time in years ], - output: VariableSpec(name: 'A', magnitude: 'currency'), // Final amount + output: VariableSpec(name: 'A', unit: 'currency'), // Final amount d4rtCode: ''' // A = P * (1 + r/n)^(n*t) var rate_per_period = r / n; diff --git a/lib/ai/FormulaWidget.dart b/lib/ai/FormulaWidget.dart deleted file mode 100644 index 9dc8898..0000000 --- a/lib/ai/FormulaWidget.dart +++ /dev/null @@ -1,333 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../formula_models.dart'; - - -class FormulaWidget extends StatelessWidget { - final Formula formula; - final double fontSize; - final Color? textColor; - final Color? backgroundColor; - final EdgeInsets padding; - final bool showMagnitudes; - final bool showCode; - - const FormulaWidget({ - super.key, - required this.formula, - this.fontSize = 16.0, - this.textColor, - this.backgroundColor, - this.padding = const EdgeInsets.all(16.0), - this.showMagnitudes = true, - this.showCode = false, - }); - - @override - Widget build(BuildContext context) { - return Card( - color: backgroundColor, - child: Padding( - padding: padding, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - // Formula name - Text( - formula.name, - style: TextStyle( - fontSize: fontSize * 1.2, - fontWeight: FontWeight.bold, - color: textColor ?? Theme.of(context).textTheme.headlineSmall?.color, - ), - ), - const SizedBox(height: 12), - - // Formula equation - _buildFormulaEquation(context), - - if (showMagnitudes) ...[ - const SizedBox(height: 16), - _buildMagnitudesSection(context), - ], - - if (showCode) ...[ - const SizedBox(height: 16), - _buildCodeSection(context), - ], - ], - ), - ), - ); - } - - Widget _buildFormulaEquation(BuildContext context) { - return Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceContainerHighest.withOpacity(0.3), - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: Theme.of(context).dividerColor, - width: 1, - ), - ), - child: Row( - children: [ - // Output variable - _buildVariableChip(formula.output, isOutput: true, context: context), - - const SizedBox(width: 12), - - // Equals sign - Text( - '=', - style: TextStyle( - fontSize: fontSize * 1.5, - fontWeight: FontWeight.bold, - color: textColor ?? Theme.of(context).textTheme.bodyLarge?.color, - ), - ), - - const SizedBox(width: 12), - - // Function notation - Text( - '${formula.name}(', - style: TextStyle( - fontSize: fontSize, - fontStyle: FontStyle.italic, - color: textColor ?? Theme.of(context).textTheme.bodyLarge?.color, - ), - ), - - // Input variables - Expanded( - child: Wrap( - spacing: 8, - runSpacing: 4, - children: [ - for (int i = 0; i < formula.input.length; i++) ...[ - _buildVariableChip(formula.input[i], context: context), - if (i < formula.input.length - 1) - Text( - ',', - style: TextStyle( - fontSize: fontSize, - color: textColor ?? Theme.of(context).textTheme.bodyLarge?.color, - ), - ), - ], - ], - ), - ), - - Text( - ')', - style: TextStyle( - fontSize: fontSize, - fontStyle: FontStyle.italic, - color: textColor ?? Theme.of(context).textTheme.bodyLarge?.color, - ), - ), - ], - ), - ); - } - - Widget _buildVariableChip(VariableSpec variable, {bool isOutput = false, required BuildContext context}) { - final bool hasMagnitude = variable.magnitude != VariableSpec.MAGNITUDELESS; - - return Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: isOutput - ? Theme.of(context).colorScheme.primary.withOpacity(0.1) - : Theme.of(context).colorScheme.secondary.withOpacity(0.1), - borderRadius: BorderRadius.circular(6), - border: Border.all( - color: isOutput - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.secondary, - width: 1, - ), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - variable.name, - style: TextStyle( - fontSize: fontSize * 0.9, - fontWeight: FontWeight.w600, - color: isOutput - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.secondary, - ), - ), - if (hasMagnitude && showMagnitudes) ...[ - const SizedBox(width: 4), - Text( - '[${variable.magnitude}]', - style: TextStyle( - fontSize: fontSize * 0.8, - fontStyle: FontStyle.italic, - color: (isOutput - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.secondary).withOpacity(0.7), - ), - ), - ], - ], - ), - ); - } - - Widget _buildMagnitudesSection(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Variables:', - style: TextStyle( - fontSize: fontSize * 0.9, - fontWeight: FontWeight.w600, - color: textColor ?? Theme.of(context).textTheme.titleSmall?.color, - ), - ), - const SizedBox(height: 8), - Wrap( - spacing: 12, - runSpacing: 6, - children: [ - ...formula.input.map((variable) => _buildVariableInfo(variable, context)), - _buildVariableInfo(formula.output, context, isOutput: true), - ], - ), - ], - ); - } - - Widget _buildVariableInfo(VariableSpec variable, BuildContext context, {bool isOutput = false}) { - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - isOutput ? Icons.arrow_forward : Icons.input, - size: fontSize * 0.8, - color: isOutput - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.secondary, - ), - const SizedBox(width: 4), - Text( - '${variable.name}: ', - style: TextStyle( - fontSize: fontSize * 0.85, - fontWeight: FontWeight.w500, - color: textColor ?? Theme.of(context).textTheme.bodyMedium?.color, - ), - ), - Text( - variable.magnitude == VariableSpec.MAGNITUDELESS ? 'dimensionless' : variable.magnitude, - style: TextStyle( - fontSize: fontSize * 0.85, - fontStyle: FontStyle.italic, - color: (textColor ?? Theme.of(context).textTheme.bodyMedium?.color)?.withOpacity(0.8), - ), - ), - ], - ); - } - - Widget _buildCodeSection(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Implementation:', - style: TextStyle( - fontSize: fontSize * 0.9, - fontWeight: FontWeight.w600, - color: textColor ?? Theme.of(context).textTheme.titleSmall?.color, - ), - ), - const SizedBox(height: 8), - Container( - width: double.infinity, - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceContainerHighest.withOpacity(0.5), - borderRadius: BorderRadius.circular(6), - ), - child: Text( - formula.d4rtCode, - style: TextStyle( - fontSize: fontSize * 0.8, - fontFamily: 'monospace', - color: textColor ?? Theme.of(context).textTheme.bodySmall?.color, - ), - ), - ), - ], - ); - } -} - -// Example usage and demo -class FormulaDisplayDemo extends StatelessWidget { - @override - Widget build(BuildContext context) { - // Create sample formulas - final sampleFormulas = [ - Formula( - name: 'calculateArea', - input: [ - VariableSpec(name: 'length', magnitude: 'meters'), - VariableSpec(name: 'width', magnitude: 'meters'), - ], - output: VariableSpec(name: 'area', magnitude: 'square_meters'), - d4rtCode: 'return length * width;', - ), - Formula( - name: 'pythagoras', - input: [ - VariableSpec(name: 'a', magnitude: 'meters'), - VariableSpec(name: 'b', magnitude: 'meters'), - ], - output: VariableSpec(name: 'c', magnitude: 'meters'), - d4rtCode: 'return sqrt(a * a + b * b);', - ), - Formula( - name: 'normalize', - input: [ - VariableSpec(name: 'value', magnitude: VariableSpec.MAGNITUDELESS), - VariableSpec(name: 'max', magnitude: VariableSpec.MAGNITUDELESS), - ], - output: VariableSpec(name: 'normalized', magnitude: VariableSpec.MAGNITUDELESS), - d4rtCode: 'return value / max;', - ), - ]; - - return Scaffold( - appBar: AppBar( - title: const Text('Formula Display Demo'), - ), - body: SingleChildScrollView( - padding: const EdgeInsets.all(16), - child: Column( - children: [ - for (final formula in sampleFormulas) ...[ - FormulaWidget( - formula: formula, - showCode: true, - ), - const SizedBox(height: 16), - ], - ], - ), - ), - ); - } -} \ No newline at end of file diff --git a/lib/ai/unit_list.dart b/lib/ai/unit_list.dart index 64e8e8b..ca39ee9 100644 --- a/lib/ai/unit_list.dart +++ b/lib/ai/unit_list.dart @@ -51,10 +51,10 @@ class _UnitListState extends State { final sampleFormula = Formula( name: "Kinetic Energy", input: [ - VariableSpec(name: 'mass', magnitude: 'kilogram'), - VariableSpec(name: 'velocity', magnitude: 'meters_per_second'), + VariableSpec(name: 'mass', unit: 'kilogram'), + VariableSpec(name: 'velocity', unit: 'meters_per_second'), ], - output: VariableSpec(name: 'energy', magnitude: 'joule'), + output: VariableSpec(name: 'energy', unit: 'joule'), d4rtCode: "energy = 0.5 * mass * velocity * velocity;", ); diff --git a/lib/formula_evaluator.dart b/lib/formula_evaluator.dart index a0e04e4..eac4cc6 100644 --- a/lib/formula_evaluator.dart +++ b/lib/formula_evaluator.dart @@ -87,7 +87,7 @@ class FormulaEvaluator { /// Gets the magnitude of the single output variable from the formula String getOutputVariableMagnitude(Formula formula) { // Formula construction already ensures exactly one output variable - return formula.output.magnitude; + return formula.output.unit; } /// Gets the ordered list of input variable names (alphabetically sorted) diff --git a/lib/formula_models.dart b/lib/formula_models.dart index b8a39b5..7e33e8c 100644 --- a/lib/formula_models.dart +++ b/lib/formula_models.dart @@ -101,24 +101,24 @@ class UnitSpec { class VariableSpec { final String name; - final String magnitude; + final String unit; static final MAGNITUDELESS = "magnitudeless"; - VariableSpec({required this.name, required this.magnitude}); + VariableSpec({required this.name, required this.unit}); @override - String toString() => 'var($name: $magnitude)'; + String toString() => 'var($name: $unit)'; @override bool operator ==(Object other) => identical(this, other) || other is VariableSpec && runtimeType == other.runtimeType && - magnitude == other.magnitude && + unit == other.unit && name == other.name; @override - int get hashCode => Object.hash(magnitude, name); + int get hashCode => Object.hash(unit, name); } class Formula { @@ -191,7 +191,7 @@ class Formula { VariableSpec parseVar(Map varSpec) { String name = SetUtils.stringValue(varSpec, "name"); String magnitude = SetUtils.stringValue(varSpec, "magnitude"); - return VariableSpec(name: name, magnitude: magnitude); + return VariableSpec(name: name, unit: magnitude); } String name = SetUtils.stringValue(theSet, "name"); diff --git a/lib/main.dart b/lib/main.dart index 594c4b4..f4d0354 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,3 @@ -import 'package:d4rt_formulas/ai/FormulaWidget.dart'; import 'package:d4rt_formulas/formula_models.dart'; import 'package:flutter/material.dart'; diff --git a/test/formula_evaluator_test.dart b/test/formula_evaluator_test.dart index 9453f95..38ab493 100644 --- a/test/formula_evaluator_test.dart +++ b/test/formula_evaluator_test.dart @@ -15,10 +15,10 @@ void main() { final formula = Formula( name: "Newton's second law", input: [ - VariableSpec(name: 'm', magnitude: 'mass'), - VariableSpec(name: 'a', magnitude: 'acceleration'), + VariableSpec(name: 'm', unit: 'mass'), + VariableSpec(name: 'a', unit: 'acceleration'), ], - output: VariableSpec(name: 'F', magnitude: 'force'), + output: VariableSpec(name: 'F', unit: 'force'), d4rtCode: ''' F = a * m; ''', @@ -36,10 +36,10 @@ void main() { final formula = Formula( name: 'Simple addition', input: [ - VariableSpec(name: 'x', magnitude: 'scalar'), - VariableSpec(name: 'y', magnitude: 'scalar'), + VariableSpec(name: 'x', unit: 'scalar'), + VariableSpec(name: 'y', unit: 'scalar'), ], - output: VariableSpec(name: 'result', magnitude: 'scalar'), + output: VariableSpec(name: 'result', unit: 'scalar'), d4rtCode: ''' result = x + y; ''', @@ -53,8 +53,8 @@ void main() { test('handles single input variable', () { final formula = Formula( name: 'Square function', - input: [VariableSpec(name: 'n', magnitude: 'scalar')], - output: VariableSpec(name: 'result', magnitude: 'scalar'), + input: [VariableSpec(name: 'n', unit: 'scalar')], + output: VariableSpec(name: 'result', unit: 'scalar'), d4rtCode: ''' result = n * n; ''', @@ -68,11 +68,11 @@ void main() { final formula = Formula( name: 'Quadratic formula discriminant', input: [ - VariableSpec(name: 'a', magnitude: 'scalar'), - VariableSpec(name: 'b', magnitude: 'scalar'), - VariableSpec(name: 'c', magnitude: 'scalar'), + VariableSpec(name: 'a', unit: 'scalar'), + VariableSpec(name: 'b', unit: 'scalar'), + VariableSpec(name: 'c', unit: 'scalar'), ], - output: VariableSpec(name: 'discriminant', magnitude: 'scalar'), + output: VariableSpec(name: 'discriminant', unit: 'scalar'), d4rtCode: ''' discriminant = b * b - 4 * a * c; ''', @@ -89,11 +89,11 @@ void main() { final formula = Formula( name: 'Test order', input: [ - VariableSpec(name: 'z', magnitude: 'scalar'), - VariableSpec(name: 'a', magnitude: 'scalar'), - VariableSpec(name: 'b', magnitude: 'scalar'), + VariableSpec(name: 'z', unit: 'scalar'), + VariableSpec(name: 'a', unit: 'scalar'), + VariableSpec(name: 'b', unit: 'scalar'), ], - output: VariableSpec(name: 'result', magnitude: 'scalar'), + output: VariableSpec(name: 'result', unit: 'scalar'), d4rtCode: 'result = a + b + z;', ); @@ -105,11 +105,11 @@ void main() { final formula = Formula( name: 'Test argument order', input: [ - VariableSpec(name: 'z', magnitude: 'scalar'), - VariableSpec(name: 'a', magnitude: 'scalar'), - VariableSpec(name: 'y', magnitude: 'scalar'), + VariableSpec(name: 'z', unit: 'scalar'), + VariableSpec(name: 'a', unit: 'scalar'), + VariableSpec(name: 'y', unit: 'scalar'), ], - output: VariableSpec(name: 'result', magnitude: 'scalar'), + output: VariableSpec(name: 'result', unit: 'scalar'), d4rtCode: ''' // Variables: a=1, y=2, z=3 result = a * 100 + y * 10 + z; @@ -128,10 +128,10 @@ void main() { final formula = Formula( name: 'Test formula', input: [ - VariableSpec(name: 'x', magnitude: 'scalar'), - VariableSpec(name: 'y', magnitude: 'scalar'), + VariableSpec(name: 'x', unit: 'scalar'), + VariableSpec(name: 'y', unit: 'scalar'), ], - output: VariableSpec(name: 'result', magnitude: 'scalar'), + output: VariableSpec(name: 'result', unit: 'scalar'), d4rtCode: 'result = x + y;', ); @@ -144,8 +144,8 @@ void main() { test('throws exception for invalid d4rt code', () { final formula = Formula( name: 'Invalid code formula', - input: [VariableSpec(name: 'x', magnitude: 'scalar')], - output: VariableSpec(name: 'result', magnitude: 'scalar'), + input: [VariableSpec(name: 'x', unit: 'scalar')], + output: VariableSpec(name: 'result', unit: 'scalar'), d4rtCode: 'invalid dart code here!', ); @@ -160,8 +160,8 @@ void main() { test('getOutputVariableName returns the single output variable name', () { final formula = Formula( name: 'Test', - input: [VariableSpec(name: 'x', magnitude: 'scalar')], - output: VariableSpec(name: 'force', magnitude: 'Newton'), + input: [VariableSpec(name: 'x', unit: 'scalar')], + output: VariableSpec(name: 'force', unit: 'Newton'), d4rtCode: 'force = x;', ); @@ -173,8 +173,8 @@ void main() { () { final formula = Formula( name: 'Test', - input: [VariableSpec(name: 'x', magnitude: 'scalar')], - output: VariableSpec(name: 'force', magnitude: 'Newton'), + input: [VariableSpec(name: 'x', unit: 'scalar')], + output: VariableSpec(name: 'force', unit: 'Newton'), d4rtCode: 'force = x;', ); @@ -185,8 +185,8 @@ void main() { test('utility methods work correctly with valid formulas', () { final validFormula = Formula( name: 'Valid Formula', - input: [VariableSpec(name: 'x', magnitude: 'scalar')], - output: VariableSpec(name: 'result', magnitude: 'Newton'), + input: [VariableSpec(name: 'x', unit: 'scalar')], + output: VariableSpec(name: 'result', unit: 'Newton'), d4rtCode: 'result = x;', ); @@ -200,8 +200,8 @@ void main() { test('handles integer values', () { final formula = Formula( name: 'Integer test', - input: [VariableSpec(name: 'n', magnitude: 'count')], - output: VariableSpec(name: 'result', magnitude: 'count'), + input: [VariableSpec(name: 'n', unit: 'count')], + output: VariableSpec(name: 'result', unit: 'count'), d4rtCode: 'result = n + 1;', ); @@ -212,8 +212,8 @@ void main() { test('handles double values', () { final formula = Formula( name: 'Double test', - input: [VariableSpec(name: 'x', magnitude: 'length')], - output: VariableSpec(name: 'result', magnitude: 'area'), + input: [VariableSpec(name: 'x', unit: 'length')], + output: VariableSpec(name: 'result', unit: 'area'), d4rtCode: 'result = x * x;', );