130 lines
3.4 KiB
TypeScript
130 lines
3.4 KiB
TypeScript
import { map, mergeAll, pick, pipe } from 'ramda'
|
|
import { typeWarning } from './error'
|
|
import { bonus, evaluateNode, mergeMissing } from './evaluation'
|
|
import { convertNodeToUnit } from './nodeUnits'
|
|
import { ParsedRule } from './types'
|
|
|
|
export const evaluateApplicability = (
|
|
cache,
|
|
situation,
|
|
parsedRules,
|
|
node: ParsedRule
|
|
) => {
|
|
const evaluatedAttributes = pipe(
|
|
pick(['non applicable si', 'applicable si', 'rendu non applicable']) as (
|
|
x: any
|
|
) => any,
|
|
map(value => evaluateNode(cache, situation, parsedRules, value))
|
|
)(node) as any,
|
|
{
|
|
'non applicable si': notApplicable,
|
|
'applicable si': applicable,
|
|
'rendu non applicable': disabled
|
|
} = evaluatedAttributes,
|
|
parentDependencies = node.parentDependencies.map(parent =>
|
|
evaluateNode(cache, situation, parsedRules, parent)
|
|
)
|
|
|
|
const anyDisabledParent = parentDependencies.find(
|
|
parent => parent?.nodeValue === false
|
|
)
|
|
|
|
const { nodeValue, missingVariables = {} } = anyDisabledParent
|
|
? anyDisabledParent
|
|
: notApplicable?.nodeValue === true
|
|
? {
|
|
nodeValue: false,
|
|
missingVariables: notApplicable.missingVariables
|
|
}
|
|
: applicable?.nodeValue === false
|
|
? { nodeValue: false, missingVariables: applicable.missingVariables }
|
|
: disabled?.nodeValue === true
|
|
? { nodeValue: false, missingVariables: disabled.missingVariables }
|
|
: {
|
|
nodeValue: [notApplicable, applicable, ...parentDependencies].some(
|
|
n => n?.nodeValue === null
|
|
)
|
|
? null
|
|
: !notApplicable?.nodeValue &&
|
|
(applicable?.nodeValue == undefined || !!applicable?.nodeValue),
|
|
missingVariables: mergeAll([
|
|
...parentDependencies.map(parent => parent.missingVariables),
|
|
notApplicable?.missingVariables || {},
|
|
disabled?.missingVariables || {},
|
|
applicable?.missingVariables || {}
|
|
])
|
|
}
|
|
|
|
return {
|
|
...node,
|
|
nodeValue,
|
|
isApplicable: nodeValue,
|
|
missingVariables,
|
|
parentDependencies,
|
|
...evaluatedAttributes
|
|
}
|
|
}
|
|
|
|
export default (cache, situation, parsedRules, node) => {
|
|
cache._meta.contextRule.push(node.dottedName)
|
|
const applicabilityEvaluation = evaluateApplicability(
|
|
cache,
|
|
situation,
|
|
parsedRules,
|
|
node
|
|
)
|
|
const {
|
|
missingVariables: condMissing,
|
|
nodeValue: isApplicable
|
|
} = applicabilityEvaluation
|
|
|
|
const evaluateFormula = () =>
|
|
node.formule
|
|
? evaluateNode(cache, situation, parsedRules, node.formule)
|
|
: {}
|
|
// evaluate the formula lazily, only if the applicability is known and true
|
|
let evaluatedFormula = isApplicable
|
|
? evaluateFormula()
|
|
: isApplicable === false
|
|
? {
|
|
...node.formule,
|
|
missingVariables: {},
|
|
nodeValue: 0
|
|
}
|
|
: {
|
|
...node.formule,
|
|
missingVariables: {},
|
|
nodeValue: null
|
|
}
|
|
|
|
if (node.unit) {
|
|
try {
|
|
evaluatedFormula = convertNodeToUnit(node.unit, evaluatedFormula)
|
|
} catch (e) {
|
|
typeWarning(
|
|
node.dottedName,
|
|
"L'unité de la règle est incompatible avec celle de sa formule",
|
|
e
|
|
)
|
|
}
|
|
}
|
|
const missingVariables = mergeMissing(
|
|
bonus(condMissing, !!Object.keys(condMissing).length),
|
|
evaluatedFormula.missingVariables
|
|
)
|
|
// console.log(node.dottedName, evaluatedFormula.unit)
|
|
|
|
const temporalValue = evaluatedFormula.temporalValue
|
|
cache._meta.contextRule.pop()
|
|
return {
|
|
...node,
|
|
...applicabilityEvaluation,
|
|
...(node.formule && { formule: evaluatedFormula }),
|
|
nodeValue: evaluatedFormula.nodeValue,
|
|
unit: node.unit ?? evaluatedFormula.unit,
|
|
temporalValue,
|
|
isApplicable,
|
|
missingVariables
|
|
}
|
|
}
|