⚙️ Évalue la situation dans l'ordre topologique

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".
pull/1158/head
Maxime Quandalle 2020-10-05 00:39:11 +01:00
parent 4789dfce04
commit 973f12ab46
7 changed files with 24 additions and 23 deletions

View File

@ -31,8 +31,6 @@ export default function Notifications() {
engine.evaluate(notification.dottedName).isApplicable
)
)
console.log(notifications.map(n => engine.evaluate(n.dottedName)))
const inversionFail = useInversionFail()
const hiddenNotifications = useSelector(
(state: RootState) => state.simulation?.hiddenNotifications

View File

@ -8,5 +8,5 @@ objectifs:
situation:
dirigeant: "'indépendant'"
aide déclaration revenu indépendant 2019: true
aide déclaration revenu indépendant 2019: oui
unité par défaut: '€/an'

View File

@ -33,7 +33,7 @@ activité:
acre:
- dirigeant . indépendant . revenu net de cotisations: 50000 €/an
entreprise . ACRE: true
entreprise . ACRE: oui
impôt sur le revenu:
- dirigeant . indépendant . revenu net de cotisations: 20000 €/an

View File

@ -17,7 +17,7 @@ export default function Rule({ dottedName, engine, language }) {
}
const rule = engine.evaluate(dottedName)
const isSetInStituation = engine.situation[dottedName] !== undefined
const isSetInStituation = engine.parsedSituation[dottedName] !== undefined
const { description, question } = rule
return (

View File

@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/ban-types */
import { mapObjIndexed } from 'ramda'
import { map } from 'ramda'
import { evaluationError, warning } from './error'
import { evaluateNode } from './evaluation'
import { convertNodeToUnit, simplifyNodeUnit } from './nodeUnits'
@ -23,9 +23,7 @@ type Cache = {
}
}
type EvaluatedSituation<Names extends string> = Partial<
Record<Names, EvaluatedNode<Names>>
>
type ParsedSituation<Names extends string> = Partial<ParsedRules<Names>>
export type EvaluationOptions = Partial<{
unit: string
@ -41,7 +39,7 @@ export { utils }
export default class Engine<Names extends string> {
parsedRules: ParsedRules<Names>
situation: EvaluatedSituation<Names> = {}
parsedSituation: ParsedSituation<Names> = {}
private cache: Cache
private warnings: Array<string> = []
@ -71,7 +69,7 @@ export default class Engine<Names extends string> {
const result = simplifyNodeUnit(
evaluateNode(
this.cache,
this.situation,
this.parsedSituation,
this.parsedRules,
parse(
this.parsedRules,
@ -95,14 +93,17 @@ export default class Engine<Names extends string> {
situation: Partial<Record<Names, string | number | object>> = {}
) {
this.resetCache()
this.situation = mapObjIndexed(
(value, name) =>
typeof value === 'string'
? this.evaluateExpression(value, `[situation] ${name}`)
: value,
this.parsedSituation = map(
value =>
typeof value === 'object'
? value
: parse(
this.parsedRules,
{ dottedName: '' },
this.parsedRules
)(value),
situation
) as EvaluatedSituation<Names>
this.resetCache()
)
return this
}

View File

@ -192,10 +192,12 @@ Par défaut, seul le premier s'applique. Si vous voulez un autre comportement, v
applicabilityEvaluation
)
}
const situationValue = situation[dottedName]?.evaluate
? evaluateNode(cache, situation, rules, situation[dottedName])
: situation[dottedName]
if (situationValue != null) {
if (situation[dottedName]) {
// Conditional evaluation is required because some mecanisms like
// "synchronisation" store raw JS objects in the situation.
const situationValue = situation[dottedName]?.evaluate
? evaluateNode(cache, situation, rules, situation[dottedName])
: situation[dottedName]
const unit =
!situationValue.unit || serializeUnit(situationValue.unit) === ''
? rule.unit

View File

@ -76,7 +76,7 @@ variable temporelle numérique . test addition:
exemples:
- situation:
date: 01/01/2019
valeur attendue: false
valeur attendue: non
- situation:
date: 15/12/2019
valeur attendue: 20