2018-01-08 15:07:26 +00:00
import {
2018-04-12 13:43:02 +00:00
add ,
2018-01-08 15:07:26 +00:00
any ,
equals ,
evolve ,
2019-01-14 14:14:57 +00:00
filter ,
2019-04-11 13:23:46 +00:00
fromPairs ,
is ,
keys ,
map ,
mergeWith ,
reduce ,
values
2018-01-08 15:07:26 +00:00
} from 'ramda'
2019-11-28 11:03:23 +00:00
import React from 'react'
import { typeWarning } from './error'
import { convertNodeToUnit , simplifyNodeUnit } from './nodeUnits'
2017-07-13 10:25:46 +00:00
2017-07-31 16:16:25 +00:00
export let makeJsx = node =>
2018-01-03 15:54:19 +00:00
typeof node . jsx == 'function'
2019-07-20 16:30:42 +00:00
? node . jsx ( node . nodeValue , node . explanation , node . lazyEval , node . unit )
2017-07-31 16:16:25 +00:00
: node . jsx
2017-07-13 19:55:59 +00:00
2018-04-12 13:43:02 +00:00
export let collectNodeMissing = node => node . missingVariables || { }
2018-06-29 13:46:42 +00:00
export let bonus = ( missings , hasCondition = true ) =>
hasCondition ? map ( x => x + 0.0001 , missings || { } ) : missings
export let mergeAllMissing = missings =>
reduce ( mergeWith ( add ) , { } , map ( collectNodeMissing , missings ) )
export let mergeMissing = ( left , right ) =>
mergeWith ( add , left || { } , right || { } )
2017-07-13 10:25:46 +00:00
2019-11-28 11:03:23 +00:00
export let evaluateNode = ( cache , situationGate , parsedRules , node ) => {
let evaluatedNode = node . evaluate
? node . evaluate ( cache , situationGate , parsedRules , node )
: node
if ( typeof evaluatedNode . nodeValue !== 'number' ) {
return evaluatedNode
}
evaluatedNode = node . unité
? convertNodeToUnit ( node . unit , evaluatedNode )
: simplifyNodeUnit ( evaluatedNode )
return evaluatedNode
}
const sameUnitValues = ( explanation , contextRule , mecanismName ) => {
const unit = explanation . map ( n => n . unit ) . find ( Boolean )
const values = explanation . map ( node => {
try {
return convertNodeToUnit ( unit , node ) . nodeValue
} catch ( e ) {
typeWarning (
contextRule ,
` ' ${ node . name } ' a une unité incompatible avec celle du mécanisme ${ mecanismName } ` ,
e
)
return node . nodeValue
}
} )
return [ unit , values ]
}
2017-07-13 10:25:46 +00:00
2018-01-03 15:54:19 +00:00
export let evaluateArray = ( reducer , start ) => (
cache ,
situationGate ,
parsedRules ,
node
) => {
let evaluateOne = child =>
evaluateNode ( cache , situationGate , parsedRules , child ) ,
2018-01-08 15:07:26 +00:00
explanation = map ( evaluateOne , node . explanation ) ,
2019-11-28 11:03:23 +00:00
[ unit , values ] = sameUnitValues (
explanation ,
cache . _meta . contextRule ,
node . name
) ,
nodeValue = values . some ( value => value === null )
2018-01-03 15:54:19 +00:00
? null
2018-04-10 11:00:03 +00:00
: reduce ( reducer , start , values ) ,
2018-06-29 13:46:42 +00:00
missingVariables =
node . nodeValue == null ? mergeAllMissing ( explanation ) : { }
2019-11-28 11:03:23 +00:00
return {
... node ,
nodeValue ,
explanation ,
missingVariables ,
unit
}
2017-07-16 21:58:06 +00:00
}
2018-01-08 15:07:26 +00:00
export let evaluateArrayWithFilter = ( evaluationFilter , reducer , start ) => (
2018-01-03 15:54:19 +00:00
cache ,
situationGate ,
parsedRules ,
node
) => {
let evaluateOne = child =>
evaluateNode ( cache , situationGate , parsedRules , child ) ,
2018-01-08 15:07:26 +00:00
explanation = map (
2018-01-03 15:54:19 +00:00
evaluateOne ,
2018-01-08 15:07:26 +00:00
filter ( evaluationFilter ( situationGate ) , node . explanation )
2018-01-03 15:54:19 +00:00
) ,
2019-11-28 11:03:23 +00:00
[ unit , values ] = sameUnitValues (
explanation ,
cache . _meta . contextRule ,
node . name
) ,
2018-01-08 15:07:26 +00:00
nodeValue = any ( equals ( null ) , values )
2018-01-03 15:54:19 +00:00
? null
2018-04-10 11:00:03 +00:00
: reduce ( reducer , start , values ) ,
2018-06-29 13:46:42 +00:00
missingVariables =
node . nodeValue == null ? mergeAllMissing ( explanation ) : { }
2017-07-13 10:25:46 +00:00
2019-11-28 11:03:23 +00:00
return { ... node , nodeValue , explanation , missingVariables , unit }
2017-07-13 10:25:46 +00:00
}
2019-02-14 17:00:31 +00:00
export let defaultNode = nodeValue => ( {
nodeValue ,
// eslint-disable-next-line
jsx : nodeValue => < span className = "value" > { nodeValue } < / s p a n > ,
isDefault : true
} )
2017-07-13 10:25:46 +00:00
export let parseObject = ( recurse , objectShape , value ) => {
let recurseOne = key => defaultValue => {
2018-12-05 17:58:38 +00:00
if ( ! value [ key ] && ! defaultValue )
throw new Error (
` Il manque une valeur ' ${ key } ' dans ${ JSON . stringify ( value ) } `
)
2018-01-03 15:54:19 +00:00
return value [ key ] ? recurse ( value [ key ] ) : defaultValue
}
2018-01-08 15:07:26 +00:00
let transforms = fromPairs ( map ( k => [ k , recurseOne ( k ) ] , keys ( objectShape ) ) )
return evolve ( transforms , objectShape )
2017-07-13 10:25:46 +00:00
}
2018-01-03 15:54:19 +00:00
export let evaluateObject = ( objectShape , effect ) => (
cache ,
situationGate ,
parsedRules ,
node
) => {
let evaluateOne = child =>
2018-06-29 13:46:42 +00:00
evaluateNode ( cache , situationGate , parsedRules , child )
2017-07-13 10:25:46 +00:00
2018-01-08 15:07:26 +00:00
let transforms = map ( k => [ k , evaluateOne ] , keys ( objectShape ) ) ,
2019-01-14 14:14:57 +00:00
automaticExplanation = evolve ( fromPairs ( transforms ) ) ( node . explanation )
// the result of effect can either be just a nodeValue, or an object {additionalExplanation, nodeValue}. The latter is useful for a richer JSX visualisation of the mecanism : the view should not duplicate code to recompute intermediate values (e.g. for a marginal 'barème', the marginal 'tranche')
2020-01-15 12:45:01 +00:00
let evaluated = effect ( automaticExplanation , cache , situationGate , parsedRules ) ,
2019-01-14 14:14:57 +00:00
explanation = is ( Object , evaluated )
? { ... automaticExplanation , ... evaluated . additionalExplanation }
: automaticExplanation ,
nodeValue = is ( Object , evaluated ) ? evaluated . nodeValue : evaluated ,
2018-04-12 13:43:02 +00:00
missingVariables = mergeAllMissing ( values ( explanation ) )
2019-11-28 11:03:23 +00:00
return simplifyNodeUnit ( {
... node ,
nodeValue ,
explanation ,
missingVariables ,
unit : explanation . unit
} )
2019-02-21 16:55:07 +00:00
}