Phase 2 : hasard + opérations mathématiques
Build and deploy / test-python (push) Successful in 1m26s
Build and deploy / test-js (push) Successful in 6s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped

screens/labels/data_operations.py : 6 nouvelles opérations pour
"Modifier une donnée"/"Modifier une variable" — multiplier, diviser,
modulo (garde-fou division par zéro : valeur inchangée plutôt qu'une
ZeroDivisionError qui interromprait le graphe), minimum/maximum (borne
la valeur ACTUELLE — utile pour une variable globale, qui n'a pas de
min_value/max_value comme un champ d'objet), et alea (tire un nombre
aléatoire entre deux bornes).

screens/data_actions/compute_operation.py (déjà factorisé en Phase 0,
donc une seule implémentation pour apply_data_action.py/
apply_variable_action.py) : implémente les 6. "alea" est la seule à
deux opérandes — réutilise data_value au format "min,max" plutôt qu'une
nouvelle colonne de nœud (bornes remises dans l'ordre si inversées).
random.uniform pour un résultat décimal, random.randint pour un entier.

static/js/screen_edit/flow-editor.js + templates/screen_edit.html :
petit indice visuel — le champ "Valeur / montant" du formulaire de nœud
affiche "min,max (ex. 1,6)" quand "alea" est choisi, pour ne pas laisser
deviner ce format à deux nombres, différent de toutes les autres
opérations. Sinon aucun nouveau champ/changement de schéma nécessaire,
le <select> était déjà généré depuis DATA_OPERATIONS.

Vérifié : 250 tests passent (19 dans test_compute_operation.py, dont un
qui a dû être corrigé — il utilisait "multiplier" comme exemple
d'opération INCONNUE, devenu un mauvais exemple maintenant qu'elle
existe), 13 tests node:test toujours au vert, syntaxe JS validée.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
william
2026-08-30 16:47:59 +02:00
co-authored by Claude Sonnet 5
parent e9d12945a9
commit 7476ed229e
5 changed files with 135 additions and 6 deletions
+46
View File
@@ -1,3 +1,6 @@
import random
def compute_new_value(operation, current, raw_value, is_decimal):
"""Calcule la nouvelle valeur d'un champ d'objet ou d'une variable
globale pour une opération de DATA_OPERATIONS (voir
@@ -32,4 +35,47 @@ def compute_new_value(operation, current, raw_value, is_decimal):
amount = -amount
result = (current or 0) + amount
return result if is_decimal else int(result)
# Phase 2 — hasard + opérations mathématiques. "multiplier"/"diviser"/
# "modulo" reprennent le même patron qu'incrementer/decrementer (un
# seul opérande numérique dans raw_value) ; "minimum"/"maximum"
# bornent la valeur ACTUELLE (utile pour une variable globale, qui n'a
# pas de min_value/max_value comme un champ d'objet, voir
# _clamp_to_field_bounds dans apply_data_action.py) ; "alea" est la
# seule opération à deux opérandes ("min,max" dans raw_value plutôt
# qu'une nouvelle colonne de nœud — voir updateDataValuePlaceholder()
# dans static/js/screen_edit/flow-editor.js).
if operation == "multiplier":
try:
factor = float(raw_value) if raw_value not in (None, "") else 1
except (TypeError, ValueError):
factor = 1
result = (current or 0) * factor
return result if is_decimal else int(result)
if operation in ("diviser", "modulo"):
try:
divisor = float(raw_value) if raw_value not in (None, "") else 0
except (TypeError, ValueError):
divisor = 0
if divisor == 0:
# Garde-fou division par zéro : valeur inchangée plutôt qu'une
# ZeroDivisionError qui interromprait tout le graphe de logique.
return current
result = (current or 0) / divisor if operation == "diviser" else (current or 0) % divisor
return result if is_decimal else int(result)
if operation in ("minimum", "maximum"):
try:
bound = float(raw_value)
except (TypeError, ValueError):
return current
result = max(current or 0, bound) if operation == "minimum" else min(current or 0, bound)
return result if is_decimal else int(result)
if operation == "alea":
parts = (raw_value or "").split(",")
try:
lo, hi = float(parts[0]), float(parts[1])
except (IndexError, TypeError, ValueError):
lo, hi = 0, 0
if lo > hi:
lo, hi = hi, lo
return random.uniform(lo, hi) if is_decimal else random.randint(int(lo), int(hi))
raise ValueError(f"opération inconnue : {operation!r}")
+8
View File
@@ -8,5 +8,13 @@ DATA_OPERATIONS = [
("basculer_bool", "Basculer Vrai / Faux"),
("incrementer", "Augmenter de..."),
("decrementer", "Diminuer de..."),
# Phase 2 (hasard + opérations mathématiques) — voir
# screens/data_actions/compute_operation.py pour le calcul de chacune.
("multiplier", "Multiplier par..."),
("diviser", "Diviser par..."),
("modulo", "Reste de la division par... (modulo)"),
("minimum", "Ne jamais descendre sous..."),
("maximum", "Ne jamais dépasser..."),
("alea", "Tirer un nombre aléatoire entre... (min,max)"),
]
DATA_OPERATION_LABELS = dict(DATA_OPERATIONS)