From 28671888e1b6282b5705969b710def8f4cd8c036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Gonz=C3=A1lez?= Date: Wed, 28 Jan 2026 11:04:33 +0100 Subject: [PATCH] Docker basado en un sh en vez de en compose --- .gitignore | 3 ++- Makefile | 12 +++++------ aider.sh | 2 -- assets/formulas/formulas.d4rt | 24 +++++++++++++++++++++ docker-exec.sh | 40 +++++++++++++++++++++++++++++++++++ lib/ai/formula_screen.dart | 5 ++++- lib/corpus.dart | 2 +- lib/formula_evaluator.dart | 37 ++++++++++++++++++++++++++------ pubspec.lock | 2 +- pubspec.yaml | 2 +- 10 files changed, 109 insertions(+), 20 deletions(-) delete mode 100755 aider.sh create mode 100755 docker-exec.sh diff --git a/.gitignore b/.gitignore index 150bea1..bade31f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # https://dart.dev/guides/libraries/private-files # Created by `dart pub` +.flutter-plugins-dependencies .dart_tool/ .dart-tool/ .dartServer/ @@ -12,7 +13,7 @@ .zcompdump .zshrc .idea -/d4rt-formulas.iml /build/ /d4rt_formulas.iml .aider* +.build-container-cache diff --git a/Makefile b/Makefile index 613c3cb..858d879 100644 --- a/Makefile +++ b/Makefile @@ -1,22 +1,20 @@ -flutter-container-exec = podman-compose run --entrypoint "$(1)" flutter - all: clean-podman build-linux-debug-podman build-linux-debug-podman build-podman: - podman-compose build + ./docker-exec.sh build clean-podman: build-podman - $(call flutter-container-exec, flutter clean) + ./docker-exec.sh exec flutter clean pub-get-podman: build-podman - $(call flutter-container-exec, flutter pub get) + ./docker-exec.sh exec flutter pub get build-android-release-podman: pub-get-podman - $(call flutter-container-exec, flutter build apk --release) + ./docker-exec.sh exec flutter build apk --release build-linux-debug-podman: pub-get-podman - $(call flutter-container-exec, flutter build linux --debug) + ./docker-exec.sh exec flutter build linux --debug run-linux-debug: build-linux-debug-podman build/linux/x64/debug/bundle/d4rt_formulas diff --git a/aider.sh b/aider.sh deleted file mode 100755 index 6a39ffb..0000000 --- a/aider.sh +++ /dev/null @@ -1,2 +0,0 @@ -aider --git --watch-files --read CLAUDE.md --notifications --no-auto-commits - diff --git a/assets/formulas/formulas.d4rt b/assets/formulas/formulas.d4rt index a6dc9db..67ee938 100644 --- a/assets/formulas/formulas.d4rt +++ b/assets/formulas/formulas.d4rt @@ -149,4 +149,28 @@ Where: """, "tags": ["medical", "pediatrics", "assessment"] } + , + { + "name": "Compare price per mass", + "description": "Compares two products by their price per mass and returns which is cheaper.", + "input": [ + {"name": "price1", "unit": "scalar"}, + {"name": "mass1", "unit": "kilogram"}, + {"name": "price2", "unit": "scalar"}, + {"name": "mass2", "unit": "kilogram"} + ], + "output": {"name": "Result", "unit": "scalar"}, + "d4rtCode": """ + var p1 = price1 / mass1; + var p2 = price2 / mass2; + if (p1 < p2) { + Result = 'first product is cheaper'; + } else if (p2 < p1) { + Result = 'second product is cheaper'; + } else { + Result = 'both products have the same price per mass'; + } + """, + "tags": ["comparison", "shopping", "economics"] + } ] diff --git a/docker-exec.sh b/docker-exec.sh new file mode 100755 index 0000000..72cd927 --- /dev/null +++ b/docker-exec.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +set -e + +DOCKER=podman + + +build_image(){ + $DOCKER build -t d4rt-formulas-builder -f Dockerfile . +} + +exec_in_container(){ + + local XOPTIONS="--env DISPLAY=$DISPLAY --volume /tmp/.X11-unix:/tmp/.X11-unix --security-opt=label=disable" + local WOPTIONS="--env=XDG_RUNTIME_DIR=/run/user/$(id -u) --volume=/run/user/$(id -u)/wayland:/run/user/$(id -u)/wayland --group-add=video" + local SPIOPTIONS="--env AT_SPI_BUS=/run/user/$(id -u)/at-spi/bus_0 --volume=/run/user/$(id -u)/at-spi:/run/user/$(id -u)/at-spi --device=/dev/dri" + + $DOCKER run \ + --rm \ + $XOPTIONS \ + $SPIOPTIONS \ + -v ./.build-container-cache:/cache:z \ + -v .:/app:z \ + -e FLUTTER_FLAVOR=prod \ + d4rt-formulas-builder \ + "$@" +} + +if [ "$1" = "build" ]; then + build_image + exit $? +fi + +if [ "$1" = "exec" ]; then + exec_in_container ${@:2} + exit $? +fi + +echo "Usage: $0 {build|exec }" +exit 1 \ No newline at end of file diff --git a/lib/ai/formula_screen.dart b/lib/ai/formula_screen.dart index b7defca..996a63b 100644 --- a/lib/ai/formula_screen.dart +++ b/lib/ai/formula_screen.dart @@ -27,6 +27,9 @@ class D4rtEditingController extends TextEditingController { bool validate() { try { _lastValue = null; + if( text.trim().isEmpty ){ + return true; + } _lastValue = FormulaEvaluator.evaluateExpression(text); _lastError = null; return true; @@ -141,7 +144,7 @@ class _FormulaScreenState extends State { // Convert output to selected unit if needed String? unit = widget.formula.output.unit; - if (unit != null) { + if (unit != null && unit is Number) { final converted = widget.corpus.convert(result, unit, _selectedOutputUnit!); if (converted is num) { _result = converted.toStringAsFixed(2); diff --git a/lib/corpus.dart b/lib/corpus.dart index 7ad4f50..fd06dc6 100644 --- a/lib/corpus.dart +++ b/lib/corpus.dart @@ -35,7 +35,7 @@ class Corpus{ if( checkUnits ){ for( final inputVar in formula.input + [formula.output] ){ if( inputVar.unit != null && !_allUnits.containsKey(inputVar.unit) ){ - throw ArgumentError( "Unit not found: ${inputVar.unit}"); + throw ArgumentError( "Unit not found in formula ${formula.name}: ${inputVar.unit}"); } } } diff --git a/lib/formula_evaluator.dart b/lib/formula_evaluator.dart index acc978d..0532ee2 100644 --- a/lib/formula_evaluator.dart +++ b/lib/formula_evaluator.dart @@ -168,14 +168,39 @@ class FormulaEvaluator { """); } } + // Build a Map> named `variableValues` that exposes allowed values + // for each VariableSpec (inputs and output) to the interpreted code. Values are + // converted to strings and quoted in the produced d4rt source. + final variableValuesMap = >{}; + + // Include input VariableSpecs when they have allowed values + for (final vs in formula.input) { + final values = vs.values; + if (values != null && values.isNotEmpty) { + variableValuesMap[vs.name] = values.map((v) => v.toString()).toList(growable: false); + } + } + // Explicitly include the output VariableSpec if it has allowed values + final outValues = formula.output.values; + if (outValues != null && outValues.isNotEmpty) { + variableValuesMap[formula.output.name] = outValues.map((v) => v.toString()).toList(growable: false); + } + + // Write the variableValues map into the generated source without escaping names/values + buffer.writeln("final variableValues = {"); + variableValuesMap.forEach((name, list) { + final listLiteral = list.map((s) => '"' + s + '"').join(', '); + buffer.writeln(' "' + name + '": [' + listLiteral + '],'); + }); + buffer.writeln('};'); + buffer.writeln(""" late var ${formula.output.name}; ${formula.d4rtCode} return ${formula.output.name}; } - """ - ); - - return buffer.toString(); - } -} + """); + + return buffer.toString(); + } + } diff --git a/pubspec.lock b/pubspec.lock index 78823f5..9621524 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -702,5 +702,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.10.7 <4.0.0" + dart: ">=3.10.4 <4.0.0" flutter: ">=3.38.0" diff --git a/pubspec.yaml b/pubspec.yaml index d70efdb..25fab72 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -19,7 +19,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ^3.10.7 + sdk: ^3.10.4 # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions