La fonction `uniroot` prend 2 paramètres d'amorçage "min" et "max" qui
nous définissions jusqu'alors comme des minimums et maximum absolus
-10^8 et +10^8. Vu que nous sommes obligés de calculer au moins une
première valeur à l'extérieur de `uniroot` notamment pour calculer les
variables manquantes, ce commit permet de ré-utiliser ce calcul dans
l'amorçage d' `uniroot`.
Les gains de performances sont détaillés dans la PR associée.
Par ailleurs supprime l'option "valeurs négatives possibles" rendue
obsolète.
Il y a des légers décalages d'1€ sur une dizaine de snapshots qui liés à
des arrondis à l'euro. On calcule en effet les inversions à 10 centimes
près et on peut donc tomber sur une valeur de xx,54€ là où la vraie
valeur est xx,48€ ce qui donne 1€ de différence avec l'arrondi alors que
la différence initialement calculée est inférieure à 10 centimes.
Par curiosité j'ai rejoué les tests de non-régressions en changeant les
paramètres d'`uniroot` pour avoir une précision au centime près (en
augmentant le nombre max d'itération à 50) et il se trouve que sur la
dizaine de tests différents entre ce commit et la version d'avant une
moitié des arrondis à l'euro étaient faux avant et corrects maintenant
et inversement pour l'autre moitié.
Plein de nouveautés et notamment la possibilité de "programmer" les
types chaînes littérales qui nous sera utile par exemple pour vérifier
statiquement la validité d'une *expression* publicode dans
`engine.evaluate`.
https://devblogs.microsoft.com/typescript/announcing-typescript-4-1/
⬆ MAJ ESLint-typescript pour la compatibilité
En analysant les traces d'execution, il apparaît qu'un temps conséquent
est passé dans la fonction `evaluateApplicability`. L'ajout d'un cache
simple semble améliorer significativement les performances (environ -30%
dans mes mesures non scientifiques).
- évite l'indirection vers "parseReferenceTransforms" pour les
références simples (il faut encore simplifier ce code)
- déplacement de fonctions de parsage vers les "stateless"
- typage de registerEvaluationFunction
- simplifie fragments.join()
Modifie l'API de la fonction `evaluate` pour transmettre le contexte
avec `this`, ce qui simplifie l'interface de ces fonctions.
L'objet `this` (qui contient `this.parsedRules`, `this.situation`,
`this.evaluate`, etc.) est un interpréteur Publicodes, mais nous n'avons
pas besoin de créer une nouvelle abstraction car cet objet présente
exactement la même interface que l'objet public exposé dans
`publicodes/index.ts` et c'est donc l'interface publique qui est
utilisée dans les appels internes.
Ce commit parachève la sortie de l'ensemble des functions "evaluate" de
l'AST et ajoute un "nodeKind" sur chaque nœud afin de les associer à la
bonne function d'évaluation.
L'API pour les mécanismes pourra être améliorée afin de ne pas appeler
`registerEvaluationFunction` sur chaque mécanisme mais en standardisant
l'interface exportée par les mécanismes, par exemple
export { name, parse, evaluate, render }
Par ailleurs il devrait être facile de sortir les fonctions `jsx` en se
basant sur les mêmes "nodeKind".
Enfin, il faudra nettoyer l'AST pour supprimer les attributs inutilisés
et ajouter du typage fort.
Si une inversion n'est pas trouvée à 0,1 près, fallback à 1 près.
Utile pour les cotisations des avocats, et permet de réaliser certaines
inversions qui étaient impossibles jusqu'à lors (cf. snapshots).
- On veut pouvoir afficher un lien vers la règle définissant la [ref] lorsqu'on est dans une formule avec une référence virtuelle
- Si on fait référence dans une règle à une notification sans formule (juste applicable) la règle crash
En attendant une réecriture de l'inlining qui permette d'ajouter le contexte à la référence appelée (référence ou définition),
je préfère désactiver cette logique
Nous utilisions jusqu'à présent le code suivant pour évaluer la situation:
> mapObjIndexed(value => evaluateExpression(value), situation)
c'est à dire une évaluation ligne par ligne. Or si certaines valeurs de
la situation contiennent des références, il faut les évaluer dans le bon
ordre.
Avec cette modification, seul le parsage est fait lorsqu'on appelle
`setSituation` et l'évaluation est faite ultérieurement lorsque c'est
nécessaire avec la même logique que pour les règles.
L'implémentation a pour effet de bord de ne plus supprimer l'utilisation
de true / false dans la situation qui doivent être remplacés par "oui"
et "non".
Grâce aux récentes évolutions de Publicode, ce retour utilisateur
fréquent trouve une solution particulièrement simple et élégante en
remplaçant la valeur littérale du SMIC par une référence vers le SMIC
contractuel. Cela procure les avantages suivants :
- Le montant du SMIC est défini une seule fois dans la base de règles,
et on y fait référence partout où on l'utilise
- Vu que c'est la référence qui est stockée dans la "situation" on peut
répondre à la question "temps partiel" après avoir cliqué sur "SMIC"
dans la case "salaire brut" et le montant correspondant va
automatiquement se recalculer.
A nécessité quelques menues modifications du code qui gère les
références dans la situation pour corriger des bugs.
Fixes#649
Build a dependencies graph and detect cycles:
* Types and guards for nodes of the ParsedRules AST
* Simple visitor framework for the nodes and their `formule` sub-nodes
* Build a directed graph for dependencies using @dagrejs/graphlib
Pour éviter les bugs comme celui corrigé dans caff99f qui était encore
présent dans la règle "contrat salarié . rémunération . brut de base .
équivalent temps plein"
La vérification de la cohérence d'unité n'est pas suffisamment stricte
pour détecter tous les problèmes, issue à venir.
Le mécanisme "allègement" proposaient ces deux paramètres ajoutant
beaucoup de complexité pour une seule utilisation dans la base de règle
qui peut être remplacée par une formule littérale.
Closes#1119
- Change l'organisation des cotisations indépendant (toutes les cotisations sont au même niveau)
- Change l'assiette de calcul de la CSG, qui est basée sur toutes les cotisations sociales obligatoire (à vérifier)
- Change le mode de calcul de l'assiette de remboursement CPAM, qui est basée sur les revenus conventionnés (ajoute une question sur le pourcentage conventionné / non conventionné)
- Change l'organisation des PL en PL . PAMC (régime URSSAF) et PL . CAR*** (caisse de retraite) pour mieux prendre en compte le médecin non conventionné
- Désactive le subSimulateur en attendant d'améliorer sa logique
Ce commit supprime le concept de "contrôle" au sein du moteur, en les
remplaçant par des règles publicodes classiques. Cela permet notamment
d'uniformiser les règles d'applicabilité (désactivation via espace de
nom ou "rend non applicable" par exemple) ainsi que d'accéder à la
valeur d'un contrôle donné avec le nom de la règle correspondante.
Par ailleurs renomme le concept de "contrôle" en "notifcation" dans la
partie mon-entreprise/.