153 lines
4.1 KiB
TypeScript
153 lines
4.1 KiB
TypeScript
import { map, pick, pipe } from 'ramda'
|
|
import { evaluationFunction } from '.'
|
|
import { typeWarning } from './error'
|
|
import { bonus, mergeAllMissing, mergeMissing } from './evaluation'
|
|
import { convertNodeToUnit } from './nodeUnits'
|
|
|
|
export const evaluateApplicability: evaluationFunction = function(node: any) {
|
|
const cacheKey = `${node.dottedName} [applicability]`
|
|
if (node.dottedName && this.cache[cacheKey]) {
|
|
return this.cache[cacheKey]
|
|
}
|
|
const evaluatedAttributes = pipe(
|
|
pick(['non applicable si', 'applicable si', 'rendu non applicable']) as (
|
|
x: any
|
|
) => any,
|
|
map(value => this.evaluateNode(value))
|
|
)(node) as any,
|
|
{
|
|
'non applicable si': notApplicable,
|
|
'applicable si': applicable,
|
|
'rendu non applicable': disabled
|
|
} = evaluatedAttributes,
|
|
parentDependencies = node.parentDependencies.map(parent =>
|
|
this.evaluateNode(parent)
|
|
)
|
|
|
|
const anyDisabledParent = parentDependencies.find(
|
|
parent => parent?.nodeValue === false
|
|
)
|
|
|
|
const { nodeValue, missingVariables = {} } = anyDisabledParent
|
|
? anyDisabledParent
|
|
: notApplicable?.nodeValue === true
|
|
? {
|
|
nodeValue: false,
|
|
missingVariables: notApplicable.missingVariables
|
|
}
|
|
: disabled?.nodeValue === true
|
|
? { nodeValue: false }
|
|
: applicable?.nodeValue === false
|
|
? { nodeValue: false, missingVariables: applicable.missingVariables }
|
|
: {
|
|
nodeValue: [notApplicable, applicable, ...parentDependencies].some(
|
|
n => n?.nodeValue === null
|
|
)
|
|
? null
|
|
: !notApplicable?.nodeValue &&
|
|
(applicable?.nodeValue == undefined || !!applicable?.nodeValue),
|
|
missingVariables: mergeAllMissing(
|
|
[...parentDependencies, notApplicable, disabled, applicable].filter(
|
|
Boolean
|
|
)
|
|
)
|
|
}
|
|
|
|
const res = {
|
|
...node,
|
|
nodeValue,
|
|
isApplicable: nodeValue,
|
|
missingVariables,
|
|
parentDependencies,
|
|
...evaluatedAttributes
|
|
}
|
|
|
|
if (node.dottedName) {
|
|
this.cache[cacheKey] = res
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
export const evaluateFormula: evaluationFunction = function(node) {
|
|
const explanation = this.evaluateNode(node.explanation)
|
|
const { nodeValue, unit, missingVariables, temporalValue } = explanation
|
|
|
|
return {
|
|
...node,
|
|
nodeValue,
|
|
unit,
|
|
missingVariables,
|
|
explanation,
|
|
temporalValue
|
|
}
|
|
}
|
|
|
|
export const evaluateRule: evaluationFunction = function(node: any) {
|
|
this.cache._meta.contextRule.push(node.dottedName)
|
|
const applicabilityEvaluation = evaluateApplicability.call(this, node)
|
|
const {
|
|
missingVariables: condMissing,
|
|
nodeValue: isApplicable
|
|
} = applicabilityEvaluation
|
|
|
|
// evaluate the formula lazily, only if the applicability is known and true
|
|
let evaluatedFormula =
|
|
isApplicable && node.formule
|
|
? this.evaluateNode(node.formule)
|
|
: node.formule
|
|
|
|
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
|
|
)
|
|
|
|
const temporalValue = evaluatedFormula.temporalValue
|
|
this.cache._meta.contextRule.pop()
|
|
return {
|
|
...node,
|
|
...applicabilityEvaluation,
|
|
...(node.formule && { formule: evaluatedFormula }),
|
|
nodeValue: evaluatedFormula.nodeValue,
|
|
unit: node.unit ?? evaluatedFormula.unit,
|
|
temporalValue,
|
|
isApplicable,
|
|
missingVariables
|
|
}
|
|
}
|
|
|
|
export const evaluateDisabledBy: evaluationFunction = function(node) {
|
|
const isDisabledBy = node.explanation.isDisabledBy.map(disablerNode =>
|
|
this.evaluateNode(disablerNode)
|
|
)
|
|
const nodeValue = isDisabledBy.some(
|
|
x => x.nodeValue !== false && x.nodeValue !== null
|
|
)
|
|
const explanation = { ...node.explanation, isDisabledBy }
|
|
return {
|
|
...node,
|
|
explanation,
|
|
nodeValue,
|
|
missingVariables: mergeAllMissing(isDisabledBy)
|
|
}
|
|
}
|
|
|
|
export const evaluateCondition: evaluationFunction = function(node) {
|
|
const explanation = this.evaluateNode(node.explanation)
|
|
const nodeValue = explanation.nodeValue
|
|
const missingVariables = explanation.missingVariables
|
|
|
|
return { ...node, nodeValue, explanation, missingVariables }
|
|
}
|